From cb0d1a9e50e2dd7d0908a60dc002f3af02380682 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 27 Mar 2019 09:15:41 +0100 Subject: [PATCH 001/238] timely initialization of builtin topics (#138) The rtps_init function used to initialize all data structures and start all threads used by the protocol stack, allowing discovery of remote entities before the built-in topic data structures were initialized. (Very) early discovery of a remote participant thus led to a crash. This commit splits the initialisation, providing a separate function for starting, in particular, the threads receiving data from the network. In terms of threads created, it matches exactly with the rtps_stop / rtps_fini split that already existed to address the exact same problem on termination. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_init.c | 15 +++- src/core/ddsi/include/dds/ddsi/q_rtps.h | 1 + src/core/ddsi/src/q_init.c | 98 ++++++++++++++----------- 3 files changed, 67 insertions(+), 47 deletions(-) diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index 1a434b5..3aa8751 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -113,6 +113,7 @@ dds_init(dds_domainid_t domain) goto fail_rtps_config; } + upgrade_main_thread(); ut_avlInit(&dds_domaintree_def, &dds_global.m_domains); /* Start monitoring the liveliness of all threads. */ @@ -129,7 +130,7 @@ dds_init(dds_domainid_t domain) } } - if (rtps_init() < 0) + if (rtps_init () < 0) { DDS_LOG(DDS_LC_CONFIG, "Failed to initialize RTPS\n"); ret = DDS_ERRNO(DDS_RETCODE_ERROR); @@ -138,6 +139,13 @@ dds_init(dds_domainid_t domain) dds__builtin_init (); + if (rtps_start () < 0) + { + DDS_LOG(DDS_LC_CONFIG, "Failed to start RTPS\n"); + ret = DDS_ERRNO(DDS_RETCODE_ERROR); + goto fail_rtps_start; + } + if (gv.servicelease && nn_servicelease_start_renewing(gv.servicelease) < 0) { DDS_ERROR("Failed to start the servicelease\n"); @@ -145,8 +153,6 @@ dds_init(dds_domainid_t domain) goto fail_servicelease_start; } - upgrade_main_thread(); - /* Set additional default participant properties */ gv.default_plist_pp.process_id = (unsigned)ddsrt_getpid(); @@ -173,6 +179,8 @@ fail_servicelease_start: if (gv.servicelease) nn_servicelease_stop_renewing (gv.servicelease); rtps_stop (); +fail_rtps_start: + dds__builtin_fini (); rtps_fini (); fail_rtps_init: if (gv.servicelease) @@ -181,6 +189,7 @@ fail_rtps_init: gv.servicelease = NULL; } fail_servicelease_new: + downgrade_main_thread (); thread_states_fini(); fail_rtps_config: fail_config_domainid: diff --git a/src/core/ddsi/include/dds/ddsi/q_rtps.h b/src/core/ddsi/include/dds/ddsi/q_rtps.h index e9793d6..731fbd9 100644 --- a/src/core/ddsi/include/dds/ddsi/q_rtps.h +++ b/src/core/ddsi/include/dds/ddsi/q_rtps.h @@ -76,6 +76,7 @@ struct cfgst; int rtps_config_prep (struct cfgst *cfgst); int rtps_config_open (void); int rtps_init (void); +int rtps_start (void); void ddsi_plugin_init (void); void rtps_stop (void); void rtps_fini (void); diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index d5ca562..97ae856 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -1275,61 +1275,20 @@ int rtps_init (void) gv.rtps_keepgoing = 1; ddsrt_rwlock_init (&gv.qoslock); - { - int r; - gv.builtins_dqueue = nn_dqueue_new ("builtins", config.delivery_queue_maxsamples, builtins_dqueue_handler, NULL); - if ((r = xeventq_start (gv.xevents, NULL)) < 0) - { - DDS_FATAL("failed to start global event processing thread (%d)\n", r); - } - } - if (config.xpack_send_async) { nn_xpack_sendq_init(); nn_xpack_sendq_start(); } + gv.builtins_dqueue = nn_dqueue_new ("builtins", config.delivery_queue_maxsamples, builtins_dqueue_handler, NULL); #ifdef DDSI_INCLUDE_NETWORK_CHANNELS - /* Create a delivery queue and start tev for each channel */ - { - struct config_channel_listelem * chptr = config.channels; - while (chptr) - { - chptr->dqueue = nn_dqueue_new (chptr->name, config.delivery_queue_maxsamples, user_dqueue_handler, NULL); - if (chptr->evq) - { - int r; - if ((r = xeventq_start (chptr->evq, chptr->name)) < 0) - DDS_FATAL("failed to start event processing thread for channel '%s' (%d)\n", chptr->name, r); - } - chptr = chptr->next; - } - } + for (struct config_channel_listelem *chptr = config.channels; chptr; chptr = chptr->next) + chptr->dqueue = nn_dqueue_new (chptr->name, config.delivery_queue_maxsamples, user_dqueue_handler, NULL); #else gv.user_dqueue = nn_dqueue_new ("user", config.delivery_queue_maxsamples, user_dqueue_handler, NULL); #endif - if (setup_and_start_recv_threads () < 0) - { - DDS_FATAL("failed to start receive threads\n"); - } - - if (gv.listener) - { - gv.listen_ts = create_thread ("listen", (uint32_t (*) (void *)) listen_thread, gv.listener); - } - - if (gv.startup_mode) - { - qxev_end_startup_mode (add_duration_to_mtime (now_mt (), config.startup_mode_duration)); - } - - if (config.monitor_port >= 0) - { - gv.debmon = new_debug_monitor (config.monitor_port); - } - return 0; err_mc_conn: @@ -1402,6 +1361,57 @@ err_udp_tcp_init: return -1; } +#ifdef DDSI_INCLUDE_NETWORK_CHANNELS +static void stop_all_xeventq_upto (struct config_channel_listelem *chptr) +{ + for (struct config_channel_listelem *chptr1 = config.channels; chptr1 != chptr; chptr1 = chptr1->next) + if (chptr1->evq) + xeventq_stop (chptr1->evq); +} +#endif + +int rtps_start (void) +{ + if (xeventq_start (gv.xevents, NULL) < 0) + return -1; +#ifdef DDSI_INCLUDE_NETWORK_CHANNELS + for (struct config_channel_listelem *chptr = config.channels; chptr; chptr = chptr->next) + { + if (chptr->evq) + { + if (xeventq_start (chptr->evq, chptr->name) < 0) + { + stop_all_xeventq_upto (chptr); + xeventq_stop (gv.xevents); + return -1; + } + } + } +#endif + + if (setup_and_start_recv_threads () < 0) + { +#ifdef DDSI_INCLUDE_NETWORK_CHANNELS + stop_all_xeventq_upto (NULL); +#endif + xeventq_stop (gv.xevents); + return -1; + } + if (gv.listener) + { + gv.listen_ts = create_thread ("listen", (uint32_t (*) (void *)) listen_thread, gv.listener); + } + if (gv.startup_mode) + { + qxev_end_startup_mode (add_duration_to_mtime (now_mt (), config.startup_mode_duration)); + } + if (config.monitor_port >= 0) + { + gv.debmon = new_debug_monitor (config.monitor_port); + } + return 0; +} + struct dq_builtins_ready_arg { ddsrt_mutex_t lock; ddsrt_cond_t cond; From dc0ebb55ff34b80af785b4c351924417d8edba80 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 27 Mar 2019 09:21:09 +0100 Subject: [PATCH 002/238] trace correct thread id during thread creation The rewrite of the abstraction layer changed some details in thread ids used in tracing and functions to get those ids, with a result of always printing the parent thread's id in create_thread rather than the newly create thread's id. As all supported platforms use thread names in the trace, it is a rather insignificant matter, and so this provides the trivial fix by letting the new thread log the message. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c index cadbb6e..4d3fe45 100644 --- a/src/core/ddsi/src/q_thread.c +++ b/src/core/ddsi/src/q_thread.c @@ -172,6 +172,7 @@ static uint32_t create_thread_wrapper (void *ptr) { uint32_t ret; struct thread_context *ctx = ptr; + DDS_TRACE ("started new thread %"PRIdTID": %s\n", ddsrt_gettid (), ctx->self->name); ctx->self->tid = ddsrt_thread_self (); ret = ctx->f (ctx->arg); ddsrt_free (ctx); @@ -272,7 +273,6 @@ struct thread_state1 *create_thread (const char *name, uint32_t (*f) (void *arg) DDS_FATAL("create_thread: %s: ddsrt_thread_create failed\n", name); goto fatal; } - DDS_TRACE("started new thread %"PRIdTID" : %s\n", ddsrt_gettid(), name); ts1->extTid = tid; /* overwrite the temporary value with the correct external one */ ddsrt_mutex_unlock (&thread_states.lock); return ts1; From bfe44a9785aa6334095b301837b09d7c48df8ab9 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 27 Mar 2019 09:25:09 +0100 Subject: [PATCH 003/238] avoid debmon thread shutdown logging write errors During shutdown, the optional "debmon" thread for getting some information about internal state of the DDSI stack had a tendency to run into errors from calling write on a connection that had already been closed immediately after connecting successfully to wake the thread. Instead of blindly writing into the connection, it now checks whether it is supposed to shutdown before doing anything, avoiding this particular problem. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_debmon.c | 49 +++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/src/core/ddsi/src/q_debmon.c b/src/core/ddsi/src/q_debmon.c index eb83d81..beaa9bf 100644 --- a/src/core/ddsi/src/q_debmon.c +++ b/src/core/ddsi/src/q_debmon.c @@ -300,37 +300,46 @@ static int print_proxy_participants (struct thread_state1 *self, ddsi_tran_conn_ return x; } +static void debmon_handle_connection (struct debug_monitor *dm, ddsi_tran_conn_t conn) +{ + struct plugin *p; + int r = 0; + r += print_participants (dm->servts, conn); + if (r == 0) + r += print_proxy_participants (dm->servts, conn); + + /* Note: can only add plugins (at the tail) */ + ddsrt_mutex_lock (&dm->lock); + p = dm->plugins; + while (r == 0 && p != NULL) + { + ddsrt_mutex_unlock (&dm->lock); + r += p->fn (conn, cpf, p->arg); + ddsrt_mutex_lock (&dm->lock); + p = p->next; + } + ddsrt_mutex_unlock (&dm->lock); +} + static uint32_t debmon_main (void *vdm) { struct debug_monitor *dm = vdm; ddsrt_mutex_lock (&dm->lock); while (!dm->stop) { - ddsi_tran_conn_t conn; ddsrt_mutex_unlock (&dm->lock); - if ((conn = ddsi_listener_accept (dm->servsock)) != NULL) + ddsi_tran_conn_t conn = ddsi_listener_accept (dm->servsock); + ddsrt_mutex_lock (&dm->lock); + if (conn != NULL && !dm->stop) { - struct plugin *p; - int r = 0; - r += print_participants (dm->servts, conn); - if (r == 0) - r += print_proxy_participants (dm->servts, conn); - - /* Note: can only add plugins (at the tail) */ - ddsrt_mutex_lock (&dm->lock); - p = dm->plugins; - while (r == 0 && p != NULL) - { - ddsrt_mutex_unlock (&dm->lock); - r += p->fn (conn, cpf, p->arg); - ddsrt_mutex_lock (&dm->lock); - p = p->next; - } ddsrt_mutex_unlock (&dm->lock); - + debmon_handle_connection (dm, conn); + ddsrt_mutex_lock (&dm->lock); + } + if (conn != NULL) + { ddsi_conn_free (conn); } - ddsrt_mutex_lock (&dm->lock); } ddsrt_mutex_unlock (&dm->lock); return 0; From 73ec5beef4da4ff44878014a85e29387cc35544a Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 27 Mar 2019 17:14:44 +0100 Subject: [PATCH 004/238] gracefully handle a too small ReceiveBufferSize Sizing/ReceiveBufferSize must be >= Sizing/ReceiveBufferChunkSize + N for some small N, and if it is not, Cyclone will crash reading beyond allocated memory in a nasty way. Ordinarily this should be handled by the configuration validation, but that would put the burden of knowing the details of computing N upon the user, an unreasonable requirement. The old state of an assertion presupposes a check, and brings us back that same requirement. Thus, a change to ensure that ReceiveBufferSize will be taken as the minimum of the configured value and the actual minimal value as determined by ChunkSize and whatever N happens to be. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_config.c | 2 +- src/core/ddsi/src/q_radmin.c | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index e318181..de2cceb 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -654,7 +654,7 @@ END_MARKER static const struct cfgelem sizing_cfgelems[] = { { LEAF("ReceiveBufferSize"), 1, "1 MiB", ABSOFF(rbuf_size), 0, uf_memsize, 0, pf_memsize, - "

This element sets the size of a single receive buffer. Many receive buffers may be needed. Their size must be greater than ReceiveBufferChunkSize by a modest amount.

" }, + "

This element sets the size of a single receive buffer. Many receive buffers may be needed. The minimum workable size a little bit larger than Sizing/ReceiveBufferChunkSize, and the value used is taken as the configured value and the actual minimum workable size.

" }, { LEAF("ReceiveBufferChunkSize"), 1, "128 KiB", ABSOFF(rmsg_chunk_size), 0, uf_memsize, 0, pf_memsize, "

This element specifies the size of one allocation unit in the receive buffer. Must be greater than the maximum packet size by a modest amount (too large packets are dropped). Each allocation is shrunk immediately after processing a message, or freed straightaway.

" }, END_MARKER diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c index c6f4a22..41c6192 100644 --- a/src/core/ddsi/src/q_radmin.c +++ b/src/core/ddsi/src/q_radmin.c @@ -330,7 +330,13 @@ struct nn_rbufpool *nn_rbufpool_new (uint32_t rbuf_size, uint32_t max_rmsg_size) struct nn_rbufpool *rbp; assert (max_rmsg_size > 0); - assert (rbuf_size >= max_rmsg_size_w_hdr (max_rmsg_size)); + + /* raise rbuf_size to minimum possible considering max_rmsg_size, there is + no reason to bother the user with the small difference between the two + when he tries to configure things, and the crash is horrible when + rbuf_size is too small */ + if (rbuf_size < max_rmsg_size_w_hdr (max_rmsg_size)) + rbuf_size = max_rmsg_size_w_hdr (max_rmsg_size); if ((rbp = ddsrt_malloc (sizeof (*rbp))) == NULL) goto fail_rbp; From 371a9cf1079ef5065a48da5a85a82b310580fbd9 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 27 Mar 2019 17:28:03 +0100 Subject: [PATCH 005/238] clarify "spdp" token in AllowMulticast option Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index de2cceb..596fb3e 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -248,7 +248,7 @@ static const struct cfgelem general_cfgelems[] = { "

This element controls whether DDSI2E uses multicasts for data traffic.

\n\

It is a comma-separated list of some of the following keywords: \"spdp\", \"asm\", \"ssm\", or either of \"false\" or \"true\".

\n\
    \n\ -
  • spdp: enables the use of ASM (any-source multicast) for participant discovery
  • \n\ +
  • spdp: enables the use of ASM (any-source multicast) for participant discovery, joining the multicast group on the discovery socket, transmitting SPDP messages to this group, but never advertising nor using any multicast address in any discovery message, thus forcing unicast communications for all endpoint discovery and user data.
  • \n\
  • asm: enables the use of ASM for all traffic (including SPDP)
  • \n\
  • ssm: enables the use of SSM (source-specific multicast) for all non-SPDP traffic (if supported)
  • \n\
\n\ From f0fdde1345b7487b07e909c99d5587609bcb3ae5 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 27 Mar 2019 17:29:26 +0100 Subject: [PATCH 006/238] remove rmbias_and_adjust assert on threadid (#121) The introduction of multiple receive threads could trigger the assertion because a set of samples ready for delivery may have been received by multiple threads (the problem manifests itself most easily with fragmented samples). This is actually a non-issue: * while synchronously processing a packet, there is a bias of 2**31 added to the refcount, to prevent any thread under any circumstance from ever freeing the data; * while data lives in the defragment buffers or reorder buffer of the proxy writer, a bias of 2**20 is added to it until this particular function is called, after delivery of the data to the readers, and (if needed) after inserting the samples in the reorder buffer of any readers that are out-of-sync with the proxy writer; * the relevant refcount is updated atomically in such a manner that this particular operation atomically removes the bias and performs the delayed increment of the refcount to account for the data being stored in any of the defragmenting or reorder buffers; * the only ordinary decrementing of the refcount happens either synchronously (if synchronous delivery is chosen), or asynchronously in a delivery queue thread, and so the entire mechanism exists to avoid premature freeing of the underlying data because the data is delivered very quickly (possibly synchronously); * as the biases are removed after all the delayed refcount increments are taken into account and there are no increments following the call to rmbias_and_adjust, the "ordinary" decrements can do no harm. * the case of data from multiple writers being combined in a single packet is dealt with by the 2**20 bias, and so there is potentially a problem if there are more than 2**20 out-of-sync readers attached to a single proxy writer, or data submessages from more than 2**11 writers in a single packet. The minimum possible data message is 32 bytes (headers, encoding, data, padding), so packets up to 64kB are safe. None of this is in any way related to which threads originally accepted the packets, and therefore I see no argument for the existence of the assertion. That said, it is a rather complicated mechanism of unknown benefit, and a major simplification is definitely something to be considered. In UDP mode I see no chance of abuse, but there may be network protocols (TCP, for sure) where there might be packets larger than 64kB and those could, under worst-case assumptions, cause trouble. That, too, is a reason to rethink it. The call to rmbias_and_adjust was sometimes called with the proxy writer locked, and sometimes after unlocking it. This commit changes it to consistently call it with the lock held. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_radmin.c | 46 +++++++---------------------------- src/core/ddsi/src/q_receive.c | 4 +-- 2 files changed, 11 insertions(+), 39 deletions(-) diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c index 41c6192..20eaa66 100644 --- a/src/core/ddsi/src/q_radmin.c +++ b/src/core/ddsi/src/q_radmin.c @@ -639,11 +639,10 @@ static void nn_rmsg_addbias (struct nn_rmsg *rmsg) static void nn_rmsg_rmbias_and_adjust (struct nn_rmsg *rmsg, int adjust) { /* This can happen to any rmsg referenced by an sample still - progressing through the pipeline, but only by the receive + progressing through the pipeline, but only by a receive thread. Can't require it to be uncommitted. */ uint32_t sub; DDS_LOG(DDS_LC_RADMIN, "rmsg_rmbias_and_adjust(%p, %d)\n", (void *) rmsg, adjust); - ASSERT_RBUFPOOL_OWNER (rmsg->chunk.rbuf->rbufpool); assert (adjust >= 0); assert ((uint32_t) adjust < RMSG_REFCOUNT_RDATA_BIAS); sub = RMSG_REFCOUNT_RDATA_BIAS - (uint32_t) adjust; @@ -652,15 +651,6 @@ static void nn_rmsg_rmbias_and_adjust (struct nn_rmsg *rmsg, int adjust) nn_rmsg_free (rmsg); } -static void nn_rmsg_rmbias_anythread (struct nn_rmsg *rmsg) -{ - /* For removing garbage when freeing a nn_defrag. */ - uint32_t sub = RMSG_REFCOUNT_RDATA_BIAS; - DDS_LOG(DDS_LC_RADMIN, "rmsg_rmbias_anythread(%p)\n", (void *) rmsg); - assert (ddsrt_atomic_ld32 (&rmsg->refcount) >= sub); - if (ddsrt_atomic_sub32_nv (&rmsg->refcount, sub) == 0) - nn_rmsg_free (rmsg); -} static void nn_rmsg_unref (struct nn_rmsg *rmsg) { DDS_LOG(DDS_LC_RADMIN, "rmsg_unref(%p)\n", (void *) rmsg); @@ -752,16 +742,6 @@ static void nn_rdata_rmbias_and_adjust (struct nn_rdata *rdata, int adjust) nn_rmsg_rmbias_and_adjust (rdata->rmsg, adjust); } -static void nn_rdata_rmbias_anythread (struct nn_rdata *rdata) -{ - DDS_LOG(DDS_LC_RADMIN, "rdata_rmbias_anythread(%p)\n", (void *) rdata); -#ifndef NDEBUG - if (ddsrt_atomic_dec32_ov (&rdata->refcount_bias_added) != 1) - abort (); -#endif - nn_rmsg_rmbias_anythread (rdata->rmsg); -} - static void nn_rdata_unref (struct nn_rdata *rdata) { DDS_LOG(DDS_LC_RADMIN, "rdata_rdata_unref(%p)\n", (void *) rdata); @@ -900,29 +880,21 @@ struct nn_defrag *nn_defrag_new (enum nn_defrag_drop_mode drop_mode, uint32_t ma void nn_fragchain_adjust_refcount (struct nn_rdata *frag, int adjust) { - struct nn_rdata *frag1; DDS_LOG(DDS_LC_RADMIN, "fragchain_adjust_refcount(%p, %d)\n", (void *) frag, adjust); while (frag) { - frag1 = frag->nextfrag; + struct nn_rdata * const frag1 = frag->nextfrag; nn_rdata_rmbias_and_adjust (frag, adjust); frag = frag1; } } -static void nn_fragchain_rmbias_anythread (struct nn_rdata *frag, UNUSED_ARG (int adjust)) +static void nn_fragchain_rmbias (struct nn_rdata *frag) { - struct nn_rdata *frag1; - DDS_LOG(DDS_LC_RADMIN, "fragchain_rmbias_anythread(%p)\n", (void *) frag); - while (frag) - { - frag1 = frag->nextfrag; - nn_rdata_rmbias_anythread (frag); - frag = frag1; - } + nn_fragchain_adjust_refcount (frag, 0); } -static void defrag_rsample_drop (struct nn_defrag *defrag, struct nn_rsample *rsample, void (*fragchain_free) (struct nn_rdata *frag, int adjust)) +static void defrag_rsample_drop (struct nn_defrag *defrag, struct nn_rsample *rsample) { /* Can't reference rsample after the first fragchain_free, because we don't know which rdata/rmsg provides the storage for the @@ -938,7 +910,7 @@ static void defrag_rsample_drop (struct nn_defrag *defrag, struct nn_rsample *rs assert (defrag->n_samples > 0); defrag->n_samples--; for (iv = ut_avlIterFirst (&rsample_defrag_fragtree_treedef, &rsample->u.defrag.fragtree, &iter); iv; iv = ut_avlIterNext (&iter)) - fragchain_free (iv->first, 0); + nn_fragchain_rmbias (iv->first); } void nn_defrag_free (struct nn_defrag *defrag) @@ -948,7 +920,7 @@ void nn_defrag_free (struct nn_defrag *defrag) while (s) { DDS_LOG(DDS_LC_RADMIN, "defrag_free(%p, sample %p seq %"PRId64")\n", (void *) defrag, (void *) s, s->u.defrag.seq); - defrag_rsample_drop (defrag, s, nn_fragchain_rmbias_anythread); + defrag_rsample_drop (defrag, s); s = ut_avlFindMin (&defrag_sampletree_treedef, &defrag->sampletree); } assert (defrag->n_samples == 0); @@ -1312,7 +1284,7 @@ static int defrag_limit_samples (struct nn_defrag *defrag, seqno_t seq, seqno_t break; } assert (sample_to_drop != NULL); - defrag_rsample_drop (defrag, sample_to_drop, nn_fragchain_adjust_refcount); + defrag_rsample_drop (defrag, sample_to_drop); if (sample_to_drop == defrag->max_sample) { defrag->max_sample = ut_avlFindMax (&defrag_sampletree_treedef, &defrag->sampletree); @@ -1444,7 +1416,7 @@ void nn_defrag_notegap (struct nn_defrag *defrag, seqno_t min, seqno_t maxp1) while (s && s->u.defrag.seq < maxp1) { struct nn_rsample *s1 = ut_avlFindSucc (&defrag_sampletree_treedef, &defrag->sampletree, s); - defrag_rsample_drop (defrag, s, nn_fragchain_adjust_refcount); + defrag_rsample_drop (defrag, s); s = s1; } defrag->max_sample = ut_avlFindMax (&defrag_sampletree_treedef, &defrag->sampletree); diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 7de04a6..d09c89d 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -2304,8 +2304,8 @@ static int handle_SPDP (const struct nn_rsample_info *sampleinfo, struct nn_rdat fragchain = nn_rsample_fragchain (rsample); if ((rres = nn_reorder_rsample (&sc, gv.spdp_reorder, rsample, &refc_adjust, nn_dqueue_is_full (gv.builtins_dqueue))) > 0) nn_dqueue_enqueue (gv.builtins_dqueue, &sc, rres); - ddsrt_mutex_unlock (&gv.spdp_lock); nn_fragchain_adjust_refcount (fragchain, refc_adjust); + ddsrt_mutex_unlock (&gv.spdp_lock); return 0; } @@ -2342,8 +2342,8 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con ddsrt_mutex_lock (&pwr->e.lock); wn = ut_avlLookup (&pwr_readers_treedef, &pwr->readers, &dst); gap_was_valuable = handle_one_gap (pwr, wn, sampleinfo->seq, sampleinfo->seq+1, gap, &refc_adjust); - ddsrt_mutex_unlock (&pwr->e.lock); nn_fragchain_adjust_refcount (gap, refc_adjust); + ddsrt_mutex_unlock (&pwr->e.lock); if (gap_was_valuable) { From 2c878c3c6290aac35877d9ea42a2755a8748723e Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Thu, 28 Mar 2019 09:43:24 +0100 Subject: [PATCH 007/238] Cleanup log tests. Signed-off-by: Martin Bremmer --- src/ddsrt/tests/log.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/ddsrt/tests/log.c b/src/ddsrt/tests/log.c index ab5fcc6..2c619c9 100644 --- a/src/ddsrt/tests/log.c +++ b/src/ddsrt/tests/log.c @@ -115,6 +115,14 @@ static void copy(void *ptr, const dds_log_data_t *data) *(char **)ptr = ddsrt_strdup(data->message); } +static void reset(void) +{ + /* Reset log internals to default. */ + dds_set_log_mask(DDS_LC_ERROR | DDS_LC_WARNING); + dds_set_trace_sink(NULL, NULL); + dds_set_log_sink(NULL, NULL); +} + static void setup(void) { fh = fmemopen(NULL, 1024, "wb+"); @@ -123,6 +131,7 @@ static void setup(void) static void teardown(void) { + reset(); (void)fclose(fh); } @@ -178,7 +187,7 @@ CU_Test(dds_log, same_file, .init=setup, .fini=teardown) /* The sinks are considered to be the same only if the callback and userdata both are an exact match. If the userdata is different, the function should be called twice for log messages. */ -CU_Test(dds_log, same_sink_function) +CU_Test(dds_log, same_sink_function, .fini=reset) { int log_cnt = 0, trace_cnt = 0; @@ -190,7 +199,7 @@ CU_Test(dds_log, same_sink_function) CU_ASSERT_EQUAL(trace_cnt, 1); } -CU_Test(dds_log, exact_same_sink) +CU_Test(dds_log, exact_same_sink, .fini=reset) { int cnt = 0; @@ -266,7 +275,7 @@ CU_Test(dds_log, no_sink, .init=setup, .fini=teardown) /* A newline terminates the message. Until that a newline is encountered, the messages must be concatenated in the buffer. The newline is replaced by a NULL byte if it is flushed to a sink. */ -CU_Test(dds_log, newline_terminates) +CU_Test(dds_log, newline_terminates, .fini=reset) { char *msg = NULL; @@ -282,10 +291,9 @@ CU_Test(dds_log, newline_terminates) } /* Nothing must be written unless a category is enabled. */ -CU_Test(dds_log, disabled_categories_discarded) +CU_Test(dds_log, disabled_categories_discarded, .fini=reset) { char *msg = NULL; - dds_set_log_sink(©, &msg); DDS_INFO("foobar\n"); CU_ASSERT_PTR_NULL_FATAL(msg); @@ -336,7 +344,7 @@ static uint32_t run(void *ptr) /* Log and trace sinks can be changed at runtime. However, the operation must be synchronous! Verify the dds_set_log_sink blocks while other threads reside in the log or trace sinks. */ -CU_Test(dds_log, synchronous_sink_changes) +CU_Test(dds_log, synchronous_sink_changes, .fini=reset) { struct arg arg; dds_time_t diff, stamp; From 79d0e1a43cfb34b770ae6bbf5cbbf3f6e504eb34 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 2 Apr 2019 14:11:21 +0200 Subject: [PATCH 008/238] ignore all-zero durability service QoS in SEDP For compatibility with TwinOaks CoreDX, ignore an all-zero durability service QoS received over SEDP for volatile and transient-local endpoints. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_plist.c | 102 ++++++++++++++++++++++++++++++++---- src/docs/config.rst | 20 +++---- 2 files changed, 100 insertions(+), 22 deletions(-) diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index 99c7f12..8ee2ccd 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -593,6 +593,11 @@ static void bswap_history_qospolicy (nn_history_qospolicy_t *q) q->depth = bswap4 (q->depth); } +static int history_qospolicy_allzero (const nn_history_qospolicy_t *q) +{ + return q->kind == NN_KEEP_LAST_HISTORY_QOS && q->depth == 0; +} + int validate_history_qospolicy (const nn_history_qospolicy_t *q) { /* Validity of history setting and of resource limits are dependent, @@ -630,6 +635,11 @@ static void bswap_resource_limits_qospolicy (nn_resource_limits_qospolicy_t *q) q->max_samples_per_instance = bswap4 (q->max_samples_per_instance); } +static int resource_limits_qospolicy_allzero (const nn_resource_limits_qospolicy_t *q) +{ + return q->max_samples == 0 && q->max_instances == 0 && q->max_samples_per_instance == 0; +} + int validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q) { const int unlimited = NN_DDS_LENGTH_UNLIMITED; @@ -707,9 +717,18 @@ static void bswap_durability_service_qospolicy (nn_durability_service_qospolicy_ bswap_resource_limits_qospolicy (&q->resource_limits); } -int validate_durability_service_qospolicy (const nn_durability_service_qospolicy_t *q) +static int durability_service_qospolicy_allzero (const nn_durability_service_qospolicy_t *q) +{ + return (history_qospolicy_allzero (&q->history) && + resource_limits_qospolicy_allzero (&q->resource_limits) && + q->service_cleanup_delay.seconds == 0 && q->service_cleanup_delay.fraction == 0); +} + +static int validate_durability_service_qospolicy_acceptzero (const nn_durability_service_qospolicy_t *q, bool acceptzero) { int res; + if (acceptzero && durability_service_qospolicy_allzero (q)) + return 0; if ((res = validate_duration (&q->service_cleanup_delay)) < 0) { DDS_TRACE("plist/validate_durability_service_qospolicy: duration invalid\n"); @@ -723,6 +742,11 @@ int validate_durability_service_qospolicy (const nn_durability_service_qospolicy return 0; } +int validate_durability_service_qospolicy (const nn_durability_service_qospolicy_t *q) +{ + return validate_durability_service_qospolicy_acceptzero (q, false); +} + static void bswap_liveliness_qospolicy (nn_liveliness_qospolicy_t *q) { q->kind = bswap4u (q->kind); @@ -1300,8 +1324,9 @@ static int do_guid (nn_guid_t *dst, uint64_t *present, uint64_t fl, int (*valid) *dst = nn_ntoh_guid (*dst); if (valid (dst, dd) < 0) { - if (fl == PP_PARTICIPANT_GUID && vendor_is_twinoaks (dd->vendorid) && - dst->entityid.u == 0 && ! NN_STRICT_P) + /* CoreDX once upon a time used to send out PARTICIPANT_GUID parameters with a 0 entity id, but it + that has long since changed (even if I don't know exactly when) */ + if (fl == PP_PARTICIPANT_GUID && vendor_is_twinoaks (dd->vendorid) && dst->entityid.u == 0 && ! NN_STRICT_P) { DDS_LOG(DDS_LC_DISCOVERY, "plist(vendor %u.%u): rewriting invalid participant guid %x:%x:%x:%x\n", dd->vendorid.id[0], dd->vendorid.id[1], PGUID (*dst)); @@ -1523,7 +1548,6 @@ static int init_one_parameter } \ return 0 Q (DURABILITY, durability); - Q (DURABILITY_SERVICE, durability_service); Q (LIVELINESS, liveliness); Q (DESTINATION_ORDER, destination_order); Q (HISTORY, history); @@ -1534,6 +1558,27 @@ static int init_one_parameter Q (TRANSPORT_PRIORITY, transport_priority); #undef Q + case PID_DURABILITY_SERVICE: + if (dd->bufsz < sizeof (nn_durability_service_qospolicy_t)) + { + DDS_TRACE("plist/init_one_parameter[pid=DURABILITY_SERVICE]: buffer too small\n"); + return ERR_INVALID; + } + else + { + nn_durability_service_qospolicy_t *q = &dest->qos.durability_service; + /* All-zero durability service is illegal, but at least CoreDX sometimes advertises + it in some harmless cases. So accept all-zero durability service, then handle it + in final_validation, where we can determine whether it really is harmless or not */ + memcpy (q, dd->buf, sizeof (*q)); + if (dd->bswap) + bswap_durability_service_qospolicy (q); + if ((res = validate_durability_service_qospolicy_acceptzero (q, true)) < 0) + return res; + dest->qos.present |= QP_DURABILITY_SERVICE; + } + return 0; + /* PID_RELIABILITY handled differently because it (formally, for static typing reasons) has a different type on the network than internally, with the transformation between the two @@ -2253,9 +2298,9 @@ nn_plist_t *nn_plist_dup (const nn_plist_t *src) return dst; } -static int final_validation (nn_plist_t *dest) +static int final_validation (nn_plist_t *dest, nn_protocol_version_t protocol_version, nn_vendorid_t vendorid) { - /* Resource limits & history are related, so if only one is given, + /* Resource limits & history are related, so if only one is given, set the other to the default, claim it has been provided & validate the combination. They can't be changed afterward, so this is a reasonable interpretation. */ @@ -2276,6 +2321,46 @@ static int final_validation (nn_plist_t *dest) if ((res = validate_history_and_resource_limits (&dest->qos.history, &dest->qos.resource_limits)) < 0) return res; } + + /* Durability service is sort-of accepted if all zeros, but only + for some protocol versions and vendors. We don't handle want + to deal with that case internally. Now that all QoS have been + parsed we know the setting of the durability QoS (the default + is always VOLATILE), and hence we can verify that the setting + is valid or delete it if irrelevant. */ + if (dest->qos.present & QP_DURABILITY_SERVICE) + { + const nn_durability_kind_t durkind = (dest->qos.present & QP_DURABILITY) ? dest->qos.durability.kind : NN_VOLATILE_DURABILITY_QOS; + bool acceptzero; + /* Use a somewhat convoluted rule to decide whether or not to + "accept" an all-zero durability service setting, to find a + reasonable mix of strictness and compatibility */ + if (protocol_version_is_newer (protocol_version)) + acceptzero = true; + else if (NN_STRICT_P) + acceptzero = vendor_is_twinoaks (vendorid); + else + acceptzero = !vendor_is_eclipse (vendorid); + switch (durkind) + { + case NN_VOLATILE_DURABILITY_QOS: + case NN_TRANSIENT_LOCAL_DURABILITY_QOS: + /* pretend we never saw it if it is all zero */ + if (acceptzero && durability_service_qospolicy_allzero (&dest->qos.durability_service)) + dest->qos.present &= ~QP_DURABILITY_SERVICE; + break; + case NN_TRANSIENT_DURABILITY_QOS: + case NN_PERSISTENT_DURABILITY_QOS: + break; + } + /* if it is still present, it must be valid */ + if (dest->qos.present & QP_DURABILITY_SERVICE) + { + int res; + if ((res = validate_durability_service_qospolicy (&dest->qos.durability_service)) < 0) + return res; + } + } return 0; } @@ -2341,10 +2426,9 @@ int nn_plist_init_frommsg length = (unsigned short) (dd.bswap ? bswap2u (par->length) : par->length); if (pid == PID_SENTINEL) { - /* Sentinel terminates list, the length is ignored, DDSI - 9.4.2.11. */ + /* Sentinel terminates list, the length is ignored, DDSI 9.4.2.11. */ DDS_LOG(DDS_LC_PLIST, "%4x PID %x\n", (unsigned) (pl - src->buf), pid); - if ((res = final_validation (dest)) < 0) + if ((res = final_validation (dest, src->protocol_version, src->vendorid)) < 0) { nn_plist_fini (dest); return ERR_INVALID; diff --git a/src/docs/config.rst b/src/docs/config.rst index 7223357..bd8b182 100644 --- a/src/docs/config.rst +++ b/src/docs/config.rst @@ -1117,20 +1117,14 @@ OpenSplice. Compatibility issues with TwinOaks ---------------------------------- -Interoperability with TwinOaks CoreDX require (or used to require at some point in the -past): +In the default configuration there should be no interoperability issues with TwinOaks CoreDX, +although there is the aforementioned difference in interpretation of the meaning of the +‘autodispose_unregistered_instances’ QoS on the writer. + +Interoperability with very old versions of CoreDX may require setting: + ``Compatibility/ManySocketsMode``: *true* -+ ``Compatibility/StandardsConformance``: *lax* -+ ``Compatibility/AckNackNumbitsEmptySet``: *0* + ``Compatibility/ExplicitlyPublishQosSetToDefault``: *true* -The ``ManySocketsMode`` option needed to be changed from the default, to ensure that -each domain participant has a unique locator; this was needed because TwinOaks CoreDX -DDS did not include the full GUID of a reader or writer if it needs to address just one, -but this is probably no longer the case. Note that the (old) behaviour of TwinOaks -CoreDX DDS has always been allowed by the specification. - -The ``Compatibility/ExplicitlyPublishQosSetToDefault`` settings work around TwinOaks -CoreDX DDS’ use of incorrect default values for some of the QoS settings if they are not -explicitly supplied during discovery. It may be that this is no longer the case. +The exact version number of CoreDX starting with which these settings are no longer needed is +unknown, but it has certainly not been needed for several years. From 4200f9a8467491fc64eafbb86145740fa57e3e27 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Mon, 1 Apr 2019 12:03:09 +0200 Subject: [PATCH 009/238] Fix format strings and signatures for fixed size integers Signed-off-by: Jeroen Koekkoek --- src/core/CMakeLists.txt | 2 + src/core/ddsc/src/dds_write.c | 8 +- src/core/ddsi/include/dds/ddsi/ddsi_tran.h | 6 + src/core/ddsi/include/dds/ddsi/q_bitset.h | 23 +-- src/core/ddsi/include/dds/ddsi/q_error.h | 22 +-- src/core/ddsi/include/dds/ddsi/q_time.h | 6 +- src/core/ddsi/src/ddsi_ipaddr.c | 4 +- src/core/ddsi/src/ddsi_tcp.c | 6 +- src/core/ddsi/src/ddsi_udp.c | 2 +- src/core/ddsi/src/q_bitset_inlines.c | 10 +- src/core/ddsi/src/q_config.c | 6 +- src/core/ddsi/src/q_ddsi_discovery.c | 10 +- src/core/ddsi/src/q_entity.c | 36 ++-- src/core/ddsi/src/q_lease.c | 4 +- src/core/ddsi/src/q_nwif.c | 6 +- src/core/ddsi/src/q_plist.c | 206 ++++++++++----------- src/core/ddsi/src/q_receive.c | 24 +-- src/core/ddsi/src/q_security.c | 2 +- src/core/ddsi/src/q_servicelease.c | 2 +- src/core/ddsi/src/q_sockwaitset.c | 2 +- src/core/ddsi/src/q_thread.c | 2 +- src/core/ddsi/src/q_time.c | 12 +- src/core/ddsi/src/q_transmit.c | 12 +- src/core/ddsi/src/q_xevent.c | 2 +- src/core/ddsi/src/q_xmsg.c | 4 +- src/core/xtests/rhc_torture.c | 2 +- src/ddsrt/include/dds/ddsrt/misc.h | 2 +- src/ddsrt/include/dds/ddsrt/sockets.h | 8 +- src/examples/helloworld/publisher.c | 2 +- src/examples/helloworld/subscriber.c | 2 +- src/examples/throughput/publisher.c | 2 +- src/tools/ddsls/ddsls.c | 6 +- src/tools/pubsub/common.c | 4 +- src/tools/pubsub/pubsub.c | 24 +-- src/util/CMakeLists.txt | 4 + 35 files changed, 245 insertions(+), 230 deletions(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 6eb4a82..2ef2fc3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -52,6 +52,8 @@ include(ddsc/CMakeLists.txt) target_link_libraries(ddsc PRIVATE util) target_link_libraries(ddsc PRIVATE ddsrt) +target_compile_definitions( + ddsc PUBLIC $>) target_include_directories( ddsc PUBLIC $>) diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index 969c6f3..3f3bb5e 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -185,10 +185,10 @@ dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstam if (!config.whc_batch) nn_xpack_send (wr->m_xp, false); ret = DDS_RETCODE_OK; - } else if (w_rc == ERR_TIMEOUT) { + } else if (w_rc == Q_ERR_TIMEOUT) { DDS_ERROR ("The writer could not deliver data on time, probably due to a reader resources being full\n"); ret = DDS_ERRNO (DDS_RETCODE_TIMEOUT); - } else if (w_rc == ERR_INVALID_DATA) { + } else if (w_rc == Q_ERR_INVALID_DATA) { DDS_ERROR ("Invalid data provided\n"); ret = DDS_ERRNO (DDS_RETCODE_ERROR); } else { @@ -224,10 +224,10 @@ dds_return_t dds_writecdr_impl_lowlevel (struct writer *ddsi_wr, struct nn_xpack if (!config.whc_batch && xp != NULL) nn_xpack_send (xp, false); ret = DDS_RETCODE_OK; - } else if (w_rc == ERR_TIMEOUT) { + } else if (w_rc == Q_ERR_TIMEOUT) { DDS_ERROR ("The writer could not deliver data on time, probably due to a reader resources being full\n"); ret = DDS_ERRNO(DDS_RETCODE_TIMEOUT); - } else if (w_rc == ERR_INVALID_DATA) { + } else if (w_rc == Q_ERR_INVALID_DATA) { DDS_ERROR ("Invalid data provided\n"); ret = DDS_ERRNO (DDS_RETCODE_ERROR); } else { diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_tran.h b/src/core/ddsi/include/dds/ddsi/ddsi_tran.h index 7946ca9..fa10474 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_tran.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_tran.h @@ -26,6 +26,12 @@ #define DDSI_TRAN_ON_CONNECT 0x0001 +#if DDSRT_HAVE_IPV6 == 1 +# define DDSI_LOCATORSTRLEN INET6_ADDRSTRLEN_EXTENDED +#else +# define DDSI_LOCATORSTRLEN INET_ADDRSTRLEN_EXTENDED +#endif + /* Core types */ typedef struct ddsi_tran_base * ddsi_tran_base_t; diff --git a/src/core/ddsi/include/dds/ddsi/q_bitset.h b/src/core/ddsi/include/dds/ddsi/q_bitset.h index efe9ba0..ec81027 100644 --- a/src/core/ddsi/include/dds/ddsi/q_bitset.h +++ b/src/core/ddsi/include/dds/ddsi/q_bitset.h @@ -13,41 +13,42 @@ #define NN_BITSET_H #include +#include #include #include "dds/ddsi/q_unused.h" -inline int nn_bitset_isset (unsigned numbits, const unsigned *bits, unsigned idx) +inline int nn_bitset_isset (uint32_t numbits, const uint32_t *bits, uint32_t idx) { - return idx < numbits && (bits[idx/32] & (1u << (31 - (idx%32)))); + return idx < numbits && (bits[idx/32] & (UINT32_C(1) << (31 - (idx%32)))); } -inline void nn_bitset_set (UNUSED_ARG_NDEBUG (unsigned numbits), unsigned *bits, unsigned idx) +inline void nn_bitset_set (UNUSED_ARG_NDEBUG (uint32_t numbits), uint32_t *bits, uint32_t idx) { assert (idx < numbits); - bits[idx/32] |= 1u << (31 - (idx%32)); + bits[idx/32] |= UINT32_C(1) << (31 - (idx%32)); } -inline void nn_bitset_clear (UNUSED_ARG_NDEBUG (unsigned numbits), unsigned *bits, unsigned idx) +inline void nn_bitset_clear (UNUSED_ARG_NDEBUG (uint32_t numbits), uint32_t *bits, uint32_t idx) { assert (idx < numbits); - bits[idx/32] &= ~(1u << (31 - (idx%32))); + bits[idx/32] &= ~(UINT32_C(1) << (31 - (idx%32))); } -inline void nn_bitset_zero (unsigned numbits, unsigned *bits) +inline void nn_bitset_zero (uint32_t numbits, uint32_t *bits) { memset (bits, 0, 4 * ((numbits + 31) / 32)); } -inline void nn_bitset_one (unsigned numbits, unsigned *bits) +inline void nn_bitset_one (uint32_t numbits, uint32_t *bits) { memset (bits, 0xff, 4 * ((numbits + 31) / 32)); /* clear bits "accidentally" set */ { - const unsigned k = numbits / 32; - const unsigned n = numbits % 32; - bits[k] &= ~(~0u >> n); + const uint32_t k = numbits / 32; + const uint32_t n = numbits % 32; + bits[k] &= ~(~UINT32_C(0) >> n); } } diff --git a/src/core/ddsi/include/dds/ddsi/q_error.h b/src/core/ddsi/include/dds/ddsi/q_error.h index c915b12..8c4f840 100644 --- a/src/core/ddsi/include/dds/ddsi/q_error.h +++ b/src/core/ddsi/include/dds/ddsi/q_error.h @@ -12,16 +12,16 @@ #ifndef NN_ERROR_H #define NN_ERROR_H -#define ERR_UNSPECIFIED -1 -#define ERR_INVALID -2 -#define ERR_OUT_OF_MEMORY -3 -#define ERR_ENTITY_EXISTS -4 -#define ERR_UNKNOWN_ENTITY -5 -#define ERR_OUT_OF_IDS -6 -#define ERR_INVALID_DATA -7 -#define ERR_BUSY -8 -#define ERR_NO_ADDRESS -9 -#define ERR_TIMEOUT -10 -#define ERR_INCOMPATIBLE -11 +#define Q_ERR_UNSPECIFIED -1 +#define Q_ERR_INVALID -2 +#define Q_ERR_OUT_OF_MEMORY -3 +#define Q_ERR_ENTITY_EXISTS -4 +#define Q_ERR_UNKNOWN_ENTITY -5 +#define Q_ERR_OUT_OF_IDS -6 +#define Q_ERR_INVALID_DATA -7 +#define Q_ERR_BUSY -8 +#define Q_ERR_NO_ADDRESS -9 +#define Q_ERR_TIMEOUT -10 +#define Q_ERR_INCOMPATIBLE -11 #endif /* NN_ERROR_H */ diff --git a/src/core/ddsi/include/dds/ddsi/q_time.h b/src/core/ddsi/include/dds/ddsi/q_time.h index 8048cfd..5c89cfa 100644 --- a/src/core/ddsi/include/dds/ddsi/q_time.h +++ b/src/core/ddsi/include/dds/ddsi/q_time.h @@ -53,9 +53,9 @@ int valid_ddsi_timestamp (nn_ddsi_time_t t); DDS_EXPORT nn_wctime_t now (void); /* wall clock time */ DDS_EXPORT nn_mtime_t now_mt (void); /* monotonic time */ DDS_EXPORT nn_etime_t now_et (void); /* elapsed time */ -DDS_EXPORT void mtime_to_sec_usec (int * __restrict sec, int * __restrict usec, nn_mtime_t t); -DDS_EXPORT void wctime_to_sec_usec (int * __restrict sec, int * __restrict usec, nn_wctime_t t); -DDS_EXPORT void etime_to_sec_usec (int * __restrict sec, int * __restrict usec, nn_etime_t t); +DDS_EXPORT void mtime_to_sec_usec (int32_t * __restrict sec, int32_t * __restrict usec, nn_mtime_t t); +DDS_EXPORT void wctime_to_sec_usec (int32_t * __restrict sec, int32_t * __restrict usec, nn_wctime_t t); +DDS_EXPORT void etime_to_sec_usec (int32_t * __restrict sec, int32_t * __restrict usec, nn_etime_t t); DDS_EXPORT nn_mtime_t mtime_round_up (nn_mtime_t t, int64_t round); DDS_EXPORT nn_mtime_t add_duration_to_mtime (nn_mtime_t t, int64_t d); DDS_EXPORT nn_wctime_t add_duration_to_wctime (nn_wctime_t t, int64_t d); diff --git a/src/core/ddsi/src/ddsi_ipaddr.c b/src/core/ddsi/src/ddsi_ipaddr.c index dc84dc7..c124b89 100644 --- a/src/core/ddsi/src/ddsi_ipaddr.c +++ b/src/core/ddsi/src/ddsi_ipaddr.c @@ -131,7 +131,7 @@ char *ddsi_ipaddr_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_ if (with_port) { pos = strlen (dst); assert(pos <= sizeof_dst); - snprintf (dst + pos, sizeof_dst - pos, ":%d", loc->port); + snprintf (dst + pos, sizeof_dst - pos, ":%"PRIu32, loc->port); } break; #if DDSRT_HAVE_IPV6 @@ -141,7 +141,7 @@ char *ddsi_ipaddr_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_ pos = strlen (dst); if (with_port) { assert(pos <= sizeof_dst); - snprintf (dst + pos, sizeof_dst - pos, "]:%u", loc->port); + snprintf (dst + pos, sizeof_dst - pos, "]:%"PRIu32, loc->port); } else { snprintf (dst + pos, sizeof_dst - pos, "]"); } diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index 4309baf..2bb6576 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -390,7 +390,7 @@ static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s { dds_retcode_t rc; ddsi_tcp_conn_t tcp = (ddsi_tcp_conn_t) conn; - ssize_t (*rd) (ddsi_tcp_conn_t, void *, size_t, int * err) = ddsi_tcp_conn_read_plain; + ssize_t (*rd) (ddsi_tcp_conn_t, void *, size_t, dds_retcode_t * err) = ddsi_tcp_conn_read_plain; size_t pos = 0; ssize_t n; @@ -467,7 +467,7 @@ static ssize_t ddsi_tcp_conn_write_ssl (ddsi_tcp_conn_t conn, const void * buf, static ssize_t ddsi_tcp_block_write ( - ssize_t (*wr) (ddsi_tcp_conn_t, const void *, size_t, int *), + ssize_t (*wr) (ddsi_tcp_conn_t, const void *, size_t, dds_retcode_t *), ddsi_tcp_conn_t conn, const void * buf, size_t sz @@ -654,7 +654,7 @@ static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const nn_locator_t *d if (piecewise) { - ssize_t (*wr) (ddsi_tcp_conn_t, const void *, size_t, int *) = ddsi_tcp_conn_write_plain; + ssize_t (*wr) (ddsi_tcp_conn_t, const void *, size_t, dds_retcode_t *) = ddsi_tcp_conn_write_plain; int i = 0; #ifdef DDSI_INCLUDE_SSL if (ddsi_tcp_ssl_plugin.write) diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index 0234c8f..a228097 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -490,7 +490,7 @@ static char *ddsi_udp_locator_to_string (ddsi_tran_factory_t tran, char *dst, si pos += (size_t)cnt; } if (with_port && pos < sizeof_dst) { - snprintf (dst + pos, sizeof_dst - pos, ":%d", loc->port); + snprintf (dst + pos, sizeof_dst - pos, ":%"PRIu32, loc->port); } return dst; } diff --git a/src/core/ddsi/src/q_bitset_inlines.c b/src/core/ddsi/src/q_bitset_inlines.c index 89d4b34..dbb9364 100644 --- a/src/core/ddsi/src/q_bitset_inlines.c +++ b/src/core/ddsi/src/q_bitset_inlines.c @@ -11,9 +11,9 @@ */ #include "dds/ddsi/q_bitset.h" -extern inline int nn_bitset_isset (unsigned numbits, const unsigned *bits, unsigned idx); -extern inline void nn_bitset_set (unsigned numbits, unsigned *bits, unsigned idx); -extern inline void nn_bitset_clear (unsigned numbits, unsigned *bits, unsigned idx); -extern inline void nn_bitset_zero (unsigned numbits, unsigned *bits); -extern inline void nn_bitset_one (unsigned numbits, unsigned *bits); +extern inline int nn_bitset_isset (uint32_t numbits, const uint32_t *bits, uint32_t idx); +extern inline void nn_bitset_set (uint32_t numbits, uint32_t *bits, uint32_t idx); +extern inline void nn_bitset_clear (uint32_t numbits, uint32_t *bits, uint32_t idx); +extern inline void nn_bitset_zero (uint32_t numbits, uint32_t *bits); +extern inline void nn_bitset_one (uint32_t numbits, uint32_t *bits); diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 596fb3e..07ddc4b 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -116,7 +116,7 @@ static const uint32_t xcheck_codes[] = { /* We want the tracing/verbosity settings to be fixed while parsing the configuration, so we update this variable instead. */ -static unsigned enabled_logcats; +static uint32_t enabled_logcats; static int cfgst_node_cmp(const void *va, const void *vb); static const ut_avlTreedef_t cfgst_found_treedef = @@ -1827,7 +1827,7 @@ static int uf_maybe_int32(struct cfgst *cfgst, void *parent, struct cfgelem cons elem->isdefault = 1; elem->value = 0; return 1; - } else if ( sscanf(value, "%d%n", &elem->value, &pos) == 1 && value[pos] == 0 ) { + } else if ( sscanf(value, "%"PRId32"%n", &elem->value, &pos) == 1 && value[pos] == 0 ) { elem->isdefault = 0; return 1; } else { @@ -1971,7 +1971,7 @@ static int uf_domainId(struct cfgst *cfgst, void *parent, struct cfgelem const * elem->isdefault = 1; elem->value = 0; return 1; - } else if (sscanf(value, "%d%n", &elem->value, &pos) == 1 && value[pos] == 0 && elem->value >= 0 && elem->value <= 230) { + } else if (sscanf(value, "%"PRId32"%n", &elem->value, &pos) == 1 && value[pos] == 0 && elem->value >= 0 && elem->value <= 230) { elem->isdefault = 0; return 1; } else { diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index ca34713..3f5a4b6 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -799,7 +799,7 @@ static void handle_SPDP (const struct receiver_state *rst, nn_wctime_t timestamp src.bufsz = len - 4; if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) { - if (plist_ret != ERR_INCOMPATIBLE) + if (plist_ret != Q_ERR_INCOMPATIBLE) DDS_WARNING("SPDP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); return; } @@ -1341,7 +1341,7 @@ static void handle_SEDP (const struct receiver_state *rst, nn_wctime_t timestamp src.bufsz = len - 4; if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) { - if (plist_ret != ERR_INCOMPATIBLE) + if (plist_ret != Q_ERR_INCOMPATIBLE) DDS_WARNING("SEDP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); return; } @@ -1469,7 +1469,7 @@ static void handle_SEDP_CM (const struct receiver_state *rst, nn_entityid_t wr_e src.bufsz = len - 4; if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) { - if (plist_ret != ERR_INCOMPATIBLE) + if (plist_ret != Q_ERR_INCOMPATIBLE) DDS_WARNING("SEDP_CM (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); return; } @@ -1631,7 +1631,7 @@ static void handle_SEDP_GROUP (const struct receiver_state *rst, nn_wctime_t tim src.bufsz = len - 4; if ((plist_ret = nn_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) { - if (plist_ret != ERR_INCOMPATIBLE) + if (plist_ret != Q_ERR_INCOMPATIBLE) DDS_WARNING("SEDP_GROUP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); return; } @@ -1754,7 +1754,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str src.bufsz = NN_RDATA_PAYLOAD_OFF (fragchain) - qos_offset; if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH, 0, &src)) < 0) { - if (plist_ret != ERR_INCOMPATIBLE) + if (plist_ret != Q_ERR_INCOMPATIBLE) DDS_WARNING("data(builtin, vendor %u.%u): %x:%x:%x:%x #%"PRId64": invalid inline qos\n", src.vendorid.id[0], src.vendorid.id[1], PGUID (srcguid), sampleinfo->seq); goto done_upd_deliv; diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 39e15c2..d83f225 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -381,7 +381,7 @@ int pp_allocate_entityid(nn_entityid_t *id, unsigned kind, struct participant *p else { DDS_ERROR("pp_allocate_entityid(%x:%x:%x:%x): all ids in use\n", PGUID(pp->e.guid)); - ret = ERR_OUT_OF_IDS; + ret = Q_ERR_OUT_OF_IDS; } ddsrt_mutex_unlock (&pp->e.lock); return ret; @@ -412,7 +412,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis used to exist, but is currently being deleted and we're trying to recreate it. */ if (ephash_lookup_participant_guid (ppguid) != NULL) - return ERR_ENTITY_EXISTS; + return Q_ERR_ENTITY_EXISTS; if (config.max_participants == 0) { @@ -432,7 +432,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis { ddsrt_mutex_unlock (&gv.participant_set_lock); DDS_ERROR("new_participant(%x:%x:%x:%x, %x) failed: max participants reached\n", PGUID (*ppguid), flags); - return ERR_OUT_OF_IDS; + return Q_ERR_OUT_OF_IDS; } } @@ -659,7 +659,7 @@ int new_participant (nn_guid_t *p_ppguid, unsigned flags, const nn_plist_t *plis if (gv.next_ppguid.prefix.u[2]++ == ~0u) { ddsrt_mutex_unlock (&gv.privileged_pp_lock); - return ERR_OUT_OF_IDS; + return Q_ERR_OUT_OF_IDS; } ddsrt_mutex_unlock (&gv.privileged_pp_lock); *p_ppguid = ppguid; @@ -854,7 +854,7 @@ int delete_participant (const struct nn_guid *ppguid) { struct participant *pp; if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL) - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; ddsi_plugin.builtintopic_write (&pp->e, now(), false); remember_deleted_participant_guid (&pp->e.guid); ephash_remove_participant_guid (pp); @@ -1105,7 +1105,7 @@ static void rebuild_trace_covered(int nreaders, int nlocs, const nn_locator_t *l int i, j; for (i = 0; i < nlocs; i++) { - char buf[INET6_ADDRSTRLEN_EXTENDED]; + char buf[DDSI_LOCATORSTRLEN]; ddsi_locator_to_string(buf, sizeof(buf), &locs[i]); DDS_LOG(DDS_LC_DISCOVERY, " loc %2d = %-20s %2d {", i, buf, locs_nrds[i]); for (j = 0; j < nreaders; j++) @@ -1140,7 +1140,7 @@ static int rebuild_select(int nlocs, const nn_locator_t *locs, const int *locs_n static void rebuild_add(struct addrset *newas, int locidx, int nreaders, int nlocs, const nn_locator_t *locs, const int8_t *covered) { - char str[INET6_ADDRSTRLEN_EXTENDED]; + char str[DDSI_LOCATORSTRLEN]; if (locs[locidx].kind != NN_LOCATOR_KIND_UDPv4MCGEN) { ddsi_locator_to_string(str, sizeof(str), &locs[locidx]); @@ -2987,7 +2987,7 @@ int delete_writer_nolinger (const struct nn_guid *guid) if ((wr = ephash_lookup_writer_guid (guid)) == NULL) { DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid %x:%x:%x:%x) - unknown guid\n", PGUID (*guid)); - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; } DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid %x:%x:%x:%x) ...\n", PGUID (*guid)); ddsrt_mutex_lock (&wr->e.lock); @@ -3010,7 +3010,7 @@ int delete_writer (const struct nn_guid *guid) if ((wr = ephash_lookup_writer_guid (guid)) == NULL) { DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid %x:%x:%x:%x) - unknown guid\n", PGUID (*guid)); - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; } DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid %x:%x:%x:%x) ...\n", PGUID (*guid)); ddsrt_mutex_lock (&wr->e.lock); @@ -3029,12 +3029,12 @@ int delete_writer (const struct nn_guid *guid) else { nn_mtime_t tsched; - int tsec, tusec; + int32_t tsec, tusec; writer_set_state (wr, WRST_LINGERING); ddsrt_mutex_unlock (&wr->e.lock); tsched = add_duration_to_mtime (now_mt (), config.writer_linger_duration); mtime_to_sec_usec (&tsec, &tusec, tsched); - DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid %x:%x:%x:%x) - unack'ed samples, will delete when ack'd or at t = %d.%06d\n", + DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid %x:%x:%x:%x) - unack'ed samples, will delete when ack'd or at t = %"PRId32".%06"PRId32"\n", PGUID (*guid), tsec, tusec); qxev_delete_writer (tsched, &wr->e.guid); } @@ -3388,7 +3388,7 @@ int delete_reader (const struct nn_guid *guid) if ((rd = ephash_lookup_reader_guid (guid)) == NULL) { DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid %x:%x:%x:%x) - unknown guid\n", PGUID (*guid)); - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; } if (rd->rhc) { @@ -3900,7 +3900,7 @@ int delete_proxy_participant_by_guid (const struct nn_guid * guid, nn_wctime_t t { ddsrt_mutex_unlock (&gv.lock); DDS_LOG(DDS_LC_DISCOVERY, "- unknown\n"); - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; } DDS_LOG(DDS_LC_DISCOVERY, "- deleting\n"); ddsi_plugin.builtintopic_write (&ppt->e, timestamp, false); @@ -3955,7 +3955,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct break; default: DDS_WARNING("new_proxy_group: unrecognised entityid: %x\n", guid->entityid.u); - return ERR_INVALID_DATA; + return Q_ERR_INVALID_DATA; } ddsrt_mutex_lock (&proxypp->e.lock); if ((pgroup = ut_avlLookupIPath (&proxypp_groups_treedef, &proxypp->groups, guid, &ipath)) != NULL) @@ -4084,7 +4084,7 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, if ((proxypp = ephash_lookup_proxy_participant_guid (ppguid)) == NULL) { DDS_WARNING("new_proxy_writer(%x:%x:%x:%x): proxy participant unknown\n", PGUID (*guid)); - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; } pwr = ddsrt_malloc (sizeof (*pwr)); @@ -4277,7 +4277,7 @@ int delete_proxy_writer (const struct nn_guid *guid, nn_wctime_t timestamp, int { ddsrt_mutex_unlock (&gv.lock); DDS_LOG(DDS_LC_DISCOVERY, "- unknown\n"); - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; } /* Set "deleting" flag in particular for Lite, to signal to the receive path it can't trust rdary[] anymore, which is because removing the proxy writer from the hash @@ -4310,7 +4310,7 @@ int new_proxy_reader (const struct nn_guid *ppguid, const struct nn_guid *guid, if ((proxypp = ephash_lookup_proxy_participant_guid (ppguid)) == NULL) { DDS_WARNING("new_proxy_reader(%x:%x:%x:%x): proxy participant unknown\n", PGUID (*guid)); - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; } prd = ddsrt_malloc (sizeof (*prd)); @@ -4408,7 +4408,7 @@ int delete_proxy_reader (const struct nn_guid *guid, nn_wctime_t timestamp, int { ddsrt_mutex_unlock (&gv.lock); DDS_LOG(DDS_LC_DISCOVERY, "- unknown\n"); - return ERR_UNKNOWN_ENTITY; + return Q_ERR_UNKNOWN_ENTITY; } ddsi_plugin.builtintopic_write (&prd->e, timestamp, false); ephash_remove_proxy_reader_guid (prd); diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c index 438c0bf..1dac32c 100644 --- a/src/core/ddsi/src/q_lease.c +++ b/src/core/ddsi/src/q_lease.c @@ -164,14 +164,14 @@ void lease_renew (struct lease *l, nn_etime_t tnowE) if (did_update && (dds_get_log_mask() & DDS_LC_TRACE)) { - int tsec, tusec; + int32_t tsec, tusec; DDS_TRACE(" L("); if (l->entity->guid.entityid.u == NN_ENTITYID_PARTICIPANT) DDS_TRACE(":%x", l->entity->guid.entityid.u); else DDS_TRACE("%x:%x:%x:%x", PGUID (l->entity->guid)); etime_to_sec_usec (&tsec, &tusec, tend_new); - DDS_TRACE(" %d.%06d)", tsec, tusec); + DDS_TRACE(" %"PRId32".%06"PRId32")", tsec, tusec); } } diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index d6a7109..66c49bf 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -39,7 +39,7 @@ static void print_sockerror (const char *msg) unsigned locator_to_hopefully_unique_uint32 (const nn_locator_t *src) { - unsigned id; + unsigned id = 0; if (src->kind == NN_LOCATOR_KIND_UDPv4 || src->kind == NN_LOCATOR_KIND_TCPv4) memcpy (&id, src->address + 12, sizeof (id)); else @@ -93,7 +93,7 @@ static void set_socket_nodelay (ddsrt_socket_t sock) static int set_rcvbuf (ddsrt_socket_t socket) { uint32_t ReceiveBufferSize; - uint32_t optlen = (uint32_t) sizeof (ReceiveBufferSize); + socklen_t optlen = (socklen_t) sizeof (ReceiveBufferSize); uint32_t socket_min_rcvbuf_size; if (config.socket_min_rcvbuf_size.isdefault) socket_min_rcvbuf_size = 1048576; @@ -137,7 +137,7 @@ static int set_rcvbuf (ddsrt_socket_t socket) static int set_sndbuf (ddsrt_socket_t socket) { unsigned SendBufferSize; - uint32_t optlen = (uint32_t) sizeof(SendBufferSize); + socklen_t optlen = (socklen_t) sizeof(SendBufferSize); if (ddsrt_getsockopt(socket, SOL_SOCKET, SO_SNDBUF,(char *)&SendBufferSize, &optlen) != DDS_RETCODE_OK) { print_sockerror ("get SO_SNDBUF"); diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index 8ee2ccd..ad97995 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -92,18 +92,18 @@ static int validate_string (const struct dd *dd, size_t *len) if (dd->bufsz < sizeof (struct cdrstring)) { DDS_TRACE("plist/validate_string: buffer too small (header)\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } *len = dd->bswap ? bswap4u (x->length) : x->length; if (*len < 1 || *len > dd->bufsz - offsetof (struct cdrstring, contents)) { DDS_TRACE("plist/validate_string: length %" PRIuSIZE " out of range\n", *len); - return ERR_INVALID; + return Q_ERR_INVALID; } if (x->contents[*len-1] != 0) { DDS_TRACE("plist/validate_string: terminator missing\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } return 0; } @@ -142,10 +142,10 @@ static int validate_octetseq (const struct dd *dd, size_t *len) { const struct cdroctetseq *x = (const struct cdroctetseq *) dd->buf; if (dd->bufsz < offsetof (struct cdroctetseq, value)) - return ERR_INVALID; + return Q_ERR_INVALID; *len = dd->bswap ? bswap4u (x->len) : x->len; if (*len > dd->bufsz - offsetof (struct cdroctetseq, value)) - return ERR_INVALID; + return Q_ERR_INVALID; return 0; } @@ -193,7 +193,7 @@ static int validate_stringseq (const struct dd *dd) if (dd->bufsz < sizeof (int)) { DDS_TRACE("plist/validate_stringseq: buffer too small (header)\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&n, seq, sizeof (n)); if (dd->bswap) @@ -202,7 +202,7 @@ static int validate_stringseq (const struct dd *dd) if (n < 0) { DDS_TRACE("plist/validate_stringseq: length %d out of range\n", n); - return ERR_INVALID; + return Q_ERR_INVALID; } else if (n == 0) { @@ -226,7 +226,7 @@ static int validate_stringseq (const struct dd *dd) if (i < n) { DDS_TRACE("plist/validate_stringseq: buffer too small (contents)\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } } /* Should I worry about junk between the last string & the end of @@ -248,7 +248,7 @@ static int alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd) if (dd->bufsz < sizeof (int)) { DDS_TRACE("plist/alias_stringseq: buffer too small (header)\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&strseq->n, seq, sizeof (strseq->n)); if (dd->bswap) @@ -257,7 +257,7 @@ static int alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd) if (strseq->n >= UINT_MAX / sizeof(*strs)) { DDS_TRACE("plist/alias_stringseq: length %u out of range\n", strseq->n); - return ERR_INVALID; + return Q_ERR_INVALID; } else if (strseq->n == 0) { @@ -284,7 +284,7 @@ static int alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd) if (i != strseq->n) { DDS_TRACE("plist/validate_stringseq: buffer too small (contents)\n"); - result = ERR_INVALID; + result = Q_ERR_INVALID; goto fail; } strseq->strs = strs; @@ -535,7 +535,7 @@ static int validate_time (const nn_ddsi_time_t *t) else { DDS_TRACE("plist/validate_time: invalid timestamp (%08x.%08x)\n", t->seconds, t->fraction); - return ERR_INVALID; + return Q_ERR_INVALID; } } @@ -555,7 +555,7 @@ static int do_duration (nn_duration_t *q, uint64_t *present, uint64_t fl, const if (dd->bufsz < sizeof (*q)) { DDS_TRACE("plist/do_duration: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (q, dd->buf, sizeof (*q)); if (dd->bswap) @@ -582,7 +582,7 @@ int validate_durability_qospolicy (const nn_durability_qospolicy_t *q) break; default: DDS_TRACE("plist/validate_durability_qospolicy: invalid kind (%d)\n", (int) q->kind); - return ERR_INVALID; + return Q_ERR_INVALID; } return 0; } @@ -614,7 +614,7 @@ int validate_history_qospolicy (const nn_history_qospolicy_t *q) break; default: DDS_TRACE("plist/validate_history_qospolicy: invalid kind (%d)\n", (int) q->kind); - return ERR_INVALID; + return Q_ERR_INVALID; } /* Accept all values for depth if kind = ALL */ if (q->kind == NN_KEEP_LAST_HISTORY_QOS) @@ -622,7 +622,7 @@ int validate_history_qospolicy (const nn_history_qospolicy_t *q) if (q->depth < 1) { DDS_TRACE("plist/validate_history_qospolicy: invalid depth (%d)\n", (int) q->depth); - return ERR_INVALID; + return Q_ERR_INVALID; } } return 0; @@ -649,17 +649,17 @@ int validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q) if (q->max_samples < 1 && q->max_samples != unlimited) { DDS_TRACE("plist/validate_resource_limits_qospolicy: max_samples invalid (%d)\n", (int) q->max_samples); - return ERR_INVALID; + return Q_ERR_INVALID; } if (q->max_instances < 1 && q->max_instances != unlimited) { DDS_TRACE("plist/validate_resource_limits_qospolicy: max_instances invalid (%d)\n", (int) q->max_instances); - return ERR_INVALID; + return Q_ERR_INVALID; } if (q->max_samples_per_instance < 1 && q->max_samples_per_instance != unlimited) { DDS_TRACE("plist/validate_resource_limits_qospolicy: max_samples_per_instance invalid (%d)\n", (int) q->max_samples_per_instance); - return ERR_INVALID; + return Q_ERR_INVALID; } if (q->max_samples != unlimited && q->max_samples_per_instance != unlimited) { @@ -668,7 +668,7 @@ int validate_resource_limits_qospolicy (const nn_resource_limits_qospolicy_t *q) if (q->max_samples < q->max_samples_per_instance) { DDS_TRACE("plist/validate_resource_limits_qospolicy: max_samples (%d) and max_samples_per_instance (%d) incompatible\n", (int) q->max_samples, (int) q->max_samples_per_instance); - return ERR_INVALID; + return Q_ERR_INVALID; } } return 0; @@ -695,7 +695,7 @@ int validate_history_and_resource_limits (const nn_history_qospolicy_t *qh, cons if (qr->max_samples_per_instance != unlimited) { DDS_TRACE("plist/validate_history_and_resource_limits: max_samples_per_instance (%d) incompatible with KEEP_ALL policy\n", (int) qr->max_samples_per_instance); - return ERR_INVALID; + return Q_ERR_INVALID; } #endif break; @@ -703,7 +703,7 @@ int validate_history_and_resource_limits (const nn_history_qospolicy_t *qh, cons if (qr->max_samples_per_instance != unlimited && qh->depth > qr->max_samples_per_instance) { DDS_TRACE("plist/validate_history_and_resource_limits: depth (%d) and max_samples_per_instance (%d) incompatible with KEEP_LAST policy\n", (int) qh->depth, (int) qr->max_samples_per_instance); - return ERR_INVALID; + return Q_ERR_INVALID; } break; } @@ -766,7 +766,7 @@ int validate_liveliness_qospolicy (const nn_liveliness_qospolicy_t *q) return res; default: DDS_TRACE("plist/validate_liveliness_qospolicy: invalid kind (%d)\n", (int) q->kind); - return ERR_INVALID; + return Q_ERR_INVALID; } } @@ -794,7 +794,7 @@ static int validate_xform_reliability_qospolicy (nn_reliability_qospolicy_t *qds return res; default: DDS_TRACE("plist/validate_xform_reliability_qospolicy[pedantic]: invalid kind (%d)\n", (int) qext->kind); - return ERR_INVALID; + return Q_ERR_INVALID; } } else @@ -811,7 +811,7 @@ static int validate_xform_reliability_qospolicy (nn_reliability_qospolicy_t *qds return res; default: DDS_TRACE("plist/validate_xform_reliability_qospolicy[!pedantic]: invalid kind (%d)\n", (int) qext->kind); - return ERR_INVALID; + return Q_ERR_INVALID; } } } @@ -830,7 +830,7 @@ int validate_destination_order_qospolicy (const nn_destination_order_qospolicy_t return 0; default: DDS_TRACE("plist/validate_destination_order_qospolicy: invalid kind (%d)\n", (int) q->kind); - return ERR_INVALID; + return Q_ERR_INVALID; } } @@ -848,7 +848,7 @@ int validate_ownership_qospolicy (const nn_ownership_qospolicy_t *q) return 0; default: DDS_TRACE("plist/validate_ownership_qospolicy: invalid kind (%d)\n", (int) q->kind); - return ERR_INVALID; + return Q_ERR_INVALID; } } @@ -877,18 +877,18 @@ int validate_presentation_qospolicy (const nn_presentation_qospolicy_t *q) break; default: DDS_TRACE("plist/validate_presentation_qospolicy: invalid access_scope (%d)\n", (int) q->access_scope); - return ERR_INVALID; + return Q_ERR_INVALID; } /* Bools must be 0 or 1, i.e., only the lsb may be set */ if (q->coherent_access & ~1) { DDS_TRACE("plist/validate_presentation_qospolicy: coherent_access invalid (%d)\n", (int) q->coherent_access); - return ERR_INVALID; + return Q_ERR_INVALID; } if (q->ordered_access & ~1) { DDS_TRACE("plist/validate_presentation_qospolicy: ordered_access invalid (%d)\n", (int) q->ordered_access); - return ERR_INVALID; + return Q_ERR_INVALID; } /* coherent_access & ordered_access are a bit irrelevant for instance presentation qos, but it appears as if their values are @@ -964,7 +964,7 @@ static int do_locator if (dd->bufsz < sizeof (loc)) { DDS_TRACE("plist/do_locator: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&loc, dd->buf, sizeof (loc)); if (dd->bswap) @@ -979,12 +979,12 @@ static int do_locator if (loc.port <= 0 || loc.port > 65535) { DDS_TRACE("plist/do_locator[kind=IPv4]: invalid port (%d)\n", (int) loc.port); - return ERR_INVALID; + return Q_ERR_INVALID; } if (!locator_address_prefix12_zero (&loc)) { DDS_TRACE("plist/do_locator[kind=IPv4]: junk in address prefix\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } break; case NN_LOCATOR_KIND_UDPv6: @@ -992,7 +992,7 @@ static int do_locator if (loc.port <= 0 || loc.port > 65535) { DDS_TRACE("plist/do_locator[kind=IPv6]: invalid port (%d)\n", (int) loc.port); - return ERR_INVALID; + return Q_ERR_INVALID; } break; case NN_LOCATOR_KIND_UDPv4MCGEN: { @@ -1002,12 +1002,12 @@ static int do_locator if (loc.port <= 0 || loc.port > 65536) { DDS_TRACE("plist/do_locator[kind=IPv4MCGEN]: invalid port (%d)\n", (int) loc.port); - return ERR_INVALID; + return Q_ERR_INVALID; } if ((int)x->base + x->count >= 28 || x->count == 0 || x->idx >= x->count) { DDS_TRACE("plist/do_locator[kind=IPv4MCGEN]: invalid base/count/idx (%u,%u,%u)\n", x->base, x->count, x->idx); - return ERR_INVALID; + return Q_ERR_INVALID; } break; } @@ -1015,12 +1015,12 @@ static int do_locator if (!locator_address_zero (&loc)) { DDS_TRACE("plist/do_locator[kind=INVALID]: junk in address\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } if (loc.port != 0) { DDS_TRACE("plist/do_locator[kind=INVALID]: junk in port\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } /* silently dropped correctly formatted "invalid" locators. */ return 0; @@ -1029,7 +1029,7 @@ static int do_locator return 0; default: DDS_TRACE("plist/do_locator: invalid kind (%d)\n", (int) loc.kind); - return NN_PEDANTIC_P ? ERR_INVALID : 0; + return NN_PEDANTIC_P ? Q_ERR_INVALID : 0; } return add_locator (ls, present, wanted, fl, &loc); } @@ -1052,7 +1052,7 @@ static int do_ipv4address (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp if (dd->bufsz < sizeof (*a)) { DDS_TRACE("plist/do_ipv4address: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } switch (fl_tmp) { @@ -1122,7 +1122,7 @@ static int do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint6 if (dd->bufsz < sizeof (*p)) { DDS_TRACE("plist/do_port: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } switch (fl_tmp) { @@ -1156,7 +1156,7 @@ static int do_port (nn_plist_t *dest, nn_ipaddress_params_tmp_t *dest_tmp, uint6 if (*p <= 0 || *p > 65535) { DDS_TRACE("plist/do_port: invalid port (%d)\n", (int) *p); - return ERR_INVALID; + return Q_ERR_INVALID; } dest_tmp->present |= fl_tmp; if ((dest_tmp->present & (fl_tmp | fl1_tmp)) == (fl_tmp | fl1_tmp)) @@ -1185,7 +1185,7 @@ static int valid_participant_guid (const nn_guid_t *g, UNUSED_ARG (const struct else { DDS_TRACE("plist/valid_participant_guid: prefix is 0 but entityid is not (%u)\n", g->entityid.u); - return ERR_INVALID; + return Q_ERR_INVALID; } } else if (g->entityid.u == NN_ENTITYID_PARTICIPANT) @@ -1195,7 +1195,7 @@ static int valid_participant_guid (const nn_guid_t *g, UNUSED_ARG (const struct else { DDS_TRACE("plist/valid_participant_guid: entityid not a participant entityid (%u)\n", g->entityid.u); - return ERR_INVALID; + return Q_ERR_INVALID; } } @@ -1209,7 +1209,7 @@ static int valid_group_guid (const nn_guid_t *g, UNUSED_ARG (const struct dd *dd else { DDS_TRACE("plist/valid_group_guid: prefix is 0 but entityid is not (%u)\n", g->entityid.u); - return ERR_INVALID; + return Q_ERR_INVALID; } } else if (g->entityid.u != 0) @@ -1220,7 +1220,7 @@ static int valid_group_guid (const nn_guid_t *g, UNUSED_ARG (const struct dd *dd else { DDS_TRACE("plist/valid_group_guid: entityid is 0\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } } @@ -1234,7 +1234,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) else { DDS_TRACE("plist/valid_endpoint_guid: prefix is 0 but entityid is not (%x)\n", g->entityid.u); - return ERR_INVALID; + return Q_ERR_INVALID; } } switch (g->entityid.u & NN_ENTITYID_SOURCE_MASK) @@ -1255,7 +1255,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) DDS_TRACE("plist/valid_endpoint_guid[src=USER,proto=%u.%u]: invalid kind (%x)\n", dd->protocol_version.major, dd->protocol_version.minor, g->entityid.u & NN_ENTITYID_KIND_MASK); - return ERR_INVALID; + return Q_ERR_INVALID; } } case NN_ENTITYID_SOURCE_BUILTIN: @@ -1279,7 +1279,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) { DDS_TRACE("plist/valid_endpoint_guid[src=BUILTIN,proto=%u.%u]: invalid entityid (%x)\n", dd->protocol_version.major, dd->protocol_version.minor, g->entityid.u); - return ERR_INVALID; + return Q_ERR_INVALID; } } case NN_ENTITYID_SOURCE_VENDOR: @@ -1309,7 +1309,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) } default: DDS_TRACE("plist/valid_endpoint_guid: invalid source (%x)\n", g->entityid.u); - return ERR_INVALID; + return Q_ERR_INVALID; } } @@ -1318,7 +1318,7 @@ static int do_guid (nn_guid_t *dst, uint64_t *present, uint64_t fl, int (*valid) if (dd->bufsz < sizeof (*dst)) { DDS_TRACE("plist/do_guid: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (dst, dd->buf, sizeof (*dst)); *dst = nn_ntoh_guid (*dst); @@ -1334,7 +1334,7 @@ static int do_guid (nn_guid_t *dst, uint64_t *present, uint64_t fl, int (*valid) } else { - return ERR_INVALID; + return Q_ERR_INVALID; } } *present |= fl; @@ -1358,7 +1358,7 @@ static int do_prismtech_participant_version_info (nn_prismtech_participant_versi else if (dd->bufsz < NN_PRISMTECH_PARTICIPANT_VERSION_INFO_FIXED_CDRSIZE) { DDS_TRACE("plist/do_prismtech_participant_version_info[pid=PRISMTECH_PARTICIPANT_VERSION_INFO]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -1393,13 +1393,13 @@ static int do_subscription_keys_qospolicy (nn_subscription_keys_qospolicy_t *q, if (dd->bufsz < 4) { DDS_TRACE("plist/do_subscription_keys: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } q->use_key_list = (unsigned char) dd->buf[0]; if (q->use_key_list != 0 && q->use_key_list != 1) { DDS_TRACE("plist/do_subscription_keys: invalid use_key_list (%d)\n", (int) q->use_key_list); - return ERR_INVALID; + return Q_ERR_INVALID; } dd1 = *dd; dd1.buf += 4; @@ -1423,7 +1423,7 @@ static int do_reader_lifespan_qospolicy (nn_reader_lifespan_qospolicy_t *q, uint if (dd->bufsz < sizeof (*q)) { DDS_TRACE("plist/do_reader_lifespan: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } *q = *((nn_reader_lifespan_qospolicy_t *) dd->buf); if (dd->bswap) @@ -1431,7 +1431,7 @@ static int do_reader_lifespan_qospolicy (nn_reader_lifespan_qospolicy_t *q, uint if (q->use_lifespan != 0 && q->use_lifespan != 1) { DDS_TRACE("plist/do_reader_lifespan: invalid use_lifespan (%d)\n", (int) q->use_lifespan); - return ERR_INVALID; + return Q_ERR_INVALID; } if ((res = validate_duration (&q->duration)) >= 0) *present |= fl; @@ -1443,13 +1443,13 @@ static int do_entity_factory_qospolicy (nn_entity_factory_qospolicy_t *q, uint64 if (dd->bufsz < sizeof (*q)) { DDS_TRACE("plist/do_entity_factory: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } q->autoenable_created_entities = dd->buf[0]; if (q->autoenable_created_entities != 0 && q->autoenable_created_entities != 1) { DDS_TRACE("plist/do_entity_factory: invalid autoenable_created_entities (%d)\n", (int) q->autoenable_created_entities); - return ERR_INVALID; + return Q_ERR_INVALID; } *present |= fl; return 0; @@ -1461,17 +1461,17 @@ int validate_reader_data_lifecycle (const nn_reader_data_lifecycle_qospolicy_t * validate_duration (&q->autopurge_disposed_samples_delay) < 0) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid autopurge_nowriter_sample_delay or autopurge_disposed_samples_delay\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } if (q->autopurge_dispose_all != 0 && q->autopurge_dispose_all != 1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid autopurge_dispose_all\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } if (q->enable_invalid_samples != 0 && q->enable_invalid_samples != 1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid enable_invalid_samples\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } /* Don't check consistency between enable_invalid_samples and invalid_samples_mode (yet) */ switch (q->invalid_sample_visibility) @@ -1482,7 +1482,7 @@ int validate_reader_data_lifecycle (const nn_reader_data_lifecycle_qospolicy_t * break; default: DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: invalid invalid_sample_visibility\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } return 0; } @@ -1535,7 +1535,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (nn_##name_##_qospolicy_t)) \ { \ DDS_TRACE("plist/init_one_parameter[pid=%s]: buffer too small\n", #NAME_); \ - return ERR_INVALID; \ + return Q_ERR_INVALID; \ } \ else \ { \ @@ -1562,7 +1562,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (nn_durability_service_qospolicy_t)) { DDS_TRACE("plist/init_one_parameter[pid=DURABILITY_SERVICE]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -1589,7 +1589,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (nn_external_reliability_qospolicy_t)) { DDS_TRACE("plist/init_one_parameter[pid=RELIABILITY]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -1640,7 +1640,7 @@ static int init_one_parameter else { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_READER_DATA_LIFECYCLE]: buffer too small\n"); - ret = ERR_INVALID; + ret = Q_ERR_INVALID; } if (ret >= 0) dest->qos.present |= QP_PRISMTECH_READER_DATA_LIFECYCLE; @@ -1655,7 +1655,7 @@ static int init_one_parameter if (dd->bufsz < 1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else if (dd->bufsz < sizeof (*q)) { @@ -1676,13 +1676,13 @@ static int init_one_parameter if (q->autodispose_unregistered_instances & ~1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: invalid autodispose_unregistered_instances (%d)\n", (int) q->autodispose_unregistered_instances); - return ERR_INVALID; + return Q_ERR_INVALID; } if (validate_duration (&q->autounregister_instance_delay) < 0 || validate_duration (&q->autopurge_suspended_samples_delay) < 0) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_WRITER_DATA_LIFECYCLE]: invalid autounregister_instance_delay or autopurge_suspended_samples_delay\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->qos.present |= QP_PRISMTECH_WRITER_DATA_LIFECYCLE; return 0; @@ -1694,7 +1694,7 @@ static int init_one_parameter else if (dd->bufsz < sizeof (dest->qos.relaxed_qos_matching)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_RELAXED_QOS_MATCHING]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -1703,7 +1703,7 @@ static int init_one_parameter if (rqm->value != 0 && rqm->value != 1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_RELAXED_QOS_MATCHING]: invalid\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->qos.present |= QP_PRISMTECH_RELAXED_QOS_MATCHING; return 0; @@ -1715,7 +1715,7 @@ static int init_one_parameter else if (dd->bufsz < sizeof (dest->qos.synchronous_endpoint)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_SYNCHRONOUS_ENDPOINT]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -1724,7 +1724,7 @@ static int init_one_parameter if (q->value != 0 && q->value != 1) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_SYNCHRONOUS_ENDPOINT]: invalid value for synchronous flag\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->qos.present |= QP_PRISMTECH_SYNCHRONOUS_ENDPOINT; return 0; @@ -1735,7 +1735,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (nn_protocol_version_t)) { DDS_TRACE("plist/init_one_parameter[pid=PROTOCOL_VERSION]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&dest->protocol_version, dd->buf, sizeof (dest->protocol_version)); if (NN_STRICT_P && @@ -1748,14 +1748,14 @@ static int init_one_parameter DDS_TRACE("plist/init_one_parameter[pid=PROTOCOL_VERSION,mode=STRICT]: version (%u.%u) mismatch with message (%u.%u)\n", dest->protocol_version.major, dest->protocol_version.minor, dd->protocol_version.major, dd->protocol_version.minor); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->present |= PP_PROTOCOL_VERSION; return 0; case PID_VENDORID: if (dd->bufsz < sizeof (nn_vendorid_t)) - return ERR_INVALID; + return Q_ERR_INVALID; memcpy (&dest->vendorid, dd->buf, sizeof (dest->vendorid)); if (NN_STRICT_P && (dest->vendorid.id[0] != dd->vendorid.id[0] || @@ -1764,7 +1764,7 @@ static int init_one_parameter /* see PROTOCOL_VERSION */ DDS_TRACE("plist/init_one_parameter[pid=VENDORID,mode=STRICT]: vendor (%u.%u) mismatch with message (%u.%u)\n", dest->vendorid.id[0], dest->vendorid.id[1], dd->vendorid.id[0], dd->vendorid.id[1]); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->present |= PP_VENDORID; return 0; @@ -1808,7 +1808,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->expects_inline_qos)) { DDS_TRACE("plist/init_one_parameter[pid=EXPECTS_INLINE_QOS]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->expects_inline_qos = dd->buf[0]; /* boolean: only lsb may be set */ @@ -1816,7 +1816,7 @@ static int init_one_parameter { DDS_TRACE("plist/init_one_parameter[pid=EXPECTS_INLINE_QOS]: invalid expects_inline_qos (%d)\n", (int) dest->expects_inline_qos); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->present |= PP_EXPECTS_INLINE_QOS; return 0; @@ -1828,7 +1828,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->participant_manual_liveliness_count)) { DDS_TRACE("plist/init_one_parameter[pid=PARTICIPANT_MANUAL_LIVELINESS_COUNT]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&dest->participant_manual_liveliness_count, dd->buf, sizeof (dest->participant_manual_liveliness_count)); if (dd->bswap) @@ -1862,7 +1862,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->builtin_endpoint_set)) { DDS_TRACE("plist/init_one_parameter[pid=BUILTIN_ENDPOINT_SET(%u)]: buffer too small\n", pid); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&dest->builtin_endpoint_set, dd->buf, sizeof (dest->builtin_endpoint_set)); if (dd->bswap) @@ -1887,7 +1887,7 @@ static int init_one_parameter { DDS_TRACE("plist/init_one_parameter[pid=BUILTIN_ENDPOINT_SET(%u),mode=STRICT,proto=%u.%u]: invalid set (0x%x)\n", pid, dd->protocol_version.major, dd->protocol_version.minor, dest->builtin_endpoint_set); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->present |= PP_BUILTIN_ENDPOINT_SET; return 0; @@ -1898,7 +1898,7 @@ static int init_one_parameter else if (dd->bufsz < sizeof (dest->prismtech_builtin_endpoint_set)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_BUILTIN_ENDPOINT_SET(%u)]: buffer too small\n", pid); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -1921,7 +1921,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->keyhash)) { DDS_TRACE("plist/init_one_parameter[pid=KEYHASH]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&dest->keyhash, dd->buf, sizeof (dest->keyhash)); dest->present |= PP_KEYHASH; @@ -1931,7 +1931,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->statusinfo)) { DDS_TRACE("plist/init_one_parameter[pid=STATUSINFO]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&dest->statusinfo, dd->buf, sizeof (dest->statusinfo)); dest->statusinfo = fromBE4u (dest->statusinfo); @@ -1942,7 +1942,7 @@ static int init_one_parameter may use them in this version of the specification */ DDS_TRACE("plist/init_one_parameter[pid=STATUSINFO,mode=STRICT,proto=%u.%u]: invalid statusinfo (0x%x)\n", dd->protocol_version.major, dd->protocol_version.minor, dest->statusinfo); - return ERR_INVALID; + return Q_ERR_INVALID; } /* Clear all bits we don't understand, then add the extended bits if present */ dest->statusinfo &= NN_STATUSINFO_STANDARDIZED; @@ -1962,7 +1962,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->coherent_set_seqno)) { DDS_TRACE("plist/init_one_parameter[pid=COHERENT_SET]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -1978,7 +1978,7 @@ static int init_one_parameter if (seqno <= 0 && seqno != NN_SEQUENCE_NUMBER_UNKNOWN) { DDS_TRACE("plist/init_one_parameter[pid=COHERENT_SET]: invalid sequence number (%" PRId64 ")\n", seqno); - return ERR_INVALID; + return Q_ERR_INVALID; } dest->present |= PP_COHERENT_SET; return 0; @@ -1999,7 +1999,7 @@ static int init_one_parameter ignore it. */ DDS_TRACE("plist/init_one_parameter[pid=ENDPOINT_GUID,mode=PEDANTIC,proto=%u.%u]: undefined pid\n", dd->protocol_version.major, dd->protocol_version.minor); - return ERR_INVALID; + return Q_ERR_INVALID; } return do_guid (&dest->endpoint_guid, &dest->present, PP_ENDPOINT_GUID, valid_endpoint_guid, dd); @@ -2056,7 +2056,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->service_type)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_SERVICE_TYPE]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&dest->service_type, dd->buf, sizeof (dest->service_type)); if (dd->bswap) @@ -2070,7 +2070,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->process_id)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_PROCESS_ID]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } memcpy (&dest->process_id, dd->buf, sizeof (dest->process_id)); if (dd->bswap) @@ -2089,7 +2089,7 @@ static int init_one_parameter else if (dd->bufsz < 2*sizeof (uint32_t)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_EOTINFO]: buffer too small (1)\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -2105,7 +2105,7 @@ static int init_one_parameter if (q->n > (dd->bufsz - 2*sizeof (uint32_t)) / sizeof (nn_prismtech_eotgroup_tid_t)) { DDS_TRACE("plist/init_one_parameter[pid=PRISMTECH_EOTINFO]: buffer too small (2)\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } if (q->n == 0) q->tids = NULL; @@ -2134,7 +2134,7 @@ static int init_one_parameter if (dd->bufsz < sizeof (dest->reader_favours_ssm)) { DDS_TRACE("plist/init_one_parameter[pid=READER_FAVOURS_SSM]: buffer too small\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -2174,13 +2174,13 @@ static int init_one_parameter bugs & the buffer overflows originate! */ if (pid & PID_UNRECOGNIZED_INCOMPATIBLE_FLAG) { dest->present |= PP_INCOMPATIBLE; - return ERR_INCOMPATIBLE; + return Q_ERR_INCOMPATIBLE; } else if (pid & PID_VENDORSPECIFIC_FLAG) { return 0; } else if (!protocol_version_is_newer (dd->protocol_version) && NN_STRICT_P) { DDS_TRACE("plist/init_one_parameter[pid=%u,mode=STRICT,proto=%u.%u]: undefined paramter id\n", pid, dd->protocol_version.major, dd->protocol_version.minor); - return ERR_INVALID; + return Q_ERR_INVALID; } else { return 0; } @@ -2188,7 +2188,7 @@ static int init_one_parameter assert (0); DDS_TRACE("plist/init_one_parameter: can't happen\n"); - return ERR_INVALID; + return Q_ERR_INVALID; } static void default_resource_limits (nn_resource_limits_qospolicy_t *q) @@ -2404,7 +2404,7 @@ int nn_plist_init_frommsg default: DDS_WARNING ("plist(vendor %u.%u): unknown encoding (%d)\n", src->vendorid.id[0], src->vendorid.id[1], src->encoding); - return ERR_INVALID; + return Q_ERR_INVALID; } nn_plist_init_empty (dest); dest->unalias_needs_bswap = dd.bswap; @@ -2431,7 +2431,7 @@ int nn_plist_init_frommsg if ((res = final_validation (dest, src->protocol_version, src->vendorid)) < 0) { nn_plist_fini (dest); - return ERR_INVALID; + return Q_ERR_INVALID; } else { @@ -2446,14 +2446,14 @@ int nn_plist_init_frommsg DDS_WARNING("plist(vendor %u.%u): parameter length %u out of bounds\n", src->vendorid.id[0], src->vendorid.id[1], length); nn_plist_fini (dest); - return ERR_INVALID; + return Q_ERR_INVALID; } if ((length % 4) != 0) /* DDSI 9.4.2.11 */ { DDS_WARNING("plist(vendor %u.%u): parameter length %u mod 4 != 0\n", src->vendorid.id[0], src->vendorid.id[1], length); nn_plist_fini (dest); - return ERR_INVALID; + return Q_ERR_INVALID; } if (dds_get_log_mask() & DDS_LC_PLIST) @@ -2479,7 +2479,7 @@ int nn_plist_init_frommsg DDS_WARNING("plist(vendor %u.%u): invalid parameter list: sentinel missing\n", src->vendorid.id[0], src->vendorid.id[1]); nn_plist_fini (dest); - return ERR_INVALID; + return Q_ERR_INVALID; } const unsigned char *nn_plist_findparam_native_unchecked (const void *src, nn_parameterid_t pid) diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index d09c89d..bd628f8 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -573,7 +573,7 @@ static int valid_DataFrag (const struct receiver_state *rst, struct nn_rmsg *rms return 1; } -static int add_Gap (struct nn_xmsg *msg, struct writer *wr, struct proxy_reader *prd, seqno_t start, seqno_t base, unsigned numbits, const unsigned *bits) +static int add_Gap (struct nn_xmsg *msg, struct writer *wr, struct proxy_reader *prd, seqno_t start, seqno_t base, uint32_t numbits, const uint32_t *bits) { struct nn_xmsg_marker sm_marker; Gap_t *gap; @@ -614,7 +614,7 @@ static void force_heartbeat_to_peer (struct writer *wr, const struct whc_state * it is as-if a Data submessage had once been sent with that sequence number and it now receives an unsollicited response to a NACK ... */ - unsigned bits = 0; + uint32_t bits = 0; seqno_t seq; if (wr->seq > 0) seq = wr->seq; @@ -708,7 +708,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac nn_count_t *countp; seqno_t gapstart = -1, gapend = -1; unsigned gapnumbits = 0; - unsigned gapbits[256 / 32]; + uint32_t gapbits[256 / 32]; int accelerate_rexmit = 0; int is_pure_ack; int is_pure_nonhist_ack; @@ -1531,7 +1531,7 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N } else { - static unsigned zero = 0; + static uint32_t zero = 0; struct nn_xmsg *m; DDS_TRACE(" msg not available: scheduling Gap\n"); m = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, 0, NN_XMSG_KIND_CONTROL); @@ -1979,7 +1979,7 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st src.bufsz = NN_RDATA_PAYLOAD_OFF (fragchain) - qos_offset; if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH | PP_COHERENT_SET | PP_PRISMTECH_EOTINFO, 0, &src)) < 0) { - if (plist_ret != ERR_INCOMPATIBLE) + if (plist_ret != Q_ERR_INCOMPATIBLE) DDS_WARNING ("data(application, vendor %u.%u): %x:%x:%x:%x #%"PRId64": invalid inline qos\n", src.vendorid.id[0], src.vendorid.id[1], PGUID (pwr->e.guid), sampleinfo->seq); return 0; @@ -2545,7 +2545,7 @@ static void malformed_packet_received if (smsize >= sizeof (AckNack_t)) { const AckNack_t *x = (const AckNack_t *) submsg; - (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%x,%"PRId64",%u}", + (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%"PRIx32",%"PRIx32",%"PRId64",%"PRIu32"}", x->smhdr.submessageId, x->smhdr.flags, x->smhdr.octetsToNextHeader, x->readerId.u, x->writerId.u, fromSN (x->readerSNState.bitmap_base), x->readerSNState.numbits); @@ -2555,7 +2555,7 @@ static void malformed_packet_received if (smsize >= sizeof (Heartbeat_t)) { const Heartbeat_t *x = (const Heartbeat_t *) submsg; - (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%x,%"PRId64",%"PRId64"}", + (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%"PRIx32",%"PRIx32",%"PRId64",%"PRId64"}", x->smhdr.submessageId, x->smhdr.flags, x->smhdr.octetsToNextHeader, x->readerId.u, x->writerId.u, fromSN (x->firstSN), fromSN (x->lastSN)); } @@ -2564,7 +2564,7 @@ static void malformed_packet_received if (smsize >= sizeof (Gap_t)) { const Gap_t *x = (const Gap_t *) submsg; - (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%x,%"PRId64",%"PRId64",%u}", + (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%"PRIx32",%"PRIx32",%"PRId64",%"PRId64",%"PRIu32"}", x->smhdr.submessageId, x->smhdr.flags, x->smhdr.octetsToNextHeader, x->readerId.u, x->writerId.u, fromSN (x->gapStart), fromSN (x->gapList.bitmap_base), x->gapList.numbits); @@ -2574,7 +2574,7 @@ static void malformed_packet_received if (smsize >= sizeof (NackFrag_t)) { const NackFrag_t *x = (const NackFrag_t *) submsg; - (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%x,%"PRId64",%u,%u}", + (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%"PRIx32",%"PRIx32",%"PRId64",%u,%"PRIu32"}", x->smhdr.submessageId, x->smhdr.flags, x->smhdr.octetsToNextHeader, x->readerId.u, x->writerId.u, fromSN (x->writerSN), x->fragmentNumberState.bitmap_base, x->fragmentNumberState.numbits); @@ -2584,7 +2584,7 @@ static void malformed_packet_received if (smsize >= sizeof (HeartbeatFrag_t)) { const HeartbeatFrag_t *x = (const HeartbeatFrag_t *) submsg; - (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%x,%"PRId64",%u}", + (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%"PRIx32",%"PRIx32",%"PRId64",%u}", x->smhdr.submessageId, x->smhdr.flags, x->smhdr.octetsToNextHeader, x->readerId.u, x->writerId.u, fromSN (x->writerSN), x->lastFragmentNum); @@ -2594,7 +2594,7 @@ static void malformed_packet_received if (smsize >= sizeof (Data_t)) { const Data_t *x = (const Data_t *) submsg; - (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%u,%x,%x,%"PRId64"}", + (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%u,%"PRIx32",%"PRIx32",%"PRId64"}", x->x.smhdr.submessageId, x->x.smhdr.flags, x->x.smhdr.octetsToNextHeader, x->x.extraFlags, x->x.octetsToInlineQos, x->x.readerId.u, x->x.writerId.u, fromSN (x->x.writerSN)); @@ -2604,7 +2604,7 @@ static void malformed_packet_received if (smsize >= sizeof (DataFrag_t)) { const DataFrag_t *x = (const DataFrag_t *) submsg; - (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%u,%x,%x,%"PRId64",%u,%u,%u,%u}", + (void) snprintf (tmp + pos, sizeof (tmp) - pos, " {{%x,%x,%u},%x,%u,%"PRIx32",%"PRIx32",%"PRId64",%u,%u,%u,%"PRIu32"}", x->x.smhdr.submessageId, x->x.smhdr.flags, x->x.smhdr.octetsToNextHeader, x->x.extraFlags, x->x.octetsToInlineQos, x->x.readerId.u, x->x.writerId.u, fromSN (x->x.writerSN), diff --git a/src/core/ddsi/src/q_security.c b/src/core/ddsi/src/q_security.c index b6ba901..408c077 100644 --- a/src/core/ddsi/src/q_security.c +++ b/src/core/ddsi/src/q_security.c @@ -1657,7 +1657,7 @@ static os_ssize_t q_security_sendmsg char stbuf[2048], *buf; size_t sz, data_size; uint32_t sz32, data_size32; - ssize_t ret = ERR_UNSPECIFIED; + ssize_t ret = Q_ERR_UNSPECIFIED; PT_InfoContainer_t * securityHeader; unsigned i; diff --git a/src/core/ddsi/src/q_servicelease.c b/src/core/ddsi/src/q_servicelease.c index 4c7fa87..2ab892a 100644 --- a/src/core/ddsi/src/q_servicelease.c +++ b/src/core/ddsi/src/q_servicelease.c @@ -217,7 +217,7 @@ int nn_servicelease_start_renewing (struct nn_servicelease *sl) fail_thread: sl->keepgoing = -1; - return ERR_UNSPECIFIED; + return Q_ERR_UNSPECIFIED; } void nn_servicelease_statechange_barrier (struct nn_servicelease *sl) diff --git a/src/core/ddsi/src/q_sockwaitset.c b/src/core/ddsi/src/q_sockwaitset.c index f0187b1..7d811e7 100644 --- a/src/core/ddsi/src/q_sockwaitset.c +++ b/src/core/ddsi/src/q_sockwaitset.c @@ -831,7 +831,7 @@ void os_sockWaitsetRemove (os_sockWaitset ws, ddsi_tran_conn_t conn) os_sockWaitsetCtx os_sockWaitsetWait (os_sockWaitset ws) { - int n = -1; + int32_t n = -1; unsigned u; int fdmax; fd_set * rdset = NULL; diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c index 4d3fe45..6789407 100644 --- a/src/core/ddsi/src/q_thread.c +++ b/src/core/ddsi/src/q_thread.c @@ -301,7 +301,7 @@ int join_thread (struct thread_state1 *ts1) if (ddsrt_thread_join (ts1->extTid, NULL) == DDS_RETCODE_OK) ret = 0; else - ret = ERR_UNSPECIFIED; + ret = Q_ERR_UNSPECIFIED; assert (vtime_asleep_p (ts1->vtime)); reap_thread_state (ts1, 1); return ret; diff --git a/src/core/ddsi/src/q_time.c b/src/core/ddsi/src/q_time.c index add0d0b..05878b3 100644 --- a/src/core/ddsi/src/q_time.c +++ b/src/core/ddsi/src/q_time.c @@ -51,23 +51,23 @@ nn_etime_t now_et (void) return t; } -static void time_to_sec_usec (int * __restrict sec, int * __restrict usec, int64_t t) +static void time_to_sec_usec (int32_t * __restrict sec, int32_t * __restrict usec, int64_t t) { - *sec = (int) (t / T_SECOND); - *usec = (int) (t % T_SECOND) / 1000; + *sec = (int32_t) (t / T_SECOND); + *usec = (int32_t) (t % T_SECOND) / 1000; } -void mtime_to_sec_usec (int * __restrict sec, int * __restrict usec, nn_mtime_t t) +void mtime_to_sec_usec (int32_t * __restrict sec, int32_t * __restrict usec, nn_mtime_t t) { time_to_sec_usec (sec, usec, t.v); } -void wctime_to_sec_usec (int * __restrict sec, int * __restrict usec, nn_wctime_t t) +void wctime_to_sec_usec (int32_t * __restrict sec, int32_t * __restrict usec, nn_wctime_t t) { time_to_sec_usec (sec, usec, t.v); } -void etime_to_sec_usec (int * __restrict sec, int * __restrict usec, nn_etime_t t) +void etime_to_sec_usec (int32_t * __restrict sec, int32_t * __restrict usec, nn_etime_t t) { time_to_sec_usec (sec, usec, t.v); } diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 85d1874..27abfc7 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -424,7 +424,7 @@ static int create_fragment_message_simple (struct writer *wr, seqno_t seq, struc ASSERT_MUTEX_HELD (&wr->e.lock); if ((*pmsg = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, sizeof (InfoTimestamp_t) + sizeof (Data_t) + expected_inline_qos_size, NN_XMSG_KIND_DATA)) == NULL) - return ERR_OUT_OF_MEMORY; + return Q_ERR_OUT_OF_MEMORY; #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS /* use the partition_id from the writer to select the proper encoder */ @@ -503,13 +503,13 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli an non-existent fragment, which a malicious (or buggy) remote reader can trigger. So we return an error instead of asserting as we used to. */ - return ERR_INVALID; + return Q_ERR_INVALID; } fragging = (config.fragment_size < size); if ((*pmsg = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, sizeof (InfoTimestamp_t) + sizeof (DataFrag_t) + expected_inline_qos_size, xmsg_kind)) == NULL) - return ERR_OUT_OF_MEMORY; + return Q_ERR_OUT_OF_MEMORY; #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS /* use the partition_id from the writer to select the proper encoder */ @@ -522,7 +522,7 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli { nn_xmsg_free (*pmsg); *pmsg = NULL; - return ERR_NO_ADDRESS; + return Q_ERR_NO_ADDRESS; } /* retransmits: latency budget doesn't apply */ } @@ -1050,7 +1050,7 @@ static int write_sample_eot (struct nn_xpack *xp, struct writer *wr, struct nn_p ddsi_serdata_size (serdata), config.max_sample_size, PGUID (wr->e.guid), tname, ttname, ppbuf, tmp < (int) sizeof (ppbuf) ? "" : " (trunc)"); - r = ERR_INVALID_DATA; + r = Q_ERR_INVALID_DATA; goto drop; } @@ -1082,7 +1082,7 @@ static int write_sample_eot (struct nn_xpack *xp, struct writer *wr, struct nn_p if (ores == DDS_RETCODE_TIMEOUT) { ddsrt_mutex_unlock (&wr->e.lock); - r = ERR_TIMEOUT; + r = Q_ERR_TIMEOUT; goto drop; } } diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index 8189c77..0e60a2a 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -521,7 +521,7 @@ int xeventq_start (struct xeventq *evq, const char *name) { ddsrt_free (evqname); } - return (evq->ts == NULL) ? ERR_UNSPECIFIED : 0; + return (evq->ts == NULL) ? Q_ERR_UNSPECIFIED : 0; } void xeventq_stop (struct xeventq *evq) diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 6f6d11d..ec1495d 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -591,7 +591,7 @@ int nn_xmsg_setdstPRD (struct nn_xmsg *m, const struct proxy_reader *prd) else { DDS_WARNING("nn_xmsg_setdstPRD: no address for %x:%x:%x:%x", PGUID (prd->e.guid)); - return ERR_NO_ADDRESS; + return Q_ERR_NO_ADDRESS; } } @@ -604,7 +604,7 @@ int nn_xmsg_setdstPWR (struct nn_xmsg *m, const struct proxy_writer *pwr) return 0; } DDS_WARNING("nn_xmsg_setdstPRD: no address for %x:%x:%x:%x", PGUID (pwr->e.guid)); - return ERR_NO_ADDRESS; + return Q_ERR_NO_ADDRESS; } void nn_xmsg_setdstN (struct nn_xmsg *m, struct addrset *as, struct addrset *as_group) diff --git a/src/core/xtests/rhc_torture.c b/src/core/xtests/rhc_torture.c index 9d66de1..827d04d 100644 --- a/src/core/xtests/rhc_torture.c +++ b/src/core/xtests/rhc_torture.c @@ -265,7 +265,7 @@ static void print_seq (int n, const dds_sample_info_t *iseq, const RhcTypes_T *m char buf[64]; assert(si->instance_handle); assert(si->publication_handle); - printf ("[%2d] %c%c%c %16"PRIx64" %16"PRIx64" %4d %4d %2d %2d %2d %2"PRId32, + printf ("[%2d] %c%c%c %16"PRIx64" %16"PRIx64" %4"PRIu32" %4"PRIu32" %2"PRIu32" %2"PRIu32" %2"PRIu32" %2"PRId32, i, si2ss(si), si2vs(si), si2is(si), si->instance_handle, si->publication_handle, si->disposed_generation_count, si->no_writers_generation_count, diff --git a/src/ddsrt/include/dds/ddsrt/misc.h b/src/ddsrt/include/dds/ddsrt/misc.h index f01b397..1d165b1 100644 --- a/src/ddsrt/include/dds/ddsrt/misc.h +++ b/src/ddsrt/include/dds/ddsrt/misc.h @@ -20,7 +20,7 @@ extern "C" { #if defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402 # define DDSRT_GNUC_STR(s) #s -# define DDSRT_GNUC_JOINSTR(x,y) DDSRT_GNUC_DIAG_STR(x ## y) +# define DDSRT_GNUC_JOINSTR(x,y) DDSRT_GNUC_STR(x ## y) # define DDSRT_GNUC_DO_PRAGMA(x) _Pragma (#x) # define DDSRT_GNUC_PRAGMA(x) DDSRT_GNUC_DO_PRAGMA(GCC diagnostic x) # if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406 diff --git a/src/ddsrt/include/dds/ddsrt/sockets.h b/src/ddsrt/include/dds/ddsrt/sockets.h index 4d25387..645af42 100644 --- a/src/ddsrt/include/dds/ddsrt/sockets.h +++ b/src/ddsrt/include/dds/ddsrt/sockets.h @@ -8,12 +8,14 @@ #include "dds/ddsrt/attributes.h" #include "dds/ddsrt/retcode.h" #include "dds/ddsrt/time.h" -#if !defined(_WIN32) -#include "dds/ddsrt/sockets/posix.h" -#else +#if _WIN32 #include "dds/ddsrt/sockets/windows.h" +#else +#include "dds/ddsrt/sockets/posix.h" #endif +#define INET_ADDRSTRLEN_EXTENDED (INET_ADDRSTRLEN + 6) /* ":12345" */ + #if DDSRT_HAVE_IPV6 #define INET6_ADDRSTRLEN_EXTENDED (INET6_ADDRSTRLEN + 8) /* "[]:12345" */ extern const struct in6_addr ddsrt_in6addr_any; diff --git a/src/examples/helloworld/publisher.c b/src/examples/helloworld/publisher.c index eeb2d54..2dec98e 100644 --- a/src/examples/helloworld/publisher.c +++ b/src/examples/helloworld/publisher.c @@ -52,7 +52,7 @@ int main (int argc, char ** argv) msg.message = "Hello World"; printf ("=== [Publisher] Writing : "); - printf ("Message (%d, %s)\n", msg.userID, msg.message); + printf ("Message (%"PRId32", %s)\n", msg.userID, msg.message); fflush (stdout); rc = dds_write (writer, &msg); diff --git a/src/examples/helloworld/subscriber.c b/src/examples/helloworld/subscriber.c index f35f80a..aee6208 100644 --- a/src/examples/helloworld/subscriber.c +++ b/src/examples/helloworld/subscriber.c @@ -61,7 +61,7 @@ int main (int argc, char ** argv) /* Print Message. */ msg = (HelloWorldData_Msg*) samples[0]; printf ("=== [Subscriber] Received : "); - printf ("Message (%d, %s)\n", msg->userID, msg->message); + printf ("Message (%"PRId32", %s)\n", msg->userID, msg->message); fflush (stdout); break; } diff --git a/src/examples/throughput/publisher.c b/src/examples/throughput/publisher.c index 8fd49d7..5109d6b 100644 --- a/src/examples/throughput/publisher.c +++ b/src/examples/throughput/publisher.c @@ -126,7 +126,7 @@ static int parse_args( *partitionName = argv[5]; /* The name of the partition */ } - printf ("payloadSize: %u bytes burstInterval: %u ms burstSize: %u timeOut: %u seconds partitionName: %s\n", + printf ("payloadSize: %"PRIu32" bytes burstInterval: %u ms burstSize: %"PRId32" timeOut: %u seconds partitionName: %s\n", *payloadSize, *burstInterval, *burstSize, *timeOut, *partitionName); fflush (stdout); diff --git a/src/tools/ddsls/ddsls.c b/src/tools/ddsls/ddsls.c index bd53700..fed04c4 100644 --- a/src/tools/ddsls/ddsls.c +++ b/src/tools/ddsls/ddsls.c @@ -150,17 +150,17 @@ void qp_resource_limits_1 (FILE *fp, int32_t max_samples, int32_t max_instances, if (max_samples == DDS_LENGTH_UNLIMITED) fprintf (fp, "unlimited"); else - fprintf (fp, "%d", max_samples); + fprintf (fp, "%"PRId32, max_samples); fprintf (fp, ", max_instances = "); if (max_instances == DDS_LENGTH_UNLIMITED) fprintf (fp, "unlimited"); else - fprintf (fp, "%d", max_instances); + fprintf (fp, "%"PRId32, max_instances); fprintf (fp, ", max_samples_per_instance = "); if (max_samples_per_instance == DDS_LENGTH_UNLIMITED) fprintf (fp, "unlimited\n"); else - fprintf (fp, "%d\n", max_samples_per_instance); + fprintf (fp, "%"PRId32"\n", max_samples_per_instance); } void qp_resource_limits (const dds_qos_t *q, FILE *fp) diff --git a/src/tools/pubsub/common.c b/src/tools/pubsub/common.c index a24abaf..43322f4 100644 --- a/src/tools/pubsub/common.c +++ b/src/tools/pubsub/common.c @@ -705,7 +705,7 @@ static int one_resource_limit(int32_t *val, const char **arg) { *val = DDS_LENGTH_UNLIMITED; (*arg) += 3; return 1; - } else if (sscanf(*arg, "%d%n", val, &pos) == 1) { + } else if (sscanf(*arg, "%"PRId32"%n", val, &pos) == 1) { (*arg) += pos; return 1; } else { @@ -957,7 +957,7 @@ bool dds_err_check (dds_return_t err, unsigned flags, const char * where) if (flags & (DDS_CHECK_REPORT | DDS_CHECK_FAIL)) { char msg[DDS_ERR_MSG_MAX]; - (void) snprintf (msg, DDS_ERR_MSG_MAX, "Error %d:M%d:%s", dds_err_file_id(err), dds_err_line(err), dds_err_str(err)); + (void) snprintf (msg, DDS_ERR_MSG_MAX, "Error %"PRId32":M%"PRId32":%s", dds_err_file_id(err), dds_err_line(err), dds_err_str(err)); if (flags & DDS_CHECK_REPORT) { printf ("%s: %s\n", where, msg); diff --git a/src/tools/pubsub/pubsub.c b/src/tools/pubsub/pubsub.c index cf7cde2..e775f10 100644 --- a/src/tools/pubsub/pubsub.c +++ b/src/tools/pubsub/pubsub.c @@ -45,7 +45,7 @@ //#define NUMSTR "0123456789" //#define HOSTNAMESTR "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-." NUMSTR -typedef int (*write_oper_t) (dds_entity_t wr, const void *d, const dds_time_t ts); +typedef dds_return_t (*write_oper_t) (dds_entity_t wr, const void *d, const dds_time_t ts); enum topicsel { UNSPEC, KS, K32, K64, K128, K256, OU, ARB }; enum readermode { MODE_PRINT, MODE_CHECK, MODE_ZEROLOAD, MODE_DUMP, MODE_NONE }; @@ -860,11 +860,11 @@ static void print_K(dds_time_t *tstart, dds_time_t tnow, dds_entity_t rd, const print_sampleinfo(tstart, tnow, si, tag); if (si->valid_data) { if(printmode == TGPM_MULTILINE) { - printf ("{\n%*.*s.seq = %u,\n%*.*s.keyval = %d }\n", 4, 4, "", seq, 4, 4, "", keyval); + printf ("{\n%*.*s.seq = %"PRIu32",\n%*.*s.keyval = %"PRId32" }\n", 4, 4, "", seq, 4, 4, "", keyval); } else if(printmode == TGPM_DENSE) { - printf ("{%u,%d}\n", seq, keyval); + printf ("{%"PRIu32",%"PRId32"}\n", seq, keyval); } else { - printf ("{ .seq = %u, .keyval = %d }\n", seq, keyval); + printf ("{ .seq = %"PRIu32", .keyval = %"PRId32" }\n", seq, keyval); } } else { /* May not look at mseq->_buffer[i] but want the key value @@ -877,11 +877,11 @@ static void print_K(dds_time_t *tstart, dds_time_t tnow, dds_entity_t rd, const int32_t d_key; if ((result = getkeyval(rd, &d_key, si->instance_handle)) == DDS_RETCODE_OK) { if(printmode == TGPM_MULTILINE) { - printf ("{\n%*.*s.seq = NA,\n%*.*s.keyval = %d }\n", 4, 4, "", 4, 4, "", keyval); + printf ("{\n%*.*s.seq = NA,\n%*.*s.keyval = %"PRId32" }\n", 4, 4, "", 4, 4, "", keyval); } else if(printmode == TGPM_DENSE) { - printf ("{NA,%d}\n", keyval); + printf ("{NA,%"PRId32"}\n", keyval); } else { - printf ("{ .seq = NA, .keyval = %d }\n", keyval); + printf ("{ .seq = NA, .keyval = %"PRId32" }\n", keyval); } } else printf ("get_key_value: error (%s)\n", dds_err_str(result)); @@ -930,11 +930,11 @@ static void print_seq_OU(dds_time_t *tstart, dds_time_t tnow, dds_entity_t rd __ print_sampleinfo(tstart, tnow, si, tag); if (si->valid_data) { if(printmode == TGPM_MULTILINE) { - printf ("{\n%*.*s.seq = %u }\n", 4, 4, "", mseq[i]->seq); + printf ("{\n%*.*s.seq = %"PRIu32" }\n", 4, 4, "", mseq[i]->seq); } else if(printmode == TGPM_DENSE) { - printf ("{%u}\n", mseq[i]->seq); + printf ("{%"PRIu32"}\n", mseq[i]->seq); } else { - printf ("{ .seq = %u }\n", mseq[i]->seq); + printf ("{ .seq = %"PRIu32" }\n", mseq[i]->seq); } } else { printf ("NA\n"); @@ -1109,7 +1109,7 @@ static void wr_on_publication_matched(dds_entity_t wr __attribute__((unused)), c } } -static int register_instance_wrapper(dds_entity_t wr, const void *d, const dds_time_t tstamp) { +static dds_return_t register_instance_wrapper(dds_entity_t wr, const void *d, const dds_time_t tstamp) { dds_instance_handle_t handle; (void)tstamp; return dds_register_instance(wr, &handle, d); @@ -1795,7 +1795,7 @@ static uint32_t subthread(void *vspec) { rc = dds_get_subscription_matched_status(rd, &status); error_report(rc, "dds_get_subscription_matched_status failed"); if (rc == DDS_RETCODE_OK) { - printf("[pre-read: subscription-matched: total=(%"PRIu32" change %d) current=(%"PRIu32" change %d) handle=%"PRIu64"]\n", + printf("[pre-read: subscription-matched: total=(%"PRIu32" change %"PRId32") current=(%"PRIu32" change %"PRId32") handle=%"PRIu64"]\n", status.total_count, status.total_count_change, status.current_count, status.current_count_change, diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 00bc5ac..4f44a70 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -25,6 +25,10 @@ generate_export_header( # util must NOT link with ddsrt to avoid duplicate symbols in ddsc! # ddsrt include directories are required though. +target_compile_definitions( + util + PUBLIC + $>) target_include_directories( util PUBLIC From c38d9761f31ce82e1d18e5cb88a4fba07185a56d Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Wed, 10 Apr 2019 14:23:33 +0200 Subject: [PATCH 010/238] Move md5 from ddsi to ddsrt Signed-off-by: Jeroen Koekkoek --- src/core/ddsc/src/dds_key.c | 11 +++-- src/core/ddsc/src/dds_serdata_builtintopic.c | 2 +- src/core/ddsc/src/dds_sertopic_builtintopic.c | 2 +- src/core/ddsc/src/dds_stream.c | 14 +++--- src/core/ddsi/CMakeLists.txt | 2 - src/core/ddsi/src/ddsi_serdata.c | 2 +- src/core/ddsi/src/ddsi_serdata_default.c | 14 +++--- src/core/ddsi/src/ddsi_sertopic.c | 15 +++--- src/core/ddsi/src/ddsi_sertopic_default.c | 2 +- src/core/ddsi/src/q_ddsi_discovery.c | 3 +- src/core/ddsi/src/q_init.c | 2 +- src/core/ddsi/src/q_misc.c | 3 +- src/core/ddsi/src/q_nwif.c | 13 ++--- src/core/ddsi/src/q_receive.c | 5 +- src/ddsrt/CMakeLists.txt | 2 +- .../q_md5.h => ddsrt/include/dds/ddsrt/md5.h} | 26 +++++----- .../ddsi/src/q_md5.c => ddsrt/src/md5.c} | 47 ++++++++++--------- 17 files changed, 84 insertions(+), 81 deletions(-) rename src/{core/ddsi/include/dds/ddsi/q_md5.h => ddsrt/include/dds/ddsrt/md5.h} (83%) rename src/{core/ddsi/src/q_md5.c => ddsrt/src/md5.c} (91%) diff --git a/src/core/ddsc/src/dds_key.c b/src/core/ddsc/src/dds_key.c index d0ab249..b919c85 100644 --- a/src/core/ddsc/src/dds_key.c +++ b/src/core/ddsc/src/dds_key.c @@ -11,11 +11,12 @@ */ #include #include + +#include "dds/ddsrt/md5.h" #include "dds__key.h" #include "dds__stream.h" #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/q_bswap.h" -#include "dds/ddsi/q_md5.h" #ifndef NDEBUG static bool keyhash_is_reset(const dds_key_hash_t *kh) @@ -112,14 +113,14 @@ void dds_key_gen (const dds_topic_descriptor_t * const desc, dds_key_hash_t * kh else { dds_stream_t os; - md5_state_t md5st; + ddsrt_md5_state_t md5st; kh->m_iskey = 0; dds_stream_init(&os, 64); os.m_endian = 0; dds_key_gen_stream (desc, &os, sample); - md5_init (&md5st); - md5_append (&md5st, os.m_buffer.p8, os.m_index); - md5_finish (&md5st, (unsigned char *) kh->m_hash); + ddsrt_md5_init (&md5st); + ddsrt_md5_append (&md5st, os.m_buffer.p8, os.m_index); + ddsrt_md5_finish (&md5st, (unsigned char *) kh->m_hash); dds_stream_fini (&os); } } diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index 4d45df5..b62d405 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -15,7 +15,7 @@ #include #include "dds/ddsrt/heap.h" -#include "dds/ddsi/q_md5.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" diff --git a/src/core/ddsc/src/dds_sertopic_builtintopic.c b/src/core/ddsc/src/dds_sertopic_builtintopic.c index 87bfe0d..05c9544 100644 --- a/src/core/ddsc/src/dds_sertopic_builtintopic.c +++ b/src/core/ddsc/src/dds_sertopic_builtintopic.c @@ -16,7 +16,7 @@ #include "dds/dds.h" #include "dds/ddsrt/heap.h" -#include "dds/ddsi/q_md5.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" diff --git a/src/core/ddsc/src/dds_stream.c b/src/core/ddsc/src/dds_stream.c index 2fbee03..9d7505c 100644 --- a/src/core/ddsc/src/dds_stream.c +++ b/src/core/ddsc/src/dds_stream.c @@ -11,19 +11,19 @@ */ #include #include + +#include "dds/ddsrt/endian.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds__stream.h" #include "dds__key.h" #include "dds__alloc.h" -#include "dds/ddsi/q_md5.h" -#include "dds/ddsrt/endian.h" //#define OP_DEBUG_READ 1 //#define OP_DEBUG_WRITE 1 //#define OP_DEBUG_KEY 1 - #if defined OP_DEBUG_WRITE || defined OP_DEBUG_READ || defined OP_DEBUG_KEY static const char * stream_op_type[11] = { @@ -1612,14 +1612,14 @@ void dds_stream_read_keyhash else { dds_stream_t os; - md5_state_t md5st; + ddsrt_md5_state_t md5st; kh->m_iskey = 0; dds_stream_init (&os, 0); os.m_endian = 0; dds_stream_extract_key (is, &os, desc->m_ops, just_key); - md5_init (&md5st); - md5_append (&md5st, os.m_buffer.p8, os.m_index); - md5_finish (&md5st, (unsigned char *) kh->m_hash); + ddsrt_md5_init (&md5st); + ddsrt_md5_append (&md5st, os.m_buffer.p8, os.m_index); + ddsrt_md5_finish (&md5st, (unsigned char *) kh->m_hash); dds_stream_fini (&os); } } diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 29725a1..8821665 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -39,7 +39,6 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" q_init.c q_lat_estim.c q_lease.c - q_md5.c q_misc.c q_nwif.c q_pcap.c @@ -97,7 +96,6 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" q_lat_estim.h q_lease.h q_log.h - q_md5.h q_misc.h q_nwif.h q_pcap.h diff --git a/src/core/ddsi/src/ddsi_serdata.c b/src/core/ddsi/src/ddsi_serdata.c index 524241c..140c049 100644 --- a/src/core/ddsi/src/ddsi_serdata.c +++ b/src/core/ddsi/src/ddsi_serdata.c @@ -14,7 +14,7 @@ #include #include -#include "dds/ddsi/q_md5.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index 9e938a8..c7c2cf9 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -16,7 +16,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" -#include "dds/ddsi/q_md5.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" @@ -377,16 +377,16 @@ static struct ddsi_serdata *serdata_default_from_sample_plist (const struct ddsi const char *topic_name = (const char *) (rawkey + sizeof(uint32_t)); uint32_t topic_name_sz; uint32_t topic_name_sz_BE; - md5_state_t md5st; - md5_byte_t digest[16]; + ddsrt_md5_state_t md5st; + ddsrt_md5_byte_t digest[16]; topic_name_sz = (uint32_t) strlen (topic_name) + 1; topic_name_sz_BE = toBE4u (topic_name_sz); d->keyhash.m_set = 1; d->keyhash.m_iskey = 0; - md5_init (&md5st); - md5_append (&md5st, (const md5_byte_t *) &topic_name_sz_BE, sizeof (topic_name_sz_BE)); - md5_append (&md5st, (const md5_byte_t *) topic_name, topic_name_sz); - md5_finish (&md5st, digest); + ddsrt_md5_init (&md5st); + ddsrt_md5_append (&md5st, (const ddsrt_md5_byte_t *) &topic_name_sz_BE, sizeof (topic_name_sz_BE)); + ddsrt_md5_append (&md5st, (const ddsrt_md5_byte_t *) topic_name, topic_name_sz); + ddsrt_md5_finish (&md5st, digest); memcpy (d->keyhash.m_hash, digest, 16); #ifndef NDEBUG keysize = sizeof (uint32_t) + topic_name_sz; diff --git a/src/core/ddsi/src/ddsi_sertopic.c b/src/core/ddsi/src/ddsi_sertopic.c index be68930..c4971b2 100644 --- a/src/core/ddsi/src/ddsi_sertopic.c +++ b/src/core/ddsi/src/ddsi_sertopic.c @@ -15,13 +15,12 @@ #include #include "dds/ddsrt/heap.h" -#include "dds/ddsi/q_md5.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" #include "dds/ddsi/ddsi_sertopic.h" #include "dds/ddsi/ddsi_serdata.h" -#include "dds/ddsi/q_md5.h" struct ddsi_sertopic *ddsi_sertopic_ref (const struct ddsi_sertopic *sertopic_const) { @@ -48,13 +47,13 @@ void ddsi_sertopic_unref (struct ddsi_sertopic *sertopic) uint32_t ddsi_sertopic_compute_serdata_basehash (const struct ddsi_serdata_ops *ops) { - md5_state_t md5st; - md5_byte_t digest[16]; + ddsrt_md5_state_t md5st; + ddsrt_md5_byte_t digest[16]; uint32_t res; - md5_init (&md5st); - md5_append (&md5st, (const md5_byte_t *) &ops, sizeof (ops)); - md5_append (&md5st, (const md5_byte_t *) ops, sizeof (*ops)); - md5_finish (&md5st, digest); + ddsrt_md5_init (&md5st); + ddsrt_md5_append (&md5st, (const ddsrt_md5_byte_t *) &ops, sizeof (ops)); + ddsrt_md5_append (&md5st, (const ddsrt_md5_byte_t *) ops, sizeof (*ops)); + ddsrt_md5_finish (&md5st, digest); memcpy (&res, digest, sizeof (res)); return res; } diff --git a/src/core/ddsi/src/ddsi_sertopic_default.c b/src/core/ddsi/src/ddsi_sertopic_default.c index be90044..3fff736 100644 --- a/src/core/ddsi/src/ddsi_sertopic_default.c +++ b/src/core/ddsi/src/ddsi_sertopic_default.c @@ -14,7 +14,7 @@ #include #include -#include "dds/ddsi/q_md5.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 3f5a4b6..be434dd 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -18,6 +18,7 @@ #include "dds/version.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsrt/sync.h" #include "dds/util/ut_avl.h" #include "dds/ddsi/q_protocol.h" @@ -30,6 +31,7 @@ #include "dds/ddsi/q_xevent.h" #include "dds/ddsi/q_addrset.h" #include "dds/ddsi/q_ddsi_discovery.h" + #include "dds/ddsi/q_radmin.h" #include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_entity.h" @@ -40,7 +42,6 @@ #include "dds/ddsi/q_lease.h" #include "dds/ddsi/q_error.h" #include "dds/ddsi/ddsi_serdata_default.h" -#include "dds/ddsi/q_md5.h" #include "dds/ddsi/q_feature_check.h" static int get_locator (nn_locator_t *loc, const nn_locators_t *locs, int uc_same_subnet) diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 97ae856..9fddd09 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -13,6 +13,7 @@ #include #include "dds/ddsrt/heap.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsrt/process.h" #include "dds/ddsrt/time.h" #include "dds/ddsrt/string.h" @@ -21,7 +22,6 @@ #include "dds/util/ut_avl.h" #include "dds/util/ut_thread_pool.h" -#include "dds/ddsi/q_md5.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_misc.h" diff --git a/src/core/ddsi/src/q_misc.c b/src/core/ddsi/src/q_misc.c index 3c97d19..8569c01 100644 --- a/src/core/ddsi/src/q_misc.c +++ b/src/core/ddsi/src/q_misc.c @@ -12,8 +12,9 @@ #include #include "dds/ddsi/q_misc.h" + +#include "dds/ddsrt/md5.h" #include "dds/ddsi/q_bswap.h" -#include "dds/ddsi/q_md5.h" extern inline seqno_t fromSN (const nn_sequence_number_t sn); extern inline nn_sequence_number_t toSN (seqno_t n); diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index 66c49bf..c013080 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -17,15 +17,16 @@ #include "dds/ddsrt/ifaddrs.h" #include "dds/ddsrt/heap.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/sockets.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_nwif.h" + #include "dds/ddsi/q_globals.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_unused.h" -#include "dds/ddsi/q_md5.h" #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_addrset.h" /* unspec locator */ #include "dds/ddsi/q_feature_check.h" @@ -45,11 +46,11 @@ unsigned locator_to_hopefully_unique_uint32 (const nn_locator_t *src) else { #if DDSRT_HAVE_IPV6 - md5_state_t st; - md5_byte_t digest[16]; - md5_init (&st); - md5_append (&st, (const md5_byte_t *) ((const struct sockaddr_in6 *) src)->sin6_addr.s6_addr, 16); - md5_finish (&st, digest); + ddsrt_md5_state_t st; + ddsrt_md5_byte_t digest[16]; + ddsrt_md5_init (&st); + ddsrt_md5_append (&st, (const ddsrt_md5_byte_t *) ((const struct sockaddr_in6 *) src)->sin6_addr.s6_addr, 16); + ddsrt_md5_finish (&st, digest); memcpy (&id, digest, sizeof (id)); #else DDS_FATAL("IPv6 unavailable\n"); diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index bd628f8..f463392 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -15,11 +15,11 @@ #include #include "dds/ddsrt/heap.h" +#include "dds/ddsrt/log.h" +#include "dds/ddsrt/md5.h" #include "dds/ddsrt/sync.h" #include "dds/ddsrt/string.h" -#include "dds/ddsrt/log.h" -#include "dds/ddsi/q_md5.h" #include "dds/util/ut_avl.h" #include "dds__stream.h" #include "dds/ddsi/q_protocol.h" @@ -44,6 +44,7 @@ #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_xmsg.h" #include "dds/ddsi/q_receive.h" + #include "dds/ddsi/q_transmit.h" #include "dds/ddsi/q_globals.h" #include "dds/ddsi/q_static_assert.h" diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index e8b62a6..5179742 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -89,7 +89,7 @@ list(APPEND sources # network stack. In order to mix-and-match various compilers, architectures, # operating systems, etc input from the build system is required. foreach(feature atomics cdtors environ heap ifaddrs random rusage - sockets string sync threads time) + sockets string sync threads time md5) if(EXISTS "${include_path}/dds/ddsrt/${feature}.h") list(APPEND headers "${include_path}/dds/ddsrt/${feature}.h") file(GLOB diff --git a/src/core/ddsi/include/dds/ddsi/q_md5.h b/src/ddsrt/include/dds/ddsrt/md5.h similarity index 83% rename from src/core/ddsi/include/dds/ddsi/q_md5.h rename to src/ddsrt/include/dds/ddsrt/md5.h index e040de0..4777d04 100644 --- a/src/core/ddsi/include/dds/ddsi/q_md5.h +++ b/src/ddsrt/include/dds/ddsrt/md5.h @@ -59,8 +59,8 @@ 1999-05-03 lpd Original version. */ -#ifndef md5_INCLUDED -# define md5_INCLUDED +#ifndef DDSRT_MD5_H +#define DDSRT_MD5_H #include @@ -74,15 +74,15 @@ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. */ -typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ +typedef unsigned char ddsrt_md5_byte_t; /* 8-bit byte */ +typedef unsigned int ddsrt_md5_word_t; /* 32-bit word */ /* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s { - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ -} md5_state_t; +typedef struct ddsrt_md5_state_s { + ddsrt_md5_word_t count[2]; /* message length in bits, lsw first */ + ddsrt_md5_word_t abcd[4]; /* digest buffer */ + ddsrt_md5_byte_t buf[64]; /* accumulate block */ +} ddsrt_md5_state_t; #ifdef __cplusplus extern "C" @@ -90,16 +90,16 @@ extern "C" #endif /* Initialize the algorithm. */ -void md5_init(md5_state_t *pms); +void ddsrt_md5_init(ddsrt_md5_state_t *pms); /* Append a string to the message. */ -void md5_append(md5_state_t *pms, const md5_byte_t *data, unsigned nbytes); +void ddsrt_md5_append(ddsrt_md5_state_t *pms, const ddsrt_md5_byte_t *data, unsigned nbytes); /* Finish the message and return the digest. */ -void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); +void ddsrt_md5_finish(ddsrt_md5_state_t *pms, ddsrt_md5_byte_t digest[16]); #ifdef __cplusplus } /* end extern "C" */ #endif -#endif /* md5_INCLUDED */ +#endif /* DDSRT_MD5_H */ diff --git a/src/core/ddsi/src/q_md5.c b/src/ddsrt/src/md5.c similarity index 91% rename from src/core/ddsi/src/q_md5.c rename to src/ddsrt/src/md5.c index 1a041c2..3116749 100644 --- a/src/core/ddsi/src/q_md5.c +++ b/src/ddsrt/src/md5.c @@ -63,9 +63,10 @@ 1999-05-03 lpd Original version. */ -#include "dds/ddsi/q_md5.h" #include + #include "dds/ddsrt/endian.h" /* big or little endianness */ +#include "dds/ddsrt/md5.h" /* Byte order stuff hacked to use OSPL's macros */ #undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ @@ -77,7 +78,7 @@ # error "DDSRT_ENDIAN not defined" #endif -#define T_MASK ((md5_word_t)~0) +#define T_MASK ((ddsrt_md5_word_t)~0) #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) #define T3 0x242070db @@ -145,19 +146,19 @@ static void -md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) +md5_process(ddsrt_md5_state_t *pms, const ddsrt_md5_byte_t *data /*[64]*/) { - md5_word_t + ddsrt_md5_word_t a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2], d = pms->abcd[3]; - md5_word_t t; + ddsrt_md5_word_t t; #if BYTE_ORDER > 0 /* Define storage only for big-endian CPUs. */ - md5_word_t X[16]; + ddsrt_md5_word_t X[16]; #else /* Define storage for little-endian or both types of CPUs. */ - md5_word_t xbuf[16]; - const md5_word_t *X; + ddsrt_md5_word_t xbuf[16]; + const ddsrt_md5_word_t *X; #endif { @@ -169,7 +170,7 @@ md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) */ static const int w = 1; - if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ + if (*((const ddsrt_md5_byte_t *)&w)) /* dynamic little-endian */ #endif #if BYTE_ORDER <= 0 /* little-endian */ { @@ -177,9 +178,9 @@ md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) * On little-endian machines, we can process properly aligned * data without copying it. */ - if (!((data - (const md5_byte_t *)0) & 3)) { + if (!((data - (const ddsrt_md5_byte_t *)0) & 3)) { /* data are properly aligned */ - X = (const md5_word_t *)data; + X = (const ddsrt_md5_word_t *)data; } else { /* not aligned */ memcpy(xbuf, data, 64); @@ -196,7 +197,7 @@ md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) * On big-endian machines, we must arrange the bytes in the * right order. */ - const md5_byte_t *xp = data; + const ddsrt_md5_byte_t *xp = data; int i; # if BYTE_ORDER == 0 @@ -326,7 +327,7 @@ md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) } void -md5_init(md5_state_t *pms) +ddsrt_md5_init(ddsrt_md5_state_t *pms) { pms->count[0] = pms->count[1] = 0; pms->abcd[0] = 0x67452301; @@ -336,12 +337,12 @@ md5_init(md5_state_t *pms) } void -md5_append(md5_state_t *pms, const md5_byte_t *data, unsigned nbytes) +ddsrt_md5_append(ddsrt_md5_state_t *pms, const ddsrt_md5_byte_t *data, unsigned nbytes) { - const md5_byte_t *p = data; + const ddsrt_md5_byte_t *p = data; unsigned left = nbytes; unsigned offset = (pms->count[0] >> 3) & 63; - md5_word_t nbits = (md5_word_t)(nbytes << 3); + ddsrt_md5_word_t nbits = (ddsrt_md5_word_t)(nbytes << 3); if (nbytes == 0) return; @@ -374,24 +375,24 @@ md5_append(md5_state_t *pms, const md5_byte_t *data, unsigned nbytes) } void -md5_finish(md5_state_t *pms, md5_byte_t digest[16]) +ddsrt_md5_finish(ddsrt_md5_state_t *pms, ddsrt_md5_byte_t digest[16]) { - static const md5_byte_t pad[64] = { + static const ddsrt_md5_byte_t pad[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - md5_byte_t data[8]; + ddsrt_md5_byte_t data[8]; int i; /* Save the length before padding. */ for (i = 0; i < 8; ++i) - data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + data[i] = (ddsrt_md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); /* Pad to 56 bytes mod 64. */ - md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + ddsrt_md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); /* Append the length. */ - md5_append(pms, data, 8); + ddsrt_md5_append(pms, data, 8); for (i = 0; i < 16; ++i) - digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); + digest[i] = (ddsrt_md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); } From d4f8456479d7979042b3e2500bda4e2aeccc3c3f Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 9 Apr 2019 21:12:46 +0200 Subject: [PATCH 011/238] ignore data until a heartbeat is received (#146) When data arrives before a heartbeat has been received, it is impossible to know whether this is a new "live" sample or a retransmit, and for this reason the requesting of historical data is delayed until a heartbeat arrives that informs the readers of the range of sequence numbers to request as historical data. However, by this time, and without this new condition in place, the reader may have already received some data directly, and may consequently request some data twice. That's not right. Requiring a heartbeat to have been received before delivering the data avoids this problem, but potentially delays receiving data after a new writer/reader pair has been matched. The delay caused by a full handshake at that point seems less bad that the odd case of stuttering where that isn't expected. There are almost certainly some tricks possible to avoid that delay in the common cases, but there are more important things to do ... Best-effort readers on a reliable proxy writer are a bit special: if there are only best-effort readers, there is no guarantee that a heartbeat will be received, and so the condition does not apply. This commit attempts to deal with that by only requiring a heartbeat if some reliable readers exist, but that doesn't allow a smooth transition from "only best-effort readers" to "some reliable readers". One could moreover argue that this condition should not be imposed on volatile readers (at worst you get a little bit of data from before the match), but equally well that it should (there's no guarantee that no sample would be skipped in the case of a keep-all writer, if the first sample happened to be a retransmit). Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_entity.c | 5 +++-- src/core/ddsi/src/q_receive.c | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index d83f225..0b0c8fa 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -4111,12 +4111,13 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, } else { pwr->deliver_synchronously = 0; } - pwr->have_seen_heartbeat = 0; + /* Pretend we have seen a heartbeat if the proxy writer is a best-effort one */ + isreliable = (pwr->c.xqos->reliability.kind != NN_BEST_EFFORT_RELIABILITY_QOS); + pwr->have_seen_heartbeat = !isreliable; pwr->local_matching_inprogress = 1; #ifdef DDSI_INCLUDE_SSM pwr->supports_ssm = (addrset_contains_ssm (as) && config.allowMulticast & AMC_SSM) ? 1 : 0; #endif - isreliable = (pwr->c.xqos->reliability.kind != NN_BEST_EFFORT_RELIABILITY_QOS); /* Only assert PP lease on receipt of data if enabled (duh) and the proxy participant is a "real" participant, rather than the thing we use for endpoints discovered via the DS */ diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index f463392..8671a5b 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -1745,6 +1745,13 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm } DDS_TRACE("%x:%x:%x:%x -> %x:%x:%x:%x", PGUID (src), PGUID (dst)); + if (!pwr->have_seen_heartbeat && pwr->n_reliable_readers > 0) + { + DDS_TRACE(": no heartbeat seen yet", PGUID (pwr->e.guid), PGUID (dst)); + ddsrt_mutex_unlock (&pwr->e.lock); + return 1; + } + /* Notify reordering in proxy writer & and the addressed reader (if it is out-of-sync, &c.), while delivering samples that become available because preceding ones are now known to be missing. */ @@ -2173,6 +2180,25 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct /* Shouldn't lock the full writer, but will do so for now */ ddsrt_mutex_lock (&pwr->e.lock); + + /* Don't accept data when reliable readers exist and we haven't yet seen + a heartbeat telling us what the "current" sequence number of the writer + is. If no reliable readers are present, we can't request a heartbeat and + therefore must not require one. + + This should be fine except for the one case where one transitions from + having only best-effort readers to also having a reliable reader (in + the same process): in that case, the requirement that a heartbeat has + been seen could potentially result in a disruption of the data flow to + the best-effort readers. That state should last only for a very short + time, but it is rather inelegant. */ + if (!pwr->have_seen_heartbeat && pwr->n_reliable_readers > 0) + { + ddsrt_mutex_unlock (&pwr->e.lock); + DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x: no heartbeat seen yet", PGUID (pwr->e.guid), PGUID (dst)); + return; + } + if (ut_avlIsEmpty (&pwr->readers) || pwr->local_matching_inprogress) { ddsrt_mutex_unlock (&pwr->e.lock); From 58f21af36e8f5593a633f17cafdd35082e8f94dc Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 10 Apr 2019 11:00:10 +0200 Subject: [PATCH 012/238] set DATA_AVAILABLE when deleting writer (#148) Deleting a writer causes unregisters (and possibly disposes) in the rest of the network, and these updates to the instances should trigger DATA_AVAILABLE. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_rhc.c | 17 ++++- src/core/ddsc/tests/listener.c | 110 ++++++++++++++++++++++++++++++++- 2 files changed, 124 insertions(+), 3 deletions(-) diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index b427df3..30dc4f3 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -1523,6 +1523,7 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ built-in topics and in get_instance_handle, and one used internally for tracking registrations and unregistrations. */ bool trigger_waitsets = false; + bool notify_data_available = false; struct rhc_instance *inst; struct ut_hhIter iter; const uint64_t wr_iid = pwr_info->iid; @@ -1568,16 +1569,28 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ TRACE ("\n"); + notify_data_available = true; if (trigger_info_differs (&pre, &post, &trig_qc) && update_conditions_locked (rhc, true, &pre, &post, &trig_qc, inst)) trigger_waitsets = true; assert (rhc_check_counts_locked (rhc, true, false)); } } TRACE (")\n"); + ddsrt_mutex_unlock (&rhc->lock); - if (trigger_waitsets) - dds_entity_status_signal (&rhc->reader->m_entity); + if (rhc->reader) + { + if (notify_data_available && (rhc->reader->m_entity.m_status_enable & DDS_DATA_AVAILABLE_STATUS)) + { + ddsrt_atomic_inc32 (&rhc->n_cbs); + dds_reader_data_available_cb (rhc->reader); + ddsrt_atomic_dec32 (&rhc->n_cbs); + } + + if (trigger_waitsets) + dds_entity_status_signal (&rhc->reader->m_entity); + } } void dds_rhc_relinquish_ownership (struct rhc * __restrict rhc, const uint64_t wr_iid) diff --git a/src/core/ddsc/tests/listener.c b/src/core/ddsc/tests/listener.c index e3f5c65..d049c85 100644 --- a/src/core/ddsc/tests/listener.c +++ b/src/core/ddsc/tests/listener.c @@ -400,7 +400,8 @@ static void fini_triggering_test(void) { dds_delete(g_reader); - dds_delete(g_writer); + if (g_writer) + dds_delete(g_writer); fini_triggering_base(); } @@ -847,6 +848,113 @@ CU_Test(ddsc_listener, data_available, .init=init_triggering_test, .fini=fini_tr ret = dds_read_status(g_reader, &status, DDS_DATA_AVAILABLE_STATUS); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL(status, 0); + + /* Deleting the writer causes unregisters (or dispose+unregister), and those + should trigger DATA_AVAILABLE as well */ + cb_called = 0; + cb_reader = 0; + ret = dds_delete (g_writer); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + g_writer = 0; + triggered = waitfor_cb(DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); + + /* The listener should have swallowed the status. */ + ret = dds_read_status(g_subscriber, &status, DDS_DATA_ON_READERS_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, 0); + ret = dds_read_status(g_reader, &status, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, 0); +} + +CU_Test(ddsc_listener, data_available_delete_writer, .init=init_triggering_test, .fini=fini_triggering_test) +{ + dds_return_t ret; + uint32_t triggered; + uint32_t status; + RoundTripModule_DataType sample; + memset (&sample, 0, sizeof (sample)); + + /* We are interested in data available notifications. */ + dds_lset_data_available(g_listener, data_available_cb); + ret = dds_set_listener(g_reader, g_listener); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + /* Write sample, wait for the listener to swallow the status. */ + ret = dds_write(g_writer, &sample); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + triggered = waitfor_cb(DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); + + /* Deleting the writer must trigger DATA_AVAILABLE as well */ + cb_called = 0; + cb_reader = 0; + ret = dds_delete (g_writer); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + g_writer = 0; + triggered = waitfor_cb(DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); + + /* The listener should have swallowed the status. */ + ret = dds_read_status(g_subscriber, &status, DDS_DATA_ON_READERS_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, 0); + ret = dds_read_status(g_reader, &status, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, 0); +} + +CU_Test(ddsc_listener, data_available_delete_writer_disposed, .init=init_triggering_test, .fini=fini_triggering_test) +{ + dds_return_t ret; + uint32_t triggered; + uint32_t status; + RoundTripModule_DataType sample; + memset (&sample, 0, sizeof (sample)); + + /* We are interested in data available notifications. */ + dds_lset_data_available(g_listener, data_available_cb); + ret = dds_set_listener(g_reader, g_listener); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + /* Write & dispose sample and take it so that the instance is empty & disposed. Then deleting + the writer should silently drop the instance. */ + ret = dds_write(g_writer, &sample); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + ret = dds_dispose(g_writer, &sample); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + triggered = waitfor_cb(DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); + + /* Take all data so that the instance becomes empty & disposed */ + do { + void *sampleptr = &sample; + dds_sample_info_t info; + ret = dds_take (g_reader, &sampleptr, &info, 1, 1); + } while (ret > 0); + + /* Deleting the writer should not trigger DATA_AVAILABLE with all instances empty & disposed */ + cb_called = 0; + cb_reader = 0; + ret = dds_delete (g_writer); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + g_writer = 0; + triggered = waitfor_cb(DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); + + /* The listener should have swallowed the status. */ + ret = dds_read_status(g_subscriber, &status, DDS_DATA_ON_READERS_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, 0); + ret = dds_read_status(g_reader, &status, DDS_DATA_AVAILABLE_STATUS); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(status, 0); } CU_Test(ddsc_listener, data_on_readers, .init=init_triggering_test, .fini=fini_triggering_test) From 2700dce0eba3430453c375e988ce818ba19892c4 Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Thu, 18 Apr 2019 17:34:14 +0200 Subject: [PATCH 013/238] Remove dependency on jdk8 Chocolatey package Signed-off-by: Jeroen Koekkoek --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1abb951..8274805 100644 --- a/.travis.yml +++ b/.travis.yml @@ -64,6 +64,9 @@ before_install: - if [ "${TRAVIS_OS_NAME}" = "windows" ]; then eval "unset CC"; eval "unset CXX"; + JAVA_HOME=$(find "/c/Program Files/Android/jdk/" -name "*openjdk*" | sort | head -n 1); + export JAVA_HOME; + export PATH="${PATH}:${JAVA_HOME}/bin"; else eval "export CC=${C_COMPILER}"; eval "export CXX=${CXX_COMPILER}"; @@ -83,13 +86,10 @@ before_install: # issue, JAVA_HOME is read from the registry and exported by this script. install: - if [ "${TRAVIS_OS_NAME}" = "windows" ]; then - choco install innoextract maven; + choco install innoextract; + choco install maven --ignore-dependencies; wget -q https://dl.bintray.com/conan/installers/conan-win-64_1_10_0.exe; innoextract conan-win-64_1_10_0.exe; - KEY='HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; - VALUE='JAVA_HOME'; - JAVA_HOME=$(REG QUERY "${KEY}" -v "${VALUE}" | sed -n 's/^.*JAVA_HOME \+[_A-Z]\+ \+//ip'); - eval "export JAVA_HOME=\"${JAVA_HOME}\""; eval "export PATH=\"$(pwd)/app/conan:${PATH}\""; elif [ "${TRAVIS_OS_NAME}" = "osx" ]; then eval "$(pyenv init -)"; From 47ba0ba8c64525ed73d66447bd03d6c590ce998b Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Thu, 18 Apr 2019 18:45:10 +0200 Subject: [PATCH 014/238] Remove JAVA_HOME regarding registry from .travis.yml Signed-off-by: Jeroen Koekkoek --- .travis.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8274805..e619bf6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -77,13 +77,6 @@ before_install: # The real fix is to wait until Python and pip are both available on the # target. Until then download Conan from the official website and simply add # the extracted folder to the path. -# -# Maven requires JAVA_HOME to be set (at least on Windows), but Windows targets -# do not come with Java installed. For now it is installed through Chocolatey -# as a dependency of Maven, hence JAVA_HOME is only available after the -# package is installed. The problem is that the shell cannot be restarted and -# the path is not fixed as it contains the version number. To workaround this -# issue, JAVA_HOME is read from the registry and exported by this script. install: - if [ "${TRAVIS_OS_NAME}" = "windows" ]; then choco install innoextract; From 19a3f6bcad038fe0bbdb7bfd5379d4516fb8f1e7 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 20 Apr 2019 10:28:33 +0200 Subject: [PATCH 015/238] fix race: delete reader & delete writer (#159) Adding and removing reader/writer matches can be done by multiple threads, and this can result in two threads simultaneously trying to do this on a single reader/writer pair. The code therefore always checks first whether the pair is (not) matched before proceeding. However, removing a reader from a proxy writer had part of the code outside this check. Therefore, if both entities are being deleted simultanously, there is a risk that local_reader_ary_remove is called twice for the same argument, and in that case, it asserts in one of them because the reader can no longer be found. The counting of the number of matched reliable readers suffers from the same race condition. This commit eliminates these race conditions by moving these operations into the block guarded by the aforementioned check. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_entity.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 0b0c8fa..c832a9b 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -1371,8 +1371,8 @@ static void writer_drop_local_connection (const struct nn_guid *wr_guid, struct if ((m = ut_avlLookup (&wr_local_readers_treedef, &wr->local_readers, &rd->e.guid)) != NULL) { ut_avlDelete (&wr_local_readers_treedef, &wr->local_readers, m); + local_reader_ary_remove (&wr->rdary, rd); } - local_reader_ary_remove (&wr->rdary, rd); ddsrt_mutex_unlock (&wr->e.lock); if (m != NULL && wr->status_cb) { @@ -1490,15 +1490,11 @@ static void proxy_writer_drop_connection (const struct nn_guid *pwr_guid, struct { ut_avlDelete (&pwr_readers_treedef, &pwr->readers, m); if (m->in_sync != PRMSS_SYNC) - { pwr->n_readers_out_of_sync--; - } + if (rd->reliable) + pwr->n_reliable_readers--; + local_reader_ary_remove (&pwr->rdary, rd); } - if (rd->reliable) - { - pwr->n_reliable_readers--; - } - local_reader_ary_remove (&pwr->rdary, rd); ddsrt_mutex_unlock (&pwr->e.lock); if (m != NULL) { From 83f3a51a477db1cedad8fa835cc69c3f1dac82ae Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 19 Feb 2019 10:53:09 +0100 Subject: [PATCH 016/238] small performance improvement in RHC The introduction of properly functioning query conditions adds some overhead, this commit removes some of that cost by avoiding some calls to update_conditions when there are no query conditions. It also removes the has_changed field from the instance, instead using a local boolean to track whether DATA_AVAILABLE should be raised or not. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_rhc.c | 76 ++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index 30dc4f3..7f3029b 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -250,7 +250,6 @@ struct rhc_instance { unsigned isnew : 1; /* NEW or NOT_NEW view state */ unsigned a_sample_free : 1; /* whether or not a_sample is in use */ unsigned isdisposed : 1; /* DISPOSED or NOT_DISPOSED (if not disposed, wrcount determines ALIVE/NOT_ALIVE_NO_WRITERS) */ - unsigned has_changed : 1; /* To track changes in an instance - if number of samples are added or data is overwritten */ unsigned wr_iid_islive : 1; /* whether wr_iid is of a live writer */ unsigned inv_exists : 1; /* whether or not state change occurred since last sample (i.e., must return invalid sample) */ unsigned inv_isread : 1; /* whether or not that state change has been read before */ @@ -313,7 +312,6 @@ struct trigger_info_cmn { unsigned qminst; bool has_read; bool has_not_read; - bool has_changed; }; struct trigger_info_pre { @@ -552,7 +550,7 @@ static void inst_clear_invsample_if_exists (struct rhc *rhc, struct rhc_instance inst_clear_invsample (rhc, inst, trig_qc); } -static void inst_set_invsample (struct rhc *rhc, struct rhc_instance *inst, struct trigger_info_qcond *trig_qc) +static void inst_set_invsample (struct rhc *rhc, struct rhc_instance *inst, struct trigger_info_qcond *trig_qc, bool *nda) { if (!inst->inv_exists || inst->inv_isread) { @@ -563,6 +561,7 @@ static void inst_set_invsample (struct rhc *rhc, struct rhc_instance *inst, stru inst->inv_exists = 1; inst->inv_isread = 0; rhc->n_invsamples++; + *nda = true; } } @@ -651,7 +650,6 @@ static void init_trigger_info_cmn_nonmatch (struct trigger_info_cmn *info) info->qminst = ~0u; info->has_read = false; info->has_not_read = false; - info->has_changed = false; } static void get_trigger_info_cmn (struct trigger_info_cmn *info, struct rhc_instance *inst) @@ -659,12 +657,10 @@ static void get_trigger_info_cmn (struct trigger_info_cmn *info, struct rhc_inst info->qminst = qmask_of_inst (inst); info->has_read = inst_has_read (inst); info->has_not_read = inst_has_unread (inst); - info->has_changed = inst->has_changed; } static void get_trigger_info_pre (struct trigger_info_pre *info, struct rhc_instance *inst) { - inst->has_changed = 0; get_trigger_info_cmn (&info->c, inst); } @@ -680,15 +676,19 @@ static void init_trigger_info_qcond (struct trigger_info_qcond *qc) qc->inc_conds_sample = 0; } -static bool trigger_info_differs (const struct trigger_info_pre *pre, const struct trigger_info_post *post, const struct trigger_info_qcond *trig_qc) +static bool trigger_info_differs (const struct rhc *rhc, const struct trigger_info_pre *pre, const struct trigger_info_post *post, const struct trigger_info_qcond *trig_qc) { - return (pre->c.qminst != post->c.qminst || - pre->c.has_read != post->c.has_read || - pre->c.has_not_read != post->c.has_not_read || - pre->c.has_changed != post->c.has_changed || - trig_qc->dec_conds_invsample != trig_qc->inc_conds_invsample || - trig_qc->dec_conds_sample != trig_qc->inc_conds_sample || - trig_qc->dec_invsample_read != trig_qc->inc_invsample_read); + if (pre->c.qminst != post->c.qminst || + pre->c.has_read != post->c.has_read || + pre->c.has_not_read != post->c.has_not_read) + return true; + else if (rhc->nqconds == 0) + return false; + else + return (trig_qc->dec_conds_invsample != trig_qc->inc_conds_invsample || + trig_qc->dec_conds_sample != trig_qc->inc_conds_sample || + trig_qc->dec_invsample_read != trig_qc->inc_invsample_read || + trig_qc->dec_sample_read != trig_qc->inc_sample_read); } static bool add_sample (struct rhc *rhc, struct rhc_instance *inst, const struct proxy_writer_info *pwr_info, const struct ddsi_serdata *sample, status_cb_data_t *cb_data, struct trigger_info_qcond *trig_qc) @@ -722,9 +722,6 @@ static bool add_sample (struct rhc *rhc, struct rhc_instance *inst, const struct inst->nvread--; rhc->n_vread--; } - - /* set a flag to indicate instance has changed to notify data_available since the sample is overwritten */ - inst->has_changed = 1; } else { @@ -1042,7 +1039,7 @@ static int rhc_unregister_isreg_w_sideeffects (struct rhc *rhc, const struct rhc } } -static int rhc_unregister_updateinst (struct rhc *rhc, struct rhc_instance *inst, const struct proxy_writer_info * __restrict pwr_info, nn_wctime_t tstamp, struct trigger_info_qcond *trig_qc) +static int rhc_unregister_updateinst (struct rhc *rhc, struct rhc_instance *inst, const struct proxy_writer_info * __restrict pwr_info, nn_wctime_t tstamp, struct trigger_info_qcond *trig_qc, bool *nda) { assert (inst->wrcount > 0); @@ -1074,7 +1071,7 @@ static int rhc_unregister_updateinst (struct rhc *rhc, struct rhc_instance *inst care.) */ if (inst->latest == NULL || inst->latest->isread) { - inst_set_invsample (rhc, inst, trig_qc); + inst_set_invsample (rhc, inst, trig_qc, nda); update_inst (inst, pwr_info, false, tstamp); } if (!inst->isdisposed) @@ -1096,7 +1093,7 @@ static int rhc_unregister_updateinst (struct rhc *rhc, struct rhc_instance *inst /* Add invalid samples for transition to no-writers */ TRACE (",#0,empty,nowriters"); assert (inst_is_empty (inst)); - inst_set_invsample (rhc, inst, trig_qc); + inst_set_invsample (rhc, inst, trig_qc, nda); update_inst (inst, pwr_info, false, tstamp); account_for_empty_to_nonempty_transition (rhc, inst); inst->wr_iid_islive = 0; @@ -1105,8 +1102,10 @@ static int rhc_unregister_updateinst (struct rhc *rhc, struct rhc_instance *inst } } -static void dds_rhc_unregister (struct rhc *rhc, struct rhc_instance *inst, const struct proxy_writer_info * __restrict pwr_info, nn_wctime_t tstamp, struct trigger_info_post *post, struct trigger_info_qcond *trig_qc) +static bool dds_rhc_unregister (struct rhc *rhc, struct rhc_instance *inst, const struct proxy_writer_info * __restrict pwr_info, nn_wctime_t tstamp, struct trigger_info_post *post, struct trigger_info_qcond *trig_qc) { + bool notify_data_available = false; + /* 'post' always gets set; instance may have been freed upon return. */ TRACE (" unregister:"); if (!rhc_unregister_isreg_w_sideeffects (rhc, inst, pwr_info->iid)) @@ -1114,7 +1113,7 @@ static void dds_rhc_unregister (struct rhc *rhc, struct rhc_instance *inst, cons /* other registrations remain */ get_trigger_info_cmn (&post->c, inst); } - else if (rhc_unregister_updateinst (rhc, inst, pwr_info, tstamp, trig_qc)) + else if (rhc_unregister_updateinst (rhc, inst, pwr_info, tstamp, trig_qc, ¬ify_data_available)) { /* instance dropped */ init_trigger_info_cmn_nonmatch (&post->c); @@ -1124,6 +1123,7 @@ static void dds_rhc_unregister (struct rhc *rhc, struct rhc_instance *inst, cons /* no writers remain, but instance not empty */ get_trigger_info_cmn (&post->c, inst); } + return notify_data_available; } static struct rhc_instance *alloc_new_instance (const struct rhc *rhc, const struct proxy_writer_info *pwr_info, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) @@ -1207,7 +1207,8 @@ static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst else { if (inst->isdisposed) { - inst_set_invsample (rhc, inst, trig_qc); + bool nda_dummy = false; + inst_set_invsample (rhc, inst, trig_qc, &nda_dummy); } } @@ -1242,6 +1243,7 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info rhc_store_result_t stored; status_cb_data_t cb_data; /* Callback data for reader status callback */ bool delivered = true; + bool notify_data_available = false; TRACE ("rhc_store(%"PRIx64",%"PRIx64" si %x has_data %d:", tk->m_iid, wr_iid, statusinfo, has_data); if (!has_data && statusinfo == 0) @@ -1282,6 +1284,7 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info goto error_or_nochange; } init_trigger_info_cmn_nonmatch (&pre.c); + notify_data_available = true; } } else if (!inst_accepts_sample (rhc, inst, pwr_info, sample, has_data)) @@ -1300,7 +1303,8 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info } if (statusinfo & NN_STATUSINFO_UNREGISTER) { - dds_rhc_unregister (rhc, inst, pwr_info, sample->timestamp, &post, &trig_qc); + if (dds_rhc_unregister (rhc, inst, pwr_info, sample->timestamp, &post, &trig_qc)) + notify_data_available = true; } else { @@ -1389,11 +1393,12 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info inst->disposed_gen--; goto error_or_nochange; } + notify_data_available = true; } /* If instance became disposed, add an invalid sample if there are no samples left */ if (inst_became_disposed && inst->latest == NULL) - inst_set_invsample (rhc, inst, &trig_qc); + inst_set_invsample (rhc, inst, &trig_qc, ¬ify_data_available); update_inst (inst, pwr_info, true, sample->timestamp); @@ -1449,18 +1454,7 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info TRACE (")\n"); - const bool update_read_conditions = trigger_info_differs (&pre, &post, &trig_qc); - bool notify_data_available; - /* do not send data available notification when an instance is dropped */ - if ((post.c.qminst == ~0u) && (post.c.has_read == 0) && (post.c.has_not_read == 0) && (post.c.has_changed == false)) - notify_data_available = false; - else /* FIXME: now that trigger_info_differs incorporates details on samples added/removed, this might well be wrong */ - notify_data_available = update_read_conditions; - - if (update_read_conditions) - trigger_waitsets = update_conditions_locked (rhc, true, &pre, &post, &trig_qc, inst); - else - trigger_waitsets = false; + trigger_waitsets = trigger_info_differs (rhc, &pre, &post, &trig_qc) && update_conditions_locked (rhc, true, &pre, &post, &trig_qc, inst); assert (rhc_check_counts_locked (rhc, true, true)); @@ -1557,7 +1551,7 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ else { const bool was_empty = inst_is_empty (inst); - inst_set_invsample (rhc, inst, &trig_qc); + inst_set_invsample (rhc, inst, &trig_qc, ¬ify_data_available); if (was_empty) account_for_empty_to_nonempty_transition (rhc, inst); else @@ -1570,7 +1564,7 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ TRACE ("\n"); notify_data_available = true; - if (trigger_info_differs (&pre, &post, &trig_qc) && update_conditions_locked (rhc, true, &pre, &post, &trig_qc, inst)) + if (trigger_info_differs (rhc, &pre, &post, &trig_qc) && update_conditions_locked (rhc, true, &pre, &post, &trig_qc, inst)) trigger_waitsets = true; assert (rhc_check_counts_locked (rhc, true, false)); } @@ -1589,7 +1583,9 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ } if (trigger_waitsets) - dds_entity_status_signal (&rhc->reader->m_entity); + { + dds_entity_status_signal(&rhc->reader->m_entity); + } } } From 9bfac607a4edb12b9c9c60f1cc66f35a4f518111 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 3 Apr 2019 17:03:17 +0200 Subject: [PATCH 017/238] move MT19937 random generator to ddsrt Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_xmsg.c | 2 +- src/core/xtests/CMakeLists.txt | 2 +- src/core/xtests/mt19937ar.c | 184 ----------------------- src/core/xtests/mt19937ar.h | 46 ------ src/core/xtests/rhc_torture.c | 18 ++- src/ddsrt/CMakeLists.txt | 2 +- src/ddsrt/include/dds/ddsrt/random.h | 23 ++- src/ddsrt/src/cdtors.c | 3 + src/ddsrt/src/random.c | 205 +++++++++++++++++++++++--- src/ddsrt/src/random/posix/random.c | 17 +++ src/ddsrt/src/random/windows/random.c | 14 ++ src/ddsrt/tests/CMakeLists.txt | 1 + src/ddsrt/tests/random.c | 92 ++++++++++++ 13 files changed, 345 insertions(+), 264 deletions(-) delete mode 100644 src/core/xtests/mt19937ar.c delete mode 100644 src/core/xtests/mt19937ar.h create mode 100644 src/ddsrt/src/random/posix/random.c create mode 100644 src/ddsrt/src/random/windows/random.c create mode 100644 src/ddsrt/tests/random.c diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index ec1495d..d1c83cb 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -1261,7 +1261,7 @@ static ssize_t nn_xpack_send1 (const nn_locator_t *loc, void * varg) { /* We drop APPROXIMATELY a fraction of xmit_lossiness * 10**(-3) of all packets to be sent */ - if ((ddsrt_random () % 1000) < config.xmit_lossiness) + if ((ddsrt_random () % 1000) < (uint32_t) config.xmit_lossiness) { DDS_TRACE("(dropped)"); xp->call_flags = 0; diff --git a/src/core/xtests/CMakeLists.txt b/src/core/xtests/CMakeLists.txt index 9a67a6c..0b1d362 100644 --- a/src/core/xtests/CMakeLists.txt +++ b/src/core/xtests/CMakeLists.txt @@ -11,7 +11,7 @@ # idlc_generate(RhcTypes RhcTypes.idl) -add_executable(rhc_torture rhc_torture.c mt19937ar.c mt19937ar.h) +add_executable(rhc_torture rhc_torture.c) target_include_directories( rhc_torture PRIVATE diff --git a/src/core/xtests/mt19937ar.c b/src/core/xtests/mt19937ar.c deleted file mode 100644 index 31e347e..0000000 --- a/src/core/xtests/mt19937ar.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright(c) 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -/* - A C-program for MT19937, with initialization improved 2002/1/26. - Coded by Takuji Nishimura and Makoto Matsumoto. - - Before using, initialize the state by using init_genrand(seed) - or init_by_array(init_key, key_length). - - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - Any feedback is very welcome. - http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html - email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) -*/ - -#include "mt19937ar.h" - -/* Period parameters */ -#define N 624 -#define M 397 -#define MATRIX_A 0x9908b0dfU /* constant vector a */ -#define UPPER_MASK 0x80000000U /* most significant w-r bits */ -#define LOWER_MASK 0x7fffffffU /* least significant r bits */ - -static uint32_t mt[N]; /* the array for the state vector */ -static uint32_t mti=N+1; /* mti==N+1 means mt[N] is not initialized */ - -/* initializes mt[N] with a seed */ -void init_genrand(uint32_t s) -{ - mt[0]= s & 0xffffffffU; - for (mti=1; mti> 30)) + mti); - /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ - /* In the previous versions, MSBs of the seed affect */ - /* only MSBs of the array mt[]. */ - /* 2002/01/09 modified by Makoto Matsumoto */ - mt[mti] &= 0xffffffffU; - /* for >32 bit machines */ - } -} - -/* initialize by an array with array-length */ -/* init_key is the array for initializing keys */ -/* key_length is its length */ -/* slight change for C++, 2004/2/26 */ -void init_by_array(uint32_t init_key[], size_t key_length) -{ - uint32_t i, j, k; - init_genrand(19650218U); - i=1; j=0; - k = (N>key_length ? N : (uint32_t)key_length); - for (; k; k--) { - mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525U)) - + init_key[j] + j; /* non linear */ - mt[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */ - i++; j++; - if (i>=N) { mt[0] = mt[N-1]; i=1; } - if (j>=(uint32_t)key_length) j=0; - } - for (k=N-1; k; k--) { - mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941U)) - - i; /* non linear */ - mt[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */ - i++; - if (i>=N) { mt[0] = mt[N-1]; i=1; } - } - - mt[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */ -} - -/* generates a random number on [0,0xffffffff]-interval */ -uint32_t genrand_int32(void) -{ - uint32_t y; - static uint32_t mag01[2]={0x0U, MATRIX_A}; - /* mag01[x] = x * MATRIX_A for x=0,1 */ - - if (mti >= N) { /* generate N words at one time */ - int kk; - - if (mti == N+1) /* if init_genrand() has not been called, */ - init_genrand(5489U); /* a default initial seed is used */ - - for (kk=0;kk> 1) ^ mag01[y & 0x1U]; - } - for (;kk> 1) ^ mag01[y & 0x1U]; - } - y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); - mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1U]; - - mti = 0; - } - - y = mt[mti++]; - - /* Tempering */ - y ^= (y >> 11); - y ^= (y << 7) & 0x9d2c5680U; - y ^= (y << 15) & 0xefc60000U; - y ^= (y >> 18); - - return (uint32_t) y; -} - -/* generates a random number on [0,0x7fffffff]-interval */ -int32_t genrand_int31(void) -{ - return (int32_t)(genrand_int32()>>1); -} - -/* generates a random number on [0,1]-real-interval */ -double genrand_real1(void) -{ - return genrand_int32()*(1.0/4294967295.0); - /* divided by 2^32-1 */ -} - -/* generates a random number on [0,1)-real-interval */ -double genrand_real2(void) -{ - return genrand_int32()*(1.0/4294967296.0); - /* divided by 2^32 */ -} - -/* generates a random number on (0,1)-real-interval */ -double genrand_real3(void) -{ - return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0); - /* divided by 2^32 */ -} - -/* generates a random number on [0,1) with 53-bit resolution*/ -double genrand_res53(void) -{ - uint32_t a=genrand_int32()>>5, b=genrand_int32()>>6; - return(a*67108864.0+b)*(1.0/9007199254740992.0); -} -/* These real versions are due to Isaku Wada, 2002/01/09 added */ diff --git a/src/core/xtests/mt19937ar.h b/src/core/xtests/mt19937ar.h deleted file mode 100644 index aaa08c8..0000000 --- a/src/core/xtests/mt19937ar.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright(c) 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef MT19937AR_H -#define MT19937AR_H - -#include -#include - -/* initializes mt[N] with a seed */ -void init_genrand(uint32_t s); - -/* initialize by an array with array-length */ -/* init_key is the array for initializing keys */ -/* key_length is its length */ -/* slight change for C++, 2004/2/26 */ -void init_by_array(uint32_t init_key[], size_t key_length); - -/* generates a random number on [0,0xffffffff]-interval */ -uint32_t genrand_int32(void); - -/* generates a random number on [0,0x7fffffff]-interval */ -int32_t genrand_int31(void); - -/* generates a random number on [0,1]-real-interval */ -double genrand_real1(void); - -/* generates a random number on [0,1)-real-interval */ -double genrand_real2(void); - -/* generates a random number on (0,1)-real-interval */ -double genrand_real3(void); - -/* generates a random number on [0,1) with 53-bit resolution*/ -double genrand_res53(void); -/* These real versions are due to Isaku Wada, 2002/01/09 added */ - -#endif diff --git a/src/core/xtests/rhc_torture.c b/src/core/xtests/rhc_torture.c index 827d04d..bc7c4fb 100644 --- a/src/core/xtests/rhc_torture.c +++ b/src/core/xtests/rhc_torture.c @@ -18,6 +18,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/process.h" #include "dds/ddsrt/sync.h" +#include "dds/ddsrt/random.h" #include "dds/dds.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds__entity.h" @@ -32,7 +33,6 @@ #include "dds__rhc.h" #include "dds/ddsi/ddsi_iid.h" -#include "mt19937ar.h" #include "RhcTypes.h" #ifndef _MSC_VER @@ -41,6 +41,8 @@ #define STATIC_ARRAY_DIM #endif +static ddsrt_prng_t prng; + static struct ddsi_sertopic *mdtopic; static struct thread_state1 *mainthread; static dds_time_t tref_dds; @@ -669,14 +671,14 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count, int lastprint_pct = 0; for (int i = 0; i < count; i++) { - const int32_t keyval = (int32_t) (genrand_int32 () % N_KEYVALS); - const uint32_t which = genrand_int32 () % 3; + const int32_t keyval = (int32_t) (ddsrt_prng_random (&prng) % N_KEYVALS); + const uint32_t which = ddsrt_prng_random (&prng) % 3; uint32_t oper_base; uint32_t oper; /* generate uniform number in range 0 .. N, then map to operation following the frequency table */ do { - oper_base = genrand_int32 (); + oper_base = ddsrt_prng_random (&prng); } while (oper_base >= opthres[sizeof (opfreqs) / sizeof (opfreqs[0]) - 1]); for (oper = 0; oper < sizeof (opfreqs) / sizeof (opfreqs[0]); oper++) { @@ -745,19 +747,19 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count, tkall (rhc[k], NULL, print && k == 0, states_seen); break; case 8: { - uint32_t cond = genrand_int32 () % (uint32_t) nconds; + uint32_t cond = ddsrt_prng_random (&prng) % (uint32_t) nconds; for (size_t k = 0; k < nrd; k++) rdcond (rhc[k], rhcconds[cond], NULL, 0, print && k == 0, states_seen); break; } case 9: { - uint32_t cond = genrand_int32 () % (uint32_t) nconds; + uint32_t cond = ddsrt_prng_random (&prng) % (uint32_t) nconds; for (size_t k = 0; k < nrd; k++) tkcond (rhc[k], rhcconds[cond], NULL, 0, print && k == 0, states_seen); break; } case 10: { - uint32_t cond = genrand_int32 () % (uint32_t) nconds; + uint32_t cond = ddsrt_prng_random (&prng) % (uint32_t) nconds; for (size_t k = 0; k < nrd; k++) tkcond (rhc[k], rhcconds[cond], NULL, 1, print && k == 0, states_seen); break; @@ -826,7 +828,7 @@ int main (int argc, char **argv) print = (atoi (argv[4]) != 0); printf ("prng seed %u first %d count %d print %d\n", seed, first, count, print); - init_genrand (seed); + ddsrt_prng_init_simple (&prng, seed); memset (rres_mseq, 0, sizeof (rres_mseq)); for (size_t i = 0; i < sizeof (rres_iseq) / sizeof(rres_iseq[0]); i++) diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index 5179742..7830104 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -165,7 +165,7 @@ find_package(Threads REQUIRED) target_link_libraries(ddsrt INTERFACE Threads::Threads) if(WIN32) - target_link_libraries(ddsrt INTERFACE wsock32 ws2_32 iphlpapi) + target_link_libraries(ddsrt INTERFACE wsock32 ws2_32 iphlpapi bcrypt) elseif(UNIX) check_library_exists(c clock_gettime "" HAVE_CLOCK_GETTIME) if(NOT HAVE_CLOCK_GETTIME) diff --git a/src/ddsrt/include/dds/ddsrt/random.h b/src/ddsrt/include/dds/ddsrt/random.h index 4e44c82..0ef600f 100644 --- a/src/ddsrt/include/dds/ddsrt/random.h +++ b/src/ddsrt/include/dds/ddsrt/random.h @@ -12,13 +12,34 @@ #ifndef DDSRT_RANDOM_H #define DDSRT_RANDOM_H +#include +#include #include "dds/export.h" #if defined (__cplusplus) extern "C" { #endif -DDS_EXPORT long ddsrt_random(void); +#define DDSRT_MT19937_N 624 + +typedef struct ddsrt_prng_seed { + uint32_t key[8]; +} ddsrt_prng_seed_t; + +typedef struct ddsrt_prng { + uint32_t mt[DDSRT_MT19937_N]; + uint32_t mti; +} ddsrt_prng_t; + +DDS_EXPORT void ddsrt_random_init (void); +DDS_EXPORT void ddsrt_random_fini (void); + +DDS_EXPORT void ddsrt_prng_init_simple (ddsrt_prng_t *prng, uint32_t seed); +DDS_EXPORT bool ddsrt_prng_makeseed (struct ddsrt_prng_seed *seed); +DDS_EXPORT void ddsrt_prng_init (ddsrt_prng_t *prng, const struct ddsrt_prng_seed *seed); +DDS_EXPORT uint32_t ddsrt_prng_random (ddsrt_prng_t *prng); + +DDS_EXPORT uint32_t ddsrt_random (void); #if defined (__cplusplus) } diff --git a/src/ddsrt/src/cdtors.c b/src/ddsrt/src/cdtors.c index a3088fb..3888c87 100644 --- a/src/ddsrt/src/cdtors.c +++ b/src/ddsrt/src/cdtors.c @@ -13,6 +13,7 @@ #include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/sync.h" #include "dds/ddsrt/time.h" +#include "dds/ddsrt/random.h" #if _WIN32 /* Sockets API initialization is only necessary on Microsoft Windows. The @@ -41,6 +42,7 @@ retry: ddsrt_winsock_init(); ddsrt_time_init(); #endif + ddsrt_random_init(); ddsrt_atomic_or32(&init_status, INIT_STATUS_OK); } else { while (v > 1 && !(v & INIT_STATUS_OK)) { @@ -65,6 +67,7 @@ void ddsrt_fini (void) if (nv == 1) { ddsrt_mutex_destroy(&init_mutex); + ddsrt_random_fini(); #if _WIN32 ddsrt_winsock_fini(); ddsrt_time_fini(); diff --git a/src/ddsrt/src/random.c b/src/ddsrt/src/random.c index 582cb48..7f2943a 100644 --- a/src/ddsrt/src/random.c +++ b/src/ddsrt/src/random.c @@ -9,36 +9,197 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ + +/* + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) +*/ + #include #include +#include #include "dds/ddsrt/random.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/time.h" +#include "dds/ddsrt/process.h" -#if _WIN32 -#define _CRT_RAND_S -#include +#define N DDSRT_MT19937_N +#define M 397 +#define MATRIX_A 0x9908b0dfU /* constant vector a */ +#define UPPER_MASK 0x80000000U /* most significant w-r bits */ +#define LOWER_MASK 0x7fffffffU /* least significant r bits */ -long random (void) +static ddsrt_prng_t default_prng; +static ddsrt_mutex_t default_prng_lock; + +/* initializes mt[N] with a seed */ +static void init_genrand (ddsrt_prng_t *prng, uint32_t s) { - /* rand() is a really terribly bad PRNG */ - /* FIXME: Indeed (especially if not seeded), use rand_s instead. */ - union { long x; unsigned char c[4]; } t; - int i; - for (i = 0; i < 4; i++) - t.c[i] = (unsigned char) ((rand () >> 4) & 0xff); -#if RAND_MAX == INT32_MAX || RAND_MAX == 0x7fff - t.x &= RAND_MAX; -#elif RAND_MAX <= 0x7ffffffe - t.x %= (RAND_MAX+1); -#else -#error "RAND_MAX out of range" -#endif - return t.x; + prng->mt[0] = s; + for (prng->mti = 1; prng->mti < N; prng->mti++) + { + prng->mt[prng->mti] = (1812433253U * (prng->mt[prng->mti-1] ^ (prng->mt[prng->mti-1] >> 30)) + prng->mti); + /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ + /* In the previous versions, MSBs of the seed affect */ + /* only MSBs of the array mt[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + } } -#endif -long ddsrt_random(void) +/* initialize by an array with array-length */ +/* init_key is the array for initializing keys */ +/* key_length is its length */ +/* slight change for C++, 2004/2/26 */ +static void init_by_array (ddsrt_prng_t *prng, const uint32_t init_key[], size_t key_length) { - /* FIXME: Not MT-safe, should use random_r (or a real PRNG) instead. */ - return random(); + uint32_t i, j, k; + init_genrand (prng, 19650218U); + i = 1; j = 0; + k = (N > key_length ? N : (uint32_t) key_length); + for (; k; k--) + { + prng->mt[i] = (prng->mt[i] ^ ((prng->mt[i-1] ^ (prng->mt[i-1] >> 30)) * 1664525U)) + init_key[j] + j; /* non linear */ + i++; j++; + if (i >= N) + { + prng->mt[0] = prng->mt[N-1]; + i=1; + } + if (j >= key_length) + { + j = 0; + } + } + for (k = N-1; k; k--) + { + prng->mt[i] = (prng->mt[i] ^ ((prng->mt[i-1] ^ (prng->mt[i-1] >> 30)) * 1566083941U)) - i; /* non linear */ + i++; + if (i >= N) + { + prng->mt[0] = prng->mt[N-1]; + i = 1; + } + } + prng->mt[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */ +} + +void ddsrt_prng_init_simple (ddsrt_prng_t *prng, uint32_t seed) +{ + init_genrand (prng, seed); +} + +void ddsrt_prng_init (ddsrt_prng_t *prng, const struct ddsrt_prng_seed *seed) +{ + init_by_array (prng, seed->key, sizeof (seed->key) / sizeof (seed->key[0])); +} + +/* generates a random number on [0,0xffffffff]-interval */ +uint32_t ddsrt_prng_random (ddsrt_prng_t *prng) +{ + /* mag01[x] = x * MATRIX_A for x=0,1 */ + static const uint32_t mag01[2] = { 0x0U, MATRIX_A }; + uint32_t y; + + if (prng->mti >= N) + { + /* generate N words at one time */ + int kk; + + for (kk=0; kk < N-M; kk++) + { + y = (prng->mt[kk] & UPPER_MASK) | (prng->mt[kk+1] & LOWER_MASK); + prng->mt[kk] = prng->mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1U]; + } + for (; kk < N-1; kk++) + { + y = (prng->mt[kk] & UPPER_MASK) | (prng->mt[kk+1] & LOWER_MASK); + prng->mt[kk] = prng->mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1U]; + } + y = (prng->mt[N-1] & UPPER_MASK) | (prng->mt[0] & LOWER_MASK); + prng->mt[N-1] = prng->mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1U]; + + prng->mti = 0; + } + + y = prng->mt[prng->mti++]; + + /* Tempering */ + y ^= (y >> 11); + y ^= (y << 7) & 0x9d2c5680U; + y ^= (y << 15) & 0xefc60000U; + y ^= (y >> 18); + + return y; +} + +uint32_t ddsrt_random (void) +{ + uint32_t x; + ddsrt_mutex_lock (&default_prng_lock); + x = ddsrt_prng_random (&default_prng); + ddsrt_mutex_unlock (&default_prng_lock); + return x; +} + +void ddsrt_random_init (void) +{ + ddsrt_prng_seed_t seed; + if (!ddsrt_prng_makeseed (&seed)) + { + /* Poor man's initialisation */ + struct lengthof_seed_large_enough { + char ok[sizeof (seed.key) / sizeof (seed.key[0]) >= 3 ? 1 : -1]; + }; + memset (&seed, 0, sizeof (seed)); + dds_time_t now = dds_time (); + seed.key[0] = (uint32_t) ddsrt_getpid (); + seed.key[1] = (uint32_t) ((uint64_t) now >> 32); + seed.key[2] = (uint32_t) now; + } + ddsrt_prng_init (&default_prng, &seed); + ddsrt_mutex_init (&default_prng_lock); +} + +void ddsrt_random_fini (void) +{ + ddsrt_mutex_destroy (&default_prng_lock); } diff --git a/src/ddsrt/src/random/posix/random.c b/src/ddsrt/src/random/posix/random.c new file mode 100644 index 0000000..067f42b --- /dev/null +++ b/src/ddsrt/src/random/posix/random.c @@ -0,0 +1,17 @@ +#include +#include +#include "dds/ddsrt/random.h" + +bool ddsrt_prng_makeseed (struct ddsrt_prng_seed *seed) +{ + FILE *rndfile; + memset (seed->key, 0, sizeof (seed->key)); + if ((rndfile = fopen ("/dev/urandom", "rb")) == NULL) + return false; + else + { + size_t n = fread (seed->key, sizeof (seed->key), 1, rndfile); + fclose (rndfile); + return (n == 1); + } +} diff --git a/src/ddsrt/src/random/windows/random.c b/src/ddsrt/src/random/windows/random.c new file mode 100644 index 0000000..6c912b3 --- /dev/null +++ b/src/ddsrt/src/random/windows/random.c @@ -0,0 +1,14 @@ +#include +#define WIN32_NO_STATUS +#include +#include "bcrypt.h" +#include +#include "dds/ddsrt/random.h" + +bool ddsrt_prng_makeseed (struct ddsrt_prng_seed *seed) +{ + NTSTATUS res; + memset (seed->key, 0, sizeof (seed->key)); + res = BCryptGenRandom (NULL, (PUCHAR) seed->key, (ULONG) sizeof (seed->key), BCRYPT_USE_SYSTEM_PREFERRED_RNG); + return (res >= 0); +} diff --git a/src/ddsrt/tests/CMakeLists.txt b/src/ddsrt/tests/CMakeLists.txt index 2b3483d..552cfd2 100644 --- a/src/ddsrt/tests/CMakeLists.txt +++ b/src/ddsrt/tests/CMakeLists.txt @@ -22,6 +22,7 @@ set(sources "thread_cleanup.c" "string.c" "log.c" + "random.c" "strlcpy.c" "socket.c" "select.c") diff --git a/src/ddsrt/tests/random.c b/src/ddsrt/tests/random.c new file mode 100644 index 0000000..f1f2dca --- /dev/null +++ b/src/ddsrt/tests/random.c @@ -0,0 +1,92 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include + +#include "CUnit/Test.h" +#include "dds/ddsrt/random.h" + +#define N_PRNG 4 +#define N_DATA 10 + +CU_Test(ddsrt_random, mt19937) +{ + static const uint32_t refdata[N_DATA] = { + 3499211612u, 581869302u, 3890346734u, 3586334585u, 545404204u, + 4161255391u, 3922919429u, 949333985u, 2715962298u, 1323567403u + }; + ddsrt_prng_t prng; + ddsrt_prng_init_simple (&prng, 5489U); + for (size_t i = 0; i < N_DATA; i++) + { + uint32_t x = ddsrt_prng_random (&prng); + CU_ASSERT_EQUAL_FATAL(x, refdata[i]); + } +} + +CU_Test(ddsrt_random, makeseed) +{ + ddsrt_prng_seed_t seeds[N_PRNG]; + + /* Until proven otherwise, assume all platforms have a good way of getting multiple seeds */ + memset (seeds, 0, sizeof (seeds)); + for (size_t i = 0; i < N_PRNG; i++) + { + bool ok = ddsrt_prng_makeseed (&seeds[i]); + CU_ASSERT_FATAL(ok); + } + + /* Any pair the same is possible, but the likelihood should be so small that it is worth accepting + an intermittently failing test */ + for (size_t i = 0; i < N_PRNG; i++) + { + for (size_t j = i + 1; j < N_PRNG; j++) + CU_ASSERT_FATAL (memcmp (&seeds[i], &seeds[j], sizeof (seeds[i])) != 0); + } + + /* A short random sequence generated from each of the different seeds should be unique -- again, + there is no guarantee but only an overwhelming likelihood */ + ddsrt_prng_t prngs[N_PRNG]; + uint32_t data[N_PRNG][N_DATA]; + memset (data, 0, sizeof (data)); + for (size_t i = 0; i < N_PRNG; i++) + { + ddsrt_prng_init (&prngs[i], &seeds[i]); + for (size_t j = 0; j < N_DATA; j++) + data[i][j] = ddsrt_prng_random (&prngs[i]); + } + for (size_t i = 0; i < N_PRNG; i++) + { + for (size_t j = i + 1; j < N_PRNG; j++) + CU_ASSERT_FATAL (memcmp (&data[i], &data[j], sizeof (data[i])) != 0); + } +} + +CU_Test(ddsrt_random, default_random) +{ +#define N_BINS 128 +#define N_PER_BIN 100 + uint32_t bins[N_BINS]; + memset (bins, 0, sizeof (bins)); + for (size_t i = 0; i < N_PER_BIN * N_BINS; i++) + { + uint32_t x = ddsrt_random (); + bins[x % N_BINS]++; + } + double chisq = 0.0; + for (size_t i = 0; i < N_BINS; i++) + chisq += ((bins[i] - N_PER_BIN) * (bins[i] - N_PER_BIN)) / (double) N_PER_BIN; + /* Solve[CDF[ChiSquareDistribution[127], x] == 999/1000] */ + CU_ASSERT (chisq < 181.993); +} From a94a2296fe404138d60bec717782d14bf25f840c Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 4 Apr 2019 15:35:11 +0200 Subject: [PATCH 018/238] install core/ddsi and util header files Some of the former are required to implement alternative serialisation methods; the latter is just generally useful. For the time being these are not part of the formal API and not subject to backwards compatibility. Still, they have value for quickly building tools on that use Cyclone and happen to need any of these functions. Signed-off-by: Erik Boasson --- src/core/CMakeLists.txt | 8 ++++++-- src/core/ddsi/CMakeLists.txt | 6 +++++- .../ddsi/include/dds/ddsi/probes-constants.h | 18 ------------------ src/util/CMakeLists.txt | 5 +++++ 4 files changed, 16 insertions(+), 21 deletions(-) delete mode 100644 src/core/ddsi/include/dds/ddsi/probes-constants.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 2ef2fc3..39a580f 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -53,9 +53,13 @@ include(ddsc/CMakeLists.txt) target_link_libraries(ddsc PRIVATE util) target_link_libraries(ddsc PRIVATE ddsrt) target_compile_definitions( - ddsc PUBLIC $>) + ddsc PUBLIC + $> + $>) target_include_directories( - ddsc PUBLIC $>) + ddsc PUBLIC + $> + $>) # SOVERSION should increase on incompatible ABI change set_target_properties(ddsc PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 8821665..683ad6e 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -78,7 +78,6 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" ddsi_iid.h ddsi_tkmap.h ddsi_vendor.h - probes-constants.h q_addrset.h q_bitset.h q_bswap.h @@ -126,3 +125,8 @@ target_sources(ddsc target_include_directories(ddsc PRIVATE "${CMAKE_CURRENT_LIST_DIR}/include") + +install( + DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/include/dds" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + COMPONENT dev) diff --git a/src/core/ddsi/include/dds/ddsi/probes-constants.h b/src/core/ddsi/include/dds/ddsi/probes-constants.h deleted file mode 100644 index 83b15ab..0000000 --- a/src/core/ddsi/include/dds/ddsi/probes-constants.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef PROBES_CONSTANTS_H -#define PROBES_CONSTANTS_H -#define DROP_QUEUE_FULL 1 -#define DROP_TOO_OLD 2 -#define DROP_REORDER_FULL 3 -#define DROP_DUPLICATE 4 -#endif diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 4f44a70..84088c3 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -37,6 +37,11 @@ target_include_directories( "$" "$>") +install( + DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/include/dds" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + COMPONENT dev) + # TODO: improve test inclusion. if((BUILD_TESTING) AND ((NOT DEFINED MSVC_VERSION) OR (MSVC_VERSION GREATER "1800"))) add_subdirectory(tests) From 069688bb76adb0fc15448f7be609e99fd356818a Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sun, 7 Apr 2019 17:30:32 +0200 Subject: [PATCH 019/238] fix trace print of tkmap_instance address Fix the trace to contain a print of the address of the tkamp_instance (along with the instance id), rather than the address of the stack variable pointing to the tkmap_instance. Signed-off-by: Erik Boasson --- src/core/ddsi/src/ddsi_tkmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsi/src/ddsi_tkmap.c b/src/core/ddsi/src/ddsi_tkmap.c index fbc6094..0d1c6bd 100644 --- a/src/core/ddsi/src/ddsi_tkmap.c +++ b/src/core/ddsi/src/ddsi_tkmap.c @@ -203,7 +203,7 @@ retry: if (tk && rd) { - DDS_TRACE("tk=%p iid=%"PRIx64" ", (void *) &tk, tk->m_iid); + DDS_TRACE("tk=%p iid=%"PRIx64" ", (void *) tk, tk->m_iid); } return tk; } From 7d281df24a947dc2384687fe80396cc1007aeaaa Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 19 Feb 2019 10:57:21 +0100 Subject: [PATCH 020/238] lift limits on handle allocation and reuse (#95) The old entity handle mechanism suffered from a number of problems, the most terrible one being that it would only ever allocate 1000 handles (not even have at most 1000 in use at the same time). Secondarily, it was protected by a single mutex that actually does show up as a limiting factor in, say, a polling-based throughput test with small messages. Thirdly, it tried to provide for various use cases that don't exist in practice but add complexity and overhead. This commit totally rewrites the mechanism, by replacing the old array with a hash table and allowing a near-arbitrary number of handles as well as reuse of handles. It also removes the entity "kind" bits in the most significant bits of the handles, because they only resulted in incorrect checking of argument validity. All that is taken out, but there is still more cleaning up to be done. It furthermore removes an indirection in the handle-to-entity lookup by embedding the "dds_handle_link" structure in the entity. Handle allocation is randomized to avoid the have a high probability of quickly finding an available handle (the total number of handles is limited to a number much smaller than the domain from which they are allocated). The likelihood of handle reuse is still dependent on the number of allocated handles -- the fewer handles there are, the longer the expected time to reuse. Non-randomized handles would give a few guarantees more, though. It moreover moves the code from the "util" to the "core/ddsc" component, because it really is only used for entities, and besides the new implementation relies on the deferred freeing (a.k.a. garbage collection mechanism) implemented in the core. The actual handle management has two variants, selectable with a macro: the preferred embodiment uses a concurrent hash table, the actually used one performs all operations inside a single mutex and uses a non-concurrent version of the hash table. The reason the less-predeferred embodiment is used is that the concurrent version requires the freeing of entity objects to be deferred (much like the GUID-to-entity hash tables in DDSI function, or indeed the key value to instance handle mapping). That is a fair bit of work, and the non-concurrent version is a reasonable intermediate step. Signed-off-by: Erik Boasson --- src/CMakeLists.txt | 1 - src/cmake/modules/FileIDs.cmake | 146 ------- src/core/CMakeLists.txt | 2 - src/core/ddsc/.fileids | 33 -- src/core/ddsc/CMakeLists.txt | 2 + src/core/ddsc/include/dds/dds.h | 11 +- .../ddsc/include/dds/ddsc/dds_public_impl.h | 4 +- src/core/ddsc/src/dds__entity.h | 30 +- src/core/ddsc/src/dds__err.h | 15 +- .../ddsc/src/dds__handles.h} | 131 ++---- src/core/ddsc/src/dds__publisher.h | 3 + src/core/ddsc/src/dds__subscriber.h | 3 +- src/core/ddsc/src/dds__types.h | 7 +- src/core/ddsc/src/dds_coherent.c | 46 +- src/core/ddsc/src/dds_entity.c | 205 ++++----- src/core/ddsc/src/dds_guardcond.c | 6 +- src/core/ddsc/src/dds_handles.c | 267 ++++++++++++ src/core/ddsc/src/dds_init.c | 36 +- src/core/ddsc/src/dds_participant.c | 8 +- src/core/ddsc/src/dds_publisher.c | 54 +-- src/core/ddsc/src/dds_querycond.c | 4 +- src/core/ddsc/src/dds_read.c | 6 +- src/core/ddsc/src/dds_readcond.c | 39 +- src/core/ddsc/src/dds_reader.c | 201 +++++---- src/core/ddsc/src/dds_subscriber.c | 3 + src/core/ddsc/src/dds_topic.c | 10 +- src/core/ddsc/src/dds_waitset.c | 14 +- src/core/ddsc/src/dds_writer.c | 87 ++-- src/core/ddsc/tests/CMakeLists.txt | 2 +- src/core/ddsc/tests/builtin_topics.c | 9 +- src/core/ddsc/tests/dispose.c | 24 +- src/core/ddsc/tests/entity_hierarchy.c | 50 +-- src/core/ddsc/tests/entity_status.c | 100 ++--- src/core/ddsc/tests/file_id.c | 37 -- src/core/ddsc/tests/publisher.c | 29 +- src/core/ddsc/tests/querycondition.c | 12 +- src/core/ddsc/tests/read_instance.c | 16 +- src/core/ddsc/tests/readcondition.c | 12 +- src/core/ddsc/tests/reader.c | 32 +- src/core/ddsc/tests/reader_iterator.c | 16 +- src/core/ddsc/tests/register.c | 4 +- src/core/ddsc/tests/take_instance.c | 16 +- src/core/ddsc/tests/topic.c | 4 +- src/core/ddsc/tests/unregister.c | 16 +- src/core/ddsc/tests/unsupported.c | 4 +- src/core/ddsc/tests/waitset.c | 30 +- src/core/ddsc/tests/write.c | 2 +- src/core/ddsc/tests/writer.c | 4 +- src/core/ddsi/.fileids | 40 -- src/core/ddsi/src/q_thread_inlines.c | 1 - src/tools/pubsub/common.c | 1 - src/util/CMakeLists.txt | 2 +- src/util/src/ut_handleserver.c | 393 ------------------ src/util/tests/CMakeLists.txt | 18 +- src/util/tests/handleserver.c | 304 -------------- 55 files changed, 871 insertions(+), 1681 deletions(-) delete mode 100644 src/cmake/modules/FileIDs.cmake delete mode 100644 src/core/ddsc/.fileids rename src/{util/include/dds/util/ut_handleserver.h => core/ddsc/src/dds__handles.h} (58%) create mode 100644 src/core/ddsc/src/dds_handles.c delete mode 100644 src/core/ddsc/tests/file_id.c delete mode 100644 src/core/ddsi/.fileids delete mode 100644 src/util/src/ut_handleserver.c delete mode 100644 src/util/tests/handleserver.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 19b0515..52a062e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -152,7 +152,6 @@ if(NOT (${USE_SANITIZER} STREQUAL "none")) link_libraries(-fno-omit-frame-pointer -fsanitize=${USE_SANITIZER}) endif() -include(FileIDs) include(GNUInstallDirs) include(AnalyzeBuild) # Include Coverage before CTest so that COVERAGE_COMMAND can be modified diff --git a/src/cmake/modules/FileIDs.cmake b/src/cmake/modules/FileIDs.cmake deleted file mode 100644 index 5c79198..0000000 --- a/src/cmake/modules/FileIDs.cmake +++ /dev/null @@ -1,146 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# - -# To uniquely identify the origin of every error all source files must be -# assigned a pseudo unique identifier (or module). Because only 32 bits are -# available in the return code (for now) to store the sign bit (1), return -# code (4), line number (8) and file identifier, using a deterministic hash -# will likely lead to collisions. To work around this issue a static map is -# applied, which also ensures that file identifiers are persisted accross -# versions/branches. Of course one could choose to specify the module manually -# with every return, but that is tedious and error prone. - -if(FILE_IDS_INCLUDED) - return() -endif() -set(FILE_IDS_INCLUDED true) - - -# Verify syntax for all .fileids files and ensure no source file id is used -# more than once. -file(GLOB_RECURSE fils__ LIST_DIRECTORIES false "${CMAKE_SOURCE_DIR}/.fileids") - -set(ids__) -foreach(fil__ ${fils__}) - file(READ "${fil__}" lines__) - string(REGEX REPLACE "\n" ";" lines__ ${lines__}) - foreach(line__ ${lines__}) - if("${line__}" MATCHES "^[ \t]*([0-9]+)[ \t]+.*$") - set(id__ "${CMAKE_MATCH_1}") - if(${id__} IN_LIST ids__) - set(dup__ true) - message(STATUS "Id ${id__} used more than once") - else() - list(APPEND ids__ ${id__}) - endif() - elseif(NOT "${line__}" MATCHES "^[ \t]*#") - message(FATAL_ERROR "Syntax error in ${fil__}") - endif() - endforeach() -endforeach() - -if(dup__) - message(FATAL_ERROR "Duplicate ids") -endif() - -function(JOIN lst glue var) - string(REPLACE ";" "${glue}" tmp "${${lst}}") - set(${var} "${tmp}" PARENT_SCOPE) -endfunction() - -function(FILE_ID src var) # private - # .fileids files may reside in subdirectories to keep them together with the - # files they assign an identifier to, much like .gitignore files - set(dir "${CMAKE_SOURCE_DIR}") - set(parts "${src}") - string(REGEX REPLACE "[/\\]+" ";" parts "${parts}") - while(parts) - set(map "${dir}/.fileids") - join(parts "/" fil) - list(APPEND maps "${map}^${fil}") - list(GET parts 0 part) - list(REMOVE_AT parts 0) - set(dir "${dir}/${part}") - endwhile() - - set(id) - foreach(entry ${maps}) - string(REPLACE "^" ";" entry "${entry}") - list(GET entry 0 map) - list(GET entry 1 fil) - if(EXISTS "${map}") - file(READ "${map}" contents) - string(REGEX REPLACE "\n" ";" lines "${contents}") - - foreach(line ${lines}) - if("${line}" MATCHES "^[ \t]*([0-9]+)[ \t]+(.*)$") - set(id "${CMAKE_MATCH_1}") - string(STRIP "${CMAKE_MATCH_2}" expr) - if("${fil}" STREQUAL "${expr}") - set(${var} ${id} PARENT_SCOPE) - return() - endif() - elseif(NOT "${line}" MATCHES "^[ \t]*#") - message(FATAL_ERROR "Syntax error in ${map}") - endif() - endforeach() - endif() - endforeach() -endfunction() - -# Source file properties are visible only to targets added in the same -# directory (CMakeLists.txt). -# https://cmake.org/cmake/help/latest/command/set_source_files_properties.html -function(SET_TARGET_FILE_IDS tgt) - get_target_property(external ${tgt} IMPORTED) - get_target_property(alias ${tgt} ALIASED_TARGET) - string(LENGTH "${CMAKE_SOURCE_DIR}" len) - math(EXPR len "${len} + 1") # strip slash following source dir too - - if((NOT external) AND (NOT alias)) - get_target_property(srcs ${tgt} SOURCES) - get_target_property(src_dir ${tgt} SOURCE_DIR) - foreach(src ${srcs}) - set(id) - if(IS_ABSOLUTE "${src}") - set(fil "${src}") - else() - set(fil "${src_dir}/${src}") - endif() - - get_filename_component(fil "${fil}" ABSOLUTE) - - string(FIND "${fil}" "${CMAKE_SOURCE_DIR}" pos) - if(${pos} EQUAL 0) - string(SUBSTRING "${fil}" ${len} -1 rel) - file_id("${rel}" id) - endif() - - if(id) - if(("${source_file_id_${id}}" STREQUAL "") OR - ("${source_file_id_${id}}" STREQUAL "${rel}")) - set("source_file_id_${id}" "${rel}" CACHE INTERNAL "") - set_source_files_properties( - "${src}" PROPERTIES COMPILE_DEFINITIONS __FILE_ID__=${id}) - else() - message(FATAL_ERROR "Same file id for ${rel} and ${source_file_id_${id}}") - endif() - else() - get_filename_component(ext "${rel}" EXT) - if (NOT "${ext}" MATCHES "\.h*") - message(FATAL_ERROR "No source file id for ${rel}") - endif() - endif() - endforeach() - endif() -endfunction() - diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 39a580f..071d6e6 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -64,8 +64,6 @@ target_include_directories( # SOVERSION should increase on incompatible ABI change set_target_properties(ddsc PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) -set_target_file_ids(ddsc) - # Create a pseudo-target that other targets (i.e. examples, tests) can depend # on and can also be provided as import-target by a package-file when building # those targets outside the regular Cyclone build-tree (i.e. the installed tree) diff --git a/src/core/ddsc/.fileids b/src/core/ddsc/.fileids deleted file mode 100644 index f24df98..0000000 --- a/src/core/ddsc/.fileids +++ /dev/null @@ -1,33 +0,0 @@ -# ddsc sources -40 src/dds_alloc.c -41 src/dds_coherent.c -42 src/dds_iid.c -43 src/dds_participant.c -44 src/dds_reader.c -45 src/dds_thread.c -46 src/dds_writer.c -47 src/dds_init.c -48 src/dds_publisher.c -49 src/dds_rhc.c -50 src/dds_time.c -51 src/q_osplser.c -52 src/dds_domain.c -53 src/dds_instance.c -54 src/dds_qos.c -55 src/dds_tkmap.c -56 src/dds_entity.c -57 src/dds_key.c -58 src/dds_querycond.c -59 src/dds_topic.c -60 src/dds_err.c -61 src/dds_listener.c -62 src/dds_read.c -63 src/dds_stream.c -64 src/dds_waitset.c -65 src/dds_log.c -66 src/dds_readcond.c -67 src/dds_subscriber.c -68 src/dds_write.c -70 src/dds_builtin.c -72 src/dds_guardcond.c -73 src/dds_whc.c diff --git a/src/core/ddsc/CMakeLists.txt b/src/core/ddsc/CMakeLists.txt index 5b3658e..a97ccda 100644 --- a/src/core/ddsc/CMakeLists.txt +++ b/src/core/ddsc/CMakeLists.txt @@ -22,6 +22,7 @@ PREPEND(srcs_ddsc "${CMAKE_CURRENT_LIST_DIR}/src" dds_domain.c dds_instance.c dds_qos.c + dds_handles.c dds_entity.c dds_key.c dds_querycond.c @@ -54,6 +55,7 @@ PREPEND(hdrs_private_ddsc "${CMAKE_CURRENT_LIST_DIR}/src" dds__alloc.h dds__builtin.h dds__domain.h + dds__handles.h dds__entity.h dds__init.h dds__key.h diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index 124a2e6..3d5dc42 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -69,6 +69,9 @@ struct ddsi_serdata; */ DDS_EXPORT dds_domainid_t dds_domain_default (void); + +#define DDS_MIN_PSEUDO_HANDLE ((dds_entity_t) 0x7fff0000) + /* @defgroup builtintopic_constants Convenience constants for referring to builtin topics * * These constants can be used in place of an actual dds_topic_t, when creating @@ -76,10 +79,10 @@ DDS_EXPORT dds_domainid_t dds_domain_default (void); * * @{ */ -extern DDS_EXPORT const dds_entity_t DDS_BUILTIN_TOPIC_DCPSPARTICIPANT; -extern DDS_EXPORT const dds_entity_t DDS_BUILTIN_TOPIC_DCPSTOPIC; -extern DDS_EXPORT const dds_entity_t DDS_BUILTIN_TOPIC_DCPSPUBLICATION; -extern DDS_EXPORT const dds_entity_t DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION; +#define DDS_BUILTIN_TOPIC_DCPSPARTICIPANT ((dds_entity_t) (DDS_MIN_PSEUDO_HANDLE + 1)) +#define DDS_BUILTIN_TOPIC_DCPSTOPIC ((dds_entity_t) (DDS_MIN_PSEUDO_HANDLE + 2)) +#define DDS_BUILTIN_TOPIC_DCPSPUBLICATION ((dds_entity_t) (DDS_MIN_PSEUDO_HANDLE + 3)) +#define DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION ((dds_entity_t) (DDS_MIN_PSEUDO_HANDLE + 4)) /** @}*/ /** @name Communication Status definitions diff --git a/src/core/ddsc/include/dds/ddsc/dds_public_impl.h b/src/core/ddsc/include/dds/ddsc/dds_public_impl.h index 923ea24..d031570 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_impl.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_impl.h @@ -96,7 +96,6 @@ dds_topic_descriptor_t; #define DDS_HANDLE_NIL 0 #define DDS_ENTITY_NIL 0 -#define DDS_ENTITY_KIND_MASK (0x7F000000) /* Should be same as UT_HANDLE_KIND_MASK. */ typedef enum dds_entity_kind { DDS_KIND_DONTCARE = 0x00000000, @@ -109,8 +108,7 @@ typedef enum dds_entity_kind DDS_KIND_COND_READ = 0x07000000, DDS_KIND_COND_QUERY = 0x08000000, DDS_KIND_COND_GUARD = 0x09000000, - DDS_KIND_WAITSET = 0x0A000000, - DDS_KIND_INTERNAL = 0x0B000000, + DDS_KIND_WAITSET = 0x0A000000 } dds_entity_kind_t; diff --git a/src/core/ddsc/src/dds__entity.h b/src/core/ddsc/src/dds__entity.h index 77ae66b..992c15a 100644 --- a/src/core/ddsc/src/dds__entity.h +++ b/src/core/ddsc/src/dds__entity.h @@ -53,6 +53,10 @@ dds_entity_add_ref_nolock(dds_entity *e); qualifier_ dds_retcode_t type_##_lock (dds_entity_t hdl, type_ **x); \ qualifier_ void type_##_unlock (type_ *x); +DDS_EXPORT inline dds_entity *dds_entity_from_handle_link (struct dds_handle_link *hdllink) { + return (dds_entity *) ((char *) hdllink - offsetof (struct dds_entity, m_hdllink)); +} + DDS_EXPORT inline bool dds_entity_is_enabled (const dds_entity *e) { return (e->m_flags & DDS_ENTITY_ENABLED) != 0; } @@ -68,11 +72,7 @@ DDS_EXPORT inline bool dds_entity_status_match (const dds_entity *e, uint32_t t) } DDS_EXPORT inline dds_entity_kind_t dds_entity_kind (const dds_entity *e) { - return (dds_entity_kind_t) (e->m_hdl & DDS_ENTITY_KIND_MASK); -} - -DDS_EXPORT inline dds_entity_kind_t dds_entity_kind_from_handle (dds_entity_t hdl) { - return (hdl > 0) ? (dds_entity_kind_t) (hdl & DDS_ENTITY_KIND_MASK) : DDS_KIND_DONTCARE; + return e->m_kind; } DDS_EXPORT void dds_entity_status_signal (dds_entity *e); @@ -80,7 +80,9 @@ DDS_EXPORT void dds_entity_status_signal (dds_entity *e); DDS_EXPORT void dds_entity_invoke_listener (const dds_entity *entity, enum dds_status_id which, const void *vst); DDS_EXPORT dds_retcode_t -dds_valid_hdl(dds_entity_t hdl, dds_entity_kind_t kind); +dds_entity_claim ( + dds_entity_t hdl, + dds_entity **eptr); DDS_EXPORT dds_retcode_t dds_entity_lock( @@ -118,14 +120,22 @@ dds_delete_impl( dds_entity_t entity, bool keep_if_explicit); -DDS_EXPORT const char * -dds__entity_kind_str( - dds_entity_t e); - DDS_EXPORT dds_domain * dds__entity_domain( dds_entity* e); +DDS_EXPORT dds_return_t +dds_generic_unimplemented_operation_manykinds( + dds_entity_t handle, + size_t nkinds, + const dds_entity_kind_t *kinds); + +DDS_EXPORT dds_return_t +dds_generic_unimplemented_operation( + dds_entity_t handle, + dds_entity_kind_t kind); + + #if defined (__cplusplus) } #endif diff --git a/src/core/ddsc/src/dds__err.h b/src/core/ddsc/src/dds__err.h index 917051a..a54be27 100644 --- a/src/core/ddsc/src/dds__err.h +++ b/src/core/ddsc/src/dds__err.h @@ -20,20 +20,7 @@ extern "C" { #endif -/* To construct return status - * Use '+' instead of '|'. Otherwise, the SAL checking doesn't - * understand when a return value is negative or positive and - * complains a lot about "A successful path through the function - * does not set the named _Out_ parameter." */ -#if !defined(__FILE_ID__) -#error "__FILE_ID__ not defined" -#endif - -#define DDS__FILE_ID__ (((__FILE_ID__ & 0x1ff)) << 22) -#define DDS__LINE__ ((__LINE__ & 0x3fff) << 8) - -#define DDS_ERRNO(err) \ - (assert(err > DDS_RETCODE_OK), -(DDS__FILE_ID__ + DDS__LINE__ + (err))) +#define DDS_ERRNO(err) (assert(err > DDS_RETCODE_OK), -(err)) #if defined (__cplusplus) } diff --git a/src/util/include/dds/util/ut_handleserver.h b/src/core/ddsc/src/dds__handles.h similarity index 58% rename from src/util/include/dds/util/ut_handleserver.h rename to src/core/ddsc/src/dds__handles.h index f0a91e0..7ceee26 100644 --- a/src/util/include/dds/util/ut_handleserver.h +++ b/src/core/ddsc/src/dds__handles.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -9,19 +9,20 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#ifndef UT_HANDLESERVER_H -#define UT_HANDLESERVER_H +#ifndef DDS__HANDLES_H +#define DDS__HANDLES_H -#include -#include - -#include "dds/export.h" #include "dds/ddsrt/time.h" +#include "dds/ddsrt/retcode.h" +#include "dds/ddsrt/atomics.h" +#include "dds/dds.h" #if defined (__cplusplus) extern "C" { #endif +struct dds_entity; + /******************************************************************************************** * * TODO CHAM-138: Header file improvements @@ -51,46 +52,8 @@ extern "C" { */ -/* - * Some error return values. - */ -typedef enum ut_handle_retcode_t { - UT_HANDLE_OK = 0, - UT_HANDLE_ERROR = -1, /* General error. */ - UT_HANDLE_CLOSED = -2, /* Handle has been previously close. */ - UT_HANDLE_DELETED = -3, /* Handle has been previously deleted. */ - UT_HANDLE_INVALID = -4, /* Handle is not a valid handle. */ - UT_HANDLE_UNEQUAL_KIND = -5, /* Handle does not contain expected kind. */ - UT_HANDLE_TIMEOUT = -6, /* Operation timed out. */ - UT_HANDLE_OUT_OF_RESOURCES = -7, /* Action isn't possible because of limited resources. */ - UT_HANDLE_NOT_INITALIZED = -8 /* Not initialized. */ -} ut_handle_retcode_t; - -/* - * The 32 bit handle - * | bits | # values | description | - * -------------------------------------------------------------------------------------- - * | 31 | 2 | positive/negative (negative can be used to indicate errors) | - * | 24-30 | 127 | handle kind (value determined by client) | - * | 0-23 | 16.777.215 | index or hash (maintained by the handleserver) | - * - * When the handle is negative, it'll contain a ut_handle_retcode_t error value. - * - * FYI: the entity id within DDSI is also 24 bits... - */ -typedef int32_t ut_handle_t; - -/* - * Handle bits - * +kkk kkkk iiii iiii iiii iiii iiii iiii - * 31| | 24| 0| - */ -#define UT_HANDLE_SIGN_MASK (0x80000000) -#define UT_HANDLE_KIND_MASK (0x7F000000) -#define UT_HANDLE_IDX_MASK (0x00FFFFFF) - -#define UT_HANDLE_DONTCARE_KIND (0) +typedef int32_t dds_handle_t; /* * The handle link type. @@ -106,14 +69,16 @@ typedef int32_t ut_handle_t; * This handlelink is invalid after the related handle is deleted and should * never be used afterwards. */ -struct ut_handlelink; - +struct dds_handle_link { + dds_handle_t hdl; + ddsrt_atomic_uint32_t cnt_flags; +}; /* * Initialize handleserver singleton. */ -DDS_EXPORT ut_handle_retcode_t -ut_handleserver_init(void); +DDS_EXPORT dds_return_t +dds_handle_server_init(void (*free_via_gc) (void *x)); /* @@ -121,7 +86,7 @@ ut_handleserver_init(void); * The handleserver is destroyed when fini() is called as often as init(). */ DDS_EXPORT void -ut_handleserver_fini(void); +dds_handle_server_fini(void); /* @@ -142,8 +107,9 @@ ut_handleserver_fini(void); * Valid handle when returned value is positive. * Otherwise negative handle is returned. */ -DDS_EXPORT ut_handle_t -ut_handle_create(int32_t kind, void *arg); +DDS_EXPORT dds_handle_t +dds_handle_create( + struct dds_handle_link *link); /* @@ -153,7 +119,8 @@ ut_handle_create(int32_t kind, void *arg); * This is a noop on an already closed handle. */ DDS_EXPORT void -ut_handle_close(ut_handle_t hdl, struct ut_handlelink *link); +dds_handle_close( + struct dds_handle_link *link); /* @@ -165,23 +132,10 @@ ut_handle_close(ut_handle_t hdl, struct ut_handlelink *link); * It will delete the information when there are no more active claims. It'll * block when necessary to wait for all possible claims to be released. */ -DDS_EXPORT ut_handle_retcode_t -ut_handle_delete( - ut_handle_t hdl, - struct ut_handlelink *link, - dds_time_t timeout); - - -/* - * Returns the status the given handle; valid/deleted/closed/etc. - * - * Returns OK when valid. - */ -ut_handle_retcode_t -ut_handle_status( - ut_handle_t hdl, - struct ut_handlelink *link, - int32_t kind); +DDS_EXPORT int32_t +dds_handle_delete( + struct dds_handle_link *link, + dds_time_t timeout); /* @@ -190,21 +144,23 @@ ut_handle_status( * * Returns OK when succeeded. */ -DDS_EXPORT ut_handle_retcode_t -ut_handle_claim( - ut_handle_t hdl, - struct ut_handlelink *link, - int32_t kind, - void **arg); +DDS_EXPORT int32_t +dds_handle_claim( + dds_handle_t hdl, + struct dds_handle_link **entity); + + +DDS_EXPORT void +dds_handle_claim_inc( + struct dds_handle_link *link); /* * The active claims count is decreased. */ DDS_EXPORT void -ut_handle_release( - ut_handle_t hdl, - struct ut_handlelink *link); +dds_handle_release( + struct dds_handle_link *link); /* @@ -217,21 +173,12 @@ ut_handle_release( * possible. */ DDS_EXPORT bool -ut_handle_is_closed( - ut_handle_t hdl, - struct ut_handlelink *link); +dds_handle_is_closed( + struct dds_handle_link *link); -/* - * This will get the link of the handle, which can be used for performance - * increase. - */ -DDS_EXPORT struct ut_handlelink* -ut_handle_get_link( - ut_handle_t hdl); - #if defined (__cplusplus) } #endif -#endif /* UT_HANDLESERVER_H */ +#endif /* DDS__HANDLES_H */ diff --git a/src/core/ddsc/src/dds__publisher.h b/src/core/ddsc/src/dds__publisher.h index 61427df..517abff 100644 --- a/src/core/ddsc/src/dds__publisher.h +++ b/src/core/ddsc/src/dds__publisher.h @@ -13,11 +13,14 @@ #define _DDS_PUBLISHER_H_ #include "dds/dds.h" +#include "dds__entity.h" #if defined (__cplusplus) extern "C" { #endif +DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_publisher, DDS_KIND_PUBLISHER) + dds_return_t dds_publisher_begin_coherent (dds_entity_t e); dds_return_t dds_publisher_end_coherent (dds_entity_t e); diff --git a/src/core/ddsc/src/dds__subscriber.h b/src/core/ddsc/src/dds__subscriber.h index 0609b03..c104255 100644 --- a/src/core/ddsc/src/dds__subscriber.h +++ b/src/core/ddsc/src/dds__subscriber.h @@ -13,12 +13,13 @@ #define _DDS_SUBSCRIBER_H_ #include "dds/dds.h" +#include "dds__entity.h" #if defined (__cplusplus) extern "C" { #endif -struct dds_entity; +DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_subscriber, DDS_KIND_SUBSCRIBER) dds_entity_t dds__create_subscriber_l( diff --git a/src/core/ddsc/src/dds__types.h b/src/core/ddsc/src/dds__types.h index 75c53b8..187aee4 100644 --- a/src/core/ddsc/src/dds__types.h +++ b/src/core/ddsc/src/dds__types.h @@ -18,7 +18,7 @@ #include "dds/ddsrt/sync.h" #include "dds/ddsi/q_rtps.h" #include "dds/util/ut_avl.h" -#include "dds/util/ut_handleserver.h" +#include "dds__handles.h" #if defined (__cplusplus) extern "C" { @@ -125,7 +125,8 @@ dds_entity_observer; typedef struct dds_entity { - ut_handle_t m_hdl; + struct dds_handle_link m_hdllink; + dds_entity_kind_t m_kind; dds_entity_deriver m_deriver; uint32_t m_refc; struct dds_entity * m_next; @@ -147,8 +148,6 @@ typedef struct dds_entity uint32_t m_status_enable; uint32_t m_cb_count; dds_entity_observer *m_observers; - - struct ut_handlelink *m_hdllink; } dds_entity; diff --git a/src/core/ddsc/src/dds_coherent.c b/src/core/ddsc/src/dds_coherent.c index 7f35660..6123a47 100644 --- a/src/core/ddsc/src/dds_coherent.c +++ b/src/core/ddsc/src/dds_coherent.c @@ -21,52 +21,14 @@ dds_return_t dds_begin_coherent( dds_entity_t entity) { - dds_return_t ret; - - switch(dds_entity_kind_from_handle(entity)) { - case DDS_KIND_READER: - case DDS_KIND_WRITER: - /* Invoking on a writer/reader behaves as if invoked on - * its parent publisher/subscriber. */ - ret = dds_begin_coherent(dds_get_parent(entity)); - break; - case DDS_KIND_PUBLISHER: - ret = dds_publisher_begin_coherent(entity); - break; - case DDS_KIND_SUBSCRIBER: - ret = dds_subscriber_begin_coherent(entity); - break; - default: - DDS_ERROR("Given entity can not control coherency\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - break; - } - return ret; + static const dds_entity_kind_t kinds[] = { DDS_KIND_READER, DDS_KIND_WRITER, DDS_KIND_PUBLISHER, DDS_KIND_SUBSCRIBER }; + return dds_generic_unimplemented_operation_manykinds (entity, sizeof (kinds) / sizeof (kinds[0]), kinds); } dds_return_t dds_end_coherent( dds_entity_t entity) { - dds_return_t ret; - - switch(dds_entity_kind_from_handle(entity)) { - case DDS_KIND_READER: - case DDS_KIND_WRITER: - /* Invoking on a writer/reader behaves as if invoked on - * its parent publisher/subscriber. */ - ret = dds_end_coherent(dds_get_parent(entity)); - break; - case DDS_KIND_PUBLISHER: - ret = dds_publisher_end_coherent(entity); - break; - case DDS_KIND_SUBSCRIBER: - ret = dds_subscriber_end_coherent(entity); - break; - default: - DDS_ERROR("Given entity can not control coherency\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - break; - } - return ret; + static const dds_entity_kind_t kinds[] = { DDS_KIND_READER, DDS_KIND_WRITER, DDS_KIND_PUBLISHER, DDS_KIND_SUBSCRIBER }; + return dds_generic_unimplemented_operation_manykinds (entity, sizeof (kinds) / sizeof (kinds[0]), kinds); } diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index cbb34d3..f8a4e14 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -22,16 +22,11 @@ #include "dds__err.h" #include "dds/version.h" -/* Sanity check. */ -#if DDS_ENTITY_KIND_MASK != UT_HANDLE_KIND_MASK -#error "DDS_ENTITY_KIND_MASK != UT_HANDLE_KIND_MASK" -#endif - +extern inline dds_entity *dds_entity_from_handle_link (struct dds_handle_link *hdllink); extern inline bool dds_entity_is_enabled (const dds_entity *e); extern inline void dds_entity_status_reset (dds_entity *e, uint32_t t); extern inline bool dds_entity_status_match (const dds_entity *e, uint32_t t); extern inline dds_entity_kind_t dds_entity_kind (const dds_entity *e); -extern inline dds_entity_kind_t dds_entity_kind_from_handle (dds_entity_t hdl); static void dds_entity_observers_signal (dds_entity *observed, uint32_t status); static void dds_entity_observers_delete (dds_entity *observed); @@ -71,10 +66,13 @@ static dds_entity *dds__nonself_parent (dds_entity *e) dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind_t kind, dds_qos_t *qos, const dds_listener_t *listener, uint32_t mask) { + dds_handle_t handle; + assert ((kind == DDS_KIND_PARTICIPANT) == (parent == NULL)); assert (e); e->m_refc = 1; + e->m_kind = kind; e->m_qos = qos; e->m_cb_count = 0; e->m_observers = NULL; @@ -116,29 +114,11 @@ dds_entity_t dds_entity_init (dds_entity *e, dds_entity *parent, dds_entity_kind ddsrt_mutex_unlock (&e->m_observers_lock); } - e->m_hdllink = NULL; - e->m_hdl = ut_handle_create ((int32_t) kind, e); - if (e->m_hdl > 0) - { - e->m_hdllink = ut_handle_get_link (e->m_hdl); - assert(e->m_hdllink); - } - else - { - if (e->m_hdl == UT_HANDLE_OUT_OF_RESOURCES) { - DDS_ERROR ("Can not create new entity; too many where created previously\n"); - e->m_hdl = DDS_ERRNO (DDS_RETCODE_OUT_OF_RESOURCES); - } else if (e->m_hdl == UT_HANDLE_NOT_INITALIZED) { - DDS_ERROR (DDS_PROJECT_NAME" is not yet initialized. Please create a participant before executing an other method\n"); - e->m_hdl = DDS_ERRNO (DDS_RETCODE_PRECONDITION_NOT_MET); - } else { - DDS_ERROR ("An internal error has occurred\n"); - e->m_hdl = DDS_ERRNO (DDS_RETCODE_ERROR); - } - } + if ((handle = dds_handle_create (&e->m_hdllink)) <= 0) + return (dds_entity_t) handle; - /* An ut_handle_t is directly used as dds_entity_t. */ - return (dds_entity_t) e->m_hdl; + /* An dds_handle_t is directly used as dds_entity_t. */ + return (dds_entity_t) handle; } dds_return_t dds_delete (dds_entity_t entity) @@ -164,7 +144,7 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) dds_return_t ret; dds_retcode_t rc; - rc = dds_entity_lock (entity, UT_HANDLE_DONTCARE_KIND, &e); + rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e); if (rc != DDS_RETCODE_OK) { DDS_TRACE ("dds_delete_impl: error on locking entity %"PRIu32" keep_if_explicit %d\n", entity, (int) keep_if_explicit); @@ -183,7 +163,7 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) return DDS_RETCODE_OK; } - ut_handle_close (e->m_hdl, e->m_hdllink); + dds_handle_close (&e->m_hdllink); ddsrt_mutex_lock (&e->m_observers_lock); while (e->m_cb_count > 0) ddsrt_cond_wait (&e->m_observers_cond, &e->m_observers_lock); @@ -219,7 +199,7 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) { next = next_non_topic_child (child->m_next); /* This will probably delete the child entry from the current children's list */ - ret = dds_delete (child->m_hdl); + ret = dds_delete (child->m_hdllink.hdl); child = next; } child = e->m_children; @@ -227,7 +207,7 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) { next = child->m_next; assert (dds_entity_kind (child) == DDS_KIND_TOPIC); - ret = dds_delete (child->m_hdl); + ret = dds_delete (child->m_hdllink.hdl); child = next; } if (ret == DDS_RETCODE_OK && e->m_deriver.close) @@ -239,11 +219,11 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) if (ret == DDS_RETCODE_OK) { - /* The ut_handle_delete will wait until the last active claim on that handle + /* The dds_handle_delete will wait until the last active claim on that handle * is released. It is possible that this last release will be done by a thread * that was kicked during the close(). */ - if (ut_handle_delete (e->m_hdl, e->m_hdllink, timeout) != UT_HANDLE_OK) - return DDS_ERRNO (DDS_RETCODE_TIMEOUT); + if ((ret = dds_handle_delete (&e->m_hdllink, timeout)) != DDS_RETCODE_OK) + return ret; } if (ret == DDS_RETCODE_OK) @@ -301,7 +281,7 @@ dds_entity_t dds_get_parent (dds_entity_t entity) hdl = DDS_ENTITY_NIL; else { - hdl = parent->m_hdl; + hdl = parent->m_hdllink.hdl; dds_set_explicit (hdl); } dds_entity_unlock (e); @@ -317,7 +297,7 @@ dds_entity_t dds_get_participant (dds_entity_t entity) return DDS_ERRNO (rc); else { - dds_entity_t hdl = e->m_participant->m_hdl; + dds_entity_t hdl = e->m_participant->m_hdllink.hdl; dds_entity_unlock (e); return hdl; } @@ -343,8 +323,8 @@ dds_return_t dds_get_children (dds_entity_t entity, dds_entity_t *children, size { if ((size_t) n < size) { - children[n] = iter->m_hdl; - dds_set_explicit (iter->m_hdl); + children[n] = iter->m_hdllink.hdl; + dds_set_explicit (iter->m_hdllink.hdl); } n++; iter = iter->m_next; @@ -437,65 +417,65 @@ void dds_entity_invoke_listener (const dds_entity *entity, enum dds_status_id wh { case DDS_INCONSISTENT_TOPIC_STATUS_ID: { struct dds_inconsistent_topic_status const * const st = vst; - lst->on_inconsistent_topic (entity->m_hdl, *st, lst->on_inconsistent_topic_arg); + lst->on_inconsistent_topic (entity->m_hdllink.hdl, *st, lst->on_inconsistent_topic_arg); break; } case DDS_REQUESTED_DEADLINE_MISSED_STATUS_ID: { struct dds_requested_deadline_missed_status const * const st = vst; - lst->on_requested_deadline_missed (entity->m_hdl, *st, lst->on_requested_deadline_missed_arg); + lst->on_requested_deadline_missed (entity->m_hdllink.hdl, *st, lst->on_requested_deadline_missed_arg); break; } case DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS_ID: { struct dds_requested_incompatible_qos_status const * const st = vst; - lst->on_requested_incompatible_qos (entity->m_hdl, *st, lst->on_requested_incompatible_qos_arg); + lst->on_requested_incompatible_qos (entity->m_hdllink.hdl, *st, lst->on_requested_incompatible_qos_arg); break; } case DDS_SAMPLE_LOST_STATUS_ID: { struct dds_sample_lost_status const * const st = vst; - lst->on_sample_lost (entity->m_hdl, *st, lst->on_sample_lost_arg); + lst->on_sample_lost (entity->m_hdllink.hdl, *st, lst->on_sample_lost_arg); break; } case DDS_SAMPLE_REJECTED_STATUS_ID: { struct dds_sample_rejected_status const * const st = vst; - lst->on_sample_rejected (entity->m_hdl, *st, lst->on_sample_rejected_arg); + lst->on_sample_rejected (entity->m_hdllink.hdl, *st, lst->on_sample_rejected_arg); break; } case DDS_LIVELINESS_CHANGED_STATUS_ID: { struct dds_liveliness_changed_status const * const st = vst; - lst->on_liveliness_changed (entity->m_hdl, *st, lst->on_liveliness_changed_arg); + lst->on_liveliness_changed (entity->m_hdllink.hdl, *st, lst->on_liveliness_changed_arg); break; } case DDS_SUBSCRIPTION_MATCHED_STATUS_ID: { struct dds_subscription_matched_status const * const st = vst; - lst->on_subscription_matched (entity->m_hdl, *st, lst->on_subscription_matched_arg); + lst->on_subscription_matched (entity->m_hdllink.hdl, *st, lst->on_subscription_matched_arg); break; } case DDS_OFFERED_DEADLINE_MISSED_STATUS_ID: { struct dds_offered_deadline_missed_status const * const st = vst; - lst->on_offered_deadline_missed (entity->m_hdl, *st, lst->on_offered_deadline_missed_arg); + lst->on_offered_deadline_missed (entity->m_hdllink.hdl, *st, lst->on_offered_deadline_missed_arg); break; } case DDS_LIVELINESS_LOST_STATUS_ID: { struct dds_liveliness_lost_status const * const st = vst; - lst->on_liveliness_lost (entity->m_hdl, *st, lst->on_liveliness_lost_arg); + lst->on_liveliness_lost (entity->m_hdllink.hdl, *st, lst->on_liveliness_lost_arg); break; } case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS_ID: { struct dds_offered_incompatible_qos_status const * const st = vst; - lst->on_offered_incompatible_qos (entity->m_hdl, *st, lst->on_offered_incompatible_qos_arg); + lst->on_offered_incompatible_qos (entity->m_hdllink.hdl, *st, lst->on_offered_incompatible_qos_arg); break; } case DDS_PUBLICATION_MATCHED_STATUS_ID: { struct dds_publication_matched_status const * const st = vst; - lst->on_publication_matched (entity->m_hdl, *st, lst->on_publication_matched_arg); + lst->on_publication_matched (entity->m_hdllink.hdl, *st, lst->on_publication_matched_arg); break; } case DDS_DATA_AVAILABLE_STATUS_ID: { - lst->on_data_available (entity->m_hdl, lst->on_data_available_arg); + lst->on_data_available (entity->m_hdllink.hdl, lst->on_data_available_arg); break; } case DDS_DATA_ON_READERS_STATUS_ID: { - lst->on_data_on_readers (entity->m_hdl, lst->on_data_on_readers_arg); + lst->on_data_on_readers (entity->m_hdllink.hdl, lst->on_data_on_readers_arg); break; } } @@ -768,45 +748,36 @@ dds_return_t dds_get_instance_handle (dds_entity_t entity, dds_instance_handle_t return ret; } - -dds_retcode_t dds_valid_hdl (dds_entity_t hdl, dds_entity_kind_t kind) +dds_retcode_t dds_entity_claim (dds_entity_t hdl, dds_entity **eptr) { - ut_handle_t utr; - if ((utr = ut_handle_status (hdl, NULL, (int32_t) kind)) == UT_HANDLE_OK) - return DDS_RETCODE_OK; - else if (hdl < 0) - return DDS_RETCODE_BAD_PARAMETER; + dds_retcode_t hres; + struct dds_handle_link *hdllink; + if ((hres = dds_handle_claim (hdl, &hdllink)) != DDS_RETCODE_OK) + return hres; else { - switch (utr) - { - case UT_HANDLE_OK: - assert (0); - /* FALLS THROUGH */ - case UT_HANDLE_UNEQUAL_KIND: - return DDS_RETCODE_ILLEGAL_OPERATION; - case UT_HANDLE_INVALID: - return DDS_RETCODE_BAD_PARAMETER; - case UT_HANDLE_DELETED: - case UT_HANDLE_CLOSED: - return DDS_RETCODE_ALREADY_DELETED; - default: - return DDS_RETCODE_ERROR; - } + *eptr = dds_entity_from_handle_link (hdllink); + return DDS_RETCODE_OK; } } dds_retcode_t dds_entity_lock (dds_entity_t hdl, dds_entity_kind_t kind, dds_entity **eptr) { - ut_handle_t utr; - void *raw; + dds_retcode_t hres; + dds_entity *e; /* When the given handle already contains an error, then return that * same error to retain the original information. */ - if ((utr = ut_handle_claim (hdl, NULL, (int32_t) kind, &raw)) == UT_HANDLE_OK) + if ((hres = dds_entity_claim (hdl, &e)) != DDS_RETCODE_OK) + return hres; + else { - dds_entity *e; - *eptr = e = raw; + if (dds_entity_kind (e) != kind && kind != DDS_KIND_DONTCARE) + { + dds_handle_release (&e->m_hdllink); + return DDS_RETCODE_ILLEGAL_OPERATION; + } + ddsrt_mutex_lock (&e->m_mutex); /* FIXME: The handle could have been closed while we were waiting for the mutex -- that should be handled differently! @@ -815,41 +786,20 @@ dds_retcode_t dds_entity_lock (dds_entity_t hdl, dds_entity_kind_t kind, dds_ent (2) preventing dds_delete_impl from doing anything once the entity is being deleted. Without (1), it would be possible to add children while trying to delete them, without (2) you're looking at crashes. */ - if (ut_handle_is_closed (hdl, e->m_hdllink)) + if (dds_handle_is_closed (&e->m_hdllink)) { dds_entity_unlock (e); - return DDS_RETCODE_ALREADY_DELETED; + return DDS_RETCODE_BAD_PARAMETER; } + *eptr = e; return DDS_RETCODE_OK; } - else if (hdl < 0) - { - return DDS_RETCODE_BAD_PARAMETER; - } - else - { - switch (utr) - { - case UT_HANDLE_OK: - assert (0); - /* FALLS THROUGH */ - case UT_HANDLE_UNEQUAL_KIND: - return DDS_RETCODE_ILLEGAL_OPERATION; - case UT_HANDLE_INVALID: - return DDS_RETCODE_BAD_PARAMETER; - case UT_HANDLE_DELETED: - case UT_HANDLE_CLOSED: - return DDS_RETCODE_ALREADY_DELETED; - default: - return DDS_RETCODE_ERROR; - } - } } void dds_entity_unlock (dds_entity *e) { ddsrt_mutex_unlock (&e->m_mutex); - ut_handle_release (e->m_hdl, e->m_hdllink); + dds_handle_release (&e->m_hdllink); } dds_return_t dds_triggered (dds_entity_t entity) @@ -965,7 +915,7 @@ static void dds_entity_observers_delete (dds_entity *observed) static void dds_entity_observers_signal (dds_entity *observed, uint32_t status) { for (dds_entity_observer *idx = observed->m_observers; idx; idx = idx->m_next) - idx->m_cb (idx->m_observer, observed->m_hdl, status); + idx->m_cb (idx->m_observer, observed->m_hdllink.hdl, status); } void dds_entity_status_signal (dds_entity *e) @@ -996,19 +946,19 @@ dds_entity_t dds_get_topic (dds_entity_t entity) { case DDS_KIND_READER: { dds_reader *rd = (dds_reader *) e; - hdl = rd->m_topic->m_entity.m_hdl; + hdl = rd->m_topic->m_entity.m_hdllink.hdl; break; } case DDS_KIND_WRITER: { dds_writer *wr = (dds_writer *) e; - hdl = wr->m_topic->m_entity.m_hdl; + hdl = wr->m_topic->m_entity.m_hdllink.hdl; break; } case DDS_KIND_COND_READ: case DDS_KIND_COND_QUERY: { assert (dds_entity_kind (e->m_parent) == DDS_KIND_READER); dds_reader *rd = (dds_reader *) e->m_parent; - hdl = rd->m_topic->m_entity.m_hdl; + hdl = rd->m_topic->m_entity.m_hdllink.hdl; break; } default: { @@ -1020,21 +970,32 @@ dds_entity_t dds_get_topic (dds_entity_t entity) return hdl; } -const char *dds__entity_kind_str (dds_entity_t e) +dds_return_t dds_generic_unimplemented_operation_manykinds (dds_entity_t handle, size_t nkinds, const dds_entity_kind_t *kinds) { - if (e <= 0) - return "(ERROR)"; - switch (e & DDS_ENTITY_KIND_MASK) + dds_entity *e; + dds_retcode_t ret; + if ((ret = dds_entity_claim (handle, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (ret); + else { - case DDS_KIND_TOPIC: return "Topic"; - case DDS_KIND_PARTICIPANT: return "Participant"; - case DDS_KIND_READER: return "Reader"; - case DDS_KIND_WRITER: return "Writer"; - case DDS_KIND_SUBSCRIBER: return "Subscriber"; - case DDS_KIND_PUBLISHER: return "Publisher"; - case DDS_KIND_COND_READ: return "ReadCondition"; - case DDS_KIND_COND_QUERY: return "QueryCondition"; - case DDS_KIND_WAITSET: return "WaitSet"; - default: return "(INVALID_ENTITY)"; + const dds_entity_kind_t actual = dds_entity_kind (e); + ret = DDS_RETCODE_ILLEGAL_OPERATION; + for (size_t i = 0; i < nkinds; i++) + { + if (kinds[i] == actual) + { + /* If the handle happens to be for an entity of the right kind, return unsupported */ + ret = DDS_RETCODE_UNSUPPORTED; + break; + } + } + dds_handle_release (&e->m_hdllink); + return DDS_ERRNO (ret); } } + +dds_return_t dds_generic_unimplemented_operation (dds_entity_t handle, dds_entity_kind_t kind) +{ + return dds_generic_unimplemented_operation_manykinds (handle, 1, &kind); +} + diff --git a/src/core/ddsc/src/dds_guardcond.c b/src/core/ddsc/src/dds_guardcond.c index c1e289a..c4feee0 100644 --- a/src/core/ddsc/src/dds_guardcond.c +++ b/src/core/ddsc/src/dds_guardcond.c @@ -43,7 +43,7 @@ dds_return_t dds_set_guardcondition (dds_entity_t condition, bool triggered) dds_retcode_t rc; if ((rc = dds_guardcond_lock (condition, &gcond)) != DDS_RETCODE_OK) - return DDS_ERRNO (dds_valid_hdl (condition, DDS_KIND_COND_GUARD)); + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); else { ddsrt_mutex_lock (&gcond->m_entity.m_observers_lock); @@ -67,7 +67,7 @@ dds_return_t dds_read_guardcondition (dds_entity_t condition, bool *triggered) *triggered = false; if ((rc = dds_guardcond_lock (condition, &gcond)) != DDS_RETCODE_OK) - return DDS_ERRNO (dds_valid_hdl (condition, DDS_KIND_COND_GUARD)); + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); else { ddsrt_mutex_lock (&gcond->m_entity.m_observers_lock); @@ -88,7 +88,7 @@ dds_return_t dds_take_guardcondition (dds_entity_t condition, bool *triggered) *triggered = false; if ((rc = dds_guardcond_lock (condition, &gcond)) != DDS_RETCODE_OK) - return DDS_ERRNO (dds_valid_hdl (condition, DDS_KIND_COND_GUARD)); + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); else { ddsrt_mutex_lock (&gcond->m_entity.m_observers_lock); diff --git a/src/core/ddsc/src/dds_handles.c b/src/core/ddsc/src/dds_handles.c new file mode 100644 index 0000000..5e4acd3 --- /dev/null +++ b/src/core/ddsc/src/dds_handles.c @@ -0,0 +1,267 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include "dds/ddsrt/time.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/random.h" +#include "dds/util/ut_hopscotch.h" +#include "dds/ddsi/q_thread.h" +#include "dds__handles.h" +#include "dds__types.h" +#include "dds__err.h" + +/* FIXME: this code isn't really correct when USE_CHH is set: + - the DDS entity code doesn't really play by the awake/asleep mechanism + - there is no provision in the code for a handle being deleted concurrent to a lookup, + that is, deleting handle links should also go through the GC + entity framework needs a fair bit of rewriting anyway ... */ +#define USE_CHH 0 + +#define HDL_FLAG_CLOSED (0x80000000u) +#define HDL_COUNT_MASK (0x00ffffffu) + +/* Maximum number of handles is INT32_MAX - 1, but as the allocator relies on a + random generator for finding a free one, the time spent in the dds_handle_create + increases with an increasing number of handles. 16M handles seems likely to be + enough and makes the likely cost of allocating a new handle somewhat more + reasonable */ +#define MAX_HANDLES (INT32_MAX / 128) + +struct dds_handle_server { +#if USE_CHH + struct ut_chh *ht; +#else + struct ut_hh *ht; +#endif + size_t count; + ddsrt_mutex_t lock; + ddsrt_cond_t cond; +}; + +static struct dds_handle_server handles; + +static uint32_t handle_hash (const void *va) +{ + /* handles are already pseudo-random numbers, so not much point in hashing it again */ + const struct dds_handle_link *a = va; + return (uint32_t) a->hdl; +} + +static int handle_equal (const void *va, const void *vb) +{ + const struct dds_handle_link *a = va; + const struct dds_handle_link *b = vb; + return a->hdl == b->hdl; +} + +dds_return_t dds_handle_server_init (void (*free_via_gc) (void *x)) +{ +#if USE_CHH + handles.ht = ut_chhNew (128, handle_hash, handle_equal, free_via_gc); +#else + handles.ht = ut_hhNew (128, handle_hash, handle_equal); + (void) free_via_gc; +#endif + handles.count = 0; + ddsrt_mutex_init (&handles.lock); + ddsrt_cond_init (&handles.cond); + return DDS_RETCODE_OK; +} + +void dds_handle_server_fini (void) +{ +#if USE_CHH +#ifndef NDEBUG + struct ut_chhIter it; + assert (ut_chhIterFirst (handles.ht, &it) == NULL); +#endif + ut_chhFree (handles.ht); +#else /* USE_CHH */ +#ifndef NDEBUG + struct ut_hhIter it; + assert (ut_hhIterFirst (handles.ht, &it) == NULL); +#endif + ut_hhFree (handles.ht); +#endif /* USE_CHH */ + ddsrt_cond_destroy (&handles.cond); + ddsrt_mutex_destroy (&handles.lock); + handles.ht = NULL; +} + +#if USE_CHH +static bool hhadd (struct ut_chh *ht, void *elem) { return ut_chhAdd (ht, elem); } +#else +static bool hhadd (struct ut_hh *ht, void *elem) { return ut_hhAdd (ht, elem); } +#endif +static dds_handle_t dds_handle_create_int (struct dds_handle_link *link) +{ + ddsrt_atomic_st32 (&link->cnt_flags, 0); + do { + do { + link->hdl = (int32_t) (ddsrt_random () & INT32_MAX); + } while (link->hdl == 0 || link->hdl >= DDS_MIN_PSEUDO_HANDLE); + } while (!hhadd (handles.ht, link)); + return link->hdl; +} + +dds_handle_t dds_handle_create (struct dds_handle_link *link) +{ + dds_handle_t ret; +#if USE_CHH + struct thread_state1 * const self = lookup_thread_state (); + const bool asleep = vtime_asleep_p (self->vtime); + if (asleep) + thread_state_awake (self); +#endif + ddsrt_mutex_lock (&handles.lock); + if (handles.count == MAX_HANDLES) + { + ddsrt_mutex_unlock (&handles.lock); + ret = DDS_ERRNO (DDS_RETCODE_OUT_OF_RESOURCES); + } + else + { + handles.count++; +#if USE_CHH + ddsrt_mutex_unlock (&handles.lock); + ret = dds_handle_create_int (link); +#else + ret = dds_handle_create_int (link); + ddsrt_mutex_unlock (&handles.lock); +#endif + assert (ret > 0); + } +#if USE_CHH + if (asleep) + thread_state_asleep (self); +#endif + return ret; +} + +void dds_handle_close (struct dds_handle_link *link) +{ + ddsrt_atomic_or32 (&link->cnt_flags, HDL_FLAG_CLOSED); +} + +int32_t dds_handle_delete (struct dds_handle_link *link, dds_duration_t timeout) +{ + assert (ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_FLAG_CLOSED); + + ddsrt_mutex_lock (&handles.lock); + if ((ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_COUNT_MASK) != 0) + { + /* FIXME: */ + const dds_time_t abstimeout = dds_time () + timeout; + while ((ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_COUNT_MASK) != 0) + { + if (!ddsrt_cond_waituntil (&handles.cond, &handles.lock, abstimeout)) + { + ddsrt_mutex_unlock (&handles.lock); + fprintf (stderr, "** timeout in handle_delete **\n"); + return DDS_RETCODE_TIMEOUT; + } + } + } +#if USE_CHH + struct thread_state1 * const self = lookup_thread_state (); + const bool asleep = vtime_asleep_p (self->vtime); + if (asleep) + thread_state_awake (self); + int x = ut_chhRemove (handles.ht, link); + if (asleep) + thread_state_asleep (self); +#else + int x = ut_hhRemove (handles.ht, link); +#endif + assert(x); + (void)x; + assert (handles.count > 0); + handles.count--; + ddsrt_mutex_unlock (&handles.lock); + return DDS_RETCODE_OK; +} + +int32_t dds_handle_claim (dds_handle_t hdl, struct dds_handle_link **link) +{ + struct dds_handle_link dummy = { .hdl = hdl }; + int32_t rc; + /* it makes sense to check here for initialization: the first thing any operation + (other than create_participant) does is to call dds_handle_claim on the supplied + entity, so checking here whether the library has been initialised helps avoid + crashes if someone forgets to create a participant (or allows a program to + continue after failing to create one). + + One could check that the handle is > 0, but that would catch fewer errors + without any advantages. */ + if (handles.ht == NULL) + return DDS_RETCODE_PRECONDITION_NOT_MET; + +#if USE_CHH + struct thread_state1 * const self = lookup_thread_state (); + const bool asleep = vtime_asleep_p (self->vtime); + if (asleep) + thread_state_awake (self); + *link = ut_chhLookup (handles.ht, &dummy); +#else + ddsrt_mutex_lock (&handles.lock); + *link = ut_hhLookup (handles.ht, &dummy); +#endif + if (*link == NULL) + rc = DDS_RETCODE_BAD_PARAMETER; + else + { + uint32_t cnt_flags; + /* Assume success; bail out if the object turns out to be in the process of + being deleted */ + rc = DDS_RETCODE_OK; + do { + cnt_flags = ddsrt_atomic_ld32 (&(*link)->cnt_flags); + if (cnt_flags & HDL_FLAG_CLOSED) + { + rc = DDS_RETCODE_BAD_PARAMETER; + break; + } + } while (!ddsrt_atomic_cas32 (&(*link)->cnt_flags, cnt_flags, cnt_flags + 1)); + } + +#if USE_CHH + if (asleep) + thread_state_asleep (self); +#else + ddsrt_mutex_unlock (&handles.lock); +#endif + return rc; +} + +void dds_handle_claim_inc (struct dds_handle_link *link) +{ + uint32_t x = ddsrt_atomic_inc32_nv (&link->cnt_flags); + assert (!(x & HDL_FLAG_CLOSED)); + (void) x; +} + +void dds_handle_release (struct dds_handle_link *link) +{ + if (ddsrt_atomic_dec32_ov (&link->cnt_flags) == (HDL_FLAG_CLOSED | 1)) + { + ddsrt_mutex_lock (&handles.lock); + ddsrt_cond_broadcast (&handles.cond); + ddsrt_mutex_unlock (&handles.lock); + } +} + +bool dds_handle_is_closed (struct dds_handle_link *link) +{ + return (ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_FLAG_CLOSED) != 0; +} diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index 3aa8751..31a1c0a 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -16,6 +16,7 @@ #include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/environ.h" #include "dds/ddsrt/process.h" +#include "dds/ddsrt/heap.h" #include "dds__init.h" #include "dds__rhc.h" #include "dds__domain.h" @@ -28,6 +29,7 @@ #include "dds/ddsi/q_servicelease.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_config.h" +#include "dds/ddsi/q_gc.h" #include "dds/version.h" #define DOMAIN_ID_MIN 0 @@ -38,6 +40,20 @@ struct q_globals gv; dds_globals dds_global = { .m_default_domain = DDS_DOMAIN_DEFAULT }; static struct cfgst * dds_cfgst = NULL; +static void free_via_gc_cb (struct gcreq *gcreq) +{ + void *bs = gcreq->arg; + gcreq_free (gcreq); + ddsrt_free (bs); +} + +static void free_via_gc (void *bs) +{ + struct gcreq *gcreq = gcreq_new (gv.gcreq_queue, free_via_gc_cb); + gcreq->arg = bs; + gcreq_enqueue (gcreq); +} + dds_return_t dds_init(dds_domainid_t domain) { @@ -60,13 +76,6 @@ dds_init(dds_domainid_t domain) goto skip; } - if (ut_handleserver_init() != UT_HANDLE_OK) - { - DDS_ERROR("Failed to initialize internal handle server\n"); - ret = DDS_ERRNO(DDS_RETCODE_ERROR); - goto fail_handleserver; - } - gv.tstart = now (); gv.exception = false; ddsrt_mutex_init (&dds_global.m_mutex); @@ -137,6 +146,13 @@ dds_init(dds_domainid_t domain) goto fail_rtps_init; } + if (dds_handle_server_init (free_via_gc) != DDS_RETCODE_OK) + { + DDS_ERROR("Failed to initialize internal handle server\n"); + ret = DDS_ERRNO(DDS_RETCODE_ERROR); + goto fail_handleserver; + } + dds__builtin_init (); if (rtps_start () < 0) @@ -178,6 +194,8 @@ skip: fail_servicelease_start: if (gv.servicelease) nn_servicelease_stop_renewing (gv.servicelease); + dds_handle_server_fini(); +fail_handleserver: rtps_stop (); fail_rtps_start: dds__builtin_fini (); @@ -198,8 +216,6 @@ fail_config_domainid: dds_cfgst = NULL; fail_config: ddsrt_mutex_destroy (&dds_global.m_mutex); - ut_handleserver_fini(); -fail_handleserver: dds_global.m_init_count--; ddsrt_mutex_unlock(init_mutex); ddsrt_fini(); @@ -217,6 +233,7 @@ extern void dds_fini (void) { if (gv.servicelease) nn_servicelease_stop_renewing (gv.servicelease); + dds_handle_server_fini(); rtps_stop (); dds__builtin_fini (); rtps_fini (); @@ -229,7 +246,6 @@ extern void dds_fini (void) config_fini (dds_cfgst); dds_cfgst = NULL; ddsrt_mutex_destroy (&dds_global.m_mutex); - ut_handleserver_fini(); dds_global.m_default_domain = DDS_DOMAIN_DEFAULT; } ddsrt_mutex_unlock(init_mutex); diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index 94d42a0..35521c0 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -55,7 +55,7 @@ dds_participant_delete( assert(e); assert(thr); - assert(dds_entity_kind_from_handle(e->m_hdl) == DDS_KIND_PARTICIPANT); + assert(dds_entity_kind(e) == DDS_KIND_PARTICIPANT); if (asleep) { thread_state_awake(thr); @@ -278,9 +278,9 @@ dds_lookup_participant( ddsrt_mutex_lock (&dds_global.m_mutex); iter = dds_pp_head; while (iter) { - if(iter->m_domainid == domain_id) { - if((size_t)ret < size) { - participants[ret] = iter->m_hdl; + if (iter->m_domainid == domain_id) { + if ((size_t)ret < size) { + participants[ret] = iter->m_hdllink.hdl; } ret++; } diff --git a/src/core/ddsc/src/dds_publisher.c b/src/core/ddsc/src/dds_publisher.c index 689ba11..47365c7 100644 --- a/src/core/ddsc/src/dds_publisher.c +++ b/src/core/ddsc/src/dds_publisher.c @@ -13,11 +13,14 @@ #include #include "dds/ddsrt/misc.h" #include "dds__listener.h" +#include "dds__publisher.h" #include "dds__qos.h" #include "dds__err.h" #include "dds/ddsi/q_entity.h" #include "dds/version.h" +DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_publisher) + #define DDS_PUBLISHER_STATUS_MASK 0u static dds_return_t @@ -145,36 +148,14 @@ DDS_EXPORT dds_return_t dds_suspend( dds_entity_t publisher) { - dds_return_t ret; - - if(dds_entity_kind_from_handle(publisher) != DDS_KIND_PUBLISHER) { - DDS_ERROR("Provided entity is not a publisher kind\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - goto err; - } - /* TODO: CHAM-123 Currently unsupported. */ - DDS_ERROR("Suspend publication operation does not being supported yet\n"); - ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); -err: - return ret; + return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER); } dds_return_t dds_resume( dds_entity_t publisher) { - dds_return_t ret = DDS_RETCODE_OK; - - if(dds_entity_kind_from_handle(publisher) != DDS_KIND_PUBLISHER) { - DDS_ERROR("Provided entity is not a publisher kind\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - goto err; - } - /* TODO: CHAM-123 Currently unsupported. */ - DDS_ERROR("Suspend publication operation does not being supported yet\n"); - ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); -err: - return ret; + return dds_generic_unimplemented_operation (publisher, DDS_KIND_PUBLISHER); } dds_return_t @@ -182,27 +163,10 @@ dds_wait_for_acks( dds_entity_t publisher_or_writer, dds_duration_t timeout) { - dds_return_t ret; - - /* TODO: CHAM-125 Currently unsupported. */ - DDSRT_UNUSED_ARG(timeout); - - switch(dds_entity_kind_from_handle(publisher_or_writer)) { - case DDS_KIND_WRITER: - DDS_ERROR("Wait for acknowledgments on a writer is not being supported yet\n"); - ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); - break; - case DDS_KIND_PUBLISHER: - DDS_ERROR("Wait for acknowledgments on a publisher is not being supported yet\n"); - ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED); - break; - default: - DDS_ERROR("Provided entity is not a publisher nor a writer\n"); - ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); - break; - } - - return ret; + if (timeout < 0) + return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); + static const dds_entity_kind_t kinds[] = { DDS_KIND_WRITER, DDS_KIND_PUBLISHER }; + return dds_generic_unimplemented_operation_manykinds (publisher_or_writer, sizeof (kinds) / sizeof (kinds[0]), kinds); } dds_return_t diff --git a/src/core/ddsc/src/dds_querycond.c b/src/core/ddsc/src/dds_querycond.c index 490fc3c..0a5e50d 100644 --- a/src/core/ddsc/src/dds_querycond.c +++ b/src/core/ddsc/src/dds_querycond.c @@ -39,9 +39,9 @@ dds_create_querycondition( const bool success = (cond->m_entity.m_deriver.delete != 0); dds_reader_unlock(r); if (success) { - hdl = cond->m_entity.m_hdl; + hdl = cond->m_entity.m_hdllink.hdl; } else { - dds_delete (cond->m_entity.m_hdl); + dds_delete (cond->m_entity.m_hdllink.hdl); hdl = DDS_ERRNO(DDS_RETCODE_OUT_OF_RESOURCES); } } else { diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 9353829..af239f6 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -47,7 +47,7 @@ static dds_retcode_t dds_read_lock (dds_entity_t hdl, dds_reader **reader, dds_r DDS_ERROR ("Given entity is a reader nor a condition\n"); return DDS_RETCODE_ILLEGAL_OPERATION; } - else if ((rc = dds_entity_lock (entity->m_parent->m_hdl, DDS_KIND_READER, &parent_entity)) != DDS_RETCODE_OK) + else if ((rc = dds_entity_lock (entity->m_parent->m_hdllink.hdl, DDS_KIND_READER, &parent_entity)) != DDS_RETCODE_OK) { dds_entity_unlock (entity); DDS_ERROR ("Failed to lock condition's reader\n"); @@ -168,7 +168,7 @@ dds_read_impl( /* read/take resets data available status */ dds_entity_status_reset(&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); /* reset DATA_ON_READERS status on subscriber after successful read/take */ - if (dds_entity_kind_from_handle(rd->m_entity.m_parent->m_hdl) == DDS_KIND_SUBSCRIBER) { + if (dds_entity_kind(rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) { dds_entity_status_reset(rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); } dds_read_unlock(rd, cond); @@ -225,7 +225,7 @@ dds_readcdr_impl( /* reset DATA_ON_READERS status on subscriber after successful read/take */ - if (dds_entity_kind_from_handle(rd->m_entity.m_parent->m_hdl) == DDS_KIND_SUBSCRIBER) + if (dds_entity_kind(rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) { dds_entity_status_reset(rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); } diff --git a/src/core/ddsc/src/dds_readcond.c b/src/core/ddsc/src/dds_readcond.c index 3d169de..322af8e 100644 --- a/src/core/ddsc/src/dds_readcond.c +++ b/src/core/ddsc/src/dds_readcond.c @@ -36,7 +36,7 @@ dds_create_readcond( { dds_readcond * cond = dds_alloc(sizeof(*cond)); assert((kind == DDS_KIND_COND_READ && filter == 0) || (kind == DDS_KIND_COND_QUERY && filter != 0)); - cond->m_entity.m_hdl = dds_entity_init(&cond->m_entity, (dds_entity*)rd, kind, NULL, NULL, 0); + (void) dds_entity_init(&cond->m_entity, (dds_entity*)rd, kind, NULL, NULL, 0); cond->m_entity.m_deriver.delete = dds_readcond_delete; cond->m_rhc = rd->m_rd->rhc; cond->m_sample_states = mask & DDS_ANY_SAMPLE_STATE; @@ -70,7 +70,7 @@ dds_create_readcondition( dds_readcond *cond = dds_create_readcond(rd, DDS_KIND_COND_READ, mask, 0); assert(cond); assert(cond->m_entity.m_deriver.delete); - hdl = cond->m_entity.m_hdl; + hdl = cond->m_entity.m_hdllink.hdl; dds_reader_unlock(rd); } else { DDS_ERROR("Error occurred on locking reader\n"); @@ -82,20 +82,31 @@ dds_create_readcondition( dds_entity_t dds_get_datareader (dds_entity_t condition) { - dds_entity_t hdl; - - if (dds_entity_kind_from_handle(condition) == DDS_KIND_COND_READ) { - hdl = dds_get_parent(condition); - } else if (dds_entity_kind_from_handle(condition) == DDS_KIND_COND_QUERY) { - hdl = dds_get_parent(condition); - } else { - DDS_ERROR("Argument condition is not valid\n"); - hdl = DDS_ERRNO(dds_valid_hdl(condition, DDS_KIND_COND_READ)); + struct dds_entity *e; + dds_retcode_t rc; + if ((rc = dds_entity_claim (condition, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + else + { + dds_entity_t rdh; + switch (dds_entity_kind (e)) + { + case DDS_KIND_COND_READ: + case DDS_KIND_COND_QUERY: + assert (dds_entity_kind (e->m_parent) == DDS_KIND_READER); + rdh = e->m_parent->m_hdllink.hdl; + break; + default: + rdh = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + break; } - - return hdl; + dds_handle_release (&e->m_hdllink); + return rdh; + } } + + dds_return_t dds_get_mask (dds_entity_t condition, uint32_t *mask) { dds_entity *entity; @@ -109,7 +120,7 @@ dds_return_t dds_get_mask (dds_entity_t condition, uint32_t *mask) else if (dds_entity_kind (entity) != DDS_KIND_COND_READ && dds_entity_kind (entity) != DDS_KIND_COND_QUERY) { dds_entity_unlock (entity); - return DDS_ERRNO (dds_valid_hdl (condition, DDS_KIND_COND_READ)); + return DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); } else { diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 2f37d8a..bd16e39 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -81,10 +81,10 @@ dds_reader_delete( dds_reader *rd = (dds_reader*)e; dds_return_t ret; assert(e); - ret = dds_delete(rd->m_topic->m_entity.m_hdl); + ret = dds_delete(rd->m_topic->m_entity.m_hdllink.hdl); if(ret == DDS_RETCODE_OK){ - ret = dds_delete_impl(e->m_parent->m_hdl, true); - if(dds_err_nr(ret) == DDS_RETCODE_ALREADY_DELETED){ + ret = dds_delete_impl(e->m_parent->m_hdllink.hdl, true); + if(dds_err_nr(ret) == DDS_RETCODE_BAD_PARAMETER){ ret = DDS_RETCODE_OK; } } @@ -185,7 +185,7 @@ void dds_reader_data_available_cb (struct dds_reader *rd) sub->m_cb_count++; ddsrt_mutex_unlock (&sub->m_observers_lock); - lst->on_data_on_readers (sub->m_hdl, lst->on_data_on_readers_arg); + lst->on_data_on_readers (sub->m_hdllink.hdl, lst->on_data_on_readers_arg); ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); ddsrt_mutex_lock (&sub->m_observers_lock); @@ -196,7 +196,7 @@ void dds_reader_data_available_cb (struct dds_reader *rd) else if (rd->m_entity.m_listener.on_data_available) { ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); - lst->on_data_available (rd->m_entity.m_hdl, lst->on_data_available_arg); + lst->on_data_available (rd->m_entity.m_hdllink.hdl, lst->on_data_available_arg); ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); } else @@ -222,7 +222,7 @@ void dds_reader_status_cb (void *ventity, const status_cb_data_t *data) { /* Release the initial claim that was done during the create. This * will indicate that further API deletion is now possible. */ - ut_handle_release (entity->m_hdl, entity->m_hdllink); + dds_handle_release (&entity->m_hdllink); return; } @@ -361,7 +361,7 @@ dds_create_reader( { dds_qos_t * rqos; dds_retcode_t rc; - dds_entity * sub = NULL; + dds_subscriber * sub = NULL; dds_entity_t subscriber; dds_reader * rd; struct rhc * rhc; @@ -371,31 +371,43 @@ dds_create_reader( struct thread_state1 * const thr = lookup_thread_state (); const bool asleep = !vtime_awake_p (thr->vtime); dds_return_t ret = DDS_RETCODE_OK; + bool internal_topic; - if (dds_entity_kind_from_handle(topic) != DDS_KIND_INTERNAL) { - /* Try claiming a participant. If that's not working, then it could be a subscriber. */ - if (dds_entity_kind_from_handle(participant_or_subscriber) == DDS_KIND_PARTICIPANT) { - subscriber = dds_create_subscriber(participant_or_subscriber, qos, NULL); - } else { - subscriber = participant_or_subscriber; + switch (topic) { + case DDS_BUILTIN_TOPIC_DCPSPARTICIPANT: + case DDS_BUILTIN_TOPIC_DCPSTOPIC: + case DDS_BUILTIN_TOPIC_DCPSPUBLICATION: + case DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION: + internal_topic = true; + subscriber = dds__get_builtin_subscriber(participant_or_subscriber); + t = dds__get_builtin_topic (subscriber, topic); + break; + + default: { + dds_entity *p_or_s; + if ((rc = dds_entity_claim (participant_or_subscriber, &p_or_s)) != DDS_RETCODE_OK) { + return DDS_ERRNO (rc); + } + if (dds_entity_kind (p_or_s) == DDS_KIND_PARTICIPANT) { + subscriber = dds_create_subscriber(participant_or_subscriber, qos, NULL); + } else { + subscriber = participant_or_subscriber; + } + dds_handle_release (&p_or_s->m_hdllink); + internal_topic = false; + t = topic; + break; } - t = topic; - } else { - subscriber = dds__get_builtin_subscriber(participant_or_subscriber); - t = dds__get_builtin_topic(subscriber, topic); } - rc = dds_entity_lock(subscriber, DDS_KIND_SUBSCRIBER, &sub); - if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking subscriber\n"); - reader = DDS_ERRNO(rc); + if ((rc = dds_subscriber_lock (subscriber, &sub)) != DDS_RETCODE_OK) { + reader = DDS_ERRNO (rc); goto err_sub_lock; } - if ((subscriber != participant_or_subscriber) && - (dds_entity_kind_from_handle(topic) != DDS_KIND_INTERNAL)) { + if ((subscriber != participant_or_subscriber) && !internal_topic) { /* Delete implicit subscriber if reader creation fails */ - sub->m_flags |= DDS_ENTITY_IMPLICIT; + sub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT; } rc = dds_topic_lock(t, &tp); @@ -405,7 +417,7 @@ dds_create_reader( goto err_tp_lock; } assert (tp->m_stopic); - assert (sub->m_domain == tp->m_entity.m_domain); + assert (sub->m_entity.m_domain == tp->m_entity.m_domain); /* Merge qos from topic and subscriber */ rqos = dds_create_qos (); @@ -415,8 +427,8 @@ dds_create_reader( (void)dds_copy_qos(rqos, qos); } - if(sub->m_qos){ - dds_merge_qos (rqos, sub->m_qos); + if(sub->m_entity.m_qos){ + dds_merge_qos (rqos, sub->m_entity.m_qos); } if (tp->m_entity.m_qos) { @@ -435,7 +447,7 @@ dds_create_reader( } /* Additional checks required for built-in topics */ - if (dds_entity_kind_from_handle(topic) == DDS_KIND_INTERNAL && !dds__validate_builtin_reader_qos(topic, qos)) { + if (internal_topic && !dds__validate_builtin_reader_qos(topic, qos)) { dds_delete_qos(rqos); DDS_ERROR("Invalid QoS specified for built-in topic reader"); reader = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); @@ -444,7 +456,7 @@ dds_create_reader( /* Create reader and associated read cache */ rd = dds_alloc (sizeof (*rd)); - reader = dds_entity_init (&rd->m_entity, sub, DDS_KIND_READER, rqos, listener, DDS_READER_STATUS_MASK); + reader = dds_entity_init (&rd->m_entity, &sub->m_entity, DDS_KIND_READER, rqos, listener, DDS_READER_STATUS_MASK); rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED; rd->m_topic = tp; rhc = dds_rhc_new (rd, tp->m_stopic); @@ -457,19 +469,17 @@ dds_create_reader( /* Extra claim of this reader to make sure that the delete waits until DDSI * has deleted its reader as well. This can be known through the callback. */ - if (ut_handle_claim(rd->m_entity.m_hdl, rd->m_entity.m_hdllink, DDS_KIND_READER, NULL) != UT_HANDLE_OK) { - assert(0); - } + dds_handle_claim_inc (&rd->m_entity.m_hdllink); ddsrt_mutex_unlock(&tp->m_entity.m_mutex); - ddsrt_mutex_unlock(&sub->m_mutex); + ddsrt_mutex_unlock(&sub->m_entity.m_mutex); if (asleep) { thread_state_awake (thr); } - rd->m_rd = new_reader(&rd->m_entity.m_guid, NULL, &sub->m_participant->m_guid, tp->m_stopic, + rd->m_rd = new_reader(&rd->m_entity.m_guid, NULL, &sub->m_entity.m_participant->m_guid, tp->m_stopic, rqos, rhc, dds_reader_status_cb, rd); - ddsrt_mutex_lock(&sub->m_mutex); + ddsrt_mutex_lock(&sub->m_entity.m_mutex); ddsrt_mutex_lock(&tp->m_entity.m_mutex); assert (rd->m_rd); if (asleep) { @@ -481,9 +491,9 @@ dds_create_reader( (dds_global.m_dur_reader) (rd, rhc); } dds_topic_unlock(tp); - dds_entity_unlock(sub); + dds_subscriber_unlock(sub); - if (dds_entity_kind_from_handle(topic) == DDS_KIND_INTERNAL) { + if (internal_topic) { /* If topic is builtin, then the topic entity is local and should * be deleted because the application won't. */ dds_delete(t); @@ -494,12 +504,12 @@ dds_create_reader( err_bad_qos: dds_topic_unlock(tp); err_tp_lock: - dds_entity_unlock(sub); - if((sub->m_flags & DDS_ENTITY_IMPLICIT) != 0){ + dds_subscriber_unlock(sub); + if((sub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0){ (void)dds_delete(subscriber); } err_sub_lock: - if (dds_entity_kind_from_handle(topic) == DDS_KIND_INTERNAL) { + if (internal_topic) { /* If topic is builtin, then the topic entity is local and should * be deleted because the application won't. */ dds_delete(t); @@ -509,47 +519,53 @@ err_sub_lock: void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb, void *cbarg) { - dds_reader *dds_rd; + dds_entity *dds_entity; + if (dds_entity_claim(entity, &dds_entity) != DDS_RETCODE_OK) + return; - if (ut_handle_claim(entity, NULL, DDS_KIND_READER, (void**)&dds_rd) == UT_HANDLE_OK) + if (dds_entity_kind (dds_entity) != DDS_KIND_READER) { - struct reader *rd = dds_rd->m_rd; - nn_guid_t pwrguid; - struct proxy_writer *pwr; - struct rd_pwr_match *m; - memset (&pwrguid, 0, sizeof (pwrguid)); - ddsrt_mutex_lock (&rd->e.lock); + dds_handle_release (&dds_entity->m_hdllink); + return; + } - rd->ddsi2direct_cb = cb; - rd->ddsi2direct_cbarg = cbarg; - while ((m = ut_avlLookupSuccEq (&rd_writers_treedef, &rd->writers, &pwrguid)) != NULL) + dds_reader *dds_rd = (dds_reader *) dds_entity; + struct reader *rd = dds_rd->m_rd; + nn_guid_t pwrguid; + struct proxy_writer *pwr; + struct rd_pwr_match *m; + memset (&pwrguid, 0, sizeof (pwrguid)); + ddsrt_mutex_lock (&rd->e.lock); + + rd->ddsi2direct_cb = cb; + rd->ddsi2direct_cbarg = cbarg; + while ((m = ut_avlLookupSuccEq (&rd_writers_treedef, &rd->writers, &pwrguid)) != NULL) + { + /* have to be careful walking the tree -- pretty is different, but + I want to check this before I write a lookup_succ function. */ + struct rd_pwr_match *m_next; + nn_guid_t pwrguid_next; + pwrguid = m->pwr_guid; + if ((m_next = ut_avlFindSucc (&rd_writers_treedef, &rd->writers, m)) != NULL) + pwrguid_next = m_next->pwr_guid; + else { - /* have to be careful walking the tree -- pretty is different, but - I want to check this before I write a lookup_succ function. */ - struct rd_pwr_match *m_next; - nn_guid_t pwrguid_next; - pwrguid = m->pwr_guid; - if ((m_next = ut_avlFindSucc (&rd_writers_treedef, &rd->writers, m)) != NULL) - pwrguid_next = m_next->pwr_guid; - else - { - memset (&pwrguid_next, 0xff, sizeof (pwrguid_next)); - pwrguid_next.entityid.u = (pwrguid_next.entityid.u & ~(uint32_t)0xff) | NN_ENTITYID_KIND_WRITER_NO_KEY; - } - ddsrt_mutex_unlock (&rd->e.lock); - if ((pwr = ephash_lookup_proxy_writer_guid (&pwrguid)) != NULL) - { - ddsrt_mutex_lock (&pwr->e.lock); - pwr->ddsi2direct_cb = cb; - pwr->ddsi2direct_cbarg = cbarg; - ddsrt_mutex_unlock (&pwr->e.lock); - } - pwrguid = pwrguid_next; - ddsrt_mutex_lock (&rd->e.lock); + memset (&pwrguid_next, 0xff, sizeof (pwrguid_next)); + pwrguid_next.entityid.u = (pwrguid_next.entityid.u & ~(uint32_t)0xff) | NN_ENTITYID_KIND_WRITER_NO_KEY; } ddsrt_mutex_unlock (&rd->e.lock); - ut_handle_release(entity, dds_rd->m_entity.m_hdllink); + if ((pwr = ephash_lookup_proxy_writer_guid (&pwrguid)) != NULL) + { + ddsrt_mutex_lock (&pwr->e.lock); + pwr->ddsi2direct_cb = cb; + pwr->ddsi2direct_cbarg = cbarg; + ddsrt_mutex_unlock (&pwr->e.lock); + } + pwrguid = pwrguid_next; + ddsrt_mutex_lock (&rd->e.lock); } + ddsrt_mutex_unlock (&rd->e.lock); + dds_handle_release (&dds_rd->m_entity.m_hdllink); } uint32_t dds_reader_lock_samples (dds_entity_t reader) @@ -587,23 +603,32 @@ int dds_reader_wait_for_historical_data (dds_entity_t reader, dds_duration_t max dds_entity_t dds_get_subscriber (dds_entity_t entity) { - dds_entity_t hdl; - if (dds_entity_kind_from_handle (entity) == DDS_KIND_READER) - hdl = dds_get_parent (entity); - else if (dds_entity_kind_from_handle (entity) == DDS_KIND_COND_READ || dds_entity_kind_from_handle (entity) == DDS_KIND_COND_QUERY) - { - hdl = dds_get_parent (entity); - if (hdl > 0) - hdl = dds_get_subscriber (hdl); - DDS_ERROR ("Reader of this condition is already deleted\n"); - } + dds_entity *e; + dds_retcode_t ret; + if ((ret = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) + return (dds_entity_t) DDS_ERRNO (ret); else { - DDS_ERROR ("Provided entity is not a reader nor a condition\n"); - hdl = DDS_ERRNO (dds_valid_hdl (entity, DDS_KIND_READER)); + dds_entity_t subh; + switch (dds_entity_kind (e)) + { + case DDS_KIND_READER: + assert (dds_entity_kind (e->m_parent) == DDS_KIND_SUBSCRIBER); + subh = e->m_parent->m_hdllink.hdl; + break; + case DDS_KIND_COND_READ: + case DDS_KIND_COND_QUERY: + assert (dds_entity_kind (e->m_parent) == DDS_KIND_READER); + assert (dds_entity_kind (e->m_parent->m_parent) == DDS_KIND_SUBSCRIBER); + subh = e->m_parent->m_parent->m_hdllink.hdl; + break; + default: + subh = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + break; + } + dds_handle_release (&e->m_hdllink); + return subh; } - - return hdl; } dds_return_t diff --git a/src/core/ddsc/src/dds_subscriber.c b/src/core/ddsc/src/dds_subscriber.c index 7a3281e..1a51775 100644 --- a/src/core/ddsc/src/dds_subscriber.c +++ b/src/core/ddsc/src/dds_subscriber.c @@ -13,9 +13,12 @@ #include "dds__listener.h" #include "dds__qos.h" #include "dds__err.h" +#include "dds__subscriber.h" #include "dds/ddsi/q_entity.h" #include "dds/version.h" +DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_subscriber) + #define DDS_SUBSCRIBER_STATUS_MASK \ DDS_DATA_ON_READERS_STATUS diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 940d493..acd36ac 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -40,12 +40,6 @@ const ut_avlTreedef_t dds_topictree_def = UT_AVL_TREEDEF_INITIALIZER_INDKEY 0 ); -/* builtin-topic handles */ -const dds_entity_t DDS_BUILTIN_TOPIC_DCPSPARTICIPANT = (DDS_KIND_INTERNAL + 1); -const dds_entity_t DDS_BUILTIN_TOPIC_DCPSTOPIC = (DDS_KIND_INTERNAL + 2); -const dds_entity_t DDS_BUILTIN_TOPIC_DCPSPUBLICATION = (DDS_KIND_INTERNAL + 3); -const dds_entity_t DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION = (DDS_KIND_INTERNAL + 4); - static bool is_valid_name( const char *name) @@ -198,7 +192,7 @@ dds_find_topic( st = dds_topic_lookup_locked (p->m_domain, name); if (st) { dds_entity_add_ref (&st->status_cb_entity->m_entity); - tp = st->status_cb_entity->m_entity.m_hdl; + tp = st->status_cb_entity->m_entity.m_hdllink.hdl; } else { DDS_ERROR("Topic is not being created yet\n"); tp = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); @@ -370,7 +364,7 @@ dds_create_topic_arbitrary ( hdl = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY); } else { dds_entity_add_ref (&stgeneric->status_cb_entity->m_entity); - hdl = stgeneric->status_cb_entity->m_entity.m_hdl; + hdl = stgeneric->status_cb_entity->m_entity.m_hdllink.hdl; } ddsrt_mutex_unlock (&dds_global.m_mutex); } else { diff --git a/src/core/ddsc/src/dds_waitset.c b/src/core/ddsc/src/dds_waitset.c index a594049..787ce2c 100644 --- a/src/core/ddsc/src/dds_waitset.c +++ b/src/core/ddsc/src/dds_waitset.c @@ -152,7 +152,7 @@ dds_waitset_close_list( dds_attachment *next; while (idx != NULL) { next = idx->next; - (void)dds_entity_observer_unregister(idx->entity->m_hdl, waitset); + (void)dds_entity_observer_unregister(idx->entity->m_hdllink.hdl, waitset); ddsrt_free(idx); idx = next; } @@ -168,7 +168,7 @@ dds_waitset_remove_from_list( dds_attachment *prev = NULL; while (idx != NULL) { - if (idx->entity->m_hdl == observed) { + if (idx->entity->m_hdllink.hdl == observed) { if (prev == NULL) { *list = idx->next; } else { @@ -191,8 +191,8 @@ dds_waitset_close( { dds_waitset *ws = (dds_waitset*)e; - dds_waitset_close_list(&ws->observed, e->m_hdl); - dds_waitset_close_list(&ws->triggered, e->m_hdl); + dds_waitset_close_list(&ws->observed, e->m_hdllink.hdl); + dds_waitset_close_list(&ws->triggered, e->m_hdllink.hdl); /* Trigger waitset to wake up. */ ddsrt_cond_broadcast(&e->m_cond); @@ -242,7 +242,7 @@ dds_waitset_get_entities( iter = ws->observed; while (iter) { if (((size_t)ret < size) && (entities != NULL)) { - entities[ret] = iter->entity->m_hdl; + entities[ret] = iter->entity->m_hdllink.hdl; } ret++; iter = iter->next; @@ -251,7 +251,7 @@ dds_waitset_get_entities( iter = ws->triggered; while (iter) { if (((size_t)ret < size) && (entities != NULL)) { - entities[ret] = iter->entity->m_hdl; + entities[ret] = iter->entity->m_hdllink.hdl; } ret++; iter = iter->next; @@ -275,7 +275,7 @@ dds_waitset_move( dds_attachment *idx = *src; dds_attachment *prev = NULL; while (idx != NULL) { - if (idx->entity->m_hdl == entity) { + if (idx->entity->m_hdllink.hdl == entity) { /* Swap idx from src to dst. */ dds_waitset_swap(dst, src, prev, idx); diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index e15bbbf..f804fe1 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -22,6 +22,7 @@ #include "dds__qos.h" #include "dds__err.h" #include "dds__init.h" +#include "dds__publisher.h" #include "dds__topic.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds__whc.h" @@ -75,7 +76,7 @@ static void dds_writer_status_cb (void *ventity, const status_cb_data_t *data) { /* Release the initial claim that was done during the create. This * will indicate that further API deletion is now possible. */ - ut_handle_release (entity->m_hdl, entity->m_hdllink); + dds_handle_release (&entity->m_hdllink); return; } @@ -235,10 +236,10 @@ dds_writer_delete( if (asleep) { thread_state_asleep(thr); } - ret = dds_delete(wr->m_topic->m_entity.m_hdl); + ret = dds_delete(wr->m_topic->m_entity.m_hdllink.hdl); if(ret == DDS_RETCODE_OK){ - ret = dds_delete_impl(e->m_parent->m_hdl, true); - if(dds_err_nr(ret) == DDS_RETCODE_ALREADY_DELETED){ + ret = dds_delete_impl(e->m_parent->m_hdllink.hdl, true); + if(dds_err_nr(ret) == DDS_RETCODE_BAD_PARAMETER){ ret = DDS_RETCODE_OK; } } @@ -399,7 +400,7 @@ dds_create_writer( dds_qos_t * wqos; dds_writer * wr; dds_entity_t writer; - dds_entity * pub = NULL; + dds_publisher * pub = NULL; dds_topic * tp; dds_entity_t publisher; struct thread_state1 * const thr = lookup_thread_state(); @@ -407,22 +408,26 @@ dds_create_writer( ddsi_tran_conn_t conn = gv.data_conn_uc; dds_return_t ret; - /* Try claiming a participant. If that's not working, then it could be a subscriber. */ - if(dds_entity_kind_from_handle(participant_or_publisher) == DDS_KIND_PARTICIPANT){ - publisher = dds_create_publisher(participant_or_publisher, qos, NULL); - } else{ - publisher = participant_or_publisher; + { + dds_entity *p_or_p; + if ((rc = dds_entity_claim (participant_or_publisher, &p_or_p)) != DDS_RETCODE_OK) { + return DDS_ERRNO (rc); + } + if (dds_entity_kind (p_or_p) == DDS_KIND_PARTICIPANT) { + publisher = dds_create_publisher(participant_or_publisher, qos, NULL); + } else { + publisher = participant_or_publisher; + } + dds_handle_release (&p_or_p->m_hdllink); } - rc = dds_entity_lock(publisher, DDS_KIND_PUBLISHER, &pub); - if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking publisher\n"); + if ((rc = dds_publisher_lock(publisher, &pub)) != DDS_RETCODE_OK) { writer = DDS_ERRNO(rc); goto err_pub_lock; } if (publisher != participant_or_publisher) { - pub->m_flags |= DDS_ENTITY_IMPLICIT; + pub->m_entity.m_flags |= DDS_ENTITY_IMPLICIT; } rc = dds_topic_lock(topic, &tp); @@ -432,7 +437,7 @@ dds_create_writer( goto err_tp_lock; } assert(tp->m_stopic); - assert(pub->m_domain == tp->m_entity.m_domain); + assert(pub->m_entity.m_domain == tp->m_entity.m_domain); /* Merge Topic & Publisher qos */ wqos = dds_create_qos(); @@ -442,8 +447,8 @@ dds_create_writer( (void)dds_copy_qos(wqos, qos); } - if (pub->m_qos) { - dds_merge_qos(wqos, pub->m_qos); + if (pub->m_entity.m_qos) { + dds_merge_qos(wqos, pub->m_entity.m_qos); } if (tp->m_entity.m_qos) { @@ -461,7 +466,7 @@ dds_create_writer( /* Create writer */ wr = dds_alloc(sizeof (*wr)); - writer = dds_entity_init(&wr->m_entity, pub, DDS_KIND_WRITER, wqos, listener, DDS_WRITER_STATUS_MASK); + writer = dds_entity_init(&wr->m_entity, &pub->m_entity, DDS_KIND_WRITER, wqos, listener, DDS_WRITER_STATUS_MASK); wr->m_topic = tp; dds_entity_add_ref_nolock(&tp->m_entity); @@ -475,32 +480,30 @@ dds_create_writer( /* Extra claim of this writer to make sure that the delete waits until DDSI * has deleted its writer as well. This can be known through the callback. */ - if (ut_handle_claim(wr->m_entity.m_hdl, wr->m_entity.m_hdllink, DDS_KIND_WRITER, NULL) != UT_HANDLE_OK) { - assert(0); - } + dds_handle_claim_inc (&wr->m_entity.m_hdllink); - ddsrt_mutex_unlock(&tp->m_entity.m_mutex); - ddsrt_mutex_unlock(&pub->m_mutex); + ddsrt_mutex_unlock (&tp->m_entity.m_mutex); + ddsrt_mutex_unlock (&pub->m_entity.m_mutex); if (asleep) { thread_state_awake(thr); } - wr->m_wr = new_writer(&wr->m_entity.m_guid, NULL, &pub->m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); - ddsrt_mutex_lock(&pub->m_mutex); - ddsrt_mutex_lock(&tp->m_entity.m_mutex); + wr->m_wr = new_writer(&wr->m_entity.m_guid, NULL, &pub->m_entity.m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); + ddsrt_mutex_lock (&pub->m_entity.m_mutex); + ddsrt_mutex_lock (&tp->m_entity.m_mutex); assert(wr->m_wr); if (asleep) { thread_state_asleep(thr); } dds_topic_unlock(tp); - dds_entity_unlock(pub); + dds_publisher_unlock(pub); return writer; err_bad_qos: dds_topic_unlock(tp); err_tp_lock: - dds_entity_unlock(pub); - if((pub->m_flags & DDS_ENTITY_IMPLICIT) != 0){ + dds_publisher_unlock(pub); + if((pub->m_entity.m_flags & DDS_ENTITY_IMPLICIT) != 0){ (void)dds_delete(publisher); } err_pub_lock: @@ -511,17 +514,23 @@ dds_entity_t dds_get_publisher( dds_entity_t writer) { - dds_entity_t hdl = DDS_RETCODE_OK; - - hdl = dds_valid_hdl(writer, DDS_KIND_WRITER); - if(hdl != DDS_RETCODE_OK){ - DDS_ERROR("Provided handle is not writer kind, so it is not valid\n"); - hdl = DDS_ERRNO(hdl); - } else{ - hdl = dds_get_parent(writer); + dds_entity *e; + dds_retcode_t rc; + if ((rc = dds_entity_claim (writer, &e)) != DDS_RETCODE_OK) + return DDS_ERRNO (rc); + else + { + dds_entity_t pubh; + if (dds_entity_kind (e) != DDS_KIND_WRITER) + pubh = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); + else + { + assert (dds_entity_kind (e->m_parent) == DDS_KIND_PUBLISHER); + pubh = e->m_parent->m_hdllink.hdl; } - - return hdl; + dds_handle_release (&e->m_hdllink); + return pubh; + } } dds_return_t diff --git a/src/core/ddsc/tests/CMakeLists.txt b/src/core/ddsc/tests/CMakeLists.txt index bd44687..978d0c3 100644 --- a/src/core/ddsc/tests/CMakeLists.txt +++ b/src/core/ddsc/tests/CMakeLists.txt @@ -23,7 +23,7 @@ set(ddsc_test_sources "entity_api.c" "entity_hierarchy.c" "entity_status.c" - "file_id.c" + "err.c" "instance_get_key.c" "listener.c" "participant.c" diff --git a/src/core/ddsc/tests/builtin_topics.c b/src/core/ddsc/tests/builtin_topics.c index 3a63478..e4d2ff0 100644 --- a/src/core/ddsc/tests/builtin_topics.c +++ b/src/core/ddsc/tests/builtin_topics.c @@ -63,7 +63,7 @@ teardown(void) } static void -check_default_qos_of_builtin_entity(dds_entity_t entity) +check_default_qos_of_builtin_entity(dds_entity_t entity, bool isread) { dds_return_t ret; int64_t deadline; @@ -110,8 +110,7 @@ check_default_qos_of_builtin_entity(dds_entity_t entity) dds_qget_partition(qos, &plen, &partitions); // no getter for ENTITY_FACTORY - CU_ASSERT_FATAL((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_SUBSCRIBER || (entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER); - if ((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_SUBSCRIBER) { + if (!isread) { CU_ASSERT_FATAL(plen == 1); CU_ASSERT_STRING_EQUAL_FATAL(partitions[0], "__BUILT-IN PARTITION__"); } else { @@ -303,9 +302,9 @@ CU_Test(ddsc_builtin_topics, builtin_qos, .init = setup, .fini = teardown) dds_sub_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, NULL); CU_ASSERT_FATAL(dds_sub_rdr > 0); - check_default_qos_of_builtin_entity(dds_sub_rdr); + check_default_qos_of_builtin_entity(dds_sub_rdr, 1); dds_sub_subscriber = dds_get_parent(dds_sub_rdr); CU_ASSERT_FATAL(dds_sub_subscriber > 0); - check_default_qos_of_builtin_entity(dds_sub_subscriber); + check_default_qos_of_builtin_entity(dds_sub_subscriber, 0); } diff --git a/src/core/ddsc/tests/dispose.c b/src/core/ddsc/tests/dispose.c index ee504fc..0e10c60 100644 --- a/src/core/ddsc/tests/dispose.c +++ b/src/core/ddsc/tests/dispose.c @@ -153,7 +153,7 @@ CU_Test(ddsc_writedispose, deleted, .init=disposing_init, .fini=disposing_fini) DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_writedispose(g_writer, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -170,7 +170,7 @@ CU_Test(ddsc_writedispose, null, .init=disposing_init, .fini=disposing_fini) /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_writedispose, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_writedispose, invalid_writers, .init=disposing_init, .fini=disposing_fini) { @@ -310,7 +310,7 @@ CU_Test(ddsc_writedispose_ts, deleted, .init=disposing_init, .fini=disposing_fin DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_writedispose_ts(g_writer, NULL, g_present); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -341,7 +341,7 @@ CU_Test(ddsc_writedispose_ts, timeout, .init=disposing_init, .fini=disposing_fin /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_writedispose_ts, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_writedispose_ts, invalid_writers, .init=disposing_init, .fini=disposing_fini) { @@ -510,7 +510,7 @@ CU_Test(ddsc_dispose, deleted, .init=disposing_init, .fini=disposing_fini) DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_dispose(g_writer, NULL); DDSRT_WARNING_MSVC_ON(6387); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -541,7 +541,7 @@ CU_Test(ddsc_dispose, timeout, .init=disposing_init, .fini=disposing_fini) /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_dispose, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_dispose, invalid_writers, .init=disposing_init, .fini=disposing_fini) { @@ -665,7 +665,7 @@ CU_Test(ddsc_dispose_ts, deleted, .init=disposing_init, .fini=disposing_fini) DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ ret = dds_dispose_ts(g_writer, NULL, g_present); DDSRT_WARNING_MSVC_ON(6387); /* Disable SAL warning on intentional misuse of the API */ - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -696,7 +696,7 @@ CU_Test(ddsc_dispose_ts, timeout, .init=disposing_init, .fini=disposing_fini) /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_dispose_ts, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_dispose_ts, invalid_writers, .init=disposing_init, .fini=disposing_fini) { @@ -861,7 +861,7 @@ CU_Test(ddsc_dispose_ih, deleted, .init=disposing_init, .fini=disposing_fini) dds_return_t ret; dds_delete(g_writer); ret = dds_dispose_ih(g_writer, DDS_HANDLE_NIL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -879,7 +879,7 @@ CU_Theory((dds_instance_handle_t handle), ddsc_dispose_ih, invalid_handles, .ini /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_dispose_ih, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_dispose_ih, invalid_writers, .init=disposing_init, .fini=disposing_fini) { @@ -959,7 +959,7 @@ CU_Test(ddsc_dispose_ih_ts, deleted, .init=disposing_init, .fini=disposing_fini) dds_return_t ret; dds_delete(g_writer); ret = dds_dispose_ih_ts(g_writer, DDS_HANDLE_NIL, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -977,7 +977,7 @@ CU_Theory((dds_instance_handle_t handle), ddsc_dispose_ih_ts, invalid_handles, . /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_dispose_ih_ts, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_dispose_ih_ts, invalid_writers, .init=disposing_init, .fini=disposing_fini) { diff --git a/src/core/ddsc/tests/entity_hierarchy.c b/src/core/ddsc/tests/entity_hierarchy.c index ef2f1f4..ec7e2dc 100644 --- a/src/core/ddsc/tests/entity_hierarchy.c +++ b/src/core/ddsc/tests/entity_hierarchy.c @@ -147,21 +147,21 @@ CU_Test(ddsc_entity_delete, recursive, .init=hierarchy_init, .fini=hierarchy_fin /* Check if all the entities are deleted now. */ ret = dds_get_domainid(g_participant, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_topic, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_publisher, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_subscriber, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_writer, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_reader, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_readcond, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_querycond, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -201,11 +201,11 @@ CU_Test(ddsc_entity_delete, recursive_with_deleted_topic) /* Check if the entities are actually deleted. */ ret = dds_get_domainid(g_participant, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED ); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER ); ret = dds_get_domainid(g_topic, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); ret = dds_get_domainid(g_writer, &id); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); dds_delete(g_keep); } @@ -240,13 +240,13 @@ CU_Theory((dds_entity_t *entity), ddsc_entity_get_participant, deleted_entities, dds_entity_t participant; dds_delete(*entity); participant = dds_get_participant(*entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(participant), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(participant), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_entity_get_participant, invalid_entities) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t entity), ddsc_entity_get_participant, invalid_entities, .init=hierarchy_init, .fini=hierarchy_fini) { @@ -327,13 +327,13 @@ CU_Theory((dds_entity_t *entity), ddsc_entity_get_parent, deleted_entities, .ini dds_entity_t parent; dds_delete(*entity); parent = dds_get_parent(*entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(parent), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(parent), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_entity_get_parent, invalid_entities) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t entity), ddsc_entity_get_parent, invalid_entities, .init=hierarchy_init, .fini=hierarchy_fini) { @@ -478,13 +478,13 @@ CU_Theory((dds_entity_t *entity), ddsc_entity_get_children, deleted_entities, .i dds_entity_t children[4]; dds_delete(*entity); ret = dds_get_children(*entity, children, 4); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_entity_get_children, invalid_entities) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t entity), ddsc_entity_get_children, invalid_entities, .init=hierarchy_init, .fini=hierarchy_fini) { @@ -527,13 +527,13 @@ CU_Theory((dds_entity_t *entity), ddsc_entity_get_topic, deleted_entities, .init dds_entity_t topic; dds_delete(*entity); topic = dds_get_topic(*entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(topic), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(topic), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_entity_get_topic, invalid_entities) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t entity), ddsc_entity_get_topic, invalid_entities, .init=hierarchy_init, .fini=hierarchy_fini) { @@ -581,13 +581,13 @@ CU_Test(ddsc_entity_get_publisher, deleted_writer, .init=hierarchy_init, .fini=h dds_entity_t publisher; dds_delete(g_writer); publisher = dds_get_publisher(g_writer); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(publisher), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(publisher), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_entity_get_publisher, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t entity), ddsc_entity_get_publisher, invalid_writers, .init=hierarchy_init, .fini=hierarchy_fini) { @@ -640,13 +640,13 @@ CU_Theory((dds_entity_t *entity), ddsc_entity_get_subscriber, deleted_readers, . dds_entity_t subscriber; dds_delete(*entity); subscriber = dds_get_subscriber(*entity); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(subscriber), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(subscriber), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_entity_get_subscriber, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t entity), ddsc_entity_get_subscriber, invalid_readers, .init=hierarchy_init, .fini=hierarchy_fini) { @@ -701,13 +701,13 @@ CU_Theory((dds_entity_t *cond), ddsc_entity_get_datareader, deleted_conds, .init dds_entity_t reader; dds_delete(*cond); reader = dds_get_datareader(*cond); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(reader), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(reader), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_entity_get_datareader, invalid_conds) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t cond), ddsc_entity_get_datareader, invalid_conds, .init=hierarchy_init, .fini=hierarchy_fini) { diff --git a/src/core/ddsc/tests/entity_status.c b/src/core/ddsc/tests/entity_status.c index f14245f..45883fe 100644 --- a/src/core/ddsc/tests/entity_status.c +++ b/src/core/ddsc/tests/entity_status.c @@ -589,9 +589,9 @@ CU_Test(ddsc_entity, all_data_available, .init=init_entity_status, .fini=fini_en /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_enabled_status, bad_param) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t e), ddsc_get_enabled_status, bad_param) +CU_Theory((dds_entity_t e), ddsc_get_enabled_status, bad_param, .init=init_entity_status, .fini=fini_entity_status) { uint32_t mask; dds_return_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -605,7 +605,7 @@ CU_Test(ddsc_get_enabled_status, deleted_reader, .init=init_entity_status, .fini uint32_t mask; dds_delete(rea); ret = dds_get_status_mask(rea, &mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_get_enabled_status, illegal, .init=init_entity_status, .fini=fini_entity_status) @@ -628,9 +628,9 @@ CU_Theory((dds_entity_t *e), ddsc_get_enabled_status, status_ok, .init=init_enti /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_set_enabled_status, bad_param) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t e), ddsc_set_enabled_status, bad_param) +CU_Theory((dds_entity_t e), ddsc_set_enabled_status, bad_param, .init=init_entity_status, .fini=fini_entity_status) { dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -642,7 +642,7 @@ CU_Test(ddsc_set_enabled_status, deleted_reader, .init=init_entity_status, .fini { dds_delete(rea); ret = dds_set_status_mask(rea, 0 /*mask*/); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_set_enabled_status, illegal, .init=init_entity_status, .fini=fini_entity_status) @@ -663,9 +663,9 @@ CU_Theory((dds_entity_t *entity), ddsc_set_enabled_status, status_ok, .init=init /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_status, bad_param) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t e), ddsc_read_status, bad_param) +CU_Theory((dds_entity_t e), ddsc_read_status, bad_param, .init=init_entity_status, .fini=fini_entity_status) { uint32_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -679,7 +679,7 @@ CU_Test(ddsc_read_status, deleted_reader, .init=init_entity_status, .fini=fini_e uint32_t status; dds_delete(rea); ret = dds_read_status(rea, &status, 0 /*mask*/); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_read_status, illegal, .init=init_entity_status, .fini=fini_entity_status) @@ -715,9 +715,9 @@ CU_Test(ddsc_read_status, invalid_status_on_writer, .init=init_entity_status, .f /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_status, bad_param) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t e), ddsc_take_status, bad_param) +CU_Theory((dds_entity_t e), ddsc_take_status, bad_param, .init=init_entity_status, .fini=fini_entity_status) { uint32_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -731,7 +731,7 @@ CU_Test(ddsc_take_status, deleted_reader, .init=init_entity_status, .fini=fini_e uint32_t status; dds_delete(rea); ret = dds_take_status(rea, &status, 0 /*mask*/); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_take_status, illegal, .init=init_entity_status, .fini=fini_entity_status) { @@ -754,9 +754,9 @@ CU_Theory((dds_entity_t *e), ddsc_take_status, status_ok, .init=init_entity_stat /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_status_changes, bad_param) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t e), ddsc_get_status_changes, bad_param) +CU_Theory((dds_entity_t e), ddsc_get_status_changes, bad_param, .init=init_entity_status, .fini=fini_entity_status) { uint32_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -770,7 +770,7 @@ CU_Test(ddsc_get_status_changes, deleted_reader, .init=init_entity_status, .fini uint32_t status; dds_delete(rea); ret = dds_get_status_changes(rea, &status); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_get_status_changes, illegal, .init=init_entity_status, .fini=fini_entity_status) @@ -793,9 +793,9 @@ CU_Theory((dds_entity_t *e), ddsc_get_status_changes, status_ok, .init=init_enti /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_triggered, bad_param) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t e), ddsc_triggered, bad_param) +CU_Theory((dds_entity_t e), ddsc_triggered, bad_param, .init=init_entity_status, .fini=fini_entity_status) { dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -807,7 +807,7 @@ CU_Test(ddsc_triggered, deleted_reader, .init=init_entity_status, .fini=fini_ent { dds_delete(rea); ret = dds_triggered(rea); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } CU_TheoryDataPoints(ddsc_triggered, status_ok) = { @@ -833,9 +833,9 @@ CU_Test(ddsc_get_inconsistent_topic_status, inconsistent_topic_status, .init=ini /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_inconsistent_topic_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t topic), ddsc_get_inconsistent_topic_status, bad_params) +CU_Theory((dds_entity_t topic), ddsc_get_inconsistent_topic_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_inconsistent_topic_status_t topic_status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -876,9 +876,9 @@ CU_Test(ddsc_get_inconsistent_topic_status, deleted_topic, .init=init_entity_sta /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_publication_matched_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t writer), ddsc_get_publication_matched_status, bad_params) +CU_Theory((dds_entity_t writer), ddsc_get_publication_matched_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_publication_matched_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -913,7 +913,7 @@ CU_Test(ddsc_get_publication_matched_status, deleted_writer, .init=init_entity_s { dds_delete(wri); ret = dds_get_publication_matched_status(wri, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -930,9 +930,9 @@ CU_Test(ddsc_get_liveliness_lost_status, liveliness_lost_status, .init=init_enti /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_liveliness_lost_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t writer), ddsc_get_liveliness_lost_status, bad_params) +CU_Theory((dds_entity_t writer), ddsc_get_liveliness_lost_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_liveliness_lost_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -967,7 +967,7 @@ CU_Test(ddsc_get_liveliness_lost_status, deleted_writer, .init=init_entity_statu { dds_delete(wri); ret = dds_get_liveliness_lost_status(wri, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -985,9 +985,9 @@ CU_Test(ddsc_get_offered_deadline_missed_status, offered_deadline_missed_status, /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_offered_deadline_missed_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t writer), ddsc_get_offered_deadline_missed_status, bad_params) +CU_Theory((dds_entity_t writer), ddsc_get_offered_deadline_missed_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_offered_deadline_missed_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -1022,15 +1022,15 @@ CU_Test(ddsc_get_offered_deadline_missed_status, deleted_writer, .init=init_enti { dds_delete(wri); ret = dds_get_offered_deadline_missed_status(wri, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_offered_incompatible_qos_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t writer), ddsc_get_offered_incompatible_qos_status, bad_params) +CU_Theory((dds_entity_t writer), ddsc_get_offered_incompatible_qos_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_offered_incompatible_qos_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -1065,15 +1065,15 @@ CU_Test(ddsc_get_offered_incompatible_qos_status, deleted_writer, .init=init_ent { dds_delete(wri); ret = dds_get_offered_incompatible_qos_status(wri, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_subscription_matched_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t reader), ddsc_get_subscription_matched_status, bad_params) +CU_Theory((dds_entity_t reader), ddsc_get_subscription_matched_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_subscription_matched_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -1108,15 +1108,15 @@ CU_Test(ddsc_get_subscription_matched_status, deleted_reader, .init=init_entity_ { dds_delete(rea); ret = dds_get_subscription_matched_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_liveliness_changed_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t reader), ddsc_get_liveliness_changed_status, bad_params) +CU_Theory((dds_entity_t reader), ddsc_get_liveliness_changed_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_liveliness_changed_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -1151,15 +1151,15 @@ CU_Test(ddsc_get_liveliness_changed_status, deleted_reader, .init=init_entity_st { dds_delete(rea); ret = dds_get_liveliness_changed_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_sample_rejected_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t reader), ddsc_get_sample_rejected_status, bad_params) +CU_Theory((dds_entity_t reader), ddsc_get_sample_rejected_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_sample_rejected_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -1194,15 +1194,15 @@ CU_Test(ddsc_get_sample_rejected_status, deleted_reader, .init=init_entity_statu { dds_delete(rea); ret = dds_get_sample_rejected_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_sample_lost_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t reader), ddsc_get_sample_lost_status, bad_params) +CU_Theory((dds_entity_t reader), ddsc_get_sample_lost_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_sample_lost_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -1237,7 +1237,7 @@ CU_Test(ddsc_get_sample_lost_status, deleted_reader, .init=init_entity_status, . { dds_delete(rea); ret = dds_get_sample_lost_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1255,9 +1255,9 @@ CU_Test(ddsc_get_requested_deadline_missed_status, requested_deadline_missed_sta /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_requested_deadline_missed_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t reader), ddsc_get_requested_deadline_missed_status, bad_params) +CU_Theory((dds_entity_t reader), ddsc_get_requested_deadline_missed_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_requested_deadline_missed_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -1292,15 +1292,15 @@ CU_Test(ddsc_get_requested_deadline_missed_status, deleted_reader, .init=init_en { dds_delete(rea); ret = dds_get_requested_deadline_missed_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_get_requested_incompatible_qos_status, bad_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; -CU_Theory((dds_entity_t reader), ddsc_get_requested_incompatible_qos_status, bad_params) +CU_Theory((dds_entity_t reader), ddsc_get_requested_incompatible_qos_status, bad_params, .init=init_entity_status, .fini=fini_entity_status) { dds_requested_incompatible_qos_status_t status; dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1; @@ -1335,7 +1335,7 @@ CU_Test(ddsc_get_requested_incompatible_qos_status, deleted_reader, .init=init_e { dds_delete(rea); ret = dds_get_requested_incompatible_qos_status(rea, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/file_id.c b/src/core/ddsc/tests/file_id.c deleted file mode 100644 index a2ce5b8..0000000 --- a/src/core/ddsc/tests/file_id.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include "dds/dds.h" -#include "CUnit/Test.h" - -#include "dds/ddsrt/misc.h" - -CU_Test(ddsc_err, unique_file_id) -{ - dds_entity_t participant, reader, writer; - - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - CU_ASSERT_FATAL(participant > 0); - - /* Disable SAL warning on intentional misuse of the API */ - DDSRT_WARNING_MSVC_OFF(28020); - reader = dds_create_reader(0, 0, NULL, NULL); - CU_ASSERT_FATAL(reader < 0); - - writer = dds_create_writer(0, 0, NULL, NULL); - CU_ASSERT_FATAL(writer < 0); - - DDSRT_WARNING_MSVC_ON(28020); - - CU_ASSERT_NOT_EQUAL_FATAL(dds_err_file_id(reader), dds_err_file_id(writer)); - - dds_delete(participant); -} diff --git a/src/core/ddsc/tests/publisher.c b/src/core/ddsc/tests/publisher.c index 5ea49d3..78c5bb1 100644 --- a/src/core/ddsc/tests/publisher.c +++ b/src/core/ddsc/tests/publisher.c @@ -42,7 +42,7 @@ CU_Test(ddsc_publisher, create) /* Use NULL participant */ publisher = dds_create_publisher(0, NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(publisher), DDS_RETCODE_BAD_PARAMETER); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(publisher), DDS_RETCODE_PRECONDITION_NOT_MET); participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); @@ -143,21 +143,21 @@ CU_Test(ddsc_publisher, suspend_resume) /* Suspend a 0 publisher */ status = dds_suspend(0); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_PRECONDITION_NOT_MET); /* Resume a 0 publisher */ status = dds_resume(0); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_PRECONDITION_NOT_MET); /* Uae dds_suspend on something else than a publisher */ participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); status = dds_suspend(participant); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_ILLEGAL_OPERATION); /* Use dds_resume on something else than a publisher */ status = dds_resume(participant); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_ILLEGAL_OPERATION); /* Use dds_resume without calling dds_suspend */ publisher = dds_create_publisher(participant, NULL, NULL); @@ -193,15 +193,15 @@ CU_Test(ddsc_publisher, wait_for_acks) /* Wait_for_acks on NULL publisher or writer and zeroSec timeout */ status = dds_wait_for_acks(0, zeroSec); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_PRECONDITION_NOT_MET); /* wait_for_acks on NULL publisher or writer and oneSec timeout */ status = dds_wait_for_acks(0, oneSec); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_PRECONDITION_NOT_MET); /* wait_for_acks on NULL publisher or writer and DDS_INFINITE timeout */ status = dds_wait_for_acks(0, DDS_INFINITY); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_PRECONDITION_NOT_MET); participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(participant > 0); @@ -212,22 +212,23 @@ CU_Test(ddsc_publisher, wait_for_acks) /* Wait_for_acks on participant and zeroSec timeout */ status = dds_wait_for_acks(participant, zeroSec); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_ILLEGAL_OPERATION); /* Wait_for_acks on participant and oneSec timeout */ status = dds_wait_for_acks(participant, oneSec); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_ILLEGAL_OPERATION); /* Wait_for_acks on participant and DDS_INFINITE timeout */ status = dds_wait_for_acks(participant, DDS_INFINITY); - cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); + cu_assert_status_eq(status, DDS_RETCODE_ILLEGAL_OPERATION); publisher = dds_create_publisher(participant, NULL, NULL); CU_ASSERT_FATAL(publisher > 0); - /* Wait_for_acks on publisher and minusOneSec timeout */ + /* Wait_for_acks on publisher and minusOneSec timeout -- + either BAD_PARAMETER or UNSUPPORTED would be both be ok, really */ status = dds_wait_for_acks(publisher, minusOneSec); - cu_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED); + cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); /* Wait_for_acks on publisher and zeroSec timeout */ status = dds_wait_for_acks(publisher, zeroSec); @@ -248,7 +249,7 @@ CU_Test(ddsc_publisher, wait_for_acks) /* Wait_for_acks on suspended publisher and minusOneSec timeout */ status = dds_wait_for_acks(publisher, minusOneSec); - cu_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED); + cu_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER); /* Wait_for_acks on suspended publisher and zeroSec timeout */ status = dds_wait_for_acks(publisher, zeroSec); diff --git a/src/core/ddsc/tests/querycondition.c b/src/core/ddsc/tests/querycondition.c index 1638a79..107fdd1 100644 --- a/src/core/ddsc/tests/querycondition.c +++ b/src/core/ddsc/tests/querycondition.c @@ -245,13 +245,13 @@ CU_Test(ddsc_querycondition_create, deleted_reader, .init=querycondition_init, . dds_entity_t cond; dds_delete(g_reader); cond = dds_create_querycondition(g_reader, mask, filter_mod2); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(cond), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(cond), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_querycondition_create, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_querycondition_create, invalid_readers, .init=querycondition_init, .fini=querycondition_fini) { @@ -297,7 +297,7 @@ CU_Test(ddsc_querycondition_get_mask, deleted, .init=querycondition_init, .fini= dds_delete(condition); mask = 0; ret = dds_get_mask(condition, &mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -319,7 +319,7 @@ CU_Test(ddsc_querycondition_get_mask, null, .init=querycondition_init, .fini=que /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_querycondition_get_mask, invalid_conditions) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t cond), ddsc_querycondition_get_mask, invalid_conditions, .init=querycondition_init, .fini=querycondition_fini) { @@ -924,7 +924,7 @@ CU_Test(ddsc_querycondition_read, already_deleted, .init=querycondition_init, .f /* Try to read with a deleted condition. */ ret = dds_read(condition, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1487,7 +1487,7 @@ CU_Test(ddsc_querycondition_take, already_deleted, .init=querycondition_init, .f /* Try to take with a deleted condition. */ ret = dds_take(condition, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/read_instance.c b/src/core/ddsc/tests/read_instance.c index 7ef1384..063d003 100644 --- a/src/core/ddsc/tests/read_instance.c +++ b/src/core/ddsc/tests/read_instance.c @@ -450,7 +450,7 @@ CU_Theory((dds_entity_t *rdr, dds_instance_handle_t hdl), ddsc_read_instance_mas *************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_instance, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_instance, invalid_readers, .init=read_instance_init, .fini=read_instance_fini) { @@ -464,7 +464,7 @@ CU_Theory((dds_entity_t rdr), ddsc_read_instance, invalid_readers, .init=read_in /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_instance_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_instance_wl, invalid_readers, .init=read_instance_init, .fini=read_instance_fini) { @@ -478,7 +478,7 @@ CU_Theory((dds_entity_t rdr), ddsc_read_instance_wl, invalid_readers, .init=read /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_instance_mask, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_instance_mask, invalid_readers, .init=read_instance_init, .fini=read_instance_fini) { @@ -493,7 +493,7 @@ CU_Theory((dds_entity_t rdr), ddsc_read_instance_mask, invalid_readers, .init=re /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_instance_mask_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_instance_mask_wl, invalid_readers, .init=read_instance_init, .fini=read_instance_fini) { @@ -586,7 +586,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_instance, already_deleted, .init=read_i ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_instance(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -600,7 +600,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_instance_wl, already_deleted, .init=rea ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_instance_wl(*rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -615,7 +615,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_instance_mask, already_deleted, .init=r ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_instance_mask(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -630,7 +630,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_instance_mask_wl, already_deleted, .ini ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_instance_mask_wl(*rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/readcondition.c b/src/core/ddsc/tests/readcondition.c index 534f51c..694d463 100644 --- a/src/core/ddsc/tests/readcondition.c +++ b/src/core/ddsc/tests/readcondition.c @@ -227,13 +227,13 @@ CU_Test(ddsc_readcondition_create, deleted_reader, .init=readcondition_init, .fi dds_entity_t cond; dds_delete(g_reader); cond = dds_create_readcondition(g_reader, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(cond), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(cond), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_readcondition_create, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_readcondition_create, invalid_readers, .init=readcondition_init, .fini=readcondition_fini) { @@ -279,7 +279,7 @@ CU_Test(ddsc_readcondition_get_mask, deleted, .init=readcondition_init, .fini=re dds_delete(condition); mask = 0; ret = dds_get_mask(condition, &mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -301,7 +301,7 @@ CU_Test(ddsc_readcondition_get_mask, null, .init=readcondition_init, .fini=readc /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_readcondition_get_mask, invalid_conditions) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t cond), ddsc_readcondition_get_mask, invalid_conditions, .init=readcondition_init, .fini=readcondition_fini) { @@ -906,7 +906,7 @@ CU_Test(ddsc_readcondition_read, already_deleted, .init=readcondition_init, .fin /* Try to read with a deleted condition. */ ret = dds_read(condition, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1462,7 +1462,7 @@ CU_Test(ddsc_readcondition_take, already_deleted, .init=readcondition_init, .fin /* Try to take with a deleted condition. */ ret = dds_take(condition, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/reader.c b/src/core/ddsc/tests/reader.c index 4698172..ad80be7 100644 --- a/src/core/ddsc/tests/reader.c +++ b/src/core/ddsc/tests/reader.c @@ -316,7 +316,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs), ddsc /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read, invalid_readers, .init=reader_init, .fini=reader_fini) { @@ -347,7 +347,7 @@ CU_Test(ddsc_read, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_read(g_reader, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -426,7 +426,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, uint32_t maxs), ddsc_read_wl, inva /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_wl, invalid_readers, .init=reader_init, .fini=reader_fini) { @@ -457,7 +457,7 @@ CU_Test(ddsc_read_wl, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_read_wl(g_reader, g_loans, g_info, MAX_SAMPLES); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -550,7 +550,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs), ddsc /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_mask, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_mask, invalid_readers, .init=reader_init, .fini=reader_fini) { @@ -584,7 +584,7 @@ CU_Test(ddsc_read_mask, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_read_mask(g_reader, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1098,7 +1098,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, uint32_t maxs), ddsc_read_mask_wl, /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_mask_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_mask_wl, invalid_readers, .init=reader_init, .fini=reader_fini) { @@ -1132,7 +1132,7 @@ CU_Test(ddsc_read_mask_wl, already_deleted, .init=reader_init, .fini=reader_fini /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_read_mask_wl(g_reader, g_loans, g_info, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1686,7 +1686,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs), ddsc /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take, invalid_readers, .init=reader_init, .fini=reader_fini) { @@ -1717,7 +1717,7 @@ CU_Test(ddsc_take, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to take with a deleted reader. */ dds_delete(g_reader); ret = dds_take(g_reader, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1796,7 +1796,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, uint32_t maxs), ddsc_take_wl, inva /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_wl, invalid_readers, .init=reader_init, .fini=reader_fini) { @@ -1827,7 +1827,7 @@ CU_Test(ddsc_take_wl, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_take_wl(g_reader, g_loans, g_info, MAX_SAMPLES); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -1921,7 +1921,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs), ddsc /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_mask, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_mask, invalid_readers, .init=reader_init, .fini=reader_fini) { @@ -1955,7 +1955,7 @@ CU_Test(ddsc_take_mask, already_deleted, .init=reader_init, .fini=reader_fini) /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_take_mask(g_reader, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -2602,7 +2602,7 @@ CU_Theory((void **buf, dds_sample_info_t *si, uint32_t maxs), ddsc_take_mask_wl, /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_mask_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_mask_wl, invalid_readers, .init=reader_init, .fini=reader_fini) { @@ -2636,7 +2636,7 @@ CU_Test(ddsc_take_mask_wl, already_deleted, .init=reader_init, .fini=reader_fini /* Try to read with a deleted reader. */ dds_delete(g_reader); ret = dds_take_mask_wl(g_reader, g_loans, g_info, MAX_SAMPLES, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/reader_iterator.c b/src/core/ddsc/tests/reader_iterator.c index 7a840ca..c0dbe6a 100644 --- a/src/core/ddsc/tests/reader_iterator.c +++ b/src/core/ddsc/tests/reader_iterator.c @@ -356,7 +356,7 @@ CU_Test(ddsc_read_next, reader, .init=reader_iterator_init, .fini=reader_iterato /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_next, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_next, invalid_readers, .init=reader_iterator_init, .fini=reader_iterator_fini) { @@ -390,7 +390,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_next, already_deleted, .init=reader_ite ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_next(*rdr, g_samples, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -472,7 +472,7 @@ CU_Test(ddsc_read_next_wl, reader, .init=reader_iterator_init, .fini=reader_iter /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_read_next_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_read_next_wl, invalid_readers, .init=reader_iterator_init, .fini=reader_iterator_fini) { @@ -506,7 +506,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_read_next_wl, already_deleted, .init=reader_ ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_read_next_wl(*rdr, g_loans, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -582,7 +582,7 @@ CU_Test(ddsc_take_next, reader, .init=reader_iterator_init, .fini=reader_iterato } /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_next, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_next, invalid_readers, .init=reader_iterator_init, .fini=reader_iterator_fini) { @@ -616,7 +616,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_next, already_deleted, .init=reader_ite ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_next(*rdr, g_samples, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -695,7 +695,7 @@ CU_Test(ddsc_take_next_wl, reader, .init=reader_iterator_init, .fini=reader_iter } /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_next_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_next_wl, invalid_readers, .init=reader_iterator_init, .fini=reader_iterator_fini) { @@ -729,7 +729,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_next_wl, already_deleted, .init=reader_ ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_next_wl(*rdr, g_loans, g_info); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/register.c b/src/core/ddsc/tests/register.c index a075ae5..11249dd 100644 --- a/src/core/ddsc/tests/register.c +++ b/src/core/ddsc/tests/register.c @@ -150,7 +150,7 @@ CU_Test(ddsc_register_instance, deleted_entity, .init=registering_init, .fini=re dds_instance_handle_t handle; dds_delete(g_writer); ret = dds_register_instance(g_writer, &handle, g_data); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } static dds_instance_handle_t hndle = 0; @@ -173,7 +173,7 @@ CU_Theory((dds_instance_handle_t *hndl2, void *datap), ddsc_register_instance, i } CU_TheoryDataPoints(ddsc_register_instance, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_register_instance, invalid_writers, .init=registering_init, .fini=registering_fini) { diff --git a/src/core/ddsc/tests/take_instance.c b/src/core/ddsc/tests/take_instance.c index d9ef401..6fba4a6 100644 --- a/src/core/ddsc/tests/take_instance.c +++ b/src/core/ddsc/tests/take_instance.c @@ -447,7 +447,7 @@ CU_Theory((dds_entity_t *rdr, dds_instance_handle_t hdl), ddsc_take_instance_mas *************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_instance, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_instance, invalid_readers, .init=take_instance_init, .fini=take_instance_fini) { @@ -461,7 +461,7 @@ CU_Theory((dds_entity_t rdr), ddsc_take_instance, invalid_readers, .init=take_in /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_instance_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_instance_wl, invalid_readers, .init=take_instance_init, .fini=take_instance_fini) { @@ -475,7 +475,7 @@ CU_Theory((dds_entity_t rdr), ddsc_take_instance_wl, invalid_readers, .init=take /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_instance_mask, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_instance_mask, invalid_readers, .init=take_instance_init, .fini=take_instance_fini) { @@ -490,7 +490,7 @@ CU_Theory((dds_entity_t rdr), ddsc_take_instance_mask, invalid_readers, .init=ta /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_take_instance_mask_wl, invalid_readers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t rdr), ddsc_take_instance_mask_wl, invalid_readers, .init=take_instance_init, .fini=take_instance_fini) { @@ -583,7 +583,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_instance, already_deleted, .init=take_i ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_instance(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -597,7 +597,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_instance_wl, already_deleted, .init=tak ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_instance_wl(*rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -612,7 +612,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_instance_mask, already_deleted, .init=t ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_instance_mask(*rdr, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -627,7 +627,7 @@ CU_Theory((dds_entity_t *rdr), ddsc_take_instance_mask_wl, already_deleted, .ini ret = dds_delete(*rdr); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); ret = dds_take_instance_mask_wl(*rdr, g_loans, g_info, MAX_SAMPLES, g_hdl_valid, mask); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/topic.c b/src/core/ddsc/tests/topic.c index 665d38d..43dde13 100644 --- a/src/core/ddsc/tests/topic.c +++ b/src/core/ddsc/tests/topic.c @@ -314,7 +314,7 @@ CU_Test(ddsc_topic_get_name, deleted, .init=ddsc_topic_init, .fini=ddsc_topic_fi dds_return_t ret; dds_delete(g_topicRtmDataType); ret = dds_get_name(g_topicRtmDataType, name, MAX_NAME_SIZE); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -387,7 +387,7 @@ CU_Test(ddsc_topic_get_type_name, deleted, .init=ddsc_topic_init, .fini=ddsc_top dds_return_t ret; dds_delete(g_topicRtmDataType); ret = dds_get_type_name(g_topicRtmDataType, name, MAX_NAME_SIZE); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ diff --git a/src/core/ddsc/tests/unregister.c b/src/core/ddsc/tests/unregister.c index c79cb9a..e27eb32 100644 --- a/src/core/ddsc/tests/unregister.c +++ b/src/core/ddsc/tests/unregister.c @@ -152,7 +152,7 @@ CU_Test(ddsc_unregister_instance, deleted, .init=unregistering_init, .fini=unreg dds_delete(g_writer); ret = dds_unregister_instance(g_writer, g_data); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -167,7 +167,7 @@ CU_Test(ddsc_unregister_instance, null, .init=unregistering_init, .fini=unregist /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_unregister_instance, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_unregister_instance, invalid_writers, .init=unregistering_init, .fini=unregistering_fini) { @@ -246,7 +246,7 @@ CU_Test(ddsc_unregister_instance_ts, deleted, .init=unregistering_init, .fini=un dds_return_t ret; dds_delete(g_writer); ret = dds_unregister_instance_ts(g_writer, g_data, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -261,7 +261,7 @@ CU_Test(ddsc_unregister_instance_ts, null, .init=unregistering_init, .fini=unreg /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_unregister_instance_ts, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_unregister_instance_ts, invalid_writers, .init=unregistering_init, .fini=unregistering_fini) { @@ -383,7 +383,7 @@ CU_Test(ddsc_unregister_instance_ih, deleted, .init=unregistering_init, .fini=un dds_return_t ret; dds_delete(g_writer); ret = dds_unregister_instance_ih(g_writer, DDS_HANDLE_NIL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -401,7 +401,7 @@ CU_Theory((dds_instance_handle_t handle), ddsc_unregister_instance_ih, invalid_h /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_unregister_instance_ih, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_unregister_instance_ih, invalid_writers, .init=unregistering_init, .fini=unregistering_fini) { @@ -481,7 +481,7 @@ CU_Test(ddsc_unregister_instance_ih_ts, deleted, .init=unregistering_init, .fini dds_return_t ret; dds_delete(g_writer); ret = dds_unregister_instance_ih_ts(g_writer, DDS_HANDLE_NIL, g_present); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -499,7 +499,7 @@ CU_Theory((dds_instance_handle_t handle), ddsc_unregister_instance_ih_ts, invali /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_unregister_instance_ih_ts, invalid_writers) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t writer), ddsc_unregister_instance_ih_ts, invalid_writers, .init=unregistering_init, .fini=unregistering_fini) { diff --git a/src/core/ddsc/tests/unsupported.c b/src/core/ddsc/tests/unsupported.c index 2a15f25..68bf4a5 100644 --- a/src/core/ddsc/tests/unsupported.c +++ b/src/core/ddsc/tests/unsupported.c @@ -50,7 +50,7 @@ setup(void) CU_ASSERT_FATAL(e[REA] > 0); e[RCD] = dds_create_readcondition(e[REA], DDS_ANY_STATE); CU_ASSERT_FATAL(e[RCD] > 0); - e[BAD] = 1; + e[BAD] = 314159265; } static void @@ -104,7 +104,7 @@ CU_Test(ddsc_unsupported, dds_suspend_resume, .init = setup, .fini = teardown) dds_return_t result; static struct index_result pars[] = { {PUB, DDS_RETCODE_UNSUPPORTED}, - {WRI, DDS_RETCODE_BAD_PARAMETER}, + {WRI, DDS_RETCODE_ILLEGAL_OPERATION}, {BAD, DDS_RETCODE_BAD_PARAMETER} }; diff --git a/src/core/ddsc/tests/waitset.c b/src/core/ddsc/tests/waitset.c index 24c9954..9c401cb 100644 --- a/src/core/ddsc/tests/waitset.c +++ b/src/core/ddsc/tests/waitset.c @@ -226,13 +226,13 @@ CU_Test(ddsc_waitset_create, deleted_participant, .init=ddsc_waitset_basic_init, deleted = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); dds_delete(deleted); ws = dds_create_waitset(deleted); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ws), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ws), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_create, invalid_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t par), ddsc_waitset_create, invalid_params, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { @@ -269,7 +269,7 @@ CU_Theory((dds_entity_t *par), ddsc_waitset_create, non_participants, .init=ddsc *************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_attach, invalid_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), CU_DataPoints(dds_attach_t, (dds_attach_t)NULL, (dds_attach_t)&reader, (dds_attach_t)3, (dds_attach_t)0, (dds_attach_t)0, (dds_attach_t)0, (dds_attach_t)0), }; CU_Theory((dds_entity_t e, dds_attach_t a), ddsc_waitset_attach, invalid_params, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) @@ -282,7 +282,7 @@ CU_Theory((dds_entity_t e, dds_attach_t a), ddsc_waitset_attach, invalid_params, /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_attach, invalid_waitsets) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), CU_DataPoints(dds_attach_t, (dds_attach_t)NULL, (dds_attach_t)&reader, (dds_attach_t)3, (dds_attach_t)0, (dds_attach_t)0, (dds_attach_t)0, (dds_attach_t)0), }; CU_Theory((dds_entity_t ws, dds_attach_t a), ddsc_waitset_attach, invalid_waitsets, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) @@ -315,7 +315,7 @@ CU_Test(ddsc_waitset_attach, deleted_waitset, .init=ddsc_waitset_basic_init, .fi dds_return_t ret; dds_delete(waitset); ret = dds_waitset_attach(waitset, participant, 0); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ @@ -393,7 +393,7 @@ CU_Test(ddsc_waitset_attach_detach, second, .init=ddsc_waitset_basic_init, .fini *************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_detach, invalid_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t e), ddsc_waitset_detach, invalid_params, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { @@ -405,7 +405,7 @@ CU_Theory((dds_entity_t e), ddsc_waitset_detach, invalid_params, .init=ddsc_wait /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_detach, invalid_waitsets) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t ws), ddsc_waitset_detach, invalid_waitsets, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { @@ -580,13 +580,13 @@ CU_Test(ddsc_waitset_set_trigger, deleted_waitset, .init=ddsc_waitset_basic_init dds_return_t ret; dds_delete(waitset); ret = dds_waitset_set_trigger(waitset, true); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_set_trigger, invalid_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t ws), ddsc_waitset_set_trigger, invalid_params, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { @@ -625,13 +625,13 @@ CU_Test(ddsc_waitset_wait, deleted_waitset, .init=ddsc_waitset_attached_init, .f dds_return_t ret; dds_delete(waitset); ret = dds_waitset_wait(waitset, &triggered, 1, DDS_SECS(1)); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_wait, invalid_waitsets) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t ws), ddsc_waitset_wait, invalid_waitsets, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { @@ -683,13 +683,13 @@ CU_Test(ddsc_waitset_wait_until, deleted_waitset, .init=ddsc_waitset_attached_in dds_return_t ret; dds_delete(waitset); ret = dds_waitset_wait_until(waitset, &triggered, 1, dds_time()); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_wait_until, invalid_waitsets) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t ws), ddsc_waitset_wait_until, invalid_waitsets, .init=ddsc_waitset_basic_init, .fini=ddsc_waitset_basic_fini) { @@ -843,13 +843,13 @@ CU_Test(ddsc_waitset_get_entities, deleted_waitset, .init=ddsc_waitset_attached_ dds_entity_t entities[MAX_ENTITIES_CNT]; dds_delete(waitset); ret = dds_waitset_get_entities(waitset, entities, MAX_ENTITIES_CNT); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER); } /*************************************************************************************************/ /*************************************************************************************************/ CU_TheoryDataPoints(ddsc_waitset_get_entities, invalid_params) = { - CU_DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN), + CU_DataPoints(dds_entity_t, -2, -1, 0, INT_MAX, INT_MIN), }; CU_Theory((dds_entity_t ws), ddsc_waitset_get_entities, invalid_params, .init=ddsc_waitset_attached_init, .fini=ddsc_waitset_attached_fini) { diff --git a/src/core/ddsc/tests/write.c b/src/core/ddsc/tests/write.c index 93dae69..2cd3f15 100644 --- a/src/core/ddsc/tests/write.c +++ b/src/core/ddsc/tests/write.c @@ -95,7 +95,7 @@ CU_Test(ddsc_write, closed_writer, .init = setup, .fini = teardown) CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_OK); status = dds_write(writer, &data); writer = 0; - CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(status), DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_write, null_sample, .init = setup, .fini = teardown) diff --git a/src/core/ddsc/tests/writer.c b/src/core/ddsc/tests/writer.c index f738ddb..66ce1ea 100644 --- a/src/core/ddsc/tests/writer.c +++ b/src/core/ddsc/tests/writer.c @@ -83,7 +83,7 @@ CU_Test(ddsc_create_writer, deleted_publisher, .init = setup, .fini = teardown) dds_delete(publisher); writer = dds_create_writer(publisher, topic, NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(writer), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(writer), DDS_RETCODE_BAD_PARAMETER); } CU_Test(ddsc_create_writer, null_topic, .init = setup, .fini = teardown) @@ -105,5 +105,5 @@ CU_Test(ddsc_create_writer, deleted_topic, .init = setup, .fini = teardown) dds_delete(topic); writer = dds_create_writer(publisher, topic, NULL, NULL); - CU_ASSERT_EQUAL_FATAL(dds_err_nr(writer), DDS_RETCODE_ALREADY_DELETED); + CU_ASSERT_EQUAL_FATAL(dds_err_nr(writer), DDS_RETCODE_BAD_PARAMETER); } diff --git a/src/core/ddsi/.fileids b/src/core/ddsi/.fileids deleted file mode 100644 index 0fd013b..0000000 --- a/src/core/ddsi/.fileids +++ /dev/null @@ -1,40 +0,0 @@ -# ddsi sources -1 src/ddsi_ser.c -2 src/ddsi_ssl.c -3 src/ddsi_tcp.c -4 src/ddsi_tran.c -5 src/ddsi_udp.c -6 src/q_addrset.c -7 src/q_bitset_inlines.c -8 src/q_bswap.c -9 src/q_bswap_inlines.c -10 src/q_config.c -11 src/q_ddsi_discovery.c -12 src/q_debmon.c -13 src/q_entity.c -14 src/q_ephash.c -15 src/q_gc.c -16 src/q_init.c -17 src/q_lat_estim.c -18 src/q_lease.c -20 src/q_md5.c -21 src/q_misc.c -22 src/q_nwif.c -23 src/q_pcap.c -24 src/q_plist.c -25 src/q_qosmatch.c -26 src/q_radmin.c -27 src/q_receive.c -28 src/q_security.c -29 src/q_servicelease.c -30 src/q_sockwaitset.c -31 src/q_thread.c -32 src/q_thread_inlines.c -33 src/q_time.c -34 src/q_transmit.c -36 src/q_xevent.c -37 src/q_xmsg.c -38 src/q_freelist.c -39 src/sysdeps.c -71 src/q_builtin_topic.c - diff --git a/src/core/ddsi/src/q_thread_inlines.c b/src/core/ddsi/src/q_thread_inlines.c index 4d26a63..b16f324 100644 --- a/src/core/ddsi/src/q_thread_inlines.c +++ b/src/core/ddsi/src/q_thread_inlines.c @@ -19,4 +19,3 @@ extern inline void thread_state_asleep (struct thread_state1 *ts1); extern inline void thread_state_awake (struct thread_state1 *ts1); extern inline void thread_state_blocked (struct thread_state1 *ts1); extern inline void thread_state_unblocked (struct thread_state1 *ts1); - diff --git a/src/tools/pubsub/common.c b/src/tools/pubsub/common.c index 43322f4..be217cb 100644 --- a/src/tools/pubsub/common.c +++ b/src/tools/pubsub/common.c @@ -390,7 +390,6 @@ static void inapplicable_qos(dds_entity_kind_t qt, const char *n) { case DDS_KIND_COND_READ: en = "cond read"; break; case DDS_KIND_COND_QUERY: en = "cond query"; break; case DDS_KIND_WAITSET: en = "waitset"; break; - case DDS_KIND_INTERNAL: en = "internal"; break; default: en = "?"; break; } fprintf(stderr, "warning: %s entity ignoring inapplicable QoS \"%s\"\n", en, n); diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 84088c3..282c131 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -11,7 +11,7 @@ # include (GenerateExportHeader) -PREPEND(srcs_util "${CMAKE_CURRENT_SOURCE_DIR}/src" ut_avl.c ut_crc.c ut_expand_envvars.c ut_fibheap.c ut_handleserver.c ut_hopscotch.c ut_thread_pool.c ut_xmlparser.c) +PREPEND(srcs_util "${CMAKE_CURRENT_SOURCE_DIR}/src" ut_avl.c ut_crc.c ut_expand_envvars.c ut_fibheap.c ut_hopscotch.c ut_thread_pool.c ut_xmlparser.c) add_library(util ${srcs_util}) set_property(TARGET util PROPERTY POSITION_INDEPENDENT_CODE TRUE) diff --git a/src/util/src/ut_handleserver.c b/src/util/src/ut_handleserver.c deleted file mode 100644 index 657f05e..0000000 --- a/src/util/src/ut_handleserver.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include -#include - -#include "dds/ddsrt/cdtors.h" -#include "dds/ddsrt/heap.h" -#include "dds/ddsrt/sync.h" -#include "dds/util/ut_handleserver.h" - -/* Arbitrarily number of max handles. Should be enough for the mock. */ -#define MAX_NR_OF_HANDLES (1000) - -#define HDL_FLAG_NONE (0x00) -#define HDL_FLAG_CLOSED (0x01) - -typedef struct ut_handlelink { - ut_handle_t hdl; - void *arg; - uint32_t cnt; - uint8_t flags; -} ut_handlelink; - -typedef struct ut_handleserver { - ut_handlelink *hdls[MAX_NR_OF_HANDLES]; - int32_t last; - ddsrt_mutex_t mutex; -} ut_handleserver; - - -/* Singleton handle server. */ -static ut_handleserver *hs = NULL; - - -static ut_handle_retcode_t -lookup_handle(ut_handle_t hdl, int32_t kind, ut_handlelink **link); - -static ut_handle_t -check_handle(ut_handle_t hdl, int32_t kind); - -static void -delete_handle(int32_t idx); - - -ut_handle_retcode_t -ut_handleserver_init(void) -{ - ddsrt_init(); - /* TODO Allow re-entry (something like ddsrt_init()). */ - assert(hs == NULL); - hs = ddsrt_malloc(sizeof(ut_handleserver)); - hs->last = 0; - ddsrt_mutex_init(&hs->mutex); - return UT_HANDLE_OK; -} - - -void -ut_handleserver_fini(void) -{ - int32_t i; - - /* TODO Only destroy when this is the last fini (something like ddsrt_fini()). */ - assert(hs); - - /* Every handle should have been deleted, but make sure. */ - for (i = 0; i < hs->last; i++) { - if (hs->hdls[i] != NULL) { - /* TODO CHAM-138: Print warning. */ - ddsrt_free(hs->hdls[i]); - } - } - ddsrt_mutex_destroy(&hs->mutex); - ddsrt_free(hs); - hs = NULL; - ddsrt_fini(); -} - - -ut_handle_t -ut_handle_create( - int32_t kind, - void *arg) -{ - ut_handle_t hdl = (ut_handle_t)UT_HANDLE_OUT_OF_RESOURCES; - - /* A kind is obligatory. */ - assert(kind & UT_HANDLE_KIND_MASK); - /* The kind should extent outside its boundaries. */ - assert(!(kind & ~UT_HANDLE_KIND_MASK)); - - if (hs == NULL) { - return (ut_handle_t)UT_HANDLE_NOT_INITALIZED; - } - - ddsrt_mutex_lock(&hs->mutex); - - /* TODO CHAM-138: Improve the creation and management of handles. */ - if (hs->last < MAX_NR_OF_HANDLES) { - hdl = hs->last; - hdl |= kind; - hs->hdls[hs->last] = ddsrt_malloc(sizeof(ut_handlelink)); - hs->hdls[hs->last]->cnt = 0; - hs->hdls[hs->last]->arg = arg; - hs->hdls[hs->last]->hdl = hdl; - hs->hdls[hs->last]->flags = HDL_FLAG_NONE; - hs->last++; - } - - ddsrt_mutex_unlock(&hs->mutex); - - return hdl; -} - -void -ut_handle_close( - ut_handle_t hdl, - struct ut_handlelink *link) -{ - struct ut_handlelink *info = link; - ut_handle_retcode_t ret = UT_HANDLE_OK; - - assert(hs); - - ddsrt_mutex_lock(&hs->mutex); - if (info == NULL) { - ret = lookup_handle(hdl, UT_HANDLE_DONTCARE_KIND, &info); - } - if (ret == UT_HANDLE_OK) { - assert(info); - assert(hdl == info->hdl); - info->flags |= HDL_FLAG_CLOSED; - } - ddsrt_mutex_unlock(&hs->mutex); -} - -ut_handle_retcode_t -ut_handle_delete( - ut_handle_t hdl, - struct ut_handlelink *link, - dds_time_t timeout) -{ - struct ut_handlelink *info = link; - ut_handle_retcode_t ret = UT_HANDLE_OK; - - assert(hs); - - ddsrt_mutex_lock(&hs->mutex); - if (info == NULL) { - ret = lookup_handle(hdl, UT_HANDLE_DONTCARE_KIND, &info); - } - if (ret == UT_HANDLE_OK) { - assert(info); - assert(hdl == info->hdl); - info->flags |= HDL_FLAG_CLOSED; - - /* FIXME: Replace this polling with conditional wait. */ - ddsrt_mutex_unlock(&hs->mutex); - { - dds_duration_t delay = DDS_MSECS(10); - while ((info->cnt != 0) && timeout > 0) { - dds_sleepfor(delay); - timeout = (delay < timeout ? timeout - delay : 0); - } - } - ddsrt_mutex_lock(&hs->mutex); - - if (info->cnt == 0) { - delete_handle(hdl & UT_HANDLE_IDX_MASK); - } else { - ret = UT_HANDLE_TIMEOUT; - } - } - ddsrt_mutex_unlock(&hs->mutex); - - return ret; -} - -ut_handle_retcode_t -ut_handle_status( - ut_handle_t hdl, - struct ut_handlelink *link, - int32_t kind) -{ - struct ut_handlelink *info = link; - ut_handle_retcode_t ret = UT_HANDLE_OK; - - if (hs == NULL) { - return (ut_handle_t)UT_HANDLE_INVALID; - } - - ddsrt_mutex_lock(&hs->mutex); - if (info == NULL) { - ret = lookup_handle(hdl, kind, &info); - } - if (ret == UT_HANDLE_OK) { - assert(info); - assert(hdl == info->hdl); - if (info->flags & HDL_FLAG_CLOSED) { - ret = UT_HANDLE_CLOSED; - } - } - ddsrt_mutex_unlock(&hs->mutex); - - return ret; -} - -ut_handle_retcode_t -ut_handle_claim( - ut_handle_t hdl, - struct ut_handlelink *link, - int32_t kind, - void **arg) -{ - struct ut_handlelink *info = link; - ut_handle_retcode_t ret = UT_HANDLE_OK; - - if (arg != NULL) { - *arg = NULL; - } - - if (hs == NULL) { - return (ut_handle_t)UT_HANDLE_INVALID; - } - - ddsrt_mutex_lock(&hs->mutex); - if (info == NULL) { - ret = lookup_handle(hdl, kind, &info); - } - if (ret == UT_HANDLE_OK) { - assert(info); - assert(hdl == info->hdl); - if (info->flags & HDL_FLAG_CLOSED) { - ret = UT_HANDLE_CLOSED; - } - } - if (ret == UT_HANDLE_OK) { - info->cnt++; - if (arg != NULL) { - *arg = info->arg; - } - } - ddsrt_mutex_unlock(&hs->mutex); - - return ret; -} - - -void -ut_handle_release( - ut_handle_t hdl, - struct ut_handlelink *link) -{ - struct ut_handlelink *info = link; - ut_handle_retcode_t ret = UT_HANDLE_OK; - - assert(hs); - - ddsrt_mutex_lock(&hs->mutex); - if (info == NULL) { - ret = lookup_handle(hdl, UT_HANDLE_DONTCARE_KIND, &info); - } - if (ret == UT_HANDLE_OK) { - assert(info); - assert(hdl == info->hdl); - assert(info->cnt > 0); - info->cnt--; - } - ddsrt_mutex_unlock(&hs->mutex); -} - -bool -ut_handle_is_closed( - ut_handle_t hdl, - struct ut_handlelink *link) -{ - struct ut_handlelink *info = link; - ut_handle_retcode_t ret = UT_HANDLE_OK; - - assert(hs); - - ddsrt_mutex_lock(&hs->mutex); - if (info == NULL) { - ret = lookup_handle(hdl, UT_HANDLE_DONTCARE_KIND, &info); - } - if (ret == UT_HANDLE_OK) { - assert(info); - assert(hdl == info->hdl); - if (info->flags & HDL_FLAG_CLOSED) { - ret = UT_HANDLE_CLOSED; - } - } - ddsrt_mutex_unlock(&hs->mutex); - - /* Simulate closed for every error. */ - return (ret != UT_HANDLE_OK); -} - -struct ut_handlelink* -ut_handle_get_link( - ut_handle_t hdl) -{ - struct ut_handlelink *info; - ut_handle_retcode_t ret; - - assert(hs); - - ddsrt_mutex_lock(&hs->mutex); - ret = lookup_handle(hdl, UT_HANDLE_DONTCARE_KIND, &info); - assert(((ret == UT_HANDLE_OK) && (info != NULL)) || - ((ret != UT_HANDLE_OK) && (info == NULL)) ); - (void)ret; - ddsrt_mutex_unlock(&hs->mutex); - - return info; -} - - -static ut_handle_retcode_t -lookup_handle( - ut_handle_t hdl, - int32_t kind, - ut_handlelink **link) -{ - ut_handle_retcode_t ret; - *link = NULL; - ret = check_handle(hdl, kind); - if (ret == UT_HANDLE_OK) { - int32_t idx = (hdl & UT_HANDLE_IDX_MASK); - assert(idx < MAX_NR_OF_HANDLES); - *link = hs->hdls[idx]; - } - return ret; -} - -static ut_handle_t -check_handle( - ut_handle_t hdl, - int32_t kind) -{ - /* When handle is negative, it contains a retcode. */ - ut_handle_retcode_t ret = UT_HANDLE_OK; - if (hdl > 0) { - if (hdl & UT_HANDLE_KIND_MASK) { - int32_t idx = (hdl & UT_HANDLE_IDX_MASK); - if (idx < hs->last) { - assert(idx < MAX_NR_OF_HANDLES); - ut_handlelink *info = hs->hdls[idx]; - if (info != NULL) { - if ((info->hdl & UT_HANDLE_KIND_MASK) == (hdl & UT_HANDLE_KIND_MASK)) { - if ((kind != UT_HANDLE_DONTCARE_KIND) && - (kind != (hdl & UT_HANDLE_KIND_MASK))) { - /* It's a valid handle, but the caller expected a different kind. */ - ret = UT_HANDLE_UNEQUAL_KIND; - } - } else { - ret = UT_HANDLE_UNEQUAL_KIND; - } - } else { - ret = UT_HANDLE_DELETED; - } - } else { - ret = UT_HANDLE_INVALID; - } - } else { - ret = UT_HANDLE_INVALID; - } - } else if (hdl == 0) { - ret = UT_HANDLE_INVALID; - } else { - /* When handle is negative, it contains a retcode. */ - ret = (ut_handle_retcode_t)hdl; - } - return ret; -} - -static void -delete_handle(int32_t idx) -{ - assert(hs); - assert(idx < MAX_NR_OF_HANDLES); - ddsrt_free(hs->hdls[idx]); - hs->hdls[idx] = NULL; -} diff --git a/src/util/tests/CMakeLists.txt b/src/util/tests/CMakeLists.txt index 0d88ea0..7828517 100644 --- a/src/util/tests/CMakeLists.txt +++ b/src/util/tests/CMakeLists.txt @@ -11,19 +11,5 @@ # include(CUnit) -add_cunit_executable(cunit_util "handleserver.c") -target_link_libraries(cunit_util PRIVATE util) -target_link_libraries(cunit_util PRIVATE ddsrt) - -# Create a dummy export header. generate_export_header can only be used with -# library targets, but since the targets are linked statically, -# __declspec(dllimport) is not required anyway. -set(export_dir "${CMAKE_CURRENT_BINARY_DIR}/include/dds") -set(export_header "${export_dir}/export.h") -if(NOT EXISTS "${export_header}") - file(MAKE_DIRECTORY "${export_dir}") - file(WRITE "${export_header}" "#define DDS_EXPORT\n") -endif() - -target_include_directories( - cunit_util PRIVATE "$") +#add_cunit_executable(CUnit_util "handleserver.c") +#target_link_libraries(CUnit_util util) diff --git a/src/util/tests/handleserver.c b/src/util/tests/handleserver.c deleted file mode 100644 index ced5832..0000000 --- a/src/util/tests/handleserver.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include "dds/util/ut_handleserver.h" -#include "CUnit/Test.h" -#include "dds/ddsrt/retcode.h" -#include "dds/ddsrt/threads.h" -#include "dds/ddsrt/time.h" - -/*****************************************************************************************/ -CU_Test(util_handleserver, basic) -{ - int32_t kind = 0x10000000; - ut_handle_retcode_t ret; - ut_handle_t hdl; - int arg = 1; - void *argx; - - ret = ut_handleserver_init(); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - hdl = ut_handle_create(kind, (void*)&arg); - CU_ASSERT_FATAL(hdl > 0); - - ret = ut_handle_claim(hdl, NULL, kind, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - CU_ASSERT_EQUAL_FATAL(argx, &arg); - - ut_handle_release(hdl, NULL); - - ret = ut_handle_delete(hdl, NULL, 0); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - ret = ut_handle_claim(hdl, NULL, kind, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_DELETED); - - ut_handleserver_fini(); -} - - -/*****************************************************************************************/ -CU_Test(util_handleserver, close) -{ - int32_t kind = 0x10000000; - ut_handle_retcode_t ret; - ut_handle_t hdl; - int arg = 1; - void *argx; - bool closed; - - ret = ut_handleserver_init(); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - hdl = ut_handle_create(kind, (void*)&arg); - CU_ASSERT_FATAL(hdl > 0); - - closed = ut_handle_is_closed(hdl, NULL); - CU_ASSERT_EQUAL_FATAL(closed, false); - - ut_handle_close(hdl, NULL); - - closed = ut_handle_is_closed(hdl, NULL); - CU_ASSERT_EQUAL_FATAL(closed, true); - - ret = ut_handle_claim(hdl, NULL, kind, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_CLOSED); - - ret = ut_handle_delete(hdl, NULL, 0); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - ret = ut_handle_claim(hdl, NULL, kind, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_DELETED); - - ut_handleserver_fini(); -} - -/*****************************************************************************************/ -CU_Test(util_handleserver, link) -{ - int32_t kind = 0x10000000; - ut_handle_retcode_t ret; - struct ut_handlelink *link; - ut_handle_t hdl; - int arg = 1; - void *argx; - - ret = ut_handleserver_init(); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - hdl = ut_handle_create(kind, (void*)&arg); - CU_ASSERT_FATAL(hdl > 0); - - link = ut_handle_get_link(hdl); - CU_ASSERT_NOT_EQUAL_FATAL(link, NULL); - - ret = ut_handle_claim(hdl, link, kind, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - CU_ASSERT_EQUAL_FATAL(argx, &arg); - - ut_handle_release(hdl, link); - - ret = ut_handle_delete(hdl, link, 0); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - link = ut_handle_get_link(hdl); - CU_ASSERT_EQUAL_FATAL(link, NULL); - - ut_handleserver_fini(); -} - - -/*****************************************************************************************/ -CU_Test(util_handleserver, types) -{ - int32_t kind1 = 0x10000000; - int32_t kind2 = 0x20000000; - ut_handle_retcode_t ret; - ut_handle_t hdl1a; - ut_handle_t hdl1b; - ut_handle_t hdl2; - int arg1a = (int)'a'; - int arg1b = (int)'b'; - int arg2 = (int)'2'; - void *argx; - - ret = ut_handleserver_init(); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - hdl1a = ut_handle_create(kind1, (void*)&arg1a); - CU_ASSERT_FATAL(hdl1a > 0); - - hdl1b = ut_handle_create(kind1, (void*)&arg1b); - CU_ASSERT_FATAL(hdl1b > 0); - - hdl2 = ut_handle_create(kind2, (void*)&arg2); - CU_ASSERT_FATAL(hdl2 > 0); - - ret = ut_handle_claim(hdl1a, NULL, kind1, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - CU_ASSERT_EQUAL_FATAL(argx, &arg1a); - - ret = ut_handle_claim(hdl1b, NULL, kind1, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - CU_ASSERT_EQUAL_FATAL(argx, &arg1b); - - ret = ut_handle_claim(hdl2, NULL, kind2, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - CU_ASSERT_EQUAL_FATAL(argx, &arg2); - - ret = ut_handle_claim(hdl1a, NULL, kind2, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_UNEQUAL_KIND); - - ret = ut_handle_claim(hdl1a, NULL, kind2, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_UNEQUAL_KIND); - - ret = ut_handle_claim(hdl2, NULL, kind1, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_UNEQUAL_KIND); - - ut_handle_release(hdl1a, NULL); - ut_handle_release(hdl1b, NULL); - ut_handle_release(hdl2, NULL); - - ret = ut_handle_delete(hdl1a, NULL, 0); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - ret = ut_handle_delete(hdl1b, NULL, 0); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - ret = ut_handle_delete(hdl2, NULL, 0); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - ut_handleserver_fini(); -} - - -/*****************************************************************************************/ -CU_Test(util_handleserver, timeout) -{ - int32_t kind = 0x10000000; - ut_handle_retcode_t ret; - ut_handle_t hdl; - int arg = 1; - void *argx; - - ret = ut_handleserver_init(); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - hdl = ut_handle_create(kind, (void*)&arg); - CU_ASSERT_FATAL(hdl > 0); - - ret = ut_handle_claim(hdl, NULL, kind, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - CU_ASSERT_EQUAL_FATAL(argx, &arg); - - ret = ut_handle_delete(hdl, NULL, 0); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_TIMEOUT); - - ut_handle_release(hdl, NULL); - - ret = ut_handle_delete(hdl, NULL, 0); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - ut_handleserver_fini(); -} - - -/*****************************************************************************************/ -typedef enum thread_state_t { - STARTING, - DELETING, - STOPPED -} thread_state_t; - -typedef struct thread_arg_t { - thread_state_t state; - ut_handle_t hdl; -} thread_arg_t; - -static uint32_t -deleting_thread(void *a) -{ - thread_arg_t *arg = (thread_arg_t*)a; - const dds_time_t ten = DDS_SECS(10); - ut_handle_t ret; - - arg->state = DELETING; - /* This should block until the main test released all claims. */ - ret = ut_handle_delete(arg->hdl, NULL, ten); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - arg->state = STOPPED; - - return 0; -} - -dds_retcode_t -thread_reached_state(thread_state_t *actual, thread_state_t expected, int32_t msec) -{ - /* Convenience function. */ - dds_time_t msec10 = DDS_MSECS(10); - while ((msec > 0) && (*actual != expected)) { - dds_sleepfor(msec10); - msec -= 10; - } - return (*actual == expected) ? DDS_RETCODE_OK : DDS_RETCODE_TIMEOUT; -} - -CU_Test(util_handleserver, wakeup) -{ - int32_t kind = 0x10000000; - ut_handle_retcode_t ret; - ut_handle_t hdl; - int arg = 1; - void *argx; - - ddsrt_thread_t thread_id; - thread_arg_t thread_arg; - ddsrt_threadattr_t thread_attr; - dds_retcode_t rc; - - ret = ut_handleserver_init(); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - hdl = ut_handle_create(kind, (void*)&arg); - CU_ASSERT_FATAL(hdl > 0); - - ret = ut_handle_claim(hdl, NULL, kind, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - ret = ut_handle_claim(hdl, NULL, kind, &argx); - CU_ASSERT_EQUAL_FATAL(ret, UT_HANDLE_OK); - - /* Try deleting in other thread, which should block. */ - thread_arg.hdl = hdl; - thread_arg.state = STARTING; - ddsrt_threadattr_init(&thread_attr); - rc = ddsrt_thread_create(&thread_id, "deleting_thread", &thread_attr, deleting_thread, (void*)&thread_arg); - CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); - rc = thread_reached_state(&thread_arg.state, DELETING, 1000); - CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); - rc = thread_reached_state(&thread_arg.state, STOPPED, 500); - CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_TIMEOUT); - - /* First release of the hdl should not unblock the thread. */ - ut_handle_release(hdl, NULL); - rc = thread_reached_state(&thread_arg.state, STOPPED, 500); - CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_TIMEOUT); - - /* Second release of the hdl should unblock the thread. */ - ut_handle_release(hdl, NULL); - rc = thread_reached_state(&thread_arg.state, STOPPED, 500); - CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); - ddsrt_thread_join(thread_id, NULL); - - /* The handle is deleted within the thread. */ - - ut_handleserver_fini(); -} - From bb7373b90df1a79ac77a6af4ce50fedcd9c68999 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sun, 7 Apr 2019 18:47:27 +0200 Subject: [PATCH 021/238] nestable calls to thread_[state_]awake Remove all the "if asleep then awake ..." stuff from the code by making awake/asleep calls nestable, whereas before it "awake ; awake" really meant a transition through "asleep". This self-evidently necessitates fixing those places where the old behaviour was relied on upon, but fortunately those are few. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_builtin.c | 5 +- src/core/ddsc/src/dds_handles.c | 35 +++-- src/core/ddsc/src/dds_init.c | 40 +++--- src/core/ddsc/src/dds_instance.c | 90 ++++--------- src/core/ddsc/src/dds_participant.c | 23 +--- src/core/ddsc/src/dds_read.c | 30 ++--- src/core/ddsc/src/dds_reader.c | 21 +-- src/core/ddsc/src/dds_topic.c | 10 +- src/core/ddsc/src/dds_write.c | 38 ++---- src/core/ddsc/src/dds_writer.c | 54 ++------ src/core/ddsi/CMakeLists.txt | 5 +- .../ddsi/include/dds/ddsi/ddsi_threadmon.h | 31 +++++ src/core/ddsi/include/dds/ddsi/q_config.h | 4 +- src/core/ddsi/include/dds/ddsi/q_globals.h | 2 +- src/core/ddsi/include/dds/ddsi/q_lease.h | 3 +- .../ddsi/include/dds/ddsi/q_servicelease.h | 31 ----- src/core/ddsi/include/dds/ddsi/q_thread.h | 104 +++++++-------- src/core/ddsi/include/dds/ddsi/q_transmit.h | 9 +- .../{q_servicelease.c => ddsi_threadmon.c} | 108 +++++----------- src/core/ddsi/src/ddsi_tkmap.c | 8 +- src/core/ddsi/src/q_config.c | 69 ++++------ src/core/ddsi/src/q_ddsi_discovery.c | 3 +- src/core/ddsi/src/q_debmon.c | 19 +-- src/core/ddsi/src/q_entity.c | 10 +- src/core/ddsi/src/q_gc.c | 24 ++-- src/core/ddsi/src/q_init.c | 19 +-- src/core/ddsi/src/q_lease.c | 2 +- src/core/ddsi/src/q_radmin.c | 9 +- src/core/ddsi/src/q_receive.c | 46 ++++--- src/core/ddsi/src/q_thread.c | 121 ++++++++++-------- src/core/ddsi/src/q_thread_inlines.c | 21 --- src/core/ddsi/src/q_transmit.c | 32 ++--- src/core/ddsi/src/q_xevent.c | 46 +++---- src/core/ddsi/src/q_xmsg.c | 2 +- src/core/ddsi/src/sysdeps.c | 12 +- src/core/xtests/rhc_torture.c | 27 ++-- 36 files changed, 450 insertions(+), 663 deletions(-) create mode 100644 src/core/ddsi/include/dds/ddsi/ddsi_threadmon.h delete mode 100644 src/core/ddsi/include/dds/ddsi/q_servicelease.h rename src/core/ddsi/src/{q_servicelease.c => ddsi_threadmon.c} (55%) delete mode 100644 src/core/ddsi/src/q_thread_inlines.c diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index 1cdb382..3f50c60 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -65,12 +65,11 @@ void dds__builtin_init (void) void dds__builtin_fini (void) { /* No more sources for builtin topic samples */ - struct thread_state1 * const self = lookup_thread_state (); - thread_state_awake (self); + thread_state_awake (lookup_thread_state ()); delete_local_orphan_writer (builtintopic_writer_participant); delete_local_orphan_writer (builtintopic_writer_publications); delete_local_orphan_writer (builtintopic_writer_subscriptions); - thread_state_asleep (self); + thread_state_asleep (lookup_thread_state ()); ddsi_sertopic_unref (builtin_participant_topic); ddsi_sertopic_unref (builtin_reader_topic); diff --git a/src/core/ddsc/src/dds_handles.c b/src/core/ddsc/src/dds_handles.c index 5e4acd3..560e661 100644 --- a/src/core/ddsc/src/dds_handles.c +++ b/src/core/ddsc/src/dds_handles.c @@ -117,12 +117,12 @@ static dds_handle_t dds_handle_create_int (struct dds_handle_link *link) dds_handle_t dds_handle_create (struct dds_handle_link *link) { +#if USE_CHH + struct thread_state1 * const ts1 = lookup_thread_state (); +#endif dds_handle_t ret; #if USE_CHH - struct thread_state1 * const self = lookup_thread_state (); - const bool asleep = vtime_asleep_p (self->vtime); - if (asleep) - thread_state_awake (self); + thread_state_awake (ts1); #endif ddsrt_mutex_lock (&handles.lock); if (handles.count == MAX_HANDLES) @@ -143,8 +143,7 @@ dds_handle_t dds_handle_create (struct dds_handle_link *link) assert (ret > 0); } #if USE_CHH - if (asleep) - thread_state_asleep (self); + thread_state_asleep (ts1); #endif return ret; } @@ -156,8 +155,10 @@ void dds_handle_close (struct dds_handle_link *link) int32_t dds_handle_delete (struct dds_handle_link *link, dds_duration_t timeout) { +#if USE_CHH + struct thread_state1 * const ts1 = lookup_thread_state (); +#endif assert (ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_FLAG_CLOSED); - ddsrt_mutex_lock (&handles.lock); if ((ddsrt_atomic_ld32 (&link->cnt_flags) & HDL_COUNT_MASK) != 0) { @@ -174,13 +175,9 @@ int32_t dds_handle_delete (struct dds_handle_link *link, dds_duration_t timeout) } } #if USE_CHH - struct thread_state1 * const self = lookup_thread_state (); - const bool asleep = vtime_asleep_p (self->vtime); - if (asleep) - thread_state_awake (self); + thread_state_awake (ts1); int x = ut_chhRemove (handles.ht, link); - if (asleep) - thread_state_asleep (self); + thread_state_asleep (ts1); #else int x = ut_hhRemove (handles.ht, link); #endif @@ -194,6 +191,9 @@ int32_t dds_handle_delete (struct dds_handle_link *link, dds_duration_t timeout) int32_t dds_handle_claim (dds_handle_t hdl, struct dds_handle_link **link) { +#if USE_CHH + struct thread_state1 * const ts1 = lookup_thread_state (); +#endif struct dds_handle_link dummy = { .hdl = hdl }; int32_t rc; /* it makes sense to check here for initialization: the first thing any operation @@ -208,10 +208,7 @@ int32_t dds_handle_claim (dds_handle_t hdl, struct dds_handle_link **link) return DDS_RETCODE_PRECONDITION_NOT_MET; #if USE_CHH - struct thread_state1 * const self = lookup_thread_state (); - const bool asleep = vtime_asleep_p (self->vtime); - if (asleep) - thread_state_awake (self); + thread_state_awake (ts1); *link = ut_chhLookup (handles.ht, &dummy); #else ddsrt_mutex_lock (&handles.lock); @@ -234,10 +231,8 @@ int32_t dds_handle_claim (dds_handle_t hdl, struct dds_handle_link **link) } } while (!ddsrt_atomic_cas32 (&(*link)->cnt_flags, cnt_flags, cnt_flags + 1)); } - #if USE_CHH - if (asleep) - thread_state_asleep (self); + thread_state_asleep (ts1); #else ddsrt_mutex_unlock (&handles.lock); #endif diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index 31a1c0a..1efd81d 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -26,7 +26,7 @@ #include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/ddsi_serdata.h" -#include "dds/ddsi/q_servicelease.h" +#include "dds/ddsi/ddsi_threadmon.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_gc.h" @@ -127,15 +127,15 @@ dds_init(dds_domainid_t domain) /* Start monitoring the liveliness of all threads. */ if (!config.liveliness_monitoring) - gv.servicelease = NULL; + gv.threadmon = NULL; else { - gv.servicelease = nn_servicelease_new(0, 0); - if (gv.servicelease == NULL) + gv.threadmon = ddsi_threadmon_new (); + if (gv.threadmon == NULL) { - DDS_ERROR("Failed to create a servicelease\n"); + DDS_ERROR("Failed to create a thread monitor\n"); ret = DDS_ERRNO(DDS_RETCODE_OUT_OF_RESOURCES); - goto fail_servicelease_new; + goto fail_threadmon_new; } } @@ -162,11 +162,11 @@ dds_init(dds_domainid_t domain) goto fail_rtps_start; } - if (gv.servicelease && nn_servicelease_start_renewing(gv.servicelease) < 0) + if (gv.threadmon && ddsi_threadmon_start(gv.threadmon) < 0) { DDS_ERROR("Failed to start the servicelease\n"); ret = DDS_ERRNO(DDS_RETCODE_ERROR); - goto fail_servicelease_start; + goto fail_threadmon_start; } /* Set additional default participant properties */ @@ -191,9 +191,9 @@ skip: ddsrt_mutex_unlock(init_mutex); return DDS_RETCODE_OK; -fail_servicelease_start: - if (gv.servicelease) - nn_servicelease_stop_renewing (gv.servicelease); +fail_threadmon_start: + if (gv.threadmon) + ddsi_threadmon_stop (gv.threadmon); dds_handle_server_fini(); fail_handleserver: rtps_stop (); @@ -201,12 +201,12 @@ fail_rtps_start: dds__builtin_fini (); rtps_fini (); fail_rtps_init: - if (gv.servicelease) + if (gv.threadmon) { - nn_servicelease_free (gv.servicelease); - gv.servicelease = NULL; + ddsi_threadmon_free (gv.threadmon); + gv.threadmon = NULL; } -fail_servicelease_new: +fail_threadmon_new: downgrade_main_thread (); thread_states_fini(); fail_rtps_config: @@ -231,15 +231,15 @@ extern void dds_fini (void) dds_global.m_init_count--; if (dds_global.m_init_count == 0) { - if (gv.servicelease) - nn_servicelease_stop_renewing (gv.servicelease); + if (gv.threadmon) + ddsi_threadmon_stop (gv.threadmon); dds_handle_server_fini(); rtps_stop (); dds__builtin_fini (); rtps_fini (); - if (gv.servicelease) - nn_servicelease_free (gv.servicelease); - gv.servicelease = NULL; + if (gv.threadmon) + ddsi_threadmon_free (gv.threadmon); + gv.threadmon = NULL; downgrade_main_thread (); thread_states_fini (); diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index 4ed3b20..5d15275 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -127,8 +127,7 @@ dds_register_instance( dds_instance_handle_t *handle, const void *data) { - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); + struct thread_state1 * const ts1 = lookup_thread_state (); struct ddsi_tkmap_instance * inst; dds_writer *wr; dds_return_t ret; @@ -150,9 +149,7 @@ dds_register_instance( ret = DDS_ERRNO(rc); goto err; } - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (ts1); inst = dds_instance_find (wr->m_topic, data, true); if(inst != NULL){ *handle = inst->m_iid; @@ -161,9 +158,7 @@ dds_register_instance( DDS_ERROR("Unable to create instance\n"); ret = DDS_ERRNO(DDS_RETCODE_ERROR); } - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (ts1); dds_writer_unlock(wr); err: return ret; @@ -191,8 +186,7 @@ dds_unregister_instance_ts( const void *data, dds_time_t timestamp) { - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); + struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret = DDS_RETCODE_OK; dds_retcode_t rc; bool autodispose = true; @@ -219,17 +213,13 @@ dds_unregister_instance_ts( if (wr->m_entity.m_qos) { dds_qget_writer_data_lifecycle (wr->m_entity.m_qos, &autodispose); } - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (ts1); if (autodispose) { dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL); action |= DDS_WR_DISPOSE_BIT; } ret = dds_write_impl (wr, data, timestamp, action); - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (ts1); dds_writer_unlock(wr); err: return ret; @@ -241,8 +231,7 @@ dds_unregister_instance_ih_ts( dds_instance_handle_t handle, dds_time_t timestamp) { - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); + struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret = DDS_RETCODE_OK; dds_retcode_t rc; bool autodispose = true; @@ -265,9 +254,7 @@ dds_unregister_instance_ih_ts( action |= DDS_WR_DISPOSE_BIT; } - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (ts1); tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle); if (tk) { struct ddsi_sertopic *tp = wr->m_topic->m_stopic; @@ -280,9 +267,7 @@ dds_unregister_instance_ih_ts( DDS_ERROR("No instance related with the provided handle is found\n"); ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); } - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (ts1); dds_writer_unlock(wr); err: return ret; @@ -294,24 +279,19 @@ dds_writedispose_ts( const void *data, dds_time_t timestamp) { + struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret; dds_retcode_t rc; dds_writer *wr; rc = dds_writer_lock(writer, &wr); if (rc == DDS_RETCODE_OK) { - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (ts1); ret = dds_write_impl (wr, data, timestamp, DDS_WR_ACTION_WRITE_DISPOSE); if (ret == DDS_RETCODE_OK) { dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL); } - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (ts1); dds_writer_unlock(wr); } else { DDS_ERROR("Error occurred on locking writer\n"); @@ -329,7 +309,7 @@ dds_dispose_impl( dds_time_t timestamp) { dds_return_t ret; - assert(vtime_awake_p(lookup_thread_state()->vtime)); + assert(thread_is_awake ()); assert(wr); ret = dds_write_impl(wr, data, timestamp, DDS_WR_ACTION_DISPOSE); if (ret == DDS_RETCODE_OK) { @@ -344,21 +324,16 @@ dds_dispose_ts( const void *data, dds_time_t timestamp) { + struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret; dds_retcode_t rc; dds_writer *wr; rc = dds_writer_lock(writer, &wr); if (rc == DDS_RETCODE_OK) { - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (ts1); ret = dds_dispose_impl(wr, data, DDS_HANDLE_NIL, timestamp); - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (ts1); dds_writer_unlock(wr); } else { DDS_ERROR("Error occurred on locking writer\n"); @@ -374,18 +349,15 @@ dds_dispose_ih_ts( dds_instance_handle_t handle, dds_time_t timestamp) { + struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret; dds_retcode_t rc; dds_writer *wr; rc = dds_writer_lock(writer, &wr); if (rc == DDS_RETCODE_OK) { - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); struct ddsi_tkmap_instance *tk; - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (ts1); if ((tk = ddsi_tkmap_find_by_id (gv.m_tkmap, handle)) != NULL) { struct ddsi_sertopic *tp = wr->m_topic->m_stopic; void *sample = ddsi_sertopic_alloc_sample (tp); @@ -397,9 +369,7 @@ dds_dispose_ih_ts( DDS_ERROR("No instance related with the provided handle is found\n"); ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); } - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (ts1); dds_writer_unlock(wr); } else { DDS_ERROR("Error occurred on locking writer\n"); @@ -414,6 +384,7 @@ dds_lookup_instance( dds_entity_t entity, const void *data) { + struct thread_state1 * const ts1 = lookup_thread_state (); dds_instance_handle_t ih = DDS_HANDLE_NIL; const dds_topic * topic; struct ddsi_tkmap * map = gv.m_tkmap; @@ -426,17 +397,11 @@ dds_lookup_instance( topic = dds_instance_info_by_hdl (entity); if (topic) { - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (ts1); sd = ddsi_serdata_from_sample (topic->m_stopic, SDK_KEY, data); ih = ddsi_tkmap_lookup (map, sd); ddsi_serdata_unref (sd); - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (ts1); } else { DDS_ERROR("Acquired topic is NULL\n"); } @@ -458,8 +423,7 @@ dds_instance_get_key( dds_instance_handle_t ih, void *data) { - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); + struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret; const dds_topic * topic; struct ddsi_tkmap_instance * tk; @@ -476,9 +440,7 @@ dds_instance_get_key( ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (ts1); if ((tk = ddsi_tkmap_find_by_id(gv.m_tkmap, ih)) != NULL) { ddsi_sertopic_zero_sample (topic->m_stopic, data); ddsi_serdata_topicless_to_sample (topic->m_stopic, tk->m_sample, data, NULL, NULL); @@ -488,9 +450,7 @@ dds_instance_get_key( DDS_ERROR("No instance related with the provided entity is found\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); } - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (ts1); err: return ret; } diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index 35521c0..587951a 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -48,18 +48,13 @@ static dds_return_t dds_participant_delete( dds_entity *e) { - struct thread_state1 * const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); dds_entity *prev = NULL; dds_entity *iter; assert(e); - assert(thr); assert(dds_entity_kind(e) == DDS_KIND_PARTICIPANT); - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (lookup_thread_state ()); dds_domain_free (e->m_domain); @@ -81,9 +76,7 @@ dds_participant_delete( assert (iter); - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (lookup_thread_state ()); /* Every dds_init needs a dds_fini. */ dds_fini(); @@ -155,8 +148,6 @@ dds_create_participant( dds_participant * pp; nn_plist_t plist; dds_qos_t * new_qos = NULL; - struct thread_state1 * thr; - bool asleep; /* Make sure DDS instance is initialized. */ ret = dds_init(domain); @@ -192,15 +183,9 @@ dds_create_participant( nn_plist_init_empty(&plist); dds_merge_qos (&plist.qos, new_qos); - thr = lookup_thread_state (); - asleep = !vtime_awake_p (thr->vtime); - if (asleep) { - thread_state_awake (thr); - } + thread_state_awake (lookup_thread_state ()); q_rc = new_participant (&guid, 0, &plist); - if (asleep) { - thread_state_asleep (thr); - } + thread_state_asleep (lookup_thread_state ()); nn_plist_fini (&plist); if (q_rc != 0) { DDS_ERROR("Internal error"); diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index af239f6..b4c5adf 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -88,16 +88,12 @@ dds_read_impl( bool lock, bool only_reader) { + struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret = DDS_RETCODE_OK; dds_retcode_t rc; struct dds_reader * rd; struct dds_readcond * cond; - struct thread_state1 * const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); - if (asleep) { - thread_state_awake (thr); - } if (buf == NULL) { DDS_ERROR("The provided buffer is NULL\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); @@ -124,18 +120,19 @@ dds_read_impl( goto fail; } + thread_state_awake (ts1); rc = dds_read_lock(reader_or_condition, &rd, &cond, only_reader); if (rc != DDS_RETCODE_OK) { DDS_ERROR("Error occurred on locking entity\n"); ret = DDS_ERRNO(rc); - goto fail; + goto fail_awake; } if (hand != DDS_HANDLE_NIL) { if (ddsi_tkmap_find_by_id(gv.m_tkmap, hand) == NULL) { DDS_ERROR("Could not find instance\n"); ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); dds_read_unlock(rd, cond); - goto fail; + goto fail_awake; } } /* Allocate samples if not provided (assuming all or none provided) */ @@ -173,10 +170,9 @@ dds_read_impl( } dds_read_unlock(rd, cond); +fail_awake: + thread_state_asleep (ts1); fail: - if (asleep) { - thread_state_asleep (thr); - } return ret; } @@ -191,12 +187,11 @@ dds_readcdr_impl( dds_instance_handle_t hand, bool lock) { + struct thread_state1 * const ts1 = lookup_thread_state (); dds_return_t ret = DDS_RETCODE_OK; dds_retcode_t rc; struct dds_reader * rd; struct dds_readcond * cond; - struct thread_state1 * const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); assert (take); assert (buf); @@ -205,10 +200,7 @@ dds_readcdr_impl( assert (maxs > 0); (void)take; - if (asleep) - { - thread_state_awake (thr); - } + thread_state_awake (ts1); rc = dds_read_lock(reader_or_condition, &rd, &cond, false); if (rc >= DDS_RETCODE_OK) { ret = dds_rhc_takecdr @@ -235,11 +227,7 @@ dds_readcdr_impl( ret = DDS_ERRNO(rc); } - if (asleep) - { - thread_state_asleep (thr); - } - + thread_state_asleep (ts1); return ret; } diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index bd16e39..2c14994 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -54,23 +54,16 @@ dds_reader_close( { dds_retcode_t rc; dds_return_t ret = DDS_RETCODE_OK; - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); assert(e); - assert(thr); - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (lookup_thread_state ()); if (delete_reader(&e->m_guid) != 0) { DDS_ERROR("Internal error"); rc = DDS_RETCODE_ERROR; ret = DDS_ERRNO(rc); } - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (lookup_thread_state ()); return ret; } @@ -368,8 +361,6 @@ dds_create_reader( dds_topic * tp; dds_entity_t reader; dds_entity_t t; - struct thread_state1 * const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); dds_return_t ret = DDS_RETCODE_OK; bool internal_topic; @@ -474,17 +465,13 @@ dds_create_reader( ddsrt_mutex_unlock(&tp->m_entity.m_mutex); ddsrt_mutex_unlock(&sub->m_entity.m_mutex); - if (asleep) { - thread_state_awake (thr); - } + thread_state_awake (lookup_thread_state ()); rd->m_rd = new_reader(&rd->m_entity.m_guid, NULL, &sub->m_entity.m_participant->m_guid, tp->m_stopic, rqos, rhc, dds_reader_status_cb, rd); ddsrt_mutex_lock(&sub->m_entity.m_mutex); ddsrt_mutex_lock(&tp->m_entity.m_mutex); assert (rd->m_rd); - if (asleep) { - thread_state_asleep (thr); - } + thread_state_asleep (lookup_thread_state ()); /* For persistent data register reader with durability */ if (dds_global.m_dur_reader && (rd->m_entity.m_qos->durability.kind > NN_TRANSIENT_LOCAL_DURABILITY_QOS)) { diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index acd36ac..1561afd 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -313,8 +313,6 @@ dds_create_topic_arbitrary ( dds_qos_t *new_qos = NULL; dds_entity_t hdl; struct participant *ddsi_pp; - struct thread_state1 *const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); if (sertopic == NULL){ DDS_ERROR("Topic description is NULL\n"); @@ -389,17 +387,13 @@ dds_create_topic_arbitrary ( ddsrt_mutex_unlock (&dds_global.m_mutex); /* Publish Topic */ - if (asleep) { - thread_state_awake (thr); - } + thread_state_awake (lookup_thread_state ()); ddsi_pp = ephash_lookup_participant_guid (&par->m_guid); assert (ddsi_pp); if (sedp_plist) { sedp_write_topic (ddsi_pp, sedp_plist); } - if (asleep) { - thread_state_asleep (thr); - } + thread_state_asleep (lookup_thread_state ()); } qos_err: diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index 3f3bb5e..3c1526c 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -148,8 +148,7 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstamp, dds_write_action action) { - struct thread_state1 * const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); + struct thread_state1 * const ts1 = lookup_thread_state (); const bool writekey = action & DDS_WR_KEY_BIT; struct writer *ddsi_wr = wr->m_wr; struct ddsi_tkmap_instance *tk; @@ -168,8 +167,7 @@ dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstam if (!(wr->m_topic->filter_fn) (data, wr->m_topic->filter_ctx)) return DDS_RETCODE_OK; - if (asleep) - thread_state_awake (thr); + thread_state_awake (ts1); /* Serialize and write data or key */ d = ddsi_serdata_from_sample (ddsi_wr->topic, writekey ? SDK_KEY : SDK_DATA, data); @@ -177,7 +175,7 @@ dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstam d->timestamp.v = tstamp; ddsi_serdata_ref (d); tk = ddsi_tkmap_lookup_instance_ref (d); - w_rc = write_sample_gc (wr->m_xp, ddsi_wr, d, tk); + w_rc = write_sample_gc (ts1, wr->m_xp, ddsi_wr, d, tk); if (w_rc >= 0) { @@ -199,26 +197,21 @@ dds_return_t dds_write_impl (dds_writer *wr, const void * data, dds_time_t tstam ret = deliver_locally (ddsi_wr, d, tk); ddsi_serdata_unref (d); ddsi_tkmap_instance_unref (tk); - - if (asleep) - thread_state_asleep (thr); + thread_state_asleep (ts1); return ret; } dds_return_t dds_writecdr_impl_lowlevel (struct writer *ddsi_wr, struct nn_xpack *xp, struct ddsi_serdata *d) { - struct thread_state1 * const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); + struct thread_state1 * const ts1 = lookup_thread_state (); struct ddsi_tkmap_instance * tk; int ret = DDS_RETCODE_OK; int w_rc; - if (asleep) - thread_state_awake (thr); - + thread_state_awake (ts1); ddsi_serdata_ref (d); tk = ddsi_tkmap_lookup_instance_ref (d); - w_rc = write_sample_gc (xp, ddsi_wr, d, tk); + w_rc = write_sample_gc (ts1, xp, ddsi_wr, d, tk); if (w_rc >= 0) { /* Flush out write unless configured to batch */ if (!config.whc_batch && xp != NULL) @@ -239,10 +232,7 @@ dds_return_t dds_writecdr_impl_lowlevel (struct writer *ddsi_wr, struct nn_xpack ret = deliver_locally (ddsi_wr, d, tk); ddsi_serdata_unref (d); ddsi_tkmap_instance_unref (tk); - - if (asleep) - thread_state_asleep (thr); - + thread_state_asleep (ts1); return ret; } @@ -263,13 +253,10 @@ void dds_write_set_batch (bool enable) void dds_write_flush (dds_entity_t writer) { - struct thread_state1 * const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); + struct thread_state1 * const ts1 = lookup_thread_state (); dds_writer *wr; dds_retcode_t rc; - - if (asleep) - thread_state_awake (thr); + thread_state_awake (ts1); if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) DDS_ERROR ("Error occurred on locking writer\n"); else @@ -277,8 +264,5 @@ void dds_write_flush (dds_entity_t writer) nn_xpack_send (wr->m_xp, true); dds_writer_unlock (wr); } - - if (asleep) - thread_state_asleep (thr); - return; + thread_state_asleep (ts1); } diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index f804fe1..06a13ef 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -192,24 +192,16 @@ dds_writer_close( { dds_return_t ret = DDS_RETCODE_OK; dds_writer *wr = (dds_writer*)e; - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = thr ? !vtime_awake_p(thr->vtime) : false; assert(e); - if (asleep) { - thread_state_awake(thr); - } - if (thr) { - nn_xpack_send (wr->m_xp, false); - } + thread_state_awake (lookup_thread_state ()); + nn_xpack_send (wr->m_xp, false); if (delete_writer (&e->m_guid) != 0) { DDS_ERROR("Internal error"); ret = DDS_ERRNO(DDS_RETCODE_ERROR); } - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (lookup_thread_state ()); return ret; } @@ -218,24 +210,11 @@ dds_writer_delete( dds_entity *e) { dds_writer *wr = (dds_writer*)e; - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = thr ? !vtime_awake_p(thr->vtime) : false; dds_return_t ret; - - assert(e); - assert(thr); - /* FIXME: not freeing WHC here because it is owned by the DDSI entity */ - - if (asleep) { - thread_state_awake(thr); - } - if (thr) { - nn_xpack_free(wr->m_xp); - } - if (asleep) { - thread_state_asleep(thr); - } + thread_state_awake (lookup_thread_state ()); + nn_xpack_free(wr->m_xp); + thread_state_asleep (lookup_thread_state ()); ret = dds_delete(wr->m_topic->m_entity.m_hdllink.hdl); if(ret == DDS_RETCODE_OK){ ret = dds_delete_impl(e->m_parent->m_hdllink.hdl, true); @@ -304,15 +283,11 @@ dds_writer_qos_set( dds_qget_ownership (e->m_qos, &kind); if (kind == DDS_OWNERSHIP_EXCLUSIVE) { - struct thread_state1 * const thr = lookup_thread_state (); - const bool asleep = !vtime_awake_p (thr->vtime); struct writer * ddsi_wr = ((dds_writer*)e)->m_wr; dds_qset_ownership_strength (e->m_qos, qos->ownership_strength.value); - if (asleep) { - thread_state_awake (thr); - } + thread_state_awake (lookup_thread_state ()); /* FIXME: with QoS changes being unsupported by the underlying stack I wonder what will happen; locking the underlying DDSI writer is of doubtful value as well */ ddsrt_mutex_lock (&ddsi_wr->e.lock); @@ -320,10 +295,7 @@ dds_writer_qos_set( ddsi_wr->xqos->ownership_strength.value = qos->ownership_strength.value; } ddsrt_mutex_unlock (&ddsi_wr->e.lock); - - if (asleep) { - thread_state_asleep (thr); - } + thread_state_asleep (lookup_thread_state ()); } else { DDS_ERROR("Setting ownership strength doesn't make sense when the ownership is shared\n"); ret = DDS_ERRNO(DDS_RETCODE_ERROR); @@ -403,8 +375,6 @@ dds_create_writer( dds_publisher * pub = NULL; dds_topic * tp; dds_entity_t publisher; - struct thread_state1 * const thr = lookup_thread_state(); - const bool asleep = !vtime_awake_p(thr->vtime); ddsi_tran_conn_t conn = gv.data_conn_uc; dds_return_t ret; @@ -485,16 +455,12 @@ dds_create_writer( ddsrt_mutex_unlock (&tp->m_entity.m_mutex); ddsrt_mutex_unlock (&pub->m_entity.m_mutex); - if (asleep) { - thread_state_awake(thr); - } + thread_state_awake (lookup_thread_state ()); wr->m_wr = new_writer(&wr->m_entity.m_guid, NULL, &pub->m_entity.m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); ddsrt_mutex_lock (&pub->m_entity.m_mutex); ddsrt_mutex_lock (&tp->m_entity.m_mutex); assert(wr->m_wr); - if (asleep) { - thread_state_asleep(thr); - } + thread_state_asleep (lookup_thread_state ()); dds_topic_unlock(tp); dds_publisher_unlock(pub); return writer; diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 683ad6e..4a6bb0f 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -26,6 +26,7 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" ddsi_iid.c ddsi_tkmap.c ddsi_vendor.c + ddsi_threadmon.c q_addrset.c q_bitset_inlines.c q_bswap.c @@ -47,10 +48,8 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" q_radmin.c q_receive.c q_security.c - q_servicelease.c q_sockwaitset.c q_thread.c - q_thread_inlines.c q_time.c q_transmit.c q_inverse_uint32_set.c @@ -78,6 +77,7 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" ddsi_iid.h ddsi_tkmap.h ddsi_vendor.h + ddsi_threadmon.h q_addrset.h q_bitset.h q_bswap.h @@ -105,7 +105,6 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" q_receive.h q_rtps.h q_security.h - q_servicelease.h q_sockwaitset.h q_static_assert.h q_thread.h diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_threadmon.h b/src/core/ddsi/include/dds/ddsi/ddsi_threadmon.h new file mode 100644 index 0000000..7d9d346 --- /dev/null +++ b/src/core/ddsi/include/dds/ddsi/ddsi_threadmon.h @@ -0,0 +1,31 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSI_THREADMON_H +#define DDSI_THREADMON_H + +#if defined (__cplusplus) +extern "C" { +#endif + +struct ddsi_threadmon; + +struct ddsi_threadmon *ddsi_threadmon_new (void); +int ddsi_threadmon_start (struct ddsi_threadmon *sl); +void ddsi_threadmon_stop (struct ddsi_threadmon *sl); +void ddsi_threadmon_free (struct ddsi_threadmon *sl); +void ddsi_threadmon_statechange_barrier (struct ddsi_threadmon *sl); + +#if defined (__cplusplus) +} +#endif + +#endif /* DDSI_THREADMON_H */ diff --git a/src/core/ddsi/include/dds/ddsi/q_config.h b/src/core/ddsi/include/dds/ddsi/q_config.h index c37a40e..c313682 100644 --- a/src/core/ddsi/include/dds/ddsi/q_config.h +++ b/src/core/ddsi/include/dds/ddsi/q_config.h @@ -267,6 +267,7 @@ struct config int forward_all_messages; int liveliness_monitoring; int noprogress_log_stacktraces; + int64_t liveliness_monitoring_interval; int prioritize_retransmit; int xpack_send_async; int multiple_recv_threads; @@ -277,9 +278,6 @@ struct config unsigned delivery_queue_maxsamples; - float servicelease_expiry_time; - float servicelease_update_factor; - int enableLoopback; enum durability_cdr durability_cdr; diff --git a/src/core/ddsi/include/dds/ddsi/q_globals.h b/src/core/ddsi/include/dds/ddsi/q_globals.h index 177793c..770c569 100644 --- a/src/core/ddsi/include/dds/ddsi/q_globals.h +++ b/src/core/ddsi/include/dds/ddsi/q_globals.h @@ -105,7 +105,7 @@ struct q_globals { /* Queue for garbage collection requests */ struct gcreq_queue *gcreq_queue; - struct nn_servicelease *servicelease; + struct ddsi_threadmon *threadmon; /* Lease junk */ ddsrt_mutex_t leaseheap_lock; diff --git a/src/core/ddsi/include/dds/ddsi/q_lease.h b/src/core/ddsi/include/dds/ddsi/q_lease.h index 2a24abe..a139075 100644 --- a/src/core/ddsi/include/dds/ddsi/q_lease.h +++ b/src/core/ddsi/include/dds/ddsi/q_lease.h @@ -22,7 +22,6 @@ struct receiver_state; struct participant; struct lease; struct entity_common; -struct thread_state1; void lease_management_init (void); void lease_management_term (void); @@ -31,7 +30,7 @@ void lease_register (struct lease *l); void lease_free (struct lease *l); void lease_renew (struct lease *l, nn_etime_t tnow); void lease_set_expiry (struct lease *l, nn_etime_t when); -int64_t check_and_handle_lease_expiration (struct thread_state1 *self, nn_etime_t tnow); +int64_t check_and_handle_lease_expiration (nn_etime_t tnow); void handle_PMD (const struct receiver_state *rst, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len); diff --git a/src/core/ddsi/include/dds/ddsi/q_servicelease.h b/src/core/ddsi/include/dds/ddsi/q_servicelease.h deleted file mode 100644 index bc9c15d..0000000 --- a/src/core/ddsi/include/dds/ddsi/q_servicelease.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef NN_SERVICELEASE_H -#define NN_SERVICELEASE_H - -#if defined (__cplusplus) -extern "C" { -#endif - -struct nn_servicelease; - -struct nn_servicelease *nn_servicelease_new (void (*renew_cb) (void *arg), void *renew_arg); -int nn_servicelease_start_renewing (struct nn_servicelease *sl); -void nn_servicelease_stop_renewing (struct nn_servicelease *sl); -void nn_servicelease_free (struct nn_servicelease *sl); -void nn_servicelease_statechange_barrier (struct nn_servicelease *sl); - -#if defined (__cplusplus) -} -#endif - -#endif /* NN_SERVICELEASE_H */ diff --git a/src/core/ddsi/include/dds/ddsi/q_thread.h b/src/core/ddsi/include/dds/ddsi/q_thread.h index fef01ea..71c9e5e 100644 --- a/src/core/ddsi/include/dds/ddsi/q_thread.h +++ b/src/core/ddsi/include/dds/ddsi/q_thread.h @@ -12,6 +12,7 @@ #ifndef Q_THREAD_H #define Q_THREAD_H +#include #include "dds/export.h" #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/sync.h" @@ -30,6 +31,9 @@ extern "C" { typedef uint32_t vtime_t; typedef int32_t svtime_t; /* signed version */ +#define VTIME_NEST_MASK 0xfu +#define VTIME_TIME_MASK 0xfffffff0u +#define VTIME_TIME_SHIFT 4 /* GCC has a nifty feature allowing the specification of the required alignment: __attribute__ ((aligned (CACHE_LINE_SIZE))) in this @@ -59,7 +63,6 @@ struct logbuf; */ #define THREAD_BASE \ volatile vtime_t vtime; \ - volatile vtime_t watchdog; \ ddsrt_thread_t tid; \ ddsrt_thread_t extTid; \ enum thread_state state; \ @@ -94,8 +97,7 @@ DDS_EXPORT void thread_states_fini (void); DDS_EXPORT void upgrade_main_thread (void); DDS_EXPORT void downgrade_main_thread (void); DDS_EXPORT const struct config_thread_properties_listelem *lookup_thread_properties (const char *name); -DDS_EXPORT struct thread_state1 *create_thread (const char *name, uint32_t (*f) (void *arg), void *arg); -DDS_EXPORT struct thread_state1 *lookup_thread_state (void); +DDS_EXPORT dds_retcode_t create_thread (struct thread_state1 **ts, const char *name, uint32_t (*f) (void *arg), void *arg); DDS_EXPORT struct thread_state1 *lookup_thread_state_real (void); DDS_EXPORT int join_thread (struct thread_state1 *ts1); DDS_EXPORT void log_stack_traces (void); @@ -104,83 +106,69 @@ DDS_EXPORT struct thread_state1 * init_thread_state (const char *tname); DDS_EXPORT void reset_thread_state (struct thread_state1 *ts1); DDS_EXPORT int thread_exists (const char *name); -DDS_EXPORT inline int vtime_awake_p (vtime_t vtime) -{ - return (vtime % 2) == 0; +DDS_EXPORT inline struct thread_state1 *lookup_thread_state (void) { + struct thread_state1 *ts1 = tsd_thread_state; + if (ts1) + return ts1; + else + return lookup_thread_state_real (); } -DDS_EXPORT inline int vtime_asleep_p (vtime_t vtime) +DDS_EXPORT inline bool vtime_awake_p (vtime_t vtime) { - return (vtime % 2) == 1; + return (vtime & VTIME_NEST_MASK) != 0; } -DDS_EXPORT inline int vtime_gt (vtime_t vtime1, vtime_t vtime0) +DDS_EXPORT inline bool vtime_asleep_p (vtime_t vtime) +{ + return (vtime & VTIME_NEST_MASK) == 0; +} + +DDS_EXPORT inline bool vtime_gt (vtime_t vtime1, vtime_t vtime0) { Q_STATIC_ASSERT_CODE (sizeof (vtime_t) == sizeof (svtime_t)); - return (svtime_t) (vtime1 - vtime0) > 0; + return (svtime_t) ((vtime1 & VTIME_TIME_MASK) - (vtime0 & VTIME_TIME_MASK)) > 0; +} + +DDS_EXPORT inline bool thread_is_awake (void) +{ + return vtime_awake_p (lookup_thread_state ()->vtime); +} + +DDS_EXPORT inline bool thread_is_asleep (void) +{ + return vtime_asleep_p (lookup_thread_state ()->vtime); } DDS_EXPORT inline void thread_state_asleep (struct thread_state1 *ts1) { vtime_t vt = ts1->vtime; - vtime_t wd = ts1->watchdog; - if (vtime_awake_p (vt)) - { - ddsrt_atomic_fence_rel (); - ts1->vtime = vt + 1; - } + assert (vtime_awake_p (vt)); + /* nested calls a rare and an extra fence doesn't break things */ + ddsrt_atomic_fence_rel (); + if ((vt & VTIME_NEST_MASK) == 1) + vt += (1u << VTIME_TIME_SHIFT) - 1u; else - { - ddsrt_atomic_fence_rel (); - ts1->vtime = vt + 2; - ddsrt_atomic_fence_acq (); - } - - if ( wd % 2 ){ - ts1->watchdog = wd + 2; - } else { - ts1->watchdog = wd + 1; - } + vt -= 1u; + ts1->vtime = vt; } DDS_EXPORT inline void thread_state_awake (struct thread_state1 *ts1) { vtime_t vt = ts1->vtime; - vtime_t wd = ts1->watchdog; - if (vtime_asleep_p (vt)) - ts1->vtime = vt + 1; - else - { - ddsrt_atomic_fence_rel (); - ts1->vtime = vt + 2; - } + assert ((vt & VTIME_NEST_MASK) < VTIME_NEST_MASK); + ts1->vtime = vt + 1u; + /* nested calls a rare and an extra fence doesn't break things */ ddsrt_atomic_fence_acq (); - - if ( wd % 2 ){ - ts1->watchdog = wd + 1; - } else { - ts1->watchdog = wd + 2; - } } -DDS_EXPORT inline void thread_state_blocked (struct thread_state1 *ts1) +DDS_EXPORT inline void thread_state_awake_to_awake_no_nest (struct thread_state1 *ts1) { - vtime_t wd = ts1->watchdog; - if ( wd % 2 ){ - ts1->watchdog = wd + 2; - } else { - ts1->watchdog = wd + 1; - } -} - -DDS_EXPORT inline void thread_state_unblocked (struct thread_state1 *ts1) -{ - vtime_t wd = ts1->watchdog; - if ( wd % 2 ){ - ts1->watchdog = wd + 1; - } else { - ts1->watchdog = wd + 2; - } + vtime_t vt = ts1->vtime; + assert ((vt & VTIME_NEST_MASK) == 1); + ddsrt_atomic_fence_rel (); + ts1->vtime = vt + (1u << VTIME_TIME_SHIFT); + ddsrt_atomic_fence_acq (); } #if defined (__cplusplus) diff --git a/src/core/ddsi/include/dds/ddsi/q_transmit.h b/src/core/ddsi/include/dds/ddsi/q_transmit.h index 14330a2..19cc947 100644 --- a/src/core/ddsi/include/dds/ddsi/q_transmit.h +++ b/src/core/ddsi/include/dds/ddsi/q_transmit.h @@ -25,6 +25,7 @@ struct whc_state; struct proxy_reader; struct ddsi_serdata; struct ddsi_tkmap_instance; +struct thread_state1; /* Writing new data; serdata_twrite (serdata) is assumed to be really recentish; serdata is unref'd. If xp == NULL, data is queued, else @@ -33,10 +34,10 @@ struct ddsi_tkmap_instance; "nogc": no GC may occur, so it may not block to throttle the writer if the high water mark of the WHC is reached, which implies true KEEP_LAST behaviour. This is true for all the DDSI built-in writers. "gc": GC may occur, which means the writer history and watermarks can be anything. This must be used for all application data. */ -int write_sample_gc (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk); -int write_sample_nogc (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk); -int write_sample_gc_notk (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata); -int write_sample_nogc_notk (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata); +int write_sample_gc (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk); +int write_sample_nogc (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk); +int write_sample_gc_notk (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata); +int write_sample_nogc_notk (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata); /* When calling the following functions, wr->lock must be held */ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_plist *plist, struct ddsi_serdata *serdata, unsigned fragnum, struct proxy_reader *prd,struct nn_xmsg **msg, int isnew); diff --git a/src/core/ddsi/src/q_servicelease.c b/src/core/ddsi/src/ddsi_threadmon.c similarity index 55% rename from src/core/ddsi/src/q_servicelease.c rename to src/core/ddsi/src/ddsi_threadmon.c index 2ab892a..755848c 100644 --- a/src/core/ddsi/src/q_servicelease.c +++ b/src/core/ddsi/src/ddsi_threadmon.c @@ -15,7 +15,7 @@ #include "dds/ddsrt/sync.h" #include "dds/ddsrt/threads.h" -#include "dds/ddsi/q_servicelease.h" +#include "dds/ddsi/ddsi_threadmon.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_thread.h" @@ -25,32 +25,14 @@ #include "dds/ddsi/q_globals.h" /* for mattr, cattr */ #include "dds/ddsi/q_receive.h" -static dds_time_t nn_retrieve_lease_settings (void) -{ - const double leaseSec = config.servicelease_expiry_time; - double sleepSec = leaseSec * config.servicelease_update_factor; - - /* Run at no less than 1Hz: internal liveliness monitoring is slaved - to this interval as well. 1Hz lease renewals and liveliness - checks is no large burden, and performing liveliness checks once - a second is a lot more useful than doing it once every few - seconds. Besides -- we're now also gathering CPU statistics. */ - if (sleepSec > 1.0f) - return DDS_NSECS_IN_SEC; - - return ((dds_time_t)(sleepSec * DDS_NSECS_IN_SEC)) + - ((dds_time_t)(sleepSec * (double)DDS_NSECS_IN_SEC) % DDS_NSECS_IN_SEC); -} - -struct alive_wd { - char alive; - vtime_t wd; +struct alive_vt { + bool alive; + vtime_t vt; }; -struct nn_servicelease { - dds_time_t sleepTime; +struct ddsi_threadmon { int keepgoing; - struct alive_wd *av_ary; + struct alive_vt *av_ary; void (*renew_cb) (void *arg); void *renew_arg; @@ -59,37 +41,38 @@ struct nn_servicelease { struct thread_state1 *ts; }; -static uint32_t lease_renewal_thread (struct nn_servicelease *sl) +static uint32_t threadmon_thread (struct ddsi_threadmon *sl) { /* Do not check more often than once every 100ms (no particular reason why it has to be 100ms), regardless of the lease settings. Note: can't trust sl->self, may have been scheduled before the assignment. */ - const int64_t min_progress_check_intv = 100 * T_MILLISECOND; - struct thread_state1 *self = lookup_thread_state (); nn_mtime_t next_thread_cputime = { 0 }; nn_mtime_t tlast = { 0 }; - int was_alive = 1; + bool was_alive = true; unsigned i; for (i = 0; i < thread_states.nthreads; i++) { - sl->av_ary[i].alive = 1; - sl->av_ary[i].wd = thread_states.ts[i].watchdog - 1; + sl->av_ary[i].alive = true; } ddsrt_mutex_lock (&sl->lock); while (sl->keepgoing) { + /* Guard against spurious wakeups by checking only when cond_waitfor signals a timeout */ + if (ddsrt_cond_waitfor (&sl->cond, &sl->lock, config.liveliness_monitoring_interval)) + continue; + unsigned n_alive = 0; nn_mtime_t tnow = now_mt (); LOG_THREAD_CPUTIME (next_thread_cputime); - DDS_TRACE("servicelease: tnow %"PRId64":", tnow.v); + DDS_TRACE("threadmon: tnow %"PRId64":", tnow.v); /* Check progress only if enough time has passed: there is no guarantee that os_cond_timedwait wont ever return early, and we do want to avoid spurious warnings. */ - if (tnow.v < tlast.v + min_progress_check_intv) + if (tnow.v < tlast.v) { n_alive = thread_states.nthreads; } @@ -103,11 +86,10 @@ static uint32_t lease_renewal_thread (struct nn_servicelease *sl) else { vtime_t vt = thread_states.ts[i].vtime; - vtime_t wd = thread_states.ts[i].watchdog; - int alive = vtime_asleep_p (vt) || vtime_asleep_p (wd) || vtime_gt (wd, sl->av_ary[i].wd); + bool alive = vtime_asleep_p (vt) || vtime_asleep_p (sl->av_ary[i].vt) || vtime_gt (vt, sl->av_ary[i].vt); n_alive += (unsigned) alive; - DDS_TRACE(" %u(%s):%c:%u:%u->%u:", i, thread_states.ts[i].name, alive ? 'a' : 'd', vt, sl->av_ary[i].wd, wd); - sl->av_ary[i].wd = wd; + DDS_TRACE(" %u(%s):%c:%x->%x", i, thread_states.ts[i].name, alive ? 'a' : 'd', sl->av_ary[i].vt, vt); + sl->av_ary[i].vt = vt; if (sl->av_ary[i].alive != alive) { const char *name = thread_states.ts[i].name; @@ -117,31 +99,23 @@ static uint32_t lease_renewal_thread (struct nn_servicelease *sl) else msg = "once again made progress"; DDS_INFO("thread %s %s\n", name ? name : "(anon)", msg); - sl->av_ary[i].alive = (char) alive; + sl->av_ary[i].alive = alive; } } } } - /* Only renew the lease if all threads are alive, so that one - thread blocking for a while but not too extremely long will - cause warnings for that thread in the log file, but won't cause - the DDSI2 service to be marked as dead. */ if (n_alive == thread_states.nthreads) { - DDS_TRACE(": [%u] renewing\n", n_alive); - /* FIXME: perhaps it would be nice to control automatic - liveliness updates from here. - FIXME: should terminate failure of renew_cb() */ - sl->renew_cb (sl->renew_arg); - was_alive = 1; + DDS_TRACE(": [%u] OK\n", n_alive); + was_alive = true; } else { - DDS_TRACE(": [%u] NOT renewing\n", n_alive); + DDS_TRACE(": [%u] FAIL\n", n_alive); if (was_alive) log_stack_traces (); - was_alive = 0; + was_alive = false; } if (dds_get_log_mask() & DDS_LC_TIMING) @@ -151,20 +125,14 @@ static uint32_t lease_renewal_thread (struct nn_servicelease *sl) { DDS_LOG(DDS_LC_TIMING, "rusage: utime %d.%09d stime %d.%09d maxrss %ld data %ld vcsw %ld ivcsw %ld\n", - (int) u.utime / DDS_NSECS_IN_SEC, - (int) u.utime % DDS_NSECS_IN_SEC, - (int) u.stime / DDS_NSECS_IN_SEC, - (int) u.stime % DDS_NSECS_IN_SEC, + (int) (u.utime / DDS_NSECS_IN_SEC), + (int) (u.utime % DDS_NSECS_IN_SEC), + (int) (u.stime / DDS_NSECS_IN_SEC), + (int) (u.stime % DDS_NSECS_IN_SEC), u.maxrss, u.idrss, u.nvcsw, u.nivcsw); } } - ddsrt_cond_waitfor (&sl->cond, &sl->lock, sl->sleepTime); - - /* We are never active in a way that matters for the garbage - collection of old writers, &c. */ - thread_state_asleep (self); - /* While deaf, we need to make sure the receive thread wakes up every now and then to try recreating sockets & rejoining multicast groups */ @@ -175,19 +143,12 @@ static uint32_t lease_renewal_thread (struct nn_servicelease *sl) return 0; } -static void dummy_renew_cb (UNUSED_ARG (void *arg)) +struct ddsi_threadmon *ddsi_threadmon_new (void) { -} - -struct nn_servicelease *nn_servicelease_new (void (*renew_cb) (void *arg), void *renew_arg) -{ - struct nn_servicelease *sl; + struct ddsi_threadmon *sl; sl = ddsrt_malloc (sizeof (*sl)); - sl->sleepTime = nn_retrieve_lease_settings (); sl->keepgoing = -1; - sl->renew_cb = renew_cb ? renew_cb : dummy_renew_cb; - sl->renew_arg = renew_arg; sl->ts = NULL; if ((sl->av_ary = ddsrt_malloc (thread_states.nthreads * sizeof (*sl->av_ary))) == NULL) @@ -203,15 +164,14 @@ struct nn_servicelease *nn_servicelease_new (void (*renew_cb) (void *arg), void return NULL; } -int nn_servicelease_start_renewing (struct nn_servicelease *sl) +int ddsi_threadmon_start (struct ddsi_threadmon *sl) { ddsrt_mutex_lock (&sl->lock); assert (sl->keepgoing == -1); sl->keepgoing = 1; ddsrt_mutex_unlock (&sl->lock); - sl->ts = create_thread ("lease", (uint32_t (*) (void *)) lease_renewal_thread, sl); - if (sl->ts == NULL) + if (create_thread (&sl->ts, "lease", (uint32_t (*) (void *)) threadmon_thread, sl) != DDS_RETCODE_OK) goto fail_thread; return 0; @@ -220,13 +180,13 @@ int nn_servicelease_start_renewing (struct nn_servicelease *sl) return Q_ERR_UNSPECIFIED; } -void nn_servicelease_statechange_barrier (struct nn_servicelease *sl) +void ddsi_threadmon_statechange_barrier (struct ddsi_threadmon *sl) { ddsrt_mutex_lock (&sl->lock); ddsrt_mutex_unlock (&sl->lock); } -void nn_servicelease_stop_renewing (struct nn_servicelease *sl) +void ddsi_threadmon_stop (struct ddsi_threadmon *sl) { if (sl->keepgoing != -1) { @@ -238,7 +198,7 @@ void nn_servicelease_stop_renewing (struct nn_servicelease *sl) } } -void nn_servicelease_free (struct nn_servicelease *sl) +void ddsi_threadmon_free (struct ddsi_threadmon *sl) { ddsrt_cond_destroy (&sl->cond); ddsrt_mutex_destroy (&sl->lock); diff --git a/src/core/ddsi/src/ddsi_tkmap.c b/src/core/ddsi/src/ddsi_tkmap.c index 0d1c6bd..b688e09 100644 --- a/src/core/ddsi/src/ddsi_tkmap.c +++ b/src/core/ddsi/src/ddsi_tkmap.c @@ -113,7 +113,7 @@ uint64_t ddsi_tkmap_lookup (struct ddsi_tkmap * map, const struct ddsi_serdata * { struct ddsi_tkmap_instance dummy; struct ddsi_tkmap_instance * tk; - assert (vtime_awake_p(lookup_thread_state()->vtime)); + assert (thread_is_awake ()); dummy.m_sample = (struct ddsi_serdata *) sd; tk = ut_chhLookup (map->m_hh, &dummy); return (tk) ? tk->m_iid : DDS_HANDLE_NIL; @@ -125,7 +125,7 @@ struct ddsi_tkmap_instance *ddsi_tkmap_find_by_id (struct ddsi_tkmap *map, uint6 struct ut_chhIter it; struct ddsi_tkmap_instance *tk; uint32_t refc; - assert (vtime_awake_p(lookup_thread_state()->vtime)); + assert (thread_is_awake ()); for (tk = ut_chhIterFirst (map->m_hh, &it); tk; tk = ut_chhIterNext (&it)) if (tk->m_iid == iid) break; @@ -162,7 +162,7 @@ ddsi_tkmap_find( struct ddsi_tkmap_instance * tk; struct ddsi_tkmap * map = gv.m_tkmap; - assert (vtime_awake_p(lookup_thread_state()->vtime)); + assert (thread_is_awake ()); dummy.m_sample = sd; retry: if ((tk = ut_chhLookup(map->m_hh, &dummy)) != NULL) @@ -221,7 +221,7 @@ void ddsi_tkmap_instance_ref (struct ddsi_tkmap_instance *tk) void ddsi_tkmap_instance_unref (struct ddsi_tkmap_instance * tk) { uint32_t old, new; - assert (vtime_awake_p(lookup_thread_state()->vtime)); + assert (thread_is_awake ()); do { old = ddsrt_atomic_ld32(&tk->m_refc); if (old == 1) diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 07ddc4b..b613df8 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -141,7 +141,6 @@ DU(tracingOutputFileName); DU(verbosity); DUPF(logcat); DUPF(xcheck); -DUPF(float); DUPF(int); DUPF(uint); DUPF(int32); @@ -158,6 +157,7 @@ DU(duration_inf); DU(duration_ms_1hr); DU(duration_ms_1s); DU(duration_us_1s); +DU(duration_100ms_1hr); PF(duration); DUPF(standards_conformance); DUPF(besmode); @@ -516,6 +516,8 @@ static const struct cfgelem heartbeat_interval_attrs[] = { static const struct cfgelem liveliness_monitoring_attrs[] = { { ATTR("StackTraces"), 1, "true", ABSOFF(noprogress_log_stacktraces), 0, uf_boolean, 0, pf_boolean, "

This element controls whether or not to write stack traces to the DDSI2 trace when a thread fails to make progress (on select platforms only).

" }, + { ATTR("Interval"), 1, "1s", ABSOFF(liveliness_monitoring_interval), 0, uf_duration_100ms_1hr, 0, pf_duration, + "

This element controls the interval at which to check whether threads have been making progress.

" }, END_MARKER }; @@ -878,23 +880,14 @@ static const struct cfgelem ddsi2_cfgelems[] = { END_MARKER }; -/* Note: using 2e-1 instead of 0.2 to avoid use of the decimal -separator, which is locale dependent. */ -static const struct cfgelem lease_expiry_time_cfgattrs[] = { - { ATTR("update_factor"), 1, "2e-1", ABSOFF(servicelease_update_factor), 0, uf_float, 0, pf_float, NULL }, - END_MARKER +static const struct cfgelem deprecated_lease_cfgelems[] = { + WILDCARD, + END_MARKER }; -static const struct cfgelem lease_cfgelems[] = { - { LEAF_W_ATTRS("ExpiryTime", lease_expiry_time_cfgattrs), 1, "10", ABSOFF(servicelease_expiry_time), 0, uf_float, 0, pf_float, NULL }, - END_MARKER -}; - - static const struct cfgelem domain_cfgelems[] = { - { GROUP("Lease", lease_cfgelems), NULL }, { LEAF("Id"), 1, "any", ABSOFF(domainId), 0, uf_domainId, 0, pf_domainId, NULL }, - WILDCARD, + { GROUP("|Lease", deprecated_lease_cfgelems), NULL }, END_MARKER }; @@ -908,7 +901,7 @@ static const struct cfgelem root_cfgelems[] = { { "DDSI2E|DDSI2", ddsi2_cfgelems, NULL, NODATA, "

DDSI2 settings ...

" }, { "Durability", durability_cfgelems, NULL, NODATA, NULL }, - { "Lease", lease_cfgelems, NULL, NODATA, NULL }, + { GROUP("|Lease", deprecated_lease_cfgelems), NULL }, END_MARKER }; @@ -1529,7 +1522,7 @@ static int uf_string(struct cfgst *cfgst, void *parent, struct cfgelem const * c } DDSRT_WARNING_MSVC_OFF(4996); -static int uf_natint64_unit(struct cfgst *cfgst, int64_t *elem, const char *value, const struct unit *unittab, int64_t def_mult, int64_t max) +static int uf_natint64_unit(struct cfgst *cfgst, int64_t *elem, const char *value, const struct unit *unittab, int64_t def_mult, int64_t min, int64_t max) { int pos; double v_dbl; @@ -1542,14 +1535,14 @@ static int uf_natint64_unit(struct cfgst *cfgst, int64_t *elem, const char *valu return cfg_error(cfgst, "%s: empty string is not a valid value", value); } else if ( sscanf(value, "%lld%n", (long long int *) &v_int, &pos) == 1 && (mult = lookup_multiplier(cfgst, unittab, value, pos, v_int == 0, def_mult, 0)) != 0 ) { assert(mult > 0); - if ( v_int < 0 || v_int > max / mult ) + if ( v_int < 0 || v_int > max / mult || mult * v_int < min) return cfg_error(cfgst, "%s: value out of range", value); *elem = mult * v_int; return 1; } else if ( sscanf(value, "%lf%n", &v_dbl, &pos) == 1 && (mult = lookup_multiplier(cfgst, unittab, value, pos, v_dbl == 0, def_mult, 1)) != 0 ) { double dmult = (double) mult; assert(dmult > 0); - if ( v_dbl < 0 || (int64_t) (v_dbl * dmult + 0.5) > max ) + if ( (int64_t) (v_dbl * dmult + 0.5) < min || (int64_t) (v_dbl * dmult + 0.5) > max ) return cfg_error(cfgst, "%s: value out of range", value); *elem = (int64_t) (v_dbl * dmult + 0.5); return 1; @@ -1587,7 +1580,7 @@ static int uf_bandwidth(struct cfgst *cfgst, void *parent, struct cfgelem const static int uf_memsize(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { int64_t size = 0; - if ( !uf_natint64_unit(cfgst, &size, value, unittab_memsize, 1, INT32_MAX) ) + if ( !uf_natint64_unit(cfgst, &size, value, unittab_memsize, 1, 0, INT32_MAX) ) return 0; else { uint32_t *elem = cfg_address(cfgst, parent, cfgelem); @@ -1844,7 +1837,7 @@ static int uf_maybe_memsize(struct cfgst *cfgst, void *parent, struct cfgelem co elem->isdefault = 1; elem->value = 0; return 1; - } else if ( !uf_natint64_unit(cfgst, &size, value, unittab_memsize, 1, INT32_MAX) ) { + } else if ( !uf_natint64_unit(cfgst, &size, value, unittab_memsize, 1, 0, INT32_MAX) ) { return 0; } else { elem->isdefault = 0; @@ -1853,19 +1846,6 @@ static int uf_maybe_memsize(struct cfgst *cfgst, void *parent, struct cfgelem co } } - -static int uf_float(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) -{ - float *elem = cfg_address(cfgst, parent, cfgelem); - char *endptr; - float f; - dds_retcode_t rc = ddsrt_strtof(value, &endptr, &f); - if (rc != DDS_RETCODE_OK || *value == 0 || *endptr != 0 ) - return cfg_error(cfgst, "%s: not a floating point number", value); - *elem = f; - return 1; -} - static int uf_int(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { int *elem = cfg_address(cfgst, parent, cfgelem); @@ -1879,9 +1859,9 @@ static int uf_int(struct cfgst *cfgst, void *parent, struct cfgelem const * cons return 1; } -static int uf_duration_gen(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, const char *value, int64_t def_mult, int64_t max_ns) +static int uf_duration_gen(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, const char *value, int64_t def_mult, int64_t min_ns, int64_t max_ns) { - return uf_natint64_unit(cfgst, cfg_address(cfgst, parent, cfgelem), value, unittab_duration, def_mult, max_ns); + return uf_natint64_unit(cfgst, cfg_address(cfgst, parent, cfgelem), value, unittab_duration, def_mult, min_ns, max_ns); } static int uf_duration_inf(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) @@ -1891,23 +1871,28 @@ static int uf_duration_inf(struct cfgst *cfgst, void *parent, struct cfgelem con *elem = T_NEVER; return 1; } else { - return uf_duration_gen(cfgst, parent, cfgelem, value, 0, T_NEVER - 1); + return uf_duration_gen(cfgst, parent, cfgelem, value, 0, 0, T_NEVER - 1); } } static int uf_duration_ms_1hr(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - return uf_duration_gen(cfgst, parent, cfgelem, value, T_MILLISECOND, 3600 * T_SECOND); + return uf_duration_gen(cfgst, parent, cfgelem, value, T_MILLISECOND, 0, 3600 * T_SECOND); } static int uf_duration_ms_1s(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - return uf_duration_gen(cfgst, parent, cfgelem, value, T_MILLISECOND, T_SECOND); + return uf_duration_gen(cfgst, parent, cfgelem, value, T_MILLISECOND, 0, T_SECOND); } static int uf_duration_us_1s(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) { - return uf_duration_gen(cfgst, parent, cfgelem, value, 1000, T_SECOND); + return uf_duration_gen(cfgst, parent, cfgelem, value, 1000, 0, T_SECOND); +} + +static int uf_duration_100ms_1hr(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) +{ + return uf_duration_gen(cfgst, parent, cfgelem, value, 0, 100 * T_MILLISECOND, 3600 * T_SECOND); } static int uf_int32(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) @@ -2309,12 +2294,6 @@ static void pf_domainId(struct cfgst *cfgst, void *parent, struct cfgelem const cfg_log(cfgst, "%d%s", p->value, is_default ? " [def]" : ""); } -static void pf_float(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) -{ - float *p = cfg_address(cfgst, parent, cfgelem); - cfg_log(cfgst, "%f%s", *p, is_default ? " [def]" : ""); -} - static void pf_boolean(struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) { int *p = cfg_address(cfgst, parent, cfgelem); diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index be434dd..bf5ec02 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -172,13 +172,14 @@ static void maybe_add_pp_as_meta_to_as_disc (const struct addrset *as_meta) static int write_mpayload (struct writer *wr, int alive, nn_parameterid_t keyparam, struct nn_xmsg *mpayload) { + struct thread_state1 * const ts1 = lookup_thread_state (); struct ddsi_plist_sample plist_sample; struct ddsi_serdata *serdata; nn_xmsg_payload_to_plistsample (&plist_sample, keyparam, mpayload); serdata = ddsi_serdata_from_sample (gv.plist_topic, alive ? SDK_DATA : SDK_KEY, &plist_sample); serdata->statusinfo = alive ? 0 : NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER; serdata->timestamp = now (); - return write_sample_nogc_notk (NULL, wr, serdata); + return write_sample_nogc_notk (ts1, NULL, wr, serdata); } int spdp_write (struct participant *pp) diff --git a/src/core/ddsi/src/q_debmon.c b/src/core/ddsi/src/q_debmon.c index beaa9bf..8043229 100644 --- a/src/core/ddsi/src/q_debmon.c +++ b/src/core/ddsi/src/q_debmon.c @@ -142,12 +142,12 @@ static int print_proxy_endpoint_common (ddsi_tran_conn_t conn, const char *label } -static int print_participants (struct thread_state1 *self, ddsi_tran_conn_t conn) +static int print_participants (struct thread_state1 * const ts1, ddsi_tran_conn_t conn) { struct ephash_enum_participant e; struct participant *p; int x = 0; - thread_state_awake (self); + thread_state_awake (ts1); ephash_enum_participant_init (&e); while ((p = ephash_enum_participant_next (&e)) != NULL) { @@ -223,16 +223,16 @@ static int print_participants (struct thread_state1 *self, ddsi_tran_conn_t conn } } ephash_enum_participant_fini (&e); - thread_state_asleep (self); + thread_state_asleep (ts1); return x; } -static int print_proxy_participants (struct thread_state1 *self, ddsi_tran_conn_t conn) +static int print_proxy_participants (struct thread_state1 * const ts1, ddsi_tran_conn_t conn) { struct ephash_enum_proxy_participant e; struct proxy_participant *p; int x = 0; - thread_state_awake (self); + thread_state_awake (ts1); ephash_enum_proxy_participant_init (&e); while ((p = ephash_enum_proxy_participant_next (&e)) != NULL) { @@ -296,17 +296,18 @@ static int print_proxy_participants (struct thread_state1 *self, ddsi_tran_conn_ } } ephash_enum_proxy_participant_fini (&e); - thread_state_asleep (self); + thread_state_asleep (ts1); return x; } static void debmon_handle_connection (struct debug_monitor *dm, ddsi_tran_conn_t conn) { + struct thread_state1 * const ts1 = lookup_thread_state (); struct plugin *p; int r = 0; - r += print_participants (dm->servts, conn); + r += print_participants (ts1, conn); if (r == 0) - r += print_proxy_participants (dm->servts, conn); + r += print_proxy_participants (ts1, conn); /* Note: can only add plugins (at the tail) */ ddsrt_mutex_lock (&dm->lock); @@ -379,7 +380,7 @@ struct debug_monitor *new_debug_monitor (int port) if (ddsi_listener_listen (dm->servsock) < 0) goto err_listen; dm->stop = 0; - dm->servts = create_thread("debmon", debmon_main, dm); + create_thread(&dm->servts, "debmon", debmon_main, dm); return dm; err_listen: diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index c832a9b..685543b 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -3862,14 +3862,11 @@ void purge_proxy_participants (const nn_locator_t *loc, bool delete_from_as_disc { /* FIXME: check whether addr:port can't be reused for a new connection by the time we get here. */ /* NOTE: This function exists for the sole purpose of cleaning up after closing a TCP connection in ddsi_tcp_close_conn and the state of the calling thread could be anything at this point. Because of that we do the unspeakable and toggle the thread state conditionally. We can't afford to have it in "asleep", as that causes a race with the garbage collector. */ - struct thread_state1 * const self = lookup_thread_state(); - const int self_is_awake = vtime_awake_p (self->vtime); + struct thread_state1 * const ts1 = lookup_thread_state (); struct ephash_enum_proxy_participant est; struct proxy_purge_data data; - if (!self_is_awake) - thread_state_awake(self); - + thread_state_awake (ts1); data.loc = loc; data.timestamp = now(); ephash_enum_proxy_participant_init (&est); @@ -3881,8 +3878,7 @@ void purge_proxy_participants (const nn_locator_t *loc, bool delete_from_as_disc if (delete_from_as_disc) remove_from_addrset (gv.as_disc, loc); - if (!self_is_awake) - thread_state_asleep(self); + thread_state_asleep (ts1); } int delete_proxy_participant_by_guid (const struct nn_guid * guid, nn_wctime_t timestamp, int isimplicit) diff --git a/src/core/ddsi/src/q_gc.c b/src/core/ddsi/src/q_gc.c index 915c92b..42fc0ef 100644 --- a/src/core/ddsi/src/q_gc.c +++ b/src/core/ddsi/src/q_gc.c @@ -79,7 +79,7 @@ static int threads_vtime_check (unsigned *nivs, struct idx_vtime *ivs) static uint32_t gcreq_queue_thread (struct gcreq_queue *q) { - struct thread_state1 *self = lookup_thread_state (); + struct thread_state1 * const ts1 = lookup_thread_state (); nn_mtime_t next_thread_cputime = { 0 }; dds_time_t shortsleep = 1 * T_MILLISECOND; int64_t delay = T_MILLISECOND; /* force evaluation after startup */ @@ -124,9 +124,9 @@ static uint32_t gcreq_queue_thread (struct gcreq_queue *q) very little impact on its primary purpose and be less of a burden on the system than having a separate thread or adding it to the workload of the data handling threads. */ - thread_state_awake (self); - delay = check_and_handle_lease_expiration (self, now_et ()); - thread_state_asleep (self); + thread_state_awake (ts1); + delay = check_and_handle_lease_expiration (now_et ()); + thread_state_asleep (ts1); if (gcreq) { @@ -151,9 +151,9 @@ static uint32_t gcreq_queue_thread (struct gcreq_queue *q) multi-phase delete) or freeing the delete request. Reset the current gcreq as this one obviously is no more. */ DDS_TRACE("gc %p: deleting\n", (void*)gcreq); - thread_state_awake (self); + thread_state_awake (ts1); gcreq->cb (gcreq); - thread_state_asleep (self); + thread_state_asleep (ts1); gcreq = NULL; trace_shortsleep = 1; } @@ -174,9 +174,15 @@ struct gcreq_queue *gcreq_queue_new (void) q->count = 0; ddsrt_mutex_init (&q->lock); ddsrt_cond_init (&q->cond); - q->ts = create_thread ("gc", (uint32_t (*) (void *)) gcreq_queue_thread, q); - assert (q->ts); - return q; + if (create_thread (&q->ts, "gc", (uint32_t (*) (void *)) gcreq_queue_thread, q) == DDS_RETCODE_OK) + return q; + else + { + ddsrt_mutex_destroy (&q->lock); + ddsrt_cond_destroy (&q->cond); + ddsrt_free (q); + return NULL; + } } void gcreq_queue_drain (struct gcreq_queue *q) diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 9fddd09..0b89411 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -839,7 +839,7 @@ static int setup_and_start_recv_threads (void) goto fail; } } - if ((gv.recv_threads[i].ts = create_thread (gv.recv_threads[i].name, recv_thread, &gv.recv_threads[i].arg)) == NULL) + if (create_thread (&gv.recv_threads[i].ts, gv.recv_threads[i].name, recv_thread, &gv.recv_threads[i].arg) != DDS_RETCODE_OK) { DDS_ERROR("rtps_init: failed to start thread %s\n", gv.recv_threads[i].name); goto fail; @@ -1399,7 +1399,7 @@ int rtps_start (void) } if (gv.listener) { - gv.listen_ts = create_thread ("listen", (uint32_t (*) (void *)) listen_thread, gv.listener); + create_thread (&gv.listen_ts, "listen", (uint32_t (*) (void *)) listen_thread, gv.listener); } if (gv.startup_mode) { @@ -1429,7 +1429,8 @@ static void builtins_dqueue_ready_cb (void *varg) void rtps_stop (void) { - struct thread_state1 *self = lookup_thread_state (); + struct thread_state1 * const ts1 = lookup_thread_state (); + #ifdef DDSI_INCLUDE_NETWORK_CHANNELS struct config_channel_listelem * chptr; #endif @@ -1496,14 +1497,14 @@ void rtps_stop (void) /* Clean up proxy readers, proxy writers and proxy participants. Deleting a proxy participants deletes all its readers and writers automatically */ - thread_state_awake (self); + thread_state_awake (ts1); ephash_enum_proxy_participant_init (&est); while ((proxypp = ephash_enum_proxy_participant_next (&est)) != NULL) { delete_proxy_participant_by_guid(&proxypp->e.guid, tnow, 1); } ephash_enum_proxy_participant_fini (&est); - thread_state_asleep (self); + thread_state_asleep (ts1); } { @@ -1518,7 +1519,7 @@ void rtps_stop (void) rwriters to get all SEDP and SPDP dispose+unregister messages out. FIXME: need to keep xevent thread alive for a while longer. */ - thread_state_awake (self); + thread_state_awake (ts1); ephash_enum_writer_init (&est_wr); while ((wr = ephash_enum_writer_next (&est_wr)) != NULL) { @@ -1526,7 +1527,7 @@ void rtps_stop (void) delete_writer_nolinger (&wr->e.guid); } ephash_enum_writer_fini (&est_wr); - thread_state_awake (self); + thread_state_awake_to_awake_no_nest (ts1); ephash_enum_reader_init (&est_rd); while ((rd = ephash_enum_reader_next (&est_rd)) != NULL) { @@ -1534,14 +1535,14 @@ void rtps_stop (void) (void)delete_reader (&rd->e.guid); } ephash_enum_reader_fini (&est_rd); - thread_state_awake (self); + thread_state_awake_to_awake_no_nest (ts1); ephash_enum_participant_init (&est_pp); while ((pp = ephash_enum_participant_next (&est_pp)) != NULL) { delete_participant (&pp->e.guid); } ephash_enum_participant_fini (&est_pp); - thread_state_asleep (self); + thread_state_asleep (ts1); } /* Wait until all participants are really gone => by then we can be diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c index 1dac32c..0e2d99c 100644 --- a/src/core/ddsi/src/q_lease.c +++ b/src/core/ddsi/src/q_lease.c @@ -205,7 +205,7 @@ void lease_set_expiry (struct lease *l, nn_etime_t when) force_lease_check(); } -int64_t check_and_handle_lease_expiration (UNUSED_ARG (struct thread_state1 *self), nn_etime_t tnowE) +int64_t check_and_handle_lease_expiration (nn_etime_t tnowE) { struct lease *l; int64_t delay; diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c index 20eaa66..1ca2e83 100644 --- a/src/core/ddsi/src/q_radmin.c +++ b/src/core/ddsi/src/q_radmin.c @@ -2397,7 +2397,7 @@ static enum dqueue_elem_kind dqueue_elem_kind (const struct nn_rsample_chain_ele static uint32_t dqueue_thread (struct nn_dqueue *q) { - struct thread_state1 *self = lookup_thread_state (); + struct thread_state1 * const ts1 = lookup_thread_state (); nn_mtime_t next_thread_cputime = { 0 }; int keepgoing = 1; nn_guid_t rdguid, *prdguid = NULL; @@ -2416,6 +2416,7 @@ static uint32_t dqueue_thread (struct nn_dqueue *q) q->sc.first = q->sc.last = NULL; ddsrt_mutex_unlock (&q->lock); + thread_state_awake (ts1); while (sc.first) { struct nn_rsample_chain_elem *e = sc.first; @@ -2424,7 +2425,7 @@ static uint32_t dqueue_thread (struct nn_dqueue *q) if (ddsrt_atomic_dec32_ov (&q->nof_samples) == 1) { ddsrt_cond_broadcast (&q->cond); } - thread_state_awake (self); + thread_state_awake_to_awake_no_nest (ts1); switch (dqueue_elem_kind (e)) { case DQEK_DATA: @@ -2474,9 +2475,9 @@ static uint32_t dqueue_thread (struct nn_dqueue *q) break; } } - thread_state_asleep (self); } + thread_state_asleep (ts1); ddsrt_mutex_lock (&q->lock); } ddsrt_mutex_unlock (&q->lock); @@ -2506,7 +2507,7 @@ struct nn_dqueue *nn_dqueue_new (const char *name, uint32_t max_samples, nn_dque if ((thrname = ddsrt_malloc (thrnamesz)) == NULL) goto fail_thrname; snprintf (thrname, thrnamesz, "dq.%s", name); - if ((q->ts = create_thread (thrname, (uint32_t (*) (void *)) dqueue_thread, q)) == NULL) + if (create_thread (&q->ts, thrname, (uint32_t (*) (void *)) dqueue_thread, q) != DDS_RETCODE_OK) goto fail_thread; ddsrt_free (thrname); return q; diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 8671a5b..9e7f899 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -2660,9 +2660,9 @@ static struct receiver_state *rst_cow_if_needed (int *rst_live, struct nn_rmsg * static int handle_submsg_sequence ( + struct thread_state1 * const ts1, ddsi_tran_conn_t conn, const nn_locator_t *srcloc, - struct thread_state1 * const self, nn_wctime_t tnowWC, nn_etime_t tnowE, const nn_guid_prefix_t * const src_prefix, @@ -2709,10 +2709,12 @@ static int handle_submsg_sequence ts_for_latmeas = 0; timestamp = invalid_ddsi_timestamp; + assert (thread_is_asleep ()); + thread_state_awake (ts1); while (submsg <= (end - sizeof (SubmessageHeader_t))) { Submessage_t *sm = (Submessage_t *) submsg; - int byteswap; + bool byteswap; unsigned octetsToNextHeader; if (sm->smhdr.flags & SMFLAG_ENDIANNESS) @@ -2749,7 +2751,7 @@ static int handle_submsg_sequence break; } - thread_state_awake (self); + thread_state_awake_to_awake_no_nest (ts1); state_smkind = sm->smhdr.submessageId; switch (sm->smhdr.submessageId) { @@ -2855,9 +2857,7 @@ static int handle_submsg_sequence unsigned char *datap; /* valid_Data does not validate the payload */ if (!valid_Data (rst, rmsg, &sm->data, submsg_size, byteswap, &sampleinfo, &datap)) - { goto malformed; - } sampleinfo.timestamp = timestamp; sampleinfo.reception_timestamp = tnowWC; handle_Data (rst, tnowE, rmsg, &sm->data, submsg_size, &sampleinfo, datap); @@ -2886,8 +2886,10 @@ static int handle_submsg_sequence size_t len2 = decode_container (submsg1, len1); if ( len2 != 0 ) { TRACE ((")\n")); - if (handle_submsg_sequence (conn, srcloc, self, tnowWC, tnowE, src_prefix, dst_prefix, msg, (size_t) (submsg1 - msg) + len2, submsg1, rmsg) < 0) - goto malformed; + thread_state_asleep (ts1); + if (handle_submsg_sequence (conn, srcloc, tnowWC, tnowE, src_prefix, dst_prefix, msg, (size_t) (submsg1 - msg) + len2, submsg1, rmsg) < 0) + goto malformed_asleep; + thread_state_awake (ts1); } TRACE (("PT_INFO_CONTAINER END")); } @@ -2952,19 +2954,24 @@ static int handle_submsg_sequence state = "parse:shortmsg"; state_smkind = SMID_PAD; DDS_TRACE("short (size %"PRIuSIZE" exp %p act %p)", submsg_size, (void *) submsg, (void *) end); - goto malformed; + goto malformed_asleep; } + thread_state_asleep (ts1); + assert (thread_is_asleep ()); return 0; malformed: - + thread_state_asleep (ts1); + assert (thread_is_asleep ()); +malformed_asleep: + assert (thread_is_asleep ()); malformed_packet_received (msg, submsg, len, state, state_smkind, hdr->vendorid); return -1; } static bool do_packet ( - struct thread_state1 *self, + struct thread_state1 * const ts1, ddsi_tran_conn_t conn, const nn_guid_prefix_t * guidprefix, struct nn_rbufpool *rbpool @@ -3052,7 +3059,7 @@ static bool do_packet if (sz > 0 && !gv.deaf) { nn_rmsg_setsize (rmsg, (uint32_t) sz); - assert (vtime_asleep_p (self->vtime)); + assert (thread_is_asleep ()); if ((size_t)sz < RTPS_MESSAGE_HEADER_SIZE || *(uint32_t *)buff != NN_PROTOCOLID_AS_UINT32) { @@ -3078,9 +3085,8 @@ static bool do_packet PGUIDPREFIX (hdr->guid_prefix), hdr->vendorid.id[0], hdr->vendorid.id[1], (unsigned long) sz, addrstr); } - handle_submsg_sequence (conn, &srcloc, self, now (), now_et (), &hdr->guid_prefix, guidprefix, buff, (size_t) sz, buff + RTPS_MESSAGE_HEADER_SIZE, rmsg); + handle_submsg_sequence (ts1, conn, &srcloc, now (), now_et (), &hdr->guid_prefix, guidprefix, buff, (size_t) sz, buff + RTPS_MESSAGE_HEADER_SIZE, rmsg); } - thread_state_asleep (self); } nn_rmsg_commit (rmsg); return (sz > 0); @@ -3144,13 +3150,13 @@ static void local_participant_set_fini (struct local_participant_set *lps) ddsrt_free (lps->ps); } -static void rebuild_local_participant_set (struct thread_state1 *self, struct local_participant_set *lps) +static void rebuild_local_participant_set (struct thread_state1 * const ts1, struct local_participant_set *lps) { struct ephash_enum_participant est; struct participant *pp; unsigned nps_alloc; DDS_TRACE("pp set gen changed: local %u global %"PRIu32"\n", lps->gen, ddsrt_atomic_ld32(&gv.participant_set_generation)); - thread_state_awake (self); + thread_state_awake (ts1); restart: lps->gen = ddsrt_atomic_ld32 (&gv.participant_set_generation); /* Actual local set of participants may never be older than the @@ -3195,7 +3201,7 @@ static void rebuild_local_participant_set (struct thread_state1 *self, struct lo DDS_TRACE(" set changed - restarting\n"); goto restart; } - thread_state_asleep (self); + thread_state_asleep (ts1); /* The definition of the hash enumeration allows visiting one participant multiple times, so guard against that, too. Note @@ -3361,8 +3367,8 @@ void trigger_recv_threads (void) uint32_t recv_thread (void *vrecv_thread_arg) { + struct thread_state1 * const ts1 = lookup_thread_state (); struct recv_thread_arg *recv_thread_arg = vrecv_thread_arg; - struct thread_state1 *self = lookup_thread_state (); struct nn_rbufpool *rbpool = recv_thread_arg->rbpool; os_sockWaitset waitset = recv_thread_arg->mode == RTM_MANY ? recv_thread_arg->u.many.ws : NULL; nn_mtime_t next_thread_cputime = { 0 }; @@ -3373,7 +3379,7 @@ uint32_t recv_thread (void *vrecv_thread_arg) while (gv.rtps_keepgoing) { LOG_THREAD_CPUTIME (next_thread_cputime); - (void) do_packet (self, recv_thread_arg->u.single.conn, NULL, rbpool); + (void) do_packet (ts1, recv_thread_arg->u.single.conn, NULL, rbpool); } } else @@ -3422,7 +3428,7 @@ uint32_t recv_thread (void *vrecv_thread_arg) { /* first rebuild local participant set - unless someone's toggling "deafness", this only happens when the participant set has changed, so might as well rebuild it */ - rebuild_local_participant_set (self, &lps); + rebuild_local_participant_set (ts1, &lps); os_sockWaitsetPurge (waitset, num_fixed); for (i = 0; i < lps.nps; i++) { @@ -3443,7 +3449,7 @@ uint32_t recv_thread (void *vrecv_thread_arg) else guid_prefix = &lps.ps[(unsigned)idx - num_fixed].guid_prefix; /* Process message and clean out connection if failed or closed */ - if (!do_packet (self, conn, guid_prefix, rbpool) && !conn->m_connless) + if (!do_packet (ts1, conn, guid_prefix, rbpool) && !conn->m_connless) ddsi_conn_free (conn); } } diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c index 6789407..9ca93fc 100644 --- a/src/core/ddsi/src/q_thread.c +++ b/src/core/ddsi/src/q_thread.c @@ -22,7 +22,7 @@ #include "dds/ddsrt/misc.h" #include "dds/ddsi/q_thread.h" -#include "dds/ddsi/q_servicelease.h" +#include "dds/ddsi/ddsi_threadmon.h" #include "dds/ddsi/q_error.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_config.h" @@ -34,6 +34,16 @@ static char main_thread_name[] = "main"; struct thread_states thread_states; ddsrt_thread_local struct thread_state1 *tsd_thread_state; +extern inline bool vtime_awake_p (vtime_t vtime); +extern inline bool vtime_asleep_p (vtime_t vtime); +extern inline bool vtime_gt (vtime_t vtime1, vtime_t vtime0); + +extern inline struct thread_state1 *lookup_thread_state (void); +extern inline bool thread_is_asleep (void); +extern inline bool thread_is_awake (void); +extern inline void thread_state_asleep (struct thread_state1 *ts1); +extern inline void thread_state_awake (struct thread_state1 *ts1); +extern inline void thread_state_awake_to_awake_no_nest (struct thread_state1 *ts1); void *ddsrt_malloc_aligned_cacheline (size_t size) { @@ -63,9 +73,10 @@ static void ddsrt_free_aligned (void *ptr) void thread_states_init_static (void) { - static struct thread_state1 ts = - { .state = THREAD_STATE_ALIVE, .vtime = 1, .watchdog = 1, .name = "(anon)" }; - tsd_thread_state = &ts; + static struct thread_state1 ts = { + .state = THREAD_STATE_ALIVE, .vtime = 0u, .name = "(anon)" + }; + tsd_thread_state = &ts; } void thread_states_init (unsigned maxthreads) @@ -82,8 +93,7 @@ DDSRT_WARNING_MSVC_OFF(6386); for (i = 0; i < thread_states.nthreads; i++) { thread_states.ts[i].state = THREAD_STATE_ZERO; - thread_states.ts[i].vtime = 1; - thread_states.ts[i].watchdog = 1; + thread_states.ts[i].vtime = 0u; thread_states.ts[i].name = NULL; } DDSRT_WARNING_MSVC_ON(6386); @@ -115,43 +125,9 @@ static void cleanup_thread_state (void *data) ddsrt_fini(); } -struct thread_state1 *lookup_thread_state (void) -{ - struct thread_state1 *ts1 = NULL; - char name[128]; - ddsrt_thread_t thr; - - if ((ts1 = tsd_thread_state) == NULL) { - if ((ts1 = lookup_thread_state_real()) == NULL) { - /* This situation only arises for threads that were not created using - create_thread, aka application threads. Since registering thread - state should be fully automatic the name is simply the identifier. */ - thr = ddsrt_thread_self(); - ddsrt_thread_getname(name, sizeof(name)); - ddsrt_mutex_lock(&thread_states.lock); - ts1 = init_thread_state(name); - if (ts1 != NULL) { - ddsrt_init(); - ts1->extTid = thr; - ts1->tid = thr; - DDS_TRACE("started application thread %s\n", name); - ddsrt_thread_cleanup_push(&cleanup_thread_state, NULL); - } - ddsrt_mutex_unlock(&thread_states.lock); - } - - tsd_thread_state = ts1; - } - - assert(ts1 != NULL); - - return ts1; -} - -struct thread_state1 *lookup_thread_state_real (void) +static struct thread_state1 *find_thread_state (ddsrt_thread_t tid) { if (thread_states.ts) { - ddsrt_thread_t tid = ddsrt_thread_self (); unsigned i; for (i = 0; i < thread_states.nthreads; i++) { if (ddsrt_thread_equal (thread_states.ts[i].tid, tid)) { @@ -162,6 +138,40 @@ struct thread_state1 *lookup_thread_state_real (void) return NULL; } +static struct thread_state1 *lazy_create_thread_state (ddsrt_thread_t self) +{ + /* This situation only arises for threads that were not created using + create_thread, aka application threads. Since registering thread + state should be fully automatic the name is simply the identifier. */ + struct thread_state1 *ts1; + char name[128]; + ddsrt_thread_getname (name, sizeof (name)); + ddsrt_mutex_lock (&thread_states.lock); + if ((ts1 = init_thread_state (name)) != NULL) { + ddsrt_init (); + ts1->extTid = self; + ts1->tid = self; + DDS_TRACE ("started application thread %s\n", name); + ddsrt_thread_cleanup_push (&cleanup_thread_state, NULL); + } + ddsrt_mutex_unlock (&thread_states.lock); + return ts1; +} + +struct thread_state1 *lookup_thread_state_real (void) +{ + struct thread_state1 *ts1 = tsd_thread_state; + if (ts1 == NULL) + { + ddsrt_thread_t self = ddsrt_thread_self (); + if ((ts1 = find_thread_state (self)) == NULL) + ts1 = lazy_create_thread_state (self); + tsd_thread_state = ts1; + } + assert(ts1 != NULL); + return ts1; +} + struct thread_context { struct thread_state1 *self; uint32_t (*f) (void *arg); @@ -221,7 +231,7 @@ const struct config_thread_properties_listelem *lookup_thread_properties (const return e; } -struct thread_state1 * init_thread_state (const char *tname) +struct thread_state1 *init_thread_state (const char *tname) { int cand; struct thread_state1 *ts; @@ -231,29 +241,29 @@ struct thread_state1 * init_thread_state (const char *tname) ts = &thread_states.ts[cand]; if (ts->state == THREAD_STATE_ZERO) + { assert (vtime_asleep_p (ts->vtime)); + } ts->name = ddsrt_strdup (tname); ts->state = THREAD_STATE_ALIVE; return ts; } -struct thread_state1 *create_thread (const char *name, uint32_t (*f) (void *arg), void *arg) +dds_retcode_t create_thread (struct thread_state1 **ts1, const char *name, uint32_t (*f) (void *arg), void *arg) { struct config_thread_properties_listelem const * const tprops = lookup_thread_properties (name); ddsrt_threadattr_t tattr; - struct thread_state1 *ts1; ddsrt_thread_t tid; struct thread_context *ctxt; ctxt = ddsrt_malloc (sizeof (*ctxt)); ddsrt_mutex_lock (&thread_states.lock); - ts1 = init_thread_state (name); - - if (ts1 == NULL) + *ts1 = init_thread_state (name); + if (*ts1 == NULL) goto fatal; - ctxt->self = ts1; + ctxt->self = *ts1; ctxt->f = f; ctxt->arg = arg; ddsrt_threadattr_init (&tattr); @@ -269,26 +279,27 @@ struct thread_state1 *create_thread (const char *name, uint32_t (*f) (void *arg) if (ddsrt_thread_create (&tid, name, &tattr, &create_thread_wrapper, ctxt) != DDS_RETCODE_OK) { - ts1->state = THREAD_STATE_ZERO; + (*ts1)->state = THREAD_STATE_ZERO; DDS_FATAL("create_thread: %s: ddsrt_thread_create failed\n", name); goto fatal; } - ts1->extTid = tid; /* overwrite the temporary value with the correct external one */ + (*ts1)->extTid = tid; /* overwrite the temporary value with the correct external one */ ddsrt_mutex_unlock (&thread_states.lock); - return ts1; + return DDS_RETCODE_OK; fatal: ddsrt_mutex_unlock (&thread_states.lock); ddsrt_free (ctxt); + *ts1 = NULL; abort (); - return NULL; + return DDS_RETCODE_ERROR; } static void reap_thread_state (struct thread_state1 *ts1, int sync_with_servicelease) { ddsrt_mutex_lock (&thread_states.lock); ts1->state = THREAD_STATE_ZERO; - if (sync_with_servicelease && gv.servicelease) - nn_servicelease_statechange_barrier (gv.servicelease); + if (sync_with_servicelease && gv.threadmon) + ddsi_threadmon_statechange_barrier (gv.threadmon); if (ts1->name != main_thread_name) ddsrt_free (ts1->name); ddsrt_mutex_unlock (&thread_states.lock); @@ -319,7 +330,7 @@ void reset_thread_state (struct thread_state1 *ts1) void downgrade_main_thread (void) { struct thread_state1 *ts1 = lookup_thread_state (); - thread_state_asleep (ts1); + assert (vtime_asleep_p (ts1->vtime)); /* no need to sync with service lease: already stopped */ reap_thread_state (ts1, 0); thread_states_init_static (); diff --git a/src/core/ddsi/src/q_thread_inlines.c b/src/core/ddsi/src/q_thread_inlines.c deleted file mode 100644 index b16f324..0000000 --- a/src/core/ddsi/src/q_thread_inlines.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include "dds/ddsi/q_thread.h" - -extern inline int vtime_awake_p (vtime_t vtime); -extern inline int vtime_asleep_p (vtime_t vtime); -extern inline int vtime_gt (vtime_t vtime1, vtime_t vtime0); - -extern inline void thread_state_asleep (struct thread_state1 *ts1); -extern inline void thread_state_awake (struct thread_state1 *ts1); -extern inline void thread_state_blocked (struct thread_state1 *ts1); -extern inline void thread_state_unblocked (struct thread_state1 *ts1); diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 27abfc7..086187e 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -911,7 +911,7 @@ static int writer_may_continue (const struct writer *wr, const struct whc_state } -static dds_retcode_t throttle_writer (struct nn_xpack *xp, struct writer *wr) +static dds_retcode_t throttle_writer (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr) { /* Sleep (cond_wait) without updating the thread's vtime: the garbage collector won't free the writer while we leave it @@ -956,7 +956,7 @@ static dds_retcode_t throttle_writer (struct nn_xpack *xp, struct writer *wr) { ASSERT_MUTEX_HELD (&wr->e.lock); assert (wr->throttling == 0); - assert (vtime_awake_p (lookup_thread_state ()->vtime)); + assert (thread_is_awake ()); assert (!is_builtin_entityid(wr->e.guid.entityid, NN_VENDORID_ECLIPSE)); } @@ -988,10 +988,10 @@ static dds_retcode_t throttle_writer (struct nn_xpack *xp, struct writer *wr) result = DDS_RETCODE_TIMEOUT; if (reltimeout > 0) { - thread_state_asleep (lookup_thread_state()); + thread_state_asleep (ts1); if (ddsrt_cond_waitfor (&wr->throttle_cond, &wr->e.lock, reltimeout)) result = DDS_RETCODE_OK; - thread_state_awake (lookup_thread_state()); + thread_state_awake (ts1); whc_get_state(wr->whc, &whcst); } if (result == DDS_RETCODE_TIMEOUT) @@ -1028,7 +1028,7 @@ static int maybe_grow_whc (struct writer *wr) return 0; } -static int write_sample_eot (struct nn_xpack *xp, struct writer *wr, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk, int end_of_txn, int gc_allowed) +static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct nn_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk, int end_of_txn, int gc_allowed) { int r; seqno_t seq; @@ -1070,14 +1070,14 @@ static int write_sample_eot (struct nn_xpack *xp, struct writer *wr, struct nn_p dds_retcode_t ores; assert(gc_allowed); /* also see beginning of the function */ if (config.prioritize_retransmit && wr->retransmitting) - ores = throttle_writer (xp, wr); + ores = throttle_writer (ts1, xp, wr); else { maybe_grow_whc (wr); if (whcst.unacked_bytes <= wr->whc_high) ores = DDS_RETCODE_OK; else - ores = throttle_writer (xp, wr); + ores = throttle_writer (ts1, xp, wr); } if (ores == DDS_RETCODE_TIMEOUT) { @@ -1168,32 +1168,34 @@ drop: return r; } -int write_sample_gc (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) +int write_sample_gc (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) { - return write_sample_eot (xp, wr, NULL, serdata, tk, 0, 1); + return write_sample_eot (ts1, xp, wr, NULL, serdata, tk, 0, 1); } -int write_sample_nogc (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) +int write_sample_nogc (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) { - return write_sample_eot (xp, wr, NULL, serdata, tk, 0, 0); + return write_sample_eot (ts1, xp, wr, NULL, serdata, tk, 0, 0); } -int write_sample_gc_notk (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata) +int write_sample_gc_notk (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata) { struct ddsi_tkmap_instance *tk; int res; + assert (thread_is_awake ()); tk = ddsi_tkmap_lookup_instance_ref (serdata); - res = write_sample_eot (xp, wr, NULL, serdata, tk, 0, 1); + res = write_sample_eot (ts1, xp, wr, NULL, serdata, tk, 0, 1); ddsi_tkmap_instance_unref (tk); return res; } -int write_sample_nogc_notk (struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata) +int write_sample_nogc_notk (struct thread_state1 * const ts1, struct nn_xpack *xp, struct writer *wr, struct ddsi_serdata *serdata) { struct ddsi_tkmap_instance *tk; int res; + assert (thread_is_awake ()); tk = ddsi_tkmap_lookup_instance_ref (serdata); - res = write_sample_eot (xp, wr, NULL, serdata, tk, 0, 0); + res = write_sample_eot (ts1, xp, wr, NULL, serdata, tk, 0, 0); ddsi_tkmap_instance_unref (tk); return res; } diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index 0e60a2a..b5d6c86 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -504,6 +504,7 @@ struct xeventq * xeventq_new int xeventq_start (struct xeventq *evq, const char *name) { + dds_retcode_t rc; char * evqname = "tev"; assert (evq->ts == NULL); @@ -515,13 +516,13 @@ int xeventq_start (struct xeventq *evq, const char *name) } evq->terminate = 0; - evq->ts = create_thread (evqname, (uint32_t (*) (void *)) xevent_thread, evq); + rc = create_thread (&evq->ts, evqname, (uint32_t (*) (void *)) xevent_thread, evq); if (name) { ddsrt_free (evqname); } - return (evq->ts == NULL) ? Q_ERR_UNSPECIFIED : 0; + return (rc != DDS_RETCODE_OK) ? Q_ERR_UNSPECIFIED : 0; } void xeventq_stop (struct xeventq *evq) @@ -1114,7 +1115,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e } } -static void write_pmd_message (struct nn_xpack *xp, struct participant *pp, unsigned pmd_kind) +static void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack *xp, struct participant *pp, unsigned pmd_kind) { #define PMD_DATA_LENGTH 1 struct writer *wr; @@ -1146,12 +1147,12 @@ static void write_pmd_message (struct nn_xpack *xp, struct participant *pp, unsi serdata->timestamp = now (); tk = ddsi_tkmap_lookup_instance_ref(serdata); - write_sample_nogc (xp, wr, serdata, tk); + write_sample_nogc (ts1, xp, wr, serdata, tk); ddsi_tkmap_instance_unref(tk); #undef PMD_DATA_LENGTH } -static void handle_xevk_pmd_update (struct nn_xpack *xp, struct xevent *ev, nn_mtime_t tnow) +static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_xpack *xp, struct xevent *ev, nn_mtime_t tnow) { struct participant *pp; int64_t intv; @@ -1162,7 +1163,7 @@ static void handle_xevk_pmd_update (struct nn_xpack *xp, struct xevent *ev, nn_m return; } - write_pmd_message (xp, pp, PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE); + write_pmd_message (ts1, xp, pp, PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE); /* QoS changes can't change lease durations. So the only thing that could cause trouble here is that the addition or removal of a @@ -1217,7 +1218,7 @@ static void handle_xevk_delete_writer (UNUSED_ARG (struct nn_xpack *xp), struct delete_xevent (ev); } -static void handle_individual_xevent (struct xevent *xev, struct nn_xpack *xp, nn_mtime_t tnow) +static void handle_individual_xevent (struct thread_state1 * const ts1, struct xevent *xev, struct nn_xpack *xp, nn_mtime_t tnow) { switch (xev->kind) { @@ -1231,7 +1232,7 @@ static void handle_individual_xevent (struct xevent *xev, struct nn_xpack *xp, n handle_xevk_spdp (xp, xev, tnow); break; case XEVK_PMD_UPDATE: - handle_xevk_pmd_update (xp, xev, tnow); + handle_xevk_pmd_update (ts1, xp, xev, tnow); break; case XEVK_END_STARTUP_MODE: handle_xevk_end_startup_mode (xp, xev, tnow); @@ -1262,7 +1263,7 @@ static void handle_individual_xevent_nt (struct xevent_nt *xev, struct nn_xpack ddsrt_free (xev); } -static void handle_timed_xevent (struct thread_state1 *self, struct xevent *xev, struct nn_xpack *xp, nn_mtime_t tnow /* monotonic */) +static void handle_timed_xevent (struct thread_state1 * const ts1, struct xevent *xev, struct nn_xpack *xp, nn_mtime_t tnow /* monotonic */) { /* This function handles the individual xevent irrespective of whether it is a "timed" or "non-timed" xevent */ @@ -1276,14 +1277,13 @@ static void handle_timed_xevent (struct thread_state1 *self, struct xevent *xev, assert (xev->tsched.v != TSCHED_DELETE); ddsrt_mutex_unlock (&xevq->lock); - thread_state_awake (self); - handle_individual_xevent (xev, xp, tnow /* monotonic */); + handle_individual_xevent (ts1, xev, xp, tnow /* monotonic */); ddsrt_mutex_lock (&xevq->lock); ASSERT_MUTEX_HELD (&xevq->lock); } -static void handle_nontimed_xevent (struct thread_state1 *self, struct xevent_nt *xev, struct nn_xpack *xp) +static void handle_nontimed_xevent (struct xevent_nt *xev, struct nn_xpack *xp) { /* This function handles the individual xevent irrespective of whether it is a "timed" or "non-timed" xevent */ @@ -1296,7 +1296,6 @@ static void handle_nontimed_xevent (struct thread_state1 *self, struct xevent_nt assert (xev->evq == xevq); ddsrt_mutex_unlock (&xevq->lock); - thread_state_awake (self); handle_individual_xevent_nt (xev, xp); /* non-timed xevents are freed by the handlers */ ddsrt_mutex_lock (&xevq->lock); @@ -1304,11 +1303,12 @@ static void handle_nontimed_xevent (struct thread_state1 *self, struct xevent_nt ASSERT_MUTEX_HELD (&xevq->lock); } -static void handle_xevents (struct thread_state1 *self, struct xeventq *xevq, struct nn_xpack *xp, nn_mtime_t tnow /* monotonic */) +static void handle_xevents (struct thread_state1 * const ts1, struct xeventq *xevq, struct nn_xpack *xp, nn_mtime_t tnow /* monotonic */) { int xeventsToProcess = 1; ASSERT_MUTEX_HELD (&xevq->lock); + assert (thread_is_awake ()); /* The following loops give priority to the "timed" events (heartbeats, acknacks etc) if there are any. The algorithm is that we handle all @@ -1334,7 +1334,8 @@ static void handle_xevents (struct thread_state1 *self, struct xeventq *xevq, st scheduled or not), so set to TSCHED_NEVER to indicate it currently isn't. */ xev->tsched.v = T_NEVER; - handle_timed_xevent (self, xev, xp, tnow); + thread_state_awake_to_awake_no_nest (ts1); + handle_timed_xevent (ts1, xev, xp, tnow); } /* Limited-bandwidth channels means events can take a LONG time @@ -1345,7 +1346,8 @@ static void handle_xevents (struct thread_state1 *self, struct xeventq *xevq, st if (!non_timed_xmit_list_is_empty (xevq)) { struct xevent_nt *xev = getnext_from_non_timed_xmit_list (xevq); - handle_nontimed_xevent (self, xev, xp); + thread_state_awake_to_awake_no_nest (ts1); + handle_nontimed_xevent (xev, xp); tnow = now_mt (); } else @@ -1359,7 +1361,7 @@ static void handle_xevents (struct thread_state1 *self, struct xeventq *xevq, st static uint32_t xevent_thread (struct xeventq * xevq) { - struct thread_state1 *self = lookup_thread_state (); + struct thread_state1 * const ts1 = lookup_thread_state (); struct nn_xpack *xp; nn_mtime_t next_thread_cputime = { 0 }; @@ -1372,15 +1374,13 @@ static uint32_t xevent_thread (struct xeventq * xevq) LOG_THREAD_CPUTIME (next_thread_cputime); - handle_xevents (self, xevq, xp, tnow); - - /* Send to the network unlocked, as it may sleep due to bandwidth - limitation */ + thread_state_awake (ts1); + handle_xevents (ts1, xevq, xp, tnow); + /* Send to the network unlocked, as it may sleep due to bandwidth limitation */ ddsrt_mutex_unlock (&xevq->lock); nn_xpack_send (xp, false); ddsrt_mutex_lock (&xevq->lock); - - thread_state_asleep (self); + thread_state_asleep (ts1); if (!non_timed_xmit_list_is_empty (xevq) || xevq->terminate) { diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index d1c83cb..4fc0e57 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -1459,7 +1459,7 @@ void nn_xpack_sendq_init (void) void nn_xpack_sendq_start (void) { - gv.sendq_ts = create_thread("sendq", nn_xpack_sendq_thread, NULL); + create_thread (&gv.sendq_ts, "sendq", nn_xpack_sendq_thread, NULL); } void nn_xpack_sendq_stop (void) diff --git a/src/core/ddsi/src/sysdeps.c b/src/core/ddsi/src/sysdeps.c index e362823..13fa3f1 100644 --- a/src/core/ddsi/src/sysdeps.c +++ b/src/core/ddsi/src/sysdeps.c @@ -51,14 +51,14 @@ void log_stacktrace (const char *name, ddsrt_thread_t tid) if (dds_get_log_mask() == 0) ; /* no op if nothing logged */ else if (!config.noprogress_log_stacktraces) - DDS_LOG(~0u, "-- stack trace of %s requested, but traces disabled --\n", name); + DDS_LOG(~DDS_LC_FATAL, "-- stack trace of %s requested, but traces disabled --\n", name); else { const dds_time_t d = 1000000; struct sigaction act, oact; char **strs; int i; - DDS_LOG(~0u, "-- stack trace of %s requested --\n", name); + DDS_LOG(~DDS_LC_FATAL, "-- stack trace of %s requested --\n", name); act.sa_handler = log_stacktrace_sigh; act.sa_flags = 0; sigfillset (&act.sa_mask); @@ -70,15 +70,15 @@ void log_stacktrace (const char *name, ddsrt_thread_t tid) dds_sleepfor (d); sigaction (SIGXCPU, &oact, NULL); if (pthread_kill (tid.v, 0) != 0) - DDS_LOG(~0u, "-- thread exited --\n"); + DDS_LOG(~DDS_LC_FATAL, "-- thread exited --\n"); else { - DDS_LOG(~0u, "-- stack trace follows --\n"); + DDS_LOG(~DDS_LC_FATAL, "-- stack trace follows --\n"); strs = backtrace_symbols (log_stacktrace_stk.stk, log_stacktrace_stk.depth); for (i = 0; i < log_stacktrace_stk.depth; i++) - DDS_LOG(~0u, "%s\n", strs[i]); + DDS_LOG(~DDS_LC_FATAL, "%s\n", strs[i]); free (strs); - DDS_LOG(~0u, "-- end of stack trace --\n"); + DDS_LOG(~DDS_LC_FATAL, "-- end of stack trace --\n"); } ddsrt_atomic_st32 (&log_stacktrace_flag, 0); } diff --git a/src/core/xtests/rhc_torture.c b/src/core/xtests/rhc_torture.c index bc7c4fb..245d057 100644 --- a/src/core/xtests/rhc_torture.c +++ b/src/core/xtests/rhc_torture.c @@ -108,7 +108,7 @@ static uint64_t store (struct rhc *rhc, struct proxy_writer *wr, struct ddsi_ser /* beware: unrefs sd */ struct ddsi_tkmap_instance *tk; struct proxy_writer_info pwr_info; - thread_state_awake (mainthread); + thread_state_awake (lookup_thread_state ()); tk = ddsi_tkmap_lookup_instance_ref(sd); uint64_t iid = tk->m_iid; if (print) @@ -132,7 +132,7 @@ static uint64_t store (struct rhc *rhc, struct proxy_writer *wr, struct ddsi_ser pwr_info.ownership_strength = wr->c.xqos->ownership_strength.value; dds_rhc_store (rhc, &pwr_info, sd, tk); ddsi_tkmap_instance_unref (tk); - thread_state_asleep (mainthread); + thread_state_asleep (lookup_thread_state ()); ddsi_serdata_unref (sd); return iid; } @@ -171,18 +171,18 @@ static struct rhc *mkrhc (dds_reader *rd, nn_history_kind_t hk, int32_t hdepth, rqos.history.depth = hdepth; rqos.destination_order.kind = dok; nn_xqos_mergein_missing (&rqos, &gv.default_xqos_rd); - thread_state_awake (mainthread); + thread_state_awake (lookup_thread_state ()); rhc = dds_rhc_new (rd, mdtopic); dds_rhc_set_qos(rhc, &rqos); - thread_state_asleep (mainthread); + thread_state_asleep (lookup_thread_state ()); return rhc; } static void frhc (struct rhc *rhc) { - thread_state_awake (mainthread); + thread_state_awake (lookup_thread_state ()); dds_rhc_free (rhc); - thread_state_asleep (mainthread); + thread_state_asleep (lookup_thread_state ()); } static char si2is (const dds_sample_info_t *si) @@ -288,9 +288,9 @@ static void rdtkcond (struct rhc *rhc, dds_readcond *cond, const struct check *c if (print) printf ("%s:\n", opname); - thread_state_awake (mainthread); + thread_state_awake (lookup_thread_state ()); cnt = op (rhc, true, rres_ptrs, rres_iseq, (max <= 0) ? (uint32_t) (sizeof (rres_iseq) / sizeof (rres_iseq[0])) : (uint32_t) max, cond ? NO_STATE_MASK_SET : (DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE), 0, cond); - thread_state_asleep (mainthread); + thread_state_asleep (lookup_thread_state ()); if (max > 0 && cnt > max) { printf ("%s TOO MUCH DATA (%d > %d)\n", opname, cnt, max); abort (); @@ -764,8 +764,8 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count, tkcond (rhc[k], rhcconds[cond], NULL, 1, print && k == 0, states_seen); break; } - case 11: - thread_state_awake (mainthread); + case 11: { + thread_state_awake (lookup_thread_state ()); struct proxy_writer_info wr_info; wr_info.auto_dispose = wr[which]->c.xqos->writer_data_lifecycle.autodispose_unregistered_instances; wr_info.guid = wr[which]->e.guid; @@ -773,8 +773,9 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count, wr_info.ownership_strength = wr[which]->c.xqos->ownership_strength.value; for (size_t k = 0; k < nrd; k++) dds_rhc_unregister_wr (rhc[k], &wr_info); - thread_state_asleep (mainthread); + thread_state_asleep (lookup_thread_state ()); break; + } } if ((i % 200) == 0) @@ -869,14 +870,14 @@ int main (int argc, char **argv) { 0, 0, 0, 0, 0, 0, 0, 0 } }; rdall (rhc, c1, print, states_seen); - thread_state_awake (mainthread); + thread_state_awake (lookup_thread_state ()); struct proxy_writer_info wr0_info; wr0_info.auto_dispose = wr0->c.xqos->writer_data_lifecycle.autodispose_unregistered_instances; wr0_info.guid = wr0->e.guid; wr0_info.iid = wr0->e.iid; wr0_info.ownership_strength = wr0->c.xqos->ownership_strength.value; dds_rhc_unregister_wr (rhc, &wr0_info); - thread_state_asleep (mainthread); + thread_state_asleep (lookup_thread_state ()); const struct check c2[] = { { "ROU", iid0, wr0->e.iid, 0,0, 1, 0,1 }, { "ROU", iid0, 0, 0,0, 0, 0,0 }, From 21a1c4aa333daa8aa9b4b1b312fc429ea74dc614 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 11 Apr 2019 15:12:17 +0200 Subject: [PATCH 022/238] enable printf format checking for dds_log Also remove superfluous parameters in a TRACE statement and fix a format specification in pong.c. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_receive.c | 2 +- src/ddsrt/include/dds/ddsrt/log.h | 4 +++- src/examples/roundtrip/pong.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 9e7f899..a442e86 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -1747,7 +1747,7 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm if (!pwr->have_seen_heartbeat && pwr->n_reliable_readers > 0) { - DDS_TRACE(": no heartbeat seen yet", PGUID (pwr->e.guid), PGUID (dst)); + DDS_TRACE(": no heartbeat seen yet"); ddsrt_mutex_unlock (&pwr->e.lock); return 1; } diff --git a/src/ddsrt/include/dds/ddsrt/log.h b/src/ddsrt/include/dds/ddsrt/log.h index b6450c0..4a08a46 100644 --- a/src/ddsrt/include/dds/ddsrt/log.h +++ b/src/ddsrt/include/dds/ddsrt/log.h @@ -25,6 +25,7 @@ #include #include "dds/export.h" +#include "dds/ddsrt/attributes.h" #if defined (__cplusplus) extern "C" { @@ -199,7 +200,8 @@ dds_log( uint32_t line, const char *func, const char *fmt, - ...); + ...) + ddsrt_attribute_format((__printf__, 5, 6)); /** * @brief Undecorated function name of the current function. diff --git a/src/examples/roundtrip/pong.c b/src/examples/roundtrip/pong.c index ef692f5..010c0c5 100644 --- a/src/examples/roundtrip/pong.c +++ b/src/examples/roundtrip/pong.c @@ -60,7 +60,7 @@ static void data_available(dds_entity_t rd, void *arg) RoundTripModule_DataType * valid_sample = &data[j]; status = dds_write_ts (writer, valid_sample, info[j].source_timestamp); if (status < 0) - DDS_FATAL("dds_write_ts: %s\n", -status); + DDS_FATAL("dds_write_ts: %d\n", -status); } } } From 7f5c56e8196abc8f6e6f009f248301b5182f9bf8 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 13 Apr 2019 17:08:07 +0200 Subject: [PATCH 023/238] defer triggering dqueue thread until end-of-packet There appears to be a minor performance benefit to not waking up the delivery thread (if used) immediately upon enqueueing the first sample, but rather to wait (typically) until the end of the packet. In a latency measurement it probably makes little difference: one shouldn't use asynchronous delivery if one needs the lowest possible latency, and the end of the packet is reached rather quickly normally. Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_radmin.h | 2 ++ src/core/ddsi/src/q_radmin.c | 22 +++++++++++++ src/core/ddsi/src/q_receive.c | 38 +++++++++++++++++------ 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_radmin.h b/src/core/ddsi/include/dds/ddsi/q_radmin.h index 829cdcd..e61c029 100644 --- a/src/core/ddsi/include/dds/ddsi/q_radmin.h +++ b/src/core/ddsi/include/dds/ddsi/q_radmin.h @@ -228,6 +228,8 @@ seqno_t nn_reorder_next_seq (const struct nn_reorder *reorder); struct nn_dqueue *nn_dqueue_new (const char *name, uint32_t max_samples, nn_dqueue_handler_t handler, void *arg); void nn_dqueue_free (struct nn_dqueue *q); +bool nn_dqueue_enqueue_deferred_wakeup (struct nn_dqueue *q, struct nn_rsample_chain *sc, nn_reorder_result_t rres); +void dd_dqueue_enqueue_trigger (struct nn_dqueue *q); void nn_dqueue_enqueue (struct nn_dqueue *q, struct nn_rsample_chain *sc, nn_reorder_result_t rres); void nn_dqueue_enqueue1 (struct nn_dqueue *q, const nn_guid_t *rdguid, struct nn_rsample_chain *sc, nn_reorder_result_t rres); void nn_dqueue_enqueue_callback (struct nn_dqueue *q, nn_dqueue_callback_t cb, void *arg); diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c index 1ca2e83..8b49c64 100644 --- a/src/core/ddsi/src/q_radmin.c +++ b/src/core/ddsi/src/q_radmin.c @@ -2541,6 +2541,26 @@ static int nn_dqueue_enqueue_locked (struct nn_dqueue *q, struct nn_rsample_chai return must_signal; } +bool nn_dqueue_enqueue_deferred_wakeup (struct nn_dqueue *q, struct nn_rsample_chain *sc, nn_reorder_result_t rres) +{ + bool signal; + assert (rres > 0); + assert (sc->first); + assert (sc->last->next == NULL); + ddsrt_mutex_lock (&q->lock); + ddsrt_atomic_add32 (&q->nof_samples, (uint32_t) rres); + signal = nn_dqueue_enqueue_locked (q, sc); + ddsrt_mutex_unlock (&q->lock); + return signal; +} + +void dd_dqueue_enqueue_trigger (struct nn_dqueue *q) +{ + ddsrt_mutex_lock (&q->lock); + ddsrt_cond_broadcast (&q->cond); + ddsrt_mutex_unlock (&q->lock); +} + void nn_dqueue_enqueue (struct nn_dqueue *q, struct nn_rsample_chain *sc, nn_reorder_result_t rres) { assert (rres > 0); @@ -2622,6 +2642,8 @@ void nn_dqueue_wait_until_empty_if_full (struct nn_dqueue *q) if (count >= q->max_samples) { ddsrt_mutex_lock (&q->lock); + /* In case the wakeups are were all deferred */ + ddsrt_cond_broadcast (&q->cond); while (ddsrt_atomic_ld32 (&q->nof_samples) > 0) ddsrt_cond_wait (&q->cond, &q->lock); ddsrt_mutex_unlock (&q->lock); diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index a442e86..8ea8c47 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -2151,7 +2151,7 @@ static void clean_defrag (struct proxy_writer *pwr) nn_defrag_notegap (pwr->defrag, 1, seq); } -static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Data_DataFrag_common_t *msg, const struct nn_rsample_info *sampleinfo, uint32_t fragnum, struct nn_rdata *rdata) +static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Data_DataFrag_common_t *msg, const struct nn_rsample_info *sampleinfo, uint32_t fragnum, struct nn_rdata *rdata, struct nn_dqueue **deferred_wakeup) { struct proxy_writer *pwr; struct nn_rsample *rsample; @@ -2251,10 +2251,23 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct receive thread's data gets interleaved -- arguably delivery needn't be exactly in-order, which would allow us to do this without pwr->e.lock held. */ - if (!pwr->deliver_synchronously) - nn_dqueue_enqueue (pwr->dqueue, &sc, rres); - else + if (pwr->deliver_synchronously) + { + /* FIXME: just in case the synchronous delivery runs into a delay caused + by the current mishandling of resource limits */ + if (*deferred_wakeup) + dd_dqueue_enqueue_trigger (*deferred_wakeup); deliver_user_data_synchronously (&sc); + } + else + { + if (nn_dqueue_enqueue_deferred_wakeup (pwr->dqueue, &sc, rres)) + { + if (*deferred_wakeup && *deferred_wakeup != pwr->dqueue) + dd_dqueue_enqueue_trigger (*deferred_wakeup); + *deferred_wakeup = pwr->dqueue; + } + } if (pwr->n_readers_out_of_sync > 0) { /* Those readers catching up with TL but in sync with the proxy @@ -2384,7 +2397,7 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con } } -static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Data_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap) +static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Data_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap, struct nn_dqueue **deferred_wakeup) { DDS_TRACE("DATA(%x:%x:%x:%x -> %x:%x:%x:%x #%"PRId64"", PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, @@ -2421,14 +2434,14 @@ static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_r } else { - handle_regular (rst, tnow, rmsg, &msg->x, sampleinfo, ~0u, rdata); + handle_regular (rst, tnow, rmsg, &msg->x, sampleinfo, ~0u, rdata, deferred_wakeup); } } DDS_TRACE(")"); return 1; } -static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const DataFrag_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap) +static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const DataFrag_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap, struct nn_dqueue **deferred_wakeup) { DDS_TRACE("DATAFRAG(%x:%x:%x:%x -> %x:%x:%x:%x #%"PRId64"/[%u..%u]", PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, @@ -2494,7 +2507,7 @@ static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct wrong, it'll simply generate a request for retransmitting a non-existent fragment. The other side SHOULD be capable of dealing with that. */ - handle_regular (rst, tnow, rmsg, &msg->x, sampleinfo, msg->fragmentStartingNum + msg->fragmentsInSubmessage - 2, rdata); + handle_regular (rst, tnow, rmsg, &msg->x, sampleinfo, msg->fragmentStartingNum + msg->fragmentsInSubmessage - 2, rdata, deferred_wakeup); } DDS_TRACE(")"); return 1; @@ -2681,6 +2694,7 @@ static int handle_submsg_sequence nn_ddsi_time_t timestamp; size_t submsg_size = 0; unsigned char * end = msg + len; + struct nn_dqueue *deferred_wakeup = NULL; /* Receiver state is dynamically allocated with lifetime bound to the message. Updates cause a new copy to be created if the @@ -2845,7 +2859,7 @@ static int handle_submsg_sequence goto malformed; sampleinfo.timestamp = timestamp; sampleinfo.reception_timestamp = tnowWC; - handle_DataFrag (rst, tnowE, rmsg, &sm->datafrag, submsg_size, &sampleinfo, datap); + handle_DataFrag (rst, tnowE, rmsg, &sm->datafrag, submsg_size, &sampleinfo, datap, &deferred_wakeup); rst_live = 1; ts_for_latmeas = 0; } @@ -2860,7 +2874,7 @@ static int handle_submsg_sequence goto malformed; sampleinfo.timestamp = timestamp; sampleinfo.reception_timestamp = tnowWC; - handle_Data (rst, tnowE, rmsg, &sm->data, submsg_size, &sampleinfo, datap); + handle_Data (rst, tnowE, rmsg, &sm->data, submsg_size, &sampleinfo, datap, &deferred_wakeup); rst_live = 1; ts_for_latmeas = 0; } @@ -2958,6 +2972,8 @@ static int handle_submsg_sequence } thread_state_asleep (ts1); assert (thread_is_asleep ()); + if (deferred_wakeup) + dd_dqueue_enqueue_trigger (deferred_wakeup); return 0; malformed: @@ -2966,6 +2982,8 @@ malformed: malformed_asleep: assert (thread_is_asleep ()); malformed_packet_received (msg, submsg, len, state, state_smkind, hdr->vendorid); + if (deferred_wakeup) + dd_dqueue_enqueue_trigger (deferred_wakeup); return -1; } From 7382c682de4f0c6032282b01bf3d8f049c5344e9 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 13 Apr 2019 17:19:25 +0200 Subject: [PATCH 024/238] eliminate clang static analyzer false positive Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_read.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index b4c5adf..d595272 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -202,7 +202,7 @@ dds_readcdr_impl( thread_state_awake (ts1); rc = dds_read_lock(reader_or_condition, &rd, &cond, false); - if (rc >= DDS_RETCODE_OK) { + if (rc == DDS_RETCODE_OK) { ret = dds_rhc_takecdr ( rd->m_rd->rhc, lock, buf, si, maxs, From 1dad5d6493fead623d59a8d716ccc120f984c0d1 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 16 Apr 2019 17:07:09 +0200 Subject: [PATCH 025/238] add dds_entity_release counterpart to entity_claim Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds__entity.h | 3 +++ src/core/ddsc/src/dds_entity.c | 7 ++++++- src/core/ddsc/src/dds_readcond.c | 4 +--- src/core/ddsc/src/dds_reader.c | 8 ++++---- src/core/ddsc/src/dds_writer.c | 4 ++-- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/core/ddsc/src/dds__entity.h b/src/core/ddsc/src/dds__entity.h index 992c15a..34c13c5 100644 --- a/src/core/ddsc/src/dds__entity.h +++ b/src/core/ddsc/src/dds__entity.h @@ -84,6 +84,9 @@ dds_entity_claim ( dds_entity_t hdl, dds_entity **eptr); +DDS_EXPORT void dds_entity_release ( + dds_entity *e); + DDS_EXPORT dds_retcode_t dds_entity_lock( dds_entity_t hdl, diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index f8a4e14..e06beee 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -761,6 +761,11 @@ dds_retcode_t dds_entity_claim (dds_entity_t hdl, dds_entity **eptr) } } +void dds_entity_release (dds_entity *e) +{ + dds_handle_release (&e->m_hdllink); +} + dds_retcode_t dds_entity_lock (dds_entity_t hdl, dds_entity_kind_t kind, dds_entity **eptr) { dds_retcode_t hres; @@ -989,7 +994,7 @@ dds_return_t dds_generic_unimplemented_operation_manykinds (dds_entity_t handle, break; } } - dds_handle_release (&e->m_hdllink); + dds_entity_release (e); return DDS_ERRNO (ret); } } diff --git a/src/core/ddsc/src/dds_readcond.c b/src/core/ddsc/src/dds_readcond.c index 322af8e..ee37521 100644 --- a/src/core/ddsc/src/dds_readcond.c +++ b/src/core/ddsc/src/dds_readcond.c @@ -100,13 +100,11 @@ dds_entity_t dds_get_datareader (dds_entity_t condition) rdh = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); break; } - dds_handle_release (&e->m_hdllink); + dds_entity_release (e); return rdh; } } - - dds_return_t dds_get_mask (dds_entity_t condition, uint32_t *mask) { dds_entity *entity; diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 2c14994..dcc3289 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -384,7 +384,7 @@ dds_create_reader( } else { subscriber = participant_or_subscriber; } - dds_handle_release (&p_or_s->m_hdllink); + dds_entity_release (p_or_s); internal_topic = false; t = topic; break; @@ -512,7 +512,7 @@ void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb if (dds_entity_kind (dds_entity) != DDS_KIND_READER) { - dds_handle_release (&dds_entity->m_hdllink); + dds_entity_release (dds_entity); return; } @@ -552,7 +552,7 @@ void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb ddsrt_mutex_lock (&rd->e.lock); } ddsrt_mutex_unlock (&rd->e.lock); - dds_handle_release (&dds_rd->m_entity.m_hdllink); + dds_entity_release (dds_entity); } uint32_t dds_reader_lock_samples (dds_entity_t reader) @@ -613,7 +613,7 @@ dds_entity_t dds_get_subscriber (dds_entity_t entity) subh = DDS_ERRNO (DDS_RETCODE_ILLEGAL_OPERATION); break; } - dds_handle_release (&e->m_hdllink); + dds_entity_release (e); return subh; } } diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 06a13ef..5bd81d6 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -388,7 +388,7 @@ dds_create_writer( } else { publisher = participant_or_publisher; } - dds_handle_release (&p_or_p->m_hdllink); + dds_entity_release (p_or_p); } if ((rc = dds_publisher_lock(publisher, &pub)) != DDS_RETCODE_OK) { @@ -494,7 +494,7 @@ dds_get_publisher( assert (dds_entity_kind (e->m_parent) == DDS_KIND_PUBLISHER); pubh = e->m_parent->m_hdllink.hdl; } - dds_handle_release (&e->m_hdllink); + dds_entity_release (e); return pubh; } } From e085130a3995f594f86699c99c260f267c2fc557 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Apr 2019 10:38:12 +0200 Subject: [PATCH 026/238] fix deadlock between listener, deleting reader, &c If a (proxy) writer delivers data to a reader that has a data_available listener calling read/take while that reader is being deleted, blocked in set_listener waiting for the listeners to complete, then a deadlock can occur: * listener calling read/take then attempt to lock reader; * deleting the reader locks the reader, then waits for the listeners to complete while holding the lock This commits unlocks the reader before waiting for the listeners to complete. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_entity.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index e06beee..6704b6e 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -163,18 +163,23 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) return DDS_RETCODE_OK; } + /* FIXME: "closing" the handle here means a listener invoked on X + can still discover that X has become inaccessible */ + /* FIXME: RHC reads m_status_enable outside lock and might still + just invoke the listener */ dds_handle_close (&e->m_hdllink); - ddsrt_mutex_lock (&e->m_observers_lock); - while (e->m_cb_count > 0) - ddsrt_cond_wait (&e->m_observers_cond, &e->m_observers_lock); e->m_status_enable = 0; dds_reset_listener (&e->m_listener); e->m_trigger |= DDS_DELETING_STATUS; - ddsrt_mutex_unlock (&e->m_observers_lock); dds_entity_unlock(e); - /* Signal observers that this entity will be deleted. */ - dds_entity_status_signal (e); + /* Signal observers that this entity will be deleted and wait for + all listeners to complete. */ + ddsrt_mutex_lock (&e->m_observers_lock); + dds_entity_observers_signal (e, e->m_trigger); + while (e->m_cb_count > 0) + ddsrt_cond_wait (&e->m_observers_cond, &e->m_observers_lock); + ddsrt_mutex_unlock (&e->m_observers_lock); /* * Recursively delete children. @@ -547,7 +552,7 @@ dds_return_t dds_set_listener (dds_entity_t entity, const dds_listener_t *listen dds_entity *e, *x; dds_retcode_t rc; - if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + if ((rc = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) return DDS_ERRNO (rc); ddsrt_mutex_lock (&e->m_observers_lock); @@ -568,7 +573,7 @@ dds_return_t dds_set_listener (dds_entity_t entity, const dds_listener_t *listen } clear_status_with_listener (e); ddsrt_mutex_unlock (&e->m_observers_lock); - dds_entity_unlock (e); + dds_entity_release (e); pushdown_listener (entity); return DDS_RETCODE_OK; } @@ -625,7 +630,7 @@ dds_return_t dds_get_status_mask (dds_entity_t entity, uint32_t *mask) if (mask == NULL) return DDS_ERRNO (DDS_RETCODE_BAD_PARAMETER); - if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + if ((rc = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) return DDS_ERRNO (rc); if (e->m_deriver.validate_status == 0) @@ -637,7 +642,7 @@ dds_return_t dds_get_status_mask (dds_entity_t entity, uint32_t *mask) ddsrt_mutex_unlock (&e->m_observers_lock); ret = DDS_RETCODE_OK; } - dds_entity_unlock(e); + dds_entity_release(e); return ret; } @@ -652,7 +657,7 @@ dds_return_t dds_set_status_mask (dds_entity_t entity, uint32_t mask) dds_retcode_t rc; dds_return_t ret; - if ((rc = dds_entity_lock (entity, DDS_KIND_DONTCARE, &e)) != DDS_RETCODE_OK) + if ((rc = dds_entity_claim (entity, &e)) != DDS_RETCODE_OK) return DDS_ERRNO (rc); if (e->m_deriver.validate_status == 0) @@ -660,13 +665,16 @@ dds_return_t dds_set_status_mask (dds_entity_t entity, uint32_t mask) else if ((ret = e->m_deriver.validate_status (mask)) == DDS_RETCODE_OK) { ddsrt_mutex_lock (&e->m_observers_lock); + while (e->m_cb_count > 0) + ddsrt_cond_wait (&e->m_observers_cond, &e->m_observers_lock); + /* Don't block internal status triggers. */ mask |= DDS_INTERNAL_STATUS_MASK; e->m_status_enable = mask; e->m_trigger &= mask; ddsrt_mutex_unlock (&e->m_observers_lock); } - dds_entity_unlock(e); + dds_entity_release (e); return ret; } From 59270173dc07da2deef422aa9afe97d4bcb161bf Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 16 Apr 2019 17:09:08 +0200 Subject: [PATCH 027/238] remove dds_rhc_fini abomination It was called strangely early in the deleting of the reader, even before the DDSI reader was no longer being accessed by other threads. The immediate and obvious problem is that it resets the pointer to the upper-layer entity even though this can still be dereferenced in invoking a listener, resulting in a crash. Secondly it blocks until there are no listener calls any more (and the resetting of that pointer will prevent any further listener invocations), but a similar piece of logic is already in generic entity code that resets the mask and then waits for all listener invocations to complete. Having both is a problem. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds__rhc.h | 1 - src/core/ddsc/src/dds_init.c | 1 - src/core/ddsc/src/dds_reader.c | 10 ++++- src/core/ddsc/src/dds_rhc.c | 44 +++---------------- .../ddsi/include/dds/ddsi/ddsi_rhc_plugin.h | 1 - src/core/ddsi/src/q_entity.c | 4 -- 6 files changed, 13 insertions(+), 48 deletions(-) diff --git a/src/core/ddsc/src/dds__rhc.h b/src/core/ddsc/src/dds__rhc.h index e01f7c4..fc08a7f 100644 --- a/src/core/ddsc/src/dds__rhc.h +++ b/src/core/ddsc/src/dds__rhc.h @@ -26,7 +26,6 @@ struct proxy_writer_info; DDS_EXPORT struct rhc *dds_rhc_new (dds_reader *reader, const struct ddsi_sertopic *topic); DDS_EXPORT void dds_rhc_free (struct rhc *rhc); -DDS_EXPORT void dds_rhc_fini (struct rhc *rhc); DDS_EXPORT uint32_t dds_rhc_lock_samples (struct rhc *rhc); diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index 1efd81d..e6558d5 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -273,7 +273,6 @@ void ddsi_plugin_init (void) ddsi_plugin.builtintopic_write = dds__builtin_write; ddsi_plugin.rhc_plugin.rhc_free_fn = dds_rhc_free; - ddsi_plugin.rhc_plugin.rhc_fini_fn = dds_rhc_fini; ddsi_plugin.rhc_plugin.rhc_store_fn = dds_rhc_store; ddsi_plugin.rhc_plugin.rhc_unregister_wr_fn = dds_rhc_unregister_wr; ddsi_plugin.rhc_plugin.rhc_relinquish_ownership_fn = dds_rhc_relinquish_ownership; diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index dcc3289..b3f241b 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -160,14 +160,20 @@ void dds_reader_data_available_cb (struct dds_reader *rd) status on the subscriber; secondly it is the only one for which overhead really matters. Otherwise, it is pretty much like dds_reader_status_cb. */ - struct dds_listener const * const lst = &rd->m_entity.m_listener; - dds_entity * const sub = rd->m_entity.m_parent; ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); + if (!(rd->m_entity.m_status_enable & DDS_DATA_AVAILABLE_STATUS)) + { + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); + return; + } + while (rd->m_entity.m_cb_count > 0) ddsrt_cond_wait (&rd->m_entity.m_observers_cond, &rd->m_entity.m_observers_lock); rd->m_entity.m_cb_count++; + struct dds_listener const * const lst = &rd->m_entity.m_listener; + dds_entity * const sub = rd->m_entity.m_parent; if (lst->on_data_on_readers) { ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index 7f3029b..4eb64dc 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -277,7 +277,6 @@ struct rhc { /* Instance/Sample maximums from resource limits QoS */ - ddsrt_atomic_uint32_t n_cbs; /* # callbacks in progress */ int32_t max_instances; /* FIXME: probably better as uint32_t with MAX_UINT32 for unlimited */ int32_t max_samples; /* FIXME: probably better as uint32_t with MAX_UINT32 for unlimited */ int32_t max_samples_per_instance; /* FIXME: probably better as uint32_t with MAX_UINT32 for unlimited */ @@ -631,20 +630,6 @@ void dds_rhc_free (struct rhc *rhc) ddsrt_free (rhc); } -void dds_rhc_fini (struct rhc * rhc) -{ - ddsrt_mutex_lock (&rhc->lock); - rhc->reader = NULL; - ddsrt_mutex_unlock (&rhc->lock); - - /* Wait for all callbacks to complete */ - - while (ddsrt_atomic_ld32 (&rhc->n_cbs) > 0) - { - dds_sleepfor (DDS_MSECS (1)); - } -} - static void init_trigger_info_cmn_nonmatch (struct trigger_info_cmn *info) { info->qminst = ~0u; @@ -1462,17 +1447,10 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info if (rhc->reader) { - if (notify_data_available && (rhc->reader->m_entity.m_status_enable & DDS_DATA_AVAILABLE_STATUS)) - { - ddsrt_atomic_inc32 (&rhc->n_cbs); + if (notify_data_available) dds_reader_data_available_cb (rhc->reader); - ddsrt_atomic_dec32 (&rhc->n_cbs); - } - if (trigger_waitsets) - { - dds_entity_status_signal(&rhc->reader->m_entity); - } + dds_entity_status_signal (&rhc->reader->m_entity); } return delivered; @@ -1489,13 +1467,8 @@ error_or_nochange: /* Make any reader status callback */ - if (cb_data.raw_status_id >= 0 && rhc->reader && rhc->reader->m_entity.m_status_enable) - { - ddsrt_atomic_inc32 (&rhc->n_cbs); + if (cb_data.raw_status_id >= 0 && rhc->reader) dds_reader_status_cb (&rhc->reader->m_entity, &cb_data); - ddsrt_atomic_dec32 (&rhc->n_cbs); - } - return delivered; } @@ -1575,17 +1548,10 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ if (rhc->reader) { - if (notify_data_available && (rhc->reader->m_entity.m_status_enable & DDS_DATA_AVAILABLE_STATUS)) - { - ddsrt_atomic_inc32 (&rhc->n_cbs); + if (notify_data_available) dds_reader_data_available_cb (rhc->reader); - ddsrt_atomic_dec32 (&rhc->n_cbs); - } - if (trigger_waitsets) - { - dds_entity_status_signal(&rhc->reader->m_entity); - } + dds_entity_status_signal (&rhc->reader->m_entity); } } diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h b/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h index 7f884fa..57c8813 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h @@ -30,7 +30,6 @@ struct proxy_writer_info struct ddsi_rhc_plugin { void (*rhc_free_fn) (struct rhc *rhc); - void (*rhc_fini_fn) (struct rhc *rhc); bool (*rhc_store_fn) (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 685543b..3dffa18 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -3386,10 +3386,6 @@ int delete_reader (const struct nn_guid *guid) DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid %x:%x:%x:%x) - unknown guid\n", PGUID (*guid)); return Q_ERR_UNKNOWN_ENTITY; } - if (rd->rhc) - { - (ddsi_plugin.rhc_plugin.rhc_fini_fn) (rd->rhc); - } DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid %x:%x:%x:%x) ...\n", PGUID (*guid)); ddsi_plugin.builtintopic_write (&rd->e, now(), false); ephash_remove_reader_guid (rd); From c891fdc685182209d17734e60d909cf8dc88c6f2 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Apr 2019 10:49:51 +0200 Subject: [PATCH 028/238] block signals in ddsrt_thread_create Signal handling in multi-threaded processes is bad enough at the best of times, and as we don't really use any signals in the Cyclone code, it makes more sense to create all threads with most signals blocked. That way an application that wants to handle signals using sigwait() need not block all signals prior to creating a participant. Note that instead of blocking all signals, we block all except SIGXCPU. The reason is that the liveliness monitoring and stack trace dumping code currently relies on that signal. Signed-off-by: Erik Boasson --- src/ddsrt/src/threads/posix/threads.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ddsrt/src/threads/posix/threads.c b/src/ddsrt/src/threads/posix/threads.c index 278d796..f8dbf4c 100644 --- a/src/ddsrt/src/threads/posix/threads.c +++ b/src/ddsrt/src/threads/posix/threads.c @@ -193,6 +193,7 @@ ddsrt_thread_create ( thread_context_t *ctx; ddsrt_threadattr_t tattr; int result, create_ret; + sigset_t set, oset; assert (threadptr != NULL); assert (name != NULL); @@ -281,11 +282,18 @@ ddsrt_thread_create ( strcpy (ctx->name, name); ctx->routine = start_routine; ctx->arg = arg; + + /* Block signal delivery in our own threads (SIGXCPU is excluded so we have a way of + dumping stack traces, but that should be improved upon) */ + sigfillset (&set); + sigdelset (&set, SIGXCPU); + sigprocmask (SIG_BLOCK, &set, &oset); if ((create_ret = pthread_create (&threadptr->v, &attr, os_startRoutineWrapper, ctx)) != 0) { DDS_ERROR ("os_threadCreate(%s): pthread_create failed with error %d\n", name, create_ret); goto err_create; } + sigprocmask (SIG_SETMASK, &oset, NULL); pthread_attr_destroy (&attr); return DDS_RETCODE_OK; From 6e2068173a8258cd0ded53a7c7a6fc977d883a6f Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Apr 2019 11:04:26 +0200 Subject: [PATCH 029/238] crash invoking data available on built-in reader The DDSI reader/writer pointers are now returned as out parameters instead of as a return value, so that the upper-layer reference is set before any listener can be invoked. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_reader.c | 6 +- src/core/ddsc/src/dds_writer.c | 4 +- src/core/ddsi/include/dds/ddsi/q_entity.h | 4 +- src/core/ddsi/src/q_entity.c | 68 ++++++++++++----------- 4 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index b3f241b..b039495 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -472,11 +472,11 @@ dds_create_reader( ddsrt_mutex_unlock(&sub->m_entity.m_mutex); thread_state_awake (lookup_thread_state ()); - rd->m_rd = new_reader(&rd->m_entity.m_guid, NULL, &sub->m_entity.m_participant->m_guid, tp->m_stopic, - rqos, rhc, dds_reader_status_cb, rd); + ret = new_reader(&rd->m_rd, &rd->m_entity.m_guid, NULL, &sub->m_entity.m_participant->m_guid, tp->m_stopic, + rqos, rhc, dds_reader_status_cb, rd); ddsrt_mutex_lock(&sub->m_entity.m_mutex); ddsrt_mutex_lock(&tp->m_entity.m_mutex); - assert (rd->m_rd); + assert (ret == DDS_RETCODE_OK); thread_state_asleep (lookup_thread_state ()); /* For persistent data register reader with durability */ diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 5bd81d6..cd83d3e 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -456,10 +456,10 @@ dds_create_writer( ddsrt_mutex_unlock (&pub->m_entity.m_mutex); thread_state_awake (lookup_thread_state ()); - wr->m_wr = new_writer(&wr->m_entity.m_guid, NULL, &pub->m_entity.m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); + ret = new_writer(&wr->m_wr, &wr->m_entity.m_guid, NULL, &pub->m_entity.m_participant->m_guid, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); ddsrt_mutex_lock (&pub->m_entity.m_mutex); ddsrt_mutex_lock (&tp->m_entity.m_mutex); - assert(wr->m_wr); + assert(ret == DDS_RETCODE_OK); thread_state_asleep (lookup_thread_state ()); dds_topic_unlock(tp); dds_publisher_unlock(pub); diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 6f79aac..9138e02 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -479,9 +479,9 @@ struct writer *get_builtin_writer (const struct participant *pp, unsigned entity GUID "ppguid". May return NULL if participant unknown or writer/reader already known. */ -struct writer *new_writer (struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg); +dds_retcode_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg); -struct reader *new_reader (struct nn_guid *rdguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct rhc * rhc, status_cb_t status_cb, void *status_cb_arg); +dds_retcode_t new_reader (struct reader **rd_out, struct nn_guid *rdguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct rhc * rhc, status_cb_t status_cb, void *status_cb_arg); struct whc_node; struct whc_state; diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 3dffa18..565c72b 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -88,8 +88,8 @@ static const unsigned prismtech_builtin_writers_besmask = NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_WRITER | NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_WRITER; -static struct writer * new_writer_guid (const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void *status_cbarg); -static struct reader * new_reader_guid (const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct rhc *rhc, status_cb_t status_cb, void *status_cbarg); +static dds_retcode_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void *status_cbarg); +static dds_retcode_t new_reader_guid (struct reader **rd_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct rhc *rhc, status_cb_t status_cb, void *status_cbarg); static struct participant *ref_participant (struct participant *pp, const struct nn_guid *guid_of_refing_entity); static void unref_participant (struct participant *pp, const struct nn_guid *guid_of_refing_entity); static void delete_proxy_group_locked (struct proxy_group *pgroup, nn_wctime_t timestamp, int isimplicit); @@ -488,7 +488,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS)) { subguid.entityid = to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER); - new_writer_guid (&subguid, &group_guid, pp, NULL, &gv.spdp_endpoint_xqos, whc_new(1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.spdp_endpoint_xqos, whc_new(1, 1, 1), LAST_WR_PARAMS); /* But we need the as_disc address set for SPDP, because we need to send it to everyone regardless of the existence of readers. */ { @@ -511,23 +511,23 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS)) { subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER); - new_writer_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER; subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER); - new_writer_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER; subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_WRITER); - new_writer_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_WRITER; subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_WRITER); - new_writer_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_WRITER; subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_WRITER); - new_writer_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_WRITER; } @@ -535,7 +535,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis { /* TODO: make this one configurable, we don't want all participants to publish all topics (or even just those that they use themselves) */ subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER); - new_writer_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER; } @@ -543,7 +543,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS)) { subguid.entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER); - new_writer_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); + new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_wr, whc_new(1, 1, 1), LAST_WR_PARAMS); pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER; } @@ -551,31 +551,31 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis if (!(flags & RTPS_PF_NO_BUILTIN_READERS)) { subguid.entityid = to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER); - new_reader_guid (&subguid, &group_guid, pp, NULL, &gv.spdp_endpoint_xqos, NULL, NULL, NULL); + new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.spdp_endpoint_xqos, NULL, NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR; subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER); - new_reader_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_DETECTOR; subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER); - new_reader_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_DETECTOR; subguid.entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER); - new_reader_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER; subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_PARTICIPANT_READER); - new_reader_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_READER; subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_PUBLISHER_READER); - new_reader_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_READER; subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_CM_SUBSCRIBER_READER); - new_reader_guid (&subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv.builtin_endpoint_xqos_rd, NULL, NULL, NULL); pp->prismtech_bes |= NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_READER; } @@ -2779,7 +2779,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se local_reader_ary_init (&wr->rdary); } -static struct writer *new_writer_guid (const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void *status_entity) +static dds_retcode_t new_writer_guid (struct writer **wr_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc, status_cb_t status_cb, void *status_entity) { struct writer *wr; nn_mtime_t tnow = now_mt (); @@ -2790,6 +2790,8 @@ static struct writer *new_writer_guid (const struct nn_guid *guid, const struct new_reader_writer_common (guid, topic, xqos); wr = ddsrt_malloc (sizeof (*wr)); + if (wr_out) + *wr_out = wr; /* want a pointer to the participant so that a parallel call to delete_participant won't interfere with our ability to address @@ -2822,27 +2824,25 @@ static struct writer *new_writer_guid (const struct nn_guid *guid, const struct resched_xevent_if_earlier (pp->pmd_update_xevent, tsched); } - return wr; + return DDS_RETCODE_OK; } -struct writer *new_writer (struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg) +dds_retcode_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, const struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg) { struct participant *pp; - struct writer * wr; if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL) { DDS_LOG(DDS_LC_DISCOVERY, "new_writer - participant %x:%x:%x:%x not found\n", PGUID (*ppguid)); - return NULL; + return DDS_RETCODE_NOT_FOUND; } /* participant can't be freed while we're mucking around cos we are awake and do not touch the thread's vtime (ephash_lookup already verifies we're awake) */ wrguid->prefix = pp->e.guid.prefix; if (pp_allocate_entityid (&wrguid->entityid, NN_ENTITYID_KIND_WRITER_WITH_KEY, pp) < 0) - return NULL; - wr = new_writer_guid (wrguid, group_guid, pp, topic, xqos, whc, status_cb, status_cb_arg); - return wr; + return DDS_RETCODE_OUT_OF_RESOURCES; + return new_writer_guid (wr_out, wrguid, group_guid, pp, topic, xqos, whc, status_cb, status_cb_arg); } struct local_orphan_writer *new_local_orphan_writer (nn_entityid_t entityid, struct ddsi_sertopic *topic, const struct nn_xqos *xqos, struct whc *whc) @@ -3170,8 +3170,9 @@ static void leave_mcast_helper (const nn_locator_t *n, void * varg) } #endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */ -static struct reader * new_reader_guid +static dds_retcode_t new_reader_guid ( + struct reader **rd_out, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp, @@ -3193,6 +3194,8 @@ static struct reader * new_reader_guid new_reader_writer_common (guid, topic, xqos); rd = ddsrt_malloc (sizeof (*rd)); + if (rd_out) + *rd_out = rd; endpoint_common_init (&rd->e, &rd->c, EK_READER, guid, group_guid, pp); @@ -3300,11 +3303,12 @@ static struct reader * new_reader_guid match_reader_with_local_writers (rd, tnow); ddsi_plugin.builtintopic_write (&rd->e, now(), true); sedp_write_reader (rd); - return rd; + return DDS_RETCODE_OK; } -struct reader * new_reader +dds_retcode_t new_reader ( + struct reader **rd_out, struct nn_guid *rdguid, const struct nn_guid *group_guid, const struct nn_guid *ppguid, @@ -3316,18 +3320,16 @@ struct reader * new_reader ) { struct participant * pp; - struct reader * rd; if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL) { DDS_LOG(DDS_LC_DISCOVERY, "new_reader - participant %x:%x:%x:%x not found\n", PGUID (*ppguid)); - return NULL; + return DDS_RETCODE_NOT_FOUND; } rdguid->prefix = pp->e.guid.prefix; if (pp_allocate_entityid (&rdguid->entityid, NN_ENTITYID_KIND_READER_WITH_KEY, pp) < 0) - return NULL; - rd = new_reader_guid (rdguid, group_guid, pp, topic, xqos, rhc, status_cb, status_cbarg); - return rd; + return DDS_RETCODE_OUT_OF_RESOURCES; + return new_reader_guid (rd_out, rdguid, group_guid, pp, topic, xqos, rhc, status_cb, status_cbarg); } static void gc_delete_reader (struct gcreq *gcreq) From 14148aceb54c8171e0236d7da0127e45aa56bc0b Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Apr 2019 11:42:56 +0200 Subject: [PATCH 030/238] add QoS to ignore local readers/writers (#78) Adds a new "ignorelocal" QoS to the readers/writers to ignore local matching readers/writers, with three settings: * DDS_IGNORELOCAL_NONE: default * DDS_IGNORELOCAL_PARTICIPANT: ignores readers/writers in the same participant * DDS_IGNORELOCAL_PROCESS: ignores readers/writers in the same process These can be set/got using dds_qset_ignorelocal and dds_qget_ignorelocal. If a matching reader or writer is ignored because of this setting, it is as-if that reader or writer doesn't exist. No traffic will be generated or data retained on its behalf. There are no consequences for interoperability as this is (by definition) a local affair. Signed-off-by: Erik Boasson --- .../ddsc/include/dds/ddsc/dds_public_qos.h | 33 +++++++++++++++++++ src/core/ddsc/src/dds_qos.c | 21 ++++++++++++ src/core/ddsi/include/dds/ddsi/q_xqos.h | 12 +++++++ src/core/ddsi/src/q_entity.c | 27 +++++++++++++++ src/core/ddsi/src/q_plist.c | 10 ++++++ 5 files changed, 103 insertions(+) diff --git a/src/core/ddsc/include/dds/ddsc/dds_public_qos.h b/src/core/ddsc/include/dds/ddsc/dds_public_qos.h index 4ffceb4..8f319c1 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_qos.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_qos.h @@ -136,6 +136,16 @@ typedef enum dds_presentation_access_scope_kind } dds_presentation_access_scope_kind_t; +/** Ignore-local QoS: Applies to DataReader, DataWriter */ +typedef enum dds_ignorelocal_kind +{ + DDS_IGNORELOCAL_NONE, + DDS_IGNORELOCAL_PARTICIPANT, + DDS_IGNORELOCAL_PROCESS +} +dds_ignorelocal_kind_t; + + /** * @brief Allocate memory and initialize default QoS-policies * @@ -465,6 +475,16 @@ dds_qset_durability_service ( int32_t max_instances, int32_t max_samples_per_instance); +/** + * @brief Set the ignore-local policy of a qos structure + * + * @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy + * @param[in] ignore - True if readers and writers owned by the same participant should be ignored + */ +DDS_EXPORT void dds_qset_ignorelocal ( + dds_qos_t * __restrict qos, + dds_ignorelocal_kind_t ignore); + /** * @brief Get the userdata from a qos structure * @@ -753,6 +773,19 @@ dds_qget_durability_service ( int32_t *max_instances, int32_t *max_samples_per_instance); + /** + * @brief Get the ignore-local qos policy + * + * @param[in] qos - Pointer to a dds_qos_t structure storing the policy + * @param[in,out] ignore - Pointer that will store whether to ignore readers/writers owned by the same participant (optional) + * + * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object + */ +DDS_EXPORT bool +dds_qget_ignorelocal ( + const dds_qos_t * __restrict qos, + dds_ignorelocal_kind_t *ignore); + #if defined (__cplusplus) } #endif diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index bc1869c..25a3ce6 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -658,6 +658,16 @@ void dds_qset_durability_service } } +void dds_qset_ignorelocal (dds_qos_t * __restrict qos, dds_ignorelocal_kind_t ignore) +{ + if (qos) { + qos->ignorelocal.value = (nn_ignorelocal_kind_t) ignore; + qos->present |= QP_CYCLONE_IGNORELOCAL; + } else { + DDS_ERROR("Argument QoS is NULL\n"); + } +} + bool dds_qget_userdata (const dds_qos_t * __restrict qos, void **value, size_t *sz) { if (!qos || !(qos->present & QP_USER_DATA)) { @@ -931,3 +941,14 @@ bool dds_qget_durability_service (const dds_qos_t * __restrict qos, dds_duration } return true; } + +bool dds_qget_ignorelocal (const dds_qos_t * __restrict qos, dds_ignorelocal_kind_t *ignore) +{ + if (!qos || !(qos->present & QP_CYCLONE_IGNORELOCAL)) { + return false; + } + if (ignore) { + *ignore = (dds_ignorelocal_kind_t) qos->ignorelocal.value; + } + return true; +} diff --git a/src/core/ddsi/include/dds/ddsi/q_xqos.h b/src/core/ddsi/include/dds/ddsi/q_xqos.h index 46a15bf..d13207d 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xqos.h +++ b/src/core/ddsi/include/dds/ddsi/q_xqos.h @@ -205,6 +205,16 @@ typedef struct nn_share_qospolicy { char *name; } nn_share_qospolicy_t; +typedef enum nn_ignorelocal_kind { + NN_NONE_IGNORELOCAL_QOS, + NN_PARTICIPANT_IGNORELOCAL_QOS, + NN_PROCESS_IGNORELOCAL_QOS +} nn_ignorelocal_kind_t; + +typedef struct nn_ignorelocal_qospolicy { + nn_ignorelocal_kind_t value; +} nn_ignorelocal_qospolicy_t; + /***/ /* Qos Present bit indices */ @@ -237,6 +247,7 @@ typedef struct nn_share_qospolicy { #define QP_PRISMTECH_ENTITY_FACTORY ((uint64_t)1 << 27) #define QP_PRISMTECH_SYNCHRONOUS_ENDPOINT ((uint64_t)1 << 28) #define QP_RTI_TYPECODE ((uint64_t)1 << 29) +#define QP_CYCLONE_IGNORELOCAL ((uint64_t)1 << 30) /* Partition QoS is not RxO according to the specification (DDS 1.2, section 7.1.3), but communication will not take place unless it @@ -290,6 +301,7 @@ typedef struct nn_xqos { /*x xR*/nn_reader_lifespan_qospolicy_t reader_lifespan; /*x xR*/nn_share_qospolicy_t share; /*xxx */nn_synchronous_endpoint_qospolicy_t synchronous_endpoint; + /* x */nn_ignorelocal_qospolicy_t ignorelocal; /* X*/nn_octetseq_t rti_typecode; } nn_xqos_t; diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 565c72b..3626afd 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -2058,12 +2058,39 @@ static void connect_proxy_writer_with_reader (struct proxy_writer *pwr, struct r proxy_writer_add_connection (pwr, rd, tnow, init_count); } +static bool ignore_local_p (const nn_guid_t *guid1, const nn_guid_t *guid2, const struct nn_xqos *xqos1, const struct nn_xqos *xqos2) +{ + assert (xqos1->present & QP_CYCLONE_IGNORELOCAL); + assert (xqos2->present & QP_CYCLONE_IGNORELOCAL); + switch (xqos1->ignorelocal.value) + { + case NN_NONE_IGNORELOCAL_QOS: + break; + case NN_PARTICIPANT_IGNORELOCAL_QOS: + return memcmp (&guid1->prefix, &guid2->prefix, sizeof (guid1->prefix)) == 0; + case NN_PROCESS_IGNORELOCAL_QOS: + return true; + } + switch (xqos2->ignorelocal.value) + { + case NN_NONE_IGNORELOCAL_QOS: + break; + case NN_PARTICIPANT_IGNORELOCAL_QOS: + return memcmp (&guid1->prefix, &guid2->prefix, sizeof (guid1->prefix)) == 0; + case NN_PROCESS_IGNORELOCAL_QOS: + return true; + } + return false; +} + static void connect_writer_with_reader (struct writer *wr, struct reader *rd, nn_mtime_t tnow) { int32_t reason; (void)tnow; if (!is_local_orphan_endpoint (&wr->e) && (is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE) || is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE))) return; + if (ignore_local_p (&wr->e.guid, &rd->e.guid, wr->xqos, rd->xqos)) + return; if ((reason = qos_match_p (rd->xqos, wr->xqos)) >= 0) { writer_qos_mismatch (wr, (uint32_t)reason); diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index ad97995..c7a8222 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -2656,6 +2656,9 @@ static void xqos_init_default_common (nn_xqos_t *xqos) xqos->present |= QP_PRISMTECH_SYNCHRONOUS_ENDPOINT; xqos->synchronous_endpoint.value = 0; + + xqos->present |= QP_CYCLONE_IGNORELOCAL; + xqos->ignorelocal.value = NN_NONE_IGNORELOCAL_QOS; } void nn_xqos_init_default_reader (nn_xqos_t *xqos) @@ -2810,6 +2813,7 @@ void nn_xqos_mergein_missing (nn_xqos_t *a, const nn_xqos_t *b) CQ (PRISMTECH_READER_LIFESPAN, reader_lifespan); CQ (PRISMTECH_ENTITY_FACTORY, entity_factory); CQ (PRISMTECH_SYNCHRONOUS_ENDPOINT, synchronous_endpoint); + CQ (CYCLONE_IGNORELOCAL, ignorelocal); #undef CQ /* For allocated ones it is Not strictly necessary to use tmp, as @@ -3197,6 +3201,10 @@ uint64_t nn_xqos_delta (const nn_xqos_t *a, const nn_xqos_t *b, uint64_t mask) if (octetseqs_differ (&a->rti_typecode, &b->rti_typecode)) delta |= QP_RTI_TYPECODE; } + if (check & QP_CYCLONE_IGNORELOCAL) { + if (a->ignorelocal.value != b->ignorelocal.value) + delta |= QP_CYCLONE_IGNORELOCAL; + } return delta; } @@ -3257,6 +3265,7 @@ void nn_xqos_addtomsg (struct nn_xmsg *m, const nn_xqos_t *xqos, uint64_t wanted SIMPLE (PRISMTECH_ENTITY_FACTORY, entity_factory); SIMPLE (PRISMTECH_SYNCHRONOUS_ENDPOINT, synchronous_endpoint); FUNC_BY_REF (RTI_TYPECODE, rti_typecode, octetseq); + /* CYCLONE_IGNORELOCAL is not visible on the wire */ #undef FUNC_BY_REF #undef FUNC_BY_VAL #undef SIMPLE @@ -3467,6 +3476,7 @@ void nn_log_xqos (uint32_t cat, const nn_xqos_t *xqos) log_octetseq (cat, xqos->rti_typecode.length, xqos->rti_typecode.value); DDS_LOG(cat, ">"); }); + DO (CYCLONE_IGNORELOCAL, { LOGB1 ("ignorelocal=%u", xqos->ignorelocal.value); }); #undef PRINTARG_DUR #undef FMT_DUR From e6f35cdab88d7a3cd59b61e5947305ed17864123 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Apr 2019 11:43:39 +0200 Subject: [PATCH 031/238] publish built-in topics prior to matching The built-in topics for readers and writers should be published before a subscription or publication matched listener is invoked, otherwise the instance handle provided to the listener is not yet available in a reader for the corresponding topic. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_entity.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 3626afd..2c5105c 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -2832,7 +2832,10 @@ static dds_retcode_t new_writer_guid (struct writer **wr_out, const struct nn_gu the order if hash insert & matching creates a window during which neither of two endpoints being created in parallel can discover the other. */ + ddsrt_mutex_lock (&wr->e.lock); ephash_insert_writer_guid (wr); + ddsi_plugin.builtintopic_write (&wr->e, now(), true); + ddsrt_mutex_unlock (&wr->e.lock); /* once it exists, match it with proxy writers and broadcast existence (I don't think it matters much what the order of these @@ -2842,7 +2845,6 @@ static dds_retcode_t new_writer_guid (struct writer **wr_out, const struct nn_gu deleted while we do so */ match_writer_with_proxy_readers (wr, tnow); match_writer_with_local_readers (wr, tnow); - ddsi_plugin.builtintopic_write (&wr->e, now(), true); sedp_write_writer (wr); if (wr->lease_duration != T_NEVER) @@ -2890,8 +2892,8 @@ struct local_orphan_writer *new_local_orphan_writer (nn_entityid_t entityid, str memset (&wr->c.group_guid, 0, sizeof (wr->c.group_guid)); new_writer_guid_common_init (wr, topic, xqos, whc, 0, NULL); ephash_insert_writer_guid (wr); - match_writer_with_local_readers (wr, tnow); ddsi_plugin.builtintopic_write (&wr->e, now(), true); + match_writer_with_local_readers (wr, tnow); return lowr; } @@ -3325,10 +3327,13 @@ static dds_retcode_t new_reader_guid ut_avlInit (&rd_writers_treedef, &rd->writers); ut_avlInit (&rd_local_writers_treedef, &rd->local_writers); + ddsrt_mutex_lock (&rd->e.lock); ephash_insert_reader_guid (rd); + ddsi_plugin.builtintopic_write (&rd->e, now(), true); + ddsrt_mutex_unlock (&rd->e.lock); + match_reader_with_proxy_writers (rd, tnow); match_reader_with_local_writers (rd, tnow); - ddsi_plugin.builtintopic_write (&rd->e, now(), true); sedp_write_reader (rd); return DDS_RETCODE_OK; } @@ -4170,9 +4175,14 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, pwr->ddsi2direct_cbarg = 0; local_reader_ary_init (&pwr->rdary); + + /* locking the entity prevents matching while the built-in topic hasn't been published yet */ + ddsrt_mutex_lock (&pwr->e.lock); ephash_insert_proxy_writer_guid (pwr); - match_proxy_writer_with_readers (pwr, tnow); ddsi_plugin.builtintopic_write (&pwr->e, timestamp, true); + ddsrt_mutex_unlock (&pwr->e.lock); + + match_proxy_writer_with_readers (pwr, tnow); ddsrt_mutex_lock (&pwr->e.lock); pwr->local_matching_inprogress = 0; @@ -4344,9 +4354,14 @@ int new_proxy_reader (const struct nn_guid *ppguid, const struct nn_guid *guid, prd->assert_pp_lease = (unsigned) !!config.arrival_of_data_asserts_pp_and_ep_liveliness; ut_avlInit (&prd_writers_treedef, &prd->writers); + + /* locking the entity prevents matching while the built-in topic hasn't been published yet */ + ddsrt_mutex_lock (&prd->e.lock); ephash_insert_proxy_reader_guid (prd); - match_proxy_reader_with_writers (prd, tnow); ddsi_plugin.builtintopic_write (&prd->e, timestamp, true); + ddsrt_mutex_unlock (&prd->e.lock); + + match_proxy_reader_with_writers (prd, tnow); return 0; } From f12b36e112043dd0b5379aece3b4ccd63919cd56 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Apr 2019 11:19:30 +0200 Subject: [PATCH 032/238] add setter for partition QoS for a single name This adds dds_qset_partition1 as a convenience function to set the partition QoS to a single name. Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/ddsc/dds_public_qos.h | 14 +++++++++++++- src/core/ddsc/src/dds_qos.c | 8 ++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/core/ddsc/include/dds/ddsc/dds_public_qos.h b/src/core/ddsc/include/dds/ddsc/dds_public_qos.h index 8f319c1..95fa4fe 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_qos.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_qos.h @@ -391,7 +391,7 @@ dds_qset_time_based_filter ( * * @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy * @param[in] n - Number of partitions stored in ps - * @param[in[ ps - Pointer to string(s) storing partition name(s) + * @param[in] ps - Pointer to string(s) storing partition name(s) */ DDS_EXPORT void dds_qset_partition ( @@ -399,6 +399,18 @@ dds_qset_partition ( uint32_t n, const char ** __restrict ps); +/** + * @brief Convenience function to set the partition policy of a qos structure to a + * single name. Name may be a null pointer. + * + * @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy + * @param[in] name - Pointer to the name + */ +DDS_EXPORT void +dds_qset_partition1 ( + dds_qos_t * __restrict qos, + const char * __restrict name); + /** * @brief Set the reliability policy of a qos structure * diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index 25a3ce6..02988bf 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -558,6 +558,14 @@ void dds_qset_partition qos->present |= QP_PARTITION; } +void dds_qset_partition1 (dds_qos_t * __restrict qos, const char * __restrict name) +{ + if (name == NULL) + dds_qset_partition (qos, 0, NULL); + else + dds_qset_partition (qos, 1, (const char **) &name); +} + void dds_qset_reliability ( dds_qos_t * __restrict qos, From 42500e7fb86ca1e11c45332e8cba8f95f3088c2c Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Apr 2019 11:21:52 +0200 Subject: [PATCH 033/238] add participant instance handle to builtin topics Extend the endpoint built-in topic data with the participant instance handle (the GUID was already present). Having the instance handle available makes it trivial to look up the participant, whereas a lookup of the GUID is rather impractical. Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/dds.h | 1 + src/core/ddsc/src/dds__serdata_builtintopic.h | 1 + src/core/ddsc/src/dds_serdata_builtintopic.c | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index 3d5dc42..d701117 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -210,6 +210,7 @@ typedef struct dds_builtintopic_endpoint { dds_builtintopic_guid_t key; dds_builtintopic_guid_t participant_key; + dds_instance_handle_t participant_instance_handle; char *topic_name; char *type_name; dds_qos_t *qos; diff --git a/src/core/ddsc/src/dds__serdata_builtintopic.h b/src/core/ddsc/src/dds__serdata_builtintopic.h index 46ccf88..6afe2d1 100644 --- a/src/core/ddsc/src/dds__serdata_builtintopic.h +++ b/src/core/ddsc/src/dds__serdata_builtintopic.h @@ -19,6 +19,7 @@ struct ddsi_serdata_builtintopic { struct ddsi_serdata c; nn_guid_t key; + dds_instance_handle_t pphandle; nn_xqos_t xqos; }; diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index b62d405..33da2ca 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -73,11 +73,13 @@ static struct ddsi_serdata_builtintopic *serdata_builtin_new(const struct ddsi_s static void from_entity_pp (struct ddsi_serdata_builtintopic *d, const struct participant *pp) { nn_xqos_copy(&d->xqos, &pp->plist->qos); + d->pphandle = pp->e.iid; } static void from_entity_proxypp (struct ddsi_serdata_builtintopic *d, const struct proxy_participant *proxypp) { nn_xqos_copy(&d->xqos, &proxypp->plist->qos); + d->pphandle = proxypp->e.iid; } static void set_topic_type_from_sertopic (struct ddsi_serdata_builtintopic *d, const struct ddsi_sertopic *tp) @@ -96,12 +98,14 @@ static void set_topic_type_from_sertopic (struct ddsi_serdata_builtintopic *d, c static void from_entity_rd (struct ddsi_serdata_builtintopic *d, const struct reader *rd) { + d->pphandle = rd->c.pp->e.iid; nn_xqos_copy(&d->xqos, rd->xqos); set_topic_type_from_sertopic(d, rd->topic); } static void from_entity_prd (struct ddsi_serdata_builtintopic *d, const struct proxy_reader *prd) { + d->pphandle = prd->c.proxypp->e.iid; nn_xqos_copy(&d->xqos, prd->c.xqos); assert (d->xqos.present & QP_TOPIC_NAME); assert (d->xqos.present & QP_TYPE_NAME); @@ -109,12 +113,14 @@ static void from_entity_prd (struct ddsi_serdata_builtintopic *d, const struct p static void from_entity_wr (struct ddsi_serdata_builtintopic *d, const struct writer *wr) { + d->pphandle = wr->c.pp->e.iid; nn_xqos_copy(&d->xqos, wr->xqos); set_topic_type_from_sertopic(d, wr->topic); } static void from_entity_pwr (struct ddsi_serdata_builtintopic *d, const struct proxy_writer *pwr) { + d->pphandle = pwr->c.proxypp->e.iid; nn_xqos_copy(&d->xqos, pwr->c.xqos); assert (d->xqos.present & QP_TOPIC_NAME); assert (d->xqos.present & QP_TYPE_NAME); @@ -219,6 +225,7 @@ static bool to_sample_endpoint (const struct ddsi_serdata_builtintopic *d, struc ppguid = d->key; ppguid.entityid.u = NN_ENTITYID_PARTICIPANT; convkey (&sample->participant_key, &ppguid); + sample->participant_instance_handle = d->pphandle; if (d->c.kind == SDK_DATA) { assert (d->xqos.present & QP_TOPIC_NAME); From 712ca3149f5521139ec22af834e6a1e1cc89afb8 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 16 Apr 2019 10:23:32 +0200 Subject: [PATCH 034/238] move util library into ddsrt As was the plan with the introduction of ddsrt; this includes renaming the identifiers to match the capitalization style and removes old junk. Signed-off-by: Erik Boasson --- docs/dev/modules.md | 4 - src/CMakeLists.txt | 1 - src/core/CMakeLists.txt | 7 +- src/core/ddsc/src/dds__domain.h | 2 +- src/core/ddsc/src/dds__handles.h | 4 +- src/core/ddsc/src/dds__types.h | 10 +- src/core/ddsc/src/dds_domain.c | 10 +- src/core/ddsc/src/dds_handles.c | 34 +- src/core/ddsc/src/dds_init.c | 2 +- src/core/ddsc/src/dds_reader.c | 4 +- src/core/ddsc/src/dds_rhc.c | 50 +- src/core/ddsc/src/dds_topic.c | 14 +- src/core/ddsc/src/dds_whc.c | 112 ++--- src/core/ddsc/src/dds_write.c | 4 +- .../include/dds/ddsi/ddsi_serdata_default.h | 2 +- .../ddsi/include/dds/ddsi/ddsi_sertopic.h | 4 +- src/core/ddsi/include/dds/ddsi/q_addrset.h | 6 +- src/core/ddsi/include/dds/ddsi/q_entity.h | 44 +- src/core/ddsi/include/dds/ddsi/q_ephash.h | 4 +- src/core/ddsi/include/dds/ddsi/q_globals.h | 8 +- .../include/dds/ddsi/q_inverse_uint32_set.h | 6 +- src/core/ddsi/src/ddsi_mcgroup.c | 36 +- src/core/ddsi/src/ddsi_tcp.c | 38 +- src/core/ddsi/src/ddsi_tkmap.c | 24 +- src/core/ddsi/src/q_addrset.c | 108 ++--- src/core/ddsi/src/q_config.c | 56 +-- src/core/ddsi/src/q_ddsi_discovery.c | 4 +- src/core/ddsi/src/q_debmon.c | 18 +- src/core/ddsi/src/q_entity.c | 220 ++++----- src/core/ddsi/src/q_ephash.c | 22 +- src/core/ddsi/src/q_init.c | 10 +- src/core/ddsi/src/q_inverse_uint32_set.c | 38 +- src/core/ddsi/src/q_lease.c | 26 +- src/core/ddsi/src/q_nwif.c | 2 +- src/core/ddsi/src/q_plist.c | 2 +- src/core/ddsi/src/q_radmin.c | 172 +++---- src/core/ddsi/src/q_receive.c | 56 +-- src/core/ddsi/src/q_transmit.c | 16 +- src/core/ddsi/src/q_xevent.c | 52 +- src/core/ddsi/src/q_xmsg.c | 6 +- src/core/xtests/CMakeLists.txt | 2 +- src/ddsrt/CMakeLists.txt | 15 + src/ddsrt/include/dds/ddsrt/avl.h | 359 ++++++++++++++ .../include/dds/ddsrt/expand_envvars.h} | 8 +- src/ddsrt/include/dds/ddsrt/fibheap.h | 54 +++ src/ddsrt/include/dds/ddsrt/hopscotch.h | 104 ++++ .../include/dds/ddsrt/thread_pool.h} | 26 +- src/ddsrt/include/dds/ddsrt/xmlparser.h | 52 ++ src/{util/src/ut_avl.c => ddsrt/src/avl.c} | 452 +++++++++--------- .../src/expand_envvars.c} | 14 +- .../src/ut_fibheap.c => ddsrt/src/fibheap.c} | 92 ++-- .../ut_hopscotch.c => ddsrt/src/hopscotch.c} | 310 ++++++------ .../src/thread_pool.c} | 28 +- .../ut_xmlparser.c => ddsrt/src/xmlparser.c} | 74 +-- src/util/CMakeLists.txt | 48 -- src/util/include/dds/util/ut_avl.h | 359 -------------- src/util/include/dds/util/ut_crc.h | 31 -- src/util/include/dds/util/ut_fibheap.h | 54 --- src/util/include/dds/util/ut_hopscotch.h | 110 ----- src/util/include/dds/util/ut_xmlparser.h | 52 -- src/util/src/ut_crc.c | 74 --- src/util/tests/CMakeLists.txt | 15 - 62 files changed, 1702 insertions(+), 1869 deletions(-) create mode 100644 src/ddsrt/include/dds/ddsrt/avl.h rename src/{util/include/dds/util/ut_expand_envvars.h => ddsrt/include/dds/ddsrt/expand_envvars.h} (78%) create mode 100644 src/ddsrt/include/dds/ddsrt/fibheap.h create mode 100644 src/ddsrt/include/dds/ddsrt/hopscotch.h rename src/{util/include/dds/util/ut_thread_pool.h => ddsrt/include/dds/ddsrt/thread_pool.h} (69%) create mode 100644 src/ddsrt/include/dds/ddsrt/xmlparser.h rename src/{util/src/ut_avl.c => ddsrt/src/avl.c} (52%) rename src/{util/src/ut_expand_envvars.c => ddsrt/src/expand_envvars.c} (93%) rename src/{util/src/ut_fibheap.c => ddsrt/src/fibheap.c} (68%) rename src/{util/src/ut_hopscotch.c => ddsrt/src/hopscotch.c} (67%) rename src/{util/src/ut_thread_pool.c => ddsrt/src/thread_pool.c} (88%) rename src/{util/src/ut_xmlparser.c => ddsrt/src/xmlparser.c} (89%) delete mode 100644 src/util/CMakeLists.txt delete mode 100644 src/util/include/dds/util/ut_avl.h delete mode 100644 src/util/include/dds/util/ut_crc.h delete mode 100644 src/util/include/dds/util/ut_fibheap.h delete mode 100644 src/util/include/dds/util/ut_hopscotch.h delete mode 100644 src/util/include/dds/util/ut_xmlparser.h delete mode 100644 src/util/src/ut_crc.c delete mode 100644 src/util/tests/CMakeLists.txt diff --git a/docs/dev/modules.md b/docs/dev/modules.md index 721c7a7..435516c 100644 --- a/docs/dev/modules.md +++ b/docs/dev/modules.md @@ -22,10 +22,6 @@ but does offer a neat way to separate features logically. | | ddsi | RTPS-DDSI specification. | | | | |---------| - | | | util is a collection of snippets that do not require - | | util | per-target implementations and may be used by the ddsc - | | | and ddsi targets. util will be merged into ddsrt. - | |---------| | | ddsrt offers target agnostic implementations of | ddsrt | functionality required by the ddsc and ddsi targets, but | | also exports a subset of the dds\_ api directly. e.g. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 52a062e..cc63136 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -173,7 +173,6 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib") add_subdirectory(idlc) add_subdirectory(ddsrt) add_subdirectory(etc) -add_subdirectory(util) add_subdirectory(core) add_subdirectory(tools) add_subdirectory(scripts) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 071d6e6..8f36723 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -50,16 +50,13 @@ endif() include(ddsi/CMakeLists.txt) include(ddsc/CMakeLists.txt) -target_link_libraries(ddsc PRIVATE util) target_link_libraries(ddsc PRIVATE ddsrt) target_compile_definitions( ddsc PUBLIC - $> - $>) + $>) target_include_directories( ddsc PUBLIC - $> - $>) + $>) # SOVERSION should increase on incompatible ABI change set_target_properties(ddsc PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) diff --git a/src/core/ddsc/src/dds__domain.h b/src/core/ddsc/src/dds__domain.h index d136184..0b13070 100644 --- a/src/core/ddsc/src/dds__domain.h +++ b/src/core/ddsc/src/dds__domain.h @@ -18,7 +18,7 @@ extern "C" { #endif -extern DDS_EXPORT const ut_avlTreedef_t dds_domaintree_def; +extern DDS_EXPORT const ddsrt_avl_treedef_t dds_domaintree_def; DDS_EXPORT dds_domain * dds_domain_create (dds_domainid_t id); DDS_EXPORT void dds_domain_free (dds_domain * domain); diff --git a/src/core/ddsc/src/dds__handles.h b/src/core/ddsc/src/dds__handles.h index 7ceee26..c13bc59 100644 --- a/src/core/ddsc/src/dds__handles.h +++ b/src/core/ddsc/src/dds__handles.h @@ -94,9 +94,9 @@ dds_handle_server_fini(void); * user data. * * A kind value != 0 has to be provided, just to make sure that no 0 handles - * will be created. It should also fit the UT_HANDLE_KIND_MASK. + * will be created. It should also fit the DDSRT_HANDLE_KIND_MASK. * In other words handle creation will fail if - * ((kind & ~UT_HANDLE_KIND_MASK != 0) || (kind & UT_HANDLE_KIND_MASK == 0)). + * ((kind & ~DDSRT_HANDLE_KIND_MASK != 0) || (kind & DDSRT_HANDLE_KIND_MASK == 0)). * * It has to do something clever to make sure that a deleted handle is not * re-issued very quickly after it was deleted. diff --git a/src/core/ddsc/src/dds__types.h b/src/core/ddsc/src/dds__types.h index 187aee4..61c7c57 100644 --- a/src/core/ddsc/src/dds__types.h +++ b/src/core/ddsc/src/dds__types.h @@ -17,7 +17,7 @@ #include "dds/dds.h" #include "dds/ddsrt/sync.h" #include "dds/ddsi/q_rtps.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds__handles.h" #if defined (__cplusplus) @@ -94,9 +94,9 @@ struct dds_listener { typedef struct dds_domain { - ut_avlNode_t m_node; + ddsrt_avl_node_t m_node; dds_domainid_t m_id; - ut_avlTree_t m_topics; + ddsrt_avl_tree_t m_topics; uint32_t m_refc; } dds_domain; @@ -151,7 +151,7 @@ typedef struct dds_entity } dds_entity; -extern const ut_avlTreedef_t dds_topictree_def; +extern const ddsrt_avl_treedef_t dds_topictree_def; typedef struct dds_subscriber { @@ -283,7 +283,7 @@ typedef struct dds_globals int (*m_dur_wait) (struct dds_reader * reader, dds_duration_t timeout); void (*m_dur_init) (void); void (*m_dur_fini) (void); - ut_avlTree_t m_domains; + ddsrt_avl_tree_t m_domains; ddsrt_mutex_t m_mutex; } dds_globals; diff --git a/src/core/ddsc/src/dds_domain.c b/src/core/ddsc/src/dds_domain.c index f2dfaa4..b8c12d8 100644 --- a/src/core/ddsc/src/dds_domain.c +++ b/src/core/ddsc/src/dds_domain.c @@ -17,7 +17,7 @@ static int dds_domain_compare (const int32_t * a, const int32_t * b) return (*a == *b) ? 0 : (*a < *b) ? -1 : 1; } -const ut_avlTreedef_t dds_domaintree_def = UT_AVL_TREEDEF_INITIALIZER +const ddsrt_avl_treedef_t dds_domaintree_def = DDSRT_AVL_TREEDEF_INITIALIZER ( offsetof (dds_domain, m_node), offsetof (dds_domain, m_id), @@ -27,7 +27,7 @@ const ut_avlTreedef_t dds_domaintree_def = UT_AVL_TREEDEF_INITIALIZER dds_domain * dds_domain_find_locked (dds_domainid_t id) { - return ut_avlLookup (&dds_domaintree_def, &dds_global.m_domains, &id); + return ddsrt_avl_lookup (&dds_domaintree_def, &dds_global.m_domains, &id); } dds_domain * dds_domain_create (dds_domainid_t id) @@ -39,8 +39,8 @@ dds_domain * dds_domain_create (dds_domainid_t id) { domain = dds_alloc (sizeof (*domain)); domain->m_id = id; - ut_avlInit (&dds_topictree_def, &domain->m_topics); - ut_avlInsert (&dds_domaintree_def, &dds_global.m_domains, domain); + ddsrt_avl_init (&dds_topictree_def, &domain->m_topics); + ddsrt_avl_insert (&dds_domaintree_def, &dds_global.m_domains, domain); } domain->m_refc++; ddsrt_mutex_unlock (&dds_global.m_mutex); @@ -52,7 +52,7 @@ void dds_domain_free (dds_domain * domain) ddsrt_mutex_lock (&dds_global.m_mutex); if (--domain->m_refc == 0) { - ut_avlDelete (&dds_domaintree_def, &dds_global.m_domains, domain); + ddsrt_avl_delete (&dds_domaintree_def, &dds_global.m_domains, domain); dds_free (domain); } ddsrt_mutex_unlock (&dds_global.m_mutex); diff --git a/src/core/ddsc/src/dds_handles.c b/src/core/ddsc/src/dds_handles.c index 560e661..dd509dd 100644 --- a/src/core/ddsc/src/dds_handles.c +++ b/src/core/ddsc/src/dds_handles.c @@ -15,7 +15,7 @@ #include "dds/ddsrt/sync.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/random.h" -#include "dds/util/ut_hopscotch.h" +#include "dds/ddsrt/hopscotch.h" #include "dds/ddsi/q_thread.h" #include "dds__handles.h" #include "dds__types.h" @@ -40,9 +40,9 @@ struct dds_handle_server { #if USE_CHH - struct ut_chh *ht; + struct ddsrt_chh *ht; #else - struct ut_hh *ht; + struct ddsrt_hh *ht; #endif size_t count; ddsrt_mutex_t lock; @@ -68,9 +68,9 @@ static int handle_equal (const void *va, const void *vb) dds_return_t dds_handle_server_init (void (*free_via_gc) (void *x)) { #if USE_CHH - handles.ht = ut_chhNew (128, handle_hash, handle_equal, free_via_gc); + handles.ht = ddsrt_chh_new (128, handle_hash, handle_equal, free_via_gc); #else - handles.ht = ut_hhNew (128, handle_hash, handle_equal); + handles.ht = ddsrt_hh_new (128, handle_hash, handle_equal); (void) free_via_gc; #endif handles.count = 0; @@ -83,16 +83,16 @@ void dds_handle_server_fini (void) { #if USE_CHH #ifndef NDEBUG - struct ut_chhIter it; - assert (ut_chhIterFirst (handles.ht, &it) == NULL); + struct ddsrt_chh_iter it; + assert (ddsrt_chh_iter_first (handles.ht, &it) == NULL); #endif - ut_chhFree (handles.ht); + ddsrt_chh_free (handles.ht); #else /* USE_CHH */ #ifndef NDEBUG - struct ut_hhIter it; - assert (ut_hhIterFirst (handles.ht, &it) == NULL); + struct ddsrt_hh_iter it; + assert (ddsrt_hh_iter_first (handles.ht, &it) == NULL); #endif - ut_hhFree (handles.ht); + ddsrt_hh_free (handles.ht); #endif /* USE_CHH */ ddsrt_cond_destroy (&handles.cond); ddsrt_mutex_destroy (&handles.lock); @@ -100,9 +100,9 @@ void dds_handle_server_fini (void) } #if USE_CHH -static bool hhadd (struct ut_chh *ht, void *elem) { return ut_chhAdd (ht, elem); } +static bool hhadd (struct ddsrt_chh *ht, void *elem) { return ddsrt_chh_add (ht, elem); } #else -static bool hhadd (struct ut_hh *ht, void *elem) { return ut_hhAdd (ht, elem); } +static bool hhadd (struct ddsrt_hh *ht, void *elem) { return ddsrt_hh_add (ht, elem); } #endif static dds_handle_t dds_handle_create_int (struct dds_handle_link *link) { @@ -176,10 +176,10 @@ int32_t dds_handle_delete (struct dds_handle_link *link, dds_duration_t timeout) } #if USE_CHH thread_state_awake (ts1); - int x = ut_chhRemove (handles.ht, link); + int x = ddsrt_chh_remove (handles.ht, link); thread_state_asleep (ts1); #else - int x = ut_hhRemove (handles.ht, link); + int x = ddsrt_hh_remove (handles.ht, link); #endif assert(x); (void)x; @@ -209,10 +209,10 @@ int32_t dds_handle_claim (dds_handle_t hdl, struct dds_handle_link **link) #if USE_CHH thread_state_awake (ts1); - *link = ut_chhLookup (handles.ht, &dummy); + *link = ddsrt_chh_lookup (handles.ht, &dummy); #else ddsrt_mutex_lock (&handles.lock); - *link = ut_hhLookup (handles.ht, &dummy); + *link = ddsrt_hh_lookup (handles.ht, &dummy); #endif if (*link == NULL) rc = DDS_RETCODE_BAD_PARAMETER; diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index e6558d5..d51bfb0 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -123,7 +123,7 @@ dds_init(dds_domainid_t domain) } upgrade_main_thread(); - ut_avlInit(&dds_domaintree_def, &dds_global.m_domains); + ddsrt_avl_init(&dds_domaintree_def, &dds_global.m_domains); /* Start monitoring the liveliness of all threads. */ if (!config.liveliness_monitoring) diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index b039495..10951e2 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -532,14 +532,14 @@ void dds_reader_ddsi2direct (dds_entity_t entity, ddsi2direct_directread_cb_t cb rd->ddsi2direct_cb = cb; rd->ddsi2direct_cbarg = cbarg; - while ((m = ut_avlLookupSuccEq (&rd_writers_treedef, &rd->writers, &pwrguid)) != NULL) + while ((m = ddsrt_avl_lookup_succ_eq (&rd_writers_treedef, &rd->writers, &pwrguid)) != NULL) { /* have to be careful walking the tree -- pretty is different, but I want to check this before I write a lookup_succ function. */ struct rd_pwr_match *m_next; nn_guid_t pwrguid_next; pwrguid = m->pwr_guid; - if ((m_next = ut_avlFindSucc (&rd_writers_treedef, &rd->writers, m)) != NULL) + if ((m_next = ddsrt_avl_find_succ (&rd_writers_treedef, &rd->writers, m)) != NULL) pwrguid_next = m_next->pwr_guid; else { diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index 4eb64dc..74133c0 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -27,8 +27,8 @@ #include "dds__reader.h" #include "dds__rhc.h" #include "dds/ddsi/ddsi_tkmap.h" -#include "dds/util/ut_hopscotch.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/hopscotch.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_xqos.h" #include "dds/ddsi/q_error.h" #include "dds/ddsi/q_unused.h" @@ -174,7 +174,7 @@ struct lwreg struct lwregs { - struct ut_ehh * regs; + struct ddsrt_ehh * regs; }; static uint32_t lwreg_hash (const void *vl) @@ -192,36 +192,36 @@ static int lwreg_equals (const void *va, const void *vb) static void lwregs_init (struct lwregs *rt) { - rt->regs = ut_ehhNew (sizeof (struct lwreg), 1, lwreg_hash, lwreg_equals); + rt->regs = ddsrt_ehh_new (sizeof (struct lwreg), 1, lwreg_hash, lwreg_equals); } static void lwregs_fini (struct lwregs *rt) { - ut_ehhFree (rt->regs); + ddsrt_ehh_free (rt->regs); } static int lwregs_contains (struct lwregs *rt, uint64_t iid, uint64_t wr_iid) { struct lwreg dummy = { .iid = iid, .wr_iid = wr_iid }; - return ut_ehhLookup (rt->regs, &dummy) != NULL; + return ddsrt_ehh_lookup (rt->regs, &dummy) != NULL; } static int lwregs_add (struct lwregs *rt, uint64_t iid, uint64_t wr_iid) { struct lwreg dummy = { .iid = iid, .wr_iid = wr_iid }; - return ut_ehhAdd (rt->regs, &dummy); + return ddsrt_ehh_add (rt->regs, &dummy); } static int lwregs_delete (struct lwregs *rt, uint64_t iid, uint64_t wr_iid) { struct lwreg dummy = { .iid = iid, .wr_iid = wr_iid }; - return ut_ehhRemove (rt->regs, &dummy); + return ddsrt_ehh_remove (rt->regs, &dummy); } void lwregs_dump (struct lwregs *rt) { - struct ut_ehhIter it; - for (struct lwreg *r = ut_ehhIterFirst(rt->regs, &it); r; r = ut_ehhIterNext(&it)) + struct ddsrt_ehh_iter it; + for (struct lwreg *r = ddsrt_ehh_iter_first(rt->regs, &it); r; r = ddsrt_ehh_iter_next(&it)) printf("iid=%"PRIu64" wr_iid=%"PRIu64"\n", r->iid, r->wr_iid); } @@ -271,7 +271,7 @@ typedef enum rhc_store_result { } rhc_store_result_t; struct rhc { - struct ut_hh *instances; + struct ddsrt_hh *instances; struct rhc_instance *nonempty_instances; /* circular, points to most recently added one, NULL if none */ struct lwregs registrations; /* should be a global one (with lock-free lookups) */ @@ -458,7 +458,7 @@ struct rhc * dds_rhc_new (dds_reader * reader, const struct ddsi_sertopic * topi lwregs_init (&rhc->registrations); ddsrt_mutex_init (&rhc->lock); - rhc->instances = ut_hhNew (1, instance_iid_hash, instance_iid_eq); + rhc->instances = ddsrt_hh_new (1, instance_iid_hash, instance_iid_eq); rhc->topic = topic; rhc->reader = reader; @@ -620,9 +620,9 @@ static void free_instance_rhc_free_wrap (void *vnode, void *varg) void dds_rhc_free (struct rhc *rhc) { assert (rhc_check_counts_locked (rhc, true, true)); - ut_hhEnum (rhc->instances, free_instance_rhc_free_wrap, rhc); + ddsrt_hh_enum (rhc->instances, free_instance_rhc_free_wrap, rhc); assert (rhc->nonempty_instances == NULL); - ut_hhFree (rhc->instances); + ddsrt_hh_free (rhc->instances); lwregs_fini (&rhc->registrations); if (rhc->qcond_eval_samplebuf != NULL) ddsi_sertopic_free_sample (rhc->topic, rhc->qcond_eval_samplebuf, DDS_FREE_ALL); @@ -848,7 +848,7 @@ static void drop_instance_noupdate_no_writers (struct rhc *rhc, struct rhc_insta rhc->n_instances--; - ret = ut_hhRemove (rhc->instances, inst); + ret = ddsrt_hh_remove (rhc->instances, inst); assert (ret); (void) ret; @@ -1198,7 +1198,7 @@ static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst } account_for_empty_to_nonempty_transition (rhc, inst); - ret = ut_hhAdd (rhc->instances, inst); + ret = ddsrt_hh_add (rhc->instances, inst); assert (ret); (void) ret; rhc->n_instances++; @@ -1248,7 +1248,7 @@ bool dds_rhc_store (struct rhc * __restrict rhc, const struct proxy_writer_info ddsrt_mutex_lock (&rhc->lock); - inst = ut_hhLookup (rhc->instances, &dummy_instance); + inst = ddsrt_hh_lookup (rhc->instances, &dummy_instance); if (inst == NULL) { /* New instance for this reader. If no data content -- not (also) @@ -1492,13 +1492,13 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ bool trigger_waitsets = false; bool notify_data_available = false; struct rhc_instance *inst; - struct ut_hhIter iter; + struct ddsrt_hh_iter iter; const uint64_t wr_iid = pwr_info->iid; const int auto_dispose = pwr_info->auto_dispose; ddsrt_mutex_lock (&rhc->lock); TRACE ("rhc_unregister_wr_iid(%"PRIx64",%d:\n", wr_iid, auto_dispose); - for (inst = ut_hhIterFirst (rhc->instances, &iter); inst; inst = ut_hhIterNext (&iter)) + for (inst = ddsrt_hh_iter_first (rhc->instances, &iter); inst; inst = ddsrt_hh_iter_next (&iter)) { if ((inst->wr_iid_islive && inst->wr_iid == wr_iid) || lwregs_contains (&rhc->registrations, inst->iid, wr_iid)) { @@ -1558,10 +1558,10 @@ void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writ void dds_rhc_relinquish_ownership (struct rhc * __restrict rhc, const uint64_t wr_iid) { struct rhc_instance *inst; - struct ut_hhIter iter; + struct ddsrt_hh_iter iter; ddsrt_mutex_lock (&rhc->lock); TRACE ("rhc_relinquish_ownership(%"PRIx64":\n", wr_iid); - for (inst = ut_hhIterFirst (rhc->instances, &iter); inst; inst = ut_hhIterNext (&iter)) + for (inst = ddsrt_hh_iter_first (rhc->instances, &iter); inst; inst = ddsrt_hh_iter_next (&iter)) { if (inst->wr_iid_islive && inst->wr_iid == wr_iid) { @@ -2234,7 +2234,7 @@ bool dds_rhc_add_readcondition (dds_readcond *cond) between those attached to a waitset or not. */ struct rhc *rhc = cond->m_rhc; - struct ut_hhIter it; + struct ddsrt_hh_iter it; assert ((dds_entity_kind (&cond->m_entity) == DDS_KIND_COND_READ && cond->m_query.m_filter == 0) || (dds_entity_kind (&cond->m_entity) == DDS_KIND_COND_QUERY && cond->m_query.m_filter != 0)); @@ -2296,7 +2296,7 @@ bool dds_rhc_add_readcondition (dds_readcond *cond) samples, except for those that match the predicate. */ const dds_querycond_mask_t qcmask = cond->m_query.m_qcmask; uint32_t trigger = 0; - for (struct rhc_instance *inst = ut_hhIterFirst (rhc->instances, &it); inst != NULL; inst = ut_hhIterNext (&it)) + for (struct rhc_instance *inst = ddsrt_hh_iter_first (rhc->instances, &it); inst != NULL; inst = ddsrt_hh_iter_next (&it)) { const bool instmatch = eval_predicate_invsample (rhc, inst, cond->m_query.m_filter);; uint32_t matches = 0; @@ -2612,7 +2612,7 @@ static int rhc_check_counts_locked (struct rhc *rhc, bool check_conds, bool chec unsigned cond_match_count[CHECK_MAX_CONDS]; dds_querycond_mask_t enabled_qcmask = 0; struct rhc_instance *inst; - struct ut_hhIter iter; + struct ddsrt_hh_iter iter; dds_readcond *rciter; uint32_t i; @@ -2628,7 +2628,7 @@ static int rhc_check_counts_locked (struct rhc *rhc, bool check_conds, bool chec enabled_qcmask |= rciter->m_query.m_qcmask; } - for (inst = ut_hhIterFirst (rhc->instances, &iter); inst; inst = ut_hhIterNext (&iter)) + for (inst = ddsrt_hh_iter_first (rhc->instances, &iter); inst; inst = ddsrt_hh_iter_next (&iter)) { unsigned n_vsamples_in_instance = 0, n_read_vsamples_in_instance = 0; bool a_sample_free = true; diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 1561afd..636c4ae 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -32,7 +32,7 @@ DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_topic) #define DDS_TOPIC_STATUS_MASK \ DDS_INCONSISTENT_TOPIC_STATUS -const ut_avlTreedef_t dds_topictree_def = UT_AVL_TREEDEF_INITIALIZER_INDKEY +const ddsrt_avl_treedef_t dds_topictree_def = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY ( offsetof (struct ddsi_sertopic, avlnode), offsetof (struct ddsi_sertopic, name_typename), @@ -118,17 +118,17 @@ dds_topic_lookup_locked( const char *name) { struct ddsi_sertopic *st = NULL; - ut_avlIter_t iter; + ddsrt_avl_iter_t iter; assert (domain); assert (name); - st = ut_avlIterFirst (&dds_topictree_def, &domain->m_topics, &iter); + st = ddsrt_avl_iter_first (&dds_topictree_def, &domain->m_topics, &iter); while (st) { if (strcmp (st->name, name) == 0) { break; } - st = ut_avlIterNext (&iter); + st = ddsrt_avl_iter_next (&iter); } return st; } @@ -155,9 +155,9 @@ dds_topic_free( assert (st); ddsrt_mutex_lock (&dds_global.m_mutex); - domain = ut_avlLookup (&dds_domaintree_def, &dds_global.m_domains, &domainid); + domain = ddsrt_avl_lookup (&dds_domaintree_def, &dds_global.m_domains, &domainid); if (domain != NULL) { - ut_avlDelete (&dds_topictree_def, &domain->m_topics, st); + ddsrt_avl_delete (&dds_topictree_def, &domain->m_topics, st); } ddsrt_mutex_unlock (&dds_global.m_mutex); st->status_cb_entity = NULL; @@ -172,7 +172,7 @@ dds_topic_add_locked( dds_domain * dom; dom = dds_domain_find_locked (id); assert (dom); - ut_avlInsert (&dds_topictree_def, &dom->m_topics, st); + ddsrt_avl_insert (&dds_topictree_def, &dom->m_topics, st); } DDS_EXPORT dds_entity_t diff --git a/src/core/ddsc/src/dds_whc.c b/src/core/ddsc/src/dds_whc.c index 1301ef9..5408c69 100644 --- a/src/core/ddsc/src/dds_whc.c +++ b/src/core/ddsc/src/dds_whc.c @@ -22,8 +22,8 @@ #include "dds__whc.h" #include "dds/ddsi/ddsi_tkmap.h" -#include "dds/util/ut_avl.h" -#include "dds/util/ut_hopscotch.h" +#include "dds/ddsrt/avl.h" +#include "dds/ddsrt/hopscotch.h" #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_freelist.h" @@ -47,7 +47,7 @@ struct whc_node { }; struct whc_intvnode { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; seqno_t min; seqno_t maxp1; struct whc_node *first; /* linked list of seqs with contiguous sequence numbers [min,maxp1) */ @@ -89,12 +89,12 @@ struct whc_impl { struct whc_node *maxseq_node; /* NULL if empty; if not in open_intv, open_intv is empty */ struct nn_freelist freelist; /* struct whc_node *; linked via whc_node::next_seq */ #if USE_EHH - struct ut_ehh *seq_hash; + struct ddsrt_ehh *seq_hash; #else - struct ut_hh *seq_hash; + struct ddsrt_hh *seq_hash; #endif - struct ut_hh *idx_hash; - ut_avlTree_t seq; + struct ddsrt_hh *idx_hash; + ddsrt_avl_tree_t seq; }; struct whc_sample_iter_impl { @@ -140,8 +140,8 @@ static void whc_default_sample_iter_init (const struct whc *whc, struct whc_samp static bool whc_default_sample_iter_borrow_next (struct whc_sample_iter *opaque_it, struct whc_borrowed_sample *sample); static void whc_default_free (struct whc *whc); -static const ut_avlTreedef_t whc_seq_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct whc_intvnode, avlnode), offsetof (struct whc_intvnode, min), compare_seq, 0); +static const ddsrt_avl_treedef_t whc_seq_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct whc_intvnode, avlnode), offsetof (struct whc_intvnode, min), compare_seq, 0); static const struct whc_ops whc_ops = { .insert = whc_default_insert, @@ -225,7 +225,7 @@ static struct whc_node *whc_findmax_procedurally (const struct whc_impl *whc) } else { - struct whc_intvnode *intv = ut_avlFindPred (&whc_seq_treedef, &whc->seq, whc->open_intv); + struct whc_intvnode *intv = ddsrt_avl_find_pred (&whc_seq_treedef, &whc->seq, whc->open_intv); assert (intv && intv->first); return intv->last; } @@ -239,8 +239,8 @@ static void check_whc (const struct whc_impl *whc) contiguous; all samples in seq & in seqhash; tlidx \subseteq seq; seq-number ordered list correct; &c. */ assert (whc->open_intv != NULL); - assert (whc->open_intv == ut_avlFindMax (&whc_seq_treedef, &whc->seq)); - assert (ut_avlFindSucc (&whc_seq_treedef, &whc->seq, whc->open_intv) == NULL); + assert (whc->open_intv == ddsrt_avl_find_max (&whc_seq_treedef, &whc->seq)); + assert (ddsrt_avl_find_succ (&whc_seq_treedef, &whc->seq, whc->open_intv) == NULL); if (whc->maxseq_node) { assert (whc->maxseq_node->next_seq == NULL); @@ -264,7 +264,7 @@ static void check_whc (const struct whc_impl *whc) struct whc_intvnode *firstintv; struct whc_node *cur; seqno_t prevseq = 0; - firstintv = ut_avlFindMin (&whc_seq_treedef, &whc->seq); + firstintv = ddsrt_avl_find_min (&whc_seq_treedef, &whc->seq); assert (firstintv); cur = firstintv->first; while (cur) @@ -283,10 +283,10 @@ static void insert_whcn_in_hash (struct whc_impl *whc, struct whc_node *whcn) /* precondition: whcn is not in hash */ #if USE_EHH struct whc_seq_entry e = { .seq = whcn->seq, .whcn = whcn }; - if (!ut_ehhAdd (whc->seq_hash, &e)) + if (!ddsrt_ehh_add (whc->seq_hash, &e)) assert(0); #else - if (!ut_hhAdd (whc->seq_hash, whcn)) + if (!ddsrt_hh_add (whc->seq_hash, whcn)) assert(0); #endif } @@ -296,10 +296,10 @@ static void remove_whcn_from_hash (struct whc_impl *whc, struct whc_node *whcn) /* precondition: whcn is in hash */ #if USE_EHH struct whc_seq_entry e = { .seq = whcn->seq }; - if (!ut_ehhRemove(whc->seq_hash, &e)) + if (!ddsrt_ehh_remove(whc->seq_hash, &e)) assert(0); #else - if (!ut_hhRemove(whc->seq_hash, whcn)) + if (!ddsrt_hh_remove(whc->seq_hash, whcn)) assert(0); #endif } @@ -308,14 +308,14 @@ static struct whc_node *whc_findseq (const struct whc_impl *whc, seqno_t seq) { #if USE_EHH struct whc_seq_entry e = { .seq = seq }, *r; - if ((r = ut_ehhLookup(whc->seq_hash, &e)) != NULL) + if ((r = ddsrt_ehh_lookup(whc->seq_hash, &e)) != NULL) return r->whcn; else return NULL; #else struct whc_node template; template.seq = seq; - return ut_hhLookup(whc->seq_hash, &template); + return ddsrt_hh_lookup(whc->seq_hash, &template); #endif } @@ -328,7 +328,7 @@ static struct whc_node *whc_findkey (const struct whc_impl *whc, const struct dd struct whc_idxnode *n; check_whc (whc); template.idxn.iid = ddsi_tkmap_lookup(gv.m_tkmap, serdata_key); - n = ut_hhLookup (whc->idx_hash, &template.idxn); + n = ddsrt_hh_lookup (whc->idx_hash, &template.idxn); if (n == NULL) return NULL; else @@ -359,22 +359,22 @@ struct whc *whc_new (int is_transient_local, unsigned hdepth, unsigned tldepth) whc->total_bytes = 0; whc->sample_overhead = sample_overhead; #if USE_EHH - whc->seq_hash = ut_ehhNew (sizeof (struct whc_seq_entry), 32, whc_seq_entry_hash, whc_seq_entry_eq); + whc->seq_hash = ddsrt_ehh_new (sizeof (struct whc_seq_entry), 32, whc_seq_entry_hash, whc_seq_entry_eq); #else - whc->seq_hash = ut_hhNew(32, whc_node_hash, whc_node_eq); + whc->seq_hash = ddsrt_hh_new(32, whc_node_hash, whc_node_eq); #endif if (whc->idxdepth > 0) - whc->idx_hash = ut_hhNew(32, whc_idxnode_hash_key, whc_idxnode_eq_key); + whc->idx_hash = ddsrt_hh_new(32, whc_idxnode_hash_key, whc_idxnode_eq_key); else whc->idx_hash = NULL; /* seq interval tree: always has an "open" node */ - ut_avlInit (&whc_seq_treedef, &whc->seq); + ddsrt_avl_init (&whc_seq_treedef, &whc->seq); intv = ddsrt_malloc (sizeof (*intv)); intv->min = intv->maxp1 = 1; intv->first = intv->last = NULL; - ut_avlInsert (&whc_seq_treedef, &whc->seq, intv); + ddsrt_avl_insert (&whc_seq_treedef, &whc->seq, intv); whc->open_intv = intv; whc->maxseq_node = NULL; @@ -402,11 +402,11 @@ void whc_default_free (struct whc *whc_generic) if (whc->idx_hash) { - struct ut_hhIter it; + struct ddsrt_hh_iter it; struct whc_idxnode *n; - for (n = ut_hhIterFirst(whc->idx_hash, &it); n != NULL; n = ut_hhIterNext(&it)) + for (n = ddsrt_hh_iter_first(whc->idx_hash, &it); n != NULL; n = ddsrt_hh_iter_next(&it)) ddsrt_free(n); - ut_hhFree(whc->idx_hash); + ddsrt_hh_free(whc->idx_hash); } { @@ -423,13 +423,13 @@ DDSRT_WARNING_MSVC_ON(6001); } } - ut_avlFree (&whc_seq_treedef, &whc->seq, ddsrt_free); + ddsrt_avl_free (&whc_seq_treedef, &whc->seq, ddsrt_free); nn_freelist_fini (&whc->freelist, ddsrt_free); #if USE_EHH - ut_ehhFree (whc->seq_hash); + ddsrt_ehh_free (whc->seq_hash); #else - ut_hhFree (whc->seq_hash); + ddsrt_hh_free (whc->seq_hash); #endif ddsrt_mutex_destroy (&whc->lock); ddsrt_free (whc); @@ -445,7 +445,7 @@ static void get_state_locked(const struct whc_impl *whc, struct whc_state *st) else { const struct whc_intvnode *intv; - intv = ut_avlFindMin (&whc_seq_treedef, &whc->seq); + intv = ddsrt_avl_find_min (&whc_seq_treedef, &whc->seq); /* not empty, open node may be anything but is (by definition) findmax, and whc is claimed to be non-empty, so min interval can't be empty */ @@ -476,12 +476,12 @@ static struct whc_node *find_nextseq_intv (struct whc_intvnode **p_intv, const s SEQ < Y can't exist */ #ifndef NDEBUG { - struct whc_intvnode *predintv = ut_avlLookupPredEq (&whc_seq_treedef, &whc->seq, &seq); + struct whc_intvnode *predintv = ddsrt_avl_lookup_pred_eq (&whc_seq_treedef, &whc->seq, &seq); assert (predintv == NULL || predintv->maxp1 <= seq); } #endif - if ((intv = ut_avlLookupSuccEq (&whc_seq_treedef, &whc->seq, &seq)) == NULL) { - assert (ut_avlLookupPredEq (&whc_seq_treedef, &whc->seq, &seq) == whc->open_intv); + if ((intv = ddsrt_avl_lookup_succ_eq (&whc_seq_treedef, &whc->seq, &seq)) == NULL) { + assert (ddsrt_avl_lookup_pred_eq (&whc_seq_treedef, &whc->seq, &seq) == whc->open_intv); return NULL; } else if (intv->min < intv->maxp1) { /* only if not empty interval */ assert (intv->min > seq); @@ -502,7 +502,7 @@ static struct whc_node *find_nextseq_intv (struct whc_intvnode **p_intv, const s assert (whc->maxseq_node != NULL); assert (n->seq < whc->maxseq_node->seq); n = n->next_seq; - *p_intv = ut_avlLookupPredEq (&whc_seq_treedef, &whc->seq, &n->seq); + *p_intv = ddsrt_avl_lookup_pred_eq (&whc_seq_treedef, &whc->seq, &n->seq); return n; } } @@ -538,7 +538,7 @@ static void delete_one_sample_from_idx (struct whc_impl *whc, struct whc_node *w for (i = 0; i < whc->idxdepth; i++) assert (i == idxn->headidx || idxn->hist[i] == NULL); #endif - if (!ut_hhRemove (whc->idx_hash, idxn)) + if (!ddsrt_hh_remove (whc->idx_hash, idxn)) assert (0); ddsi_tkmap_instance_unref(idxn->tk); ddsrt_free (idxn); @@ -568,7 +568,7 @@ static void free_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop_s static void delete_one_instance_from_idx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_idxnode *idxn) { - if (!ut_hhRemove (whc->idx_hash, idxn)) + if (!ddsrt_hh_remove (whc->idx_hash, idxn)) assert (0); free_one_instance_from_idx (whc, max_drop_seq, idxn); } @@ -612,11 +612,11 @@ static unsigned whc_default_downgrade_to_volatile (struct whc *whc_generic, stru whc->tldepth = 0; if (whc->hdepth == 0) { - struct ut_hhIter it; + struct ddsrt_hh_iter it; struct whc_idxnode *n; - for (n = ut_hhIterFirst(whc->idx_hash, &it); n != NULL; n = ut_hhIterNext(&it)) + for (n = ddsrt_hh_iter_first(whc->idx_hash, &it); n != NULL; n = ddsrt_hh_iter_next(&it)) free_one_instance_from_idx (whc, 0, n); - ut_hhFree(whc->idx_hash); + ddsrt_hh_free(whc->idx_hash); whc->idxdepth = 0; whc->idx_hash = NULL; } @@ -680,9 +680,9 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i if (whcn == intv->last && intv != whc->open_intv) { struct whc_intvnode *tmp = intv; - *p_intv = ut_avlFindSucc (&whc_seq_treedef, &whc->seq, intv); + *p_intv = ddsrt_avl_find_succ (&whc_seq_treedef, &whc->seq, intv); /* only sample in interval and not the open interval => delete interval */ - ut_avlDelete (&whc_seq_treedef, &whc->seq, tmp); + ddsrt_avl_delete (&whc_seq_treedef, &whc->seq, tmp); ddsrt_free (tmp); } else @@ -703,7 +703,7 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i assert (whcn->prev_seq->seq + 1 == whcn->seq); intv->last = whcn->prev_seq; intv->maxp1--; - *p_intv = ut_avlFindSucc (&whc_seq_treedef, &whc->seq, intv); + *p_intv = ddsrt_avl_find_succ (&whc_seq_treedef, &whc->seq, intv); } else { @@ -712,7 +712,7 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i issue only, and so we can (for now) get away with splitting it greedily */ struct whc_intvnode *new_intv; - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; new_intv = ddsrt_malloc (sizeof (*new_intv)); @@ -730,9 +730,9 @@ static void whc_delete_one_intv (struct whc_impl *whc, struct whc_intvnode **p_i /* insert new node & continue the loop with intv set to the new interval */ - if (ut_avlLookupIPath (&whc_seq_treedef, &whc->seq, &new_intv->min, &path) != NULL) + if (ddsrt_avl_lookup_ipath (&whc_seq_treedef, &whc->seq, &new_intv->min, &path) != NULL) assert (0); - ut_avlInsertIPath (&whc_seq_treedef, &whc->seq, new_intv, &path); + ddsrt_avl_insert_ipath (&whc_seq_treedef, &whc->seq, new_intv, &path); if (intv == whc->open_intv) whc->open_intv = new_intv; @@ -744,7 +744,7 @@ static void whc_delete_one (struct whc_impl *whc, struct whc_node *whcn) { struct whc_intvnode *intv; struct whc_node *whcn_tmp = whcn; - intv = ut_avlLookupPredEq (&whc_seq_treedef, &whc->seq, &whcn->seq); + intv = ddsrt_avl_lookup_pred_eq (&whc_seq_treedef, &whc->seq, &whcn->seq); assert (intv != NULL); whc_delete_one_intv (whc, &intv, &whcn); if (whcn_tmp->prev_seq) @@ -804,7 +804,7 @@ static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, s #ifndef NDEBUG whcn = find_nextseq_intv (&intv, whc, whc->max_drop_seq); assert (whcn == NULL || whcn->prev_seq == NULL); - assert (ut_avlIsSingleton (&whc->seq)); + assert (ddsrt_avl_is_singleton (&whc->seq)); #endif intv = whc->open_intv; @@ -894,7 +894,7 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se } if (whcn == intv->last) - intv = ut_avlFindSucc (&whc_seq_treedef, &whc->seq, intv); + intv = ddsrt_avl_find_succ (&whc_seq_treedef, &whc->seq, intv); if (prev_seq) prev_seq->next_seq = whcn; whcn->prev_seq = prev_seq; @@ -975,7 +975,7 @@ static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, se DDS_LOG(DDS_LC_WHC, " del %p %"PRId64, (void *) oldn, oldn->seq); whc_delete_one (whc, oldn); #ifndef NDEBUG - assert(ut_hhLookup(whc->idx_hash, &template) == idxn); + assert(ddsrt_hh_lookup(whc->idx_hash, &template) == idxn); ddsi_serdata_unref(whcn_template.serdata); #endif } @@ -1069,14 +1069,14 @@ static struct whc_node *whc_default_insert_seq (struct whc_impl *whc, seqno_t ma { /* gap => need new open_intv */ struct whc_intvnode *intv1; - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; intv1 = ddsrt_malloc (sizeof (*intv1)); intv1->min = seq; intv1->maxp1 = seq + 1; intv1->first = intv1->last = newn; - if (ut_avlLookupIPath (&whc_seq_treedef, &whc->seq, &seq, &path) != NULL) + if (ddsrt_avl_lookup_ipath (&whc_seq_treedef, &whc->seq, &seq, &path) != NULL) assert (0); - ut_avlInsertIPath (&whc_seq_treedef, &whc->seq, intv1, &path); + ddsrt_avl_insert_ipath (&whc_seq_treedef, &whc->seq, intv1, &path); whc->open_intv = intv1; } @@ -1128,7 +1128,7 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se } template.idxn.iid = tk->m_iid; - if ((idxn = ut_hhLookup (whc->idx_hash, &template)) != NULL) + if ((idxn = ddsrt_hh_lookup (whc->idx_hash, &template)) != NULL) { /* Unregisters cause deleting of index entry, non-unregister of adding/overwriting in history */ DDS_LOG(DDS_LC_WHC, " idxn %p", (void *)idxn); @@ -1203,7 +1203,7 @@ static int whc_default_insert (struct whc *whc_generic, seqno_t max_drop_seq, se idxn->hist[i] = NULL; newn->idxnode = idxn; newn->idxnode_pos = 0; - if (!ut_hhAdd (whc->idx_hash, idxn)) + if (!ddsrt_hh_add (whc->idx_hash, idxn)) assert (0); } else diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index 3c1526c..98a590b 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -123,14 +123,14 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay we fall back to using the GUIDs so that we can deliver all samples we received from it. As writer being deleted any reliable samples that are rejected are simply discarded. */ - ut_avlIter_t it; + ddsrt_avl_iter_t it; struct pwr_rd_match *m; struct proxy_writer_info pwr_info; dds_duration_t max_block_ms = nn_from_ddsi_duration (wr->xqos->reliability.max_blocking_time); ddsrt_mutex_unlock (&wr->rdary.rdary_lock); make_proxy_writer_info (&pwr_info, &wr->e, wr->xqos); ddsrt_mutex_lock (&wr->e.lock); - for (m = ut_avlIterFirst (&wr_local_readers_treedef, &wr->local_readers, &it); m != NULL; m = ut_avlIterNext (&it)) + for (m = ddsrt_avl_iter_first (&wr_local_readers_treedef, &wr->local_readers, &it); m != NULL; m = ddsrt_avl_iter_next (&it)) { struct reader *rd; if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL) diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h index 403a1c0..7775e1c 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h @@ -15,7 +15,7 @@ #include "dds/ddsrt/endian.h" #include "dds/ddsi/q_plist.h" /* for nn_prismtech_writer_info */ #include "dds/ddsi/q_freelist.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_sertopic.h" diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h index 2b48ad5..edd0b02 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h @@ -13,7 +13,7 @@ #define DDSI_SERTOPIC_H #include "dds/ddsrt/atomics.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsc/dds_public_alloc.h" struct ddsi_serdata; @@ -25,7 +25,7 @@ typedef void (*topic_cb_t) (struct dds_topic * topic); struct ddsi_sertopic_ops; struct ddsi_sertopic { - ut_avlNode_t avlnode; /* index on name_typename */ + ddsrt_avl_node_t avlnode; /* index on name_typename */ const struct ddsi_sertopic_ops *ops; const struct ddsi_serdata_ops *serdata_ops; uint32_t serdata_basehash; diff --git a/src/core/ddsi/include/dds/ddsi/q_addrset.h b/src/core/ddsi/include/dds/ddsi/q_addrset.h index 500337f..22476d5 100644 --- a/src/core/ddsi/include/dds/ddsi/q_addrset.h +++ b/src/core/ddsi/include/dds/ddsi/q_addrset.h @@ -13,7 +13,7 @@ #define NN_ADDRSET_H #include "dds/ddsrt/sync.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_feature_check.h" @@ -23,14 +23,14 @@ extern "C" { #endif typedef struct addrset_node { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_locator_t loc; } * addrset_node_t; struct addrset { ddsrt_mutex_t lock; ddsrt_atomic_uint32_t refc; - ut_avlCTree_t ucaddrs, mcaddrs; + ddsrt_avl_ctree_t ucaddrs, mcaddrs; }; typedef void (*addrset_forall_fun_t) (const nn_locator_t *loc, void *arg); diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 9138e02..f6f1f8e 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -13,7 +13,7 @@ #define Q_ENTITY_H #include "dds/ddsrt/atomics.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_lat_estim.h" @@ -54,12 +54,12 @@ status_cb_data_t; typedef void (*status_cb_t) (void *entity, const status_cb_data_t *data); struct prd_wr_match { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_guid_t wr_guid; }; struct rd_pwr_match { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_guid_t pwr_guid; #ifdef DDSI_INCLUDE_SSM nn_locator_t ssm_mc_loc; @@ -68,17 +68,17 @@ struct rd_pwr_match { }; struct wr_rd_match { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_guid_t rd_guid; }; struct rd_wr_match { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_guid_t wr_guid; }; struct wr_prd_match { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_guid_t prd_guid; /* guid of the proxy reader */ unsigned assumed_in_sync: 1; /* set to 1 upon receipt of ack not nack'ing msgs */ unsigned has_replied_to_hb: 1; /* we must keep sending HBs until all readers have this set */ @@ -105,7 +105,7 @@ enum pwr_rd_match_syncstate { }; struct pwr_rd_match { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_guid_t rd_guid; nn_mtime_t tcreate; nn_count_t count; /* most recent acknack sequence number */ @@ -247,8 +247,8 @@ struct writer nn_etime_t t_rexmit_end; /* time of last 1->0 transition of "retransmitting" */ nn_etime_t t_whc_high_upd; /* time "whc_high" was last updated for controlled ramp-up of throughput */ int num_reliable_readers; /* number of matching reliable PROXY readers */ - ut_avlTree_t readers; /* all matching PROXY readers, see struct wr_prd_match */ - ut_avlTree_t local_readers; /* all matching LOCAL readers, see struct wr_rd_match */ + ddsrt_avl_tree_t readers; /* all matching PROXY readers, see struct wr_prd_match */ + ddsrt_avl_tree_t local_readers; /* all matching LOCAL readers, see struct wr_rd_match */ #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS uint32_t partition_id; #endif @@ -280,8 +280,8 @@ struct reader struct addrset *as; #endif const struct ddsi_sertopic * topic; /* topic is NULL for built-in readers */ - ut_avlTree_t writers; /* all matching PROXY writers, see struct rd_pwr_match */ - ut_avlTree_t local_writers; /* all matching LOCAL writers, see struct rd_wr_match */ + ddsrt_avl_tree_t writers; /* all matching PROXY writers, see struct rd_pwr_match */ + ddsrt_avl_tree_t local_writers; /* all matching LOCAL writers, see struct rd_wr_match */ ddsi2direct_directread_cb_t ddsi2direct_cb; void *ddsi2direct_cbarg; }; @@ -299,7 +299,7 @@ struct proxy_participant struct addrset *as_default; /* default address set to use for user data traffic */ struct addrset *as_meta; /* default address set to use for discovery traffic */ struct proxy_endpoint_common *endpoints; /* all proxy endpoints can be reached from here */ - ut_avlTree_t groups; /* table of all groups (publisher, subscriber), see struct proxy_group */ + ddsrt_avl_tree_t groups; /* table of all groups (publisher, subscriber), see struct proxy_group */ unsigned kernel_sequence_numbers : 1; /* whether this proxy participant generates OSPL kernel sequence numbers */ unsigned implicitly_created : 1; /* participants are implicitly created for Cloud/Fog discovered endpoints */ unsigned is_ddsi2_pp: 1; /* if this is the federation-leader on the remote node */ @@ -318,7 +318,7 @@ struct proxy_participant tables, but "groups" only live in the context of a proxy participant. */ struct proxy_group { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_guid_t guid; char *name; struct proxy_participant *proxypp; /* uncounted backref to proxy participant */ @@ -340,7 +340,7 @@ struct proxy_endpoint_common struct proxy_writer { struct entity_common e; struct proxy_endpoint_common c; - ut_avlTree_t readers; /* matching LOCAL readers, see pwr_rd_match */ + ddsrt_avl_tree_t readers; /* matching LOCAL readers, see pwr_rd_match */ int n_reliable_readers; /* number of those that are reliable */ int n_readers_out_of_sync; /* number of those that require special handling (accepting historical data, waiting for historical data set to become complete) */ seqno_t last_seq; /* highest known seq published by the writer, not last delivered */ @@ -373,16 +373,16 @@ struct proxy_reader { #ifdef DDSI_INCLUDE_SSM unsigned favours_ssm: 1; /* iff 1, this proxy reader favours SSM when available */ #endif - ut_avlTree_t writers; /* matching LOCAL writers */ + ddsrt_avl_tree_t writers; /* matching LOCAL writers */ }; -extern const ut_avlTreedef_t wr_readers_treedef; -extern const ut_avlTreedef_t wr_local_readers_treedef; -extern const ut_avlTreedef_t rd_writers_treedef; -extern const ut_avlTreedef_t rd_local_writers_treedef; -extern const ut_avlTreedef_t pwr_readers_treedef; -extern const ut_avlTreedef_t prd_writers_treedef; -extern const ut_avlTreedef_t deleted_participants_treedef; +extern const ddsrt_avl_treedef_t wr_readers_treedef; +extern const ddsrt_avl_treedef_t wr_local_readers_treedef; +extern const ddsrt_avl_treedef_t rd_writers_treedef; +extern const ddsrt_avl_treedef_t rd_local_writers_treedef; +extern const ddsrt_avl_treedef_t pwr_readers_treedef; +extern const ddsrt_avl_treedef_t prd_writers_treedef; +extern const ddsrt_avl_treedef_t deleted_participants_treedef; #define DPG_LOCAL 1 #define DPG_REMOTE 2 diff --git a/src/core/ddsi/include/dds/ddsi/q_ephash.h b/src/core/ddsi/include/dds/ddsi/q_ephash.h index e6e0d4a..cf218c3 100644 --- a/src/core/ddsi/include/dds/ddsi/q_ephash.h +++ b/src/core/ddsi/include/dds/ddsi/q_ephash.h @@ -12,7 +12,7 @@ #ifndef Q_EPHASH_H #define Q_EPHASH_H -#include "dds/util/ut_hopscotch.h" +#include "dds/ddsrt/hopscotch.h" #if defined (__cplusplus) extern "C" { @@ -39,7 +39,7 @@ struct nn_guid; struct ephash_enum { - struct ut_chhIter it; + struct ddsrt_chh_iter it; enum entity_kind kind; struct entity_common *cur; }; diff --git a/src/core/ddsi/include/dds/ddsi/q_globals.h b/src/core/ddsi/include/dds/ddsi/q_globals.h index 770c569..517b699 100644 --- a/src/core/ddsi/include/dds/ddsi/q_globals.h +++ b/src/core/ddsi/include/dds/ddsi/q_globals.h @@ -18,7 +18,7 @@ #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/sockets.h" #include "dds/ddsrt/sync.h" -#include "dds/util/ut_fibheap.h" +#include "dds/ddsrt/fibheap.h" #include "dds/ddsi/q_plist.h" #include "dds/ddsi/q_protocol.h" @@ -47,7 +47,7 @@ struct lease; struct ddsi_tran_conn; struct ddsi_tran_listener; struct ddsi_tran_factory; -struct ut_thread_pool_s; +struct ddsrt_thread_pool_s; struct debug_monitor; struct ddsi_tkmap; @@ -110,7 +110,7 @@ struct q_globals { /* Lease junk */ ddsrt_mutex_t leaseheap_lock; ddsrt_mutex_t lease_locks[N_LEASE_LOCKS]; - ut_fibheap_t leaseheap; + ddsrt_fibheap_t leaseheap; /* Transport factory */ @@ -133,7 +133,7 @@ struct q_globals { /* Thread pool */ - struct ut_thread_pool_s * thread_pool; + struct ddsrt_thread_pool_s * thread_pool; /* In many sockets mode, the receive threads maintain a local array with participant GUIDs and sockets, participant_set_generation is diff --git a/src/core/ddsi/include/dds/ddsi/q_inverse_uint32_set.h b/src/core/ddsi/include/dds/ddsi/q_inverse_uint32_set.h index 927d94c..d48cf96 100644 --- a/src/core/ddsi/include/dds/ddsi/q_inverse_uint32_set.h +++ b/src/core/ddsi/include/dds/ddsi/q_inverse_uint32_set.h @@ -12,14 +12,14 @@ #ifndef NN_INVERSE_UINT32_SET_H #define NN_INVERSE_UINT32_SET_H -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" struct inverse_uint32_set_node { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; uint32_t min, max; }; struct inverse_uint32_set { - ut_avlTree_t ids; + ddsrt_avl_tree_t ids; uint32_t cursor; uint32_t min, max; }; diff --git a/src/core/ddsi/src/ddsi_mcgroup.c b/src/core/ddsi/src/ddsi_mcgroup.c index 744ace4..51ca755 100644 --- a/src/core/ddsi/src/ddsi_mcgroup.c +++ b/src/core/ddsi/src/ddsi_mcgroup.c @@ -20,10 +20,10 @@ #include "dds/ddsi/ddsi_mcgroup.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" struct nn_group_membership_node { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; ddsi_tran_conn_t conn; nn_locator_t srcloc; nn_locator_t mcloc; @@ -32,7 +32,7 @@ struct nn_group_membership_node { struct nn_group_membership { ddsrt_mutex_t lock; - ut_avlTree_t mships; + ddsrt_avl_tree_t mships; }; static int locator_compare_no_port (const nn_locator_t *as, const nn_locator_t *bs) @@ -60,19 +60,19 @@ static int cmp_group_membership (const void *va, const void *vb) return 0; } -static ut_avlTreedef_t mship_td = UT_AVL_TREEDEF_INITIALIZER(offsetof (struct nn_group_membership_node, avlnode), 0, cmp_group_membership, 0); +static ddsrt_avl_treedef_t mship_td = DDSRT_AVL_TREEDEF_INITIALIZER(offsetof (struct nn_group_membership_node, avlnode), 0, cmp_group_membership, 0); struct nn_group_membership *new_group_membership (void) { struct nn_group_membership *mship = ddsrt_malloc (sizeof (*mship)); ddsrt_mutex_init (&mship->lock); - ut_avlInit (&mship_td, &mship->mships); + ddsrt_avl_init (&mship_td, &mship->mships); return mship; } void free_group_membership (struct nn_group_membership *mship) { - ut_avlFree (&mship_td, &mship->mships, ddsrt_free); + ddsrt_avl_free (&mship_td, &mship->mships, ddsrt_free); ddsrt_mutex_destroy (&mship->lock); ddsrt_free (mship); } @@ -80,7 +80,7 @@ void free_group_membership (struct nn_group_membership *mship) static int reg_group_membership (struct nn_group_membership *mship, ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc) { struct nn_group_membership_node key, *n; - ut_avlIPath_t ip; + ddsrt_avl_ipath_t ip; int isnew; key.conn = conn; if (srcloc) @@ -88,7 +88,7 @@ static int reg_group_membership (struct nn_group_membership *mship, ddsi_tran_co else memset (&key.srcloc, 0, sizeof (key.srcloc)); key.mcloc = *mcloc; - if ((n = ut_avlLookupIPath (&mship_td, &mship->mships, &key, &ip)) != NULL) { + if ((n = ddsrt_avl_lookup_ipath (&mship_td, &mship->mships, &key, &ip)) != NULL) { isnew = 0; n->count++; } else { @@ -98,7 +98,7 @@ static int reg_group_membership (struct nn_group_membership *mship, ddsi_tran_co n->srcloc = key.srcloc; n->mcloc = key.mcloc; n->count = 1; - ut_avlInsertIPath (&mship_td, &mship->mships, n, &ip); + ddsrt_avl_insert_ipath (&mship_td, &mship->mships, n, &ip); } return isnew; } @@ -106,7 +106,7 @@ static int reg_group_membership (struct nn_group_membership *mship, ddsi_tran_co static int unreg_group_membership (struct nn_group_membership *mship, ddsi_tran_conn_t conn, const nn_locator_t *srcloc, const nn_locator_t *mcloc) { struct nn_group_membership_node key, *n; - ut_avlDPath_t dp; + ddsrt_avl_dpath_t dp; int mustdel; key.conn = conn; if (srcloc) @@ -114,7 +114,7 @@ static int unreg_group_membership (struct nn_group_membership *mship, ddsi_tran_ else memset (&key.srcloc, 0, sizeof (key.srcloc)); key.mcloc = *mcloc; - n = ut_avlLookupDPath (&mship_td, &mship->mships, &key, &dp); + n = ddsrt_avl_lookup_dpath (&mship_td, &mship->mships, &key, &dp); assert (n != NULL); assert (n->count > 0); if (--n->count > 0) @@ -122,7 +122,7 @@ static int unreg_group_membership (struct nn_group_membership *mship, ddsi_tran_ else { mustdel = 1; - ut_avlDeleteDPath (&mship_td, &mship->mships, n, &dp); + ddsrt_avl_delete_dpath (&mship_td, &mship->mships, n, &dp); ddsrt_free (n); } return mustdel; @@ -268,13 +268,13 @@ void ddsi_transfer_group_membership (ddsi_tran_conn_t conn, ddsi_tran_conn_t new are neither 0 nor maximum representable, min and max define the range of key values that relate to oldsock */ ddsrt_mutex_lock (&gv.mship->lock); - n = ut_avlLookupSuccEq (&mship_td, &gv.mship->mships, &min); + n = ddsrt_avl_lookup_succ_eq (&mship_td, &gv.mship->mships, &min); while (n != NULL && cmp_group_membership (n, &max) <= 0) { - struct nn_group_membership_node * const nn = ut_avlFindSucc (&mship_td, &gv.mship->mships, n); - ut_avlDelete (&mship_td, &gv.mship->mships, n); + struct nn_group_membership_node * const nn = ddsrt_avl_find_succ (&mship_td, &gv.mship->mships, n); + ddsrt_avl_delete (&mship_td, &gv.mship->mships, n); n->conn = newconn; - ut_avlInsert (&mship_td, &gv.mship->mships, n); + ddsrt_avl_insert (&mship_td, &gv.mship->mships, n); n = nn; } ddsrt_mutex_unlock (&gv.mship->lock); @@ -283,13 +283,13 @@ void ddsi_transfer_group_membership (ddsi_tran_conn_t conn, ddsi_tran_conn_t new int ddsi_rejoin_transferred_mcgroups (ddsi_tran_conn_t conn) { struct nn_group_membership_node *n, min, max; - ut_avlIter_t it; + ddsrt_avl_iter_t it; int ret = 0; memset(&min, 0, sizeof(min)); memset(&max, 0xff, sizeof(max)); min.conn = max.conn = conn; ddsrt_mutex_lock (&gv.mship->lock); - for (n = ut_avlIterSuccEq (&mship_td, &gv.mship->mships, &it, &min); n != NULL && ret >= 0 && cmp_group_membership(n, &max) <= 0; n = ut_avlIterNext (&it)) + for (n = ddsrt_avl_iter_succ_eq (&mship_td, &gv.mship->mships, &it, &min); n != NULL && ret >= 0 && cmp_group_membership(n, &max) <= 0; n = ddsrt_avl_iter_next (&it)) { int have_srcloc = (memcmp(&n->srcloc, &min.srcloc, sizeof(n->srcloc)) != 0); assert (n->conn == conn); diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index 2bb6576..0adbd73 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -20,7 +20,7 @@ #include "dds/ddsi/ddsi_tran.h" #include "dds/ddsi/ddsi_tcp.h" #include "dds/ddsi/ddsi_ipaddr.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_nwif.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" @@ -93,12 +93,12 @@ static int ddsi_tcp_cmp_conn_wrap (const void *a, const void *b) typedef struct ddsi_tcp_node { - ut_avlNode_t m_avlnode; + ddsrt_avl_node_t m_avlnode; ddsi_tcp_conn_t m_conn; } * ddsi_tcp_node_t; -static const ut_avlTreedef_t ddsi_tcp_treedef = UT_AVL_TREEDEF_INITIALIZER_INDKEY +static const ddsrt_avl_treedef_t ddsi_tcp_treedef = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY ( offsetof (struct ddsi_tcp_node, m_avlnode), offsetof (struct ddsi_tcp_node, m_conn), @@ -107,7 +107,7 @@ static const ut_avlTreedef_t ddsi_tcp_treedef = UT_AVL_TREEDEF_INITIALIZER_INDKE ); static ddsrt_mutex_t ddsi_tcp_cache_lock_g; -static ut_avlTree_t ddsi_tcp_cache_g; +static ddsrt_avl_tree_t ddsi_tcp_cache_g; static struct ddsi_tran_factory ddsi_tcp_factory_g; static ddsi_tcp_conn_t ddsi_tcp_new_conn (ddsrt_socket_t, bool, struct sockaddr *); @@ -125,11 +125,11 @@ static char *sockaddr_to_string_with_port (char *dst, size_t sizeof_dst, const s static void ddsi_tcp_cache_dump (void) { char buff[64]; - ut_avlIter_t iter; + ddsrt_avl_iter_t iter; ddsi_tcp_node_t n; unsigned i = 0; - n = ut_avlIterFirst (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, &iter); + n = ddsrt_avl_iter_first (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, &iter); while (n) { os_sockaddrAddressPortToString ((const os_sockaddr *) &n->m_conn->m_peer_addr, buff, sizeof (buff)); @@ -140,7 +140,7 @@ static void ddsi_tcp_cache_dump (void) ddsi_name, i++, n->m_conn->m_base.m_server ? "server" : "client", n->m_conn->m_sock, n->m_conn->m_base.m_base.m_port, buff ); - n = ut_avlIterNext (&iter); + n = ddsrt_avl_iter_next (&iter); } } */ @@ -242,7 +242,7 @@ static void ddsi_tcp_conn_connect (ddsi_tcp_conn_t conn, const ddsrt_msghdr_t * } } -static void ddsi_tcp_cache_add (ddsi_tcp_conn_t conn, ut_avlIPath_t * path) +static void ddsi_tcp_cache_add (ddsi_tcp_conn_t conn, ddsrt_avl_ipath_t * path) { const char * action = "added"; ddsi_tcp_node_t node; @@ -255,11 +255,11 @@ static void ddsi_tcp_cache_add (ddsi_tcp_conn_t conn, ut_avlIPath_t * path) { node = ddsrt_malloc (sizeof (*node)); node->m_conn = conn; - ut_avlInsertIPath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node, path); + ddsrt_avl_insert_ipath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node, path); } else { - node = ut_avlLookup (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, conn); + node = ddsrt_avl_lookup (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, conn); if (node) { /* Replace connection in cache */ @@ -272,7 +272,7 @@ static void ddsi_tcp_cache_add (ddsi_tcp_conn_t conn, ut_avlIPath_t * path) { node = ddsrt_malloc (sizeof (*node)); node->m_conn = conn; - ut_avlInsert (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node); + ddsrt_avl_insert (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node); } } @@ -284,15 +284,15 @@ static void ddsi_tcp_cache_remove (ddsi_tcp_conn_t conn) { char buff[DDSI_LOCSTRLEN]; ddsi_tcp_node_t node; - ut_avlDPath_t path; + ddsrt_avl_dpath_t path; ddsrt_mutex_lock (&ddsi_tcp_cache_lock_g); - node = ut_avlLookupDPath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, conn, &path); + node = ddsrt_avl_lookup_dpath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, conn, &path); if (node) { sockaddr_to_string_with_port(buff, sizeof(buff), (struct sockaddr *)&conn->m_peer_addr); DDS_LOG(DDS_LC_TCP, "%s cache removed socket %"PRIdSOCK" to %s\n", ddsi_name, conn->m_sock, buff); - ut_avlDeleteDPath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node, &path); + ddsrt_avl_delete_dpath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node, &path); ddsi_tcp_node_free (node); } ddsrt_mutex_unlock (&ddsi_tcp_cache_lock_g); @@ -305,7 +305,7 @@ static void ddsi_tcp_cache_remove (ddsi_tcp_conn_t conn) static ddsi_tcp_conn_t ddsi_tcp_cache_find (const ddsrt_msghdr_t * msg) { - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; ddsi_tcp_node_t node; struct ddsi_tcp_conn key; ddsi_tcp_conn_t ret = NULL; @@ -317,12 +317,12 @@ static ddsi_tcp_conn_t ddsi_tcp_cache_find (const ddsrt_msghdr_t * msg) /* Check cache for existing connection to target */ ddsrt_mutex_lock (&ddsi_tcp_cache_lock_g); - node = ut_avlLookupIPath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, &key, &path); + node = ddsrt_avl_lookup_ipath (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, &key, &path); if (node) { if (node->m_conn->m_base.m_closed) { - ut_avlDelete (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node); + ddsrt_avl_delete (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, node); ddsi_tcp_node_free (node); } else @@ -1010,7 +1010,7 @@ static void ddsi_tcp_release_listener (ddsi_tran_listener_t listener) static void ddsi_tcp_release_factory (void) { if (ddsrt_atomic_dec32_nv (&ddsi_tcp_init_g) == 0) { - ut_avlFree (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, ddsi_tcp_node_free); + ddsrt_avl_free (&ddsi_tcp_treedef, &ddsi_tcp_cache_g, ddsi_tcp_node_free); ddsrt_mutex_destroy (&ddsi_tcp_cache_lock_g); #ifdef DDSI_INCLUDE_SSL if (ddsi_tcp_ssl_plugin.fini) @@ -1095,7 +1095,7 @@ int ddsi_tcp_init (void) } #endif - ut_avlInit (&ddsi_tcp_treedef, &ddsi_tcp_cache_g); + ddsrt_avl_init (&ddsi_tcp_treedef, &ddsi_tcp_cache_g); ddsrt_mutex_init (&ddsi_tcp_cache_lock_g); DDS_LOG(DDS_LC_CONFIG, "%s initialized\n", ddsi_name); diff --git a/src/core/ddsi/src/ddsi_tkmap.c b/src/core/ddsi/src/ddsi_tkmap.c index b688e09..132fd5d 100644 --- a/src/core/ddsi/src/ddsi_tkmap.c +++ b/src/core/ddsi/src/ddsi_tkmap.c @@ -22,7 +22,7 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/ddsi_iid.h" #include "dds/ddsi/ddsi_tkmap.h" -#include "dds/util/ut_hopscotch.h" +#include "dds/ddsrt/hopscotch.h" #include "dds__stream.h" #include "dds/ddsi/ddsi_serdata.h" @@ -31,7 +31,7 @@ struct ddsi_tkmap { - struct ut_chh * m_hh; + struct ddsrt_chh * m_hh; ddsrt_mutex_t m_lock; ddsrt_cond_t m_cond; }; @@ -87,7 +87,7 @@ static int dds_tk_equals_void (const void *a, const void *b) struct ddsi_tkmap *ddsi_tkmap_new (void) { struct ddsi_tkmap *tkmap = dds_alloc (sizeof (*tkmap)); - tkmap->m_hh = ut_chhNew (1, dds_tk_hash_void, dds_tk_equals_void, gc_buckets); + tkmap->m_hh = ddsrt_chh_new (1, dds_tk_hash_void, dds_tk_equals_void, gc_buckets); ddsrt_mutex_init (&tkmap->m_lock); ddsrt_cond_init (&tkmap->m_cond); return tkmap; @@ -102,8 +102,8 @@ static void free_tkmap_instance (void *vtk, UNUSED_ARG(void *f_arg)) void ddsi_tkmap_free (struct ddsi_tkmap * map) { - ut_chhEnumUnsafe (map->m_hh, free_tkmap_instance, NULL); - ut_chhFree (map->m_hh); + ddsrt_chh_enum_unsafe (map->m_hh, free_tkmap_instance, NULL); + ddsrt_chh_free (map->m_hh); ddsrt_cond_destroy (&map->m_cond); ddsrt_mutex_destroy (&map->m_lock); dds_free (map); @@ -115,18 +115,18 @@ uint64_t ddsi_tkmap_lookup (struct ddsi_tkmap * map, const struct ddsi_serdata * struct ddsi_tkmap_instance * tk; assert (thread_is_awake ()); dummy.m_sample = (struct ddsi_serdata *) sd; - tk = ut_chhLookup (map->m_hh, &dummy); + tk = ddsrt_chh_lookup (map->m_hh, &dummy); return (tk) ? tk->m_iid : DDS_HANDLE_NIL; } struct ddsi_tkmap_instance *ddsi_tkmap_find_by_id (struct ddsi_tkmap *map, uint64_t iid) { /* This is not a function that should be used liberally, as it linearly scans the key-to-iid map. */ - struct ut_chhIter it; + struct ddsrt_chh_iter it; struct ddsi_tkmap_instance *tk; uint32_t refc; assert (thread_is_awake ()); - for (tk = ut_chhIterFirst (map->m_hh, &it); tk; tk = ut_chhIterNext (&it)) + for (tk = ddsrt_chh_iter_first (map->m_hh, &it); tk; tk = ddsrt_chh_iter_next (&it)) if (tk->m_iid == iid) break; if (tk == NULL) @@ -165,7 +165,7 @@ ddsi_tkmap_find( assert (thread_is_awake ()); dummy.m_sample = sd; retry: - if ((tk = ut_chhLookup(map->m_hh, &dummy)) != NULL) + if ((tk = ddsrt_chh_lookup(map->m_hh, &dummy)) != NULL) { uint32_t new; new = ddsrt_atomic_inc32_nv(&tk->m_refc); @@ -178,7 +178,7 @@ retry: we can block until someone signals some entry is removed from the map if we take some lock & wait for some condition */ ddsrt_mutex_lock(&map->m_lock); - while ((tk = ut_chhLookup(map->m_hh, &dummy)) != NULL && (ddsrt_atomic_ld32(&tk->m_refc) & REFC_DELETE)) + while ((tk = ddsrt_chh_lookup(map->m_hh, &dummy)) != NULL && (ddsrt_atomic_ld32(&tk->m_refc) & REFC_DELETE)) ddsrt_cond_wait(&map->m_cond, &map->m_lock); ddsrt_mutex_unlock(&map->m_lock); goto retry; @@ -192,7 +192,7 @@ retry: tk->m_sample = ddsi_serdata_to_topicless (sd); ddsrt_atomic_st32 (&tk->m_refc, 1); tk->m_iid = ddsi_iid_gen (); - if (!ut_chhAdd (map->m_hh, tk)) + if (!ddsrt_chh_add (map->m_hh, tk)) { /* Lost a race from another thread, retry */ ddsi_serdata_unref (tk->m_sample); @@ -237,7 +237,7 @@ void ddsi_tkmap_instance_unref (struct ddsi_tkmap_instance * tk) struct ddsi_tkmap *map = gv.m_tkmap; /* Remove from hash table */ - int removed = ut_chhRemove(map->m_hh, tk); + int removed = ddsrt_chh_remove(map->m_hh, tk); assert (removed); (void)removed; diff --git a/src/core/ddsi/src/q_addrset.c b/src/core/ddsi/src/q_addrset.c index 48d9a4a..f8694d8 100644 --- a/src/core/ddsi/src/q_addrset.c +++ b/src/core/ddsi/src/q_addrset.c @@ -17,7 +17,7 @@ #include "dds/ddsrt/log.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/misc.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_config.h" @@ -39,8 +39,8 @@ static int compare_locators_vwrap (const void *va, const void *vb); -static const ut_avlCTreedef_t addrset_treedef = - UT_AVL_CTREEDEF_INITIALIZER (offsetof (struct addrset_node, avlnode), offsetof (struct addrset_node, loc), compare_locators_vwrap, 0); +static const ddsrt_avl_ctreedef_t addrset_treedef = + DDSRT_AVL_CTREEDEF_INITIALIZER (offsetof (struct addrset_node, avlnode), offsetof (struct addrset_node, loc), compare_locators_vwrap, 0); static int add_addresses_to_addrset_1 (struct addrset *as, const char *ip, int port_mode, const char *msgtag, int req_mc, int mcgen_base, int mcgen_count, int mcgen_idx) { @@ -203,8 +203,8 @@ struct addrset *new_addrset (void) struct addrset *as = ddsrt_malloc (sizeof (*as)); ddsrt_atomic_st32 (&as->refc, 1); ddsrt_mutex_init (&as->lock); - ut_avlCInit (&addrset_treedef, &as->ucaddrs); - ut_avlCInit (&addrset_treedef, &as->mcaddrs); + ddsrt_avl_cinit (&addrset_treedef, &as->ucaddrs); + ddsrt_avl_cinit (&addrset_treedef, &as->mcaddrs); return as; } @@ -221,8 +221,8 @@ void unref_addrset (struct addrset *as) { if ((as != NULL) && (ddsrt_atomic_dec32_ov (&as->refc) == 1)) { - ut_avlCFree (&addrset_treedef, &as->ucaddrs, ddsrt_free); - ut_avlCFree (&addrset_treedef, &as->mcaddrs, ddsrt_free); + ddsrt_avl_cfree (&addrset_treedef, &as->ucaddrs, ddsrt_free); + ddsrt_avl_cfree (&addrset_treedef, &as->mcaddrs, ddsrt_free); ddsrt_mutex_destroy (&as->lock); ddsrt_free (as); } @@ -247,9 +247,9 @@ int is_unspec_locator (const nn_locator_t *loc) int addrset_contains_ssm (const struct addrset *as) { struct addrset_node *n; - ut_avlCIter_t it; + ddsrt_avl_citer_t it; LOCK (as); - for (n = ut_avlCIterFirst (&addrset_treedef, &as->mcaddrs, &it); n; n = ut_avlCIterNext (&it)) + for (n = ddsrt_avl_citer_first (&addrset_treedef, &as->mcaddrs, &it); n; n = ddsrt_avl_citer_next (&it)) { if (ddsi_is_ssm_mcaddr (&n->loc)) { @@ -264,9 +264,9 @@ int addrset_contains_ssm (const struct addrset *as) int addrset_any_ssm (const struct addrset *as, nn_locator_t *dst) { struct addrset_node *n; - ut_avlCIter_t it; + ddsrt_avl_citer_t it; LOCK (as); - for (n = ut_avlCIterFirst (&addrset_treedef, &as->mcaddrs, &it); n; n = ut_avlCIterNext (&it)) + for (n = ddsrt_avl_citer_first (&addrset_treedef, &as->mcaddrs, &it); n; n = ddsrt_avl_citer_next (&it)) { if (ddsi_is_ssm_mcaddr (&n->loc)) { @@ -282,9 +282,9 @@ int addrset_any_ssm (const struct addrset *as, nn_locator_t *dst) int addrset_any_non_ssm_mc (const struct addrset *as, nn_locator_t *dst) { struct addrset_node *n; - ut_avlCIter_t it; + ddsrt_avl_citer_t it; LOCK (as); - for (n = ut_avlCIterFirst (&addrset_treedef, &as->mcaddrs, &it); n; n = ut_avlCIterNext (&it)) + for (n = ddsrt_avl_citer_first (&addrset_treedef, &as->mcaddrs, &it); n; n = ddsrt_avl_citer_next (&it)) { if (!ddsi_is_ssm_mcaddr (&n->loc)) { @@ -301,8 +301,8 @@ int addrset_any_non_ssm_mc (const struct addrset *as, nn_locator_t *dst) int addrset_purge (struct addrset *as) { LOCK (as); - ut_avlCFree (&addrset_treedef, &as->ucaddrs, ddsrt_free); - ut_avlCFree (&addrset_treedef, &as->mcaddrs, ddsrt_free); + ddsrt_avl_cfree (&addrset_treedef, &as->ucaddrs, ddsrt_free); + ddsrt_avl_cfree (&addrset_treedef, &as->mcaddrs, ddsrt_free); UNLOCK (as); return 0; } @@ -311,14 +311,14 @@ void add_to_addrset (struct addrset *as, const nn_locator_t *loc) { if (!is_unspec_locator (loc)) { - ut_avlIPath_t path; - ut_avlCTree_t *tree = ddsi_is_mcaddr (loc) ? &as->mcaddrs : &as->ucaddrs; + ddsrt_avl_ipath_t path; + ddsrt_avl_ctree_t *tree = ddsi_is_mcaddr (loc) ? &as->mcaddrs : &as->ucaddrs; LOCK (as); - if (ut_avlCLookupIPath (&addrset_treedef, tree, loc, &path) == NULL) + if (ddsrt_avl_clookup_ipath (&addrset_treedef, tree, loc, &path) == NULL) { struct addrset_node *n = ddsrt_malloc (sizeof (*n)); n->loc = *loc; - ut_avlCInsertIPath (&addrset_treedef, tree, n, &path); + ddsrt_avl_cinsert_ipath (&addrset_treedef, tree, n, &path); } UNLOCK (as); } @@ -326,13 +326,13 @@ void add_to_addrset (struct addrset *as, const nn_locator_t *loc) void remove_from_addrset (struct addrset *as, const nn_locator_t *loc) { - ut_avlDPath_t path; - ut_avlCTree_t *tree = ddsi_is_mcaddr (loc) ? &as->mcaddrs : &as->ucaddrs; + ddsrt_avl_dpath_t path; + ddsrt_avl_ctree_t *tree = ddsi_is_mcaddr (loc) ? &as->mcaddrs : &as->ucaddrs; struct addrset_node *n; LOCK (as); - if ((n = ut_avlCLookupDPath (&addrset_treedef, tree, loc, &path)) != NULL) + if ((n = ddsrt_avl_clookup_dpath (&addrset_treedef, tree, loc, &path)) != NULL) { - ut_avlCDeleteDPath (&addrset_treedef, tree, n, &path); + ddsrt_avl_cdelete_dpath (&addrset_treedef, tree, n, &path); ddsrt_free (n); } UNLOCK (as); @@ -341,9 +341,9 @@ void remove_from_addrset (struct addrset *as, const nn_locator_t *loc) void copy_addrset_into_addrset_uc (struct addrset *as, const struct addrset *asadd) { struct addrset_node *n; - ut_avlCIter_t it; + ddsrt_avl_citer_t it; LOCK (asadd); - for (n = ut_avlCIterFirst (&addrset_treedef, &asadd->ucaddrs, &it); n; n = ut_avlCIterNext (&it)) + for (n = ddsrt_avl_citer_first (&addrset_treedef, &asadd->ucaddrs, &it); n; n = ddsrt_avl_citer_next (&it)) add_to_addrset (as, &n->loc); UNLOCK (asadd); } @@ -351,9 +351,9 @@ void copy_addrset_into_addrset_uc (struct addrset *as, const struct addrset *asa void copy_addrset_into_addrset_mc (struct addrset *as, const struct addrset *asadd) { struct addrset_node *n; - ut_avlCIter_t it; + ddsrt_avl_citer_t it; LOCK (asadd); - for (n = ut_avlCIterFirst (&addrset_treedef, &asadd->mcaddrs, &it); n; n = ut_avlCIterNext (&it)) + for (n = ddsrt_avl_citer_first (&addrset_treedef, &asadd->mcaddrs, &it); n; n = ddsrt_avl_citer_next (&it)) add_to_addrset (as, &n->loc); UNLOCK (asadd); } @@ -368,9 +368,9 @@ void copy_addrset_into_addrset (struct addrset *as, const struct addrset *asadd) void copy_addrset_into_addrset_no_ssm_mc (struct addrset *as, const struct addrset *asadd) { struct addrset_node *n; - ut_avlCIter_t it; + ddsrt_avl_citer_t it; LOCK (asadd); - for (n = ut_avlCIterFirst (&addrset_treedef, &asadd->mcaddrs, &it); n; n = ut_avlCIterNext (&it)) + for (n = ddsrt_avl_citer_first (&addrset_treedef, &asadd->mcaddrs, &it); n; n = ddsrt_avl_citer_next (&it)) { if (!ddsi_is_ssm_mcaddr (&n->loc)) add_to_addrset (as, &n->loc); @@ -389,14 +389,14 @@ void addrset_purge_ssm (struct addrset *as) { struct addrset_node *n; LOCK (as); - n = ut_avlCFindMin (&addrset_treedef, &as->mcaddrs); + n = ddsrt_avl_cfind_min (&addrset_treedef, &as->mcaddrs); while (n) { struct addrset_node *n1 = n; - n = ut_avlCFindSucc (&addrset_treedef, &as->mcaddrs, n); + n = ddsrt_avl_cfind_succ (&addrset_treedef, &as->mcaddrs, n); if (ddsi_is_ssm_mcaddr (&n1->loc)) { - ut_avlCDelete (&addrset_treedef, &as->mcaddrs, n1); + ddsrt_avl_cdelete (&addrset_treedef, &as->mcaddrs, n1); ddsrt_free (n1); } } @@ -412,7 +412,7 @@ size_t addrset_count (const struct addrset *as) { size_t count; LOCK (as); - count = ut_avlCCount (&as->ucaddrs) + ut_avlCCount (&as->mcaddrs); + count = ddsrt_avl_ccount (&as->ucaddrs) + ddsrt_avl_ccount (&as->mcaddrs); UNLOCK (as); return count; } @@ -426,7 +426,7 @@ size_t addrset_count_uc (const struct addrset *as) { size_t count; LOCK (as); - count = ut_avlCCount (&as->ucaddrs); + count = ddsrt_avl_ccount (&as->ucaddrs); UNLOCK (as); return count; } @@ -440,7 +440,7 @@ size_t addrset_count_mc (const struct addrset *as) { size_t count; LOCK (as); - count = ut_avlCCount (&as->mcaddrs); + count = ddsrt_avl_ccount (&as->mcaddrs); UNLOCK (as); return count; } @@ -450,7 +450,7 @@ int addrset_empty_uc (const struct addrset *as) { int isempty; LOCK (as); - isempty = ut_avlCIsEmpty (&as->ucaddrs); + isempty = ddsrt_avl_cis_empty (&as->ucaddrs); UNLOCK (as); return isempty; } @@ -459,7 +459,7 @@ int addrset_empty_mc (const struct addrset *as) { int isempty; LOCK (as); - isempty = ut_avlCIsEmpty (&as->mcaddrs); + isempty = ddsrt_avl_cis_empty (&as->mcaddrs); UNLOCK (as); return isempty; } @@ -468,7 +468,7 @@ int addrset_empty (const struct addrset *as) { int isempty; LOCK (as); - isempty = ut_avlCIsEmpty (&as->ucaddrs) && ut_avlCIsEmpty (&as->mcaddrs); + isempty = ddsrt_avl_cis_empty (&as->ucaddrs) && ddsrt_avl_cis_empty (&as->mcaddrs); UNLOCK (as); return isempty; } @@ -476,14 +476,14 @@ int addrset_empty (const struct addrset *as) int addrset_any_uc (const struct addrset *as, nn_locator_t *dst) { LOCK (as); - if (ut_avlCIsEmpty (&as->ucaddrs)) + if (ddsrt_avl_cis_empty (&as->ucaddrs)) { UNLOCK (as); return 0; } else { - const struct addrset_node *n = ut_avlCRootNonEmpty (&addrset_treedef, &as->ucaddrs); + const struct addrset_node *n = ddsrt_avl_croot_non_empty (&addrset_treedef, &as->ucaddrs); *dst = n->loc; UNLOCK (as); return 1; @@ -493,14 +493,14 @@ int addrset_any_uc (const struct addrset *as, nn_locator_t *dst) int addrset_any_mc (const struct addrset *as, nn_locator_t *dst) { LOCK (as); - if (ut_avlCIsEmpty (&as->mcaddrs)) + if (ddsrt_avl_cis_empty (&as->mcaddrs)) { UNLOCK (as); return 0; } else { - const struct addrset_node *n = ut_avlCRootNonEmpty (&addrset_treedef, &as->mcaddrs); + const struct addrset_node *n = ddsrt_avl_croot_non_empty (&addrset_treedef, &as->mcaddrs); *dst = n->loc; UNLOCK (as); return 1; @@ -527,9 +527,9 @@ size_t addrset_forall_count (struct addrset *as, addrset_forall_fun_t f, void *a arg1.f = f; arg1.arg = arg; LOCK (as); - ut_avlCWalk (&addrset_treedef, &as->mcaddrs, addrset_forall_helper, &arg1); - ut_avlCWalk (&addrset_treedef, &as->ucaddrs, addrset_forall_helper, &arg1); - count = ut_avlCCount (&as->ucaddrs) + ut_avlCCount (&as->mcaddrs); + ddsrt_avl_cwalk (&addrset_treedef, &as->mcaddrs, addrset_forall_helper, &arg1); + ddsrt_avl_cwalk (&addrset_treedef, &as->ucaddrs, addrset_forall_helper, &arg1); + count = ddsrt_avl_ccount (&as->ucaddrs) + ddsrt_avl_ccount (&as->mcaddrs); UNLOCK (as); return count; } @@ -543,22 +543,22 @@ int addrset_forone (struct addrset *as, addrset_forone_fun_t f, void *arg) { unsigned i; addrset_node_t n; - ut_avlCTree_t *trees[2]; - ut_avlCIter_t iter; + ddsrt_avl_ctree_t *trees[2]; + ddsrt_avl_citer_t iter; trees[0] = &as->mcaddrs; trees[1] = &as->ucaddrs; for (i = 0; i < 2u; i++) { - n = (addrset_node_t) ut_avlCIterFirst (&addrset_treedef, trees[i], &iter); + n = (addrset_node_t) ddsrt_avl_citer_first (&addrset_treedef, trees[i], &iter); while (n) { if ((f) (&n->loc, arg) > 0) { return 0; } - n = (addrset_node_t) ut_avlCIterNext (&iter); + n = (addrset_node_t) ddsrt_avl_citer_next (&iter); } } return -1; @@ -588,14 +588,14 @@ void nn_log_addrset (uint32_t tf, const char *prefix, const struct addrset *as) } } -static int addrset_eq_onesidederr1 (const ut_avlCTree_t *at, const ut_avlCTree_t *bt) +static int addrset_eq_onesidederr1 (const ddsrt_avl_ctree_t *at, const ddsrt_avl_ctree_t *bt) { /* Just checking the root */ - if (ut_avlCIsEmpty (at) && ut_avlCIsEmpty (bt)) { + if (ddsrt_avl_cis_empty (at) && ddsrt_avl_cis_empty (bt)) { return 1; - } else if (ut_avlCIsSingleton (at) && ut_avlCIsSingleton (bt)) { - const struct addrset_node *a = ut_avlCRootNonEmpty (&addrset_treedef, at); - const struct addrset_node *b = ut_avlCRootNonEmpty (&addrset_treedef, bt); + } else if (ddsrt_avl_cis_singleton (at) && ddsrt_avl_cis_singleton (bt)) { + const struct addrset_node *a = ddsrt_avl_croot_non_empty (&addrset_treedef, at); + const struct addrset_node *b = ddsrt_avl_croot_non_empty (&addrset_treedef, bt); return compare_locators (&a->loc, &b->loc) == 0; } else { return 0; diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index b613df8..5a412e8 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -24,15 +24,15 @@ #include "dds/ddsrt/misc.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_addrset.h" #include "dds/ddsi/q_nwif.h" #include "dds/ddsi/q_error.h" -#include "dds/util/ut_xmlparser.h" -#include "dds/util/ut_expand_envvars.h" +#include "dds/ddsrt/xmlparser.h" +#include "dds/ddsrt/expand_envvars.h" #include "dds/version.h" @@ -77,7 +77,7 @@ struct cfgst_nodekey { }; struct cfgst_node { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; struct cfgst_nodekey key; int count; int failed; @@ -85,7 +85,7 @@ struct cfgst_node { }; struct cfgst { - ut_avlTree_t found; + ddsrt_avl_tree_t found; struct config *cfg; /* error flag set so that we can continue parsing for some errors and still fail properly */ int error; @@ -119,8 +119,8 @@ the configuration, so we update this variable instead. */ static uint32_t enabled_logcats; static int cfgst_node_cmp(const void *va, const void *vb); -static const ut_avlTreedef_t cfgst_found_treedef = -UT_AVL_TREEDEF_INITIALIZER(offsetof(struct cfgst_node, avlnode), offsetof(struct cfgst_node, key), cfgst_node_cmp, 0); +static const ddsrt_avl_treedef_t cfgst_found_treedef = +DDSRT_AVL_TREEDEF_INITIALIZER(offsetof(struct cfgst_node, avlnode), offsetof(struct cfgst_node, key), cfgst_node_cmp, 0); #define DU(fname) static int uf_##fname (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) #define PF(fname) static void pf_##fname (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) @@ -2067,10 +2067,10 @@ static int do_update(struct cfgst *cfgst, update_fun_t upd, void *parent, struct { struct cfgst_node *n; struct cfgst_nodekey key; - ut_avlIPath_t np; + ddsrt_avl_ipath_t np; int ok; key.e = cfgelem; - if ( (n = ut_avlLookupIPath(&cfgst_found_treedef, &cfgst->found, &key, &np)) == NULL ) { + if ( (n = ddsrt_avl_lookup_ipath(&cfgst_found_treedef, &cfgst->found, &key, &np)) == NULL ) { if ( (n = ddsrt_malloc(sizeof(*n))) == NULL ) return cfg_error(cfgst, "out of memory"); @@ -2078,7 +2078,7 @@ static int do_update(struct cfgst *cfgst, update_fun_t upd, void *parent, struct n->count = 0; n->failed = 0; n->is_default = is_default; - ut_avlInsertIPath(&cfgst_found_treedef, &cfgst->found, n, &np); + ddsrt_avl_insert_ipath(&cfgst_found_treedef, &cfgst->found, n, &np); } if ( cfgelem->multiplicity == 0 || n->count < cfgelem->multiplicity ) ok = upd(cfgst, parent, cfgelem, (n->count == n->failed), value); @@ -2108,7 +2108,7 @@ static int set_defaults(struct cfgst *cfgst, void *parent, int isattr, struct cf key.e = ce; cfgst_push(cfgst, isattr, ce, parent); if ( ce->multiplicity == 1 ) { - if ( ut_avlLookup(&cfgst_found_treedef, &cfgst->found, &key) == NULL ) { + if ( ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key) == NULL ) { if ( ce->update ) { int ok1; cfgst_push(cfgst, 0, NULL, NULL); @@ -2117,9 +2117,9 @@ static int set_defaults(struct cfgst *cfgst, void *parent, int isattr, struct cf ok = ok && ok1; } } - if ( (n = ut_avlLookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { + if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { if ( clear_found ) { - ut_avlDelete(&cfgst_found_treedef, &cfgst->found, n); + ddsrt_avl_delete(&cfgst_found_treedef, &cfgst->found, n); ddsrt_free(n); } } @@ -2419,7 +2419,7 @@ static void print_configitems(struct cfgst *cfgst, void *parent, int isattr, str key.e = ce; cfgst_push(cfgst, isattr, ce, parent); if ( ce->multiplicity == 1 ) { - if ( (n = ut_avlLookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { + if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { cfgst_push(cfgst, 0, NULL, NULL); ce->print(cfgst, parent, ce, n->is_default); cfgst_pop(cfgst); @@ -2496,7 +2496,7 @@ static void free_configured_elements(struct cfgst *cfgst, void *parent, struct c if ( ce->name[0] == '>' ) /* moved, so don't care */ continue; key.e = ce; - if ( (n = ut_avlLookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { + if ( (n = ddsrt_avl_lookup(&cfgst_found_treedef, &cfgst->found, &key)) != NULL ) { if ( ce->free && n->count > n->failed ) ce->free(cfgst, parent, ce); } @@ -2646,7 +2646,7 @@ static int proc_attr(void *varg, UNUSED_ARG(uintptr_t eleminfo), const char *nam return cfg_error(cfgst, "%s: unknown attribute", name); else { void *parent = cfgst_parent(cfgst); - char *xvalue = ut_expand_envvars(value); + char *xvalue = ddsrt_expand_envvars(value); int ok; cfgst_push(cfgst, 1, cfg_attr, parent); ok = do_update(cfgst, cfg_attr->update, parent, cfg_attr, xvalue, 0); @@ -2666,7 +2666,7 @@ static int proc_elem_data(void *varg, UNUSED_ARG(uintptr_t eleminfo), const char return cfg_error(cfgst, "%s: no data expected", value); else { void *parent = cfgst_parent(cfgst); - char *xvalue = ut_expand_envvars(value); + char *xvalue = ddsrt_expand_envvars(value); int ok; cfgst_push(cfgst, 0, NULL, parent); ok = do_update(cfgst, cfgelem->update, parent, cfgelem, xvalue, 0); @@ -2802,14 +2802,14 @@ struct cfgst * config_init (const char *configfile) cfgst = ddsrt_malloc(sizeof(*cfgst)); memset(cfgst, 0, sizeof(*cfgst)); - ut_avlInit(&cfgst_found_treedef, &cfgst->found); + ddsrt_avl_init(&cfgst_found_treedef, &cfgst->found); cfgst->cfg = &config; cfgst->error = 0; /* configfile == NULL will get you the default configuration */ if (configfile) { char *copy = ddsrt_strdup(configfile), *cursor = copy; - struct ut_xmlpCallbacks cb; + struct ddsrt_xmlp_callbacks cb; cb.attr = proc_attr; cb.elem_close = proc_elem_close; @@ -2818,14 +2818,14 @@ struct cfgst * config_init (const char *configfile) cb.error = proc_error; while (ok && cursor && cursor[0]) { - struct ut_xmlpState *qx; + struct ddsrt_xmlp_state *qx; FILE *fp; char *tok; tok = cursor; if (tok[0] == '<') { /* Read XML directly from input string */ - qx = ut_xmlpNewString (tok, cfgst, &cb); - ut_xmlpSetRequireEOF (qx, 0); + qx = ddsrt_xmlp_new_string (tok, cfgst, &cb); + ddsrt_xmlp_set_requireEOF (qx, 0); fp = NULL; } else { char *comma; @@ -2845,11 +2845,11 @@ struct cfgst * config_init (const char *configfile) } } DDSRT_WARNING_MSVC_ON(4996); - qx = ut_xmlpNewFile(fp, cfgst, &cb); + qx = ddsrt_xmlp_new_file(fp, cfgst, &cb); } cfgst_push(cfgst, 0, &root_cfgelem, &config); - ok = (ut_xmlpParse(qx) >= 0) && !cfgst->error; + ok = (ddsrt_xmlp_parse(qx) >= 0) && !cfgst->error; /* Pop until stack empty: error handling is rather brutal */ assert(!ok || cfgst->path_depth == 1); while (cfgst->path_depth > 0) { @@ -2858,9 +2858,9 @@ struct cfgst * config_init (const char *configfile) if (fp) { fclose(fp); } else if (ok) { - cursor = tok + ut_xmlpGetBufpos (qx); + cursor = tok + ddsrt_xmlp_get_bufpos (qx); } - ut_xmlpFree(qx); + ddsrt_xmlp_free(qx); while (cursor && cursor[0] == ',') { cursor++; } @@ -3019,7 +3019,7 @@ struct cfgst * config_init (const char *configfile) config.valid = 1; return cfgst; } else { - ut_avlFree(&cfgst_found_treedef, &cfgst->found, ddsrt_free); + ddsrt_avl_free(&cfgst_found_treedef, &cfgst->found, ddsrt_free); ddsrt_free(cfgst); return NULL; } @@ -3047,7 +3047,7 @@ void config_fini(struct cfgst *cfgst) memset(&config, 0, sizeof(config)); config.valid = 0; - ut_avlFree(&cfgst_found_treedef, &cfgst->found, ddsrt_free); + ddsrt_avl_free(&cfgst_found_treedef, &cfgst->found, ddsrt_free); ddsrt_free(cfgst); } diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index bf5ec02..12ab0bc 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -20,7 +20,7 @@ #include "dds/ddsrt/log.h" #include "dds/ddsrt/md5.h" #include "dds/ddsrt/sync.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_misc.h" @@ -1767,7 +1767,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str statusinfo = (qos.present & PP_STATUSINFO) ? qos.statusinfo : 0; } - if (pwr && ut_avlIsEmpty (&pwr->readers)) + if (pwr && ddsrt_avl_is_empty (&pwr->readers)) { /* Wasn't empty when enqueued, but needn't still be; SPDP has no proxy writer, and is always accepted */ diff --git a/src/core/ddsi/src/q_debmon.c b/src/core/ddsi/src/q_debmon.c index 8043229..2e5358a 100644 --- a/src/core/ddsi/src/q_debmon.c +++ b/src/core/ddsi/src/q_debmon.c @@ -18,7 +18,7 @@ #include "dds/ddsrt/sync.h" #include "dds/ddsrt/misc.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_config.h" @@ -161,7 +161,7 @@ static int print_participants (struct thread_state1 * const ts1, ddsi_tran_conn_ ephash_enum_reader_init (&er); while ((r = ephash_enum_reader_next (&er)) != NULL) { - ut_avlIter_t writ; + ddsrt_avl_iter_t writ; struct rd_pwr_match *m; if (r->c.pp != p) continue; @@ -170,7 +170,7 @@ static int print_participants (struct thread_state1 * const ts1, ddsi_tran_conn_ #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS x += print_addrset_if_notempty (conn, " as", r->as, "\n"); #endif - for (m = ut_avlIterFirst (&rd_writers_treedef, &r->writers, &writ); m; m = ut_avlIterNext (&writ)) + for (m = ddsrt_avl_iter_first (&rd_writers_treedef, &r->writers, &writ); m; m = ddsrt_avl_iter_next (&writ)) x += cpf (conn, " pwr %x:%x:%x:%x\n", PGUID (m->pwr_guid)); ddsrt_mutex_unlock (&r->e.lock); } @@ -183,7 +183,7 @@ static int print_participants (struct thread_state1 * const ts1, ddsi_tran_conn_ ephash_enum_writer_init (&ew); while ((w = ephash_enum_writer_next (&ew)) != NULL) { - ut_avlIter_t rdit; + ddsrt_avl_iter_t rdit; struct wr_prd_match *m; struct whc_state whcst; if (w->c.pp != p) @@ -207,7 +207,7 @@ static int print_participants (struct thread_state1 * const ts1, ddsi_tran_conn_ x += cpf (conn, " max-drop-seq %lld\n", writer_max_drop_seq (w)); } x += print_addrset_if_notempty (conn, " as", w->as, "\n"); - for (m = ut_avlIterFirst (&wr_readers_treedef, &w->readers, &rdit); m; m = ut_avlIterNext (&rdit)) + for (m = ddsrt_avl_iter_first (&wr_readers_treedef, &w->readers, &rdit); m; m = ddsrt_avl_iter_next (&rdit)) { char wr_prd_flags[4]; wr_prd_flags[0] = m->is_reliable ? 'R' : 'U'; @@ -248,13 +248,13 @@ static int print_proxy_participants (struct thread_state1 * const ts1, ddsi_tran ephash_enum_proxy_reader_init (&er); while ((r = ephash_enum_proxy_reader_next (&er)) != NULL) { - ut_avlIter_t writ; + ddsrt_avl_iter_t writ; struct prd_wr_match *m; if (r->c.proxypp != p) continue; ddsrt_mutex_lock (&r->e.lock); print_proxy_endpoint_common (conn, "prd", &r->e, &r->c); - for (m = ut_avlIterFirst (&rd_writers_treedef, &r->writers, &writ); m; m = ut_avlIterNext (&writ)) + for (m = ddsrt_avl_iter_first (&rd_writers_treedef, &r->writers, &writ); m; m = ddsrt_avl_iter_next (&writ)) x += cpf (conn, " wr %x:%x:%x:%x\n", PGUID (m->wr_guid)); ddsrt_mutex_unlock (&r->e.lock); } @@ -267,14 +267,14 @@ static int print_proxy_participants (struct thread_state1 * const ts1, ddsi_tran ephash_enum_proxy_writer_init (&ew); while ((w = ephash_enum_proxy_writer_next (&ew)) != NULL) { - ut_avlIter_t rdit; + ddsrt_avl_iter_t rdit; struct pwr_rd_match *m; if (w->c.proxypp != p) continue; ddsrt_mutex_lock (&w->e.lock); print_proxy_endpoint_common (conn, "pwr", &w->e, &w->c); x += cpf (conn, " last_seq %lld last_fragnum %u\n", w->last_seq, w->last_fragnum); - for (m = ut_avlIterFirst (&wr_readers_treedef, &w->readers, &rdit); m; m = ut_avlIterNext (&rdit)) + for (m = ddsrt_avl_iter_first (&wr_readers_treedef, &w->readers, &rdit); m; m = ddsrt_avl_iter_next (&rdit)) { x += cpf (conn, " rd %x:%x:%x:%x (nack %lld %lld)\n", PGUID (m->rd_guid), m->seq_last_nack, m->t_last_nack); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 2c5105c..25ef9ea 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -25,7 +25,7 @@ #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_misc.h" #include "dds/ddsi/q_log.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_plist.h" #include "dds/ddsi/q_lease.h" #include "dds/ddsi/q_qosmatch.h" @@ -49,34 +49,34 @@ #include "dds/ddsi/ddsi_tkmap.h" struct deleted_participant { - ut_avlNode_t avlnode; + ddsrt_avl_node_t avlnode; nn_guid_t guid; unsigned for_what; nn_mtime_t t_prune; }; static ddsrt_mutex_t deleted_participants_lock; -static ut_avlTree_t deleted_participants; +static ddsrt_avl_tree_t deleted_participants; static int compare_guid (const void *va, const void *vb); static void augment_wr_prd_match (void *vnode, const void *vleft, const void *vright); -const ut_avlTreedef_t wr_readers_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct wr_prd_match, avlnode), offsetof (struct wr_prd_match, prd_guid), compare_guid, augment_wr_prd_match); -const ut_avlTreedef_t wr_local_readers_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct wr_rd_match, avlnode), offsetof (struct wr_rd_match, rd_guid), compare_guid, 0); -const ut_avlTreedef_t rd_writers_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct rd_pwr_match, avlnode), offsetof (struct rd_pwr_match, pwr_guid), compare_guid, 0); -const ut_avlTreedef_t rd_local_writers_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct rd_wr_match, avlnode), offsetof (struct rd_wr_match, wr_guid), compare_guid, 0); -const ut_avlTreedef_t pwr_readers_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct pwr_rd_match, avlnode), offsetof (struct pwr_rd_match, rd_guid), compare_guid, 0); -const ut_avlTreedef_t prd_writers_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct prd_wr_match, avlnode), offsetof (struct prd_wr_match, wr_guid), compare_guid, 0); -const ut_avlTreedef_t deleted_participants_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct deleted_participant, avlnode), offsetof (struct deleted_participant, guid), compare_guid, 0); -const ut_avlTreedef_t proxypp_groups_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct proxy_group, avlnode), offsetof (struct proxy_group, guid), compare_guid, 0); +const ddsrt_avl_treedef_t wr_readers_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct wr_prd_match, avlnode), offsetof (struct wr_prd_match, prd_guid), compare_guid, augment_wr_prd_match); +const ddsrt_avl_treedef_t wr_local_readers_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct wr_rd_match, avlnode), offsetof (struct wr_rd_match, rd_guid), compare_guid, 0); +const ddsrt_avl_treedef_t rd_writers_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct rd_pwr_match, avlnode), offsetof (struct rd_pwr_match, pwr_guid), compare_guid, 0); +const ddsrt_avl_treedef_t rd_local_writers_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct rd_wr_match, avlnode), offsetof (struct rd_wr_match, wr_guid), compare_guid, 0); +const ddsrt_avl_treedef_t pwr_readers_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct pwr_rd_match, avlnode), offsetof (struct pwr_rd_match, rd_guid), compare_guid, 0); +const ddsrt_avl_treedef_t prd_writers_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct prd_wr_match, avlnode), offsetof (struct prd_wr_match, wr_guid), compare_guid, 0); +const ddsrt_avl_treedef_t deleted_participants_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct deleted_participant, avlnode), offsetof (struct deleted_participant, guid), compare_guid, 0); +const ddsrt_avl_treedef_t proxypp_groups_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct proxy_group, avlnode), offsetof (struct proxy_group, guid), compare_guid, 0); static const unsigned builtin_writers_besmask = NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER | @@ -267,13 +267,13 @@ nn_vendorid_t get_entity_vendorid (const struct entity_common *e) int deleted_participants_admin_init (void) { ddsrt_mutex_init (&deleted_participants_lock); - ut_avlInit (&deleted_participants_treedef, &deleted_participants); + ddsrt_avl_init (&deleted_participants_treedef, &deleted_participants); return 0; } void deleted_participants_admin_fini (void) { - ut_avlFree (&deleted_participants_treedef, &deleted_participants, ddsrt_free); + ddsrt_avl_free (&deleted_participants_treedef, &deleted_participants, ddsrt_free); ddsrt_mutex_destroy (&deleted_participants_lock); } @@ -283,13 +283,13 @@ static void prune_deleted_participant_guids_unlocked (nn_mtime_t tnow) all circumstances, but I expect the tree to be very small at all times, so a full scan is fine, too ... */ struct deleted_participant *dpp; - dpp = ut_avlFindMin (&deleted_participants_treedef, &deleted_participants); + dpp = ddsrt_avl_find_min (&deleted_participants_treedef, &deleted_participants); while (dpp) { - struct deleted_participant *dpp1 = ut_avlFindSucc (&deleted_participants_treedef, &deleted_participants, dpp); + struct deleted_participant *dpp1 = ddsrt_avl_find_succ (&deleted_participants_treedef, &deleted_participants, dpp); if (dpp->t_prune.v < tnow.v) { - ut_avlDelete (&deleted_participants_treedef, &deleted_participants, dpp); + ddsrt_avl_delete (&deleted_participants_treedef, &deleted_participants, dpp); ddsrt_free (dpp); } dpp = dpp1; @@ -306,16 +306,16 @@ static void prune_deleted_participant_guids (nn_mtime_t tnow) static void remember_deleted_participant_guid (const struct nn_guid *guid) { struct deleted_participant *n; - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; ddsrt_mutex_lock (&deleted_participants_lock); - if (ut_avlLookupIPath (&deleted_participants_treedef, &deleted_participants, guid, &path) == NULL) + if (ddsrt_avl_lookup_ipath (&deleted_participants_treedef, &deleted_participants, guid, &path) == NULL) { if ((n = ddsrt_malloc (sizeof (*n))) != NULL) { n->guid = *guid; n->t_prune.v = T_NEVER; n->for_what = DPG_LOCAL | DPG_REMOTE; - ut_avlInsertIPath (&deleted_participants_treedef, &deleted_participants, n, &path); + ddsrt_avl_insert_ipath (&deleted_participants_treedef, &deleted_participants, n, &path); } } ddsrt_mutex_unlock (&deleted_participants_lock); @@ -327,7 +327,7 @@ int is_deleted_participant_guid (const struct nn_guid *guid, unsigned for_what) int known; ddsrt_mutex_lock (&deleted_participants_lock); prune_deleted_participant_guids_unlocked (now_mt()); - if ((n = ut_avlLookup (&deleted_participants_treedef, &deleted_participants, guid)) == NULL) + if ((n = ddsrt_avl_lookup (&deleted_participants_treedef, &deleted_participants, guid)) == NULL) known = 0; else known = ((n->for_what & for_what) != 0); @@ -340,7 +340,7 @@ static void remove_deleted_participant_guid (const struct nn_guid *guid, unsigne struct deleted_participant *n; DDS_LOG(DDS_LC_DISCOVERY, "remove_deleted_participant_guid(%x:%x:%x:%x for_what=%x)\n", PGUID (*guid), for_what); ddsrt_mutex_lock (&deleted_participants_lock); - if ((n = ut_avlLookup (&deleted_participants_treedef, &deleted_participants, guid)) != NULL) + if ((n = ddsrt_avl_lookup (&deleted_participants_treedef, &deleted_participants, guid)) != NULL) { if (config.prune_deleted_ppant.enforce_delay) { @@ -357,7 +357,7 @@ static void remove_deleted_participant_guid (const struct nn_guid *guid, unsigne } else { - ut_avlDelete (&deleted_participants_treedef, &deleted_participants, n); + ddsrt_avl_delete (&deleted_participants_treedef, &deleted_participants, n); ddsrt_free (n); } } @@ -971,13 +971,13 @@ static struct addrset *rebuild_make_all_addrs (int *nreaders, struct writer *wr) { struct addrset *all_addrs = new_addrset(); struct wr_prd_match *m; - ut_avlIter_t it; + ddsrt_avl_iter_t it; #ifdef DDSI_INCLUDE_SSM if (wr->supports_ssm && wr->ssm_as) copy_addrset_into_addrset_mc (all_addrs, wr->ssm_as); #endif *nreaders = 0; - for (m = ut_avlIterFirst (&wr_readers_treedef, &wr->readers, &it); m; m = ut_avlIterNext (&it)) + for (m = ddsrt_avl_iter_first (&wr_readers_treedef, &wr->readers, &it); m; m = ddsrt_avl_iter_next (&it)) { struct proxy_reader *prd; if ((prd = ephash_lookup_proxy_reader_guid (&m->prd_guid)) == NULL) @@ -1030,7 +1030,7 @@ static void rebuild_make_covered(int8_t **covered, const struct writer *wr, int { struct rebuild_flatten_locs_arg flarg; struct wr_prd_match *m; - ut_avlIter_t it; + ddsrt_avl_iter_t it; int rdidx, i, j; int8_t *cov = ddsrt_malloc((size_t) *nreaders * (size_t) nlocs * sizeof (*cov)); for (i = 0; i < *nreaders * nlocs; i++) @@ -1040,7 +1040,7 @@ static void rebuild_make_covered(int8_t **covered, const struct writer *wr, int #ifndef NDEBUG flarg.size = nlocs; #endif - for (m = ut_avlIterFirst (&wr_readers_treedef, &wr->readers, &it); m; m = ut_avlIterNext (&it)) + for (m = ddsrt_avl_iter_first (&wr_readers_treedef, &wr->readers, &it); m; m = ddsrt_avl_iter_next (&it)) { struct proxy_reader *prd; struct addrset *ass[] = { NULL, NULL, NULL }; @@ -1337,10 +1337,10 @@ static void writer_drop_connection (const struct nn_guid * wr_guid, const struct struct whc_node *deferred_free_list = NULL; struct wr_prd_match *m; ddsrt_mutex_lock (&wr->e.lock); - if ((m = ut_avlLookup (&wr_readers_treedef, &wr->readers, &prd->e.guid)) != NULL) + if ((m = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &prd->e.guid)) != NULL) { struct whc_state whcst; - ut_avlDelete (&wr_readers_treedef, &wr->readers, m); + ddsrt_avl_delete (&wr_readers_treedef, &wr->readers, m); rebuild_writer_addrset (wr); remove_acked_messages (wr, &whcst, &deferred_free_list); wr->num_reliable_readers -= m->is_reliable; @@ -1368,9 +1368,9 @@ static void writer_drop_local_connection (const struct nn_guid *wr_guid, struct struct wr_rd_match *m; ddsrt_mutex_lock (&wr->e.lock); - if ((m = ut_avlLookup (&wr_local_readers_treedef, &wr->local_readers, &rd->e.guid)) != NULL) + if ((m = ddsrt_avl_lookup (&wr_local_readers_treedef, &wr->local_readers, &rd->e.guid)) != NULL) { - ut_avlDelete (&wr_local_readers_treedef, &wr->local_readers, m); + ddsrt_avl_delete (&wr_local_readers_treedef, &wr->local_readers, m); local_reader_ary_remove (&wr->rdary, rd); } ddsrt_mutex_unlock (&wr->e.lock); @@ -1393,8 +1393,8 @@ static void reader_drop_connection (const struct nn_guid *rd_guid, const struct { struct rd_pwr_match *m; ddsrt_mutex_lock (&rd->e.lock); - if ((m = ut_avlLookup (&rd_writers_treedef, &rd->writers, &pwr->e.guid)) != NULL) - ut_avlDelete (&rd_writers_treedef, &rd->writers, m); + if ((m = ddsrt_avl_lookup (&rd_writers_treedef, &rd->writers, &pwr->e.guid)) != NULL) + ddsrt_avl_delete (&rd_writers_treedef, &rd->writers, m); ddsrt_mutex_unlock (&rd->e.lock); free_rd_pwr_match (m); @@ -1427,8 +1427,8 @@ static void reader_drop_local_connection (const struct nn_guid *rd_guid, const s { struct rd_wr_match *m; ddsrt_mutex_lock (&rd->e.lock); - if ((m = ut_avlLookup (&rd_local_writers_treedef, &rd->local_writers, &wr->e.guid)) != NULL) - ut_avlDelete (&rd_local_writers_treedef, &rd->local_writers, m); + if ((m = ddsrt_avl_lookup (&rd_local_writers_treedef, &rd->local_writers, &wr->e.guid)) != NULL) + ddsrt_avl_delete (&rd_local_writers_treedef, &rd->local_writers, m); ddsrt_mutex_unlock (&rd->e.lock); free_rd_wr_match (m); @@ -1486,9 +1486,9 @@ static void proxy_writer_drop_connection (const struct nn_guid *pwr_guid, struct struct pwr_rd_match *m; ddsrt_mutex_lock (&pwr->e.lock); - if ((m = ut_avlLookup (&pwr_readers_treedef, &pwr->readers, &rd->e.guid)) != NULL) + if ((m = ddsrt_avl_lookup (&pwr_readers_treedef, &pwr->readers, &rd->e.guid)) != NULL) { - ut_avlDelete (&pwr_readers_treedef, &pwr->readers, m); + ddsrt_avl_delete (&pwr_readers_treedef, &pwr->readers, m); if (m->in_sync != PRMSS_SYNC) pwr->n_readers_out_of_sync--; if (rd->reliable) @@ -1512,10 +1512,10 @@ static void proxy_reader_drop_connection { struct prd_wr_match *m; ddsrt_mutex_lock (&prd->e.lock); - m = ut_avlLookup (&prd_writers_treedef, &prd->writers, &wr->e.guid); + m = ddsrt_avl_lookup (&prd_writers_treedef, &prd->writers, &wr->e.guid); if (m) { - ut_avlDelete (&prd_writers_treedef, &prd->writers, m); + ddsrt_avl_delete (&prd_writers_treedef, &prd->writers, m); } ddsrt_mutex_unlock (&prd->e.lock); free_prd_wr_match (m); @@ -1525,7 +1525,7 @@ static void proxy_reader_drop_connection static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) { struct wr_prd_match *m = ddsrt_malloc (sizeof (*m)); - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; int pretend_everything_acked; m->prd_guid = prd->e.guid; m->is_reliable = (prd->c.xqos->reliability.kind > NN_BEST_EFFORT_RELIABILITY_QOS); @@ -1564,7 +1564,7 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) m->seq = MAX_SEQ_NUMBER; else m->seq = wr->seq; - if (ut_avlLookupIPath (&wr_readers_treedef, &wr->readers, &prd->e.guid, &path)) + if (ddsrt_avl_lookup_ipath (&wr_readers_treedef, &wr->readers, &prd->e.guid, &path)) { DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x) - already connected\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); ddsrt_mutex_unlock (&wr->e.lock); @@ -1574,7 +1574,7 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) else { DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x) - ack seq %"PRId64"\n", PGUID (wr->e.guid), PGUID (prd->e.guid), m->seq); - ut_avlInsertIPath (&wr_readers_treedef, &wr->readers, m, &path); + ddsrt_avl_insert_ipath (&wr_readers_treedef, &wr->readers, m, &path); rebuild_writer_addrset (wr); wr->num_reliable_readers += m->is_reliable; ddsrt_mutex_unlock (&wr->e.lock); @@ -1618,10 +1618,10 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) static void writer_add_local_connection (struct writer *wr, struct reader *rd) { struct wr_rd_match *m = ddsrt_malloc (sizeof (*m)); - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; ddsrt_mutex_lock (&wr->e.lock); - if (ut_avlLookupIPath (&wr_local_readers_treedef, &wr->local_readers, &rd->e.guid, &path)) + if (ddsrt_avl_lookup_ipath (&wr_local_readers_treedef, &wr->local_readers, &rd->e.guid, &path)) { DDS_LOG(DDS_LC_DISCOVERY, " writer_add_local_connection(wr %x:%x:%x:%x rd %x:%x:%x:%x) - already connected\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); ddsrt_mutex_unlock (&wr->e.lock); @@ -1631,7 +1631,7 @@ static void writer_add_local_connection (struct writer *wr, struct reader *rd) DDS_LOG(DDS_LC_DISCOVERY, " writer_add_local_connection(wr %x:%x:%x:%x rd %x:%x:%x:%x)", PGUID (wr->e.guid), PGUID (rd->e.guid)); m->rd_guid = rd->e.guid; - ut_avlInsertIPath (&wr_local_readers_treedef, &wr->local_readers, m, &path); + ddsrt_avl_insert_ipath (&wr_local_readers_treedef, &wr->local_readers, m, &path); local_reader_ary_insert (&wr->rdary, rd); /* Store available data into the late joining reader when it is reliable (we don't do @@ -1672,7 +1672,7 @@ static void writer_add_local_connection (struct writer *wr, struct reader *rd) static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, nn_count_t *init_count) { struct rd_pwr_match *m = ddsrt_malloc (sizeof (*m)); - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; m->pwr_guid = pwr->e.guid; @@ -1687,7 +1687,7 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, DDS_LOG(DDS_LC_DISCOVERY, " reader %x:%x:%x:%x init_acknack_count = %d\n", PGUID (rd->e.guid), rd->init_acknack_count); *init_count = rd->init_acknack_count; - if (ut_avlLookupIPath (&rd_writers_treedef, &rd->writers, &pwr->e.guid, &path)) + if (ddsrt_avl_lookup_ipath (&rd_writers_treedef, &rd->writers, &pwr->e.guid, &path)) { DDS_LOG(DDS_LC_DISCOVERY, " reader_add_connection(pwr %x:%x:%x:%x rd %x:%x:%x:%x) - already connected\n", PGUID (pwr->e.guid), PGUID (rd->e.guid)); @@ -1698,7 +1698,7 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, { DDS_LOG(DDS_LC_DISCOVERY, " reader_add_connection(pwr %x:%x:%x:%x rd %x:%x:%x:%x)\n", PGUID (pwr->e.guid), PGUID (rd->e.guid)); - ut_avlInsertIPath (&rd_writers_treedef, &rd->writers, m, &path); + ddsrt_avl_insert_ipath (&rd_writers_treedef, &rd->writers, m, &path); ddsrt_mutex_unlock (&rd->e.lock); #ifdef DDSI_INCLUDE_SSM @@ -1736,13 +1736,13 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, static void reader_add_local_connection (struct reader *rd, struct writer *wr) { struct rd_wr_match *m = ddsrt_malloc (sizeof (*m)); - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; m->wr_guid = wr->e.guid; ddsrt_mutex_lock (&rd->e.lock); - if (ut_avlLookupIPath (&rd_local_writers_treedef, &rd->local_writers, &wr->e.guid, &path)) + if (ddsrt_avl_lookup_ipath (&rd_local_writers_treedef, &rd->local_writers, &wr->e.guid, &path)) { DDS_LOG(DDS_LC_DISCOVERY, " reader_add_local_connection(wr %x:%x:%x:%x rd %x:%x:%x:%x) - already connected\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); ddsrt_mutex_unlock (&rd->e.lock); @@ -1751,7 +1751,7 @@ static void reader_add_local_connection (struct reader *rd, struct writer *wr) else { DDS_LOG(DDS_LC_DISCOVERY, " reader_add_local_connection(wr %x:%x:%x:%x rd %x:%x:%x:%x)\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); - ut_avlInsertIPath (&rd_local_writers_treedef, &rd->local_writers, m, &path); + ddsrt_avl_insert_ipath (&rd_local_writers_treedef, &rd->local_writers, m, &path); ddsrt_mutex_unlock (&rd->e.lock); if (rd->status_cb) @@ -1772,11 +1772,11 @@ static void reader_add_local_connection (struct reader *rd, struct writer *wr) static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader *rd, nn_mtime_t tnow, nn_count_t init_count) { struct pwr_rd_match *m = ddsrt_malloc (sizeof (*m)); - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; seqno_t last_deliv_seq; ddsrt_mutex_lock (&pwr->e.lock); - if (ut_avlLookupIPath (&pwr_readers_treedef, &pwr->readers, &rd->e.guid, &path)) + if (ddsrt_avl_lookup_ipath (&pwr_readers_treedef, &pwr->readers, &rd->e.guid, &path)) goto already_matched; if (pwr->c.topic == NULL && rd->topic) @@ -1816,7 +1816,7 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader { m->in_sync = PRMSS_SYNC; } - else if (!config.conservative_builtin_reader_startup && is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE) && !ut_avlIsEmpty (&pwr->readers)) + else if (!config.conservative_builtin_reader_startup && is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE) && !ddsrt_avl_is_empty (&pwr->readers)) { /* builtins really don't care about multiple copies */ m->in_sync = PRMSS_SYNC; @@ -1860,7 +1860,7 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader nn_reorder_new (NN_REORDER_MODE_MONOTONICALLY_INCREASING, config.secondary_reorder_maxsamples); } - ut_avlInsertIPath (&pwr_readers_treedef, &pwr->readers, m, &path); + ddsrt_avl_insert_ipath (&pwr_readers_treedef, &pwr->readers, m, &path); local_reader_ary_insert(&pwr->rdary, rd); ddsrt_mutex_unlock (&pwr->e.lock); qxev_pwr_entityid (pwr, &rd->e.guid.prefix); @@ -1890,13 +1890,13 @@ already_matched: static void proxy_reader_add_connection (struct proxy_reader *prd, struct writer *wr) { struct prd_wr_match *m = ddsrt_malloc (sizeof (*m)); - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; m->wr_guid = wr->e.guid; ddsrt_mutex_lock (&prd->e.lock); if (prd->c.topic == NULL) prd->c.topic = ddsi_sertopic_ref (wr->topic); - if (ut_avlLookupIPath (&prd_writers_treedef, &prd->writers, &wr->e.guid, &path)) + if (ddsrt_avl_lookup_ipath (&prd_writers_treedef, &prd->writers, &wr->e.guid, &path)) { DDS_LOG(DDS_LC_DISCOVERY, " proxy_reader_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x) - already connected\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); @@ -1907,7 +1907,7 @@ static void proxy_reader_add_connection (struct proxy_reader *prd, struct writer { DDS_LOG(DDS_LC_DISCOVERY, " proxy_reader_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x)\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); - ut_avlInsertIPath (&prd_writers_treedef, &prd->writers, m, &path); + ddsrt_avl_insert_ipath (&prd_writers_treedef, &prd->writers, m, &path); ddsrt_mutex_unlock (&prd->e.lock); qxev_prd_entityid (prd, &wr->e.guid.prefix); } @@ -2539,15 +2539,15 @@ static void augment_wr_prd_match (void *vnode, const void *vleft, const void *vr seqno_t writer_max_drop_seq (const struct writer *wr) { const struct wr_prd_match *n; - if (ut_avlIsEmpty (&wr->readers)) + if (ddsrt_avl_is_empty (&wr->readers)) return wr->seq; - n = ut_avlRootNonEmpty (&wr_readers_treedef, &wr->readers); + n = ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers); return (n->min_seq == MAX_SEQ_NUMBER) ? wr->seq : n->min_seq; } int writer_must_have_hb_scheduled (const struct writer *wr, const struct whc_state *whcst) { - if (ut_avlIsEmpty (&wr->readers) || whcst->max_seq < 0) + if (ddsrt_avl_is_empty (&wr->readers) || whcst->max_seq < 0) { /* Can't transmit a valid heartbeat if there is no data; and it wouldn't actually be sent anywhere if there are no readers, so @@ -2558,7 +2558,7 @@ int writer_must_have_hb_scheduled (const struct writer *wr, const struct whc_sta a heartbeat if no data is available. */ return 0; } - else if (!((const struct wr_prd_match *) ut_avlRootNonEmpty (&wr_readers_treedef, &wr->readers))->all_have_replied_to_hb) + else if (!((const struct wr_prd_match *) ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers))->all_have_replied_to_hb) { /* Labouring under the belief that heartbeats must be sent regardless of ack state */ @@ -2800,8 +2800,8 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se assert (!is_builtin_entityid(wr->e.guid.entityid, NN_VENDORID_ECLIPSE) || (wr->whc_low == wr->whc_high && wr->whc_low == INT32_MAX)); /* Connection admin */ - ut_avlInit (&wr_readers_treedef, &wr->readers); - ut_avlInit (&wr_local_readers_treedef, &wr->local_readers); + ddsrt_avl_init (&wr_readers_treedef, &wr->readers); + ddsrt_avl_init (&wr_local_readers_treedef, &wr->local_readers); local_reader_ary_init (&wr->rdary); } @@ -2917,17 +2917,17 @@ static void gc_delete_writer (struct gcreq *gcreq) us now, because we can't be found via guid_hash anymore. We therefore need not take lock. */ - while (!ut_avlIsEmpty (&wr->readers)) + while (!ddsrt_avl_is_empty (&wr->readers)) { - struct wr_prd_match *m = ut_avlRootNonEmpty (&wr_readers_treedef, &wr->readers); - ut_avlDelete (&wr_readers_treedef, &wr->readers, m); + struct wr_prd_match *m = ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers); + ddsrt_avl_delete (&wr_readers_treedef, &wr->readers, m); proxy_reader_drop_connection (&m->prd_guid, wr); free_wr_prd_match (m); } - while (!ut_avlIsEmpty (&wr->local_readers)) + while (!ddsrt_avl_is_empty (&wr->local_readers)) { - struct wr_rd_match *m = ut_avlRootNonEmpty (&wr_local_readers_treedef, &wr->local_readers); - ut_avlDelete (&wr_local_readers_treedef, &wr->local_readers, m); + struct wr_rd_match *m = ddsrt_avl_root_non_empty (&wr_local_readers_treedef, &wr->local_readers); + ddsrt_avl_delete (&wr_local_readers_treedef, &wr->local_readers, m); reader_drop_local_connection (&m->rd_guid, wr); free_wr_rd_match (m); } @@ -3324,8 +3324,8 @@ static dds_retcode_t new_reader_guid #endif #endif - ut_avlInit (&rd_writers_treedef, &rd->writers); - ut_avlInit (&rd_local_writers_treedef, &rd->local_writers); + ddsrt_avl_init (&rd_writers_treedef, &rd->writers); + ddsrt_avl_init (&rd_local_writers_treedef, &rd->local_writers); ddsrt_mutex_lock (&rd->e.lock); ephash_insert_reader_guid (rd); @@ -3371,17 +3371,17 @@ static void gc_delete_reader (struct gcreq *gcreq) DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_reader(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (rd->e.guid)); gcreq_free (gcreq); - while (!ut_avlIsEmpty (&rd->writers)) + while (!ddsrt_avl_is_empty (&rd->writers)) { - struct rd_pwr_match *m = ut_avlRootNonEmpty (&rd_writers_treedef, &rd->writers); - ut_avlDelete (&rd_writers_treedef, &rd->writers, m); + struct rd_pwr_match *m = ddsrt_avl_root_non_empty (&rd_writers_treedef, &rd->writers); + ddsrt_avl_delete (&rd_writers_treedef, &rd->writers, m); proxy_writer_drop_connection (&m->pwr_guid, rd); free_rd_pwr_match (m); } - while (!ut_avlIsEmpty (&rd->local_writers)) + while (!ddsrt_avl_is_empty (&rd->local_writers)) { - struct rd_wr_match *m = ut_avlRootNonEmpty (&rd_local_writers_treedef, &rd->local_writers); - ut_avlDelete (&rd_local_writers_treedef, &rd->local_writers, m); + struct rd_wr_match *m = ddsrt_avl_root_non_empty (&rd_local_writers_treedef, &rd->local_writers); + ddsrt_avl_delete (&rd_local_writers_treedef, &rd->local_writers, m); writer_drop_local_connection (&m->wr_guid, rd); free_rd_wr_match (m); } @@ -3552,7 +3552,7 @@ void new_proxy_participant proxypp->as_meta = as_meta; proxypp->endpoints = NULL; proxypp->plist = nn_plist_dup (plist); - ut_avlInit (&proxypp_groups_treedef, &proxypp->groups); + ddsrt_avl_init (&proxypp_groups_treedef, &proxypp->groups); if (custom_flags & CF_INC_KERNEL_SEQUENCE_NUMBERS) @@ -3851,8 +3851,8 @@ static void delete_ppt (struct proxy_participant * proxypp, nn_wctime_t timestam proxypp->lease_expired = 1; DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt(%x:%x:%x:%x) - deleting groups\n", PGUID (proxypp->e.guid)); - while (!ut_avlIsEmpty (&proxypp->groups)) - delete_proxy_group_locked (ut_avlRoot (&proxypp_groups_treedef, &proxypp->groups), timestamp, isimplicit); + while (!ddsrt_avl_is_empty (&proxypp->groups)) + delete_proxy_group_locked (ddsrt_avl_root (&proxypp_groups_treedef, &proxypp->groups), timestamp, isimplicit); DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt(%x:%x:%x:%x) - deleting endpoints\n", PGUID (proxypp->e.guid)); c = proxypp->endpoints; @@ -3965,7 +3965,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct else { struct proxy_group *pgroup; - ut_avlIPath_t ipath; + ddsrt_avl_ipath_t ipath; int is_sub; switch (guid->entityid.u & (NN_ENTITYID_SOURCE_MASK | NN_ENTITYID_KIND_MASK)) { @@ -3980,7 +3980,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct return Q_ERR_INVALID_DATA; } ddsrt_mutex_lock (&proxypp->e.lock); - if ((pgroup = ut_avlLookupIPath (&proxypp_groups_treedef, &proxypp->groups, guid, &ipath)) != NULL) + if ((pgroup = ddsrt_avl_lookup_ipath (&proxypp_groups_treedef, &proxypp->groups, guid, &ipath)) != NULL) { /* Complete proxy group definition if it was a partial definition made by creating a proxy reader or writer, @@ -3997,7 +3997,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct pgroup->proxypp = proxypp; pgroup->name = NULL; pgroup->xqos = NULL; - ut_avlInsertIPath (&proxypp_groups_treedef, &proxypp->groups, pgroup, &ipath); + ddsrt_avl_insert_ipath (&proxypp_groups_treedef, &proxypp->groups, pgroup, &ipath); } if (name) { @@ -4021,7 +4021,7 @@ static void delete_proxy_group_locked (struct proxy_group *pgroup, nn_wctime_t t (void)isimplicit; assert ((pgroup->xqos != NULL) == (pgroup->name != NULL)); DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_group_locked %x:%x:%x:%x\n", PGUID (pgroup->guid)); - ut_avlDelete (&proxypp_groups_treedef, &proxypp->groups, pgroup); + ddsrt_avl_delete (&proxypp_groups_treedef, &proxypp->groups, pgroup); /* Publish corresponding built-in topic only if it is not a place holder: in that case we haven't announced its presence and therefore don't need to dispose it, and this saves us from having @@ -4046,7 +4046,7 @@ void delete_proxy_group (const nn_guid_t *guid, nn_wctime_t timestamp, int isimp { struct proxy_group *pgroup; ddsrt_mutex_lock (&proxypp->e.lock); - if ((pgroup = ut_avlLookup (&proxypp_groups_treedef, &proxypp->groups, guid)) != NULL) + if ((pgroup = ddsrt_avl_lookup (&proxypp_groups_treedef, &proxypp->groups, guid)) != NULL) delete_proxy_group_locked (pgroup, timestamp, isimplicit); ddsrt_mutex_unlock (&proxypp->e.lock); } @@ -4112,7 +4112,7 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, pwr = ddsrt_malloc (sizeof (*pwr)); proxy_endpoint_common_init (&pwr->e, &pwr->c, EK_PROXY_WRITER, guid, timestamp, proxypp, as, plist); - ut_avlInit (&pwr_readers_treedef, &pwr->readers); + ddsrt_avl_init (&pwr_readers_treedef, &pwr->readers); pwr->n_reliable_readers = 0; pwr->n_readers_out_of_sync = 0; pwr->last_seq = 0; @@ -4195,7 +4195,7 @@ void update_proxy_writer (struct proxy_writer * pwr, struct addrset * as) { struct reader * rd; struct pwr_rd_match * m; - ut_avlIter_t iter; + ddsrt_avl_iter_t iter; /* Update proxy writer endpoints (from SEDP alive) */ @@ -4208,7 +4208,7 @@ void update_proxy_writer (struct proxy_writer * pwr, struct addrset * as) unref_addrset (pwr->c.as); ref_addrset (as); pwr->c.as = as; - m = ut_avlIterFirst (&pwr_readers_treedef, &pwr->readers, &iter); + m = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &iter); while (m) { rd = ephash_lookup_reader_guid (&m->rd_guid); @@ -4216,7 +4216,7 @@ void update_proxy_writer (struct proxy_writer * pwr, struct addrset * as) { qxev_pwr_entityid (pwr, &rd->e.guid.prefix); } - m = ut_avlIterNext (&iter); + m = ddsrt_avl_iter_next (&iter); } } ddsrt_mutex_unlock (&pwr->e.lock); @@ -4240,14 +4240,14 @@ void update_proxy_reader (struct proxy_reader * prd, struct addrset * as) /* Rebuild writer endpoints */ - while ((m = ut_avlLookupSuccEq (&prd_writers_treedef, &prd->writers, &wrguid)) != NULL) + while ((m = ddsrt_avl_lookup_succ_eq (&prd_writers_treedef, &prd->writers, &wrguid)) != NULL) { struct prd_wr_match *next; nn_guid_t guid_next; struct writer * wr; wrguid = m->wr_guid; - next = ut_avlFindSucc (&prd_writers_treedef, &prd->writers, m); + next = ddsrt_avl_find_succ (&prd_writers_treedef, &prd->writers, m); if (next) { guid_next = next->wr_guid; @@ -4280,10 +4280,10 @@ static void gc_delete_proxy_writer (struct gcreq *gcreq) DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (pwr->e.guid)); gcreq_free (gcreq); - while (!ut_avlIsEmpty (&pwr->readers)) + while (!ddsrt_avl_is_empty (&pwr->readers)) { - struct pwr_rd_match *m = ut_avlRootNonEmpty (&pwr_readers_treedef, &pwr->readers); - ut_avlDelete (&pwr_readers_treedef, &pwr->readers, m); + struct pwr_rd_match *m = ddsrt_avl_root_non_empty (&pwr_readers_treedef, &pwr->readers); + ddsrt_avl_delete (&pwr_readers_treedef, &pwr->readers, m); reader_drop_connection (&m->rd_guid, pwr); update_reader_init_acknack_count (&m->rd_guid, m->count); free_pwr_rd_match (m); @@ -4353,7 +4353,7 @@ int new_proxy_reader (const struct nn_guid *ppguid, const struct nn_guid *guid, "real" participant, rather than the thing we use for endpoints discovered via the DS */ prd->assert_pp_lease = (unsigned) !!config.arrival_of_data_asserts_pp_and_ep_liveliness; - ut_avlInit (&prd_writers_treedef, &prd->writers); + ddsrt_avl_init (&prd_writers_treedef, &prd->writers); /* locking the entity prevents matching while the built-in topic hasn't been published yet */ ddsrt_mutex_lock (&prd->e.lock); @@ -4374,14 +4374,14 @@ static void proxy_reader_set_delete_and_ack_all_messages (struct proxy_reader *p memset (&wrguid, 0, sizeof (wrguid)); ddsrt_mutex_lock (&prd->e.lock); prd->deleting = 1; - while ((m = ut_avlLookupSuccEq (&prd_writers_treedef, &prd->writers, &wrguid)) != NULL) + while ((m = ddsrt_avl_lookup_succ_eq (&prd_writers_treedef, &prd->writers, &wrguid)) != NULL) { /* have to be careful walking the tree -- pretty is different, but I want to check this before I write a lookup_succ function. */ struct prd_wr_match *m_a_next; nn_guid_t wrguid_next; wrguid = m->wr_guid; - if ((m_a_next = ut_avlFindSucc (&prd_writers_treedef, &prd->writers, m)) != NULL) + if ((m_a_next = ddsrt_avl_find_succ (&prd_writers_treedef, &prd->writers, m)) != NULL) wrguid_next = m_a_next->wr_guid; else { @@ -4395,11 +4395,11 @@ static void proxy_reader_set_delete_and_ack_all_messages (struct proxy_reader *p struct whc_node *deferred_free_list = NULL; struct wr_prd_match *m_wr; ddsrt_mutex_lock (&wr->e.lock); - if ((m_wr = ut_avlLookup (&wr_readers_treedef, &wr->readers, &prd->e.guid)) != NULL) + if ((m_wr = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &prd->e.guid)) != NULL) { struct whc_state whcst; m_wr->seq = MAX_SEQ_NUMBER; - ut_avlAugmentUpdate (&wr_readers_treedef, m_wr); + ddsrt_avl_augment_update (&wr_readers_treedef, m_wr); (void)remove_acked_messages (wr, &whcst, &deferred_free_list); writer_clear_retransmitting (wr); } @@ -4419,10 +4419,10 @@ static void gc_delete_proxy_reader (struct gcreq *gcreq) DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_reader(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (prd->e.guid)); gcreq_free (gcreq); - while (!ut_avlIsEmpty (&prd->writers)) + while (!ddsrt_avl_is_empty (&prd->writers)) { - struct prd_wr_match *m = ut_avlRootNonEmpty (&prd_writers_treedef, &prd->writers); - ut_avlDelete (&prd_writers_treedef, &prd->writers, m); + struct prd_wr_match *m = ddsrt_avl_root_non_empty (&prd_writers_treedef, &prd->writers); + ddsrt_avl_delete (&prd_writers_treedef, &prd->writers, m); writer_drop_connection (&m->wr_guid, prd); free_prd_wr_match (m); } diff --git a/src/core/ddsi/src/q_ephash.c b/src/core/ddsi/src/q_ephash.c index f287aae..d02fcba 100644 --- a/src/core/ddsi/src/q_ephash.c +++ b/src/core/ddsi/src/q_ephash.c @@ -15,7 +15,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/misc.h" -#include "dds/util/ut_hopscotch.h" +#include "dds/ddsrt/hopscotch.h" #include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_globals.h" @@ -25,7 +25,7 @@ #include "dds/ddsi/q_thread.h" /* for assert(thread is awake) */ struct ephash { - struct ut_chh *hash; + struct ddsrt_chh *hash; }; static const uint64_t unihashconsts[] = { @@ -80,7 +80,7 @@ struct ephash *ephash_new (void) { struct ephash *ephash; ephash = ddsrt_malloc (sizeof (*ephash)); - ephash->hash = ut_chhNew (32, hash_entity_guid_wrapper, entity_guid_eq_wrapper, gc_buckets); + ephash->hash = ddsrt_chh_new (32, hash_entity_guid_wrapper, entity_guid_eq_wrapper, gc_buckets); if (ephash->hash == NULL) { ddsrt_free (ephash); return NULL; @@ -91,7 +91,7 @@ struct ephash *ephash_new (void) void ephash_free (struct ephash *ephash) { - ut_chhFree (ephash->hash); + ddsrt_chh_free (ephash->hash); ephash->hash = NULL; ddsrt_free (ephash); } @@ -101,7 +101,7 @@ static void ephash_guid_insert (struct entity_common *e) int x; assert(gv.guid_hash); assert(gv.guid_hash->hash); - x = ut_chhAdd (gv.guid_hash->hash, e); + x = ddsrt_chh_add (gv.guid_hash->hash, e); (void)x; assert (x); } @@ -111,7 +111,7 @@ static void ephash_guid_remove (struct entity_common *e) int x; assert(gv.guid_hash); assert(gv.guid_hash->hash); - x = ut_chhRemove (gv.guid_hash->hash, e); + x = ddsrt_chh_remove (gv.guid_hash->hash, e); (void)x; assert (x); } @@ -121,7 +121,7 @@ void *ephash_lookup_guid_untyped (const struct nn_guid *guid) /* FIXME: could (now) require guid to be first in entity_common; entity_common already is first in entity */ struct entity_common e; e.guid = *guid; - return ut_chhLookup (gv.guid_hash->hash, &e); + return ddsrt_chh_lookup (gv.guid_hash->hash, &e); } static void *ephash_lookup_guid_int (const struct ephash *ephash, const struct nn_guid *guid, enum entity_kind kind) @@ -246,9 +246,9 @@ struct proxy_reader *ephash_lookup_proxy_reader_guid (const struct nn_guid *guid static void ephash_enum_init_int (struct ephash_enum *st, struct ephash *ephash, enum entity_kind kind) { st->kind = kind; - st->cur = ut_chhIterFirst (ephash->hash, &st->it); + st->cur = ddsrt_chh_iter_first (ephash->hash, &st->it); while (st->cur && st->cur->kind != st->kind) - st->cur = ut_chhIterNext (&st->it); + st->cur = ddsrt_chh_iter_next (&st->it); } void ephash_enum_init (struct ephash_enum *st, enum entity_kind kind) @@ -291,9 +291,9 @@ void *ephash_enum_next (struct ephash_enum *st) void *res = st->cur; if (st->cur) { - st->cur = ut_chhIterNext (&st->it); + st->cur = ddsrt_chh_iter_next (&st->it); while (st->cur && st->cur->kind != st->kind) - st->cur = ut_chhIterNext (&st->it); + st->cur = ddsrt_chh_iter_next (&st->it); } return res; } diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 0b89411..ee25e6c 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -19,8 +19,8 @@ #include "dds/ddsrt/string.h" #include "dds/ddsrt/sync.h" -#include "dds/util/ut_avl.h" -#include "dds/util/ut_thread_pool.h" +#include "dds/ddsrt/avl.h" +#include "dds/ddsrt/thread_pool.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_rtps.h" @@ -895,7 +895,7 @@ int rtps_init (void) if (config.tp_enable) { - gv.thread_pool = ut_thread_pool_new + gv.thread_pool = ddsrt_thread_pool_new (config.tp_threads, config.tp_max_threads, 0, NULL); } @@ -1357,7 +1357,7 @@ err_find_own_ip: ddsi_tran_factories_fini (); err_udp_tcp_init: if (config.tp_enable) - ut_thread_pool_free (gv.thread_pool); + ddsrt_thread_pool_free (gv.thread_pool); return -1; } @@ -1609,7 +1609,7 @@ void rtps_fini (void) } #endif - ut_thread_pool_free (gv.thread_pool); + ddsrt_thread_pool_free (gv.thread_pool); (void) joinleave_spdp_defmcip (0); diff --git a/src/core/ddsi/src/q_inverse_uint32_set.c b/src/core/ddsi/src/q_inverse_uint32_set.c index 99d24ac..0750425 100644 --- a/src/core/ddsi/src/q_inverse_uint32_set.c +++ b/src/core/ddsi/src/q_inverse_uint32_set.c @@ -12,14 +12,14 @@ #include #include #include "dds/ddsrt/heap.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_inverse_uint32_set.h" static int uint32_t_cmp(const void *va, const void *vb); -static ut_avlTreedef_t inverse_uint32_set_td = UT_AVL_TREEDEF_INITIALIZER(offsetof(struct inverse_uint32_set_node, avlnode), offsetof(struct inverse_uint32_set_node, min), uint32_t_cmp, 0); +static ddsrt_avl_treedef_t inverse_uint32_set_td = DDSRT_AVL_TREEDEF_INITIALIZER(offsetof(struct inverse_uint32_set_node, avlnode), offsetof(struct inverse_uint32_set_node, min), uint32_t_cmp, 0); static int uint32_t_cmp(const void *va, const void *vb) { @@ -31,12 +31,12 @@ static int uint32_t_cmp(const void *va, const void *vb) static void check(const struct inverse_uint32_set *set) { #ifndef NDEBUG - ut_avlIter_t it; + ddsrt_avl_iter_t it; struct inverse_uint32_set_node *pn = NULL, *n; assert(set->min <= set->max); assert(set->cursor >= set->min); assert(set->cursor <= set->max); - for (n = ut_avlIterFirst(&inverse_uint32_set_td, &set->ids, &it); n; pn = n, n = ut_avlIterNext(&it)) + for (n = ddsrt_avl_iter_first(&inverse_uint32_set_td, &set->ids, &it); n; pn = n, n = ddsrt_avl_iter_next(&it)) { assert(n->min <= n->max); assert(n->min >= set->min); @@ -51,20 +51,20 @@ static void check(const struct inverse_uint32_set *set) void inverse_uint32_set_init(struct inverse_uint32_set *set, uint32_t min, uint32_t max) { struct inverse_uint32_set_node *n; - ut_avlInit(&inverse_uint32_set_td, &set->ids); + ddsrt_avl_init(&inverse_uint32_set_td, &set->ids); set->cursor = min; set->min = min; set->max = max; n = ddsrt_malloc(sizeof(*n)); n->min = min; n->max = max; - ut_avlInsert(&inverse_uint32_set_td, &set->ids, n); + ddsrt_avl_insert(&inverse_uint32_set_td, &set->ids, n); check(set); } void inverse_uint32_set_fini(struct inverse_uint32_set *set) { - ut_avlFree(&inverse_uint32_set_td, &set->ids, ddsrt_free); + ddsrt_avl_free(&inverse_uint32_set_td, &set->ids, ddsrt_free); } static uint32_t inverse_uint32_set_alloc_use_min(struct inverse_uint32_set *set, struct inverse_uint32_set_node *n) @@ -72,7 +72,7 @@ static uint32_t inverse_uint32_set_alloc_use_min(struct inverse_uint32_set *set, const uint32_t id = n->min; if (n->min == n->max) { - ut_avlDelete(&inverse_uint32_set_td, &set->ids, n); + ddsrt_avl_delete(&inverse_uint32_set_td, &set->ids, n); ddsrt_free(n); } else @@ -86,7 +86,7 @@ static uint32_t inverse_uint32_set_alloc_use_min(struct inverse_uint32_set *set, int inverse_uint32_set_alloc(uint32_t * const id, struct inverse_uint32_set *set) { struct inverse_uint32_set_node *n; - if ((n = ut_avlLookupPredEq(&inverse_uint32_set_td, &set->ids, &set->cursor)) != NULL && set->cursor <= n->max) { + if ((n = ddsrt_avl_lookup_pred_eq(&inverse_uint32_set_td, &set->ids, &set->cursor)) != NULL && set->cursor <= n->max) { /* n is [a,b] s.t. a <= C <= b, so C is available */ *id = set->cursor; if (n->min == set->cursor) @@ -105,15 +105,15 @@ int inverse_uint32_set_alloc(uint32_t * const id, struct inverse_uint32_set *set n1->min = set->cursor + 1; n1->max = n->max; n->max = set->cursor - 1; - ut_avlInsert(&inverse_uint32_set_td, &set->ids, n1); + ddsrt_avl_insert(&inverse_uint32_set_td, &set->ids, n1); } } - else if ((n = ut_avlLookupSucc(&inverse_uint32_set_td, &set->ids, &set->cursor)) != NULL) + else if ((n = ddsrt_avl_lookup_succ(&inverse_uint32_set_td, &set->ids, &set->cursor)) != NULL) { /* n is [a,b] s.t. a > C and all intervals [a',b'] in tree have a' <= C */ *id = inverse_uint32_set_alloc_use_min(set, n); } - else if ((n = ut_avlFindMin(&inverse_uint32_set_td, &set->ids)) != NULL) + else if ((n = ddsrt_avl_find_min(&inverse_uint32_set_td, &set->ids)) != NULL) { /* no available ids >= cursor: wrap around and use the first available */ assert(n->max < set->cursor); @@ -133,8 +133,8 @@ void inverse_uint32_set_free(struct inverse_uint32_set *set, uint32_t id) { struct inverse_uint32_set_node *n; const uint32_t idp1 = id + 1; - ut_avlIPath_t ip; - if ((n = ut_avlLookupPredEq(&inverse_uint32_set_td, &set->ids, &id)) != NULL && id <= n->max + 1) { + ddsrt_avl_ipath_t ip; + if ((n = ddsrt_avl_lookup_pred_eq(&inverse_uint32_set_td, &set->ids, &id)) != NULL && id <= n->max + 1) { if (id <= n->max) { /* n is [a,b] s.t. a <= I <= b: so it is already in the set */ @@ -143,18 +143,18 @@ void inverse_uint32_set_free(struct inverse_uint32_set *set, uint32_t id) else { struct inverse_uint32_set_node *n1; - ut_avlDPath_t dp; + ddsrt_avl_dpath_t dp; /* grow the interval, possibly coalesce with next */ - if ((n1 = ut_avlLookupDPath(&inverse_uint32_set_td, &set->ids, &idp1, &dp)) == NULL) { + if ((n1 = ddsrt_avl_lookup_dpath(&inverse_uint32_set_td, &set->ids, &idp1, &dp)) == NULL) { n->max = id; } else { n->max = n1->max; - ut_avlDeleteDPath(&inverse_uint32_set_td, &set->ids, n1, &dp); + ddsrt_avl_delete_dpath(&inverse_uint32_set_td, &set->ids, n1, &dp); ddsrt_free(n1); } } } - else if ((n = ut_avlLookupIPath(&inverse_uint32_set_td, &set->ids, &idp1, &ip)) != NULL) { + else if ((n = ddsrt_avl_lookup_ipath(&inverse_uint32_set_td, &set->ids, &idp1, &ip)) != NULL) { /* changing the key in-place here: the key value may be changing, but the structure of the tree is not or the previous case would have applied */ n->min = id; } @@ -163,7 +163,7 @@ void inverse_uint32_set_free(struct inverse_uint32_set *set, uint32_t id) /* no adjacent interval */ n = ddsrt_malloc(sizeof(*n)); n->min = n->max = id; - ut_avlInsertIPath(&inverse_uint32_set_td, &set->ids, n, &ip); + ddsrt_avl_insert_ipath(&inverse_uint32_set_td, &set->ids, n, &ip); } check(set); } diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c index 0e2d99c..22dc1f4 100644 --- a/src/core/ddsi/src/q_lease.c +++ b/src/core/ddsi/src/q_lease.c @@ -16,7 +16,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" -#include "dds/util/ut_fibheap.h" +#include "dds/ddsrt/fibheap.h" #include "dds/ddsi/ddsi_serdata_default.h" #include "dds/ddsi/q_protocol.h" @@ -44,7 +44,7 @@ #define TSCHED_NOT_ON_HEAP INT64_MIN struct lease { - ut_fibheapNode_t heapnode; + ddsrt_fibheap_node_t heapnode; nn_etime_t tsched; /* access guarded by leaseheap_lock */ nn_etime_t tend; /* access guarded by lock_lease/unlock_lease */ int64_t tdur; /* constant (renew depends on it) */ @@ -53,7 +53,7 @@ struct lease { static int compare_lease_tsched (const void *va, const void *vb); -static const ut_fibheapDef_t lease_fhdef = UT_FIBHEAPDEF_INITIALIZER(offsetof (struct lease, heapnode), compare_lease_tsched); +static const ddsrt_fibheap_def_t lease_fhdef = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct lease, heapnode), compare_lease_tsched); static void force_lease_check (void) { @@ -73,13 +73,13 @@ void lease_management_init (void) ddsrt_mutex_init (&gv.leaseheap_lock); for (i = 0; i < N_LEASE_LOCKS; i++) ddsrt_mutex_init (&gv.lease_locks[i]); - ut_fibheapInit (&lease_fhdef, &gv.leaseheap); + ddsrt_fibheap_init (&lease_fhdef, &gv.leaseheap); } void lease_management_term (void) { int i; - assert (ut_fibheapMin (&lease_fhdef, &gv.leaseheap) == NULL); + assert (ddsrt_fibheap_min (&lease_fhdef, &gv.leaseheap) == NULL); for (i = 0; i < N_LEASE_LOCKS; i++) ddsrt_mutex_destroy (&gv.lease_locks[i]); ddsrt_mutex_destroy (&gv.leaseheap_lock); @@ -125,7 +125,7 @@ void lease_register (struct lease *l) if (l->tend.v != T_NEVER) { l->tsched = l->tend; - ut_fibheapInsert (&lease_fhdef, &gv.leaseheap, l); + ddsrt_fibheap_insert (&lease_fhdef, &gv.leaseheap, l); } unlock_lease (l); ddsrt_mutex_unlock (&gv.leaseheap_lock); @@ -139,7 +139,7 @@ void lease_free (struct lease *l) DDS_TRACE("lease_free(l %p guid %x:%x:%x:%x)\n", (void *) l, PGUID (l->entity->guid)); ddsrt_mutex_lock (&gv.leaseheap_lock); if (l->tsched.v != TSCHED_NOT_ON_HEAP) - ut_fibheapDelete (&lease_fhdef, &gv.leaseheap, l); + ddsrt_fibheap_delete (&lease_fhdef, &gv.leaseheap, l); ddsrt_mutex_unlock (&gv.leaseheap_lock); ddsrt_free (l); @@ -187,14 +187,14 @@ void lease_set_expiry (struct lease *l, nn_etime_t when) /* moved forward and currently scheduled (by virtue of TSCHED_NOT_ON_HEAP == INT64_MIN) */ l->tsched = l->tend; - ut_fibheapDecreaseKey (&lease_fhdef, &gv.leaseheap, l); + ddsrt_fibheap_decrease_key (&lease_fhdef, &gv.leaseheap, l); trigger = true; } else if (l->tsched.v == TSCHED_NOT_ON_HEAP && l->tend.v < T_NEVER) { /* not currently scheduled, with a finite new expiry time */ l->tsched = l->tend; - ut_fibheapInsert (&lease_fhdef, &gv.leaseheap, l); + ddsrt_fibheap_insert (&lease_fhdef, &gv.leaseheap, l); trigger = true; } unlock_lease (l); @@ -210,13 +210,13 @@ int64_t check_and_handle_lease_expiration (nn_etime_t tnowE) struct lease *l; int64_t delay; ddsrt_mutex_lock (&gv.leaseheap_lock); - while ((l = ut_fibheapMin (&lease_fhdef, &gv.leaseheap)) != NULL && l->tsched.v <= tnowE.v) + while ((l = ddsrt_fibheap_min (&lease_fhdef, &gv.leaseheap)) != NULL && l->tsched.v <= tnowE.v) { nn_guid_t g = l->entity->guid; enum entity_kind k = l->entity->kind; assert (l->tsched.v != TSCHED_NOT_ON_HEAP); - ut_fibheapExtractMin (&lease_fhdef, &gv.leaseheap); + ddsrt_fibheap_extract_min (&lease_fhdef, &gv.leaseheap); lock_lease (l); if (tnowE.v < l->tend.v) @@ -228,7 +228,7 @@ int64_t check_and_handle_lease_expiration (nn_etime_t tnowE) } else { l->tsched = l->tend; unlock_lease (l); - ut_fibheapInsert (&lease_fhdef, &gv.leaseheap, l); + ddsrt_fibheap_insert (&lease_fhdef, &gv.leaseheap, l); } continue; } @@ -270,7 +270,7 @@ int64_t check_and_handle_lease_expiration (nn_etime_t tnowE) PGUID (proxypp->privileged_pp_guid)); l->tsched = l->tend = add_duration_to_etime (tnowE, 200 * T_MILLISECOND); unlock_lease (l); - ut_fibheapInsert (&lease_fhdef, &gv.leaseheap, l); + ddsrt_fibheap_insert (&lease_fhdef, &gv.leaseheap, l); continue; } } diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index c013080..6e8cbef 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -31,7 +31,7 @@ #include "dds/ddsi/q_addrset.h" /* unspec locator */ #include "dds/ddsi/q_feature_check.h" #include "dds/ddsi/ddsi_ipaddr.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" static void print_sockerror (const char *msg) { diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index c7a8222..fed7f43 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -32,7 +32,7 @@ #include "dds/ddsi/q_radmin.h" /* for nn_plist_quickscan */ #include "dds/ddsi/q_static_assert.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_misc.h" /* for vendor_is_... */ /* These are internal to the parameter list processing. We never diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c index 8b49c64..4a739fd 100644 --- a/src/core/ddsi/src/q_radmin.c +++ b/src/core/ddsi/src/q_radmin.c @@ -28,7 +28,7 @@ #include "dds/ddsrt/string.h" #include "dds/ddsrt/log.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_misc.h" @@ -812,7 +812,7 @@ static void nn_rdata_unref (struct nn_rdata *rdata) anyway). */ struct nn_defrag_iv { - ut_avlNode_t avlnode; /* for nn_rsample.defrag::fragtree */ + ddsrt_avl_node_t avlnode; /* for nn_rsample.defrag::fragtree */ uint32_t min, maxp1; struct nn_rdata *first; struct nn_rdata *last; @@ -821,14 +821,14 @@ struct nn_defrag_iv { struct nn_rsample { union { struct nn_rsample_defrag { - ut_avlNode_t avlnode; /* for nn_defrag::sampletree */ - ut_avlTree_t fragtree; + ddsrt_avl_node_t avlnode; /* for nn_defrag::sampletree */ + ddsrt_avl_tree_t fragtree; struct nn_defrag_iv *lastfrag; struct nn_rsample_info *sampleinfo; seqno_t seq; } defrag; struct nn_rsample_reorder { - ut_avlNode_t avlnode; /* for nn_reorder::sampleivtree, if head of a chain */ + ddsrt_avl_node_t avlnode; /* for nn_reorder::sampleivtree, if head of a chain */ struct nn_rsample_chain sc; /* this interval's samples, covering ... */ seqno_t min, maxp1; /* ... seq nos: [min,maxp1), but possibly with holes in it */ uint32_t n_samples; /* so this is the actual length of the chain */ @@ -837,7 +837,7 @@ struct nn_rsample { }; struct nn_defrag { - ut_avlTree_t sampletree; + ddsrt_avl_tree_t sampletree; struct nn_rsample *max_sample; /* = max(sampletree) */ uint32_t n_samples; uint32_t max_samples; @@ -847,8 +847,8 @@ struct nn_defrag { static int compare_uint32 (const void *va, const void *vb); static int compare_seqno (const void *va, const void *vb); -static const ut_avlTreedef_t defrag_sampletree_treedef = UT_AVL_TREEDEF_INITIALIZER (offsetof (struct nn_rsample, u.defrag.avlnode), offsetof (struct nn_rsample, u.defrag.seq), compare_seqno, 0); -static const ut_avlTreedef_t rsample_defrag_fragtree_treedef = UT_AVL_TREEDEF_INITIALIZER (offsetof (struct nn_defrag_iv, avlnode), offsetof (struct nn_defrag_iv, min), compare_uint32, 0); +static const ddsrt_avl_treedef_t defrag_sampletree_treedef = DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct nn_rsample, u.defrag.avlnode), offsetof (struct nn_rsample, u.defrag.seq), compare_seqno, 0); +static const ddsrt_avl_treedef_t rsample_defrag_fragtree_treedef = DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct nn_defrag_iv, avlnode), offsetof (struct nn_defrag_iv, min), compare_uint32, 0); static int compare_uint32 (const void *va, const void *vb) { @@ -870,7 +870,7 @@ struct nn_defrag *nn_defrag_new (enum nn_defrag_drop_mode drop_mode, uint32_t ma assert (max_samples >= 1); if ((d = ddsrt_malloc (sizeof (*d))) == NULL) return NULL; - ut_avlInit (&defrag_sampletree_treedef, &d->sampletree); + ddsrt_avl_init (&defrag_sampletree_treedef, &d->sampletree); d->drop_mode = drop_mode; d->max_samples = max_samples; d->n_samples = 0; @@ -903,25 +903,25 @@ static void defrag_rsample_drop (struct nn_defrag *defrag, struct nn_rsample *rs So we need to walk the fragments while guaranteeing strict "forward progress" in the memory accesses, which this particular inorder treewalk does provide. */ - ut_avlIter_t iter; + ddsrt_avl_iter_t iter; struct nn_defrag_iv *iv; DDS_LOG(DDS_LC_RADMIN, " defrag_rsample_drop (%p, %p)\n", (void *) defrag, (void *) rsample); - ut_avlDelete (&defrag_sampletree_treedef, &defrag->sampletree, rsample); + ddsrt_avl_delete (&defrag_sampletree_treedef, &defrag->sampletree, rsample); assert (defrag->n_samples > 0); defrag->n_samples--; - for (iv = ut_avlIterFirst (&rsample_defrag_fragtree_treedef, &rsample->u.defrag.fragtree, &iter); iv; iv = ut_avlIterNext (&iter)) + for (iv = ddsrt_avl_iter_first (&rsample_defrag_fragtree_treedef, &rsample->u.defrag.fragtree, &iter); iv; iv = ddsrt_avl_iter_next (&iter)) nn_fragchain_rmbias (iv->first); } void nn_defrag_free (struct nn_defrag *defrag) { struct nn_rsample *s; - s = ut_avlFindMin (&defrag_sampletree_treedef, &defrag->sampletree); + s = ddsrt_avl_find_min (&defrag_sampletree_treedef, &defrag->sampletree); while (s) { DDS_LOG(DDS_LC_RADMIN, "defrag_free(%p, sample %p seq %"PRId64")\n", (void *) defrag, (void *) s, s->u.defrag.seq); defrag_rsample_drop (defrag, s); - s = ut_avlFindMin (&defrag_sampletree_treedef, &defrag->sampletree); + s = ddsrt_avl_find_min (&defrag_sampletree_treedef, &defrag->sampletree); } assert (defrag->n_samples == 0); ddsrt_free (defrag); @@ -940,7 +940,7 @@ static int defrag_try_merge_with_succ (struct nn_rsample_defrag *sample, struct return 0; } - succ = ut_avlFindSucc (&rsample_defrag_fragtree_treedef, &sample->fragtree, node); + succ = ddsrt_avl_find_succ (&rsample_defrag_fragtree_treedef, &sample->fragtree, node); assert (succ != NULL); DDS_LOG(DDS_LC_RADMIN, " succ is %p [%u..%u)\n", (void *) succ, succ->min, succ->maxp1); if (succ->min > node->maxp1) @@ -955,7 +955,7 @@ static int defrag_try_merge_with_succ (struct nn_rsample_defrag *sample, struct /* no longer a gap between node & succ => succ will be removed from the interval tree and therefore node will become the last interval if succ currently is */ - ut_avlDelete (&rsample_defrag_fragtree_treedef, &sample->fragtree, succ); + ddsrt_avl_delete (&rsample_defrag_fragtree_treedef, &sample->fragtree, succ); if (sample->lastfrag == succ) { DDS_LOG(DDS_LC_RADMIN, " succ is lastfrag\n"); @@ -987,7 +987,7 @@ static int defrag_try_merge_with_succ (struct nn_rsample_defrag *sample, struct } } -static void defrag_rsample_addiv (struct nn_rsample_defrag *sample, struct nn_rdata *rdata, ut_avlIPath_t *path) +static void defrag_rsample_addiv (struct nn_rsample_defrag *sample, struct nn_rdata *rdata, ddsrt_avl_ipath_t *path) { struct nn_defrag_iv *newiv; if ((newiv = nn_rmsg_alloc (rdata->rmsg, sizeof (*newiv))) == NULL) @@ -997,7 +997,7 @@ static void defrag_rsample_addiv (struct nn_rsample_defrag *sample, struct nn_rd newiv->min = rdata->min; newiv->maxp1 = rdata->maxp1; nn_rdata_addbias (rdata); - ut_avlInsertIPath (&rsample_defrag_fragtree_treedef, &sample->fragtree, newiv, path); + ddsrt_avl_insert_ipath (&rsample_defrag_fragtree_treedef, &sample->fragtree, newiv, path); if (sample->lastfrag == NULL || rdata->min > sample->lastfrag->min) sample->lastfrag = newiv; } @@ -1010,7 +1010,7 @@ static struct nn_rsample *defrag_rsample_new (struct nn_rdata *rdata, const stru { struct nn_rsample *rsample; struct nn_rsample_defrag *dfsample; - ut_avlIPath_t ivpath; + ddsrt_avl_ipath_t ivpath; if ((rsample = nn_rmsg_alloc (rdata->rmsg, sizeof (*rsample))) == NULL) return NULL; @@ -1022,7 +1022,7 @@ static struct nn_rsample *defrag_rsample_new (struct nn_rdata *rdata, const stru return NULL; *dfsample->sampleinfo = *sampleinfo; - ut_avlInit (&rsample_defrag_fragtree_treedef, &dfsample->fragtree); + ddsrt_avl_init (&rsample_defrag_fragtree_treedef, &dfsample->fragtree); /* add sentinel if rdata is not the first fragment of the message */ if (rdata->min > 0) @@ -1032,12 +1032,12 @@ static struct nn_rsample *defrag_rsample_new (struct nn_rdata *rdata, const stru return NULL; sentinel->first = sentinel->last = NULL; sentinel->min = sentinel->maxp1 = 0; - ut_avlLookupIPath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &sentinel->min, &ivpath); - ut_avlInsertIPath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, sentinel, &ivpath); + ddsrt_avl_lookup_ipath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &sentinel->min, &ivpath); + ddsrt_avl_insert_ipath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, sentinel, &ivpath); } /* add an interval for the first received fragment */ - ut_avlLookupIPath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &rdata->min, &ivpath); + ddsrt_avl_lookup_ipath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &rdata->min, &ivpath); defrag_rsample_addiv (dfsample, rdata, &ivpath); return rsample; } @@ -1084,7 +1084,7 @@ static int is_complete (const struct nn_rsample_defrag *sample) one interval covering all bytes. One interval because of the greedy coalescing in add_fragment(). There is at least one interval if we get here. */ - const struct nn_defrag_iv *iv = ut_avlRoot (&rsample_defrag_fragtree_treedef, &sample->fragtree); + const struct nn_defrag_iv *iv = ddsrt_avl_root (&rsample_defrag_fragtree_treedef, &sample->fragtree); assert (iv != NULL); if (iv->min == 0 && iv->maxp1 >= sample->sampleinfo->size) { @@ -1094,7 +1094,7 @@ static int is_complete (const struct nn_rsample_defrag *sample) samples that will never be completed; dropping them in the defragmenter would be feasible by discarding all fragments of that sample collected so far. */ - assert (ut_avlIsSingleton (&sample->fragtree)); + assert (ddsrt_avl_is_singleton (&sample->fragtree)); return 1; } else @@ -1111,14 +1111,14 @@ static void rsample_convert_defrag_to_reorder (struct nn_rsample *sample) self-respecting compiler will optimise them away, and any self-respecting CPU would need to copy them via registers anyway because it uses a load-store architecture. */ - struct nn_defrag_iv *iv = ut_avlRootNonEmpty (&rsample_defrag_fragtree_treedef, &sample->u.defrag.fragtree); + struct nn_defrag_iv *iv = ddsrt_avl_root_non_empty (&rsample_defrag_fragtree_treedef, &sample->u.defrag.fragtree); struct nn_rdata *fragchain = iv->first; struct nn_rsample_info *sampleinfo = sample->u.defrag.sampleinfo; struct nn_rsample_chain_elem *sce; seqno_t seq = sample->u.defrag.seq; /* re-use memory fragment interval node for sample chain */ - sce = (struct nn_rsample_chain_elem *) ut_avlRootNonEmpty (&rsample_defrag_fragtree_treedef, &sample->u.defrag.fragtree); + sce = (struct nn_rsample_chain_elem *) ddsrt_avl_root_non_empty (&rsample_defrag_fragtree_treedef, &sample->u.defrag.fragtree); sce->fragchain = fragchain; sce->next = NULL; sce->sampleinfo = sampleinfo; @@ -1145,7 +1145,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct /* there must be a last fragment */ assert (dfsample->lastfrag); /* relatively expensive test: lastfrag, tree must be consistent */ - assert (dfsample->lastfrag == ut_avlFindMax (&rsample_defrag_fragtree_treedef, &dfsample->fragtree)); + assert (dfsample->lastfrag == ddsrt_avl_find_max (&rsample_defrag_fragtree_treedef, &dfsample->fragtree)); DDS_LOG(DDS_LC_RADMIN, " lastfrag %p [%u..%u)\n", (void *) dfsample->lastfrag, @@ -1162,7 +1162,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct else { /* Slow path: find preceding fragment by tree search */ - predeq = ut_avlLookupPredEq (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &min); + predeq = ddsrt_avl_lookup_pred_eq (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &min); assert (predeq); DDS_LOG(DDS_LC_RADMIN, " slow path: predeq = lookup %u => %p [%u..%u)\n", min, (void *) predeq, predeq->min, predeq->maxp1); @@ -1206,7 +1206,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct return is_complete (dfsample) ? sample : NULL; } else if (predeq != dfsample->lastfrag && /* if predeq is last frag, there is no succ */ - (succ = ut_avlFindSucc (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, predeq)) != NULL && + (succ = ddsrt_avl_find_succ (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, predeq)) != NULL && succ->min <= maxp1) { /* extends succ (at the low end; no guarantee each individual @@ -1236,9 +1236,9 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct { /* doesn't extend either predeq at the end or succ at the head => new interval; rdata did not cause completion of sample */ - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; DDS_LOG(DDS_LC_RADMIN, " new interval\n"); - if (ut_avlLookupIPath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &min, &path)) + if (ddsrt_avl_lookup_ipath (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &min, &path)) assert (0); defrag_rsample_addiv (dfsample, rdata, &path); return NULL; @@ -1274,7 +1274,7 @@ static int defrag_limit_samples (struct nn_defrag *defrag, seqno_t seq, seqno_t break; case NN_DEFRAG_DROP_OLDEST: DDS_LOG(DDS_LC_RADMIN, " drop mode = DROP_OLDEST\n"); - sample_to_drop = ut_avlFindMin (&defrag_sampletree_treedef, &defrag->sampletree); + sample_to_drop = ddsrt_avl_find_min (&defrag_sampletree_treedef, &defrag->sampletree); assert (sample_to_drop); if (seq < sample_to_drop->u.defrag.seq) { @@ -1287,7 +1287,7 @@ static int defrag_limit_samples (struct nn_defrag *defrag, seqno_t seq, seqno_t defrag_rsample_drop (defrag, sample_to_drop); if (sample_to_drop == defrag->max_sample) { - defrag->max_sample = ut_avlFindMax (&defrag_sampletree_treedef, &defrag->sampletree); + defrag->max_sample = ddsrt_avl_find_max (&defrag_sampletree_treedef, &defrag->sampletree); *max_seq = defrag->max_sample ? defrag->max_sample->u.defrag.seq : 0; DDS_LOG(DDS_LC_RADMIN, " updating max_sample: now %p %"PRId64"\n", (void *) defrag->max_sample, @@ -1322,7 +1322,7 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata by adding BIAS to the refcount. */ struct nn_rsample *sample, *result; seqno_t max_seq; - ut_avlIPath_t path; + ddsrt_avl_ipath_t path; assert (defrag->n_samples <= defrag->max_samples); @@ -1334,7 +1334,7 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata /* max_seq is used for the fast path, and is 0 when there is no last message in 'defrag'. max_seq and max_sample must be consistent. Max_sample must be consistent with tree */ - assert (defrag->max_sample == ut_avlFindMax (&defrag_sampletree_treedef, &defrag->sampletree)); + assert (defrag->max_sample == ddsrt_avl_find_max (&defrag_sampletree_treedef, &defrag->sampletree)); max_seq = defrag->max_sample ? defrag->max_sample->u.defrag.seq : 0; DDS_LOG(DDS_LC_RADMIN, "defrag_rsample(%p, %p [%u..%u) msg %p, %p seq %"PRId64" size %u) max_seq %p %"PRId64":\n", (void *) defrag, (void *) rdata, rdata->min, rdata->maxp1, (void *) rdata->rmsg, @@ -1358,22 +1358,22 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata child of the old maximum node */ /* FIXME: MERGE THIS ONE WITH THE NEXT */ DDS_LOG(DDS_LC_RADMIN, " new max sample\n"); - ut_avlLookupIPath (&defrag_sampletree_treedef, &defrag->sampletree, &sampleinfo->seq, &path); + ddsrt_avl_lookup_ipath (&defrag_sampletree_treedef, &defrag->sampletree, &sampleinfo->seq, &path); if ((sample = defrag_rsample_new (rdata, sampleinfo)) == NULL) return NULL; - ut_avlInsertIPath (&defrag_sampletree_treedef, &defrag->sampletree, sample, &path); + ddsrt_avl_insert_ipath (&defrag_sampletree_treedef, &defrag->sampletree, sample, &path); defrag->max_sample = sample; defrag->n_samples++; result = NULL; } - else if ((sample = ut_avlLookupIPath (&defrag_sampletree_treedef, &defrag->sampletree, &sampleinfo->seq, &path)) == NULL) + else if ((sample = ddsrt_avl_lookup_ipath (&defrag_sampletree_treedef, &defrag->sampletree, &sampleinfo->seq, &path)) == NULL) { /* a new sequence number, but smaller than the maximum */ DDS_LOG(DDS_LC_RADMIN, " new sample less than max\n"); assert (sampleinfo->seq < max_seq); if ((sample = defrag_rsample_new (rdata, sampleinfo)) == NULL) return NULL; - ut_avlInsertIPath (&defrag_sampletree_treedef, &defrag->sampletree, sample, &path); + ddsrt_avl_insert_ipath (&defrag_sampletree_treedef, &defrag->sampletree, sample, &path); defrag->n_samples++; result = NULL; } @@ -1390,12 +1390,12 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata reorder format. If it is the sample with the maximum sequence in the tree, an update of max_sample is required. */ DDS_LOG(DDS_LC_RADMIN, " complete\n"); - ut_avlDelete (&defrag_sampletree_treedef, &defrag->sampletree, result); + ddsrt_avl_delete (&defrag_sampletree_treedef, &defrag->sampletree, result); assert (defrag->n_samples > 0); defrag->n_samples--; if (result == defrag->max_sample) { - defrag->max_sample = ut_avlFindMax (&defrag_sampletree_treedef, &defrag->sampletree); + defrag->max_sample = ddsrt_avl_find_max (&defrag_sampletree_treedef, &defrag->sampletree); DDS_LOG(DDS_LC_RADMIN, " updating max_sample: now %p %"PRId64"\n", (void *) defrag->max_sample, defrag->max_sample ? defrag->max_sample->u.defrag.seq : 0); @@ -1403,7 +1403,7 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata rsample_convert_defrag_to_reorder (result); } - assert (defrag->max_sample == ut_avlFindMax (&defrag_sampletree_treedef, &defrag->sampletree)); + assert (defrag->max_sample == ddsrt_avl_find_max (&defrag_sampletree_treedef, &defrag->sampletree)); return result; } @@ -1412,14 +1412,14 @@ void nn_defrag_notegap (struct nn_defrag *defrag, seqno_t min, seqno_t maxp1) /* All sequence numbers in [min,maxp1) are unavailable so any fragments in that range must be discarded. Used both for Hearbeats (by setting min=1) and for Gaps. */ - struct nn_rsample *s = ut_avlLookupSuccEq (&defrag_sampletree_treedef, &defrag->sampletree, &min); + struct nn_rsample *s = ddsrt_avl_lookup_succ_eq (&defrag_sampletree_treedef, &defrag->sampletree, &min); while (s && s->u.defrag.seq < maxp1) { - struct nn_rsample *s1 = ut_avlFindSucc (&defrag_sampletree_treedef, &defrag->sampletree, s); + struct nn_rsample *s1 = ddsrt_avl_find_succ (&defrag_sampletree_treedef, &defrag->sampletree, s); defrag_rsample_drop (defrag, s); s = s1; } - defrag->max_sample = ut_avlFindMax (&defrag_sampletree_treedef, &defrag->sampletree); + defrag->max_sample = ddsrt_avl_find_max (&defrag_sampletree_treedef, &defrag->sampletree); } int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnum, struct nn_fragment_number_set *map, uint32_t maxsz) @@ -1428,7 +1428,7 @@ int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnu struct nn_defrag_iv *iv; uint32_t i, fragsz, nfrags; assert (maxsz <= 256); - s = ut_avlLookup (&defrag_sampletree_treedef, &defrag->sampletree, &seq); + s = ddsrt_avl_lookup (&defrag_sampletree_treedef, &defrag->sampletree, &seq); if (s == NULL) { if (maxfragnum == UINT32_MAX) @@ -1465,7 +1465,7 @@ int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnu are missing the first fragment. */ struct nn_defrag_iv *liv = s->u.defrag.lastfrag; nn_fragment_number_t map_end; - iv = ut_avlFindMin (&rsample_defrag_fragtree_treedef, &s->u.defrag.fragtree); + iv = ddsrt_avl_find_min (&rsample_defrag_fragtree_treedef, &s->u.defrag.fragtree); assert (iv != NULL); /* iv is first interval, iv->maxp1 is first byte beyond that => divide by fragsz to get first missing fragment */ @@ -1485,7 +1485,7 @@ int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnu map->bitmap_base, but there is nothing to request in that case. */ map->numbits = (map_end < map->bitmap_base) ? 0 : map_end - map->bitmap_base + 1; - iv = ut_avlFindSucc (&rsample_defrag_fragtree_treedef, &s->u.defrag.fragtree, iv); + iv = ddsrt_avl_find_succ (&rsample_defrag_fragtree_treedef, &s->u.defrag.fragtree, iv); } /* Clear bitmap, then set bits for gaps in available fragments */ @@ -1515,7 +1515,7 @@ int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnu at fragment containing maxp1 (because we don't have that byte yet), and runs until the next interval begins */ i = iv->maxp1 / fragsz; - iv = ut_avlFindSucc (&rsample_defrag_fragtree_treedef, &s->u.defrag.fragtree, iv); + iv = ddsrt_avl_find_succ (&rsample_defrag_fragtree_treedef, &s->u.defrag.fragtree, iv); } /* and set bits for missing fragments beyond the highest interval */ for (; i < map->bitmap_base + map->numbits; i++) @@ -1603,7 +1603,7 @@ int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnu in the overview comment at the top of this file. */ struct nn_reorder { - ut_avlTree_t sampleivtree; + ddsrt_avl_tree_t sampleivtree; struct nn_rsample *max_sampleiv; /* = max(sampleivtree) */ seqno_t next_seq; enum nn_reorder_mode mode; @@ -1611,15 +1611,15 @@ struct nn_reorder { uint32_t n_samples; }; -static const ut_avlTreedef_t reorder_sampleivtree_treedef = - UT_AVL_TREEDEF_INITIALIZER (offsetof (struct nn_rsample, u.reorder.avlnode), offsetof (struct nn_rsample, u.reorder.min), compare_seqno, 0); +static const ddsrt_avl_treedef_t reorder_sampleivtree_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct nn_rsample, u.reorder.avlnode), offsetof (struct nn_rsample, u.reorder.min), compare_seqno, 0); struct nn_reorder *nn_reorder_new (enum nn_reorder_mode mode, uint32_t max_samples) { struct nn_reorder *r; if ((r = ddsrt_malloc (sizeof (*r))) == NULL) return NULL; - ut_avlInit (&reorder_sampleivtree_treedef, &r->sampleivtree); + ddsrt_avl_init (&reorder_sampleivtree_treedef, &r->sampleivtree); r->max_sampleiv = NULL; r->next_seq = 1; r->mode = mode; @@ -1644,10 +1644,10 @@ void nn_reorder_free (struct nn_reorder *r) struct nn_rsample *iv; struct nn_rsample_chain_elem *sce; /* FXIME: instead of findmin/delete, a treewalk can be used. */ - iv = ut_avlFindMin (&reorder_sampleivtree_treedef, &r->sampleivtree); + iv = ddsrt_avl_find_min (&reorder_sampleivtree_treedef, &r->sampleivtree); while (iv) { - ut_avlDelete (&reorder_sampleivtree_treedef, &r->sampleivtree, iv); + ddsrt_avl_delete (&reorder_sampleivtree_treedef, &r->sampleivtree, iv); sce = iv->u.reorder.sc.first; while (sce) { @@ -1655,17 +1655,17 @@ void nn_reorder_free (struct nn_reorder *r) nn_fragchain_unref (sce->fragchain); sce = sce1; } - iv = ut_avlFindMin (&reorder_sampleivtree_treedef, &r->sampleivtree); + iv = ddsrt_avl_find_min (&reorder_sampleivtree_treedef, &r->sampleivtree); } ddsrt_free (r); } static void reorder_add_rsampleiv (struct nn_reorder *reorder, struct nn_rsample *rsample) { - ut_avlIPath_t path; - if (ut_avlLookupIPath (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &rsample->u.reorder.min, &path) != NULL) + ddsrt_avl_ipath_t path; + if (ddsrt_avl_lookup_ipath (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &rsample->u.reorder.min, &path) != NULL) assert (0); - ut_avlInsertIPath (&reorder_sampleivtree_treedef, &reorder->sampleivtree, rsample, &path); + ddsrt_avl_insert_ipath (&reorder_sampleivtree_treedef, &reorder->sampleivtree, rsample, &path); } #ifndef NDEBUG @@ -1713,7 +1713,7 @@ static int reorder_try_append_and_discard (struct nn_reorder *reorder, struct nn appendto->u.reorder.min, appendto->u.reorder.maxp1, (void *) appendto, todiscard->u.reorder.min, todiscard->u.reorder.maxp1, (void *) todiscard); assert (todiscard->u.reorder.min == appendto->u.reorder.maxp1); - ut_avlDelete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, todiscard); + ddsrt_avl_delete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, todiscard); append_rsample_interval (appendto, todiscard); DDS_LOG(DDS_LC_RADMIN, " try_append_and_discard: max_sampleiv needs update? %s\n", (todiscard == reorder->max_sampleiv) ? "yes" : "no"); @@ -1793,8 +1793,8 @@ static void delete_last_sample (struct nn_reorder *reorder) recalc max_sampleiv. */ DDS_LOG(DDS_LC_RADMIN, " delete_last_sample: in singleton interval\n"); fragchain = last->sc.first->fragchain; - ut_avlDelete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, reorder->max_sampleiv); - reorder->max_sampleiv = ut_avlFindMax (&reorder_sampleivtree_treedef, &reorder->sampleivtree); + ddsrt_avl_delete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, reorder->max_sampleiv); + reorder->max_sampleiv = ddsrt_avl_find_max (&reorder_sampleivtree_treedef, &reorder->sampleivtree); /* No harm done if it the sampleivtree is empty, except that we chose not to allow it */ assert (reorder->max_sampleiv != NULL); @@ -1847,7 +1847,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r seq; max must be set iff the reorder is non-empty. */ #ifndef NDEBUG { - struct nn_rsample *min = ut_avlFindMin (&reorder_sampleivtree_treedef, &reorder->sampleivtree); + struct nn_rsample *min = ddsrt_avl_find_min (&reorder_sampleivtree_treedef, &reorder->sampleivtree); if (min) DDS_LOG(DDS_LC_RADMIN, " min = %"PRId64" @ %p\n", min->u.reorder.min, (void *) min); assert (min == NULL || reorder->next_seq < min->u.reorder.min); @@ -1855,8 +1855,8 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r (reorder->max_sampleiv != NULL && min != NULL)); } #endif - assert ((!!ut_avlIsEmpty (&reorder->sampleivtree)) == (reorder->max_sampleiv == NULL)); - assert (reorder->max_sampleiv == NULL || reorder->max_sampleiv == ut_avlFindMax (&reorder_sampleivtree_treedef, &reorder->sampleivtree)); + assert ((!!ddsrt_avl_is_empty (&reorder->sampleivtree)) == (reorder->max_sampleiv == NULL)); + assert (reorder->max_sampleiv == NULL || reorder->max_sampleiv == ddsrt_avl_find_max (&reorder_sampleivtree_treedef, &reorder->sampleivtree)); assert (reorder->n_samples <= reorder->max_samples); if (reorder->max_sampleiv) DDS_LOG(DDS_LC_RADMIN, " max = [%"PRId64",%"PRId64") @ %p\n", reorder->max_sampleiv->u.reorder.min, reorder->max_sampleiv->u.reorder.maxp1, (void *) reorder->max_sampleiv); @@ -1883,7 +1883,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r out-of-order either ends up here or in discard.) */ if (reorder->max_sampleiv != NULL) { - struct nn_rsample *min = ut_avlFindMin (&reorder_sampleivtree_treedef, &reorder->sampleivtree); + struct nn_rsample *min = ddsrt_avl_find_min (&reorder_sampleivtree_treedef, &reorder->sampleivtree); DDS_LOG(DDS_LC_RADMIN, " try append_and_discard\n"); if (reorder_try_append_and_discard (reorder, rsampleiv, min)) reorder->max_sampleiv = NULL; @@ -1908,7 +1908,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r DDS_LOG(DDS_LC_RADMIN, " discard: too old\n"); return NN_REORDER_TOO_OLD; /* don't want refcount increment */ } - else if (ut_avlIsEmpty (&reorder->sampleivtree)) + else if (ddsrt_avl_is_empty (&reorder->sampleivtree)) { /* else, if nothing's stored simply add this one, max_samples = 0 is technically allowed, and potentially useful, so check for @@ -1989,7 +1989,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r return NN_REORDER_REJECT; } - predeq = ut_avlLookupPredEq (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &s->min); + predeq = ddsrt_avl_lookup_pred_eq (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &s->min); if (predeq) DDS_LOG(DDS_LC_RADMIN, " predeq = [%"PRId64",%"PRId64") @ %p\n", predeq->u.reorder.min, predeq->u.reorder.maxp1, (void *) predeq); @@ -2002,7 +2002,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r return NN_REORDER_REJECT; } - immsucc = ut_avlLookup (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &s->maxp1); + immsucc = ddsrt_avl_lookup (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &s->maxp1); if (immsucc) DDS_LOG(DDS_LC_RADMIN, " immsucc = [%"PRId64",%"PRId64") @ %p\n", immsucc->u.reorder.min, immsucc->u.reorder.maxp1, (void *) immsucc); @@ -2040,7 +2040,7 @@ nn_reorder_result_t nn_reorder_rsample (struct nn_rsample_chain *sc, struct nn_r Therefore, we can swap rsampleiv in for immsucc and avoid the case above. */ rsampleiv->u.reorder = immsucc->u.reorder; - ut_avlSwapNode (&reorder_sampleivtree_treedef, &reorder->sampleivtree, immsucc, rsampleiv); + ddsrt_avl_swap_node (&reorder_sampleivtree_treedef, &reorder->sampleivtree, immsucc, rsampleiv); if (immsucc == reorder->max_sampleiv) reorder->max_sampleiv = rsampleiv; } @@ -2072,12 +2072,12 @@ static struct nn_rsample *coalesce_intervals_touching_range (struct nn_reorder * struct nn_rsample *s, *t; *valuable = 0; /* Find first (lowest m) interval [m,n) s.t. n >= min && m <= maxp1 */ - s = ut_avlLookupPredEq (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &min); + s = ddsrt_avl_lookup_pred_eq (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &min); if (s && s->u.reorder.maxp1 >= min) { /* m <= min && n >= min (note: pred of s [m',n') necessarily has n' < m) */ #ifndef NDEBUG - struct nn_rsample *q = ut_avlFindPred (&reorder_sampleivtree_treedef, &reorder->sampleivtree, s); + struct nn_rsample *q = ddsrt_avl_find_pred (&reorder_sampleivtree_treedef, &reorder->sampleivtree, s); assert (q == NULL || q->u.reorder.maxp1 < min); #endif } @@ -2086,15 +2086,15 @@ static struct nn_rsample *coalesce_intervals_touching_range (struct nn_reorder * /* No good, but the first (if s = NULL) or the next one (if s != NULL) may still have m <= maxp1 (m > min is implied now). If not, no such interval. */ - s = ut_avlFindSucc (&reorder_sampleivtree_treedef, &reorder->sampleivtree, s); + s = ddsrt_avl_find_succ (&reorder_sampleivtree_treedef, &reorder->sampleivtree, s); if (!(s && s->u.reorder.min <= maxp1)) return NULL; } /* Append successors [m',n') s.t. m' <= maxp1 to s */ assert (s->u.reorder.min + s->u.reorder.n_samples <= s->u.reorder.maxp1); - while ((t = ut_avlFindSucc (&reorder_sampleivtree_treedef, &reorder->sampleivtree, s)) != NULL && t->u.reorder.min <= maxp1) + while ((t = ddsrt_avl_find_succ (&reorder_sampleivtree_treedef, &reorder->sampleivtree, s)) != NULL && t->u.reorder.min <= maxp1) { - ut_avlDelete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, t); + ddsrt_avl_delete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, t); assert (t->u.reorder.min + t->u.reorder.n_samples <= t->u.reorder.maxp1); append_rsample_interval (s, t); *valuable = 1; @@ -2126,8 +2126,8 @@ static int reorder_insert_gap (struct nn_reorder *reorder, struct nn_rdata *rdat { struct nn_rsample_chain_elem *sce; struct nn_rsample *s; - ut_avlIPath_t path; - if (ut_avlLookupIPath (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &min, &path) != NULL) + ddsrt_avl_ipath_t path; + if (ddsrt_avl_lookup_ipath (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &min, &path) != NULL) assert (0); if ((sce = nn_rmsg_alloc (rdata->rmsg, sizeof (*sce))) == NULL) return 0; @@ -2140,7 +2140,7 @@ static int reorder_insert_gap (struct nn_reorder *reorder, struct nn_rdata *rdat s->u.reorder.min = min; s->u.reorder.maxp1 = maxp1; s->u.reorder.n_samples = 1; - ut_avlInsertIPath (&reorder_sampleivtree_treedef, &reorder->sampleivtree, s, &path); + ddsrt_avl_insert_ipath (&reorder_sampleivtree_treedef, &reorder->sampleivtree, s, &path); return 1; } @@ -2225,7 +2225,7 @@ nn_reorder_result_t nn_reorder_gap (struct nn_rsample_chain *sc, struct nn_reord delete_last_sample (reorder); (*refcount_adjust)++; } - reorder->max_sampleiv = ut_avlFindMax (&reorder_sampleivtree_treedef, &reorder->sampleivtree); + reorder->max_sampleiv = ddsrt_avl_find_max (&reorder_sampleivtree_treedef, &reorder->sampleivtree); return res; } else if (coalesced->u.reorder.min <= reorder->next_seq) @@ -2233,11 +2233,11 @@ nn_reorder_result_t nn_reorder_gap (struct nn_rsample_chain *sc, struct nn_reord DDS_LOG(DDS_LC_RADMIN, " coalesced = [%"PRId64",%"PRId64") @ %p containing %d samples\n", coalesced->u.reorder.min, coalesced->u.reorder.maxp1, (void *) coalesced, coalesced->u.reorder.n_samples); - ut_avlDelete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, coalesced); + ddsrt_avl_delete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, coalesced); if (coalesced->u.reorder.min <= reorder->next_seq) assert (min <= reorder->next_seq); reorder->next_seq = coalesced->u.reorder.maxp1; - reorder->max_sampleiv = ut_avlFindMax (&reorder_sampleivtree_treedef, &reorder->sampleivtree); + reorder->max_sampleiv = ddsrt_avl_find_max (&reorder_sampleivtree_treedef, &reorder->sampleivtree); DDS_LOG(DDS_LC_RADMIN, " next expected: %"PRId64"\n", reorder->next_seq); *sc = coalesced->u.reorder.sc; @@ -2251,7 +2251,7 @@ nn_reorder_result_t nn_reorder_gap (struct nn_rsample_chain *sc, struct nn_reord { DDS_LOG(DDS_LC_RADMIN, " coalesced = [%"PRId64",%"PRId64") @ %p - that is all\n", coalesced->u.reorder.min, coalesced->u.reorder.maxp1, (void *) coalesced); - reorder->max_sampleiv = ut_avlFindMax (&reorder_sampleivtree_treedef, &reorder->sampleivtree); + reorder->max_sampleiv = ddsrt_avl_find_max (&reorder_sampleivtree_treedef, &reorder->sampleivtree); return valuable ? NN_REORDER_ACCEPT : NN_REORDER_REJECT; } } @@ -2264,7 +2264,7 @@ int nn_reorder_wantsample (struct nn_reorder *reorder, seqno_t seq) return 0; /* Find interval that contains seq, if we know seq. We are interested if seq is outside this interval (if any). */ - s = ut_avlLookupPredEq (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &seq); + s = ddsrt_avl_lookup_pred_eq (&reorder_sampleivtree_treedef, &reorder->sampleivtree, &seq); return (s == NULL || s->u.reorder.maxp1 <= seq); } @@ -2307,7 +2307,7 @@ unsigned nn_reorder_nackmap (struct nn_reorder *reorder, seqno_t base, seqno_t m map->numbits = (uint32_t) (maxseq + 1 - base); nn_bitset_zero (map->numbits, map->bits); - if ((iv = ut_avlFindMin (&reorder_sampleivtree_treedef, &reorder->sampleivtree)) != NULL) + if ((iv = ddsrt_avl_find_min (&reorder_sampleivtree_treedef, &reorder->sampleivtree)) != NULL) assert (iv->u.reorder.min > base); i = base; while (iv && i < base + map->numbits) @@ -2318,7 +2318,7 @@ unsigned nn_reorder_nackmap (struct nn_reorder *reorder, seqno_t base, seqno_t m nn_bitset_set (map->numbits, map->bits, x); } i = iv->u.reorder.maxp1; - iv = ut_avlFindSucc (&reorder_sampleivtree_treedef, &reorder->sampleivtree, iv); + iv = ddsrt_avl_find_succ (&reorder_sampleivtree_treedef, &reorder->sampleivtree, iv); } if (notail && i < base + map->numbits) map->numbits = (unsigned) (i - base); diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 8ea8c47..520c334 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -20,7 +20,7 @@ #include "dds/ddsrt/sync.h" #include "dds/ddsrt/string.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds__stream.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_rtps.h" @@ -767,7 +767,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac } ddsrt_mutex_lock (&wr->e.lock); - if ((rn = ut_avlLookup (&wr_readers_treedef, &wr->readers, &src)) == NULL) + if ((rn = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &src)) == NULL) { DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not a connection)", PGUID (src), PGUID (dst)); goto out; @@ -823,7 +823,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac that rn->seq <= wr->seq) */ rn->seq = wr->seq; } - ut_avlAugmentUpdate (&wr_readers_treedef, rn); + ddsrt_avl_augment_update (&wr_readers_treedef, rn); n = remove_acked_messages (wr, &whcst, &deferred_free_list); DDS_TRACE(" ACK%"PRId64" RM%u", n_ack, n); } @@ -850,7 +850,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac that rn->seq <= wr->seq) */ rn->seq = wr->seq; } - ut_avlAugmentUpdate (&wr_readers_treedef, rn); + ddsrt_avl_augment_update (&wr_readers_treedef, rn); DDS_LOG(DDS_LC_THROTTLE, "writer %x:%x:%x:%x considering reader %x:%x:%x:%x responsive again\n", PGUID (wr->e.guid), PGUID (rn->prd_guid)); } @@ -867,7 +867,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac rn->has_replied_to_hb = 1; /* walk the whole tree to ensure all proxy readers for this writer have their unack'ed info updated */ - ut_avlAugmentUpdate (&wr_readers_treedef, rn); + ddsrt_avl_augment_update (&wr_readers_treedef, rn); } if (is_preemptive_ack) { @@ -1075,7 +1075,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac return 1; } -static void handle_forall_destinations (const nn_guid_t *dst, struct proxy_writer *pwr, ut_avlWalk_t fun, void *arg) +static void handle_forall_destinations (const nn_guid_t *dst, struct proxy_writer *pwr, ddsrt_avl_walk_t fun, void *arg) { /* prefix: id: to: 0 0 all matched readers @@ -1093,12 +1093,12 @@ static void handle_forall_destinations (const nn_guid_t *dst, struct proxy_write switch ((haveprefix << 1) | haveid) { case (0 << 1) | 0: /* all: full treewalk */ - ut_avlWalk (&pwr_readers_treedef, &pwr->readers, fun, arg); + ddsrt_avl_walk (&pwr_readers_treedef, &pwr->readers, fun, arg); break; case (0 << 1) | 1: /* all with correct entityid: special filtering treewalk */ { struct pwr_rd_match *wn; - for (wn = ut_avlFindMin (&pwr_readers_treedef, &pwr->readers); wn; wn = ut_avlFindSucc (&pwr_readers_treedef, &pwr->readers, wn)) + for (wn = ddsrt_avl_find_min (&pwr_readers_treedef, &pwr->readers); wn; wn = ddsrt_avl_find_succ (&pwr_readers_treedef, &pwr->readers, wn)) { if (wn->rd_guid.entityid.u == dst->entityid.u) fun (wn, arg); @@ -1110,13 +1110,13 @@ static void handle_forall_destinations (const nn_guid_t *dst, struct proxy_write nn_guid_t a, b; a = *dst; a.entityid.u = 0; b = *dst; b.entityid.u = ~0u; - ut_avlWalkRange (&pwr_readers_treedef, &pwr->readers, &a, &b, fun, arg); + ddsrt_avl_walk_range (&pwr_readers_treedef, &pwr->readers, &a, &b, fun, arg); } break; case (1 << 1) | 1: /* fully addressed: dst should exist (but for removal) */ { struct pwr_rd_match *wn; - if ((wn = ut_avlLookup (&pwr_readers_treedef, &pwr->readers, dst)) != NULL) + if ((wn = ddsrt_avl_lookup (&pwr_readers_treedef, &pwr->readers, dst)) != NULL) fun (wn, arg); } break; @@ -1289,7 +1289,7 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct else nn_dqueue_enqueue (pwr->dqueue, &sc, res); } - for (wn = ut_avlFindMin (&pwr_readers_treedef, &pwr->readers); wn; wn = ut_avlFindSucc (&pwr_readers_treedef, &pwr->readers, wn)) + for (wn = ddsrt_avl_find_min (&pwr_readers_treedef, &pwr->readers); wn; wn = ddsrt_avl_find_succ (&pwr_readers_treedef, &pwr->readers, wn)) if (wn->in_sync != PRMSS_SYNC) { seqno_t last_deliv_seq = 0; @@ -1324,7 +1324,7 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct arg.timestamp = timestamp; arg.tnow = tnow; arg.tnow_mt = now_mt (); - handle_forall_destinations (&dst, pwr, (ut_avlWalk_t) handle_Heartbeat_helper, &arg); + handle_forall_destinations (&dst, pwr, (ddsrt_avl_walk_t) handle_Heartbeat_helper, &arg); DDS_TRACE(")"); ddsrt_mutex_unlock (&pwr->e.lock); @@ -1380,7 +1380,7 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime discover a missing fragment, which differs significantly from handle_Heartbeat's scheduling of an AckNack event when it must respond. Why? Just because. */ - if (ut_avlIsEmpty (&pwr->readers) || pwr->local_matching_inprogress) + if (ddsrt_avl_is_empty (&pwr->readers) || pwr->local_matching_inprogress) DDS_TRACE(" no readers"); else { @@ -1392,19 +1392,19 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime assuming a reliable writer -> unreliable reader is rare, and so scanning the readers is acceptable if the first guess fails */ - m = ut_avlRootNonEmpty (&pwr_readers_treedef, &pwr->readers); + m = ddsrt_avl_root_non_empty (&pwr_readers_treedef, &pwr->readers); if (m->acknack_xevent == NULL) { - m = ut_avlFindMin (&pwr_readers_treedef, &pwr->readers); + m = ddsrt_avl_find_min (&pwr_readers_treedef, &pwr->readers); while (m && m->acknack_xevent == NULL) - m = ut_avlFindSucc (&pwr_readers_treedef, &pwr->readers, m); + m = ddsrt_avl_find_succ (&pwr_readers_treedef, &pwr->readers, m); } } else if (seq < nn_reorder_next_seq (pwr->reorder)) { /* Check out-of-sync readers -- should add a bit to cheaply test whether there are any (usually there aren't) */ - m = ut_avlFindMin (&pwr_readers_treedef, &pwr->readers); + m = ddsrt_avl_find_min (&pwr_readers_treedef, &pwr->readers); while (m) { if ((m->in_sync == PRMSS_OUT_OF_SYNC) && m->acknack_xevent != NULL && nn_reorder_wantsample (m->u.not_in_sync.reorder, seq)) @@ -1414,7 +1414,7 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime reader to decide which fragments to nack */ break; } - m = ut_avlFindSucc (&pwr_readers_treedef, &pwr->readers, m); + m = ddsrt_avl_find_succ (&pwr_readers_treedef, &pwr->readers, m); } } @@ -1495,7 +1495,7 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N } ddsrt_mutex_lock (&wr->e.lock); - if ((rn = ut_avlLookup (&wr_readers_treedef, &wr->readers, &src)) == NULL) + if ((rn = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &src)) == NULL) { DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not a connection", PGUID (src), PGUID (dst)); goto out; @@ -1737,7 +1737,7 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); ddsrt_mutex_lock (&pwr->e.lock); - if ((wn = ut_avlLookup (&pwr_readers_treedef, &pwr->readers, &dst)) == NULL) + if ((wn = ddsrt_avl_lookup (&pwr_readers_treedef, &pwr->readers, &dst)) == NULL) { DDS_TRACE("%x:%x:%x:%x -> %x:%x:%x:%x not a connection)", PGUID (src), PGUID (dst)); ddsrt_mutex_unlock (&pwr->e.lock); @@ -2069,11 +2069,11 @@ retry: we fall back to using the GUIDs so that we can deliver all samples we received from it. As writer being deleted any reliable samples that are rejected are simply discarded. */ - ut_avlIter_t it; + ddsrt_avl_iter_t it; struct pwr_rd_match *m; ddsrt_mutex_unlock (&pwr->rdary.rdary_lock); if (!pwr_locked) ddsrt_mutex_lock (&pwr->e.lock); - for (m = ut_avlIterFirst (&pwr_readers_treedef, &pwr->readers, &it); m != NULL; m = ut_avlIterNext (&it)) + for (m = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &it); m != NULL; m = ddsrt_avl_iter_next (&it)) { struct reader *rd; if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL) @@ -2138,7 +2138,7 @@ static void clean_defrag (struct proxy_writer *pwr) if (pwr->n_readers_out_of_sync > 0) { struct pwr_rd_match *wn; - for (wn = ut_avlFindMin (&pwr_readers_treedef, &pwr->readers); wn != NULL; wn = ut_avlFindSucc (&pwr_readers_treedef, &pwr->readers, wn)) + for (wn = ddsrt_avl_find_min (&pwr_readers_treedef, &pwr->readers); wn != NULL; wn = ddsrt_avl_find_succ (&pwr_readers_treedef, &pwr->readers, wn)) { if (wn->in_sync == PRMSS_OUT_OF_SYNC) { @@ -2199,7 +2199,7 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct return; } - if (ut_avlIsEmpty (&pwr->readers) || pwr->local_matching_inprogress) + if (ddsrt_avl_is_empty (&pwr->readers) || pwr->local_matching_inprogress) { ddsrt_mutex_unlock (&pwr->e.lock); DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x: no readers", PGUID (pwr->e.guid), PGUID (dst)); @@ -2274,9 +2274,9 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct writer may have become in sync with the proxy writer and the writer; those catching up with TL all by themselves go through the "TOO_OLD" path below. */ - ut_avlIter_t it; + ddsrt_avl_iter_t it; struct pwr_rd_match *wn; - for (wn = ut_avlIterFirst (&pwr_readers_treedef, &pwr->readers, &it); wn != NULL; wn = ut_avlIterNext (&it)) + for (wn = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &it); wn != NULL; wn = ddsrt_avl_iter_next (&it)) if (wn->in_sync == PRMSS_TLCATCHUP) maybe_set_reader_in_sync (pwr, wn, sampleinfo->seq); } @@ -2286,7 +2286,7 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct struct pwr_rd_match *wn; struct nn_rsample *rsample_dup = NULL; int reuse_rsample_dup = 0; - for (wn = ut_avlFindMin (&pwr_readers_treedef, &pwr->readers); wn != NULL; wn = ut_avlFindSucc (&pwr_readers_treedef, &pwr->readers, wn)) + for (wn = ddsrt_avl_find_min (&pwr_readers_treedef, &pwr->readers); wn != NULL; wn = ddsrt_avl_find_succ (&pwr_readers_treedef, &pwr->readers, wn)) { nn_reorder_result_t rres2; if (wn->in_sync != PRMSS_OUT_OF_SYNC || sampleinfo->seq > wn->u.not_in_sync.end_of_out_of_sync_seq) @@ -2380,7 +2380,7 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con dst.entityid = msg->readerId; ddsrt_mutex_lock (&pwr->e.lock); - wn = ut_avlLookup (&pwr_readers_treedef, &pwr->readers, &dst); + wn = ddsrt_avl_lookup (&pwr_readers_treedef, &pwr->readers, &dst); gap_was_valuable = handle_one_gap (pwr, wn, sampleinfo->seq, sampleinfo->seq+1, gap, &refc_adjust); nn_fragchain_adjust_refcount (gap, refc_adjust); ddsrt_mutex_unlock (&pwr->e.lock); diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 086187e..4d67295 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -15,7 +15,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_addrset.h" #include "dds/ddsi/q_xmsg.h" @@ -51,12 +51,12 @@ static const struct wr_prd_match *root_rdmatch (const struct writer *wr) { - return ut_avlRoot (&wr_readers_treedef, &wr->readers); + return ddsrt_avl_root (&wr_readers_treedef, &wr->readers); } static int have_reliable_subs (const struct writer *wr) { - if (ut_avlIsEmpty (&wr->readers) || root_rdmatch (wr)->min_seq == MAX_SEQ_NUMBER) + if (ddsrt_avl_is_empty (&wr->readers) || root_rdmatch (wr)->min_seq == MAX_SEQ_NUMBER) return 0; else return 1; @@ -152,7 +152,7 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru /* out of memory at worst slows down traffic */ return NULL; - if (ut_avlIsEmpty (&wr->readers) || wr->num_reliable_readers == 0) + if (ddsrt_avl_is_empty (&wr->readers) || wr->num_reliable_readers == 0) { /* Not really supposed to come here, at least not for the first case. Secondly, there really seems to be little use for @@ -192,9 +192,9 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru DDS_TRACE("unicasting to prd %x:%x:%x:%x ", PGUID (*prd_guid)); DDS_TRACE("(rel-prd %d seq-eq-max %d seq %"PRId64" maxseq %"PRId64")\n", wr->num_reliable_readers, - ut_avlIsEmpty (&wr->readers) ? -1 : root_rdmatch (wr)->num_reliable_readers_where_seq_equals_max, + ddsrt_avl_is_empty (&wr->readers) ? -1 : root_rdmatch (wr)->num_reliable_readers_where_seq_equals_max, wr->seq, - ut_avlIsEmpty (&wr->readers) ? (seqno_t) -1 : root_rdmatch (wr)->max_seq); + ddsrt_avl_is_empty (&wr->readers) ? (seqno_t) -1 : root_rdmatch (wr)->max_seq); if (prd_guid == NULL) { @@ -312,8 +312,8 @@ struct nn_xmsg *writer_hbcontrol_piggyback (struct writer *wr, const struct whc_ PGUID (wr->e.guid), *hbansreq ? "" : " final", (hbc->tsched.v == T_NEVER) ? POS_INFINITY_DOUBLE : (double) (hbc->tsched.v - tnow.v) / 1e9, - ut_avlIsEmpty (&wr->readers) ? -1 : root_rdmatch (wr)->min_seq, - ut_avlIsEmpty (&wr->readers) || root_rdmatch (wr)->all_have_replied_to_hb ? "" : "!", + ddsrt_avl_is_empty (&wr->readers) ? -1 : root_rdmatch (wr)->min_seq, + ddsrt_avl_is_empty (&wr->readers) || root_rdmatch (wr)->all_have_replied_to_hb ? "" : "!", whcst->max_seq, READ_SEQ_XMIT(wr)); } diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index b5d6c86..bbeb9c2 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -16,8 +16,8 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" -#include "dds/util/ut_avl.h" -#include "dds/util/ut_fibheap.h" +#include "dds/ddsrt/avl.h" +#include "dds/ddsrt/fibheap.h" #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_log.h" @@ -70,7 +70,7 @@ enum xeventkind struct xevent { - ut_fibheapNode_t heapnode; + ddsrt_fibheap_node_t heapnode; struct xeventq *evq; nn_mtime_t tsched; enum xeventkind kind; @@ -133,7 +133,7 @@ struct xevent_nt /* xmsg is self-contained / relies on reference counts */ struct nn_xmsg *msg; size_t queued_rexmit_bytes; - ut_avlNode_t msg_avlnode; + ddsrt_avl_node_t msg_avlnode; } msg_rexmit; struct { /* xmsg is self-contained / relies on reference counts */ @@ -143,8 +143,8 @@ struct xevent_nt }; struct xeventq { - ut_fibheap_t xevents; - ut_avlTree_t msg_xevents; + ddsrt_fibheap_t xevents; + ddsrt_avl_tree_t msg_xevents; struct xevent_nt *non_timed_xmit_list_oldest; struct xevent_nt *non_timed_xmit_list_newest; /* undefined if ..._oldest == NULL */ size_t queued_rexmit_bytes; @@ -164,9 +164,9 @@ static nn_mtime_t earliest_in_xeventq (struct xeventq *evq); static int msg_xevents_cmp (const void *a, const void *b); static int compare_xevent_tsched (const void *va, const void *vb); -static const ut_avlTreedef_t msg_xevents_treedef = UT_AVL_TREEDEF_INITIALIZER_INDKEY (offsetof (struct xevent_nt, u.msg_rexmit.msg_avlnode), offsetof (struct xevent_nt, u.msg_rexmit.msg), msg_xevents_cmp, 0); +static const ddsrt_avl_treedef_t msg_xevents_treedef = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY (offsetof (struct xevent_nt, u.msg_rexmit.msg_avlnode), offsetof (struct xevent_nt, u.msg_rexmit.msg), msg_xevents_cmp, 0); -static const ut_fibheapDef_t evq_xevents_fhdef = UT_FIBHEAPDEF_INITIALIZER(offsetof (struct xevent, heapnode), compare_xevent_tsched); +static const ddsrt_fibheap_def_t evq_xevents_fhdef = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct xevent, heapnode), compare_xevent_tsched); static int compare_xevent_tsched (const void *va, const void *vb) { @@ -209,21 +209,21 @@ static struct xevent_nt *lookup_msg (struct xeventq *evq, struct nn_xmsg *msg) { assert (nn_xmsg_kind (msg) == NN_XMSG_KIND_DATA_REXMIT); trace_msg ("lookup-msg", msg); - return ut_avlLookup (&msg_xevents_treedef, &evq->msg_xevents, msg); + return ddsrt_avl_lookup (&msg_xevents_treedef, &evq->msg_xevents, msg); } static void remember_msg (struct xeventq *evq, struct xevent_nt *ev) { assert (ev->kind == XEVK_MSG_REXMIT); trace_msg ("remember-msg", ev->u.msg_rexmit.msg); - ut_avlInsert (&msg_xevents_treedef, &evq->msg_xevents, ev); + ddsrt_avl_insert (&msg_xevents_treedef, &evq->msg_xevents, ev); } static void forget_msg (struct xeventq *evq, struct xevent_nt *ev) { assert (ev->kind == XEVK_MSG_REXMIT); trace_msg ("forget-msg", ev->u.msg_rexmit.msg); - ut_avlDelete (&msg_xevents_treedef, &evq->msg_xevents, ev); + ddsrt_avl_delete (&msg_xevents_treedef, &evq->msg_xevents, ev); } static void add_to_non_timed_xmit_list (struct xeventq *evq, struct xevent_nt *ev) @@ -330,7 +330,7 @@ static void free_xevent_nt (struct xeventq *evq, struct xevent_nt *ev) nn_xmsg_free (ev->u.msg.msg); break; case XEVK_MSG_REXMIT: - assert (ut_avlLookup (&msg_xevents_treedef, &evq->msg_xevents, ev->u.msg_rexmit.msg) == NULL); + assert (ddsrt_avl_lookup (&msg_xevents_treedef, &evq->msg_xevents, ev->u.msg_rexmit.msg) == NULL); update_rexmit_counts (evq, ev); nn_xmsg_free (ev->u.msg_rexmit.msg); break; @@ -351,12 +351,12 @@ void delete_xevent (struct xevent *ev) if (ev->tsched.v != T_NEVER) { ev->tsched.v = TSCHED_DELETE; - ut_fibheapDecreaseKey (&evq_xevents_fhdef, &evq->xevents, ev); + ddsrt_fibheap_decrease_key (&evq_xevents_fhdef, &evq->xevents, ev); } else { ev->tsched.v = TSCHED_DELETE; - ut_fibheapInsert (&evq_xevents_fhdef, &evq->xevents, ev); + ddsrt_fibheap_insert (&evq_xevents_fhdef, &evq->xevents, ev); } /* TSCHED_DELETE is absolute minimum time, so chances are we need to wake up the thread. The superfluous signal is harmless. */ @@ -384,12 +384,12 @@ int resched_xevent_if_earlier (struct xevent *ev, nn_mtime_t tsched) if (ev->tsched.v != T_NEVER) { ev->tsched = tsched; - ut_fibheapDecreaseKey (&evq_xevents_fhdef, &evq->xevents, ev); + ddsrt_fibheap_decrease_key (&evq_xevents_fhdef, &evq->xevents, ev); } else { ev->tsched = tsched; - ut_fibheapInsert (&evq_xevents_fhdef, &evq->xevents, ev); + ddsrt_fibheap_insert (&evq_xevents_fhdef, &evq->xevents, ev); } is_resched = 1; if (tsched.v < tbefore.v) @@ -435,7 +435,7 @@ static nn_mtime_t earliest_in_xeventq (struct xeventq *evq) { struct xevent *min; ASSERT_MUTEX_HELD (&evq->lock); - if ((min = ut_fibheapMin (&evq_xevents_fhdef, &evq->xevents)) != NULL) + if ((min = ddsrt_fibheap_min (&evq_xevents_fhdef, &evq->xevents)) != NULL) return min->tsched; else { @@ -453,7 +453,7 @@ static void qxev_insert (struct xevent *ev) if (ev->tsched.v != T_NEVER) { nn_mtime_t tbefore = earliest_in_xeventq (evq); - ut_fibheapInsert (&evq_xevents_fhdef, &evq->xevents, ev); + ddsrt_fibheap_insert (&evq_xevents_fhdef, &evq->xevents, ev); if (ev->tsched.v < tbefore.v) ddsrt_cond_signal (&evq->cond); } @@ -485,8 +485,8 @@ struct xeventq * xeventq_new /* limit to 2GB to prevent overflow (4GB - 64kB should be ok, too) */ if (max_queued_rexmit_bytes > 2147483648u) max_queued_rexmit_bytes = 2147483648u; - ut_fibheapInit (&evq_xevents_fhdef, &evq->xevents); - ut_avlInit (&msg_xevents_treedef, &evq->msg_xevents); + ddsrt_fibheap_init (&evq_xevents_fhdef, &evq->xevents); + ddsrt_avl_init (&msg_xevents_treedef, &evq->msg_xevents); evq->non_timed_xmit_list_oldest = NULL; evq->non_timed_xmit_list_newest = NULL; evq->terminate = 0; @@ -540,7 +540,7 @@ void xeventq_free (struct xeventq *evq) { struct xevent *ev; assert (evq->ts == NULL); - while ((ev = ut_fibheapExtractMin (&evq_xevents_fhdef, &evq->xevents)) != NULL) + while ((ev = ddsrt_fibheap_extract_min (&evq_xevents_fhdef, &evq->xevents)) != NULL) { if (ev->tsched.v == TSCHED_DELETE || ev->kind != XEVK_CALLBACK) free_xevent (evq, ev); @@ -559,7 +559,7 @@ void xeventq_free (struct xeventq *evq) } while (!non_timed_xmit_list_is_empty(evq)) free_xevent_nt (evq, getnext_from_non_timed_xmit_list (evq)); - assert (ut_avlIsEmpty (&evq->msg_xevents)); + assert (ddsrt_avl_is_empty (&evq->msg_xevents)); ddsrt_cond_destroy (&evq->cond); ddsrt_mutex_destroy (&evq->lock); ddsrt_free (evq); @@ -636,8 +636,8 @@ static void handle_xevk_heartbeat (struct nn_xpack *xp, struct xevent *ev, nn_mt hbansreq ? "" : " final", msg ? "sent" : "suppressed", (t_next.v == T_NEVER) ? POS_INFINITY_DOUBLE : (double)(t_next.v - tnow.v) / 1e9, - ut_avlIsEmpty (&wr->readers) ? (seqno_t) -1 : ((struct wr_prd_match *) ut_avlRootNonEmpty (&wr_readers_treedef, &wr->readers))->min_seq, - ut_avlIsEmpty (&wr->readers) || ((struct wr_prd_match *) ut_avlRootNonEmpty (&wr_readers_treedef, &wr->readers))->all_have_replied_to_hb ? "" : "!", + ddsrt_avl_is_empty (&wr->readers) ? (seqno_t) -1 : ((struct wr_prd_match *) ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers))->min_seq, + ddsrt_avl_is_empty (&wr->readers) || ((struct wr_prd_match *) ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers))->all_have_replied_to_hb ? "" : "!", whcst.max_seq, READ_SEQ_XMIT(wr)); resched_xevent_if_earlier (ev, t_next); wr->hbcontrol.tsched = t_next; @@ -888,7 +888,7 @@ static void handle_xevk_acknack (UNUSED_ARG (struct nn_xpack *xp), struct xevent } ddsrt_mutex_lock (&pwr->e.lock); - if ((rwn = ut_avlLookup (&pwr_readers_treedef, &pwr->readers, &ev->u.acknack.rd_guid)) == NULL) + if ((rwn = ddsrt_avl_lookup (&pwr_readers_treedef, &pwr->readers, &ev->u.acknack.rd_guid)) == NULL) { ddsrt_mutex_unlock (&pwr->e.lock); return; @@ -1322,7 +1322,7 @@ static void handle_xevents (struct thread_state1 * const ts1, struct xeventq *xe { while (earliest_in_xeventq(xevq).v <= tnow.v) { - struct xevent *xev = ut_fibheapExtractMin (&evq_xevents_fhdef, &xevq->xevents); + struct xevent *xev = ddsrt_fibheap_extract_min (&evq_xevents_fhdef, &xevq->xevents); if (xev->tsched.v == TSCHED_DELETE) { free_xevent (xevq, xev); diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 4fc0e57..6e3a6ef 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -23,8 +23,8 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/random.h" -#include "dds/util/ut_avl.h" -#include "dds/util/ut_thread_pool.h" +#include "dds/ddsrt/avl.h" +#include "dds/ddsrt/thread_pool.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_xqos.h" @@ -1340,7 +1340,7 @@ static void nn_xpack_send1_threaded (const nn_locator_t *loc, void * varg) arg->xp = (struct nn_xpack *) varg; arg->loc = loc; ddsrt_atomic_inc32 (&arg->xp->calls); - ut_thread_pool_submit (gv.thread_pool, nn_xpack_send1_thread, arg); + ddsrt_thread_pool_submit (gv.thread_pool, nn_xpack_send1_thread, arg); } static void nn_xpack_send_real (struct nn_xpack * xp) diff --git a/src/core/xtests/CMakeLists.txt b/src/core/xtests/CMakeLists.txt index 0b1d362..02b7bfd 100644 --- a/src/core/xtests/CMakeLists.txt +++ b/src/core/xtests/CMakeLists.txt @@ -18,7 +18,7 @@ target_include_directories( "$" "$") -target_link_libraries(rhc_torture RhcTypes ddsc util) +target_link_libraries(rhc_torture RhcTypes ddsc) add_test( NAME rhc_torture diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index 7830104..404f425 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -78,6 +78,21 @@ list(APPEND sources "${source_path}/strtod.c" "${source_path}/strtol.c") +list(APPEND headers + "${source_path}/dds/ddsrt/avl.h" + "${source_path}/dds/ddsrt/expand_envvars.h" + "${source_path}/dds/ddsrt/fibheap.h" + "${source_path}/dds/ddsrt/hopscotch.h" + "${source_path}/dds/ddsrt/thread_pool.h") + +list(APPEND sources + "${source_path}/avl.c" + "${source_path}/expand_envvars.c" + "${source_path}/fibheap.c" + "${source_path}/hopscotch.c" + "${source_path}/thread_pool.c" + "${source_path}/xmlparser.c") + # Not every target offers the same set of features. For embedded targets the # set of features may even be different between builds. e.g. a FreeRTOS build # could use the lightweight IP stack, but later change to FreeRTOS+TCP. diff --git a/src/ddsrt/include/dds/ddsrt/avl.h b/src/ddsrt/include/dds/ddsrt/avl.h new file mode 100644 index 0000000..a99f206 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/avl.h @@ -0,0 +1,359 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSRT_AVL_H +#define DDSRT_AVL_H + +/* The tree library never performs memory allocations or deallocations internally. + + - Treedef_t: defines the properties of the tree, offsets, + comparison functions, augmented structures, flags -- these are + related to the code/data structure in which the tree is embedded, + and in nearly all cases known at compile time. + - avlTree_t: represents the tree, i.e., pointer to the root. + - avlNode_t: contains the administrative data for a single node in + the tree. + + For a tree node: + struct T { + avlNode_t avlnode; + int key; + }; + by definition, avlnodeoffset == offsetof(struct T, avlnode) and + keyoffset = offsetof(struct T, key). The user of the library only + ever deals in pointers to (in this case) struct T, never with + pointers to the avlNode_t, and the compare function operations on + pointers to keys, in this case pointers to "int"s. If you wish, you + can also do: keyoffset = 0, in which case the compare function + would be operating on struct T's. + + The compare function is assumed to behave just like all compare + functions in the C library: < 0, =0, >0 for left argument less + than, equal to or greater than the right argument. + + The "augment" function is automatically called whenever some of the + children of a node change, as well as when the "augment" function + has been called on some of the children. It allows you to maintain + a "summary" of the subtree -- currently only used in ddsi2e, in one + spot. + + Trees come in various "variants", configured through "treedef" + flags: + - direct/indirect key: direct meaning the key value is embedded in + the structure containing the avlNode_t, indirect meaning a + pointer to the key value is. The compare function doesn't deal + with tree nodes, but with key values. + - re-entrant: in the style of the C library, meaning, the + comparison function gets a user-supplied 3rd argument (in + particular used by mmstat). + - unique keys/duplicate keys: when keys must be unique, some + optimizations apply; it is up to the caller to ensure one doesn't + violate the uniqueness of the keys (it'll happily crash in insert + if you don't); when duplicate keys are allowed, a forward scan of + the tree will visit them in the order of insertion. + + For a tree node: + struct T { + avlnode_t avlnode; + char *key; + }; + you could set the "indirect" flag, and then you simply use + strcmp(), avoiding the need for passing templates in looking up key + values. Much nicer. + + There is also an orthogonal variant that is enforced through the + type system -- note that would be possible for all of the above as + well, but the number of cases simply explodes and none of the above + flags affects the dynamically changing data structures (just the + tree definition), unlike this one. + + - the "C" variant keeps track of the number of nodes in the tree to + support a "count" operation in O(1) time, but is otherwise + identical. + + The various initializer macros and TreedefInit functions should + make sense with this. + + All functions for looking up nodes return NULL if there is no node + satisfying the requirements. + + - Init: initializes a tree (really just: root = NULL, perhaps count = 0) + - Free: calls "freefun" on each node, which may free the node + - FreeArg: as "Free", but with an extra, user-supplied, argument + - Root: returns the root node + - Lookup: returns a node with key value "key" (ref allowdups flag) + - LookupIPath: like Lookup, but also filling an IPath_t structure + for efficient insertion in case of a failed lookup (or inserting + duplicates) + - LookupDPath: like Lookup, but also filling a DPath_t structure + that helps with deleting a node + - LookupPredEq: locates the node with the greatest key value <= "key" + - LookupSuccEq: similar, but smallest key value >= "key" + - LookupPred: similar, < "key" + - LookupSucc: similar, > "key" + - Insert: convenience function: LookupIPath ; InsertIPath + - Delete: convenience function: LookupDPath ; DeleteDPath + - InsertIPath: insert node based on the "path" obtained from LookupIPath + - DeleteDPath: delete node, using information in "path" to do so efficiently + - SwapNode: replace "oldn" by "newn" without modifying the tree + structure (the key need not be equal, but must be + FindPred(oldn).key < newn.key < FindSucc(oldn).key, where a + non-existing predecessor has key -inf and a non-existing + successor has key +inf, and where it is understood that the < + operator becomes <= if allowdups is set + - AugmentUpdate: to be called when something in "node" changes that + affects the subtree "summary" computed by the configured + "augment" function + - IsEmpty: returns 1 if tree is empty, 0 if not + - IsSingleton: returns 1 if tree contains exactly one node, 0 if not + - FindMin: returns the node with the smallest key value in the tree + - FindMax: similar, largest key value + - FindPred: preceding node in in-order treewalk + - FindSucc: similar, following node + + - Walk: calls "f" with user-supplied argument "a" once for each + node, starting at FindMin and ending at FindMax + - ConstWalk: same, but with a const tree + - WalkRange: like Walk, but only visiting nodes with key values in + range [min,max] (that's inclusive) + - ConstWalkRange: same, but with a const tree + - WalkRangeReverse: like WalkRange, but in the reverse direction + - ConstWalkRangeReverse: same, but with a const tree + - IterFirst: starts forward iteration, starting at (and returning) FindMin + - IterSuccEq: similar, starting at LookupSuccEq + - IterSucc: similar, starting at LookupSucc + - IterNext: returns FindSucc(last returned node); may not be called + if preceding IterXXX call on same "iter" returned NULL + + That's all there is to it. + + Note that all calls to Walk(f,a) can be rewritten as: + for(n=IterFirst(&it); n; n=IterNext(&it)) { f(n,a) } + or as + for(n=FindMin(); n; n=FindSucc(n)) { f(n,a) } + + The walk functions and iterators may not alter the tree + structure. If that is desired, the latter can easily be rewritten + as: + n=FindMin() ; while(n) { nn=FindSucc(n); f(n,a); n=nn } + because FindMin/FindSucc doesn't store any information to allow + fast processing. That'll allow every operation, with the obvious + exception of f(n) calling Delete(FindSucc(n)). + + Currently, all trees maintain parent pointers, but it may be worth + doing a separate set without it, as it reduces the size of + avlNode_t. But in that case, the FindMin/FindSucc option would no + longer be a reasonable option because it would be prohibitively + expensive, whereas the IterFirst/IterNext option are alway + efficiently. If one were to do a threaded tree variant, the + implemetantion of IterFirst/IterNext would become absolute trivial + and faster still, but at the cost of significantly more overhead in + memory and updates. */ + +#include +#include + +#include "dds/export.h" +#include "dds/ddsrt/attributes.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +#define DDSRT_AVL_MAX_TREEHEIGHT (12 * sizeof (void *)) + +typedef int (*ddsrt_avl_compare_t) (const void *a, const void *b); +typedef int (*ddsrt_avl_compare_r_t) (const void *a, const void *b, void *arg); +typedef void (*ddsrt_avl_augment_t) (void *node, const void *left, const void *right); +typedef void (*ddsrt_avl_walk_t) (void *node, void *arg); +typedef void (*ddsrt_avl_const_walk_t) (const void *node, void *arg); + +typedef struct ddsrt_avl_node { + struct ddsrt_avl_node *cs[2]; /* 0 = left, 1 = right */ + struct ddsrt_avl_node *parent; + int height; +} ddsrt_avl_node_t; + +#define DDSRT_AVL_TREEDEF_FLAG_INDKEY 1 +#define DDSRT_AVL_TREEDEF_FLAG_R 2 +#define DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS 4 + +typedef struct ddsrt_avl_treedef { +#if defined (__cplusplus) + ddsrt_avl_treedef() {} +#endif + size_t avlnodeoffset; + size_t keyoffset; + union { + ddsrt_avl_compare_t comparekk; + ddsrt_avl_compare_r_t comparekk_r; + } u; + ddsrt_avl_augment_t augment; + uint32_t flags; + void *cmp_arg; /* for _r variant */ +} ddsrt_avl_treedef_t; + +typedef struct ddsrt_avl_ctreedef { + ddsrt_avl_treedef_t t; +} ddsrt_avl_ctreedef_t; + +typedef struct ddsrt_avl_tree { + ddsrt_avl_node_t *root; +} ddsrt_avl_tree_t; + +typedef struct ddsrt_avl_ctree { + ddsrt_avl_tree_t t; + size_t count; +} ddsrt_avl_ctree_t; + +typedef struct ddsrt_avl_path { + int depth; /* total depth of path */ + int pnodeidx; + ddsrt_avl_node_t *parent; /* (nodeidx == 0 ? NULL : *(path[nodeidx-1])) */ + ddsrt_avl_node_t **pnode[DDSRT_AVL_MAX_TREEHEIGHT]; +} ddsrt_avl_path_t; + +typedef struct ddsrt_avl_ipath { + ddsrt_avl_path_t p; +} ddsrt_avl_ipath_t; + +typedef struct ddsrt_avl_dpath { + ddsrt_avl_path_t p; +} ddsrt_avl_dpath_t; + +typedef struct ddsrt_avl_iter { + const ddsrt_avl_treedef_t *td; + ddsrt_avl_node_t *right; + ddsrt_avl_node_t **todop; + ddsrt_avl_node_t *todo[1+DDSRT_AVL_MAX_TREEHEIGHT]; +} ddsrt_avl_iter_t; + +typedef struct ddsrt_avl_citer { + ddsrt_avl_iter_t t; +} ddsrt_avl_citer_t; + +/* avlnodeoffset and keyoffset must both be in [0,2**31-1] */ +#define DDSRT_AVL_TREEDEF_INITIALIZER(avlnodeoffset, keyoffset, comparekk_, augment) { (avlnodeoffset), (keyoffset), { .comparekk = (comparekk_) }, (augment), 0, 0 } +#define DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY(avlnodeoffset, keyoffset, comparekk_, augment) { (avlnodeoffset), (keyoffset), { .comparekk = (comparekk_) }, (augment), DDSRT_AVL_TREEDEF_FLAG_INDKEY, 0 } +#define DDSRT_AVL_TREEDEF_INITIALIZER_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk_, augment) { (avlnodeoffset), (keyoffset), { .comparekk = (comparekk_) }, (augment), DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS, 0 } +#define DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk_, augment) { (avlnodeoffset), (keyoffset), { .comparekk = (comparekk_) }, (augment), DDSRT_AVL_TREEDEF_FLAG_INDKEY|DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS, 0 } +#define DDSRT_AVL_TREEDEF_INITIALIZER_R(avlnodeoffset, keyoffset, comparekk_, cmparg, augment) { (avlnodeoffset), (keyoffset), { .comparekk_r = (comparekk_) }, (augment), DDSRT_AVL_TREEDEF_FLAG_R, (cmparg) } +#define DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY_R(avlnodeoffset, keyoffset, comparekk_, cmparg, augment) { (avlnodeoffset), (keyoffset), { .comparekk_r = (comparekk_) }, (augment), DDSRT_AVL_TREEDEF_FLAG_INDKEY|DDSRT_AVL_TREEDEF_FLAG_R, (cmparg) } +#define DDSRT_AVL_TREEDEF_INITIALIZER_R_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk_, cmparg, augment) { (avlnodeoffset), (keyoffset), { .comparekk_r = (comparekk_) }, (augment), DDSRT_AVL_TREEDEF_FLAG_R|DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS, (cmparg) } +#define DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY_R_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk_, cmparg, augment) { (avlnodeoffset), (keyoffset), { .comparekk_r = (comparekk_) }, (augment), DDSRT_AVL_TREEDEF_FLAG_INDKEY|DDSRT_AVL_TREEDEF_FLAG_R|DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS, (cmparg) } + +/* Not maintaining # nodes */ + +DDS_EXPORT void ddsrt_avl_treedef_init (ddsrt_avl_treedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_compare_t comparekk, ddsrt_avl_augment_t augment, uint32_t flags) ddsrt_nonnull((1,4)); +DDS_EXPORT void ddsrt_avl_treedef_init_r (ddsrt_avl_treedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_compare_r_t comparekk_r, void *cmp_arg, ddsrt_avl_augment_t augment, uint32_t flags) ddsrt_nonnull((1,4)); + +DDS_EXPORT void ddsrt_avl_init (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_free (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void (*freefun) (void *node)) ddsrt_nonnull((1,2)); +DDS_EXPORT void ddsrt_avl_free_arg (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void (*freefun) (void *node, void *arg), void *arg) ddsrt_nonnull((1,2)); + +DDS_EXPORT void *ddsrt_avl_root (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_root_non_empty (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_lookup (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_lookup_ipath (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key, ddsrt_avl_ipath_t *path) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_lookup_dpath (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key, ddsrt_avl_dpath_t *path) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_lookup_pred_eq (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_lookup_succ_eq (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_lookup_pred (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_lookup_succ (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) ddsrt_nonnull_all; + +DDS_EXPORT void ddsrt_avl_insert (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *node) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_delete (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *node) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_insert_ipath (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *node, ddsrt_avl_ipath_t *path) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_delete_dpath (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *node, ddsrt_avl_dpath_t *path) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_swap_node (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *oldn, void *newn) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_augment_update (const ddsrt_avl_treedef_t *td, void *node) ddsrt_nonnull_all; + +DDS_EXPORT int ddsrt_avl_is_empty (const ddsrt_avl_tree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT int ddsrt_avl_is_singleton (const ddsrt_avl_tree_t *tree) ddsrt_nonnull_all; + +DDS_EXPORT void *ddsrt_avl_find_min (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_find_max (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_find_pred (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *vnode) ddsrt_nonnull((1,2)); +DDS_EXPORT void *ddsrt_avl_find_succ (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *vnode) ddsrt_nonnull((1,2)); + +DDS_EXPORT void ddsrt_avl_walk (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, ddsrt_avl_walk_t f, void *a) ddsrt_nonnull((1,2,3)); +DDS_EXPORT void ddsrt_avl_const_walk (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, ddsrt_avl_const_walk_t f, void *a) ddsrt_nonnull((1,2,3)); +DDS_EXPORT void ddsrt_avl_walk_range (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, const void *min, const void *max, ddsrt_avl_walk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); +DDS_EXPORT void ddsrt_avl_const_walk_range (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *min, const void *max, ddsrt_avl_const_walk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); +DDS_EXPORT void ddsrt_avl_walk_range_reverse (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, const void *min, const void *max, ddsrt_avl_walk_t f, void *a) ddsrt_nonnull((1,2,3)); +DDS_EXPORT void ddsrt_avl_const_walk_range_reverse (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *min, const void *max, ddsrt_avl_const_walk_t f, void *a) ddsrt_nonnull((1,2,3)); + +DDS_EXPORT void *ddsrt_avl_iter_first (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, ddsrt_avl_iter_t *iter) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_iter_succ_eq (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, ddsrt_avl_iter_t *iter, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_iter_succ (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, ddsrt_avl_iter_t *iter, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_iter_next (ddsrt_avl_iter_t *iter) ddsrt_nonnull_all; + +/* Maintaining # nodes */ + +#define DDSRT_AVL_CTREEDEF_INITIALIZER(avlnodeoffset, keyoffset, comparekk, augment) { DDSRT_AVL_TREEDEF_INITIALIZER (avlnodeoffset, keyoffset, comparekk, augment) } +#define DDSRT_AVL_CTREEDEF_INITIALIZER_INDKEY(avlnodeoffset, keyoffset, comparekk, augment) { DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY (avlnodeoffset, keyoffset, comparekk, augment) } +#define DDSRT_AVL_CTREEDEF_INITIALIZER_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk, augment) { DDSRT_AVL_TREEDEF_INITIALIZER_ALLOWDUPS (avlnodeoffset, keyoffset, comparekk, augment) } +#define DDSRT_AVL_CTREEDEF_INITIALIZER_INDKEY_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk, augment) { DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY_ALLOWDUPS (avlnodeoffset, keyoffset, comparekk, augment) } +#define DDSRT_AVL_CTREEDEF_INITIALIZER_R(avlnodeoffset, keyoffset, comparekk, cmparg, augment) { DDSRT_AVL_TREEDEF_INITIALIZER_R (avlnodeoffset, keyoffset, comparekk, cmparg, augment) } +#define DDSRT_AVL_CTREEDEF_INITIALIZER_INDKEY_R(avlnodeoffset, keyoffset, comparekk, cmparg, augment) { DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY_R (avlnodeoffset, keyoffset, comparekk, cmparg, augment) } +#define DDSRT_AVL_CTREEDEF_INITIALIZER_R_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk, cmparg, augment) { DDSRT_AVL_TREEDEF_INITIALIZER_R_ALLOWDUPS (avlnodeoffset, keyoffset, comparekk, cmparg, augment) } +#define DDSRT_AVL_CTREEDEF_INITIALIZER_INDKEY_R_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk, cmparg, augment) { DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY_R_ALLOWDUPS (avlnodeoffset, keyoffset, comparekk, cmparg, augment) } + +DDS_EXPORT void ddsrt_avl_ctreedef_init (ddsrt_avl_ctreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_compare_t comparekk, ddsrt_avl_augment_t augment, uint32_t flags) ddsrt_nonnull((1,4)); +DDS_EXPORT void ddsrt_avl_ctreedef_init_r (ddsrt_avl_ctreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_compare_r_t comparekk_r, void *cmp_arg, ddsrt_avl_augment_t augment, uint32_t flags) ddsrt_nonnull((1,4)); + +DDS_EXPORT void ddsrt_avl_cinit (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_cfree (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void (*freefun) (void *node)) ddsrt_nonnull((1,2)); +DDS_EXPORT void ddsrt_avl_cfree_arg (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void (*freefun) (void *node, void *arg), void *arg) ddsrt_nonnull((1,2)); + +DDS_EXPORT void *ddsrt_avl_croot (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_croot_non_empty (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_clookup (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_clookup_ipath (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key, ddsrt_avl_ipath_t *path) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_clookup_dpath (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key, ddsrt_avl_dpath_t *path) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_clookup_pred_eq (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_clookup_succ_eq (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_clookup_pred (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_clookup_succ (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) ddsrt_nonnull_all; + +DDS_EXPORT void ddsrt_avl_cinsert (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *node) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_cdelete (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *node) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_cinsert_ipath (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *node, ddsrt_avl_ipath_t *path) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_cdelete_dpath (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *node, ddsrt_avl_dpath_t *path) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_cswap_node (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *oldn, void *newn) ddsrt_nonnull_all; +DDS_EXPORT void ddsrt_avl_caugment_update (const ddsrt_avl_ctreedef_t *td, void *node) ddsrt_nonnull_all; + +DDS_EXPORT int ddsrt_avl_cis_empty (const ddsrt_avl_ctree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT int ddsrt_avl_cis_singleton (const ddsrt_avl_ctree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT size_t ddsrt_avl_ccount (const ddsrt_avl_ctree_t *tree) ddsrt_nonnull_all; + +DDS_EXPORT void *ddsrt_avl_cfind_min (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_cfind_max (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_cfind_pred (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *vnode) ddsrt_nonnull((1,2)); +DDS_EXPORT void *ddsrt_avl_cfind_succ (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *vnode) ddsrt_nonnull((1,2)); + +DDS_EXPORT void ddsrt_avl_cwalk (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, ddsrt_avl_walk_t f, void *a) ddsrt_nonnull((1,2,3)); +DDS_EXPORT void ddsrt_avl_cconst_walk (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, ddsrt_avl_const_walk_t f, void *a) ddsrt_nonnull((1,2,3)); +DDS_EXPORT void ddsrt_avl_cwalk_range (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, const void *min, const void *max, ddsrt_avl_walk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); +DDS_EXPORT void ddsrt_avl_cconst_walk_range (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *min, const void *max, ddsrt_avl_const_walk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); +DDS_EXPORT void ddsrt_avl_cwalk_range_reverse (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, const void *min, const void *max, ddsrt_avl_walk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); +DDS_EXPORT void ddsrt_avl_cconst_walk_range_reverse (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *min, const void *max, ddsrt_avl_const_walk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); + +DDS_EXPORT void *ddsrt_avl_citer_first (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, ddsrt_avl_citer_t *iter) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_citer_succ_eq (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, ddsrt_avl_citer_t *iter, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_citer_succ (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, ddsrt_avl_citer_t *iter, const void *key) ddsrt_nonnull_all; +DDS_EXPORT void *ddsrt_avl_citer_next (ddsrt_avl_citer_t *iter) ddsrt_nonnull_all; + +#if defined (__cplusplus) +} +#endif + +#endif /* DDSRT_AVL_H */ diff --git a/src/util/include/dds/util/ut_expand_envvars.h b/src/ddsrt/include/dds/ddsrt/expand_envvars.h similarity index 78% rename from src/util/include/dds/util/ut_expand_envvars.h rename to src/ddsrt/include/dds/ddsrt/expand_envvars.h index c101679..d7b66f4 100644 --- a/src/util/include/dds/util/ut_expand_envvars.h +++ b/src/ddsrt/include/dds/ddsrt/expand_envvars.h @@ -9,8 +9,8 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#ifndef UT_EXPAND_ENVVARS_H -#define UT_EXPAND_ENVVARS_H +#ifndef DDSRT_EXPAND_ENVVARS_H +#define DDSRT_EXPAND_ENVVARS_H #include "dds/export.h" @@ -19,10 +19,10 @@ extern "C" { #endif /* Expands ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, but not $X */ - DDS_EXPORT char *ut_expand_envvars(const char *string); + DDS_EXPORT char *ddsrt_expand_envvars(const char *string); /* Expands $X, ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, $ and \ can be escaped with \ */ - DDS_EXPORT char *ut_expand_envvars_sh(const char *string); + DDS_EXPORT char *ddsrt_expand_envvars_sh(const char *string); #if defined (__cplusplus) } diff --git a/src/ddsrt/include/dds/ddsrt/fibheap.h b/src/ddsrt/include/dds/ddsrt/fibheap.h new file mode 100644 index 0000000..4a2c330 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/fibheap.h @@ -0,0 +1,54 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSRT_FIBHEAP_H +#define DDSRT_FIBHEAP_H + +#include + +#include "dds/export.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +typedef struct ddsrt_fibheap_node { + struct ddsrt_fibheap_node *parent, *children; + struct ddsrt_fibheap_node *prev, *next; + unsigned mark: 1; + unsigned degree: 31; +} ddsrt_fibheap_node_t; + +typedef struct ddsrt_fibheap_def { + uintptr_t offset; + int (*cmp) (const void *va, const void *vb); +} ddsrt_fibheap_def_t; + +typedef struct ddsrt_fibheap { + ddsrt_fibheap_node_t *roots; /* points to root with min key value */ +} ddsrt_fibheap_t; + +#define DDSRT_FIBHEAPDEF_INITIALIZER(offset, cmp) { (offset), (cmp) } + +DDS_EXPORT void ddsrt_fibheap_def_init (ddsrt_fibheap_def_t *fhdef, uintptr_t offset, int (*cmp) (const void *va, const void *vb)); +DDS_EXPORT void ddsrt_fibheap_init (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh); +DDS_EXPORT void *ddsrt_fibheap_min (const ddsrt_fibheap_def_t *fhdef, const ddsrt_fibheap_t *fh); +DDS_EXPORT void ddsrt_fibheap_merge (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *a, ddsrt_fibheap_t *b); +DDS_EXPORT void ddsrt_fibheap_insert (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh, const void *vnode); +DDS_EXPORT void ddsrt_fibheap_delete (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh, const void *vnode); +DDS_EXPORT void *ddsrt_fibheap_extract_min (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh); +DDS_EXPORT void ddsrt_fibheap_decrease_key (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh, const void *vnode); /* to be called AFTER decreasing the key */ + +#if defined (__cplusplus) +} +#endif + +#endif /* DDSRT_FIBHEAP_H */ diff --git a/src/ddsrt/include/dds/ddsrt/hopscotch.h b/src/ddsrt/include/dds/ddsrt/hopscotch.h new file mode 100644 index 0000000..24d9213 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/hopscotch.h @@ -0,0 +1,104 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSRT_HOPSCOTCH_H +#define DDSRT_HOPSCOTCH_H + +#include + +#include "dds/export.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +/* Concurrent version */ +struct ddsrt_chh; +struct ddsrt_chh_bucket; +struct ddsrt_chh_iter { + struct ddsrt_chh_bucket *bs; + uint32_t size; + uint32_t cursor; +}; + +/* + * The hopscotch hash table is dependent on a proper functioning hash. + * If the hash function generates a lot of hash collisions, then it will + * not be able to handle that by design. + * It is capable of handling some collisions, but not more than 32 per + * bucket (less, when other hash values are clustered around the + * collision value). + * When proper distributed hash values are generated, then hopscotch + * works nice and quickly. + */ +typedef uint32_t (*ddsrt_hh_hash_fn) (const void *); + +/* + * Hopscotch needs to be able to compare two elements. + * Returns 0 when not equal. + */ +typedef int (*ddsrt_hh_equals_fn) (const void *, const void *); + +/* + * Hopscotch is will resize its internal buckets list when needed. It will + * call this garbage collection function with the old buckets list. The + * caller has to delete the list when it deems it safe to do so. + */ +typedef void (*ddsrt_hh_buckets_gc_fn) (void *); + +DDS_EXPORT struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets); +DDS_EXPORT void ddsrt_chh_free (struct ddsrt_chh * __restrict hh); +DDS_EXPORT void *ddsrt_chh_lookup (struct ddsrt_chh * __restrict rt, const void * __restrict template); +DDS_EXPORT int ddsrt_chh_add (struct ddsrt_chh * __restrict rt, const void * __restrict data); +DDS_EXPORT int ddsrt_chh_remove (struct ddsrt_chh * __restrict rt, const void * __restrict template); +DDS_EXPORT void ddsrt_chh_enum_unsafe (struct ddsrt_chh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */ +void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict rt, struct ddsrt_chh_iter *it); +void *ddsrt_chh_iter_next (struct ddsrt_chh_iter *it); + +/* Sequential version */ +struct ddsrt_hh; + +struct ddsrt_hh_iter { + struct ddsrt_hh *hh; + uint32_t cursor; +}; + +DDS_EXPORT struct ddsrt_hh *ddsrt_hh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals); +DDS_EXPORT void ddsrt_hh_free (struct ddsrt_hh * __restrict hh); +DDS_EXPORT void *ddsrt_hh_lookup (const struct ddsrt_hh * __restrict rt, const void * __restrict template); +DDS_EXPORT int ddsrt_hh_add (struct ddsrt_hh * __restrict rt, const void * __restrict data); +DDS_EXPORT int ddsrt_hh_remove (struct ddsrt_hh * __restrict rt, const void * __restrict template); +DDS_EXPORT void ddsrt_hh_enum (struct ddsrt_hh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */ +DDS_EXPORT void *ddsrt_hh_iter_first (struct ddsrt_hh * __restrict rt, struct ddsrt_hh_iter * __restrict iter); /* may delete nodes */ +DDS_EXPORT void *ddsrt_hh_iter_next (struct ddsrt_hh_iter * __restrict iter); + +/* Sequential version, embedded data */ +struct ddsrt_ehh; + +struct ddsrt_ehh_iter { + struct ddsrt_ehh *hh; + uint32_t cursor; +}; + +DDS_EXPORT struct ddsrt_ehh *ddsrt_ehh_new (size_t elemsz, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals); +DDS_EXPORT void ddsrt_ehh_free (struct ddsrt_ehh * __restrict hh); +DDS_EXPORT void *ddsrt_ehh_lookup (const struct ddsrt_ehh * __restrict rt, const void * __restrict template); +DDS_EXPORT int ddsrt_ehh_add (struct ddsrt_ehh * __restrict rt, const void * __restrict data); +DDS_EXPORT int ddsrt_ehh_remove (struct ddsrt_ehh * __restrict rt, const void * __restrict template); +DDS_EXPORT void ddsrt_ehh_enum (struct ddsrt_ehh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */ +DDS_EXPORT void *ddsrt_ehh_iter_first (struct ddsrt_ehh * __restrict rt, struct ddsrt_ehh_iter * __restrict iter); /* may delete nodes */ +DDS_EXPORT void *ddsrt_ehh_iter_next (struct ddsrt_ehh_iter * __restrict iter); + +#if defined (__cplusplus) +} +#endif + +#endif diff --git a/src/util/include/dds/util/ut_thread_pool.h b/src/ddsrt/include/dds/ddsrt/thread_pool.h similarity index 69% rename from src/util/include/dds/util/ut_thread_pool.h rename to src/ddsrt/include/dds/ddsrt/thread_pool.h index 50863a9..f03fe46 100644 --- a/src/util/include/dds/util/ut_thread_pool.h +++ b/src/ddsrt/include/dds/ddsrt/thread_pool.h @@ -9,8 +9,8 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#ifndef UT_THREAD_POOL_H -#define UT_THREAD_POOL_H +#ifndef DDSRT_THREAD_POOL_H +#define DDSRT_THREAD_POOL_H #include @@ -22,16 +22,16 @@ extern "C" { #endif -typedef struct ut_thread_pool_s *ut_thread_pool; +typedef struct ddsrt_thread_pool_s *ddsrt_thread_pool; /* - ut_thread_pool_new: Creates a new thread pool. Returns NULL if + ddsrt_thread_pool_new: Creates a new thread pool. Returns NULL if cannot create initial set of threads. Threads are created with the optional atribute argument. Additional threads may be created on demand up to max_threads. */ -DDS_EXPORT ut_thread_pool ut_thread_pool_new +DDS_EXPORT ddsrt_thread_pool ddsrt_thread_pool_new ( uint32_t threads, /* Initial number of threads in pool (can be 0) */ uint32_t max_threads, /* Maximum number of threads in pool (0 == infinite) */ @@ -39,25 +39,25 @@ DDS_EXPORT ut_thread_pool ut_thread_pool_new ddsrt_threadattr_t * attr /* Attributes used to create pool threads (can be NULL) */ ); -/* ut_thread_pool_free: Frees pool, destroying threads. */ +/* ddsrt_thread_pool_free: Frees pool, destroying threads. */ -DDS_EXPORT void ut_thread_pool_free (ut_thread_pool pool); +DDS_EXPORT void ddsrt_thread_pool_free (ddsrt_thread_pool pool); -/* ut_thread_pool_purge: Purge threads from pool back to initial set. */ +/* ddsrt_thread_pool_purge: Purge threads from pool back to initial set. */ -DDS_EXPORT void ut_thread_pool_purge (ut_thread_pool pool); +DDS_EXPORT void ddsrt_thread_pool_purge (ddsrt_thread_pool pool); /* - ut_thread_pool_submit: Submit a thread function and associated argument + ddsrt_thread_pool_submit: Submit a thread function and associated argument to be invoked by a thread from the pool. If no threads are available a new thread will be created on demand to handle the function unless the pool thread maximum has been reached, in which case the function is queued. Note that if the pool queue has reached it's maximum DDS_RETCODE_TRY_AGAIN is returned. */ -DDS_EXPORT dds_retcode_t ut_thread_pool_submit +DDS_EXPORT dds_retcode_t ddsrt_thread_pool_submit ( - ut_thread_pool pool, /* Thread pool instance */ + ddsrt_thread_pool pool, /* Thread pool instance */ void (*fn) (void *arg), /* Function to be invoked by thread from pool */ void * arg /* Argument passed to invoked function */ ); @@ -66,4 +66,4 @@ DDS_EXPORT dds_retcode_t ut_thread_pool_submit } #endif -#endif /* UT_THREAD_POOL_H */ +#endif /* DDSRT_THREAD_POOL_H */ diff --git a/src/ddsrt/include/dds/ddsrt/xmlparser.h b/src/ddsrt/include/dds/ddsrt/xmlparser.h new file mode 100644 index 0000000..120be63 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/xmlparser.h @@ -0,0 +1,52 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSRT_XMLPARSER_H +#define DDSRT_XMLPARSER_H + +#include + +#include "dds/export.h" + +#if defined (__cplusplus) +extern "C" { +#endif + + typedef int (*ddsrt_xmlp_proc_elem_open_t) (void *varg, uintptr_t parentinfo, uintptr_t *eleminfo, const char *name); + typedef int (*ddsrt_xmlp_proc_attr_t) (void *varg, uintptr_t eleminfo, const char *name, const char *value); + typedef int (*ddsrt_xmlp_proc_elem_data_t) (void *varg, uintptr_t eleminfo, const char *data); + typedef int (*ddsrt_xmlp_proc_elem_close_t) (void *varg, uintptr_t eleminfo); + typedef void (*ddsrt_xmlp_error) (void *varg, const char *msg, int line); + + struct ddsrt_xmlp_callbacks { + ddsrt_xmlp_proc_elem_open_t elem_open; + ddsrt_xmlp_proc_attr_t attr; + ddsrt_xmlp_proc_elem_data_t elem_data; + ddsrt_xmlp_proc_elem_close_t elem_close; + ddsrt_xmlp_error error; + }; + + struct ddsrt_xmlp_state; + + DDS_EXPORT struct ddsrt_xmlp_state *ddsrt_xmlp_new_file (FILE *fp, void *varg, const struct ddsrt_xmlp_callbacks *cb); + DDS_EXPORT struct ddsrt_xmlp_state *ddsrt_xmlp_new_string (const char *string, void *varg, const struct ddsrt_xmlp_callbacks *cb); + DDS_EXPORT void ddsrt_xmlp_set_requireEOF (struct ddsrt_xmlp_state *st, int require_eof); + DDS_EXPORT size_t ddsrt_xmlp_get_bufpos (const struct ddsrt_xmlp_state *st); + DDS_EXPORT void ddsrt_xmlp_free (struct ddsrt_xmlp_state *st); + DDS_EXPORT int ddsrt_xmlp_parse (struct ddsrt_xmlp_state *st); + + DDS_EXPORT int ddsrt_xmlUnescapeInsitu (char *buffer, size_t *n); + +#if defined (__cplusplus) +} +#endif + +#endif diff --git a/src/util/src/ut_avl.c b/src/ddsrt/src/avl.c similarity index 52% rename from src/util/src/ut_avl.c rename to src/ddsrt/src/avl.c index 3dc05e3..52ceddb 100644 --- a/src/util/src/ut_avl.c +++ b/src/ddsrt/src/avl.c @@ -15,20 +15,20 @@ #include #include "dds/ddsrt/attributes.h" -#include "dds/util/ut_avl.h" +#include "dds/ddsrt/avl.h" #define LOAD_DIRKEY(avlnode, tree) (((char *) (avlnode)) - (tree)->avlnodeoffset + (tree)->keyoffset) #define LOAD_INDKEY(avlnode, tree) (*((char **) (((char *) (avlnode)) - (tree)->avlnodeoffset + (tree)->keyoffset))) -static int comparenk (const ut_avlTreedef_t *td, const ut_avlNode_t *a, const void *b) +static int comparenk (const ddsrt_avl_treedef_t *td, const ddsrt_avl_node_t *a, const void *b) { const void *ka; - if (td->flags & UT_AVL_TREEDEF_FLAG_INDKEY) { + if (td->flags & DDSRT_AVL_TREEDEF_FLAG_INDKEY) { ka = LOAD_INDKEY (a, td); } else { ka = LOAD_DIRKEY (a, td); } - if (td->flags & UT_AVL_TREEDEF_FLAG_R) { + if (td->flags & DDSRT_AVL_TREEDEF_FLAG_R) { return td->u.comparekk_r (ka, b, td->cmp_arg); } else { return td->u.comparekk (ka, b); @@ -36,17 +36,17 @@ static int comparenk (const ut_avlTreedef_t *td, const ut_avlNode_t *a, const vo } #if 0 -static int comparenn_direct (const ut_avlTreedef_t *td, const ut_avlNode_t *a, const ut_avlNode_t *b) +static int comparenn_direct (const ddsrt_avl_treedef_t *td, const ddsrt_avl_node_t *a, const ddsrt_avl_node_t *b) { return td->comparekk (LOAD_DIRKEY (a, td), LOAD_DIRKEY (b, td)); } -static int comparenn_indirect (const ut_avlTreedef_t *td, const ut_avlNode_t *a, const ut_avlNode_t *b) +static int comparenn_indirect (const ddsrt_avl_treedef_t *td, const ddsrt_avl_node_t *a, const ddsrt_avl_node_t *b) { return td->comparekk (LOAD_INDKEY (a, td), LOAD_INDKEY (b, td)); } -static int comparenn (const ut_avlTreedef_t *td, const ut_avlNode_t *a, const ut_avlNode_t *b) +static int comparenn (const ddsrt_avl_treedef_t *td, const ddsrt_avl_node_t *a, const ddsrt_avl_node_t *b) { if (IS_INDKEY (td->keyoffset)) { return comparenn_indirect (td, a, b); @@ -56,25 +56,25 @@ static int comparenn (const ut_avlTreedef_t *td, const ut_avlNode_t *a, const ut } #endif -static ut_avlNode_t *node_from_onode (const ut_avlTreedef_t *td, char *onode) +static ddsrt_avl_node_t *node_from_onode (const ddsrt_avl_treedef_t *td, char *onode) { if (onode == NULL) { return NULL; } else { - return (ut_avlNode_t *) (onode + td->avlnodeoffset); + return (ddsrt_avl_node_t *) (onode + td->avlnodeoffset); } } -static const ut_avlNode_t *cnode_from_onode (const ut_avlTreedef_t *td, const char *onode) +static const ddsrt_avl_node_t *cnode_from_onode (const ddsrt_avl_treedef_t *td, const char *onode) { if (onode == NULL) { return NULL; } else { - return (const ut_avlNode_t *) (onode + td->avlnodeoffset); + return (const ddsrt_avl_node_t *) (onode + td->avlnodeoffset); } } -static char *onode_from_node (const ut_avlTreedef_t *td, ut_avlNode_t *node) +static char *onode_from_node (const ddsrt_avl_treedef_t *td, ddsrt_avl_node_t *node) { if (node == NULL) { return NULL; @@ -83,7 +83,7 @@ static char *onode_from_node (const ut_avlTreedef_t *td, ut_avlNode_t *node) } } -static const char *conode_from_node (const ut_avlTreedef_t *td, const ut_avlNode_t *node) +static const char *conode_from_node (const ddsrt_avl_treedef_t *td, const ddsrt_avl_node_t *node) { if (node == NULL) { return NULL; @@ -92,7 +92,7 @@ static const char *conode_from_node (const ut_avlTreedef_t *td, const ut_avlNode } } -static void treedef_init_common (ut_avlTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlAugment_t augment, uint32_t flags) +static void treedef_init_common (ddsrt_avl_treedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_augment_t augment, uint32_t flags) { assert (avlnodeoffset <= 0x7fffffff); assert (keyoffset <= 0x7fffffff); @@ -102,26 +102,26 @@ static void treedef_init_common (ut_avlTreedef_t *td, size_t avlnodeoffset, size td->flags = flags; } -void ut_avlTreedefInit (ut_avlTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlCompare_t comparekk, ut_avlAugment_t augment, uint32_t flags) +void ddsrt_avl_treedef_init (ddsrt_avl_treedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_compare_t comparekk, ddsrt_avl_augment_t augment, uint32_t flags) { treedef_init_common (td, avlnodeoffset, keyoffset, augment, flags); td->u.comparekk = comparekk; } -void ut_avlTreedefInit_r (ut_avlTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlCompare_r_t comparekk_r, void *cmp_arg, ut_avlAugment_t augment, uint32_t flags) +void ddsrt_avl_treedef_init_r (ddsrt_avl_treedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_compare_r_t comparekk_r, void *cmp_arg, ddsrt_avl_augment_t augment, uint32_t flags) { - treedef_init_common (td, avlnodeoffset, keyoffset, augment, flags | UT_AVL_TREEDEF_FLAG_R); + treedef_init_common (td, avlnodeoffset, keyoffset, augment, flags | DDSRT_AVL_TREEDEF_FLAG_R); td->cmp_arg = cmp_arg; td->u.comparekk_r = comparekk_r; } -void ut_avlInit (const ut_avlTreedef_t *td, ut_avlTree_t *tree) +void ddsrt_avl_init (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree) { tree->root = NULL; (void) td; } -static void treedestroy (const ut_avlTreedef_t *td, ut_avlNode_t *n, void (*freefun) (void *node)) +static void treedestroy (const ddsrt_avl_treedef_t *td, ddsrt_avl_node_t *n, void (*freefun) (void *node)) { if (n) { n->parent = NULL; @@ -133,7 +133,7 @@ static void treedestroy (const ut_avlTreedef_t *td, ut_avlNode_t *n, void (*free } } -static void treedestroy_arg (const ut_avlTreedef_t *td, ut_avlNode_t *n, void (*freefun) (void *node, void *arg), void *arg) +static void treedestroy_arg (const ddsrt_avl_treedef_t *td, ddsrt_avl_node_t *n, void (*freefun) (void *node, void *arg), void *arg) { if (n) { n->parent = NULL; @@ -145,30 +145,30 @@ static void treedestroy_arg (const ut_avlTreedef_t *td, ut_avlNode_t *n, void (* } } -void ut_avlFree (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void (*freefun) (void *node)) +void ddsrt_avl_free (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void (*freefun) (void *node)) { - ut_avlNode_t *n = tree->root; + ddsrt_avl_node_t *n = tree->root; tree->root = NULL; if (freefun) { treedestroy (td, n, freefun); } } -void ut_avlFreeArg (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void (*freefun) (void *node, void *arg), void *arg) +void ddsrt_avl_free_arg (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void (*freefun) (void *node, void *arg), void *arg) { - ut_avlNode_t *n = tree->root; + ddsrt_avl_node_t *n = tree->root; tree->root = NULL; if (freefun) { treedestroy_arg (td, n, freefun, arg); } } -static void augment (const ut_avlTreedef_t *td, ut_avlNode_t *n) +static void augment (const ddsrt_avl_treedef_t *td, ddsrt_avl_node_t *n) { td->augment (onode_from_node (td, n), conode_from_node (td, n->cs[0]), conode_from_node (td, n->cs[1])); } -static ut_avlNode_t *rotate_single (const ut_avlTreedef_t *td, ut_avlNode_t **pnode, ut_avlNode_t *node, int dir) +static ddsrt_avl_node_t *rotate_single (const ddsrt_avl_treedef_t *td, ddsrt_avl_node_t **pnode, ddsrt_avl_node_t *node, int dir) { /* rotate_single(N, dir) performs one rotation, e.g., for dir=1, a right rotation as depicted below, for dir=0 a left rotation: @@ -179,9 +179,9 @@ static ut_avlNode_t *rotate_single (const ut_avlTreedef_t *td, ut_avlNode_t **pn Since a right rotation is only ever done with the left side is overweight, _ND must be != NULL. */ - ut_avlNode_t * const parent = node->parent; - ut_avlNode_t * const node_ND = node->cs[1-dir]; - ut_avlNode_t * const node_ND_D = node_ND->cs[dir]; + ddsrt_avl_node_t * const parent = node->parent; + ddsrt_avl_node_t * const node_ND = node->cs[1-dir]; + ddsrt_avl_node_t * const node_ND_D = node_ND->cs[dir]; assert (node_ND); node_ND->cs[dir] = node; node_ND->parent = parent; @@ -200,7 +200,7 @@ static ut_avlNode_t *rotate_single (const ut_avlTreedef_t *td, ut_avlNode_t **pn return parent; } -static ut_avlNode_t *rotate_double (const ut_avlTreedef_t *td, ut_avlNode_t **pnode, ut_avlNode_t *node, int dir) +static ddsrt_avl_node_t *rotate_double (const ddsrt_avl_treedef_t *td, ddsrt_avl_node_t **pnode, ddsrt_avl_node_t *node, int dir) { /* rotate_double() performs one double rotation, which is slightly faster when written out than the equivalent: @@ -218,9 +218,9 @@ static ut_avlNode_t *rotate_double (const ut_avlTreedef_t *td, ut_avlNode_t **pn Since a right double rotation is only ever done with the N is overweight on the left side and _ND is overweight on the right side, both _ND and _ND_D must be != NULL. */ - ut_avlNode_t * const parent = node->parent; - ut_avlNode_t * const node_ND = node->cs[1-dir]; - ut_avlNode_t * const node_ND_D = node_ND->cs[dir]; + ddsrt_avl_node_t * const parent = node->parent; + ddsrt_avl_node_t * const node_ND = node->cs[1-dir]; + ddsrt_avl_node_t * const node_ND_D = node_ND->cs[dir]; assert (node_ND); assert (node_ND_D); node_ND->cs[dir] = node_ND_D->cs[1-dir]; @@ -251,16 +251,16 @@ static ut_avlNode_t *rotate_double (const ut_avlTreedef_t *td, ut_avlNode_t **pn return parent; } -static ut_avlNode_t *rotate (const ut_avlTreedef_t *td, ut_avlNode_t **pnode, ut_avlNode_t *node, int dir) +static ddsrt_avl_node_t *rotate (const ddsrt_avl_treedef_t *td, ddsrt_avl_node_t **pnode, ddsrt_avl_node_t *node, int dir) { /* _D => child in the direction of rotation (1 for right, 0 for left); _ND => child in the opposite direction. So in a right rotation, _ND_D means the grandchild that is the right child of the left child. */ - ut_avlNode_t * const node_ND = node->cs[1-dir]; + ddsrt_avl_node_t * const node_ND = node->cs[1-dir]; assert (node_ND != NULL); - ut_avlNode_t * const node_ND_ND = node_ND->cs[1-dir]; - ut_avlNode_t * const node_ND_D = node_ND->cs[dir]; + ddsrt_avl_node_t * const node_ND_ND = node_ND->cs[1-dir]; + ddsrt_avl_node_t * const node_ND_D = node_ND->cs[dir]; int height_ND_ND, height_ND_D; assert (dir == !!dir); height_ND_ND = node_ND_ND ? node_ND_ND->height : 0; @@ -272,10 +272,10 @@ static ut_avlNode_t *rotate (const ut_avlTreedef_t *td, ut_avlNode_t **pnode, ut } } -static ut_avlNode_t *rebalance_one (const ut_avlTreedef_t *td, ut_avlNode_t **pnode, ut_avlNode_t *node) +static ddsrt_avl_node_t *rebalance_one (const ddsrt_avl_treedef_t *td, ddsrt_avl_node_t **pnode, ddsrt_avl_node_t *node) { - ut_avlNode_t *node_L = node->cs[0]; - ut_avlNode_t *node_R = node->cs[1]; + ddsrt_avl_node_t *node_L = node->cs[0]; + ddsrt_avl_node_t *node_R = node->cs[1]; int height_L = node_L ? node_L->height : 0; int height_R = node_R ? node_R->height : 0; if (height_L > height_R + 1) { @@ -301,7 +301,7 @@ static ut_avlNode_t *rebalance_one (const ut_avlTreedef_t *td, ut_avlNode_t **pn } } -static void rebalance_path (const ut_avlTreedef_t *td, ut_avlPath_t *path, ut_avlNode_t *node) +static void rebalance_path (const ddsrt_avl_treedef_t *td, ddsrt_avl_path_t *path, ddsrt_avl_node_t *node) { while (node) { assert (*path->pnode[path->depth] == node); @@ -310,25 +310,25 @@ static void rebalance_path (const ut_avlTreedef_t *td, ut_avlPath_t *path, ut_av } } -static ut_avlNode_t **nodeptr_from_node (ut_avlTree_t *tree, ut_avlNode_t *node) +static ddsrt_avl_node_t **nodeptr_from_node (ddsrt_avl_tree_t *tree, ddsrt_avl_node_t *node) { - ut_avlNode_t *parent = node->parent; + ddsrt_avl_node_t *parent = node->parent; return (parent == NULL) ? &tree->root : (node == parent->cs[0]) ? &parent->cs[0] : &parent->cs[1]; } -static void rebalance_nopath (const ut_avlTreedef_t *td, ut_avlTree_t *tree, ut_avlNode_t *node) +static void rebalance_nopath (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, ddsrt_avl_node_t *node) { while (node) { - ut_avlNode_t **pnode = nodeptr_from_node (tree, node); + ddsrt_avl_node_t **pnode = nodeptr_from_node (tree, node); node = rebalance_one (td, pnode, node); } } -void *ut_avlLookup (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +void *ddsrt_avl_lookup (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { - const ut_avlNode_t *cursor = tree->root; + const ddsrt_avl_node_t *cursor = tree->root; int c; while (cursor && (c = comparenk (td, cursor, key)) != 0) { const int dir = (c <= 0); @@ -337,59 +337,59 @@ void *ut_avlLookup (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const v return (void *) conode_from_node (td, cursor); } -static const ut_avlNode_t *lookup_path (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key, ut_avlPath_t *path) +static const ddsrt_avl_node_t *lookup_path (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key, ddsrt_avl_path_t *path) { - const ut_avlNode_t *cursor = tree->root; - const ut_avlNode_t *prev = NULL; + const ddsrt_avl_node_t *cursor = tree->root; + const ddsrt_avl_node_t *prev = NULL; int c; path->depth = 0; - path->pnode[0] = (ut_avlNode_t **) &tree->root; + path->pnode[0] = (ddsrt_avl_node_t **) &tree->root; while (cursor && (c = comparenk (td, cursor, key)) != 0) { const int dir = (c <= 0); prev = cursor; - path->pnode[++path->depth] = (ut_avlNode_t **) &cursor->cs[dir]; + path->pnode[++path->depth] = (ddsrt_avl_node_t **) &cursor->cs[dir]; cursor = cursor->cs[dir]; } path->pnodeidx = path->depth; - path->parent = (ut_avlNode_t *) prev; + path->parent = (ddsrt_avl_node_t *) prev; return cursor; } -void *ut_avlLookupDPath (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key, ut_avlDPath_t *path) +void *ddsrt_avl_lookup_dpath (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key, ddsrt_avl_dpath_t *path) { - const ut_avlNode_t *node = lookup_path (td, tree, key, &path->p); + const ddsrt_avl_node_t *node = lookup_path (td, tree, key, &path->p); return (void *) conode_from_node (td, node); } -void *ut_avlLookupIPath (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key, ut_avlIPath_t *path) +void *ddsrt_avl_lookup_ipath (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key, ddsrt_avl_ipath_t *path) { - const ut_avlNode_t *node = lookup_path (td, tree, key, &path->p); + const ddsrt_avl_node_t *node = lookup_path (td, tree, key, &path->p); /* If no duplicates allowed, path may not be used for insertion, and hence there is no need to continue descending the tree. Since we can invalidate it very efficiently, do so. */ if (node) { - if (!(td->flags & UT_AVL_TREEDEF_FLAG_ALLOWDUPS)) { + if (!(td->flags & DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS)) { path->p.pnode[path->p.depth] = NULL; } else { - const ut_avlNode_t *cursor = node; - const ut_avlNode_t *prev; + const ddsrt_avl_node_t *cursor = node; + const ddsrt_avl_node_t *prev; int c, dir; do { c = comparenk (td, cursor, key); dir = (c <= 0); prev = cursor; - path->p.pnode[++path->p.depth] = (ut_avlNode_t **) &cursor->cs[dir]; + path->p.pnode[++path->p.depth] = (ddsrt_avl_node_t **) &cursor->cs[dir]; cursor = cursor->cs[dir]; } while (cursor); - path->p.parent = (ut_avlNode_t *) prev; + path->p.parent = (ddsrt_avl_node_t *) prev; } } return (void *) conode_from_node (td, node); } -void ut_avlInsertIPath (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *vnode, ut_avlIPath_t *path) +void ddsrt_avl_insert_ipath (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *vnode, ddsrt_avl_ipath_t *path) { - ut_avlNode_t *node = node_from_onode (td, vnode); + ddsrt_avl_node_t *node = node_from_onode (td, vnode); (void) tree; node->cs[0] = NULL; node->cs[1] = NULL; @@ -405,25 +405,25 @@ void ut_avlInsertIPath (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *vno rebalance_path (td, &path->p, node->parent); } -void ut_avlInsert (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *vnode) +void ddsrt_avl_insert (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *vnode) { const void *node = cnode_from_onode (td, vnode); const void *key; - ut_avlIPath_t path; - if (td->flags & UT_AVL_TREEDEF_FLAG_INDKEY) { + ddsrt_avl_ipath_t path; + if (td->flags & DDSRT_AVL_TREEDEF_FLAG_INDKEY) { key = LOAD_INDKEY (node, td); } else { key = LOAD_DIRKEY (node, td); } - ut_avlLookupIPath (td, tree, key, &path); - ut_avlInsertIPath (td, tree, vnode, &path); + ddsrt_avl_lookup_ipath (td, tree, key, &path); + ddsrt_avl_insert_ipath (td, tree, vnode, &path); } -static void delete_generic (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *vnode, ut_avlDPath_t *path) +static void delete_generic (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *vnode, ddsrt_avl_dpath_t *path) { - ut_avlNode_t *node = node_from_onode (td, vnode); - ut_avlNode_t **pnode; - ut_avlNode_t *whence; + ddsrt_avl_node_t *node = node_from_onode (td, vnode); + ddsrt_avl_node_t **pnode; + ddsrt_avl_node_t *whence; if (path) { assert (tree == NULL); @@ -448,7 +448,7 @@ static void delete_generic (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void } else { - ut_avlNode_t *subst; + ddsrt_avl_node_t *subst; assert (node->cs[0] != NULL); assert (node->cs[1] != NULL); @@ -502,21 +502,21 @@ static void delete_generic (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void } } -void ut_avlDeleteDPath (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *vnode, ut_avlDPath_t *path) +void ddsrt_avl_delete_dpath (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *vnode, ddsrt_avl_dpath_t *path) { (void) tree; delete_generic (td, NULL, vnode, path); } -void ut_avlDelete (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *vnode) +void ddsrt_avl_delete (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *vnode) { delete_generic (td, tree, vnode, NULL); } -void ut_avlSwapNode (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *vold, void *vnew) +void ddsrt_avl_swap_node (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, void *vold, void *vnew) { - ut_avlNode_t *old = node_from_onode (td, vold); - ut_avlNode_t *new = node_from_onode (td, vnew); + ddsrt_avl_node_t *old = node_from_onode (td, vold); + ddsrt_avl_node_t *new = node_from_onode (td, vnew); *nodeptr_from_node (tree, old) = new; /* use memmove so partially overlap between old & new is allowed (yikes!, but exploited by the memory allocator, and not a big @@ -533,7 +533,7 @@ void ut_avlSwapNode (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *vold, } } -static ut_avlNode_t *find_neighbour (const ut_avlNode_t *n, int dir) +static ddsrt_avl_node_t *find_neighbour (const ddsrt_avl_node_t *n, int dir) { /* dir = 0 => pred; dir = 1 = succ */ if (n->cs[dir]) { @@ -541,62 +541,62 @@ static ut_avlNode_t *find_neighbour (const ut_avlNode_t *n, int dir) while (n->cs[1-dir]) { n = n->cs[1-dir]; } - return (ut_avlNode_t *) n; + return (ddsrt_avl_node_t *) n; } else { - const ut_avlNode_t *p = n->parent; + const ddsrt_avl_node_t *p = n->parent; while (p && n == p->cs[dir]) { n = p; p = p->parent; } - return (ut_avlNode_t *) p; + return (ddsrt_avl_node_t *) p; } } -static ut_avlNode_t *find_extremum (const ut_avlTree_t *tree, int dir) +static ddsrt_avl_node_t *find_extremum (const ddsrt_avl_tree_t *tree, int dir) { - const ut_avlNode_t *n = tree->root; + const ddsrt_avl_node_t *n = tree->root; if (n) { while (n->cs[dir]) { n = n->cs[dir]; } } - return (ut_avlNode_t *) n; + return (ddsrt_avl_node_t *) n; } -void *ut_avlFindMin (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) +void *ddsrt_avl_find_min (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree) { return (void *) conode_from_node (td, find_extremum (tree, 0)); } -void *ut_avlFindMax (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) +void *ddsrt_avl_find_max (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree) { return (void *) conode_from_node (td, find_extremum (tree, 1)); } -void *ut_avlFindPred (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *vnode) +void *ddsrt_avl_find_pred (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *vnode) { - const ut_avlNode_t *n = cnode_from_onode (td, vnode); + const ddsrt_avl_node_t *n = cnode_from_onode (td, vnode); if (n == NULL) { - return ut_avlFindMax (td, tree); + return ddsrt_avl_find_max (td, tree); } else { return (void *) conode_from_node (td, find_neighbour (n, 0)); } } -void *ut_avlFindSucc (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *vnode) +void *ddsrt_avl_find_succ (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *vnode) { - const ut_avlNode_t *n = cnode_from_onode (td, vnode); + const ddsrt_avl_node_t *n = cnode_from_onode (td, vnode); if (n == NULL) { - return ut_avlFindMin (td, tree); + return ddsrt_avl_find_min (td, tree); } else { return (void *) conode_from_node (td, find_neighbour (n, 1)); } } -static void avl_iter_downleft (ut_avlIter_t *iter) +static void avl_iter_downleft (ddsrt_avl_iter_t *iter) { if (*iter->todop) { - ut_avlNode_t *n; + ddsrt_avl_node_t *n; n = (*iter->todop)->cs[0]; while (n) { assert ((int) (iter->todop - iter->todo) < (int) (sizeof (iter->todo) / sizeof (*iter->todo))); @@ -607,16 +607,16 @@ static void avl_iter_downleft (ut_avlIter_t *iter) } } -void *ut_avlIterFirst (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_avlIter_t *iter) +void *ddsrt_avl_iter_first (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, ddsrt_avl_iter_t *iter) { iter->td = td; iter->todop = iter->todo+1; - *iter->todop = (ut_avlNode_t *) tree->root; + *iter->todop = (ddsrt_avl_node_t *) tree->root; avl_iter_downleft (iter); return onode_from_node (td, *iter->todop); } -void *ut_avlIterNext (ut_avlIter_t *iter) +void *ddsrt_avl_iter_next (ddsrt_avl_iter_t *iter) { if (iter->todop-- > iter->todo+1 && iter->right == NULL) { iter->right = (*iter->todop)->cs[1]; @@ -628,13 +628,13 @@ void *ut_avlIterNext (ut_avlIter_t *iter) return onode_from_node (iter->td, *iter->todop); } -void ut_avlWalk (const ut_avlTreedef_t *td, ut_avlTree_t *tree, ut_avlWalk_t f, void *a) +void ddsrt_avl_walk (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, ddsrt_avl_walk_t f, void *a) { - const ut_avlNode_t *todo[1+UT_AVL_MAX_TREEHEIGHT]; - const ut_avlNode_t **todop = todo+1; + const ddsrt_avl_node_t *todo[1+DDSRT_AVL_MAX_TREEHEIGHT]; + const ddsrt_avl_node_t **todop = todo+1; *todop = tree->root; while (*todop) { - ut_avlNode_t *right, *n; + ddsrt_avl_node_t *right, *n; /* First locate the minimum value in this subtree */ n = (*todop)->cs[0]; while (n) { @@ -654,27 +654,27 @@ void ut_avlWalk (const ut_avlTreedef_t *td, ut_avlTree_t *tree, ut_avlWalk_t f, } } -void ut_avlConstWalk (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_avlConstWalk_t f, void *a) +void ddsrt_avl_const_walk (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, ddsrt_avl_const_walk_t f, void *a) { - ut_avlWalk (td, (ut_avlTree_t *) tree, (ut_avlWalk_t) f, a); + ddsrt_avl_walk (td, (ddsrt_avl_tree_t *) tree, (ddsrt_avl_walk_t) f, a); } -int ut_avlIsEmpty (const ut_avlTree_t *tree) +int ddsrt_avl_is_empty (const ddsrt_avl_tree_t *tree) { return tree->root == NULL; } -int ut_avlIsSingleton (const ut_avlTree_t *tree) +int ddsrt_avl_is_singleton (const ddsrt_avl_tree_t *tree) { int r = (tree->root && tree->root->height == 1); assert (!r || (tree->root->cs[0] == NULL && tree->root->cs[1] == NULL)); return r; } -void ut_avlAugmentUpdate (const ut_avlTreedef_t *td, void *vnode) +void ddsrt_avl_augment_update (const ddsrt_avl_treedef_t *td, void *vnode) { if (td->augment) { - ut_avlNode_t *node = node_from_onode (td, vnode); + ddsrt_avl_node_t *node = node_from_onode (td, vnode); while (node) { augment (td, node); node = node->parent; @@ -682,11 +682,11 @@ void ut_avlAugmentUpdate (const ut_avlTreedef_t *td, void *vnode) } } -static const ut_avlNode_t *fixup_predsucceq (const ut_avlTreedef_t *td, const void *key, const ut_avlNode_t *tmp, const ut_avlNode_t *cand, int dir) +static const ddsrt_avl_node_t *fixup_predsucceq (const ddsrt_avl_treedef_t *td, const void *key, const ddsrt_avl_node_t *tmp, const ddsrt_avl_node_t *cand, int dir) { if (tmp == NULL) { return cand; - } else if (!(td->flags & UT_AVL_TREEDEF_FLAG_ALLOWDUPS)) { + } else if (!(td->flags & DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS)) { return tmp; } else { /* key exists - but it there's no guarantee we hit the first @@ -705,10 +705,10 @@ static const ut_avlNode_t *fixup_predsucceq (const ut_avlTreedef_t *td, const vo } } -static const ut_avlNode_t *lookup_predeq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +static const ddsrt_avl_node_t *lookup_predeq (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { - const ut_avlNode_t *tmp = tree->root; - const ut_avlNode_t *cand = NULL; + const ddsrt_avl_node_t *tmp = tree->root; + const ddsrt_avl_node_t *cand = NULL; int c; while (tmp && (c = comparenk (td, tmp, key)) != 0) { if (c < 0) { @@ -721,10 +721,10 @@ static const ut_avlNode_t *lookup_predeq (const ut_avlTreedef_t *td, const ut_av return fixup_predsucceq (td, key, tmp, cand, 0); } -static const ut_avlNode_t *lookup_succeq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +static const ddsrt_avl_node_t *lookup_succeq (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { - const ut_avlNode_t *tmp = tree->root; - const ut_avlNode_t *cand = NULL; + const ddsrt_avl_node_t *tmp = tree->root; + const ddsrt_avl_node_t *cand = NULL; int c; while (tmp && (c = comparenk (td, tmp, key)) != 0) { if (c > 0) { @@ -737,12 +737,12 @@ static const ut_avlNode_t *lookup_succeq (const ut_avlTreedef_t *td, const ut_av return fixup_predsucceq (td, key, tmp, cand, 1); } -static const ut_avlNode_t *fixup_predsucc (const ut_avlTreedef_t *td, const void *key, const ut_avlNode_t *tmp, const ut_avlNode_t *cand, int dir) +static const ddsrt_avl_node_t *fixup_predsucc (const ddsrt_avl_treedef_t *td, const void *key, const ddsrt_avl_node_t *tmp, const ddsrt_avl_node_t *cand, int dir) { /* dir=0: pred, dir=1: succ */ if (tmp == NULL || tmp->cs[dir] == NULL) { return cand; - } else if (!(td->flags & UT_AVL_TREEDEF_FLAG_ALLOWDUPS)) { + } else if (!(td->flags & DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS)) { /* No duplicates, therefore the extremum in the subtree */ tmp = tmp->cs[dir]; while (tmp->cs[1-dir]) { @@ -766,10 +766,10 @@ static const ut_avlNode_t *fixup_predsucc (const ut_avlTreedef_t *td, const void } } -static const ut_avlNode_t *lookup_pred (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +static const ddsrt_avl_node_t *lookup_pred (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { - const ut_avlNode_t *tmp = tree->root; - const ut_avlNode_t *cand = NULL; + const ddsrt_avl_node_t *tmp = tree->root; + const ddsrt_avl_node_t *cand = NULL; int c; while (tmp && (c = comparenk (td, tmp, key)) != 0) { if (c < 0) { @@ -782,10 +782,10 @@ static const ut_avlNode_t *lookup_pred (const ut_avlTreedef_t *td, const ut_avlT return fixup_predsucc (td, key, tmp, cand, 0); } -static const ut_avlNode_t *lookup_succ (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +static const ddsrt_avl_node_t *lookup_succ (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { - const ut_avlNode_t *tmp = tree->root; - const ut_avlNode_t *cand = NULL; + const ddsrt_avl_node_t *tmp = tree->root; + const ddsrt_avl_node_t *cand = NULL; int c; while (tmp && (c = comparenk (td, tmp, key)) != 0) { if (c > 0) { @@ -798,43 +798,43 @@ static const ut_avlNode_t *lookup_succ (const ut_avlTreedef_t *td, const ut_avlT return fixup_predsucc (td, key, tmp, cand, 1); } -void *ut_avlLookupSuccEq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +void *ddsrt_avl_lookup_succ_eq (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { return (void *) conode_from_node (td, lookup_succeq (td, tree, key)); } -void *ut_avlLookupPredEq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +void *ddsrt_avl_lookup_pred_eq (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { return (void *) conode_from_node (td, lookup_predeq (td, tree, key)); } -void *ut_avlLookupSucc (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +void *ddsrt_avl_lookup_succ (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { return (void *) conode_from_node (td, lookup_succ (td, tree, key)); } -void *ut_avlLookupPred (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) +void *ddsrt_avl_lookup_pred (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *key) { return (void *) conode_from_node (td, lookup_pred (td, tree, key)); } -void *ut_avlIterSuccEq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_avlIter_t *iter, const void *key) +void *ddsrt_avl_iter_succ_eq (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, ddsrt_avl_iter_t *iter, const void *key) { - const ut_avlNode_t *tmp = tree->root; + const ddsrt_avl_node_t *tmp = tree->root; int c; iter->td = td; iter->todop = iter->todo; while (tmp && (c = comparenk (td, tmp, key)) != 0) { if (c > 0) { - *++iter->todop = (ut_avlNode_t *) tmp; + *++iter->todop = (ddsrt_avl_node_t *) tmp; tmp = tmp->cs[0]; } else { tmp = tmp->cs[1]; } } if (tmp != NULL) { - *++iter->todop = (ut_avlNode_t *) tmp; - if (td->flags & UT_AVL_TREEDEF_FLAG_ALLOWDUPS) { + *++iter->todop = (ddsrt_avl_node_t *) tmp; + if (td->flags & DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS) { /* key exists - but it there's no guarantee we hit the first one in the in-order enumeration of the tree */ tmp = tmp->cs[0]; @@ -842,7 +842,7 @@ void *ut_avlIterSuccEq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_ if (comparenk (td, tmp, key) != 0) { tmp = tmp->cs[1]; } else { - *++iter->todop = (ut_avlNode_t *) tmp; + *++iter->todop = (ddsrt_avl_node_t *) tmp; tmp = tmp->cs[0]; } } @@ -856,26 +856,26 @@ void *ut_avlIterSuccEq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_ } } -void *ut_avlIterSucc (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_avlIter_t *iter, const void *key) +void *ddsrt_avl_iter_succ (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, ddsrt_avl_iter_t *iter, const void *key) { - const ut_avlNode_t *tmp = tree->root; + const ddsrt_avl_node_t *tmp = tree->root; int c; iter->td = td; iter->todop = iter->todo; while (tmp && (c = comparenk (td, tmp, key)) != 0) { if (c > 0) { - *++iter->todop = (ut_avlNode_t *) tmp; + *++iter->todop = (ddsrt_avl_node_t *) tmp; tmp = tmp->cs[0]; } else { tmp = tmp->cs[1]; } } if (tmp != NULL) { - if (!(td->flags & UT_AVL_TREEDEF_FLAG_ALLOWDUPS)) { + if (!(td->flags & DDSRT_AVL_TREEDEF_FLAG_ALLOWDUPS)) { tmp = tmp->cs[1]; if (tmp) { do { - *++iter->todop = (ut_avlNode_t *) tmp; + *++iter->todop = (ddsrt_avl_node_t *) tmp; tmp = tmp->cs[0]; } while (tmp); } @@ -883,7 +883,7 @@ void *ut_avlIterSucc (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_av tmp = tmp->cs[1]; while (tmp) { if (comparenk (td, tmp, key) != 0) { - *++iter->todop = (ut_avlNode_t *) tmp; + *++iter->todop = (ddsrt_avl_node_t *) tmp; tmp = tmp->cs[0]; } else { tmp = tmp->cs[1]; @@ -899,10 +899,10 @@ void *ut_avlIterSucc (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_av } } -void ut_avlWalkRange (const ut_avlTreedef_t *td, ut_avlTree_t *tree, const void *min, const void *max, ut_avlWalk_t f, void *a) +void ddsrt_avl_walk_range (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, const void *min, const void *max, ddsrt_avl_walk_t f, void *a) { - ut_avlNode_t *n, *nn; - n = (ut_avlNode_t *) lookup_succeq (td, tree, min); + ddsrt_avl_node_t *n, *nn; + n = (ddsrt_avl_node_t *) lookup_succeq (td, tree, min); while (n && comparenk (td, n, max) <= 0) { nn = find_neighbour (n, 1); f (onode_from_node (td, n), a); @@ -910,15 +910,15 @@ void ut_avlWalkRange (const ut_avlTreedef_t *td, ut_avlTree_t *tree, const void } } -void ut_avlConstWalkRange (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *min, const void *max, ut_avlConstWalk_t f, void *a) +void ddsrt_avl_const_walk_range (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *min, const void *max, ddsrt_avl_const_walk_t f, void *a) { - ut_avlWalkRange (td, (ut_avlTree_t *) tree, min, max, (ut_avlWalk_t) f, a); + ddsrt_avl_walk_range (td, (ddsrt_avl_tree_t *) tree, min, max, (ddsrt_avl_walk_t) f, a); } -void ut_avlWalkRangeReverse (const ut_avlTreedef_t *td, ut_avlTree_t *tree, const void *min, const void *max, ut_avlWalk_t f, void *a) +void ddsrt_avl_walk_range_reverse (const ddsrt_avl_treedef_t *td, ddsrt_avl_tree_t *tree, const void *min, const void *max, ddsrt_avl_walk_t f, void *a) { - ut_avlNode_t *n, *nn; - n = (ut_avlNode_t *) lookup_predeq (td, tree, max); + ddsrt_avl_node_t *n, *nn; + n = (ddsrt_avl_node_t *) lookup_predeq (td, tree, max); while (n && comparenk (td, n, min) >= 0) { nn = find_neighbour (n, 0); f (onode_from_node (td, n), a); @@ -926,17 +926,17 @@ void ut_avlWalkRangeReverse (const ut_avlTreedef_t *td, ut_avlTree_t *tree, cons } } -void ut_avlConstWalkRangeReverse (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *min, const void *max, ut_avlConstWalk_t f, void *a) +void ddsrt_avl_const_walk_range_reverse (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree, const void *min, const void *max, ddsrt_avl_const_walk_t f, void *a) { - ut_avlWalkRangeReverse (td, (ut_avlTree_t *) tree, min, max, (ut_avlWalk_t) f, a); + ddsrt_avl_walk_range_reverse (td, (ddsrt_avl_tree_t *) tree, min, max, (ddsrt_avl_walk_t) f, a); } -void *ut_avlRoot (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) +void *ddsrt_avl_root (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree) { return (void *) conode_from_node (td, tree->root); } -void *ut_avlRootNonEmpty (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) +void *ddsrt_avl_root_non_empty (const ddsrt_avl_treedef_t *td, const ddsrt_avl_tree_t *tree) { assert (tree->root); return (void *) conode_from_node (td, tree->root); @@ -948,201 +948,201 @@ void *ut_avlRootNonEmpty (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) **** **************************************************************************************/ -void ut_avlCTreedefInit (ut_avlCTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlCompare_t comparekk, ut_avlAugment_t augment, uint32_t flags) +void ddsrt_avl_ctreedef_init (ddsrt_avl_ctreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_compare_t comparekk, ddsrt_avl_augment_t augment, uint32_t flags) { treedef_init_common (&td->t, avlnodeoffset, keyoffset, augment, flags); td->t.u.comparekk = comparekk; } -void ut_avlCTreedefInit_r (ut_avlCTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlCompare_r_t comparekk_r, void *cmp_arg, ut_avlAugment_t augment, uint32_t flags) +void ddsrt_avl_ctreedef_init_r (ddsrt_avl_ctreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ddsrt_avl_compare_r_t comparekk_r, void *cmp_arg, ddsrt_avl_augment_t augment, uint32_t flags) { - treedef_init_common (&td->t, avlnodeoffset, keyoffset, augment, flags | UT_AVL_TREEDEF_FLAG_R); + treedef_init_common (&td->t, avlnodeoffset, keyoffset, augment, flags | DDSRT_AVL_TREEDEF_FLAG_R); td->t.cmp_arg = cmp_arg; td->t.u.comparekk_r = comparekk_r; } -void ut_avlCInit (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree) +void ddsrt_avl_cinit (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree) { - ut_avlInit (&td->t, &tree->t); + ddsrt_avl_init (&td->t, &tree->t); tree->count = 0; } -void ut_avlCFree (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void (*freefun) (void *node)) +void ddsrt_avl_cfree (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void (*freefun) (void *node)) { tree->count = 0; - ut_avlFree (&td->t, &tree->t, freefun); + ddsrt_avl_free (&td->t, &tree->t, freefun); } -void ut_avlCFreeArg (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void (*freefun) (void *node, void *arg), void *arg) +void ddsrt_avl_cfree_arg (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void (*freefun) (void *node, void *arg), void *arg) { tree->count = 0; - ut_avlFreeArg (&td->t, &tree->t, freefun, arg); + ddsrt_avl_free_arg (&td->t, &tree->t, freefun, arg); } -void *ut_avlCRoot (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree) +void *ddsrt_avl_croot (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree) { - return ut_avlRoot (&td->t, &tree->t); + return ddsrt_avl_root (&td->t, &tree->t); } -void *ut_avlCRootNonEmpty (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree) +void *ddsrt_avl_croot_non_empty (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree) { - return ut_avlRootNonEmpty (&td->t, &tree->t); + return ddsrt_avl_root_non_empty (&td->t, &tree->t); } -void *ut_avlCLookup (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) +void *ddsrt_avl_clookup (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) { - return ut_avlLookup (&td->t, &tree->t, key); + return ddsrt_avl_lookup (&td->t, &tree->t, key); } -void *ut_avlCLookupIPath (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key, ut_avlIPath_t *path) +void *ddsrt_avl_clookup_ipath (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key, ddsrt_avl_ipath_t *path) { - return ut_avlLookupIPath (&td->t, &tree->t, key, path); + return ddsrt_avl_lookup_ipath (&td->t, &tree->t, key, path); } -void *ut_avlCLookupDPath (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key, ut_avlDPath_t *path) +void *ddsrt_avl_clookup_dpath (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key, ddsrt_avl_dpath_t *path) { - return ut_avlLookupDPath (&td->t, &tree->t, key, path); + return ddsrt_avl_lookup_dpath (&td->t, &tree->t, key, path); } -void *ut_avlCLookupPredEq (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) +void *ddsrt_avl_clookup_pred_eq (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) { - return ut_avlLookupPredEq (&td->t, &tree->t, key); + return ddsrt_avl_lookup_pred_eq (&td->t, &tree->t, key); } -void *ut_avlCLookupSuccEq (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) +void *ddsrt_avl_clookup_succ_eq (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) { - return ut_avlLookupSuccEq (&td->t, &tree->t, key); + return ddsrt_avl_lookup_succ_eq (&td->t, &tree->t, key); } -void *ut_avlCLookupPred (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) +void *ddsrt_avl_clookup_pred (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) { - return ut_avlLookupPred (&td->t, &tree->t, key); + return ddsrt_avl_lookup_pred (&td->t, &tree->t, key); } -void *ut_avlCLookupSucc (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) +void *ddsrt_avl_clookup_succ (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *key) { - return ut_avlLookupSucc (&td->t, &tree->t, key); + return ddsrt_avl_lookup_succ (&td->t, &tree->t, key); } -void ut_avlCInsert (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *node) +void ddsrt_avl_cinsert (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *node) { tree->count++; - ut_avlInsert (&td->t, &tree->t, node); + ddsrt_avl_insert (&td->t, &tree->t, node); } -void ut_avlCDelete (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *node) +void ddsrt_avl_cdelete (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *node) { assert (tree->count > 0); tree->count--; - ut_avlDelete (&td->t, &tree->t, node); + ddsrt_avl_delete (&td->t, &tree->t, node); } -void ut_avlCInsertIPath (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *node, ut_avlIPath_t *path) +void ddsrt_avl_cinsert_ipath (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *node, ddsrt_avl_ipath_t *path) { tree->count++; - ut_avlInsertIPath (&td->t, &tree->t, node, path); + ddsrt_avl_insert_ipath (&td->t, &tree->t, node, path); } -void ut_avlCDeleteDPath (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *node, ut_avlDPath_t *path) +void ddsrt_avl_cdelete_dpath (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *node, ddsrt_avl_dpath_t *path) { assert (tree->count > 0); tree->count--; - ut_avlDeleteDPath (&td->t, &tree->t, node, path); + ddsrt_avl_delete_dpath (&td->t, &tree->t, node, path); } -void ut_avlCSwapNode (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *old, void *new) +void ddsrt_avl_cswap_node (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, void *old, void *new) { - ut_avlSwapNode (&td->t, &tree->t, old, new); + ddsrt_avl_swap_node (&td->t, &tree->t, old, new); } -void ut_avlCAugmentUpdate (const ut_avlCTreedef_t *td, void *node) +void ddsrt_avl_caugment_update (const ddsrt_avl_ctreedef_t *td, void *node) { - ut_avlAugmentUpdate (&td->t, node); + ddsrt_avl_augment_update (&td->t, node); } -int ut_avlCIsEmpty (const ut_avlCTree_t *tree) +int ddsrt_avl_cis_empty (const ddsrt_avl_ctree_t *tree) { - return ut_avlIsEmpty (&tree->t); + return ddsrt_avl_is_empty (&tree->t); } -int ut_avlCIsSingleton (const ut_avlCTree_t *tree) +int ddsrt_avl_cis_singleton (const ddsrt_avl_ctree_t *tree) { - return ut_avlIsSingleton (&tree->t); + return ddsrt_avl_is_singleton (&tree->t); } -size_t ut_avlCCount (const ut_avlCTree_t *tree) +size_t ddsrt_avl_ccount (const ddsrt_avl_ctree_t *tree) { return tree->count; } -void *ut_avlCFindMin (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree) +void *ddsrt_avl_cfind_min (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree) { - return ut_avlFindMin (&td->t, &tree->t); + return ddsrt_avl_find_min (&td->t, &tree->t); } -void *ut_avlCFindMax (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree) +void *ddsrt_avl_cfind_max (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree) { - return ut_avlFindMax (&td->t, &tree->t); + return ddsrt_avl_find_max (&td->t, &tree->t); } -void *ut_avlCFindPred (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *vnode) +void *ddsrt_avl_cfind_pred (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *vnode) { - return ut_avlFindPred (&td->t, &tree->t, vnode); + return ddsrt_avl_find_pred (&td->t, &tree->t, vnode); } -void *ut_avlCFindSucc (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *vnode) +void *ddsrt_avl_cfind_succ (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *vnode) { - return ut_avlFindSucc (&td->t, &tree->t, vnode); + return ddsrt_avl_find_succ (&td->t, &tree->t, vnode); } -void ut_avlCWalk (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, ut_avlWalk_t f, void *a) +void ddsrt_avl_cwalk (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, ddsrt_avl_walk_t f, void *a) { - ut_avlWalk (&td->t, &tree->t, f, a); + ddsrt_avl_walk (&td->t, &tree->t, f, a); } -void ut_avlCConstWalk (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, ut_avlConstWalk_t f, void *a) +void ddsrt_avl_cconst_walk (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, ddsrt_avl_const_walk_t f, void *a) { - ut_avlConstWalk (&td->t, &tree->t, f, a); + ddsrt_avl_const_walk (&td->t, &tree->t, f, a); } -void ut_avlCWalkRange (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, const void *min, const void *max, ut_avlWalk_t f, void *a) +void ddsrt_avl_cwalk_range (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, const void *min, const void *max, ddsrt_avl_walk_t f, void *a) { - ut_avlWalkRange (&td->t, &tree->t, min, max, f, a); + ddsrt_avl_walk_range (&td->t, &tree->t, min, max, f, a); } -void ut_avlCConstWalkRange (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *min, const void *max, ut_avlConstWalk_t f, void *a) +void ddsrt_avl_cconst_walk_range (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *min, const void *max, ddsrt_avl_const_walk_t f, void *a) { - ut_avlConstWalkRange (&td->t, &tree->t, min, max, f, a); + ddsrt_avl_const_walk_range (&td->t, &tree->t, min, max, f, a); } -void ut_avlCWalkRangeReverse (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, const void *min, const void *max, ut_avlWalk_t f, void *a) +void ddsrt_avl_cwalk_range_reverse (const ddsrt_avl_ctreedef_t *td, ddsrt_avl_ctree_t *tree, const void *min, const void *max, ddsrt_avl_walk_t f, void *a) { - ut_avlWalkRangeReverse (&td->t, &tree->t, min, max, f, a); + ddsrt_avl_walk_range_reverse (&td->t, &tree->t, min, max, f, a); } -void ut_avlCConstWalkRangeReverse (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *min, const void *max, ut_avlConstWalk_t f, void *a) +void ddsrt_avl_cconst_walk_range_reverse (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, const void *min, const void *max, ddsrt_avl_const_walk_t f, void *a) { - ut_avlConstWalkRangeReverse (&td->t, &tree->t, min, max, f, a); + ddsrt_avl_const_walk_range_reverse (&td->t, &tree->t, min, max, f, a); } -void *ut_avlCIterFirst (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, ut_avlCIter_t *iter) +void *ddsrt_avl_citer_first (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, ddsrt_avl_citer_t *iter) { - return ut_avlIterFirst (&td->t, &tree->t, &iter->t); + return ddsrt_avl_iter_first (&td->t, &tree->t, &iter->t); } -void *ut_avlCIterSuccEq (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, ut_avlCIter_t *iter, const void *key) +void *ddsrt_avl_citer_succ_eq (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, ddsrt_avl_citer_t *iter, const void *key) { - return ut_avlIterSuccEq (&td->t, &tree->t, &iter->t, key); + return ddsrt_avl_iter_succ_eq (&td->t, &tree->t, &iter->t, key); } -void *ut_avlCIterSucc (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, ut_avlCIter_t *iter, const void *key) +void *ddsrt_avl_citer_succ (const ddsrt_avl_ctreedef_t *td, const ddsrt_avl_ctree_t *tree, ddsrt_avl_citer_t *iter, const void *key) { - return ut_avlIterSucc (&td->t, &tree->t, &iter->t, key); + return ddsrt_avl_iter_succ (&td->t, &tree->t, &iter->t, key); } -void *ut_avlCIterNext (ut_avlCIter_t *iter) +void *ddsrt_avl_citer_next (ddsrt_avl_citer_t *iter) { /* Added this in-between t variable to satisfy SAL. */ - ut_avlIter_t *t = &(iter->t); - return ut_avlIterNext(t); + ddsrt_avl_iter_t *t = &(iter->t); + return ddsrt_avl_iter_next(t); } diff --git a/src/util/src/ut_expand_envvars.c b/src/ddsrt/src/expand_envvars.c similarity index 93% rename from src/util/src/ut_expand_envvars.c rename to src/ddsrt/src/expand_envvars.c index 3b2b999..ded0d0a 100644 --- a/src/util/src/ut_expand_envvars.c +++ b/src/ddsrt/src/expand_envvars.c @@ -19,7 +19,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" #include "dds/ddsrt/string.h" -#include "dds/util/ut_expand_envvars.h" +#include "dds/ddsrt/expand_envvars.h" typedef char * (*expand_fn)(const char *src0); @@ -157,7 +157,7 @@ static char *expand_envchar (const char **src, expand_fn expand) return expand_env (name, 0, NULL, expand); } -char *ut_expand_envvars_sh (const char *src0) +char *ddsrt_expand_envvars_sh (const char *src0) { /* Expands $X, ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms; $ and \ can be escaped with \ */ const char *src = src0; @@ -180,11 +180,11 @@ char *ut_expand_envvars_sh (const char *src0) ddsrt_free(dst); return NULL; } else if (*src == '{') { - x = expand_envbrace (&src, &ut_expand_envvars_sh); + x = expand_envbrace (&src, &ddsrt_expand_envvars_sh); } else if (isalnum ((unsigned char) *src) || *src == '_') { - x = expand_envsimple (&src, &ut_expand_envvars_sh); + x = expand_envsimple (&src, &ddsrt_expand_envvars_sh); } else { - x = expand_envchar (&src, &ut_expand_envvars_sh); + x = expand_envchar (&src, &ddsrt_expand_envvars_sh); } if (x == NULL) { ddsrt_free(dst); @@ -203,7 +203,7 @@ char *ut_expand_envvars_sh (const char *src0) return dst; } -char *ut_expand_envvars (const char *src0) +char *ddsrt_expand_envvars (const char *src0) { /* Expands ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, but not $X */ const char *src = src0; @@ -213,7 +213,7 @@ char *ut_expand_envvars (const char *src0) if (*src == '$' && *(src + 1) == '{') { char *x, *xp; src++; - x = expand_envbrace (&src, &ut_expand_envvars); + x = expand_envbrace (&src, &ddsrt_expand_envvars); if (x == NULL) { ddsrt_free(dst); return NULL; diff --git a/src/util/src/ut_fibheap.c b/src/ddsrt/src/fibheap.c similarity index 68% rename from src/util/src/ut_fibheap.c rename to src/ddsrt/src/fibheap.c index a92d186..2e3bcf8 100644 --- a/src/util/src/ut_fibheap.c +++ b/src/ddsrt/src/fibheap.c @@ -14,7 +14,7 @@ #include #include "dds/ddsrt/misc.h" -#include "dds/util/ut_fibheap.h" +#include "dds/ddsrt/fibheap.h" /* max degree: n >= F_{d+2} >= \phi^d ==> d <= log_\phi n, where \phi (as usual) is the golden ratio ~= 1.618. We know n <= (size of @@ -23,24 +23,24 @@ space). */ #define MAX_DEGREE ((unsigned) (sizeof (void *) * CHAR_BIT - 1)) -static int cmp (const ut_fibheapDef_t *fhdef, const ut_fibheapNode_t *a, const ut_fibheapNode_t *b) +static int cmp (const ddsrt_fibheap_def_t *fhdef, const ddsrt_fibheap_node_t *a, const ddsrt_fibheap_node_t *b) { return fhdef->cmp ((const char *) a - fhdef->offset, (const char *) b - fhdef->offset); } -void ut_fibheapDefInit (ut_fibheapDef_t *fhdef, uintptr_t offset, int (*cmp) (const void *va, const void *vb)) +void ddsrt_fibheap_def_init (ddsrt_fibheap_def_t *fhdef, uintptr_t offset, int (*cmp) (const void *va, const void *vb)) { fhdef->offset = offset; fhdef->cmp = cmp; } -void ut_fibheapInit (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh) +void ddsrt_fibheap_init (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh) { DDSRT_UNUSED_ARG(fhdef); fh->roots = NULL; } -void *ut_fibheapMin (const ut_fibheapDef_t *fhdef, const ut_fibheap_t *fh) +void *ddsrt_fibheap_min (const ddsrt_fibheap_def_t *fhdef, const ddsrt_fibheap_t *fh) { if (fh->roots) { return (void *) ((char *) fh->roots - fhdef->offset); @@ -49,16 +49,16 @@ void *ut_fibheapMin (const ut_fibheapDef_t *fhdef, const ut_fibheap_t *fh) } } -static void ut_fibheap_merge_nonempty_list (ut_fibheapNode_t **markptr, ut_fibheapNode_t *list) +static void ddsrt_fibheap_merge_nonempty_list (ddsrt_fibheap_node_t **markptr, ddsrt_fibheap_node_t *list) { assert (list != NULL); if (*markptr == NULL) { *markptr = list; } else { - ut_fibheapNode_t * const mark = *markptr; - ut_fibheapNode_t * const old_mark_next = mark->next; - ut_fibheapNode_t * const old_list_prev = list->prev; + ddsrt_fibheap_node_t * const mark = *markptr; + ddsrt_fibheap_node_t * const old_mark_next = mark->next; + ddsrt_fibheap_node_t * const old_list_prev = list->prev; mark->next = list; old_mark_next->prev = old_list_prev; list->prev = mark; @@ -66,7 +66,7 @@ static void ut_fibheap_merge_nonempty_list (ut_fibheapNode_t **markptr, ut_fibhe } } -static void ut_fibheap_merge_into (const ut_fibheapDef_t *fhdef, ut_fibheap_t *a, ut_fibheapNode_t * const br) +static void ddsrt_fibheap_merge_into (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *a, ddsrt_fibheap_node_t * const br) { if (br == NULL) { return; @@ -74,25 +74,25 @@ static void ut_fibheap_merge_into (const ut_fibheapDef_t *fhdef, ut_fibheap_t *a a->roots = br; } else { const int c = cmp (fhdef, br, a->roots); - ut_fibheap_merge_nonempty_list (&a->roots, br); + ddsrt_fibheap_merge_nonempty_list (&a->roots, br); if (c < 0) a->roots = br; } } -void ut_fibheapMerge (const ut_fibheapDef_t *fhdef, ut_fibheap_t *a, ut_fibheap_t *b) +void ddsrt_fibheap_merge (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *a, ddsrt_fibheap_t *b) { /* merges nodes from b into a, thereafter, b is empty */ - ut_fibheap_merge_into (fhdef, a, b->roots); + ddsrt_fibheap_merge_into (fhdef, a, b->roots); b->roots = NULL; } -void ut_fibheapInsert (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, const void *vnode) +void ddsrt_fibheap_insert (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh, const void *vnode) { /* fibheap node is opaque => nothing in node changes as far as caller is concerned => declare as const argument, then drop the const qualifier */ - ut_fibheapNode_t *node = (ut_fibheapNode_t *) ((char *) vnode + fhdef->offset); + ddsrt_fibheap_node_t *node = (ddsrt_fibheap_node_t *) ((char *) vnode + fhdef->offset); /* new heap of degree 0 (i.e., only containing NODE) */ node->parent = node->children = NULL; @@ -101,24 +101,24 @@ void ut_fibheapInsert (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, const voi node->degree = 0; /* then merge it in */ - ut_fibheap_merge_into (fhdef, fh, node); + ddsrt_fibheap_merge_into (fhdef, fh, node); } -static void ut_fibheap_add_as_child (ut_fibheapNode_t *parent, ut_fibheapNode_t *child) +static void ddsrt_fibheap_add_as_child (ddsrt_fibheap_node_t *parent, ddsrt_fibheap_node_t *child) { parent->degree++; child->parent = parent; child->prev = child->next = child; - ut_fibheap_merge_nonempty_list (&parent->children, child); + ddsrt_fibheap_merge_nonempty_list (&parent->children, child); } -static void ut_fibheap_delete_one_from_list (ut_fibheapNode_t **markptr, ut_fibheapNode_t *node) +static void ddsrt_fibheap_delete_one_from_list (ddsrt_fibheap_node_t **markptr, ddsrt_fibheap_node_t *node) { if (node->next == node) { *markptr = NULL; } else { - ut_fibheapNode_t * const node_prev = node->prev; - ut_fibheapNode_t * const node_next = node->next; + ddsrt_fibheap_node_t * const node_prev = node->prev; + ddsrt_fibheap_node_t * const node_next = node->next; node_prev->next = node_next; node_next->prev = node_prev; if (*markptr == node) { @@ -127,10 +127,10 @@ static void ut_fibheap_delete_one_from_list (ut_fibheapNode_t **markptr, ut_fibh } } -void *ut_fibheapExtractMin (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh) +void *ddsrt_fibheap_extract_min (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh) { - ut_fibheapNode_t *roots[MAX_DEGREE + 1]; - ut_fibheapNode_t * const min = fh->roots; + ddsrt_fibheap_node_t *roots[MAX_DEGREE + 1]; + ddsrt_fibheap_node_t * const min = fh->roots; unsigned min_degree_noninit = 0; /* empty heap => return that, alternative would be to require the @@ -147,7 +147,7 @@ void *ut_fibheapExtractMin (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh) } /* remove min from fh->roots */ - ut_fibheap_delete_one_from_list (&fh->roots, min); + ddsrt_fibheap_delete_one_from_list (&fh->roots, min); /* FIXME: can speed up by combining a few things & improving locality of reference by scanning lists only once */ @@ -155,30 +155,30 @@ void *ut_fibheapExtractMin (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh) /* insert min'schildren as new roots -- must fix parent pointers, and reset marks because roots are always unmarked */ if (min->children) { - ut_fibheapNode_t * const mark = min->children; - ut_fibheapNode_t *n = mark; + ddsrt_fibheap_node_t * const mark = min->children; + ddsrt_fibheap_node_t *n = mark; do { n->parent = NULL; n->mark = 0; n = n->next; } while (n != mark); - ut_fibheap_merge_nonempty_list (&fh->roots, min->children); + ddsrt_fibheap_merge_nonempty_list (&fh->roots, min->children); } /* iteratively merge roots of equal degree, completely messing up fh->roots, ... */ { - ut_fibheapNode_t *const mark = fh->roots; - ut_fibheapNode_t *n = mark; + ddsrt_fibheap_node_t *const mark = fh->roots; + ddsrt_fibheap_node_t *n = mark; do { - ut_fibheapNode_t * const n1 = n->next; + ddsrt_fibheap_node_t * const n1 = n->next; /* if n is first root with this high a degree, there's certainly not going to be another root to merge with yet */ while (n->degree < min_degree_noninit && roots[n->degree]) { unsigned const degree = n->degree; - ut_fibheapNode_t *u, *v; + ddsrt_fibheap_node_t *u, *v; if (cmp (fhdef, roots[degree], n) < 0) { u = roots[degree]; v = n; @@ -186,7 +186,7 @@ void *ut_fibheapExtractMin (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh) u = n; v = roots[degree]; } roots[degree] = NULL; - ut_fibheap_add_as_child (u, v); + ddsrt_fibheap_add_as_child (u, v); n = u; } @@ -206,7 +206,7 @@ void *ut_fibheapExtractMin (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh) memory at an astonishing rate, and we need to compare the root keys anyway to find the minimum */ { - ut_fibheapNode_t *mark, *cursor, *newmin; + ddsrt_fibheap_node_t *mark, *cursor, *newmin; unsigned i; for (i = 0; roots[i] == NULL; i++) { assert (i+1 < min_degree_noninit); @@ -216,7 +216,7 @@ void *ut_fibheapExtractMin (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh) mark = cursor = roots[i]; for (++i; i < min_degree_noninit; i++) { if (roots[i]) { - ut_fibheapNode_t * const r = roots[i]; + ddsrt_fibheap_node_t * const r = roots[i]; if (cmp (fhdef, r, newmin) < 0) newmin = r; r->prev = cursor; @@ -233,17 +233,17 @@ void *ut_fibheapExtractMin (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh) return (void *) ((char *) min - fhdef->offset); } -static void ut_fibheap_cutnode (ut_fibheap_t *fh, ut_fibheapNode_t *node) +static void ddsrt_fibheap_cutnode (ddsrt_fibheap_t *fh, ddsrt_fibheap_node_t *node) { /* by marking the node, we ensure it gets cut */ node->mark = 1; /* traverse towards the root, cutting marked nodes on the way */ while (node->parent && node->mark) { - ut_fibheapNode_t *parent = node->parent; + ddsrt_fibheap_node_t *parent = node->parent; assert (parent->degree > 0); - ut_fibheap_delete_one_from_list (&parent->children, node); + ddsrt_fibheap_delete_one_from_list (&parent->children, node); parent->degree--; node->mark = 0; @@ -252,7 +252,7 @@ static void ut_fibheap_cutnode (ut_fibheap_t *fh, ut_fibheapNode_t *node) /* we assume heap properties haven't been violated, and therefore none of the nodes we cut can become the new minimum */ - ut_fibheap_merge_nonempty_list (&fh->roots, node); + ddsrt_fibheap_merge_nonempty_list (&fh->roots, node); node = parent; } @@ -264,12 +264,12 @@ static void ut_fibheap_cutnode (ut_fibheap_t *fh, ut_fibheapNode_t *node) } } -void ut_fibheapDecreaseKey (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, const void *vnode) +void ddsrt_fibheap_decrease_key (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh, const void *vnode) { /* fibheap node is opaque => nothing in node changes as far as caller is concerned => declare as const argument, then drop the const qualifier */ - ut_fibheapNode_t *node = (ut_fibheapNode_t *) ((char *) vnode + fhdef->offset); + ddsrt_fibheap_node_t *node = (ddsrt_fibheap_node_t *) ((char *) vnode + fhdef->offset); if (node->parent && cmp (fhdef, node->parent, node) <= 0) { /* heap property not violated, do nothing */ @@ -278,7 +278,7 @@ void ut_fibheapDecreaseKey (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, cons /* heap property violated by decreasing the key, but we cut it pretending nothing has happened yet, then fix up the minimum if this node is the new minimum */ - ut_fibheap_cutnode (fh, node); + ddsrt_fibheap_cutnode (fh, node); } if (cmp (fhdef, node, fh->roots) < 0) { fh->roots = node; @@ -286,19 +286,19 @@ void ut_fibheapDecreaseKey (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, cons } } -void ut_fibheapDelete (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, const void *vnode) +void ddsrt_fibheap_delete (const ddsrt_fibheap_def_t *fhdef, ddsrt_fibheap_t *fh, const void *vnode) { /* fibheap node is opaque => nothing in node changes as far as caller is concerned => declare as const argument, then drop the const qualifier */ - ut_fibheapNode_t *node = (ut_fibheapNode_t *) ((char *) vnode + fhdef->offset); + ddsrt_fibheap_node_t *node = (ddsrt_fibheap_node_t *) ((char *) vnode + fhdef->offset); /* essentially decreasekey(node);extractmin while pretending the node key is -infinity. That means we can't directly call decreasekey, because it considers the actual value of the key. */ if (node->parent != NULL) { - ut_fibheap_cutnode (fh, node); + ddsrt_fibheap_cutnode (fh, node); } fh->roots = node; - (void) ut_fibheapExtractMin (fhdef, fh); + (void) ddsrt_fibheap_extract_min (fhdef, fh); } diff --git a/src/util/src/ut_hopscotch.c b/src/ddsrt/src/hopscotch.c similarity index 67% rename from src/util/src/ut_hopscotch.c rename to src/ddsrt/src/hopscotch.c index 276c9cb..eef7efb 100644 --- a/src/util/src/ut_hopscotch.c +++ b/src/ddsrt/src/hopscotch.c @@ -15,7 +15,7 @@ #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" -#include "dds/util/ut_hopscotch.h" +#include "dds/ddsrt/hopscotch.h" #define HH_HOP_RANGE 32 #define HH_ADD_RANGE 64 @@ -27,45 +27,45 @@ #define N_BACKING_LOCKS 32 #define N_RESIZE_LOCKS 8 -struct ut_chhBucket { +struct ddsrt_chh_bucket { ddsrt_atomic_uint32_t hopinfo; ddsrt_atomic_uint32_t timestamp; ddsrt_atomic_uint32_t lock; ddsrt_atomic_voidp_t data; }; -struct ut_chhBucketArray { +struct ddsrt_chh_bucket_array { uint32_t size; /* power of 2 */ - struct ut_chhBucket bs[]; + struct ddsrt_chh_bucket bs[]; }; -struct ut_chhBackingLock { +struct ddsrt_chh_backing_lock { ddsrt_mutex_t lock; ddsrt_cond_t cv; }; -struct ut_chh { - ddsrt_atomic_voidp_t buckets; /* struct ut_chhBucketArray * */ - struct ut_chhBackingLock backingLocks[N_BACKING_LOCKS]; - ut_hhHash_fn hash; - ut_hhEquals_fn equals; +struct ddsrt_chh { + ddsrt_atomic_voidp_t buckets; /* struct ddsrt_chh_bucket_array * */ + struct ddsrt_chh_backing_lock backingLocks[N_BACKING_LOCKS]; + ddsrt_hh_hash_fn hash; + ddsrt_hh_equals_fn equals; ddsrt_rwlock_t resize_locks[N_RESIZE_LOCKS]; - ut_hhBucketsGc_fn gc_buckets; + ddsrt_hh_buckets_gc_fn gc_buckets; }; #define CHH_MAX_TRIES 4 #define CHH_BUSY ((void *) 1) -static int ut_chhDataValid_p (void *data) +static int ddsrt_chh_data_valid_p (void *data) { return data != NULL && data != CHH_BUSY; } -static int ut_chhInit (struct ut_chh *rt, uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals, ut_hhBucketsGc_fn gc_buckets) +static int ddsrt_chh_init (struct ddsrt_chh *rt, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets) { uint32_t size; uint32_t i; - struct ut_chhBucketArray *buckets; + struct ddsrt_chh_bucket_array *buckets; size = HH_HOP_RANGE; while (size < init_size) { @@ -75,11 +75,11 @@ static int ut_chhInit (struct ut_chh *rt, uint32_t init_size, ut_hhHash_fn hash, rt->equals = equals; rt->gc_buckets = gc_buckets; - buckets = ddsrt_malloc (offsetof (struct ut_chhBucketArray, bs) + size * sizeof (*buckets->bs)); + buckets = ddsrt_malloc (offsetof (struct ddsrt_chh_bucket_array, bs) + size * sizeof (*buckets->bs)); ddsrt_atomic_stvoidp (&rt->buckets, buckets); buckets->size = size; for (i = 0; i < size; i++) { - struct ut_chhBucket *b = &buckets->bs[i]; + struct ddsrt_chh_bucket *b = &buckets->bs[i]; ddsrt_atomic_st32 (&b->hopinfo, 0); ddsrt_atomic_st32 (&b->timestamp, 0); ddsrt_atomic_st32 (&b->lock, 0); @@ -87,7 +87,7 @@ static int ut_chhInit (struct ut_chh *rt, uint32_t init_size, ut_hhHash_fn hash, } for (i = 0; i < N_BACKING_LOCKS; i++) { - struct ut_chhBackingLock *s = &rt->backingLocks[i]; + struct ddsrt_chh_backing_lock *s = &rt->backingLocks[i]; ddsrt_mutex_init (&s->lock); ddsrt_cond_init (&s->cv); } @@ -97,12 +97,12 @@ static int ut_chhInit (struct ut_chh *rt, uint32_t init_size, ut_hhHash_fn hash, return 0; } -static void ut_chhFini (struct ut_chh *rt) +static void ddsrt_chh_fini (struct ddsrt_chh *rt) { int i; ddsrt_free (ddsrt_atomic_ldvoidp (&rt->buckets)); for (i = 0; i < N_BACKING_LOCKS; i++) { - struct ut_chhBackingLock *s = &rt->backingLocks[i]; + struct ddsrt_chh_backing_lock *s = &rt->backingLocks[i]; ddsrt_cond_destroy (&s->cv); ddsrt_mutex_destroy (&s->lock); } @@ -111,10 +111,10 @@ static void ut_chhFini (struct ut_chh *rt) } } -struct ut_chh *ut_chhNew (uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals, ut_hhBucketsGc_fn gc_buckets) +struct ddsrt_chh *ddsrt_chh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals, ddsrt_hh_buckets_gc_fn gc_buckets) { - struct ut_chh *hh = ddsrt_malloc (sizeof (*hh)); - if (ut_chhInit (hh, init_size, hash, equals, gc_buckets) < 0) { + struct ddsrt_chh *hh = ddsrt_malloc (sizeof (*hh)); + if (ddsrt_chh_init (hh, init_size, hash, equals, gc_buckets) < 0) { ddsrt_free (hh); return NULL; } else { @@ -122,22 +122,22 @@ struct ut_chh *ut_chhNew (uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn } } -void ut_chhFree (struct ut_chh * UT_HH_RESTRICT hh) +void ddsrt_chh_free (struct ddsrt_chh * __restrict hh) { - ut_chhFini (hh); + ddsrt_chh_fini (hh); ddsrt_free (hh); } #define LOCKBIT ((uint32_t)1 << 31) -static void ut_chhLockBucket (struct ut_chh *rt, uint32_t bidx) +static void ddsrt_chh_lock_bucket (struct ddsrt_chh *rt, uint32_t bidx) { /* Lock: MSB <=> LOCKBIT, LSBs <=> wait count; note that (o&LOCKBIT)==0 means a thread can sneak in when there are already waiters, changing it to o==0 would avoid that. */ - struct ut_chhBucketArray * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); - struct ut_chhBucket * const b = &bsary->bs[bidx]; - struct ut_chhBackingLock * const s = &rt->backingLocks[bidx % N_BACKING_LOCKS]; + struct ddsrt_chh_bucket_array * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket * const b = &bsary->bs[bidx]; + struct ddsrt_chh_backing_lock * const s = &rt->backingLocks[bidx % N_BACKING_LOCKS]; uint32_t o, n; fastpath_retry: o = ddsrt_atomic_ld32 (&b->lock); @@ -162,11 +162,11 @@ static void ut_chhLockBucket (struct ut_chh *rt, uint32_t bidx) } } -static void ut_chhUnlockBucket (struct ut_chh *rt, uint32_t bidx) +static void ddsrt_chh_unlock_bucket (struct ddsrt_chh *rt, uint32_t bidx) { - struct ut_chhBucketArray * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); - struct ut_chhBucket * const b = &bsary->bs[bidx]; - struct ut_chhBackingLock * const s = &rt->backingLocks[bidx % N_BACKING_LOCKS]; + struct ddsrt_chh_bucket_array * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket * const b = &bsary->bs[bidx]; + struct ddsrt_chh_backing_lock * const s = &rt->backingLocks[bidx % N_BACKING_LOCKS]; uint32_t o, n; retry: o = ddsrt_atomic_ld32 (&b->lock); @@ -190,9 +190,9 @@ static void ut_chhUnlockBucket (struct ut_chh *rt, uint32_t bidx) } } -static void *ut_chhLookupInternal (struct ut_chhBucketArray const * const bsary, ut_hhEquals_fn equals, const uint32_t bucket, const void *template) +static void *ddsrt_chh_lookup_internal (struct ddsrt_chh_bucket_array const * const bsary, ddsrt_hh_equals_fn equals, const uint32_t bucket, const void *template) { - struct ut_chhBucket const * const bs = bsary->bs; + struct ddsrt_chh_bucket const * const bs = bsary->bs; const uint32_t idxmask = bsary->size - 1; uint32_t timestamp; int try_counter = 0; @@ -205,7 +205,7 @@ static void *ut_chhLookupInternal (struct ut_chhBucketArray const * const bsary, for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) { const uint32_t bidx = (bucket + idx) & idxmask; void *data = ddsrt_atomic_ldvoidp (&bs[bidx].data); - if (ut_chhDataValid_p (data) && equals (data, template)) { + if (ddsrt_chh_data_valid_p (data) && equals (data, template)) { return data; } } @@ -218,7 +218,7 @@ static void *ut_chhLookupInternal (struct ut_chhBucketArray const * const bsary, for (idx = 0; idx < HH_HOP_RANGE; idx++) { const uint32_t bidx = (bucket + idx) & idxmask; void *data = ddsrt_atomic_ldvoidp (&bs[bidx].data); - if (ut_chhDataValid_p (data) && equals (data, template)) { + if (ddsrt_chh_data_valid_p (data) && equals (data, template)) { return data; } } @@ -232,19 +232,19 @@ static void *ut_chhLookupInternal (struct ut_chhBucketArray const * const bsary, ddsrt_atomic_st32 (var__, (expr_)); \ } while (0) -void *ut_chhLookup (struct ut_chh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template) +void *ddsrt_chh_lookup (struct ddsrt_chh * __restrict rt, const void * __restrict template) { - struct ut_chhBucketArray const * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket_array const * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); const uint32_t hash = rt->hash (template); const uint32_t idxmask = bsary->size - 1; const uint32_t bucket = hash & idxmask; - return ut_chhLookupInternal (bsary, rt->equals, bucket, template); + return ddsrt_chh_lookup_internal (bsary, rt->equals, bucket, template); } -static uint32_t ut_chhFindCloserFreeBucket (struct ut_chh *rt, uint32_t free_bucket, uint32_t *free_distance) +static uint32_t ddsrt_chh_find_closer_free_bucket (struct ddsrt_chh *rt, uint32_t free_bucket, uint32_t *free_distance) { - struct ut_chhBucketArray * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); - struct ut_chhBucket * const bs = bsary->bs; + struct ddsrt_chh_bucket_array * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket * const bs = bsary->bs; const uint32_t idxmask = bsary->size - 1; uint32_t move_bucket, free_dist; move_bucket = (free_bucket - (HH_HOP_RANGE - 1)) & idxmask; @@ -260,7 +260,7 @@ static uint32_t ut_chhFindCloserFreeBucket (struct ut_chh *rt, uint32_t free_buc } } if (move_free_distance != NOT_A_BUCKET) { - ut_chhLockBucket (rt, move_bucket); + ddsrt_chh_lock_bucket (rt, move_bucket); if (start_hop_info == ddsrt_atomic_ld32 (&bs[move_bucket].hopinfo)) { uint32_t new_free_bucket = (move_bucket + move_free_distance) & idxmask; @@ -272,31 +272,31 @@ static uint32_t ut_chhFindCloserFreeBucket (struct ut_chh *rt, uint32_t free_buc ddsrt_atomic_rmw32_nonatomic (&bs[move_bucket].hopinfo, x, x & ~(1u << move_free_distance)); *free_distance -= free_dist - move_free_distance; - ut_chhUnlockBucket (rt, move_bucket); + ddsrt_chh_unlock_bucket (rt, move_bucket); return new_free_bucket; } - ut_chhUnlockBucket (rt, move_bucket); + ddsrt_chh_unlock_bucket (rt, move_bucket); } move_bucket = (move_bucket + 1) & idxmask; } return NOT_A_BUCKET; } -static void ut_chhResize (struct ut_chh *rt) +static void ddsrt_chh_resize (struct ddsrt_chh *rt) { /* doubles the size => bucket index gains one bit at the msb => start bucket is unchanged or moved into the added half of the set => those for which the (new) msb is 0 are guaranteed to fit, and so are those for which the (new) msb is 1 => never have to resize recursively */ - struct ut_chhBucketArray * const bsary0 = ddsrt_atomic_ldvoidp (&rt->buckets); - struct ut_chhBucket * const bs0 = bsary0->bs; - struct ut_chhBucketArray *bsary1; - struct ut_chhBucket *bs1; + struct ddsrt_chh_bucket_array * const bsary0 = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket * const bs0 = bsary0->bs; + struct ddsrt_chh_bucket_array *bsary1; + struct ddsrt_chh_bucket *bs1; uint32_t i, idxmask0, idxmask1; assert (bsary0->size > 0); - bsary1 = ddsrt_malloc (offsetof (struct ut_chhBucketArray, bs) + 2 * bsary0->size * sizeof (*bsary1->bs)); + bsary1 = ddsrt_malloc (offsetof (struct ddsrt_chh_bucket_array, bs) + 2 * bsary0->size * sizeof (*bsary1->bs)); bsary1->size = 2 * bsary0->size; bs1 = bsary1->bs; @@ -327,15 +327,15 @@ static void ut_chhResize (struct ut_chh *rt) rt->gc_buckets (bsary0); } -int ut_chhAdd (struct ut_chh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT data) +int ddsrt_chh_add (struct ddsrt_chh * __restrict rt, const void * __restrict data) { const uint32_t hash = rt->hash (data); uint32_t size; ddsrt_rwlock_read (&rt->resize_locks[hash % N_RESIZE_LOCKS]); { - struct ut_chhBucketArray * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); - struct ut_chhBucket * const bs = bsary->bs; + struct ddsrt_chh_bucket_array * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket * const bs = bsary->bs; uint32_t idxmask; uint32_t start_bucket, free_distance, free_bucket; @@ -343,9 +343,9 @@ int ut_chhAdd (struct ut_chh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT da idxmask = size - 1; start_bucket = hash & idxmask; - ut_chhLockBucket (rt, start_bucket); - if (ut_chhLookupInternal (bsary, rt->equals, start_bucket, data)) { - ut_chhUnlockBucket (rt, start_bucket); + ddsrt_chh_lock_bucket (rt, start_bucket); + if (ddsrt_chh_lookup_internal (bsary, rt->equals, start_bucket, data)) { + ddsrt_chh_unlock_bucket (rt, start_bucket); ddsrt_rwlock_unlock (&rt->resize_locks[hash % N_RESIZE_LOCKS]); return 0; } @@ -365,77 +365,77 @@ int ut_chhAdd (struct ut_chh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT da ddsrt_atomic_rmw32_nonatomic (&bs[start_bucket].hopinfo, x, x | (1u << free_distance)); ddsrt_atomic_fence (); ddsrt_atomic_stvoidp (&bs[free_bucket].data, (void *) data); - ut_chhUnlockBucket (rt, start_bucket); + ddsrt_chh_unlock_bucket (rt, start_bucket); ddsrt_rwlock_unlock (&rt->resize_locks[hash % N_RESIZE_LOCKS]); return 1; } - free_bucket = ut_chhFindCloserFreeBucket (rt, free_bucket, &free_distance); + free_bucket = ddsrt_chh_find_closer_free_bucket (rt, free_bucket, &free_distance); assert (free_bucket == NOT_A_BUCKET || free_bucket <= idxmask); } while (free_bucket != NOT_A_BUCKET); } - ut_chhUnlockBucket (rt, start_bucket); + ddsrt_chh_unlock_bucket (rt, start_bucket); } ddsrt_rwlock_unlock (&rt->resize_locks[hash % N_RESIZE_LOCKS]); { int i; - struct ut_chhBucketArray *bsary1; + struct ddsrt_chh_bucket_array *bsary1; for (i = 0; i < N_RESIZE_LOCKS; i++) { ddsrt_rwlock_write (&rt->resize_locks[i]); } /* another thread may have sneaked past and grown the hash table */ bsary1 = ddsrt_atomic_ldvoidp (&rt->buckets); if (bsary1->size == size) { - ut_chhResize (rt); + ddsrt_chh_resize (rt); } for (i = 0; i < N_RESIZE_LOCKS; i++) { ddsrt_rwlock_unlock (&rt->resize_locks[i]); } } - return ut_chhAdd (rt, data); + return ddsrt_chh_add (rt, data); } -int ut_chhRemove (struct ut_chh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template) +int ddsrt_chh_remove (struct ddsrt_chh * __restrict rt, const void * __restrict template) { const uint32_t hash = rt->hash (template); ddsrt_rwlock_read (&rt->resize_locks[hash % N_RESIZE_LOCKS]); { - struct ut_chhBucketArray * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); - struct ut_chhBucket * const bs = bsary->bs; + struct ddsrt_chh_bucket_array * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket * const bs = bsary->bs; const uint32_t size = bsary->size; const uint32_t idxmask = size - 1; const uint32_t bucket = hash & idxmask; uint32_t hopinfo; uint32_t idx; - ut_chhLockBucket (rt, bucket); + ddsrt_chh_lock_bucket (rt, bucket); hopinfo = ddsrt_atomic_ld32 (&bs[bucket].hopinfo); for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) { if (hopinfo & 1) { const uint32_t bidx = (bucket + idx) & idxmask; void *data = ddsrt_atomic_ldvoidp (&bs[bidx].data); - if (ut_chhDataValid_p (data) && rt->equals (data, template)) { + if (ddsrt_chh_data_valid_p (data) && rt->equals (data, template)) { ddsrt_atomic_stvoidp (&bs[bidx].data, NULL); ddsrt_atomic_rmw32_nonatomic (&bs[bucket].hopinfo, x, x & ~(1u << idx)); - ut_chhUnlockBucket (rt, bucket); + ddsrt_chh_unlock_bucket (rt, bucket); ddsrt_rwlock_unlock (&rt->resize_locks[hash % N_RESIZE_LOCKS]); return 1; } } } - ut_chhUnlockBucket (rt, bucket); + ddsrt_chh_unlock_bucket (rt, bucket); } ddsrt_rwlock_unlock (&rt->resize_locks[hash % N_RESIZE_LOCKS]); return 0; } -void ut_chhEnumUnsafe (struct ut_chh * UT_HH_RESTRICT rt, void (*f) (void *a, void *f_arg), void *f_arg) +void ddsrt_chh_enum_unsafe (struct ddsrt_chh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg) { - struct ut_chhBucketArray * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); - struct ut_chhBucket * const bs = bsary->bs; + struct ddsrt_chh_bucket_array * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket * const bs = bsary->bs; uint32_t i; for (i = 0; i < bsary->size; i++) { void *data = ddsrt_atomic_ldvoidp (&bs[i].data); @@ -445,7 +445,7 @@ void ut_chhEnumUnsafe (struct ut_chh * UT_HH_RESTRICT rt, void (*f) (void *a, vo } } -void *ut_chhIterNext (struct ut_chhIter *it) +void *ddsrt_chh_iter_next (struct ddsrt_chh_iter *it) { uint32_t i; for (i = it->cursor; i < it->size; i++) { @@ -458,30 +458,30 @@ void *ut_chhIterNext (struct ut_chhIter *it) return NULL; } -void *ut_chhIterFirst (struct ut_chh * UT_HH_RESTRICT rt, struct ut_chhIter *it) +void *ddsrt_chh_iter_first (struct ddsrt_chh * __restrict rt, struct ddsrt_chh_iter *it) { - struct ut_chhBucketArray * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); + struct ddsrt_chh_bucket_array * const bsary = ddsrt_atomic_ldvoidp (&rt->buckets); it->bs = bsary->bs; it->size = bsary->size; it->cursor = 0; - return ut_chhIterNext (it); + return ddsrt_chh_iter_next (it); } /************* SEQUENTIAL VERSION ***************/ -struct ut_hhBucket { +struct ddsrt_hh_bucket { uint32_t hopinfo; void *data; }; -struct ut_hh { +struct ddsrt_hh { uint32_t size; /* power of 2 */ - struct ut_hhBucket *buckets; - ut_hhHash_fn hash; - ut_hhEquals_fn equals; + struct ddsrt_hh_bucket *buckets; + ddsrt_hh_hash_fn hash; + ddsrt_hh_equals_fn equals; }; -static void ut_hhInit (struct ut_hh *rt, uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals) +static void ddsrt_hh_init (struct ddsrt_hh *rt, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals) { uint32_t size = HH_HOP_RANGE; uint32_t i; @@ -498,25 +498,25 @@ static void ut_hhInit (struct ut_hh *rt, uint32_t init_size, ut_hhHash_fn hash, } } -static void ut_hhFini (struct ut_hh *rt) +static void ddsrt_hh_fini (struct ddsrt_hh *rt) { ddsrt_free (rt->buckets); } -struct ut_hh *ut_hhNew (uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals) +struct ddsrt_hh *ddsrt_hh_new (uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals) { - struct ut_hh *hh = ddsrt_malloc (sizeof (*hh)); - ut_hhInit (hh, init_size, hash, equals); + struct ddsrt_hh *hh = ddsrt_malloc (sizeof (*hh)); + ddsrt_hh_init (hh, init_size, hash, equals); return hh; } -void ut_hhFree (struct ut_hh * UT_HH_RESTRICT hh) +void ddsrt_hh_free (struct ddsrt_hh * __restrict hh) { - ut_hhFini (hh); + ddsrt_hh_fini (hh); ddsrt_free (hh); } -static void *ut_hhLookupInternal (const struct ut_hh *rt, const uint32_t bucket, const void *template) +static void *ddsrt_hh_lookup_internal (const struct ddsrt_hh *rt, const uint32_t bucket, const void *template) { const uint32_t idxmask = rt->size - 1; uint32_t hopinfo = rt->buckets[bucket].hopinfo; @@ -530,15 +530,15 @@ static void *ut_hhLookupInternal (const struct ut_hh *rt, const uint32_t bucket, return NULL; } -void *ut_hhLookup (const struct ut_hh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template) +void *ddsrt_hh_lookup (const struct ddsrt_hh * __restrict rt, const void * __restrict template) { const uint32_t hash = rt->hash (template); const uint32_t idxmask = rt->size - 1; const uint32_t bucket = hash & idxmask; - return ut_hhLookupInternal (rt, bucket, template); + return ddsrt_hh_lookup_internal (rt, bucket, template); } -static uint32_t ut_hhFindCloserFreeBucket (struct ut_hh *rt, uint32_t free_bucket, uint32_t *free_distance) +static uint32_t ddsrt_hh_find_closer_free_bucket (struct ddsrt_hh *rt, uint32_t free_bucket, uint32_t *free_distance) { const uint32_t idxmask = rt->size - 1; uint32_t move_bucket, free_dist; @@ -567,9 +567,9 @@ static uint32_t ut_hhFindCloserFreeBucket (struct ut_hh *rt, uint32_t free_bucke return NOT_A_BUCKET; } -static void ut_hhResize (struct ut_hh *rt) +static void ddsrt_hh_resize (struct ddsrt_hh *rt) { - struct ut_hhBucket *bs1; + struct ddsrt_hh_bucket *bs1; uint32_t i, idxmask0, idxmask1; bs1 = ddsrt_malloc (2 * rt->size * sizeof (*rt->buckets)); @@ -599,14 +599,14 @@ static void ut_hhResize (struct ut_hh *rt) rt->buckets = bs1; } -int ut_hhAdd (struct ut_hh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT data) +int ddsrt_hh_add (struct ddsrt_hh * __restrict rt, const void * __restrict data) { const uint32_t hash = rt->hash (data); const uint32_t idxmask = rt->size - 1; const uint32_t start_bucket = hash & idxmask; uint32_t free_distance, free_bucket; - if (ut_hhLookupInternal (rt, start_bucket, data)) { + if (ddsrt_hh_lookup_internal (rt, start_bucket, data)) { return 0; } @@ -624,16 +624,16 @@ int ut_hhAdd (struct ut_hh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT data rt->buckets[free_bucket].data = (void *) data; return 1; } - free_bucket = ut_hhFindCloserFreeBucket (rt, free_bucket, &free_distance); + free_bucket = ddsrt_hh_find_closer_free_bucket (rt, free_bucket, &free_distance); assert (free_bucket == NOT_A_BUCKET || free_bucket <= idxmask); } while (free_bucket != NOT_A_BUCKET); } - ut_hhResize (rt); - return ut_hhAdd (rt, data); + ddsrt_hh_resize (rt); + return ddsrt_hh_add (rt, data); } -int ut_hhRemove (struct ut_hh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template) +int ddsrt_hh_remove (struct ddsrt_hh * __restrict rt, const void * __restrict template) { const uint32_t hash = rt->hash (template); const uint32_t idxmask = rt->size - 1; @@ -655,7 +655,7 @@ int ut_hhRemove (struct ut_hh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT t return 0; } -void ut_hhEnum (struct ut_hh * UT_HH_RESTRICT rt, void (*f) (void *a, void *f_arg), void *f_arg) +void ddsrt_hh_enum (struct ddsrt_hh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg) { uint32_t i; for (i = 0; i < rt->size; i++) { @@ -666,16 +666,16 @@ void ut_hhEnum (struct ut_hh * UT_HH_RESTRICT rt, void (*f) (void *a, void *f_ar } } -void *ut_hhIterFirst (struct ut_hh * UT_HH_RESTRICT rt, struct ut_hhIter * UT_HH_RESTRICT iter) +void *ddsrt_hh_iter_first (struct ddsrt_hh * __restrict rt, struct ddsrt_hh_iter * __restrict iter) { iter->hh = rt; iter->cursor = 0; - return ut_hhIterNext (iter); + return ddsrt_hh_iter_next (iter); } -void *ut_hhIterNext (struct ut_hhIter * UT_HH_RESTRICT iter) +void *ddsrt_hh_iter_next (struct ddsrt_hh_iter * __restrict iter) { - struct ut_hh *rt = iter->hh; + struct ddsrt_hh *rt = iter->hh; while (iter->cursor < rt->size) { void *data = rt->buckets[iter->cursor].data; iter->cursor++; @@ -688,22 +688,22 @@ void *ut_hhIterNext (struct ut_hhIter * UT_HH_RESTRICT iter) /************* SEQUENTIAL VERSION WITH EMBEDDED DATA ***************/ -struct ut_ehhBucket { +struct ddsrt_ehh_bucket { uint32_t hopinfo; uint32_t inuse; char data[]; }; -struct ut_ehh { +struct ddsrt_ehh { uint32_t size; /* power of 2 */ size_t elemsz; size_t bucketsz; char *buckets; /* ehhBucket, but embedded data messes up the layout */ - ut_hhHash_fn hash; - ut_hhEquals_fn equals; + ddsrt_hh_hash_fn hash; + ddsrt_hh_equals_fn equals; }; -static void ut_ehhInit (struct ut_ehh *rt, size_t elemsz, uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals) +static void ddsrt_ehh_init (struct ddsrt_ehh *rt, size_t elemsz, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals) { uint32_t size = HH_HOP_RANGE; uint32_t i; @@ -714,36 +714,36 @@ static void ut_ehhInit (struct ut_ehh *rt, size_t elemsz, uint32_t init_size, ut rt->equals = equals; rt->size = size; rt->elemsz = elemsz; - rt->bucketsz = sizeof (struct ut_ehhBucket) + ((elemsz+7) & ~(size_t)7); + rt->bucketsz = sizeof (struct ddsrt_ehh_bucket) + ((elemsz+7) & ~(size_t)7); rt->buckets = ddsrt_malloc (size * rt->bucketsz); for (i = 0; i < size; i++) { - struct ut_ehhBucket *b = (struct ut_ehhBucket *) (rt->buckets + i * rt->bucketsz); + struct ddsrt_ehh_bucket *b = (struct ddsrt_ehh_bucket *) (rt->buckets + i * rt->bucketsz); b->hopinfo = 0; b->inuse = 0; } } -static void ut_ehhFini (struct ut_ehh *rt) +static void ddsrt_ehh_fini (struct ddsrt_ehh *rt) { ddsrt_free (rt->buckets); } -struct ut_ehh *ut_ehhNew (size_t elemsz, uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals) +struct ddsrt_ehh *ddsrt_ehh_new (size_t elemsz, uint32_t init_size, ddsrt_hh_hash_fn hash, ddsrt_hh_equals_fn equals) { - struct ut_ehh *hh = ddsrt_malloc (sizeof (*hh)); - ut_ehhInit (hh, elemsz, init_size, hash, equals); + struct ddsrt_ehh *hh = ddsrt_malloc (sizeof (*hh)); + ddsrt_ehh_init (hh, elemsz, init_size, hash, equals); return hh; } -void ut_ehhFree (struct ut_ehh * UT_HH_RESTRICT hh) +void ddsrt_ehh_free (struct ddsrt_ehh * __restrict hh) { - ut_ehhFini (hh); + ddsrt_ehh_fini (hh); ddsrt_free (hh); } -static void *ut_ehhLookupInternal (const struct ut_ehh *rt, uint32_t bucket, const void *template) +static void *ddsrt_ehh_lookup_internal (const struct ddsrt_ehh *rt, uint32_t bucket, const void *template) { - const struct ut_ehhBucket *b = (const struct ut_ehhBucket *) (rt->buckets + bucket * rt->bucketsz); + const struct ddsrt_ehh_bucket *b = (const struct ddsrt_ehh_bucket *) (rt->buckets + bucket * rt->bucketsz); uint32_t hopinfo = b->hopinfo; if (hopinfo & 1) { @@ -758,7 +758,7 @@ static void *ut_ehhLookupInternal (const struct ut_ehh *rt, uint32_t bucket, con bucket = 0; } if (hopinfo & 1) { - b = (const struct ut_ehhBucket *) (rt->buckets + bucket * rt->bucketsz); + b = (const struct ddsrt_ehh_bucket *) (rt->buckets + bucket * rt->bucketsz); if (b->inuse && rt->equals (b->data, template)) { return (void *) b->data; } @@ -767,21 +767,21 @@ static void *ut_ehhLookupInternal (const struct ut_ehh *rt, uint32_t bucket, con return NULL; } -void *ut_ehhLookup (const struct ut_ehh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template) +void *ddsrt_ehh_lookup (const struct ddsrt_ehh * __restrict rt, const void * __restrict template) { const uint32_t hash = rt->hash (template); const uint32_t idxmask = rt->size - 1; const uint32_t bucket = hash & idxmask; - return ut_ehhLookupInternal (rt, bucket, template); + return ddsrt_ehh_lookup_internal (rt, bucket, template); } -static uint32_t ut_ehhFindCloserFreeBucket (struct ut_ehh *rt, uint32_t free_bucket, uint32_t *free_distance) +static uint32_t ddsrt_ehh_find_closer_free_bucket (struct ddsrt_ehh *rt, uint32_t free_bucket, uint32_t *free_distance) { const uint32_t idxmask = rt->size - 1; uint32_t move_bucket, free_dist; move_bucket = (free_bucket - (HH_HOP_RANGE - 1)) & idxmask; for (free_dist = HH_HOP_RANGE - 1; free_dist > 0; free_dist--) { - struct ut_ehhBucket * const mb = (struct ut_ehhBucket *) (rt->buckets + move_bucket * rt->bucketsz); + struct ddsrt_ehh_bucket * const mb = (struct ddsrt_ehh_bucket *) (rt->buckets + move_bucket * rt->bucketsz); uint32_t move_free_distance = NOT_A_BUCKET; uint32_t mask = 1; uint32_t i; @@ -793,8 +793,8 @@ static uint32_t ut_ehhFindCloserFreeBucket (struct ut_ehh *rt, uint32_t free_buc } if (move_free_distance != NOT_A_BUCKET) { uint32_t new_free_bucket = (move_bucket + move_free_distance) & idxmask; - struct ut_ehhBucket * const fb = (struct ut_ehhBucket *) (rt->buckets + free_bucket * rt->bucketsz); - struct ut_ehhBucket * const nfb = (struct ut_ehhBucket *) (rt->buckets + new_free_bucket * rt->bucketsz); + struct ddsrt_ehh_bucket * const fb = (struct ddsrt_ehh_bucket *) (rt->buckets + free_bucket * rt->bucketsz); + struct ddsrt_ehh_bucket * const nfb = (struct ddsrt_ehh_bucket *) (rt->buckets + new_free_bucket * rt->bucketsz); mb->hopinfo |= 1u << free_dist; fb->inuse = 1; memcpy (fb->data, nfb->data, rt->elemsz); @@ -808,7 +808,7 @@ static uint32_t ut_ehhFindCloserFreeBucket (struct ut_ehh *rt, uint32_t free_buc return NOT_A_BUCKET; } -static void ut_ehhResize (struct ut_ehh *rt) +static void ddsrt_ehh_resize (struct ddsrt_ehh *rt) { char *bs1; uint32_t i, idxmask0, idxmask1; @@ -816,22 +816,22 @@ static void ut_ehhResize (struct ut_ehh *rt) bs1 = ddsrt_malloc (2 * rt->size * rt->bucketsz); for (i = 0; i < 2 * rt->size; i++) { - struct ut_ehhBucket *b = (struct ut_ehhBucket *) (bs1 + i * rt->bucketsz); + struct ddsrt_ehh_bucket *b = (struct ddsrt_ehh_bucket *) (bs1 + i * rt->bucketsz); b->hopinfo = 0; b->inuse = 0; } idxmask0 = rt->size - 1; idxmask1 = 2 * rt->size - 1; for (i = 0; i < rt->size; i++) { - struct ut_ehhBucket const * const b = (struct ut_ehhBucket *) (rt->buckets + i * rt->bucketsz); + struct ddsrt_ehh_bucket const * const b = (struct ddsrt_ehh_bucket *) (rt->buckets + i * rt->bucketsz); if (b->inuse) { const uint32_t hash = rt->hash (b->data); const uint32_t old_start_bucket = hash & idxmask0; const uint32_t new_start_bucket = hash & idxmask1; const uint32_t dist = (i >= old_start_bucket) ? (i - old_start_bucket) : (rt->size + i - old_start_bucket); const uint32_t newb = (new_start_bucket + dist) & idxmask1; - struct ut_ehhBucket * const nsb = (struct ut_ehhBucket *) (bs1 + new_start_bucket * rt->bucketsz); - struct ut_ehhBucket * const nb = (struct ut_ehhBucket *) (bs1 + newb * rt->bucketsz); + struct ddsrt_ehh_bucket * const nsb = (struct ddsrt_ehh_bucket *) (bs1 + new_start_bucket * rt->bucketsz); + struct ddsrt_ehh_bucket * const nb = (struct ddsrt_ehh_bucket *) (bs1 + newb * rt->bucketsz); assert (dist < HH_HOP_RANGE); assert (!nb->inuse); nsb->hopinfo |= 1u << dist; @@ -845,20 +845,20 @@ static void ut_ehhResize (struct ut_ehh *rt) rt->buckets = bs1; } -int ut_ehhAdd (struct ut_ehh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT data) +int ddsrt_ehh_add (struct ddsrt_ehh * __restrict rt, const void * __restrict data) { const uint32_t hash = rt->hash (data); const uint32_t idxmask = rt->size - 1; const uint32_t start_bucket = hash & idxmask; uint32_t free_distance, free_bucket; - if (ut_ehhLookupInternal (rt, start_bucket, data)) { + if (ddsrt_ehh_lookup_internal (rt, start_bucket, data)) { return 0; } free_bucket = start_bucket; for (free_distance = 0; free_distance < HH_ADD_RANGE; free_distance++) { - struct ut_ehhBucket const * const fb = (struct ut_ehhBucket *) (rt->buckets + free_bucket * rt->bucketsz); + struct ddsrt_ehh_bucket const * const fb = (struct ddsrt_ehh_bucket *) (rt->buckets + free_bucket * rt->bucketsz); if (!fb->inuse) { break; } @@ -867,73 +867,73 @@ int ut_ehhAdd (struct ut_ehh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT da if (free_distance < HH_ADD_RANGE) { do { if (free_distance < HH_HOP_RANGE) { - struct ut_ehhBucket * const sb = (struct ut_ehhBucket *) (rt->buckets + start_bucket * rt->bucketsz); - struct ut_ehhBucket * const fb = (struct ut_ehhBucket *) (rt->buckets + free_bucket * rt->bucketsz); + struct ddsrt_ehh_bucket * const sb = (struct ddsrt_ehh_bucket *) (rt->buckets + start_bucket * rt->bucketsz); + struct ddsrt_ehh_bucket * const fb = (struct ddsrt_ehh_bucket *) (rt->buckets + free_bucket * rt->bucketsz); assert ((uint32_t) free_bucket == ((start_bucket + free_distance) & idxmask)); sb->hopinfo |= 1u << free_distance; fb->inuse = 1; memcpy (fb->data, data, rt->elemsz); - assert (ut_ehhLookupInternal (rt, start_bucket, data)); + assert (ddsrt_ehh_lookup_internal (rt, start_bucket, data)); return 1; } - free_bucket = ut_ehhFindCloserFreeBucket (rt, free_bucket, &free_distance); + free_bucket = ddsrt_ehh_find_closer_free_bucket (rt, free_bucket, &free_distance); assert (free_bucket == NOT_A_BUCKET || free_bucket <= idxmask); } while (free_bucket != NOT_A_BUCKET); } - ut_ehhResize (rt); - return ut_ehhAdd (rt, data); + ddsrt_ehh_resize (rt); + return ddsrt_ehh_add (rt, data); } -int ut_ehhRemove (struct ut_ehh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template) +int ddsrt_ehh_remove (struct ddsrt_ehh * __restrict rt, const void * __restrict template) { const uint32_t hash = rt->hash (template); const uint32_t idxmask = rt->size - 1; const uint32_t bucket = hash & idxmask; uint32_t hopinfo; - struct ut_ehhBucket *sb; + struct ddsrt_ehh_bucket *sb; uint32_t idx; - sb = (struct ut_ehhBucket *) (rt->buckets + bucket * rt->bucketsz); + sb = (struct ddsrt_ehh_bucket *) (rt->buckets + bucket * rt->bucketsz); hopinfo = sb->hopinfo; for (idx = 0; hopinfo != 0; hopinfo >>= 1, idx++) { if (hopinfo & 1) { const uint32_t bidx = (bucket + idx) & idxmask; - struct ut_ehhBucket *b = (struct ut_ehhBucket *) (rt->buckets + bidx * rt->bucketsz); + struct ddsrt_ehh_bucket *b = (struct ddsrt_ehh_bucket *) (rt->buckets + bidx * rt->bucketsz); if (b->inuse && rt->equals (b->data, template)) { - assert (ut_ehhLookupInternal(rt, bucket, template)); + assert (ddsrt_ehh_lookup_internal(rt, bucket, template)); b->inuse = 0; sb->hopinfo &= ~(1u << idx); return 1; } } } - assert (!ut_ehhLookupInternal(rt, bucket, template)); + assert (!ddsrt_ehh_lookup_internal(rt, bucket, template)); return 0; } -void ut_ehhEnum (struct ut_ehh * UT_HH_RESTRICT rt, void (*f) (void *a, void *f_arg), void *f_arg) +void ddsrt_ehh_enum (struct ddsrt_ehh * __restrict rt, void (*f) (void *a, void *f_arg), void *f_arg) { uint32_t i; for (i = 0; i < rt->size; i++) { - struct ut_ehhBucket *b = (struct ut_ehhBucket *) (rt->buckets + i * rt->bucketsz); + struct ddsrt_ehh_bucket *b = (struct ddsrt_ehh_bucket *) (rt->buckets + i * rt->bucketsz); if (b->inuse) { f (b->data, f_arg); } } } -void *ut_ehhIterFirst (struct ut_ehh * UT_HH_RESTRICT rt, struct ut_ehhIter * UT_HH_RESTRICT iter) +void *ddsrt_ehh_iter_first (struct ddsrt_ehh * __restrict rt, struct ddsrt_ehh_iter * __restrict iter) { iter->hh = rt; iter->cursor = 0; - return ut_ehhIterNext (iter); + return ddsrt_ehh_iter_next (iter); } -void *ut_ehhIterNext (struct ut_ehhIter * UT_HH_RESTRICT iter) +void *ddsrt_ehh_iter_next (struct ddsrt_ehh_iter * __restrict iter) { - struct ut_ehh *rt = iter->hh; + struct ddsrt_ehh *rt = iter->hh; while (iter->cursor < rt->size) { - struct ut_ehhBucket *b = (struct ut_ehhBucket *) (rt->buckets + iter->cursor * rt->bucketsz); + struct ddsrt_ehh_bucket *b = (struct ddsrt_ehh_bucket *) (rt->buckets + iter->cursor * rt->bucketsz); iter->cursor++; if (b->inuse) { return b->data; diff --git a/src/util/src/ut_thread_pool.c b/src/ddsrt/src/thread_pool.c similarity index 88% rename from src/util/src/ut_thread_pool.c rename to src/ddsrt/src/thread_pool.c index acc4258..48cba27 100644 --- a/src/util/src/ut_thread_pool.c +++ b/src/ddsrt/src/thread_pool.c @@ -15,7 +15,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" #include "dds/ddsrt/threads.h" -#include "dds/util/ut_thread_pool.h" +#include "dds/ddsrt/thread_pool.h" typedef struct ddsi_work_queue_job { @@ -25,7 +25,7 @@ typedef struct ddsi_work_queue_job } * ddsi_work_queue_job_t; -struct ut_thread_pool_s +struct ddsrt_thread_pool_s { ddsi_work_queue_job_t m_jobs; /* Job queue */ ddsi_work_queue_job_t m_jobs_tail; /* Tail of job queue */ @@ -42,10 +42,10 @@ struct ut_thread_pool_s ddsrt_mutex_t m_mutex; /* Pool guard mutex */ }; -static uint32_t ut_thread_start_fn (void * arg) +static uint32_t ddsrt_thread_start_fn (void * arg) { ddsi_work_queue_job_t job; - ut_thread_pool pool = (ut_thread_pool) arg; + ddsrt_thread_pool pool = (ddsrt_thread_pool) arg; /* Thread loops, pulling jobs from queue */ @@ -88,7 +88,7 @@ static uint32_t ut_thread_start_fn (void * arg) return 0; } -static dds_retcode_t ut_thread_pool_new_thread (ut_thread_pool pool) +static dds_retcode_t ddsrt_thread_pool_new_thread (ddsrt_thread_pool pool) { static unsigned char pools = 0; /* Pool counter - TODO make atomic */ @@ -97,7 +97,7 @@ static dds_retcode_t ut_thread_pool_new_thread (ut_thread_pool pool) dds_retcode_t res; (void) snprintf (name, sizeof (name), "OSPL-%u-%u", pools++, pool->m_count++); - res = ddsrt_thread_create (&id, name, &pool->m_attr, &ut_thread_start_fn, pool); + res = ddsrt_thread_create (&id, name, &pool->m_attr, &ddsrt_thread_start_fn, pool); if (res == DDS_RETCODE_OK) { @@ -110,9 +110,9 @@ static dds_retcode_t ut_thread_pool_new_thread (ut_thread_pool pool) return res; } -ut_thread_pool ut_thread_pool_new (uint32_t threads, uint32_t max_threads, uint32_t max_queue, ddsrt_threadattr_t * attr) +ddsrt_thread_pool ddsrt_thread_pool_new (uint32_t threads, uint32_t max_threads, uint32_t max_queue, ddsrt_threadattr_t * attr) { - ut_thread_pool pool; + ddsrt_thread_pool pool; ddsi_work_queue_job_t job; /* Sanity check QoS */ @@ -144,9 +144,9 @@ ut_thread_pool ut_thread_pool_new (uint32_t threads, uint32_t max_threads, uint3 while (threads--) { - if (ut_thread_pool_new_thread (pool) != DDS_RETCODE_OK) + if (ddsrt_thread_pool_new_thread (pool) != DDS_RETCODE_OK) { - ut_thread_pool_free (pool); + ddsrt_thread_pool_free (pool); pool = NULL; break; } @@ -158,7 +158,7 @@ ut_thread_pool ut_thread_pool_new (uint32_t threads, uint32_t max_threads, uint3 return pool; } -void ut_thread_pool_free (ut_thread_pool pool) +void ddsrt_thread_pool_free (ddsrt_thread_pool pool) { ddsi_work_queue_job_t job; @@ -205,7 +205,7 @@ void ut_thread_pool_free (ut_thread_pool pool) ddsrt_free (pool); } -dds_retcode_t ut_thread_pool_submit (ut_thread_pool pool, void (*fn) (void *arg), void * arg) +dds_retcode_t ddsrt_thread_pool_submit (ddsrt_thread_pool pool, void (*fn) (void *arg), void * arg) { dds_retcode_t res = DDS_RETCODE_OK; ddsi_work_queue_job_t job; @@ -255,7 +255,7 @@ dds_retcode_t ut_thread_pool_submit (ut_thread_pool pool, void (*fn) (void *arg) if ((pool->m_thread_max == 0) || (pool->m_threads < pool->m_thread_max)) { /* OK if fails as have queued job */ - (void) ut_thread_pool_new_thread (pool); + (void) ddsrt_thread_pool_new_thread (pool); } } @@ -269,7 +269,7 @@ dds_retcode_t ut_thread_pool_submit (ut_thread_pool pool, void (*fn) (void *arg) return res; } -void ut_thread_pool_purge (ut_thread_pool pool) +void ddsrt_thread_pool_purge (ddsrt_thread_pool pool) { uint32_t total; diff --git a/src/util/src/ut_xmlparser.c b/src/ddsrt/src/xmlparser.c similarity index 89% rename from src/util/src/ut_xmlparser.c rename to src/ddsrt/src/xmlparser.c index 2d31a54..7a7e0cb 100644 --- a/src/util/src/ut_xmlparser.c +++ b/src/ddsrt/src/xmlparser.c @@ -18,7 +18,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/misc.h" #include "dds/ddsrt/string.h" -#include "dds/util/ut_xmlparser.h" +#include "dds/ddsrt/xmlparser.h" #define TOK_EOF -1 #define TOK_OPEN_TAG -2 @@ -30,7 +30,7 @@ #define NOMARKER (~(size_t)0) -struct ut_xmlpState { +struct ddsrt_xmlp_state { size_t cbufp; /* current position in cbuf */ size_t cbufn; /* number of bytes in cbuf (cbufp <= cbufn) */ size_t cbufmax; /* allocated size of cbuf (cbufn <= cbufmax) */ @@ -50,7 +50,7 @@ struct ut_xmlpState { int nest; /* current nesting level */ void *varg; /* user argument to callback functions */ int require_eof; /* if false, junk may follow top-level closing tag */ - struct ut_xmlpCallbacks cb; /* user-supplied callbacks (or stubs) */ + struct ddsrt_xmlp_callbacks cb; /* user-supplied callbacks (or stubs) */ }; static int cb_null_elem_open (void *varg, uintptr_t parentinfo, uintptr_t *eleminfo, const char *name) @@ -93,7 +93,7 @@ static void cb_null_error (void *varg, const char *msg, int line) DDSRT_UNUSED_ARG (line); } -static void ut_xmlpNewCommon (struct ut_xmlpState *st) +static void ddsrt_xmlp_new_common (struct ddsrt_xmlp_state *st) { st->cbufp = 0; st->cbufmark = NOMARKER; @@ -111,7 +111,7 @@ static void ut_xmlpNewCommon (struct ut_xmlpState *st) st->require_eof = 1; } -static void ut_xmlpNewSetCB (struct ut_xmlpState *st, void *varg, const struct ut_xmlpCallbacks *cb) +static void ddsrt_xmlp_new_setCB (struct ddsrt_xmlp_state *st, void *varg, const struct ddsrt_xmlp_callbacks *cb) { st->varg = varg; st->cb = *cb; @@ -122,43 +122,43 @@ static void ut_xmlpNewSetCB (struct ut_xmlpState *st, void *varg, const struct u if (st->cb.error == 0) st->cb.error = cb_null_error; } -struct ut_xmlpState *ut_xmlpNewFile (FILE *fp, void *varg, const struct ut_xmlpCallbacks *cb) +struct ddsrt_xmlp_state *ddsrt_xmlp_new_file (FILE *fp, void *varg, const struct ddsrt_xmlp_callbacks *cb) { - struct ut_xmlpState *st; + struct ddsrt_xmlp_state *st; st = ddsrt_malloc (sizeof (*st)); st->cbufn = 0; st->cbufmax = 8192; st->cbuf = ddsrt_malloc (st->cbufmax); st->fp = fp; - ut_xmlpNewCommon (st); - ut_xmlpNewSetCB (st, varg, cb); + ddsrt_xmlp_new_common (st); + ddsrt_xmlp_new_setCB (st, varg, cb); return st; } -struct ut_xmlpState *ut_xmlpNewString (const char *string, void *varg, const struct ut_xmlpCallbacks *cb) +struct ddsrt_xmlp_state *ddsrt_xmlp_new_string (const char *string, void *varg, const struct ddsrt_xmlp_callbacks *cb) { - struct ut_xmlpState *st; + struct ddsrt_xmlp_state *st; st = ddsrt_malloc (sizeof (*st)); st->cbufn = strlen (string); st->cbufmax = st->cbufn; st->cbuf = (char *) string; st->fp = NULL; - ut_xmlpNewCommon (st); - ut_xmlpNewSetCB (st, varg, cb); + ddsrt_xmlp_new_common (st); + ddsrt_xmlp_new_setCB (st, varg, cb); return st; } -void ut_xmlpSetRequireEOF (struct ut_xmlpState *st, int require_eof) +void ddsrt_xmlp_set_requireEOF (struct ddsrt_xmlp_state *st, int require_eof) { st->require_eof = require_eof; } -size_t ut_xmlpGetBufpos (const struct ut_xmlpState *st) +size_t ddsrt_xmlp_get_bufpos (const struct ddsrt_xmlp_state *st) { return st->cbufp; } -void ut_xmlpFree (struct ut_xmlpState *st) +void ddsrt_xmlp_free (struct ddsrt_xmlp_state *st) { if (st->fp != NULL) { ddsrt_free (st->cbuf); @@ -167,7 +167,7 @@ void ut_xmlpFree (struct ut_xmlpState *st) ddsrt_free (st); } -static int make_chars_available (struct ut_xmlpState *st, size_t nmin) +static int make_chars_available (struct ddsrt_xmlp_state *st, size_t nmin) { size_t n, pos; pos = (st->cbufmark != NOMARKER) ? st->cbufmark : st->cbufp; @@ -201,21 +201,21 @@ static int make_chars_available (struct ut_xmlpState *st, size_t nmin) return (st->cbufn - st->cbufp >= nmin); } -static void set_input_marker (struct ut_xmlpState *st) +static void set_input_marker (struct ddsrt_xmlp_state *st) { assert (st->cbufmark == NOMARKER); st->cbufmark = st->cbufp; st->linemark = st->line; } -static void discard_input_marker (struct ut_xmlpState *st) +static void discard_input_marker (struct ddsrt_xmlp_state *st) { assert (st->cbufmark != NOMARKER); st->cbufmark = NOMARKER; st->linemark = 0; } -static void rewind_to_input_marker (struct ut_xmlpState *st) +static void rewind_to_input_marker (struct ddsrt_xmlp_state *st) { assert (st->cbufmark != NOMARKER); st->cbufp = st->cbufmark; @@ -223,7 +223,7 @@ static void rewind_to_input_marker (struct ut_xmlpState *st) discard_input_marker (st); } -static int next_char (struct ut_xmlpState *st) +static int next_char (struct ddsrt_xmlp_state *st) { char c; if (!make_chars_available (st, 1)) { @@ -236,7 +236,7 @@ static int next_char (struct ut_xmlpState *st) return c; } -static int peek_char (struct ut_xmlpState *st) +static int peek_char (struct ddsrt_xmlp_state *st) { if (!make_chars_available (st, 1)) { return TOK_EOF; @@ -244,7 +244,7 @@ static int peek_char (struct ut_xmlpState *st) return st->cbuf[st->cbufp]; } -static int peek_chars (struct ut_xmlpState *st, const char *seq, int consume) +static int peek_chars (struct ddsrt_xmlp_state *st, const char *seq, int consume) { size_t n = strlen (seq); if (!make_chars_available (st, n)) { @@ -354,13 +354,13 @@ static int unescape_insitu (char *buffer, size_t *n) } DDSRT_WARNING_MSVC_ON(4996); -static void discard_payload (struct ut_xmlpState *st) +static void discard_payload (struct ddsrt_xmlp_state *st) { st->tpp = 0; st->tpescp = 0; } -static int append_to_payload (struct ut_xmlpState *st, int c, int islit) +static int append_to_payload (struct ddsrt_xmlp_state *st, int c, int islit) { if (!islit) { st->tp[st->tpp++] = (char) c; @@ -383,7 +383,7 @@ static int append_to_payload (struct ut_xmlpState *st, int c, int islit) return 0; } -static int save_payload (char **payload, struct ut_xmlpState *st, int trim) +static int save_payload (char **payload, struct ddsrt_xmlp_state *st, int trim) { char *p; if (st->tpescp < st->tpp) { @@ -424,7 +424,7 @@ static int save_payload (char **payload, struct ut_xmlpState *st, int trim) return 0; } -static int next_token_ident (struct ut_xmlpState *st, char **payload) +static int next_token_ident (struct ddsrt_xmlp_state *st, char **payload) { while (qq_isidentcont (peek_char (st))) { if (append_to_payload (st, next_char (st), 0) < 0) { @@ -438,7 +438,7 @@ static int next_token_ident (struct ut_xmlpState *st, char **payload) } } -static int next_token_tag_withoutclose (struct ut_xmlpState *st, char **payload) +static int next_token_tag_withoutclose (struct ddsrt_xmlp_state *st, char **payload) { if (peek_chars (st, " */ while (peek_char (st) != TOK_EOF && !peek_chars (st, end, 1)) { @@ -501,7 +501,7 @@ static void processing_instruction (struct ut_xmlpState *st, const char *end) } } -static void drop_peek_token (struct ut_xmlpState *st) +static void drop_peek_token (struct ddsrt_xmlp_state *st) { st->peektok = 0; if (st->peekpayload) { @@ -510,7 +510,7 @@ static void drop_peek_token (struct ut_xmlpState *st) } } -static int next_token (struct ut_xmlpState *st, char **payload) +static int next_token (struct ddsrt_xmlp_state *st, char **payload) { /* Always return a valid pointer to allocated memory or a null pointer, regardless of token type */ @@ -566,7 +566,7 @@ static int next_token (struct ut_xmlpState *st, char **payload) } } -static int peek_token (struct ut_xmlpState *st) +static int peek_token (struct ddsrt_xmlp_state *st) { int tok; char *payload; @@ -576,7 +576,7 @@ static int peek_token (struct ut_xmlpState *st) return tok; } -static int parse_element (struct ut_xmlpState *st, uintptr_t parentinfo) +static int parse_element (struct ddsrt_xmlp_state *st, uintptr_t parentinfo) { #define PE_ERROR2(c,c1,c2) do { errc = (c); errc1 = (c1); errc2 = (c2); goto err; } while (0) #define PE_ERROR(c,c1) PE_ERROR2(c,c1,0) @@ -703,7 +703,7 @@ ok: #undef PE_ERROR2 } -int ut_xmlpParse (struct ut_xmlpState *st) +int ddsrt_xmlp_parse (struct ddsrt_xmlp_state *st) { if (peek_token (st) == TOK_EOF) { return 0; @@ -717,6 +717,6 @@ int ut_xmlpParse (struct ut_xmlpState *st) } } -int ut_xmlUnescapeInsitu (char *buffer, size_t *n) { +int ddsrt_xmlUnescapeInsitu (char *buffer, size_t *n) { return unescape_insitu (buffer, n); } diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt deleted file mode 100644 index 282c131..0000000 --- a/src/util/CMakeLists.txt +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# -include (GenerateExportHeader) - -PREPEND(srcs_util "${CMAKE_CURRENT_SOURCE_DIR}/src" ut_avl.c ut_crc.c ut_expand_envvars.c ut_fibheap.c ut_hopscotch.c ut_thread_pool.c ut_xmlparser.c) - -add_library(util ${srcs_util}) -set_property(TARGET util PROPERTY POSITION_INDEPENDENT_CODE TRUE) - -generate_export_header( - util - BASE_NAME - dds - EXPORT_FILE_NAME - "${CMAKE_CURRENT_BINARY_DIR}/include/dds/export.h") - -# util must NOT link with ddsrt to avoid duplicate symbols in ddsc! -# ddsrt include directories are required though. -target_compile_definitions( - util - PUBLIC - $>) -target_include_directories( - util - PUBLIC - "$" - PRIVATE - "$" - "$>") - -install( - DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/include/dds" - DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" - COMPONENT dev) - -# TODO: improve test inclusion. -if((BUILD_TESTING) AND ((NOT DEFINED MSVC_VERSION) OR (MSVC_VERSION GREATER "1800"))) - add_subdirectory(tests) -endif() diff --git a/src/util/include/dds/util/ut_avl.h b/src/util/include/dds/util/ut_avl.h deleted file mode 100644 index 8d3b76b..0000000 --- a/src/util/include/dds/util/ut_avl.h +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef UT_AVL_H -#define UT_AVL_H - -/* The tree library never performs memory allocations or deallocations internally. - - - Treedef_t: defines the properties of the tree, offsets, - comparison functions, augmented structures, flags -- these are - related to the code/data structure in which the tree is embedded, - and in nearly all cases known at compile time. - - avlTree_t: represents the tree, i.e., pointer to the root. - - avlNode_t: contains the administrative data for a single node in - the tree. - - For a tree node: - struct T { - avlNode_t avlnode; - int key; - }; - by definition, avlnodeoffset == offsetof(struct T, avlnode) and - keyoffset = offsetof(struct T, key). The user of the library only - ever deals in pointers to (in this case) struct T, never with - pointers to the avlNode_t, and the compare function operations on - pointers to keys, in this case pointers to "int"s. If you wish, you - can also do: keyoffset = 0, in which case the compare function - would be operating on struct T's. - - The compare function is assumed to behave just like all compare - functions in the C library: < 0, =0, >0 for left argument less - than, equal to or greater than the right argument. - - The "augment" function is automatically called whenever some of the - children of a node change, as well as when the "augment" function - has been called on some of the children. It allows you to maintain - a "summary" of the subtree -- currently only used in ddsi2e, in one - spot. - - Trees come in various "variants", configured through "treedef" - flags: - - direct/indirect key: direct meaning the key value is embedded in - the structure containing the avlNode_t, indirect meaning a - pointer to the key value is. The compare function doesn't deal - with tree nodes, but with key values. - - re-entrant: in the style of the C library, meaning, the - comparison function gets a user-supplied 3rd argument (in - particular used by mmstat). - - unique keys/duplicate keys: when keys must be unique, some - optimizations apply; it is up to the caller to ensure one doesn't - violate the uniqueness of the keys (it'll happily crash in insert - if you don't); when duplicate keys are allowed, a forward scan of - the tree will visit them in the order of insertion. - - For a tree node: - struct T { - avlnode_t avlnode; - char *key; - }; - you could set the "indirect" flag, and then you simply use - strcmp(), avoiding the need for passing templates in looking up key - values. Much nicer. - - There is also an orthogonal variant that is enforced through the - type system -- note that would be possible for all of the above as - well, but the number of cases simply explodes and none of the above - flags affects the dynamically changing data structures (just the - tree definition), unlike this one. - - - the "C" variant keeps track of the number of nodes in the tree to - support a "count" operation in O(1) time, but is otherwise - identical. - - The various initializer macros and TreedefInit functions should - make sense with this. - - All functions for looking up nodes return NULL if there is no node - satisfying the requirements. - - - Init: initializes a tree (really just: root = NULL, perhaps count = 0) - - Free: calls "freefun" on each node, which may free the node - - FreeArg: as "Free", but with an extra, user-supplied, argument - - Root: returns the root node - - Lookup: returns a node with key value "key" (ref allowdups flag) - - LookupIPath: like Lookup, but also filling an IPath_t structure - for efficient insertion in case of a failed lookup (or inserting - duplicates) - - LookupDPath: like Lookup, but also filling a DPath_t structure - that helps with deleting a node - - LookupPredEq: locates the node with the greatest key value <= "key" - - LookupSuccEq: similar, but smallest key value >= "key" - - LookupPred: similar, < "key" - - LookupSucc: similar, > "key" - - Insert: convenience function: LookupIPath ; InsertIPath - - Delete: convenience function: LookupDPath ; DeleteDPath - - InsertIPath: insert node based on the "path" obtained from LookupIPath - - DeleteDPath: delete node, using information in "path" to do so efficiently - - SwapNode: replace "oldn" by "newn" without modifying the tree - structure (the key need not be equal, but must be - FindPred(oldn).key < newn.key < FindSucc(oldn).key, where a - non-existing predecessor has key -inf and a non-existing - successor has key +inf, and where it is understood that the < - operator becomes <= if allowdups is set - - AugmentUpdate: to be called when something in "node" changes that - affects the subtree "summary" computed by the configured - "augment" function - - IsEmpty: returns 1 if tree is empty, 0 if not - - IsSingleton: returns 1 if tree contains exactly one node, 0 if not - - FindMin: returns the node with the smallest key value in the tree - - FindMax: similar, largest key value - - FindPred: preceding node in in-order treewalk - - FindSucc: similar, following node - - - Walk: calls "f" with user-supplied argument "a" once for each - node, starting at FindMin and ending at FindMax - - ConstWalk: same, but with a const tree - - WalkRange: like Walk, but only visiting nodes with key values in - range [min,max] (that's inclusive) - - ConstWalkRange: same, but with a const tree - - WalkRangeReverse: like WalkRange, but in the reverse direction - - ConstWalkRangeReverse: same, but with a const tree - - IterFirst: starts forward iteration, starting at (and returning) FindMin - - IterSuccEq: similar, starting at LookupSuccEq - - IterSucc: similar, starting at LookupSucc - - IterNext: returns FindSucc(last returned node); may not be called - if preceding IterXXX call on same "iter" returned NULL - - That's all there is to it. - - Note that all calls to Walk(f,a) can be rewritten as: - for(n=IterFirst(&it); n; n=IterNext(&it)) { f(n,a) } - or as - for(n=FindMin(); n; n=FindSucc(n)) { f(n,a) } - - The walk functions and iterators may not alter the tree - structure. If that is desired, the latter can easily be rewritten - as: - n=FindMin() ; while(n) { nn=FindSucc(n); f(n,a); n=nn } - because FindMin/FindSucc doesn't store any information to allow - fast processing. That'll allow every operation, with the obvious - exception of f(n) calling Delete(FindSucc(n)). - - Currently, all trees maintain parent pointers, but it may be worth - doing a separate set without it, as it reduces the size of - avlNode_t. But in that case, the FindMin/FindSucc option would no - longer be a reasonable option because it would be prohibitively - expensive, whereas the IterFirst/IterNext option are alway - efficiently. If one were to do a threaded tree variant, the - implemetantion of IterFirst/IterNext would become absolute trivial - and faster still, but at the cost of significantly more overhead in - memory and updates. */ - -#include -#include - -#include "dds/export.h" -#include "dds/ddsrt/attributes.h" - -#if defined (__cplusplus) -extern "C" { -#endif - -#define UT_AVL_MAX_TREEHEIGHT (12 * sizeof (void *)) - -typedef int (*ut_avlCompare_t) (const void *a, const void *b); -typedef int (*ut_avlCompare_r_t) (const void *a, const void *b, void *arg); -typedef void (*ut_avlAugment_t) (void *node, const void *left, const void *right); -typedef void (*ut_avlWalk_t) (void *node, void *arg); -typedef void (*ut_avlConstWalk_t) (const void *node, void *arg); - -typedef struct ut_avlNode { - struct ut_avlNode *cs[2]; /* 0 = left, 1 = right */ - struct ut_avlNode *parent; - int height; -} ut_avlNode_t; - -#define UT_AVL_TREEDEF_FLAG_INDKEY 1 -#define UT_AVL_TREEDEF_FLAG_R 2 -#define UT_AVL_TREEDEF_FLAG_ALLOWDUPS 4 - -typedef struct ut_avlTreedef { -#if defined (__cplusplus) - ut_avlTreedef() {} -#endif - size_t avlnodeoffset; - size_t keyoffset; - union { - ut_avlCompare_t comparekk; - ut_avlCompare_r_t comparekk_r; - } u; - ut_avlAugment_t augment; - uint32_t flags; - void *cmp_arg; /* for _r variant */ -} ut_avlTreedef_t; - -typedef struct ut_avlCTreedef { - ut_avlTreedef_t t; -} ut_avlCTreedef_t; - -typedef struct ut_avlTree { - ut_avlNode_t *root; -} ut_avlTree_t; - -typedef struct ut_avlCTree { - ut_avlTree_t t; - size_t count; -} ut_avlCTree_t; - -typedef struct ut_avlPath { - int depth; /* total depth of path */ - int pnodeidx; - ut_avlNode_t *parent; /* (nodeidx == 0 ? NULL : *(path[nodeidx-1])) */ - ut_avlNode_t **pnode[UT_AVL_MAX_TREEHEIGHT]; -} ut_avlPath_t; - -typedef struct ut_avlIPath { - ut_avlPath_t p; -} ut_avlIPath_t; - -typedef struct ut_avlDPath { - ut_avlPath_t p; -} ut_avlDPath_t; - -typedef struct ut_avlIter { - const ut_avlTreedef_t *td; - ut_avlNode_t *right; - ut_avlNode_t **todop; - ut_avlNode_t *todo[1+UT_AVL_MAX_TREEHEIGHT]; -} ut_avlIter_t; - -typedef struct ut_avlCIter { - ut_avlIter_t t; -} ut_avlCIter_t; - -/* avlnodeoffset and keyoffset must both be in [0,2**31-1] */ -#define UT_AVL_TREEDEF_INITIALIZER(avlnodeoffset, keyoffset, comparekk_, augment) { (avlnodeoffset), (keyoffset), { .comparekk = (comparekk_) }, (augment), 0, 0 } -#define UT_AVL_TREEDEF_INITIALIZER_INDKEY(avlnodeoffset, keyoffset, comparekk_, augment) { (avlnodeoffset), (keyoffset), { .comparekk = (comparekk_) }, (augment), UT_AVL_TREEDEF_FLAG_INDKEY, 0 } -#define UT_AVL_TREEDEF_INITIALIZER_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk_, augment) { (avlnodeoffset), (keyoffset), { .comparekk = (comparekk_) }, (augment), UT_AVL_TREEDEF_FLAG_ALLOWDUPS, 0 } -#define UT_AVL_TREEDEF_INITIALIZER_INDKEY_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk_, augment) { (avlnodeoffset), (keyoffset), { .comparekk = (comparekk_) }, (augment), UT_AVL_TREEDEF_FLAG_INDKEY|UT_AVL_TREEDEF_FLAG_ALLOWDUPS, 0 } -#define UT_AVL_TREEDEF_INITIALIZER_R(avlnodeoffset, keyoffset, comparekk_, cmparg, augment) { (avlnodeoffset), (keyoffset), { .comparekk_r = (comparekk_) }, (augment), UT_AVL_TREEDEF_FLAG_R, (cmparg) } -#define UT_AVL_TREEDEF_INITIALIZER_INDKEY_R(avlnodeoffset, keyoffset, comparekk_, cmparg, augment) { (avlnodeoffset), (keyoffset), { .comparekk_r = (comparekk_) }, (augment), UT_AVL_TREEDEF_FLAG_INDKEY|UT_AVL_TREEDEF_FLAG_R, (cmparg) } -#define UT_AVL_TREEDEF_INITIALIZER_R_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk_, cmparg, augment) { (avlnodeoffset), (keyoffset), { .comparekk_r = (comparekk_) }, (augment), UT_AVL_TREEDEF_FLAG_R|UT_AVL_TREEDEF_FLAG_ALLOWDUPS, (cmparg) } -#define UT_AVL_TREEDEF_INITIALIZER_INDKEY_R_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk_, cmparg, augment) { (avlnodeoffset), (keyoffset), { .comparekk_r = (comparekk_) }, (augment), UT_AVL_TREEDEF_FLAG_INDKEY|UT_AVL_TREEDEF_FLAG_R|UT_AVL_TREEDEF_FLAG_ALLOWDUPS, (cmparg) } - -/* Not maintaining # nodes */ - -DDS_EXPORT void ut_avlTreedefInit (ut_avlTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlCompare_t comparekk, ut_avlAugment_t augment, uint32_t flags) ddsrt_nonnull((1,4)); -DDS_EXPORT void ut_avlTreedefInit_r (ut_avlTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlCompare_r_t comparekk_r, void *cmp_arg, ut_avlAugment_t augment, uint32_t flags) ddsrt_nonnull((1,4)); - -DDS_EXPORT void ut_avlInit (const ut_avlTreedef_t *td, ut_avlTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlFree (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void (*freefun) (void *node)) ddsrt_nonnull((1,2)); -DDS_EXPORT void ut_avlFreeArg (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void (*freefun) (void *node, void *arg), void *arg) ddsrt_nonnull((1,2)); - -DDS_EXPORT void *ut_avlRoot (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlRootNonEmpty (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlLookup (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlLookupIPath (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key, ut_avlIPath_t *path) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlLookupDPath (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key, ut_avlDPath_t *path) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlLookupPredEq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlLookupSuccEq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlLookupPred (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlLookupSucc (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *key) ddsrt_nonnull_all; - -DDS_EXPORT void ut_avlInsert (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *node) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlDelete (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *node) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlInsertIPath (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *node, ut_avlIPath_t *path) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlDeleteDPath (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *node, ut_avlDPath_t *path) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlSwapNode (const ut_avlTreedef_t *td, ut_avlTree_t *tree, void *oldn, void *newn) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlAugmentUpdate (const ut_avlTreedef_t *td, void *node) ddsrt_nonnull_all; - -DDS_EXPORT int ut_avlIsEmpty (const ut_avlTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT int ut_avlIsSingleton (const ut_avlTree_t *tree) ddsrt_nonnull_all; - -DDS_EXPORT void *ut_avlFindMin (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlFindMax (const ut_avlTreedef_t *td, const ut_avlTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlFindPred (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *vnode) ddsrt_nonnull((1,2)); -DDS_EXPORT void *ut_avlFindSucc (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *vnode) ddsrt_nonnull((1,2)); - -DDS_EXPORT void ut_avlWalk (const ut_avlTreedef_t *td, ut_avlTree_t *tree, ut_avlWalk_t f, void *a) ddsrt_nonnull((1,2,3)); -DDS_EXPORT void ut_avlConstWalk (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_avlConstWalk_t f, void *a) ddsrt_nonnull((1,2,3)); -DDS_EXPORT void ut_avlWalkRange (const ut_avlTreedef_t *td, ut_avlTree_t *tree, const void *min, const void *max, ut_avlWalk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); -DDS_EXPORT void ut_avlConstWalkRange (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *min, const void *max, ut_avlConstWalk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); -DDS_EXPORT void ut_avlWalkRangeReverse (const ut_avlTreedef_t *td, ut_avlTree_t *tree, const void *min, const void *max, ut_avlWalk_t f, void *a) ddsrt_nonnull((1,2,3)); -DDS_EXPORT void ut_avlConstWalkRangeReverse (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, const void *min, const void *max, ut_avlConstWalk_t f, void *a) ddsrt_nonnull((1,2,3)); - -DDS_EXPORT void *ut_avlIterFirst (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_avlIter_t *iter) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlIterSuccEq (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_avlIter_t *iter, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlIterSucc (const ut_avlTreedef_t *td, const ut_avlTree_t *tree, ut_avlIter_t *iter, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlIterNext (ut_avlIter_t *iter) ddsrt_nonnull_all; - -/* Maintaining # nodes */ - -#define UT_AVL_CTREEDEF_INITIALIZER(avlnodeoffset, keyoffset, comparekk, augment) { UT_AVL_TREEDEF_INITIALIZER (avlnodeoffset, keyoffset, comparekk, augment) } -#define UT_AVL_CTREEDEF_INITIALIZER_INDKEY(avlnodeoffset, keyoffset, comparekk, augment) { UT_AVL_TREEDEF_INITIALIZER_INDKEY (avlnodeoffset, keyoffset, comparekk, augment) } -#define UT_AVL_CTREEDEF_INITIALIZER_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk, augment) { UT_AVL_TREEDEF_INITIALIZER_ALLOWDUPS (avlnodeoffset, keyoffset, comparekk, augment) } -#define UT_AVL_CTREEDEF_INITIALIZER_INDKEY_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk, augment) { UT_AVL_TREEDEF_INITIALIZER_INDKEY_ALLOWDUPS (avlnodeoffset, keyoffset, comparekk, augment) } -#define UT_AVL_CTREEDEF_INITIALIZER_R(avlnodeoffset, keyoffset, comparekk, cmparg, augment) { UT_AVL_TREEDEF_INITIALIZER_R (avlnodeoffset, keyoffset, comparekk, cmparg, augment) } -#define UT_AVL_CTREEDEF_INITIALIZER_INDKEY_R(avlnodeoffset, keyoffset, comparekk, cmparg, augment) { UT_AVL_TREEDEF_INITIALIZER_INDKEY_R (avlnodeoffset, keyoffset, comparekk, cmparg, augment) } -#define UT_AVL_CTREEDEF_INITIALIZER_R_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk, cmparg, augment) { UT_AVL_TREEDEF_INITIALIZER_R_ALLOWDUPS (avlnodeoffset, keyoffset, comparekk, cmparg, augment) } -#define UT_AVL_CTREEDEF_INITIALIZER_INDKEY_R_ALLOWDUPS(avlnodeoffset, keyoffset, comparekk, cmparg, augment) { UT_AVL_TREEDEF_INITIALIZER_INDKEY_R_ALLOWDUPS (avlnodeoffset, keyoffset, comparekk, cmparg, augment) } - -DDS_EXPORT void ut_avlCTreedefInit (ut_avlCTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlCompare_t comparekk, ut_avlAugment_t augment, uint32_t flags) ddsrt_nonnull((1,4)); -DDS_EXPORT void ut_avlCTreedefInit_r (ut_avlCTreedef_t *td, size_t avlnodeoffset, size_t keyoffset, ut_avlCompare_r_t comparekk_r, void *cmp_arg, ut_avlAugment_t augment, uint32_t flags) ddsrt_nonnull((1,4)); - -DDS_EXPORT void ut_avlCInit (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlCFree (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void (*freefun) (void *node)) ddsrt_nonnull((1,2)); -DDS_EXPORT void ut_avlCFreeArg (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void (*freefun) (void *node, void *arg), void *arg) ddsrt_nonnull((1,2)); - -DDS_EXPORT void *ut_avlCRoot (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCRootNonEmpty (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCLookup (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCLookupIPath (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key, ut_avlIPath_t *path) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCLookupDPath (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key, ut_avlDPath_t *path) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCLookupPredEq (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCLookupSuccEq (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCLookupPred (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCLookupSucc (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *key) ddsrt_nonnull_all; - -DDS_EXPORT void ut_avlCInsert (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *node) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlCDelete (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *node) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlCInsertIPath (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *node, ut_avlIPath_t *path) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlCDeleteDPath (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *node, ut_avlDPath_t *path) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlCSwapNode (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, void *oldn, void *newn) ddsrt_nonnull_all; -DDS_EXPORT void ut_avlCAugmentUpdate (const ut_avlCTreedef_t *td, void *node) ddsrt_nonnull_all; - -DDS_EXPORT int ut_avlCIsEmpty (const ut_avlCTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT int ut_avlCIsSingleton (const ut_avlCTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT size_t ut_avlCCount (const ut_avlCTree_t *tree) ddsrt_nonnull_all; - -DDS_EXPORT void *ut_avlCFindMin (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCFindMax (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCFindPred (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *vnode) ddsrt_nonnull((1,2)); -DDS_EXPORT void *ut_avlCFindSucc (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *vnode) ddsrt_nonnull((1,2)); - -DDS_EXPORT void ut_avlCWalk (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, ut_avlWalk_t f, void *a) ddsrt_nonnull((1,2,3)); -DDS_EXPORT void ut_avlCConstWalk (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, ut_avlConstWalk_t f, void *a) ddsrt_nonnull((1,2,3)); -DDS_EXPORT void ut_avlCWalkRange (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, const void *min, const void *max, ut_avlWalk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); -DDS_EXPORT void ut_avlCConstWalkRange (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *min, const void *max, ut_avlConstWalk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); -DDS_EXPORT void ut_avlCWalkRangeReverse (const ut_avlCTreedef_t *td, ut_avlCTree_t *tree, const void *min, const void *max, ut_avlWalk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); -DDS_EXPORT void ut_avlCConstWalkRangeReverse (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, const void *min, const void *max, ut_avlConstWalk_t f, void *a) ddsrt_nonnull((1,2,3,4,5)); - -DDS_EXPORT void *ut_avlCIterFirst (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, ut_avlCIter_t *iter) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCIterSuccEq (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, ut_avlCIter_t *iter, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCIterSucc (const ut_avlCTreedef_t *td, const ut_avlCTree_t *tree, ut_avlCIter_t *iter, const void *key) ddsrt_nonnull_all; -DDS_EXPORT void *ut_avlCIterNext (ut_avlCIter_t *iter) ddsrt_nonnull_all; - -#if defined (__cplusplus) -} -#endif - -#endif /* UT_AVL_H */ diff --git a/src/util/include/dds/util/ut_crc.h b/src/util/include/dds/util/ut_crc.h deleted file mode 100644 index 144009f..0000000 --- a/src/util/include/dds/util/ut_crc.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef UT_CRC_H -#define UT_CRC_H - -#include -#include - -#include "dds/export.h" -#include "dds/ddsrt/attributes.h" - -#if defined (__cplusplus) -extern "C" { -#endif - -DDS_EXPORT uint32_t ut_crcCalculate (const void *buf, size_t length) ddsrt_nonnull_all ddsrt_attribute_pure; - -#if defined (__cplusplus) -} -#endif - -#endif /* UT_CRC_H */ diff --git a/src/util/include/dds/util/ut_fibheap.h b/src/util/include/dds/util/ut_fibheap.h deleted file mode 100644 index d02b9c8..0000000 --- a/src/util/include/dds/util/ut_fibheap.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef UT_FIBHEAP_H -#define UT_FIBHEAP_H - -#include - -#include "dds/export.h" - -#if defined (__cplusplus) -extern "C" { -#endif - -typedef struct ut_fibheapNode { - struct ut_fibheapNode *parent, *children; - struct ut_fibheapNode *prev, *next; - unsigned mark: 1; - unsigned degree: 31; -} ut_fibheapNode_t; - -typedef struct ut_fibheapDef { - uintptr_t offset; - int (*cmp) (const void *va, const void *vb); -} ut_fibheapDef_t; - -typedef struct ut_fibheap { - ut_fibheapNode_t *roots; /* points to root with min key value */ -} ut_fibheap_t; - -#define UT_FIBHEAPDEF_INITIALIZER(offset, cmp) { (offset), (cmp) } - -DDS_EXPORT void ut_fibheapDefInit (ut_fibheapDef_t *fhdef, uintptr_t offset, int (*cmp) (const void *va, const void *vb)); -DDS_EXPORT void ut_fibheapInit (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh); -DDS_EXPORT void *ut_fibheapMin (const ut_fibheapDef_t *fhdef, const ut_fibheap_t *fh); -DDS_EXPORT void ut_fibheapMerge (const ut_fibheapDef_t *fhdef, ut_fibheap_t *a, ut_fibheap_t *b); -DDS_EXPORT void ut_fibheapInsert (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, const void *vnode); -DDS_EXPORT void ut_fibheapDelete (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, const void *vnode); -DDS_EXPORT void *ut_fibheapExtractMin (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh); -DDS_EXPORT void ut_fibheapDecreaseKey (const ut_fibheapDef_t *fhdef, ut_fibheap_t *fh, const void *vnode); /* to be called AFTER decreasing the key */ - -#if defined (__cplusplus) -} -#endif - -#endif /* UT_FIBHEAP_H */ diff --git a/src/util/include/dds/util/ut_hopscotch.h b/src/util/include/dds/util/ut_hopscotch.h deleted file mode 100644 index 9c632a8..0000000 --- a/src/util/include/dds/util/ut_hopscotch.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef UT_HOPSCOTCH_H -#define UT_HOPSCOTCH_H - -#include - -#include "dds/export.h" - -#if defined (__cplusplus) -extern "C" { -#endif - -#if __STDC_VERSION__ >= 199901L -#define UT_HH_RESTRICT restrict -#else -#define UT_HH_RESTRICT -#endif - -/* Concurrent version */ -struct ut_chh; -struct ut_chhBucket; -struct ut_chhIter { - struct ut_chhBucket *bs; - uint32_t size; - uint32_t cursor; -}; - -/* - * The hopscotch hash table is dependent on a proper functioning hash. - * If the hash function generates a lot of hash collisions, then it will - * not be able to handle that by design. - * It is capable of handling some collisions, but not more than 32 per - * bucket (less, when other hash values are clustered around the - * collision value). - * When proper distributed hash values are generated, then hopscotch - * works nice and quickly. - */ -typedef uint32_t (*ut_hhHash_fn) (const void *); - -/* - * Hopscotch needs to be able to compare two elements. - * Returns 0 when not equal. - */ -typedef int (*ut_hhEquals_fn) (const void *, const void *); - -/* - * Hopscotch is will resize its internal buckets list when needed. It will - * call this garbage collection function with the old buckets list. The - * caller has to delete the list when it deems it safe to do so. - */ -typedef void (*ut_hhBucketsGc_fn) (void *); - -DDS_EXPORT struct ut_chh *ut_chhNew (uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals, ut_hhBucketsGc_fn gc_buckets); -DDS_EXPORT void ut_chhFree (struct ut_chh * UT_HH_RESTRICT hh); -DDS_EXPORT void *ut_chhLookup (struct ut_chh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template); -DDS_EXPORT int ut_chhAdd (struct ut_chh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT data); -DDS_EXPORT int ut_chhRemove (struct ut_chh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template); -DDS_EXPORT void ut_chhEnumUnsafe (struct ut_chh * UT_HH_RESTRICT rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */ -void *ut_chhIterFirst (struct ut_chh * UT_HH_RESTRICT rt, struct ut_chhIter *it); -void *ut_chhIterNext (struct ut_chhIter *it); - -/* Sequential version */ -struct ut_hh; - -struct ut_hhIter { - struct ut_hh *hh; - uint32_t cursor; -}; - -DDS_EXPORT struct ut_hh *ut_hhNew (uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals); -DDS_EXPORT void ut_hhFree (struct ut_hh * UT_HH_RESTRICT hh); -DDS_EXPORT void *ut_hhLookup (const struct ut_hh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template); -DDS_EXPORT int ut_hhAdd (struct ut_hh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT data); -DDS_EXPORT int ut_hhRemove (struct ut_hh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template); -DDS_EXPORT void ut_hhEnum (struct ut_hh * UT_HH_RESTRICT rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */ -DDS_EXPORT void *ut_hhIterFirst (struct ut_hh * UT_HH_RESTRICT rt, struct ut_hhIter * UT_HH_RESTRICT iter); /* may delete nodes */ -DDS_EXPORT void *ut_hhIterNext (struct ut_hhIter * UT_HH_RESTRICT iter); - -/* Sequential version, embedded data */ -struct ut_ehh; - -struct ut_ehhIter { - struct ut_ehh *hh; - uint32_t cursor; -}; - -DDS_EXPORT struct ut_ehh *ut_ehhNew (size_t elemsz, uint32_t init_size, ut_hhHash_fn hash, ut_hhEquals_fn equals); -DDS_EXPORT void ut_ehhFree (struct ut_ehh * UT_HH_RESTRICT hh); -DDS_EXPORT void *ut_ehhLookup (const struct ut_ehh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template); -DDS_EXPORT int ut_ehhAdd (struct ut_ehh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT data); -DDS_EXPORT int ut_ehhRemove (struct ut_ehh * UT_HH_RESTRICT rt, const void * UT_HH_RESTRICT template); -DDS_EXPORT void ut_ehhEnum (struct ut_ehh * UT_HH_RESTRICT rt, void (*f) (void *a, void *f_arg), void *f_arg); /* may delete a */ -DDS_EXPORT void *ut_ehhIterFirst (struct ut_ehh * UT_HH_RESTRICT rt, struct ut_ehhIter * UT_HH_RESTRICT iter); /* may delete nodes */ -DDS_EXPORT void *ut_ehhIterNext (struct ut_ehhIter * UT_HH_RESTRICT iter); - -#if defined (__cplusplus) -} -#endif - -#endif diff --git a/src/util/include/dds/util/ut_xmlparser.h b/src/util/include/dds/util/ut_xmlparser.h deleted file mode 100644 index b7d5076..0000000 --- a/src/util/include/dds/util/ut_xmlparser.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef UT_XMLPARSER_H -#define UT_XMLPARSER_H - -#include - -#include "dds/export.h" - -#if defined (__cplusplus) -extern "C" { -#endif - - typedef int (*ut_xmlpProcElemOpen_t) (void *varg, uintptr_t parentinfo, uintptr_t *eleminfo, const char *name); - typedef int (*ut_xmlpProcAttr_t) (void *varg, uintptr_t eleminfo, const char *name, const char *value); - typedef int (*ut_xmlpProcElemData_t) (void *varg, uintptr_t eleminfo, const char *data); - typedef int (*ut_xmlpProcElemClose_t) (void *varg, uintptr_t eleminfo); - typedef void (*ut_xmlpError) (void *varg, const char *msg, int line); - - struct ut_xmlpCallbacks { - ut_xmlpProcElemOpen_t elem_open; - ut_xmlpProcAttr_t attr; - ut_xmlpProcElemData_t elem_data; - ut_xmlpProcElemClose_t elem_close; - ut_xmlpError error; - }; - - struct ut_xmlpState; - - DDS_EXPORT struct ut_xmlpState *ut_xmlpNewFile (FILE *fp, void *varg, const struct ut_xmlpCallbacks *cb); - DDS_EXPORT struct ut_xmlpState *ut_xmlpNewString (const char *string, void *varg, const struct ut_xmlpCallbacks *cb); - DDS_EXPORT void ut_xmlpSetRequireEOF (struct ut_xmlpState *st, int require_eof); - DDS_EXPORT size_t ut_xmlpGetBufpos (const struct ut_xmlpState *st); - DDS_EXPORT void ut_xmlpFree (struct ut_xmlpState *st); - DDS_EXPORT int ut_xmlpParse (struct ut_xmlpState *st); - - DDS_EXPORT int ut_xmlUnescapeInsitu (char *buffer, size_t *n); - -#if defined (__cplusplus) -} -#endif - -#endif diff --git a/src/util/src/ut_crc.c b/src/util/src/ut_crc.c deleted file mode 100644 index 87778a9..0000000 --- a/src/util/src/ut_crc.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include "dds/util/ut_crc.h" - -static const uint32_t crc32_table[] = { - 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, - 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, - 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, - 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, - 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, - 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, - 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, - 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, - 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, - 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, - 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, - 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, - 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, - 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, - 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, - 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, - 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, - 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, - 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, - 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, - 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, - 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, - 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, - 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, - 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, - 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, - 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, - 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, - 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, - 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, - 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, - 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, - 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, - 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, - 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, - 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, - 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, - 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, - 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, - 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, - 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, - 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, - 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 -}; - -uint32_t ut_crcCalculate (const void *buf, size_t length) -{ - const unsigned char *vptr = buf; - size_t i; - uint32_t reg = 0; - unsigned char top; - for (i = 0; i < length; i++) - { - top = (unsigned char) (reg >> 24); - top ^= *vptr; - reg = (reg << 8) ^ crc32_table[top]; - vptr++; - } - return reg; -} diff --git a/src/util/tests/CMakeLists.txt b/src/util/tests/CMakeLists.txt deleted file mode 100644 index 7828517..0000000 --- a/src/util/tests/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# -include(CUnit) - -#add_cunit_executable(CUnit_util "handleserver.c") -#target_link_libraries(CUnit_util util) From 986db690b82e2a84d4d8684c0655259acd5ecee9 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 16 Apr 2019 15:22:04 +0200 Subject: [PATCH 035/238] always append 0 byte to user/group/topic data Changes the semantics of dds_qget_{user,group,topic}data to always append a 0 byte to any non-empty value without counting it in the size. (An empty value is always represented by a null pointer and a size of 0). The advantage is that any code treating the data as the octet sequence it formally is will do exactly the same, but any code written with the knowledge that it should be a string can safely interpret it as one. Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/ddsc/dds_public_qos.h | 6 +++--- src/core/ddsc/src/dds_qos.c | 10 ++++++---- src/core/ddsi/src/q_plist.c | 6 +++--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/core/ddsc/include/dds/ddsc/dds_public_qos.h b/src/core/ddsc/include/dds/ddsc/dds_public_qos.h index 95fa4fe..b8fc7fa 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_qos.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_qos.h @@ -501,7 +501,7 @@ DDS_EXPORT void dds_qset_ignorelocal ( * @brief Get the userdata from a qos structure * * @param[in] qos - Pointer to a dds_qos_t structure storing the policy - * @param[in,out] value - Pointer that will store the userdata + * @param[in,out] value - Pointer that will store the userdata. If sz = 0, then a null pointer, else it is a pointer to an allocated buffer of sz+1 bytes where the last byte is always 0 * @param[in,out] sz - Pointer that will store the size of userdata * * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object @@ -512,7 +512,7 @@ DDS_EXPORT bool dds_qget_userdata (const dds_qos_t * __restrict qos, void **valu * @brief Get the topicdata from a qos structure * * @param[in] qos - Pointer to a dds_qos_t structure storing the policy - * @param[in,out] value - Pointer that will store the topicdata + * @param[in,out] value - Pointer that will store the topicdata. If sz = 0, then a null pointer, else it is a pointer to an allocated buffer of sz+1 bytes where the last byte is always 0 * @param[in,out] sz - Pointer that will store the size of topicdata * * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object @@ -523,7 +523,7 @@ DDS_EXPORT bool dds_qget_topicdata (const dds_qos_t * __restrict qos, void **val * @brief Get the groupdata from a qos structure * * @param[in] qos - Pointer to a dds_qos_t structure storing the policy - * @param[in,out] value - Pointer that will store the groupdata + * @param[in,out] value - Pointer that will store the groupdata. If sz = 0, then a null pointer, else it is a pointer to an allocated buffer of sz+1 bytes where the last byte is always 0 * @param[in,out] sz - Pointer that will store the size of groupdata * * @returns - false iff any of the arguments is invalid or the qos is not present in the qos object diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index 02988bf..d95add8 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -43,6 +43,7 @@ dds_qos_data_copy_out( void ** value, size_t * sz) { + assert (data->length < UINT32_MAX); if (sz == NULL && value != NULL) { return false; } @@ -51,9 +52,10 @@ dds_qos_data_copy_out( } if (value) { if (data->length != 0) { - assert(data->value); - *value = dds_alloc(data->length); - memcpy(*value, data->value, data->length); + assert (data->value); + *value = dds_alloc (data->length + 1); + memcpy (*value, data->value, data->length); + ((char *) (*value))[data->length] = 0; } else { *value = NULL; } @@ -66,7 +68,7 @@ validate_octetseq( const nn_octetseq_t* seq) { /* default value is NULL with length 0 */ - return (((seq->length == 0) && (seq->value == NULL)) || (seq->length > 0)); + return (((seq->length == 0) && (seq->value == NULL)) || (seq->length > 0 && seq->length < UINT32_MAX)); } bool diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index fed7f43..d44cec1 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -144,7 +144,7 @@ static int validate_octetseq (const struct dd *dd, size_t *len) if (dd->bufsz < offsetof (struct cdroctetseq, value)) return Q_ERR_INVALID; *len = dd->bswap ? bswap4u (x->len) : x->len; - if (*len > dd->bufsz - offsetof (struct cdroctetseq, value)) + if (*len > dd->bufsz - offsetof (struct cdroctetseq, value) || *len >= UINT32_MAX) return Q_ERR_INVALID; return 0; } @@ -158,7 +158,7 @@ static int alias_octetseq (nn_octetseq_t *oseq, const struct dd *dd) else { const struct cdroctetseq *x = (const struct cdroctetseq *) dd->buf; - assert(len <= UINT32_MAX); /* it really is an uint32_t on the wire */ + assert(len < UINT32_MAX); /* it really is an uint32_t on the wire */ oseq->length = (uint32_t)len; oseq->value = (len == 0) ? NULL : (unsigned char *) x->value; return 0; @@ -167,7 +167,7 @@ static int alias_octetseq (nn_octetseq_t *oseq, const struct dd *dd) static int alias_blob (nn_octetseq_t *oseq, const struct dd *dd) { - assert (dd->bufsz <= UINT32_MAX); + assert (dd->bufsz < UINT32_MAX); oseq->length = (uint32_t)dd->bufsz; oseq->value = (oseq->length == 0) ? NULL : (unsigned char *) dd->buf; return 0; From e350aa903c72dde99592b6082fd1fb0f9483c983 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 16 Apr 2019 17:04:21 +0200 Subject: [PATCH 036/238] suppress EHOSTUNREACH and EHOSTDOWN errors in log Signed-off-by: Erik Boasson --- src/core/ddsi/src/ddsi_udp.c | 2 +- src/ddsrt/src/sockets/posix/socket.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index a228097..0ab4489 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -167,7 +167,7 @@ static ssize_t ddsi_udp_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *d rc != DDS_RETCODE_NOT_ALLOWED && rc != DDS_RETCODE_NO_CONNECTION) { - DDS_ERROR("ddsi_udp_conn_write failed with retcode %d", rc); + DDS_ERROR("ddsi_udp_conn_write failed with retcode %d\n", rc); } return (rc == DDS_RETCODE_OK ? ret : -1); } diff --git a/src/ddsrt/src/sockets/posix/socket.c b/src/ddsrt/src/sockets/posix/socket.c index 35b80d8..94b7f89 100644 --- a/src/ddsrt/src/sockets/posix/socket.c +++ b/src/ddsrt/src/sockets/posix/socket.c @@ -455,6 +455,9 @@ send_error_to_retcode(int errnum) case ENOBUFS: case ENOMEM: return DDS_RETCODE_OUT_OF_RESOURCES; + case EHOSTUNREACH: + case EHOSTDOWN: + return DDS_RETCODE_NO_CONNECTION; default: break; } From 410e0afb3b43b84bd041649b53e7b737fe7e8d4e Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 19 Apr 2019 22:01:11 +0200 Subject: [PATCH 037/238] remove "Error occurred on locking entity" messages Those should not be printed to stderr (or wherever), there are errors returned in these cases ... Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_entity.c | 6 ++---- src/core/ddsc/src/dds_instance.c | 21 +-------------------- src/core/ddsc/src/dds_participant.c | 1 - src/core/ddsc/src/dds_read.c | 3 --- src/core/ddsc/src/dds_topic.c | 2 -- src/core/ddsc/src/dds_waitset.c | 1 - 6 files changed, 3 insertions(+), 31 deletions(-) diff --git a/src/core/ddsc/src/dds_entity.c b/src/core/ddsc/src/dds_entity.c index 6704b6e..7d62349 100644 --- a/src/core/ddsc/src/dds_entity.c +++ b/src/core/ddsc/src/dds_entity.c @@ -269,8 +269,8 @@ dds_return_t dds_delete_impl (dds_entity_t entity, bool keep_if_explicit) dds_free (e); } - return ret; - } + return ret; +} dds_entity_t dds_get_parent (dds_entity_t entity) { @@ -404,11 +404,9 @@ dds_return_t dds_get_listener (dds_entity_t entity, dds_listener_t *listener) ddsrt_mutex_unlock (&e->m_observers_lock); dds_entity_unlock(e); } else { - DDS_ERROR("Error occurred on locking entity\n"); ret = DDS_ERRNO(rc); } } else { - DDS_ERROR("Argument listener is NULL\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); } diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index 5d15275..25156fe 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -134,18 +134,15 @@ dds_register_instance( dds_retcode_t rc; if(data == NULL){ - DDS_ERROR("Argument data is NULL\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } if(handle == NULL){ - DDS_ERROR("Argument handle is NULL\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } rc = dds_writer_lock(writer, &wr); if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking writer\n"); ret = DDS_ERRNO(rc); goto err; } @@ -155,7 +152,6 @@ dds_register_instance( *handle = inst->m_iid; ret = DDS_RETCODE_OK; } else { - DDS_ERROR("Unable to create instance\n"); ret = DDS_ERRNO(DDS_RETCODE_ERROR); } thread_state_asleep (ts1); @@ -194,19 +190,16 @@ dds_unregister_instance_ts( dds_writer *wr; if (data == NULL){ - DDS_ERROR("Argument data is NULL\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } if(timestamp < 0){ - DDS_ERROR("Argument timestamp has negative value\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } rc = dds_writer_lock(writer, &wr); if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking writer\n"); - ret = DDS_ERRNO(rc); + ret = DDS_ERRNO(rc); goto err; } @@ -241,7 +234,6 @@ dds_unregister_instance_ih_ts( rc = dds_writer_lock(writer, &wr); if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking writer\n"); ret = DDS_ERRNO(rc); goto err; } @@ -264,7 +256,6 @@ dds_unregister_instance_ih_ts( ret = dds_write_impl (wr, sample, timestamp, action); ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL); } else { - DDS_ERROR("No instance related with the provided handle is found\n"); ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); } thread_state_asleep (ts1); @@ -294,7 +285,6 @@ dds_writedispose_ts( thread_state_asleep (ts1); dds_writer_unlock(wr); } else { - DDS_ERROR("Error occurred on locking writer\n"); ret = DDS_ERRNO(rc); } @@ -336,7 +326,6 @@ dds_dispose_ts( thread_state_asleep (ts1); dds_writer_unlock(wr); } else { - DDS_ERROR("Error occurred on locking writer\n"); ret = DDS_ERRNO(rc); } @@ -366,13 +355,11 @@ dds_dispose_ih_ts( ret = dds_dispose_impl (wr, sample, handle, timestamp); ddsi_sertopic_free_sample (tp, sample, DDS_FREE_ALL); } else { - DDS_ERROR("No instance related with the provided handle is found\n"); ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET); } thread_state_asleep (ts1); dds_writer_unlock(wr); } else { - DDS_ERROR("Error occurred on locking writer\n"); ret = DDS_ERRNO(rc); } @@ -391,7 +378,6 @@ dds_lookup_instance( struct ddsi_serdata *sd; if(data == NULL){ - DDS_ERROR("Argument data is NULL\n"); goto err; } @@ -402,8 +388,6 @@ dds_lookup_instance( ih = ddsi_tkmap_lookup (map, sd); ddsi_serdata_unref (sd); thread_state_asleep (ts1); - } else { - DDS_ERROR("Acquired topic is NULL\n"); } err: return ih; @@ -429,14 +413,12 @@ dds_instance_get_key( struct ddsi_tkmap_instance * tk; if(data == NULL){ - DDS_ERROR("Argument data is NULL\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } topic = dds_instance_info_by_hdl (entity); if(topic == NULL){ - DDS_ERROR("Could not find topic related to the given entity\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto err; } @@ -447,7 +429,6 @@ dds_instance_get_key( ddsi_tkmap_instance_unref (tk); ret = DDS_RETCODE_OK; } else { - DDS_ERROR("No instance related with the provided entity is found\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); } thread_state_asleep (ts1); diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index 587951a..a0c3c03 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -37,7 +37,6 @@ dds_participant_status_validate( dds_return_t ret = DDS_RETCODE_OK; if (mask & ~(DDS_PARTICIPANT_STATUS_MASK)) { - DDS_ERROR("Argument mask is invalid\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); } diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index d595272..5be40d1 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -123,7 +123,6 @@ dds_read_impl( thread_state_awake (ts1); rc = dds_read_lock(reader_or_condition, &rd, &cond, only_reader); if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking entity\n"); ret = DDS_ERRNO(rc); goto fail_awake; } @@ -223,7 +222,6 @@ dds_readcdr_impl( } dds_read_unlock(rd, cond); } else { - DDS_ERROR("Error occurred on locking entity\n"); ret = DDS_ERRNO(rc); } @@ -695,7 +693,6 @@ dds_return_loan( rc = dds_read_lock(reader_or_condition, &rd, &cond, false); if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking entity\n"); ret = DDS_ERRNO(rc); goto fail; } diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 636c4ae..5d62fdf 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -200,7 +200,6 @@ dds_find_topic( ddsrt_mutex_unlock (&dds_global.m_mutex); dds_entity_unlock(p); } else { - DDS_ERROR("Error occurred on locking entity\n"); tp = DDS_ERRNO(rc); } } else { @@ -334,7 +333,6 @@ dds_create_topic_arbitrary ( rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par); if (rc != DDS_RETCODE_OK) { - DDS_ERROR("Error occurred on locking entity\n"); hdl = DDS_ERRNO(rc); goto lock_err; } diff --git a/src/core/ddsc/src/dds_waitset.c b/src/core/ddsc/src/dds_waitset.c index 787ce2c..4d5bd4b 100644 --- a/src/core/ddsc/src/dds_waitset.c +++ b/src/core/ddsc/src/dds_waitset.c @@ -217,7 +217,6 @@ dds_create_waitset( waitset->triggered = NULL; dds_entity_unlock(par); } else { - DDS_ERROR("Error occurred on locking entity\n"); hdl = DDS_ERRNO(rc); } From d8cfececaebed9eae622e38d71f67ffd7b25cad6 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 20 Apr 2019 17:14:23 +0200 Subject: [PATCH 038/238] Fix DATA_AVAILABLE race condition The DATA_AVAILABLE status was reset by read and take while holding the upper-layer reader lock, but after completing the read/take operation on the RHC. As data can be written into the RHC without holding the upper-layer reader lock, new data could arrive in between the reading/taking and the resetting of the DATA_AVAILABLE status, leading to a missed detection. Resetting DATA_AVAILABLE prior to accessing the RHC solves this. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_read.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 5be40d1..6a9dc73 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -156,17 +156,19 @@ dds_read_impl( rd->m_loan_out = true; } } + + /* read/take resets data available status -- must reset before reading because + the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ + dds_entity_status_reset (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); + /* reset DATA_ON_READERS status on subscriber after successful read/take */ + if (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) { + dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); + } if (take) { ret = (dds_return_t)dds_rhc_take(rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond); } else { ret = (dds_return_t)dds_rhc_read(rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond); } - /* read/take resets data available status */ - dds_entity_status_reset(&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); - /* reset DATA_ON_READERS status on subscriber after successful read/take */ - if (dds_entity_kind(rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) { - dds_entity_status_reset(rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); - } dds_read_unlock(rd, cond); fail_awake: @@ -202,6 +204,13 @@ dds_readcdr_impl( thread_state_awake (ts1); rc = dds_read_lock(reader_or_condition, &rd, &cond, false); if (rc == DDS_RETCODE_OK) { + /* read/take resets data available status -- must reset before reading because + the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ + dds_entity_status_reset (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); + /* reset DATA_ON_READERS status on subscriber after successful read/take */ + if (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) { + dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); + } ret = dds_rhc_takecdr ( rd->m_rd->rhc, lock, buf, si, maxs, @@ -211,15 +220,6 @@ dds_readcdr_impl( hand ); - /* read/take resets data available status */ - dds_entity_status_reset(&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); - - /* reset DATA_ON_READERS status on subscriber after successful read/take */ - - if (dds_entity_kind(rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) - { - dds_entity_status_reset(rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); - } dds_read_unlock(rd, cond); } else { ret = DDS_ERRNO(rc); From 053229e5082c7aea7de16ed324c260bf23f9a194 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 20 Apr 2019 17:17:47 +0200 Subject: [PATCH 039/238] missing m_observer_lock on (re)setting statuses Most of the places where the status flags were reset, this happened without holding m_observer_lock protecting these status flags. For most of these statuses, they are only ever set/reset while also holding the entity lock, but this is not true for all of them (DATA_AVAILABLE for example), and thus there are some cases where retrieving the status could lead to losing the raising of a (at least a DATA_AVAILABLE) status. The problem was introduced in ba46cb1140ea86c7e5321e27bc6a20dedb745ff4. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_read.c | 6 ++++++ src/core/ddsc/src/dds_reader.c | 12 ++++++++++++ src/core/ddsc/src/dds_topic.c | 2 ++ src/core/ddsc/src/dds_writer.c | 8 ++++++++ 4 files changed, 28 insertions(+) diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 6a9dc73..114e6ff 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -159,11 +159,14 @@ dds_read_impl( /* read/take resets data available status -- must reset before reading because the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); dds_entity_status_reset (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); /* reset DATA_ON_READERS status on subscriber after successful read/take */ if (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) { dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); } + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); + if (take) { ret = (dds_return_t)dds_rhc_take(rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond); } else { @@ -206,11 +209,14 @@ dds_readcdr_impl( if (rc == DDS_RETCODE_OK) { /* read/take resets data available status -- must reset before reading because the actual writing is protected by RHC lock, not by rd->m_entity.m_lock */ + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); dds_entity_status_reset (&rd->m_entity, DDS_DATA_AVAILABLE_STATUS); /* reset DATA_ON_READERS status on subscriber after successful read/take */ if (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER) { dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); } + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); + ret = dds_rhc_takecdr ( rd->m_rd->rhc, lock, buf, si, maxs, diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 10951e2..6ce57b9 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -643,11 +643,13 @@ dds_get_subscription_matched_status ( if (status) { *status = rd->m_subscription_matched_status; } + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); if (rd->m_entity.m_status_enable & DDS_SUBSCRIPTION_MATCHED_STATUS) { rd->m_subscription_matched_status.total_count_change = 0; rd->m_subscription_matched_status.current_count_change = 0; dds_entity_status_reset(&rd->m_entity, DDS_SUBSCRIPTION_MATCHED_STATUS); } + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); dds_reader_unlock(rd); fail: return ret; @@ -672,11 +674,13 @@ dds_get_liveliness_changed_status ( if (status) { *status = rd->m_liveliness_changed_status; } + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); if (rd->m_entity.m_status_enable & DDS_LIVELINESS_CHANGED_STATUS) { rd->m_liveliness_changed_status.alive_count_change = 0; rd->m_liveliness_changed_status.not_alive_count_change = 0; dds_entity_status_reset(&rd->m_entity, DDS_LIVELINESS_CHANGED_STATUS); } + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); dds_reader_unlock(rd); fail: return ret; @@ -700,11 +704,13 @@ dds_return_t dds_get_sample_rejected_status ( if (status) { *status = rd->m_sample_rejected_status; } + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); if (rd->m_entity.m_status_enable & DDS_SAMPLE_REJECTED_STATUS) { rd->m_sample_rejected_status.total_count_change = 0; rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED; dds_entity_status_reset(&rd->m_entity, DDS_SAMPLE_REJECTED_STATUS); } + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); dds_reader_unlock(rd); fail: return ret; @@ -728,10 +734,12 @@ dds_return_t dds_get_sample_lost_status ( if (status) { *status = rd->m_sample_lost_status; } + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); if (rd->m_entity.m_status_enable & DDS_SAMPLE_LOST_STATUS) { rd->m_sample_lost_status.total_count_change = 0; dds_entity_status_reset(&rd->m_entity, DDS_SAMPLE_LOST_STATUS); } + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); dds_reader_unlock(rd); fail: return ret; @@ -755,10 +763,12 @@ dds_return_t dds_get_requested_deadline_missed_status ( if (status) { *status = rd->m_requested_deadline_missed_status; } + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); if (rd->m_entity.m_status_enable & DDS_REQUESTED_DEADLINE_MISSED_STATUS) { rd->m_requested_deadline_missed_status.total_count_change = 0; dds_entity_status_reset(&rd->m_entity, DDS_REQUESTED_DEADLINE_MISSED_STATUS); } + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); dds_reader_unlock(rd); fail: return ret; @@ -782,10 +792,12 @@ dds_return_t dds_get_requested_incompatible_qos_status ( if (status) { *status = rd->m_requested_incompatible_qos_status; } + ddsrt_mutex_lock (&rd->m_entity.m_observers_lock); if (rd->m_entity.m_status_enable & DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS) { rd->m_requested_incompatible_qos_status.total_count_change = 0; dds_entity_status_reset(&rd->m_entity, DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS); } + ddsrt_mutex_unlock (&rd->m_entity.m_observers_lock); dds_reader_unlock(rd); fail: return ret; diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 5d62fdf..f834f00 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -669,10 +669,12 @@ dds_get_inconsistent_topic_status( if (status) { *status = t->m_inconsistent_topic_status; } + ddsrt_mutex_lock (&t->m_entity.m_observers_lock); if (t->m_entity.m_status_enable & DDS_INCONSISTENT_TOPIC_STATUS) { t->m_inconsistent_topic_status.total_count_change = 0; dds_entity_status_reset(&t->m_entity, DDS_INCONSISTENT_TOPIC_STATUS); } + ddsrt_mutex_unlock (&t->m_entity.m_observers_lock); dds_topic_unlock(t); fail: return ret; diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index cd83d3e..f98d70c 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -518,11 +518,13 @@ dds_get_publication_matched_status ( if (status) { *status = wr->m_publication_matched_status; } + ddsrt_mutex_lock (&wr->m_entity.m_observers_lock); if (wr->m_entity.m_status_enable & DDS_PUBLICATION_MATCHED_STATUS) { wr->m_publication_matched_status.total_count_change = 0; wr->m_publication_matched_status.current_count_change = 0; dds_entity_status_reset(&wr->m_entity, DDS_PUBLICATION_MATCHED_STATUS); } + ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock); dds_writer_unlock(wr); fail: return ret; @@ -547,10 +549,12 @@ dds_get_liveliness_lost_status ( if (status) { *status = wr->m_liveliness_lost_status; } + ddsrt_mutex_lock (&wr->m_entity.m_observers_lock); if (wr->m_entity.m_status_enable & DDS_LIVELINESS_LOST_STATUS) { wr->m_liveliness_lost_status.total_count_change = 0; dds_entity_status_reset(&wr->m_entity, DDS_LIVELINESS_LOST_STATUS); } + ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock); dds_writer_unlock(wr); fail: return ret; @@ -575,10 +579,12 @@ dds_get_offered_deadline_missed_status( if (status) { *status = wr->m_offered_deadline_missed_status; } + ddsrt_mutex_lock (&wr->m_entity.m_observers_lock); if (wr->m_entity.m_status_enable & DDS_OFFERED_DEADLINE_MISSED_STATUS) { wr->m_offered_deadline_missed_status.total_count_change = 0; dds_entity_status_reset(&wr->m_entity, DDS_OFFERED_DEADLINE_MISSED_STATUS); } + ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock); dds_writer_unlock(wr); fail: return ret; @@ -603,10 +609,12 @@ dds_get_offered_incompatible_qos_status ( if (status) { *status = wr->m_offered_incompatible_qos_status; } + ddsrt_mutex_lock (&wr->m_entity.m_observers_lock); if (wr->m_entity.m_status_enable & DDS_OFFERED_INCOMPATIBLE_QOS_STATUS) { wr->m_offered_incompatible_qos_status.total_count_change = 0; dds_entity_status_reset(&wr->m_entity, DDS_OFFERED_INCOMPATIBLE_QOS_STATUS); } + ddsrt_mutex_unlock (&wr->m_entity.m_observers_lock); dds_writer_unlock(wr); fail: return ret; From 8c6055f92cd013d693951c774f320ae1629b08ca Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 15 Apr 2019 11:52:43 +0200 Subject: [PATCH 040/238] initial version of permance/network check tool The current situation for performance measurements and checking network behaviour is rather unsatisfactory, as the only tools available are ``pubsub`` and the ``roundtrip`` and ``throughput`` examples. The first can do many things thanks to its thousand-and-one options, but its purpose really is to be able to read/write arbitrary data with arbitrary QoS -- though the arbitrary data bit was lost in the hacked conversion from the original code. The latter two have a terrible user interface, don't perform any verification that the measurement was successful and do not provide the results in a convenient form. Furthermore, the abuse of the two examples as the primary means for measuring performance has resulted in a reduction of their value as an example, e.g., they can do waitset- or listener-based reading (and the throughput one also polling-based), but that kind of complication does not help a new user understand what is going on. Especially not given that these features were simply hacked in. Hence the need for a new tool, one that integrates the common measurements and can be used to verify that the results make sense. It is not quite done yet, in particular it is lacking in a number of aspects: * no measurement of CPU- and network load, memory usage and context switches yet; * very limited statistics (min/max/average, if you're lucky; no interesting things such as jitter on a throughput test yet); * it can't yet gather the data from all participants in the network using DDS; * it doesn't output the data in a convenient file format yet; * it doesn't allow specifying boundaries within which the results must fall for the run to be successful. What it does verify is that all the endpoint matches that should exist given the discovered participant do in fact come into existence, reporting an error (and exiting with an exit status code of 1) if they don't, as well as checking the number of participants. With the way the DDSI protocol works, this is a pretty decent network connectivity check. The raw measurements needed for the desired statistics (apart from system-level measurements) are pretty much made, so the main thing that still needs to be done is exploit them and output them. It can already replace the examples for most benchmarks (only the 50%/90%/99% percentiles are still missing for a complete replacement). Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_read.c | 5 +- src/tools/CMakeLists.txt | 1 + src/tools/ddsperf/CMakeLists.txt | 23 + src/tools/ddsperf/ddsperf.c | 2036 +++++++++++++++++++++++++++ src/tools/ddsperf/ddsperf_types.idl | 29 + 5 files changed, 2091 insertions(+), 3 deletions(-) create mode 100644 src/tools/ddsperf/CMakeLists.txt create mode 100644 src/tools/ddsperf/ddsperf.c create mode 100644 src/tools/ddsperf/ddsperf_types.idl diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 114e6ff..37e35ec 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -686,13 +686,12 @@ dds_return_loan( dds_readcond *cond; dds_return_t ret = DDS_RETCODE_OK; - if (!buf ) { + if (!buf) { DDS_ERROR("Argument buf is NULL\n"); ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto fail; } - if(*buf == NULL && bufsz > 0){ - DDS_ERROR("Argument buf is NULL\n"); + if (*buf == NULL && bufsz > 0) { ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER); goto fail; } diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index 7e615a1..9c2d51c 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -13,6 +13,7 @@ set(CMAKE_INSTALL_TOOLSDIR "${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}/tools add_subdirectory(pubsub) add_subdirectory(config) add_subdirectory(ddsls) +add_subdirectory(ddsperf) # VxWorks build machines use OpenJDK 8, which lack jfxrt.jar. Do not build launcher on that platform. # diff --git a/src/tools/ddsperf/CMakeLists.txt b/src/tools/ddsperf/CMakeLists.txt new file mode 100644 index 0000000..c1c12e0 --- /dev/null +++ b/src/tools/ddsperf/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +# v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# +idlc_generate(ddsperf_types ddsperf_types.idl) +add_executable(ddsperf ddsperf.c) +target_link_libraries(ddsperf ddsperf_types ddsc) +if(WIN32) + target_compile_definitions(ddsperf PRIVATE _CRT_SECURE_NO_WARNINGS) +endif() + +install( + TARGETS ddsperf + DESTINATION "${CMAKE_INSTALL_BINDIR}" + COMPONENT dev +) diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c new file mode 100644 index 0000000..51874a4 --- /dev/null +++ b/src/tools/ddsperf/ddsperf.c @@ -0,0 +1,2036 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#define _ISOC99_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef _WIN32 +#include +#endif +#include + +#include "dds/dds.h" +#include "ddsperf_types.h" + +#include "dds/ddsrt/process.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/sockets.h" +#include "dds/ddsrt/threads.h" +#include "dds/ddsrt/random.h" +#include "dds/ddsrt/avl.h" +#include "dds/ddsrt/fibheap.h" + +#define UDATA_MAGIC "DDSPerf:" +#define UDATA_MAGIC_SIZE (sizeof (UDATA_MAGIC) - 1) + +enum topicsel { + KS, /* KeyedSeq type: seq#, key, sequence-of-octet */ + K32, /* Keyed32 type: seq#, key, array-of-24-octet (sizeof = 32) */ + K256, /* Keyed256 type: seq#, key, array-of-248-octet (sizeof = 256) */ + OU /* OneULong type: seq# */ +}; + +enum submode { + SM_NONE, /* no subscriber at all */ + SM_WAITSET, /* subscriber using a waitset */ + SM_POLLING, /* ... using polling, sleeping for 1ms if no data */ + SM_LISTENER /* ... using a DATA_AVAILABLE listener */ +}; + +static const char *argv0; +static volatile sig_atomic_t termflag = 0; + +/* Domain participant, guard condition for termination, domain id */ +static dds_entity_t dp; +static dds_instance_handle_t dp_handle; +static dds_entity_t termcond; +static dds_domainid_t did = DDS_DOMAIN_DEFAULT; + +/* Readers for built-in topics to get discovery information */ +static dds_entity_t rd_participants, rd_subscriptions, rd_publications; + +/* Topics, readers, writers (except for pong writers: there are + many of those) */ +static dds_entity_t tp_data, tp_ping, tp_pong; +static char tpname_data[32], tpname_ping[32], tpname_pong[32]; +static dds_entity_t sub, pub, wr_data, wr_ping, rd_data, rd_ping, rd_pong; + +/* Number of different key values to use (must be 1 for OU type) */ +static unsigned nkeyvals = 1; + +/* Topic type to use */ +static enum topicsel topicsel = OU; + +/* Data and ping/pong subscriber triggering modes */ +static enum submode submode = SM_LISTENER; +static enum submode pingpongmode = SM_LISTENER; + +/* Size of the sequence in KeyedSeq type in bytes */ +static unsigned baggagesize = 0; + +/* Whether or not to register instances prior to writing */ +static bool register_instances = true; + +/* Maximum run time in seconds */ +static double dur = HUGE_VAL; + +/* Minimum number of peers (if not met, exit status is 1) */ +static uint32_t minmatch = 0; + +/* Maximum time it may take to discover all MINMATCH peers */ +static double maxwait = HUGE_VAL; + +/* Number of participants for which all expected endpoints + have been matched (this includes the local participant + if ignorelocal is DDS_IGNORELOCAL_NONE) [protected by + disc_lock] */ +static uint32_t matchcount = 0; + +/* An error is always signalled if not all endpoints of a + participant have been discovered within a set amount of + time (5s, currently) [protected by disc_lock] */ +static uint32_t matchtimeout = 0; + +/* Data is published in bursts of this many samples */ +static unsigned burstsize = 1; + +/* Whether to use reliable or best-effort readers/writers */ +static bool reliable = true; + +/* History depth for throughput data reader and writer; 0 is + KEEP_ALL, otherwise it is KEEP_LAST histdepth. Ping/pong + always uses KEEP_LAST 1. */ +static int32_t histdepth = 0; + +/* Publishing rate in Hz, HUGE_VAL means as fast as possible, + 0 means no throughput data is published at all */ +static double rate; + +/* Fraction of throughput data samples that double as a ping + message */ +static uint32_t ping_frac = 0; + +/* Setting for "ignore local" reader/writer QoS: whether or + not to ignore readers and writers in the same particiapnt + that would otherwise match */ +static dds_ignorelocal_kind_t ignorelocal = DDS_IGNORELOCAL_PARTICIPANT; + +/* Pinging interval for roundtrip testing, 0 means as fast as + possible, DDS_INFINITY means never */ +static dds_duration_t ping_intv; + +static ddsrt_mutex_t disc_lock; + +/* Publisher statistics and lock protecting it */ +struct hist { + unsigned nbins; + uint64_t binwidth; + uint64_t bin0; /* bins are [bin0,bin0+binwidth),[bin0+binwidth,bin0+2*binwidth) */ + uint64_t binN; /* bin0 + nbins*binwidth */ + uint64_t min, max; /* min and max observed since last reset */ + uint64_t under, over; /* < bin0, >= binN */ + uint64_t bins[]; +}; + +static ddsrt_mutex_t pubstat_lock; +static struct hist *pubstat_hist; + +/* Subscriber statistics for tracking number of samples received + and lost per source */ +struct eseq_stat { + /* totals */ + uint64_t nrecv; + uint64_t nlost; + uint64_t nrecv_bytes; + + /* stats printer state */ + uint64_t nrecv_ref; + uint64_t nlost_ref; + uint64_t nrecv_bytes_ref; +}; + +struct eseq_admin { + ddsrt_mutex_t lock; + unsigned nkeys; + unsigned nph; + dds_instance_handle_t *ph; + struct eseq_stat *stats; + uint32_t **eseq; +}; + +static struct eseq_admin eseq_admin; + +/* Entry for mapping ping/data publication handle to pong writer */ +struct subthread_arg_pongwr { + dds_instance_handle_t pubhandle; + dds_instance_handle_t pphandle; + dds_entity_t wr_pong; +}; + +/* Entry for mapping pong publication handle to latency statistics */ +struct subthread_arg_pongstat { + dds_instance_handle_t pubhandle; + dds_instance_handle_t pphandle; + uint64_t min, max; + uint64_t sum; + uint32_t cnt; +}; + +/* Pong statistics is stored in n array of npongstat entries + [protected by pongstat_lock] */ +static ddsrt_mutex_t pongstat_lock; +static uint32_t npongstat; +static struct subthread_arg_pongstat *pongstat; + +/* All topics have a sequence number, this is the one of the + latest ping sent and the number of pongs received for that + sequence number. Also the time at which it was sent for + generating new ping messages in the case of loss of topology + changes, and a timestamp after which a warning is printed + when a new ping is published. [All protected by + pongwr_lock] */ +static dds_time_t cur_ping_time; +static dds_time_t twarn_ping_timeout; +static uint32_t cur_ping_seq; +static uint32_t n_pong_seen; + +/* Number of pongs expected for each ping [protected by + pongwr_lock] */ +static uint32_t n_pong_expected; + +/* Table mapping data and ping publication handles to writers + of pongs (one per participant in a unique partition so that + a participant only receives responses to its own pings) is + a simply array of npongwr entries [protected by pongwr_lock] */ +static ddsrt_mutex_t pongwr_lock; +static uint32_t npongwr; +static struct subthread_arg_pongwr *pongwr; + +/* Each subscriber thread gets its own not-quite-pre-allocated + set of samples (it does use a loan, but that loan gets reused) */ +struct subthread_arg { + dds_entity_t rd; + uint32_t max_samples; + dds_sample_info_t *iseq; + void **mseq; +}; + +/* Type used for converting GUIDs to strings, used for generating + the per-participant partition names */ +struct guidstr { + char str[36]; +}; + +/* Endpoints that can be matched; all endpoints except for a data + subscriber always exist; the data subscriber is only created if + requested */ +#define MM_RD_DATA 1u +#define MM_RD_PING 2u +#define MM_RD_PONG 4u +#define MM_WR_DATA 8u +#define MM_WR_PING 16u +#define MM_WR_PONG 32u +#define MM_ALL (2 * MM_WR_PONG - 1) + +struct ppant { + ddsrt_avl_node_t avlnode; /* embedded AVL node for handle index */ + ddsrt_fibheap_node_t fhnode; /* prio queue for timeout handling */ + dds_instance_handle_t handle; /* participant instance handle */ + dds_builtintopic_guid_t guid; /* participant GUID */ + char *hostname; /* hostname is taken from user_data QoS */ + uint32_t pid; /* pid is also taken from user_data QoS */ + dds_time_t tdisc; /* time at which it was discovered */ + dds_time_t tdeadline; /* by what time must unmatched be 0 */ + uint32_t unmatched; /* expected but not yet detected endpoints */ +}; + +static int cmp_instance_handle (const void *va, const void *vb) +{ + const dds_instance_handle_t *a = va; + const dds_instance_handle_t *b = vb; + return (*a == *b) ? 0 : (*a < *b) ? -1 : 1; +} + +/* AVL tree of ppant structures indexed on handle using cmp_instance_handle */ +static ddsrt_avl_treedef_t ppants_td = DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct ppant, avlnode), offsetof (struct ppant, handle), cmp_instance_handle, 0); +static ddsrt_avl_tree_t ppants; + +/* Priority queue (Fibonacci heap) of ppant structures with tdeadline as key */ +static int cmp_ppant_tdeadline (const void *va, const void *vb) +{ + const struct ppant *a = va; + const struct ppant *b = vb; + return (a->tdeadline == b->tdeadline) ? 0 : (a->tdeadline < b->tdeadline) ? -1 : 1; +} + +static ddsrt_fibheap_def_t ppants_to_match_fhd = DDSRT_FIBHEAPDEF_INITIALIZER (offsetof (struct ppant, fhnode), cmp_ppant_tdeadline); +static ddsrt_fibheap_t ppants_to_match; + +/* Printing error messages: error2 is for DDS errors, error3 is for usage errors */ +static void verrorx (int exitcode, const char *fmt, va_list ap) ddsrt_attribute_noreturn; +static void error2 (const char *fmt, ...) ddsrt_attribute_format ((printf, 1, 2)) ddsrt_attribute_noreturn; +static void error3 (const char *fmt, ...) ddsrt_attribute_format ((printf, 1, 2)) ddsrt_attribute_noreturn; + +static void publication_matched_listener (dds_entity_t wr, const dds_publication_matched_status_t status, void *arg); + +struct seq_keyval { + uint32_t seq; + int32_t keyval; +}; + +union data { + uint32_t seq; + struct seq_keyval seq_keyval; + KeyedSeq ks; + Keyed32 k32; + Keyed256 k256; + OneULong ou; +}; + +static void verrorx (int exitcode, const char *fmt, va_list ap) +{ + vprintf (fmt, ap); + fflush (stdout); + exit (exitcode); +} + +static void error2 (const char *fmt, ...) +{ + va_list ap; + va_start (ap, fmt); + verrorx (2, fmt, ap); +} + +static void error3 (const char *fmt, ...) +{ + va_list ap; + va_start (ap, fmt); + verrorx (3, fmt, ap); +} + +static char *make_guidstr (struct guidstr *buf, const dds_builtintopic_guid_t *guid) +{ + snprintf (buf->str, sizeof (buf->str), "%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x_%02x%02x%02x%02x", + guid->v[0], guid->v[1], guid->v[2], guid->v[3], + guid->v[4], guid->v[5], guid->v[6], guid->v[7], + guid->v[8], guid->v[9], guid->v[10], guid->v[11], + guid->v[12], guid->v[13], guid->v[14], guid->v[15]); + return buf->str; +} + +static void hist_reset_minmax (struct hist *h) +{ + h->min = UINT64_MAX; + h->max = 0; +} + +static void hist_reset (struct hist *h) +{ + hist_reset_minmax (h); + h->under = 0; + h->over = 0; + memset (h->bins, 0, h->nbins * sizeof (*h->bins)); +} + +static struct hist *hist_new (unsigned nbins, uint64_t binwidth, uint64_t bin0) +{ + struct hist *h = malloc (sizeof (*h) + nbins * sizeof (*h->bins)); + h->nbins = nbins; + h->binwidth = binwidth; + h->bin0 = bin0; + h->binN = h->bin0 + h->nbins * h->binwidth; + hist_reset (h); + return h; +} + +static void hist_free (struct hist *h) +{ + free (h); +} + +static void hist_record (struct hist *h, uint64_t x, unsigned weight) +{ + if (x < h->min) + h->min = x; + if (x > h->max) + h->max = x; + if (x < h->bin0) + h->under += weight; + else if (x >= h->binN) + h->over += weight; + else + h->bins[(x - h->bin0) / h->binwidth] += weight; +} + +static void xsnprintf(char *buf, size_t bufsz, size_t *p, const char *fmt, ...) +{ + if (*p < bufsz) + { + int n; + va_list ap; + va_start (ap, fmt); + n = vsnprintf (buf + *p, bufsz - *p, fmt, ap); + va_end (ap); + *p += (size_t) n; + } +} + +static void hist_print (const char *prefix, struct hist *h, dds_time_t dt, int reset) +{ + const size_t l_size = sizeof(char) * h->nbins + 200 + strlen (prefix); + const size_t hist_size = sizeof(char) * h->nbins + 1; + char *l = (char *) malloc(l_size); + char *hist = (char *) malloc(hist_size); + double dt_s = (double)dt / 1e9, avg; + uint64_t peak = 0, cnt = h->under + h->over; + size_t p = 0; + + xsnprintf (l, l_size, &p, "%s", prefix); + + hist[h->nbins] = 0; + for (unsigned i = 0; i < h->nbins; i++) + { + cnt += h->bins[i]; + if (h->bins[i] > peak) + peak = h->bins[i]; + } + + const uint64_t p1 = peak / 100; + const uint64_t p10 = peak / 10; + const uint64_t p20 = 1 * peak / 5; + const uint64_t p40 = 2 * peak / 5; + const uint64_t p60 = 3 * peak / 5; + const uint64_t p80 = 4 * peak / 5; + for (unsigned i = 0; i < h->nbins; i++) + { + if (h->bins[i] == 0) hist[i] = ' '; + else if (h->bins[i] <= p1) hist[i] = '.'; + else if (h->bins[i] <= p10) hist[i] = '_'; + else if (h->bins[i] <= p20) hist[i] = '-'; + else if (h->bins[i] <= p40) hist[i] = '='; + else if (h->bins[i] <= p60) hist[i] = 'x'; + else if (h->bins[i] <= p80) hist[i] = 'X'; + else hist[i] = '@'; + } + + avg = (double) cnt / dt_s; + if (avg < 999.5) + xsnprintf (l, l_size, &p, "%5.3g", avg); + else if (avg < 1e6) + xsnprintf (l, l_size, &p, "%4.3gk", avg / 1e3); + else + xsnprintf (l, l_size, &p, "%4.3gM", avg / 1e6); + xsnprintf (l, l_size, &p, "/s "); + + if (h->min == UINT64_MAX) + xsnprintf (l, l_size, &p, " inf "); + else if (h->min < 1000) + xsnprintf (l, l_size, &p, "%3"PRIu64"n ", h->min); + else if (h->min + 500 < 1000000) + xsnprintf (l, l_size, &p, "%3"PRIu64"u ", (h->min + 500) / 1000); + else if (h->min + 500000 < 1000000000) + xsnprintf (l, l_size, &p, "%3"PRIu64"m ", (h->min + 500000) / 1000000); + else + xsnprintf (l, l_size, &p, "%3"PRIu64"s ", (h->min + 500000000) / 1000000000); + + if (h->bin0 > 0) { + int pct = (cnt == 0) ? 0 : 100 * (int) ((h->under + cnt/2) / cnt); + xsnprintf (l, l_size, &p, "%3d%% ", pct); + } + + { + int pct = (cnt == 0) ? 0 : 100 * (int) ((h->over + cnt/2) / cnt); + xsnprintf (l, l_size, &p, "|%s| %3d%%", hist, pct); + } + + if (h->max < 1000) + xsnprintf (l, l_size, &p, " %3"PRIu64"n", h->max); + else if (h->max + 500 < 1000000) + xsnprintf (l, l_size, &p, " %3"PRIu64"u", (h->max + 500) / 1000); + else if (h->max + 500000 < 1000000000) + xsnprintf (l, l_size, &p, " %3"PRIu64"m", (h->max + 500000) / 1000000); + else + xsnprintf (l, l_size, &p, " %3"PRIu64"s", (h->max + 500000000) / 1000000000); + + (void) p; + puts (l); + fflush (stdout); + free (l); + free (hist); + if (reset) + hist_reset (h); +} + +static void *make_baggage (dds_sequence_t *b, unsigned cnt) +{ + b->_maximum = b->_length = cnt; + if (cnt == 0) + b->_buffer = NULL; + else + { + b->_buffer = malloc (b->_maximum); + memset(b->_buffer, 0xee, b->_maximum); + } + return b->_buffer; +} + +static void *init_sample (union data *data, uint32_t seq) +{ + void *baggage = NULL; + switch (topicsel) + { + case KS: + data->ks.seq = seq; + data->ks.keyval = 0; + baggage = make_baggage (&data->ks.baggage, baggagesize); + break; + case K32: + data->k32.seq = seq; + data->k32.keyval = 0; + memset (data->k32.baggage, 0xee, sizeof (data->k32.baggage)); + break; + case K256: + data->k256.seq = seq; + data->k256.keyval = 0; + memset (data->k256.baggage, 0xee, sizeof (data->k256.baggage)); + break; + case OU: + data->ou.seq = seq; + break; + } + return baggage; +} + +static uint32_t pubthread (void *varg) +{ + int result; + dds_instance_handle_t *ihs; + dds_time_t ntot = 0, tfirst, tfirst0; + union data data; + uint64_t timeouts = 0; + void *baggage = NULL; + (void) varg; + + memset (&data, 0, sizeof (data)); + assert (nkeyvals > 0); + assert (topicsel != OU || nkeyvals == 1); + + baggage = init_sample (&data, 0); + ihs = malloc (nkeyvals * sizeof (dds_instance_handle_t)); + for (unsigned k = 0; k < nkeyvals; k++) + { + data.seq_keyval.keyval = (int32_t) k; + if (register_instances) + dds_register_instance (wr_data, &ihs[k], &data); + else + ihs[k] = 0; + } + data.seq_keyval.keyval = 0; + + tfirst0 = tfirst = dds_time(); + + unsigned bi = 0; + while (!termflag) + { + /* lsb of timestamp is abused to signal whether the sample is a ping requiring a response or not */ + bool reqresp = (ping_frac == 0) ? 0 : (ping_frac == UINT32_MAX) ? 1 : (ddsrt_random () <= ping_frac); + const dds_time_t t_write = (dds_time () & ~1) | reqresp; + if ((result = dds_write_ts (wr_data, &data, t_write)) != DDS_RETCODE_OK) + { + printf ("write error: %d\n", result); + fflush (stdout); + if (dds_err_nr (result) != DDS_RETCODE_TIMEOUT) + exit (2); + timeouts++; + /* retry with original timestamp, it really is just a way of reporting + blocking for an exceedingly long time */ + continue; + } + if (reqresp) + { + dds_write_flush (wr_data); + } + + const dds_time_t t_post_write = dds_time (); + dds_time_t t = t_post_write; + ddsrt_mutex_lock (&pubstat_lock); + hist_record (pubstat_hist, (uint64_t) ((t_post_write - t_write) / 1), 1); + ntot++; + ddsrt_mutex_unlock (&pubstat_lock); + + data.seq_keyval.keyval = (data.seq_keyval.keyval + 1) % (int32_t) nkeyvals; + data.seq++; + + if (rate < HUGE_VAL) + { + if (++bi == burstsize) + { + /* FIXME: should average rate over a short-ish period, rather than over the entire run */ + while (((double) (ntot / burstsize) / ((double) (t - tfirst0) / 1e9 + 5e-3)) > rate && !termflag) + { + /* FIXME: flushing manually because batching is not yet implemented properly */ + dds_write_flush (wr_data); + dds_sleepfor (DDS_MSECS (1)); + t = dds_time (); + } + bi = 0; + } + } + } + if (baggage) + free (baggage); + free (ihs); + return 0; +} + +static void init_eseq_admin (struct eseq_admin *ea, unsigned nkeys) +{ + ddsrt_mutex_init (&ea->lock); + ea->nkeys = nkeys; + ea->nph = 0; + ea->ph = NULL; + ea->stats = NULL; + ea->eseq = NULL; +} + +static void fini_eseq_admin (struct eseq_admin *ea) +{ + free (ea->ph); + free (ea->stats); + for (unsigned i = 0; i < ea->nph; i++) + free (ea->eseq[i]); + ddsrt_mutex_destroy (&ea->lock); + free (ea->eseq); +} + +static int check_eseq (struct eseq_admin *ea, uint32_t seq, uint32_t keyval, uint32_t size, const dds_instance_handle_t pubhandle) +{ + uint32_t *eseq; + if (keyval >= ea->nkeys) + { + printf ("received key %u >= nkeys %u\n", keyval, ea->nkeys); + exit (3); + } + ddsrt_mutex_lock (&ea->lock); + for (uint32_t i = 0; i < ea->nph; i++) + if (pubhandle == ea->ph[i]) + { + uint32_t e = ea->eseq[i][keyval]; + ea->eseq[i][keyval] = seq + ea->nkeys; + ea->stats[i].nrecv++; + ea->stats[i].nrecv_bytes += size; + ea->stats[i].nlost += seq - e; + ddsrt_mutex_unlock (&ea->lock); + return seq == e; + } + ea->ph = realloc (ea->ph, (ea->nph + 1) * sizeof (*ea->ph)); + ea->ph[ea->nph] = pubhandle; + ea->eseq = realloc (ea->eseq, (ea->nph + 1) * sizeof (*ea->eseq)); + ea->eseq[ea->nph] = malloc (ea->nkeys * sizeof (*ea->eseq[ea->nph])); + eseq = ea->eseq[ea->nph]; + for (unsigned i = 0; i < ea->nkeys; i++) + eseq[i] = seq + (i - keyval) + (i <= keyval ? ea->nkeys : 0); + ea->stats = realloc (ea->stats, (ea->nph + 1) * sizeof (*ea->stats)); + memset (&ea->stats[ea->nph], 0, sizeof (ea->stats[ea->nph])); + ea->stats[ea->nph].nrecv = 1; + ea->stats[ea->nph].nrecv_bytes = size; + ea->nph++; + ddsrt_mutex_unlock (&ea->lock); + return 1; +} + +static dds_instance_handle_t get_pphandle_for_pubhandle (dds_instance_handle_t pubhandle) +{ + /* FIXME: implement the get_matched_... interfaces so there's no need for keeping a reader + (and having to GC it, which I'm skipping here ...) */ + int32_t n; + void *msg = NULL; + dds_sample_info_t info; + if ((n = dds_read_instance (rd_publications, &msg, &info, 1, 1, pubhandle)) < 0) + error2 ("dds_read_instance(rd_publications, %"PRIx64") failed: %d\n", pubhandle, (int) n); + else if (n == 0 || !info.valid_data) + { + printf ("get_pong_writer: publication handle %"PRIx64" not found\n", pubhandle); + fflush (stdout); + return 0; + } + else + { + const dds_builtintopic_endpoint_t *sample = msg; + dds_instance_handle_t pphandle = sample->participant_instance_handle; + dds_return_loan (rd_publications, &msg, n); + return pphandle; + } +} + +static bool update_roundtrip (dds_instance_handle_t pubhandle, uint64_t tdelta, bool isping, uint32_t seq) +{ + bool allseen; + ddsrt_mutex_lock (&pongstat_lock); + if (isping && seq == cur_ping_seq) + allseen = (++n_pong_seen == n_pong_expected); + else + allseen = false; + for (uint32_t i = 0; i < npongstat; i++) + if (pongstat[i].pubhandle == pubhandle) + { + struct subthread_arg_pongstat * const x = &pongstat[i]; + if (tdelta < x->min) x->min = tdelta; + if (tdelta > x->max) x->max = tdelta; + x->sum += tdelta; + x->cnt++; + ddsrt_mutex_unlock (&pongstat_lock); + return allseen; + } + pongstat = realloc (pongstat, (npongstat + 1) * sizeof (*pongstat)); + struct subthread_arg_pongstat * const x = &pongstat[npongstat]; + x->pubhandle = pubhandle; + x->pphandle = get_pphandle_for_pubhandle (pubhandle); + x->min = x->max = x->sum = tdelta; + x->cnt = 1; + npongstat++; + ddsrt_mutex_unlock (&pongstat_lock); + return allseen; +} + +static dds_entity_t get_pong_writer_locked (dds_instance_handle_t pubhandle) +{ + dds_instance_handle_t pphandle; + + for (uint32_t j = 0; j < npongwr; j++) + if (pongwr[j].pubhandle == pubhandle) + return pongwr[j].wr_pong; + + /* FIXME: implement the get_matched_... interfaces so there's no need for keeping a reader + (and having to GC it, which I'm skipping here ...) */ + pphandle = get_pphandle_for_pubhandle (pubhandle); + + /* This gets called when no writer is associaed yet with pubhandle, but it may be that a writer + is associated already with pphandle (because there is the data writer and the ping writer) */ + for (uint32_t i = 0; i < npongwr; i++) + { + if (pongwr[i].pphandle == pphandle) + { + dds_entity_t wr_pong = pongwr[i].wr_pong; + if (pongwr[i].pubhandle == 0) + { + pongwr[i].pubhandle = pubhandle; + ddsrt_mutex_unlock (&pongwr_lock); + return wr_pong; + } + else + { + pongwr = realloc (pongwr, (npongwr + 1) * sizeof (*pongwr)); + pongwr[npongwr].pubhandle = pubhandle; + pongwr[npongwr].pphandle = pphandle; + pongwr[npongwr].wr_pong = wr_pong; + npongwr++; + ddsrt_mutex_unlock (&pongwr_lock); + return wr_pong; + } + } + } + printf ("get_pong_writer: participant handle %"PRIx64" not found\n", pphandle); + fflush (stdout); + return 0; +} + +static dds_entity_t get_pong_writer (dds_instance_handle_t pubhandle) +{ + dds_entity_t wr_pong = 0; + ddsrt_mutex_lock (&pongwr_lock); + wr_pong = get_pong_writer_locked (pubhandle); + ddsrt_mutex_unlock (&pongwr_lock); + return wr_pong; +} + +static bool process_data (dds_entity_t rd, struct subthread_arg *arg) +{ + uint32_t max_samples = arg->max_samples; + dds_sample_info_t *iseq = arg->iseq; + void **mseq = arg->mseq; + int32_t nread_data; + if ((nread_data = dds_take (rd, mseq, iseq, max_samples, max_samples)) < 0) + error2 ("dds_take (rd_data): %d\n", (int) nread_data); + for (int32_t i = 0; i < nread_data; i++) + { + if (iseq[i].valid_data) + { + uint32_t seq, keyval, size; + switch (topicsel) + { + case KS: { KeyedSeq *d = (KeyedSeq *) mseq[i]; keyval = d->keyval; seq = d->seq; size = 12 + d->baggage._length; } break; + case K32: { Keyed32 *d = (Keyed32 *) mseq[i]; keyval = d->keyval; seq = d->seq; size = 32; } break; + case K256: { Keyed256 *d = (Keyed256 *) mseq[i]; keyval = d->keyval; seq = d->seq; size = 256; } break; + case OU: { OneULong *d = (OneULong *) mseq[i]; keyval = 0; seq = d->seq; size = 4; } break; + } + (void) check_eseq (&eseq_admin, seq, keyval, size, iseq[i].publication_handle); + if (iseq[i].source_timestamp & 1) + { + dds_entity_t wr_pong = 0; + if ((wr_pong = get_pong_writer (iseq[i].publication_handle)) != 0) + { + dds_return_t rc; + if ((rc = dds_write_ts (wr_pong, mseq[i], iseq[i].source_timestamp - 1)) < 0 && dds_err_nr(rc) != DDS_RETCODE_TIMEOUT) + error2 ("dds_write_ts (wr_pong, mseq[i], iseq[i].source_timestamp): %d\n", (int) rc); + dds_write_flush (wr_pong); + } + } + } + } + return (nread_data > 0); +} + +static bool process_ping (dds_entity_t rd, struct subthread_arg *arg) +{ + /* Ping sends back Pongs with the lsb 1; Data sends back Pongs with the lsb 0. This way, the Pong handler can + figure out whether to Ping again or not by looking at the lsb. If it is 1, another Ping is required */ + uint32_t max_samples = arg->max_samples; + dds_sample_info_t *iseq = arg->iseq; + void **mseq = arg->mseq; + int32_t nread_ping; + if ((nread_ping = dds_take (rd, mseq, iseq, max_samples, max_samples)) < 0) + error2 ("dds_take (rd_data): %d\n", (int) nread_ping); + for (int32_t i = 0; i < nread_ping; i++) + { + if (iseq[i].valid_data) + { + dds_entity_t wr_pong; + if ((wr_pong = get_pong_writer (iseq[i].publication_handle)) != 0) + { + dds_return_t rc; + if ((rc = dds_write_ts (wr_pong, mseq[i], iseq[i].source_timestamp | 1)) < 0 && dds_err_nr(rc) != DDS_RETCODE_TIMEOUT) + error2 ("dds_write_ts (wr_pong, mseq[i], iseq[i].source_timestamp): %d\n", (int) rc); + dds_write_flush (wr_pong); + } + } + } + return (nread_ping > 0); +} + +static bool process_pong (dds_entity_t rd, struct subthread_arg *arg) +{ + uint32_t max_samples = arg->max_samples; + dds_sample_info_t *iseq = arg->iseq; + void **mseq = arg->mseq; + int32_t nread_pong; + if ((nread_pong = dds_take (rd, mseq, iseq, max_samples, max_samples)) < 0) + error2 ("dds_take (rd_pong): %d\n", (int) nread_pong); + else if (nread_pong > 0) + { + dds_time_t tnow = dds_time (); + for (int32_t i = 0; i < nread_pong; i++) + if (iseq[i].valid_data) + { + uint32_t * const seq = mseq[i]; + const bool isping = (iseq[i].source_timestamp & 1) != 0; + const bool all = update_roundtrip (iseq[i].publication_handle, (uint64_t) (tnow - iseq[i].source_timestamp) / 2, isping, *seq); + if (isping && all && ping_intv == 0) + { + /* If it is a pong sent in response to a ping, and all known nodes have responded, send out a new ping */ + dds_return_t rc; + ddsrt_mutex_lock (&pongwr_lock); + n_pong_seen = 0; + cur_ping_time = dds_time (); + cur_ping_seq = ++(*seq); + ddsrt_mutex_unlock (&pongwr_lock); + if ((rc = dds_write_ts (wr_ping, mseq[i], dds_time () | 1)) < 0 && dds_err_nr(rc) != DDS_RETCODE_TIMEOUT) + error2 ("dds_write (wr_ping, mseq[i]): %d\n", (int) rc); + dds_write_flush (wr_ping); + } + } + } + return (nread_pong > 0); +} + +static void maybe_send_new_ping (dds_time_t tnow, dds_time_t *tnextping) +{ + void *baggage; + union data data; + int32_t rc; + assert (ping_intv != DDS_INFINITY); + ddsrt_mutex_lock (&pongwr_lock); + if (tnow < cur_ping_time + (ping_intv == 0 ? DDS_SECS (1) : ping_intv)) + { + if (ping_intv == 0) + *tnextping = cur_ping_time + DDS_SECS (1); + ddsrt_mutex_unlock (&pongwr_lock); + } + else + { + if (tnow > twarn_ping_timeout) + { + printf ("[%"PRIdPID"] ping timed out ... sending new ping\n", ddsrt_getpid ()); + fflush (stdout); + } + n_pong_seen = 0; + cur_ping_time = tnow; + if (ping_intv > 0) + *tnextping = cur_ping_time + ping_intv; + else if (ping_intv == 0) + *tnextping = cur_ping_time + DDS_SECS (1); + if (ping_intv > 0 && *tnextping > twarn_ping_timeout) + twarn_ping_timeout = *tnextping + ping_intv / 2; + cur_ping_seq++; + baggage = init_sample (&data, cur_ping_seq); + ddsrt_mutex_unlock (&pongwr_lock); + if ((rc = dds_write_ts (wr_ping, &data, dds_time () | 1)) < 0 && dds_err_nr (rc) != DDS_RETCODE_TIMEOUT) + error2 ("send_new_ping: dds_write (wr_ping, &data): %d\n", (int) rc); + dds_write_flush (wr_ping); + if (baggage) + free (baggage); + } +} + +static uint32_t subthread_waitset (void *varg) +{ + struct subthread_arg * const arg = varg; + dds_entity_t ws; + int32_t rc; + ws = dds_create_waitset (dp); + if ((rc = dds_waitset_attach (ws, termcond, 0)) < 0) + error2 ("dds_waitset_attach (termcond, 0): %d\n", (int) rc); + if ((rc = dds_set_status_mask (rd_data, DDS_DATA_AVAILABLE_STATUS)) < 0) + error2 ("dds_set_status_mask (rd_data, DDS_DATA_AVAILABLE_STATUS): %d\n", (int) rc); + if ((rc = dds_waitset_attach (ws, rd_data, 1)) < 0) + error2 ("dds_waitset_attach (ws, rd_data, 1): %d\n", (int) rc); + while (!termflag) + { + if (!process_data (rd_data, arg)) + { + /* when we use DATA_AVAILABLE, we must read until nothing remains, or we would deadlock + if more than max_samples were available and nothing further is received */ + int32_t nxs; + if ((nxs = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY)) < 0) + error2 ("dds_waitset_wait: %d\n", (int) nxs); + } + } + return 0; +} + +static uint32_t subpingthread_waitset (void *varg) +{ + struct subthread_arg * const arg = varg; + dds_entity_t ws; + int32_t rc; + ws = dds_create_waitset (dp); + if ((rc = dds_waitset_attach (ws, termcond, 0)) < 0) + error2 ("dds_waitset_attach (termcond, 0): %d\n", (int) rc); + if ((rc = dds_set_status_mask (rd_ping, DDS_DATA_AVAILABLE_STATUS)) < 0) + error2 ("dds_set_status_mask (rd_ping, DDS_DATA_AVAILABLE_STATUS): %d\n", (int) rc); + if ((rc = dds_waitset_attach (ws, rd_ping, 1)) < 0) + error2 ("dds_waitset_attach (ws, rd_ping, 1): %d\n", (int) rc); + while (!termflag) + { + int32_t nxs; + if ((nxs = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY)) < 0) + error2 ("dds_waitset_wait: %d\n", (int) nxs); + process_ping (rd_ping, arg); + } + return 0; +} + +static uint32_t subpongthread_waitset (void *varg) +{ + struct subthread_arg * const arg = varg; + dds_entity_t ws; + int32_t rc; + ws = dds_create_waitset (dp); + if ((rc = dds_waitset_attach (ws, termcond, 0)) < 0) + error2 ("dds_waitset_attach (termcond, 0): %d\n", (int) rc); + if ((rc = dds_set_status_mask (rd_pong, DDS_DATA_AVAILABLE_STATUS)) < 0) + error2 ("dds_set_status_mask (rd_pong, DDS_DATA_AVAILABLE_STATUS): %d\n", (int) rc); + if ((rc = dds_waitset_attach (ws, rd_pong, 1)) < 0) + error2 ("dds_waitset_attach (ws, rd_pong, 1): %d\n", (int) rc); + while (!termflag) + { + int32_t nxs; + if ((nxs = dds_waitset_wait (ws, NULL, 0, DDS_INFINITY)) < 0) + error2 ("dds_waitset_wait: %d\n", (int) nxs); + process_pong (rd_pong, arg); + } + return 0; +} + +static uint32_t subthread_polling (void *varg) +{ + struct subthread_arg * const arg = varg; + while (!termflag) + { + if (!process_data (rd_data, arg)) + dds_sleepfor (DDS_MSECS (1)); + } + return 0; +} + +static void data_available_listener (dds_entity_t rd, void *arg) +{ + process_data (rd, arg); +} + +static void ping_available_listener (dds_entity_t rd, void *arg) +{ + process_ping (rd, arg); +} + +static void pong_available_listener (dds_entity_t rd, void *arg) +{ + process_pong (rd, arg); +} + +static dds_entity_t create_pong_writer (dds_instance_handle_t pphandle, const struct guidstr *guidstr) +{ + dds_qos_t *qos; + dds_listener_t *listener; + dds_entity_t pongpub; + dds_entity_t wr_pong; + + //printf ("[%"PRIdPID"] create_pong_writer: creating writer in partition %s pubhandle %"PRIx64"\n", ddsrt_getpid (), guidstr->str, pphandle); + //fflush (stdout); + + qos = dds_create_qos (); + dds_qset_partition1 (qos, guidstr->str); + if ((pongpub = dds_create_publisher (dp, qos, NULL)) < 0) + error2 ("dds_create_publisher failed: %d\n", (int) pongpub); + dds_delete_qos (qos); + + listener = dds_create_listener ((void *) (uintptr_t) MM_RD_PONG); + dds_lset_publication_matched (listener, publication_matched_listener); + qos = dds_create_qos (); + dds_qset_history (qos, DDS_HISTORY_KEEP_LAST, 1); + dds_qset_ignorelocal (qos, ignorelocal); + if ((wr_pong = dds_create_writer (pongpub, tp_pong, qos, listener)) < 0) + error2 ("dds_create_writer(%s) failed: %d\n", tpname_pong, (int) wr_pong); + dds_delete_qos (qos); + dds_delete_listener (listener); + + ddsrt_mutex_lock (&pongwr_lock); + pongwr = realloc (pongwr, (npongwr + 1) * sizeof (*pongwr)); + pongwr[npongwr].pubhandle = 0; + pongwr[npongwr].pphandle = pphandle; + pongwr[npongwr].wr_pong = wr_pong; + npongwr++; + ddsrt_mutex_unlock (&pongwr_lock); + return wr_pong; +} + +static void delete_pong_writer (dds_instance_handle_t pphandle) +{ + uint32_t i = 0; + dds_entity_t wr_pong = 0; + ddsrt_mutex_lock (&pongwr_lock); + while (i < npongwr) + { + if (pongwr[i].pphandle != pphandle) + i++; + else + { + assert (wr_pong == 0 || wr_pong == pongwr[i].wr_pong); + memmove (&pongwr[i], &pongwr[i+1], (npongwr - i) * sizeof (pongwr[0])); + npongwr--; + } + } + ddsrt_mutex_unlock (&pongwr_lock); + if (wr_pong) + dds_delete (wr_pong); +} + +static void participant_data_listener (dds_entity_t rd, void *arg) +{ + dds_sample_info_t info; + void *msg = NULL; + uint32_t n_pong_expected_delta = 0; + int32_t n; + (void) arg; + while ((n = dds_take (rd, &msg, &info, 1, 1)) > 0) + { + struct ppant *pp; + assert (info.instance_state != DDS_ALIVE_INSTANCE_STATE || info.valid_data); + if (info.instance_state != DDS_ALIVE_INSTANCE_STATE) + { + ddsrt_avl_dpath_t dpath; + ddsrt_mutex_lock (&disc_lock); + if ((pp = ddsrt_avl_lookup_dpath (&ppants_td, &ppants, &info.instance_handle, &dpath)) != NULL) + { + printf ("[%"PRIdPID"] participant %s:%"PRIu32": gone\n", ddsrt_getpid (), pp->hostname, pp->pid); + fflush (stdout); + + if (pp->handle != dp_handle || ignorelocal == DDS_IGNORELOCAL_NONE) + { + delete_pong_writer (pp->handle); + n_pong_expected_delta--; + } + + ddsrt_avl_delete_dpath (&ppants_td, &ppants, pp, &dpath); + if (pp->tdeadline != DDS_NEVER) + ddsrt_fibheap_delete (&ppants_to_match_fhd, &ppants_to_match, pp); + free (pp); + } + ddsrt_mutex_unlock (&disc_lock); + } + else + { + const dds_builtintopic_participant_t *sample = msg; + void *vudata; + size_t usz; + ddsrt_avl_ipath_t ipath; + /* only add unknown participants with the magic user_data value: DDSPerf:X:HOSTNAME, where X is decimal */ + if (dds_qget_userdata (sample->qos, &vudata, &usz) && usz > 0) + { + const char *udata = vudata; + int has_reader, pos; + long pid; + if (sscanf (udata, UDATA_MAGIC "%d:%ld%n", &has_reader, &pid, &pos) == 2 && udata[pos] == ':' && strlen (udata + pos) == usz - (unsigned) pos) + { + size_t sz = usz - (unsigned) pos; + char *hostname = malloc (sz); + memcpy (hostname, udata + pos + 1, sz); + ddsrt_mutex_lock (&disc_lock); + if ((pp = ddsrt_avl_lookup_ipath (&ppants_td, &ppants, &info.instance_handle, &ipath)) != NULL) + free (hostname); + else + { + printf ("[%"PRIdPID"] participant %s:%"PRIu32": new%s\n", ddsrt_getpid (), hostname, (uint32_t) pid, (info.instance_handle == dp_handle) ? " (self)" : ""); + pp = malloc (sizeof (*pp)); + pp->handle = info.instance_handle; + pp->guid = sample->key; + pp->hostname = hostname; + pp->pid = (uint32_t) pid; + pp->tdisc = dds_time (); + pp->tdeadline = pp->tdisc + DDS_SECS (5); + if (pp->handle != dp_handle || ignorelocal == DDS_IGNORELOCAL_NONE) + pp->unmatched = MM_ALL & ~(has_reader ? 0 : MM_RD_DATA) & ~(rd_data ? 0 : MM_WR_DATA); + else + pp->unmatched = 0; + ddsrt_fibheap_insert (&ppants_to_match_fhd, &ppants_to_match, pp); + ddsrt_avl_insert_ipath (&ppants_td, &ppants, pp, &ipath); + + if (pp->handle != dp_handle || ignorelocal == DDS_IGNORELOCAL_NONE) + { + struct guidstr guidstr; + make_guidstr (&guidstr, &sample->key); + create_pong_writer (pp->handle, &guidstr); + n_pong_expected_delta++; + } + } + ddsrt_mutex_unlock (&disc_lock); + } + dds_free (vudata); + } + } + dds_return_loan (rd, &msg, n); + } + if (n < 0) + error2 ("dds_take(rd_participants): error %d\n", (int) n); + + if (n_pong_expected_delta) + { + ddsrt_mutex_lock (&pongstat_lock); + n_pong_expected += n_pong_expected_delta; + /* potential initial packet loss & lazy writer creation conspire against receiving + the expected number of responses, so allow for a few attempts before starting to + warn about timeouts */ + twarn_ping_timeout = dds_time () + DDS_MSECS (3333); + //printf ("[%"PRIdPID"] n_pong_expected = %u\n", ddsrt_getpid (), n_pong_expected); + ddsrt_mutex_unlock (&pongstat_lock); + } +} + +static void endpoint_matched_listener (uint32_t match_mask, dds_entity_t rd_epinfo, dds_instance_handle_t remote_endpoint) +{ + dds_sample_info_t info; + void *msg = NULL; + int32_t n; + + /* update participant data so this remote endpoint's participant will be known */ + participant_data_listener (rd_participants, NULL); + + /* FIXME: implement the get_matched_... interfaces so there's no need for keeping a reader + (and having to GC it, which I'm skipping here ...) */ + if ((n = dds_read_instance (rd_epinfo, &msg, &info, 1, 1, remote_endpoint)) < 0) + error2 ("dds_read_instance(rd_epinfo, %"PRIx64") failed: %d\n", remote_endpoint, (int) n); + else if (n == 0) + printf ("[%"PRIdPID"] endpoint %"PRIx64" not found\n", ddsrt_getpid (), remote_endpoint); + else + { + if (info.valid_data) + { + const dds_builtintopic_endpoint_t *sample = msg; + struct ppant *pp; + ddsrt_mutex_lock (&disc_lock); + if ((pp = ddsrt_avl_lookup (&ppants_td, &ppants, &sample->participant_instance_handle)) == NULL) + printf ("[%"PRIdPID"] participant %"PRIx64" no longer exists\n", ddsrt_getpid (), sample->participant_instance_handle); + else + { + pp->unmatched &= ~match_mask; + if (pp->unmatched == 0) + matchcount++; + } + ddsrt_mutex_unlock (&disc_lock); + } + dds_return_loan (rd_epinfo, &msg, n); + } + fflush (stdout); +} + +static const char *match_mask1_to_string (uint32_t mask) +{ + assert ((mask & ~MM_ALL) == 0); + switch (mask) + { + case MM_WR_DATA: return "data writer"; + case MM_RD_DATA: return "data reader"; + case MM_WR_PING: return "ping writer"; + case MM_RD_PING: return "ping reader"; + case MM_WR_PONG: return "pong writer"; + case MM_RD_PONG: return "pong reader"; + } + return "?"; +} + +static char *match_mask_to_string (char *buf, size_t size, uint32_t mask) +{ + size_t pos = 0; + while (pos < size && mask != 0) + { + uint32_t mask1 = mask & (~mask + 1u); + mask &= ~mask1; + int n = snprintf (buf + pos, size - (unsigned) pos, "%s%s", (pos > 0) ? ", " : "", match_mask1_to_string (mask1)); + if (n >= 0) pos += (size_t) n; + } + return buf; +} + +static void subscription_matched_listener (dds_entity_t rd, const dds_subscription_matched_status_t status, void *arg) +{ + /* this only works because the listener is called for every match; but I don't think that is something the + spec guarantees, and I don't think Cyclone should guarantee that either -- and if it isn't guaranteed + _really_ needs the get_matched_... interfaces to not have to implement the matching logic ... */ + (void) rd; + if (status.current_count_change > 0) + { + uint32_t mask = (uint32_t) (uintptr_t) arg; + //printf ("[%"PRIdPID"] subscription match: %s\n", ddsrt_getpid (), match_mask1_to_string (mask)); + endpoint_matched_listener (mask, rd_publications, status.last_publication_handle); + } +} + +static void publication_matched_listener (dds_entity_t wr, const dds_publication_matched_status_t status, void *arg) +{ + /* this only works because the listener is called for every match; but I don't think that is something the + spec guarantees, and I don't think Cyclone should guarantee that either -- and if it isn't guaranteed + _really_ needs the get_matched_... interfaces to not have to implement the matching logic ... */ + (void) wr; + if (status.current_count_change > 0) + { + uint32_t mask = (uint32_t) (uintptr_t) arg; + //printf ("[%"PRIdPID"] publication match: %s\n", ddsrt_getpid (), match_mask1_to_string (mask)); + endpoint_matched_listener (mask, rd_subscriptions, status.last_subscription_handle); + } +} + +static void set_data_available_listener (dds_entity_t rd, const char *rd_name, dds_on_data_available_fn fn, void *arg) +{ + /* This convoluted code is so that we leave all listeners unchanged, except the + data_available one. There is no real need for these complications, but it is + a nice exercise. */ + dds_listener_t *listener = dds_create_listener (arg); + dds_return_t rc; + dds_lset_data_available (listener, fn); + dds_listener_t *tmplistener = dds_create_listener (NULL); + if ((rc = dds_get_listener (rd, tmplistener)) < 0) + error2 ("dds_get_listener(%s) failed: %d\n", rd_name, (int) rc); + dds_merge_listener (listener, tmplistener); + dds_delete_listener (tmplistener); + + if ((rc = dds_set_listener (rd, listener)) < 0) + error2 ("dds_set_listener(%s) failed: %d\n", rd_name, (int) rc); + dds_delete_listener (listener); +} + +static void print_stats (dds_time_t tstart, dds_time_t tnow, dds_time_t tprev) +{ + char prefix[128]; + const double ts = (double) (tnow - tstart) / 1e9; + snprintf (prefix, sizeof (prefix), "[%"PRIdPID"] %.3f ", ddsrt_getpid (), ts); + + if (rate > 0) + { + ddsrt_mutex_lock (&pubstat_lock); + hist_print (prefix, pubstat_hist, tnow - tprev, 1); + ddsrt_mutex_unlock (&pubstat_lock); + } + + if (submode != SM_NONE) + { + struct eseq_admin * const ea = &eseq_admin; + uint64_t tot_nrecv = 0, nrecv = 0, nrecv_bytes = 0, nlost = 0; + ddsrt_mutex_lock (&ea->lock); + for (uint32_t i = 0; i < ea->nph; i++) + { + struct eseq_stat * const x = &ea->stats[i]; + tot_nrecv += x->nrecv; + nrecv += x->nrecv - x->nrecv_ref; + nlost += x->nlost - x->nlost_ref; + nrecv_bytes += x->nrecv_bytes - x->nrecv_bytes_ref; + x->nrecv_ref = x->nrecv; + x->nlost_ref = x->nlost; + x->nrecv_bytes_ref = x->nrecv_bytes; + } + ddsrt_mutex_unlock (&ea->lock); + + if (nrecv > 0) + { + printf ("%s ntot %"PRIu64" delta: %"PRIu64" lost %"PRIu64" rate %.2f Mb/s\n", + prefix, tot_nrecv, nrecv, nlost, (double) nrecv_bytes * 8 / 1e6 / (1e9 * (double) (tnow - tprev))); + } + } + + ddsrt_mutex_lock (&pongstat_lock); + for (uint32_t i = 0; i < npongstat; i++) + { + struct subthread_arg_pongstat * const x = &pongstat[i]; + if (x->cnt > 0) + { + struct ppant *pp; + ddsrt_mutex_lock (&disc_lock); + if ((pp = ddsrt_avl_lookup (&ppants_td, &ppants, &x->pphandle)) == NULL) + printf ("%s %"PRIx64" min %.3fus mean %.3fus max %.3fus cnt %"PRIu32"\n", + prefix, x->pubhandle, (double) x->min / 1e3, + (double) x->sum / (double) x->cnt / 1e3, (double) x->max / 1e3, x->cnt); + else + printf ("%s %s:%d min %.3fus mean %.3fus max %.3fus cnt %"PRIu32"\n", + prefix, pp->hostname, pp->pid, (double) x->min / 1e3, + (double) x->sum / (double) x->cnt / 1e3, (double) x->max / 1e3, x->cnt); + ddsrt_mutex_unlock (&disc_lock); + x->min = UINT64_MAX; + x->max = x->sum = x->cnt = 0; + } + } + ddsrt_mutex_unlock (&pongstat_lock); + fflush (stdout); +} + +static void subthread_arg_init (struct subthread_arg *arg, dds_entity_t rd, uint32_t max_samples) +{ + arg->rd = rd; + arg->max_samples = max_samples; + arg->mseq = malloc (arg->max_samples * sizeof (arg->mseq[0])); + arg->iseq = malloc (arg->max_samples * sizeof (arg->iseq[0])); + for (uint32_t i = 0; i < arg->max_samples; i++) + arg->mseq[i] = NULL; +} + +static void subthread_arg_fini (struct subthread_arg *arg) +{ + dds_return_loan(arg->rd, arg->mseq, (int32_t) arg->max_samples); + free (arg->mseq); + free (arg->iseq); +} + +static void signal_handler (int sig) +{ + (void) sig; + termflag = 1; + dds_set_guardcondition (termcond, true); +} + +#ifndef _WIN32 +static uint32_t sigthread (void *varg) +{ + sigset_t *set = varg; + int sig; + if (sigwait (set, &sig) == 0) + signal_handler (sig); + else + error2 ("sigwait failed: %d\n", errno); + return 0; +} +#endif + +/******************** + COMMAND LINE PARSING + ********************/ + +static void usage (void) +{ + printf ("\ +%s help\n\ +%s [OPTIONS] MODE...\n\ +\n\ +OPTIONS:\n\ + -T KS|K32|K256|OU topic:\n\ + KS seq num, key value, sequence-of-octets\n\ + K32 seq num, key value, array of 24 octets\n\ + K256 seq num, key value, array of 248 octets\n\ + OU seq num\n\ + -L allow matching with local endpoints\n\ + -u best-effort instead of reliable\n\ + -k all|N keep-all or keep-last-N for data (ping/pong is\n\ + always keep-last-1)\n\ + -n N number of key values to use for data (only for\n\ + topics with a key value)\n\ + -D DUR run for at most DUR seconds\n\ + -N COUNT require at least COUNT matching participants\n\ + -M DUR require those participants to match within DUR seconds\n\ +\n\ +MODE... is zero or more of:\n\ + ping [R[Hz]] [waitset|listener]\n\ + Send a ping upon receiving all expected pongs, or send a ping at\n\ + rate R (optionally suffixed with Hz). The triggering mode is either\n\ + a listener (default, unless -L has been specified) or a waitset.\n\ + pong [waitset|listener]\n\ + A \"dummy\" mode that serves two purposes: configuring the triggering.\n\ + mode (but it is shared with ping's mode), and suppressing the 1Hz ping\n\ + if no other options are selected. It always responds to pings.\n\ + sub [waitset|listener|polling]\n\ + Subscribe to data, with calls to take occurring either in a listener\n\ + (default), when a waitset is triggered, or by polling at 1kHz.\n\ + pub [R[Hz]] [burst N] [[ping] X%%]\n\ + Publish bursts of data at rate R, optionally suffixed with Hz. If\n\ + no rate is given or R is \"inf\", data is published as fast as\n\ + possible. Each burst is a single sample by default, but can be set\n\ + to larger value using \"burst N\".\n\ + If desired, a fraction of the samples can be treated as if it were a\n\ + ping, for this, specify a percentage either as \"ping X%%\" (the\n\ + \"ping\" keyword is optional, the %% sign is not).\n\ +\n\ +If no MODE specified, it defaults to a 1Hz ping + responding to any pings.\n\ +", argv0, argv0); + fflush (stdout); + exit (3); +} + +struct string_int_map_elem { + const char *name; + int value; +}; + +static const struct string_int_map_elem modestrings[] = { + { "ping", 1 }, + { "pong", 2 }, + { "sub", 3 }, + { "pub", 4 }, + { NULL, 0 } +}; + +static const struct string_int_map_elem pingpongmodes[] = { + { "waitset", SM_WAITSET }, + { "listener", SM_LISTENER }, + { NULL, 0 } +}; + +static int exact_string_int_map_lookup (const struct string_int_map_elem *elems, const char *label, const char *str, bool notfound_error) +{ + for (size_t i = 0; elems[i].name; i++) + if (strcmp (elems[i].name, str) == 0) + return elems[i].value; + if (notfound_error) + error3 ("%s: undefined %s", str, label); + return -1; +} + +static int string_int_map_lookup (const struct string_int_map_elem *elems, const char *label, const char *str, bool notfound_error) +{ + size_t match = SIZE_MAX; + size_t len = strlen (str); + bool ambiguous = false; + for (size_t i = 0; elems[i].name; i++) + { + if (strcmp (elems[i].name, str) == 0) + return elems[match].value; + else if (len >= 3 && strlen (elems[i].name) >= 3 && strncmp (elems[i].name, str, len) == 0) + { + if (match == SIZE_MAX) + match = i; + else + ambiguous = true; + } + } + if (ambiguous) + error3 ("%s: ambiguous %sspecification", str, label); + if (match == SIZE_MAX && notfound_error) + error3 ("%s: undefined %s", str, label); + return (match == SIZE_MAX) ? -1 : elems[match].value; +} + +static void set_mode_ping (int *xoptind, int xargc, char * const xargv[]) +{ + ping_intv = 0; + pingpongmode = SM_LISTENER; + while (*xoptind < xargc && exact_string_int_map_lookup (modestrings, "mode string", xargv[*xoptind], false) == -1) + { + int pos; + double r; + if (strcmp (xargv[*xoptind], "inf") == 0) + { + ping_intv = 0; + } + else if (sscanf (xargv[*xoptind], "%lf%n", &r, &pos) == 1 && (xargv[*xoptind][pos] == 0 || strcmp (xargv[*xoptind] + pos, "Hz") == 0)) + { + if (r == 0) ping_intv = DDS_INFINITY; + else if (r > 0) ping_intv = (dds_duration_t) (1e9 / rate + 0.5); + else error3 ("%s: invalid ping rate\n", xargv[*xoptind]); + } + else + { + pingpongmode = (enum submode) string_int_map_lookup (pingpongmodes, "ping mode", xargv[*xoptind], true); + } + (*xoptind)++; + } +} + +static void set_mode_pong (int *xoptind, int xargc, char * const xargv[]) +{ + pingpongmode = SM_LISTENER; + while (*xoptind < xargc && exact_string_int_map_lookup (modestrings, "mode string", xargv[*xoptind], false) == -1) + { + pingpongmode = (enum submode) string_int_map_lookup (pingpongmodes, "pong mode", xargv[*xoptind], true); + (*xoptind)++; + } +} + +static void set_mode_sub (int *xoptind, int xargc, char * const xargv[]) +{ + static const struct string_int_map_elem submodes[] = { + { "waitset", SM_WAITSET }, + { "polling", SM_POLLING }, + { "listener", SM_LISTENER }, + { NULL, 0 } + }; + submode = SM_LISTENER; + while (*xoptind < xargc && exact_string_int_map_lookup (modestrings, "mode string", xargv[*xoptind], false) == -1) + { + submode = (enum submode) string_int_map_lookup (submodes, "subscription mode", xargv[*xoptind], true); + (*xoptind)++; + } +} + +static void set_mode_pub (int *xoptind, int xargc, char * const xargv[]) +{ + rate = HUGE_VAL; + burstsize = 1; + ping_frac = 0; + while (*xoptind < xargc && exact_string_int_map_lookup (modestrings, "mode string", xargv[*xoptind], false) == -1) + { + int pos = 0; + double r; + if (strcmp (xargv[*xoptind], "inf") == 0 || strcmp (xargv[*xoptind], "infHz") == 0) + { + rate = HUGE_VAL; + } + else if (sscanf (xargv[*xoptind], "%lf%n", &r, &pos) == 1 && (xargv[*xoptind][pos] == 0 || strcmp (xargv[*xoptind] + pos, "Hz") == 0)) + { + if (r < 0) error3 ("%s: invalid publish rate\n", xargv[*xoptind]); + rate = r; + } + else if (strcmp (xargv[*xoptind], "burst") == 0) + { + unsigned b; + if (++(*xoptind) == xargc) + error3 ("argument missing in burst size specification\n"); + if (sscanf (xargv[*xoptind], "%u%n", &b, &pos) == 1 && xargv[*xoptind][pos] == 0) + burstsize = b; + else + error3 ("%s: invalid burst size specification\n", xargv[*xoptind]); + } + else if (sscanf (xargv[*xoptind], "%lf%n", &r, &pos) == 1 && strcmp (xargv[*xoptind] + pos, "%") == 0) + { + if (r < 0 || r > 100) error3 ("%s: ping fraction out of range\n", xargv[*xoptind]); + ping_frac = (uint32_t) (UINT32_MAX * (r / 100.0) + 0.5); + } + else if (strcmp (xargv[*xoptind], "ping") == 0 && *xoptind + 1 < xargc && sscanf (xargv[*xoptind + 1], "%lf%%%n", &rate, &pos) == 1 && xargv[*xoptind + 1][pos] == 0) + { + ++(*xoptind); + if (r < 0 || r > 100) error3 ("%s: ping fraction out of range\n", xargv[*xoptind]); + ping_frac = (uint32_t) (UINT32_MAX * (r / 100.0) + 0.5); + } + else + { + error3 ("%s: unrecognised publish specification\n", xargv[*xoptind]); + } + (*xoptind)++; + } +} + +static void set_mode (int xoptind, int xargc, char * const xargv[]) +{ + int code; + rate = 0.0; + submode = SM_NONE; + pingpongmode = SM_LISTENER; + ping_intv = (xoptind == xargc) ? DDS_SECS (1) : DDS_INFINITY; + ping_frac = 0; + while (xoptind < xargc && (code = exact_string_int_map_lookup (modestrings, "mode string", xargv[xoptind], true)) != -1) + { + xoptind++; + switch (code) + { + case 1: set_mode_ping (&xoptind, xargc, xargv); break; + case 2: set_mode_pong (&xoptind, xargc, xargv); break; + case 3: set_mode_sub (&xoptind, xargc, xargv); break; + case 4: set_mode_pub (&xoptind, xargc, xargv); break; + } + } + if (xoptind != xargc) + { + error3 ("%s: unrecognized argument\n", xargv[xoptind]); + } +} + +int main (int argc, char *argv[]) +{ + dds_entity_t ws; + dds_return_t rc; + dds_qos_t *qos; + dds_listener_t *listener; + int opt; + ddsrt_threadattr_t attr; + ddsrt_thread_t pubtid, subtid, subpingtid, subpongtid; +#ifndef _WIN32 + sigset_t sigset, osigset; + ddsrt_thread_t sigtid; +#endif + ddsrt_threadattr_init (&attr); + + argv0 = argv[0]; + + if (argc == 2 && strcmp (argv[1], "help") == 0) + usage (); + while ((opt = getopt (argc, argv, "D:n:z:k:uLT:M:N:h")) != EOF) + { + switch (opt) + { + case 'D': dur = atof (optarg); if (dur <= 0) dur = HUGE_VAL; break; + case 'n': nkeyvals = (unsigned) atoi (optarg); break; + case 'u': reliable = false; break; + case 'k': histdepth = atoi (optarg); if (histdepth < 0) histdepth = 0; break; + case 'L': ignorelocal = DDS_IGNORELOCAL_NONE; break; + case 'T': + if (strcmp (optarg, "KS") == 0) topicsel = KS; + else if (strcmp (optarg, "K32") == 0) topicsel = K32; + else if (strcmp (optarg, "K256") == 0) topicsel = K256; + else if (strcmp (optarg, "OU") == 0) topicsel = OU; + else error3 ("%s: unknown topic\n", optarg); + break; + case 'M': maxwait = atof (optarg); if (maxwait <= 0) maxwait = HUGE_VAL; break; + case 'N': minmatch = (unsigned) atoi (optarg); break; + case 'z': baggagesize = (unsigned) atoi (optarg); break; + case 'h': usage (); break; + default: error3 ("-%c: unknown option\n", opt); break; + } + } + set_mode (optind, argc, argv); + + if (nkeyvals == 0) + nkeyvals = 1; + if (topicsel == OU && nkeyvals != 1) + error3 ("-n%u invalid: topic OU has no key\n", nkeyvals); + if (topicsel != KS && baggagesize != 0) + error3 ("-z%u invalid: only topic KS has a sequence\n", baggagesize); + + ddsrt_avl_init (&ppants_td, &ppants); + ddsrt_fibheap_init (&ppants_to_match_fhd, &ppants_to_match); + + ddsrt_mutex_init (&disc_lock); + ddsrt_mutex_init (&pongstat_lock); + ddsrt_mutex_init (&pongwr_lock); + ddsrt_mutex_init (&pubstat_lock); + + pubstat_hist = hist_new (30, 1000, 0); + + qos = dds_create_qos (); + /* set user data: magic cookie, whether we have a reader for the Data topic + (all other endpoints always exist), and our hostname */ + { + unsigned pos; + char udata[256]; + pos = (unsigned) snprintf (udata, sizeof (udata), UDATA_MAGIC"%d:%"PRIdPID":", submode != SM_NONE, ddsrt_getpid ()); + assert (pos < sizeof (udata)); + if (ddsrt_gethostname (udata + pos, sizeof (udata) - pos) != DDS_RETCODE_OK) + strcpy (udata + UDATA_MAGIC_SIZE, "?"); + dds_qset_userdata (qos, udata, strlen (udata)); + } + if ((dp = dds_create_participant (did, qos, NULL)) < 0) + error2 ("dds_create_participant(domain %d) failed: %d\n", (int) did, (int) dp); + dds_delete_qos (qos); + dds_write_set_batch (true); + if ((rc = dds_get_instance_handle (dp, &dp_handle)) < 0) + error2 ("dds_get_instance_handle(participant) failed: %d\n", (int) rc); + + qos = dds_create_qos (); + dds_qset_partition1 (qos, "DDSPerf"); + if ((sub = dds_create_subscriber (dp, NULL, NULL)) < 0) + error2 ("dds_create_subscriber failed: %d\n", (int) dp); + if ((pub = dds_create_publisher (dp, NULL, NULL)) < 0) + error2 ("dds_create_publisher failed: %d\n", (int) dp); + dds_delete_qos (qos); + + { + const char *tp_suf = ""; + const dds_topic_descriptor_t *tp_desc = NULL; + switch (topicsel) + { + case KS: tp_suf = "KS"; tp_desc = &KeyedSeq_desc; break; + case K32: tp_suf = "K32"; tp_desc = &Keyed32_desc; break; + case K256: tp_suf = "K256"; tp_desc = &Keyed256_desc; break; + case OU: tp_suf = "OU"; tp_desc = &OneULong_desc; break; + } + snprintf (tpname_data, sizeof (tpname_data), "DDSPerf%cData%s", reliable ? 'R' : 'U', tp_suf); + snprintf (tpname_ping, sizeof (tpname_ping), "DDSPerf%cPing%s", reliable ? 'R' : 'U', tp_suf); + snprintf (tpname_pong, sizeof (tpname_pong), "DDSPerf%cPong%s", reliable ? 'R' : 'U', tp_suf); + qos = dds_create_qos (); + dds_qset_reliability (qos, reliable ? DDS_RELIABILITY_RELIABLE : DDS_RELIABILITY_BEST_EFFORT, DDS_SECS (1)); + if ((tp_data = dds_create_topic (dp, tp_desc, tpname_data, qos, NULL)) < 0) + error2 ("dds_create_topic(%s) failed: %d\n", tpname_data, (int) tp_data); + if ((tp_ping = dds_create_topic (dp, tp_desc, tpname_ping, qos, NULL)) < 0) + error2 ("dds_create_topic(%s) failed: %d\n", tpname_ping, (int) tp_ping); + if ((tp_pong = dds_create_topic (dp, tp_desc, tpname_pong, qos, NULL)) < 0) + error2 ("dds_create_topic(%s) failed: %d\n", tpname_pong, (int) tp_pong); + dds_delete_qos (qos); + } + + /* participants reader must exist before the "publication matched" or "subscription matched" + listener is invoked, or it won't be able to get the details (FIXME: even the DDS spec + has convenience functions for that ...) */ + listener = dds_create_listener (NULL); + dds_lset_data_available (listener, participant_data_listener); + if ((rd_participants = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSPARTICIPANT, NULL, listener)) < 0) + error2 ("dds_create_reader(participants) failed: %d\n", (int) rd_participants); + dds_delete_listener (listener); + if ((rd_subscriptions = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, NULL)) < 0) + error2 ("dds_create_reader(subscriptions) failed: %d\n", (int) rd_subscriptions); + if ((rd_publications = dds_create_reader (dp, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, NULL, NULL)) < 0) + error2 ("dds_create_reader(publications) failed: %d\n", (int) rd_publications); + + /* ping reader/writer uses keep-last-1 history; not checking matching on these (yet) */ + qos = dds_create_qos (); + dds_qset_history (qos, DDS_HISTORY_KEEP_LAST, 1); + dds_qset_ignorelocal (qos, ignorelocal); + listener = dds_create_listener ((void *) (uintptr_t) MM_WR_PING); + dds_lset_subscription_matched (listener, subscription_matched_listener); + if ((rd_ping = dds_create_reader (sub, tp_ping, qos, listener)) < 0) + error2 ("dds_create_reader(%s) failed: %d\n", tpname_ping, (int) rd_ping); + dds_delete_listener (listener); + listener = dds_create_listener ((void *) (uintptr_t) MM_RD_PING); + dds_lset_publication_matched (listener, publication_matched_listener); + if ((wr_ping = dds_create_writer (pub, tp_ping, qos, listener)) < 0) + error2 ("dds_create_writer(%s) failed: %d\n", tpname_ping, (int) wr_ping); + dds_delete_listener (listener); + dds_delete_qos (qos); + + /* data reader/writer use a keep-all history with generous resource limits. */ + qos = dds_create_qos (); + if (histdepth == 0) + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 1); + else + dds_qset_history (qos, DDS_HISTORY_KEEP_LAST, histdepth); + dds_qset_resource_limits (qos, 10000, DDS_LENGTH_UNLIMITED, DDS_LENGTH_UNLIMITED); + dds_qset_ignorelocal (qos, ignorelocal); + listener = dds_create_listener ((void *) (uintptr_t) MM_WR_DATA); + dds_lset_subscription_matched (listener, subscription_matched_listener); + if (submode != SM_NONE && (rd_data = dds_create_reader (sub, tp_data, qos, listener)) < 0) + error2 ("dds_create_reader(%s) failed: %d\n", tpname_data, (int) rd_data); + dds_delete_listener (listener); + listener = dds_create_listener ((void *) (uintptr_t) MM_RD_DATA); + dds_lset_publication_matched (listener, publication_matched_listener); + if ((wr_data = dds_create_writer (pub, tp_data, qos, listener)) < 0) + error2 ("dds_create_writer(%s) failed: %d\n", tpname_data, (int) wr_data); + dds_delete_listener (listener); + + /* We only need a pong reader when sending data with a non-zero probability + of it being a "ping", or when sending "real" pings. I.e., if + rate > 0 && ping_frac > 0) || ping_intv != DDS_NEVER + but it doesn't really hurt to have the reader either, and always creating + it and futhermore eagerly creating the pong writers means we can do more + checking. */ + { + /* participant listener should have already been called for "dp", so we + can simply look up the details on ourself to get at the GUID of the + participant */ + struct guidstr guidstr; + struct ppant *pp; + dds_entity_t sub_pong; + ddsrt_mutex_lock (&disc_lock); + if ((pp = ddsrt_avl_lookup (&ppants_td, &ppants, &dp_handle)) == NULL) + { + printf ("participant %"PRIx64" (self) not found\n", dp_handle); + exit (2); + } + make_guidstr (&guidstr, &pp->guid); + ddsrt_mutex_unlock (&disc_lock); + dds_qos_t *subqos = dds_create_qos (); + dds_qset_partition1 (subqos, guidstr.str); + if ((sub_pong = dds_create_subscriber (dp, subqos, NULL)) < 0) + error2 ("dds_create_subscriber(pong) failed: %d\n", (int) sub_pong); + dds_delete_qos (subqos); + listener = dds_create_listener ((void *) (uintptr_t) MM_WR_PONG); + dds_lset_subscription_matched (listener, subscription_matched_listener); + if ((rd_pong = dds_create_reader (sub_pong, tp_pong, qos, listener)) < 0) + error2 ("dds_create_reader(%s) failed: %d\n", tpname_pong, (int) rd_pong); + dds_delete_listener (listener); + } + dds_delete_qos (qos); + + if ((termcond = dds_create_guardcondition (dp)) < 0) + error2 ("dds_create_guardcondition(termcond) failed: %d\n", (int) termcond); + if ((ws = dds_create_waitset (dp)) < 0) + error2 ("dds_create_waitset(main) failed: %d\n", (int) ws); + if ((rc = dds_waitset_attach (ws, termcond, 0)) < 0) + error2 ("dds_waitset_attach(main, termcond) failed: %d\n", (int) rc); + + /* I hate Unix signals in multi-threaded processes ... */ +#ifdef _WIN32 + signal (SIGINT, signal_handler); +#else + sigemptyset (&sigset); + sigaddset (&sigset, SIGINT); + sigaddset (&sigset, SIGTERM); + sigprocmask (SIG_BLOCK, &sigset, &osigset); + ddsrt_thread_create (&sigtid, "sigthread", &attr, sigthread, &sigset); +#endif + + /* Make publisher & subscriber thread arguments and start the threads we + need (so what if we allocate memory for reading data even if we don't + have a reader or will never really be receiving data) */ + struct subthread_arg subarg_data, subarg_ping, subarg_pong; + init_eseq_admin (&eseq_admin, nkeyvals); + subthread_arg_init (&subarg_data, rd_data, 100); + subthread_arg_init (&subarg_ping, rd_ping, 100); + subthread_arg_init (&subarg_pong, rd_pong, 100); + uint32_t (*subthread_func) (void *arg) = 0; + switch (submode) + { + case SM_NONE: break; + case SM_WAITSET: subthread_func = subthread_waitset; break; + case SM_POLLING: subthread_func = subthread_polling; break; + case SM_LISTENER: break; + } + memset (&pubtid, 0, sizeof (pubtid)); + memset (&subtid, 0, sizeof (subtid)); + memset (&subpingtid, 0, sizeof (subpingtid)); + memset (&subpongtid, 0, sizeof (subpongtid)); + if (rate > 0) + ddsrt_thread_create (&pubtid, "pub", &attr, pubthread, NULL); + if (subthread_func != 0) + ddsrt_thread_create (&subtid, "sub", &attr, subthread_func, &subarg_data); + else if (submode == SM_LISTENER) + set_data_available_listener (rd_data, "rd_data", data_available_listener, &subarg_data); + /* Need to handle incoming "pong"s only if we can be sending "ping"s (whether that + be pings from the "ping" mode (i.e. ping_intv != DDS_NEVER), or pings embedded + in the published data stream (i.e. rate > 0 && ping_frac > 0). The trouble with + the first category is that a publication/subscription pair in the same process + would result in a "thread awake nesting" overflow (and otherwise in a stack + overflow) because each sample triggers the next. So in that particular case we + had better create a waitset. */ + const bool pingpong_waitset = (ping_intv != DDS_NEVER && ignorelocal == DDS_IGNORELOCAL_NONE) || pingpongmode == SM_WAITSET; + if (pingpong_waitset) + { + ddsrt_thread_create (&subpingtid, "sub", &attr, subpingthread_waitset, &subarg_pong); + ddsrt_thread_create (&subpongtid, "sub", &attr, subpongthread_waitset, &subarg_pong); + } + else + { + set_data_available_listener (rd_ping, "rd_ping", ping_available_listener, &subarg_ping); + set_data_available_listener (rd_pong, "rd_pong", pong_available_listener, &subarg_pong); + } + + /* Run until time limit reached or a signal received. (The time calculations + ignore the possibility of overflow around the year 2260.) */ + dds_time_t tnow = dds_time (); + const dds_time_t tstart = tnow; + dds_time_t tmatch = (maxwait == HUGE_VAL) ? DDS_NEVER : tstart + (int64_t) (maxwait * 1e9 + 0.5); + const dds_time_t tstop = (dur == HUGE_VAL) ? DDS_NEVER : tstart + (int64_t) (dur * 1e9 + 0.5); + dds_time_t tnext = tstart + DDS_SECS (1); + dds_time_t tlast = tstart; + dds_time_t tnextping = (ping_intv == DDS_INFINITY) ? DDS_NEVER : (ping_intv == 0) ? tstart + DDS_SECS (1) : tstart + ping_intv; + while (!termflag && tnow < tstop) + { + dds_time_t twakeup = DDS_NEVER; + int32_t nxs; + + /* bail out if too few readers discovered within the deadline */ + if (tnow >= tmatch) + { + bool ok; + ddsrt_mutex_lock (&disc_lock); + ok = (matchcount >= minmatch); + ddsrt_mutex_unlock (&disc_lock); + if (ok) + tmatch = DDS_NEVER; + else + { + /* set minmatch to an impossible value to avoid a match occurring between now and + the determining of the exit status from causing a successful return */ + minmatch = UINT32_MAX; + break; + } + } + + /* sometimes multicast only works one way, thus it makes sense to verify + reader/writer matching takes place within a set amount of time after + discovering the participant. */ + { + struct ppant *pp; + ddsrt_mutex_lock (&disc_lock); + while ((pp = ddsrt_fibheap_min (&ppants_to_match_fhd, &ppants_to_match)) != NULL && pp->tdeadline < tnow) + { + (void) ddsrt_fibheap_extract_min (&ppants_to_match_fhd, &ppants_to_match); + if (pp->unmatched != 0) + { + printf ("[%"PRIdPID"] participant %s:%"PRIu32": failed to match in %.3fs\n", ddsrt_getpid (), pp->hostname, pp->pid, (double) (pp->tdeadline - pp->tdisc) / 1e9); + fflush (stdout); + matchtimeout++; + } + /* keep the participant in the admin so we will never look at it again */ + pp->tdeadline = DDS_NEVER; + } + if (pp && pp->tdeadline < tnext) + { + twakeup = pp->tdeadline; + } + ddsrt_mutex_unlock (&disc_lock); + } + + /* next wakeup should be when the next event occurs */ + if (tnext < twakeup) + twakeup = tnext; + if (tstop < twakeup) + twakeup = tstop; + if (tmatch < twakeup) + twakeup = tmatch; + if (tnextping < twakeup) + twakeup = tnextping; + + if ((nxs = dds_waitset_wait_until (ws, NULL, 0, twakeup)) < 0) + error2 ("dds_waitset_wait_until(main): error %d\n", (int) nxs); + + /* try to print exactly once per second, but do gracefully handle a very late wakeup */ + tnow = dds_time (); + if (tnext <= tnow) + { + print_stats (tstart, tnow, tlast); + tlast = tnow; + if (tnow > tnext + DDS_MSECS (500)) + tnext = tnow + DDS_SECS (1); + else + tnext += DDS_SECS (1); + } + + /* If a "real" ping doesn't result in the expected number of pongs within a reasonable + time, send a new ping to restart the process. This can happen as a result of starting + or stopping a process, as a result of packet loss if best-effort reliability is + selected, or as a result of overwhelming the ping/pong from the data publishing thread + (as the QoS is a simple keep-last-1) */ + if (tnextping <= tnow) + { + maybe_send_new_ping (tnow, &tnextping); + } + } + +#if _WIN32 + signal_handler (SIGINT); +#else + { + /* get the attention of the signal handler thread */ + void (*osigint) (int); + void (*osigterm) (int); + kill (getpid (), SIGTERM); + ddsrt_thread_join (sigtid, NULL); + osigint = signal (SIGINT, SIG_IGN); + osigterm = signal (SIGTERM, SIG_IGN); + sigprocmask (SIG_SETMASK, &osigset, NULL); + signal (SIGINT, osigint); + signal (SIGINT, osigterm); + } +#endif + + if (rate > 0) + ddsrt_thread_join (pubtid, NULL); + if (subthread_func != 0) + ddsrt_thread_join (subtid, NULL); + if (pingpong_waitset) + { + ddsrt_thread_join (subpingtid, NULL); + ddsrt_thread_join (subpongtid, NULL); + } + + /* stop the listeners before deleting the readers: otherwise they may + still try to access a reader that has already become inaccessible + (not quite good, but ...) */ + dds_set_listener (rd_ping, NULL); + dds_set_listener (rd_pong, NULL); + dds_set_listener (rd_data, NULL); + dds_set_listener (rd_participants, NULL); + dds_set_listener (rd_subscriptions, NULL); + dds_set_listener (rd_publications, NULL); + + /* Delete rd_data early to workaround a deadlock deleting a reader + or writer while the receive thread (or a delivery thread) got + stuck trying to write into a reader that hit its resource limits. + + The deadlock is that the deleting of a reader/writer requires + waiting for the DDSI-level entity to be deleted (a multi-stage + GC process), and a "stuck" receive thread prevents the GC from + making progress. + + The fix is to eliminate the waiting and retrying, and instead + flip the reader's state to out-of-sync and rely on retransmits + to let it make progress once room is available again. */ + dds_delete (rd_data); + + uint64_t nlost = 0; + for (uint32_t i = 0; i < eseq_admin.nph; i++) + nlost += eseq_admin.stats[i].nlost; + fini_eseq_admin (&eseq_admin); + subthread_arg_fini (&subarg_data); + subthread_arg_fini (&subarg_ping); + subthread_arg_fini (&subarg_pong); + dds_delete (dp); + ddsrt_mutex_destroy (&disc_lock); + ddsrt_mutex_destroy (&pongwr_lock); + ddsrt_mutex_destroy (&pongstat_lock); + ddsrt_mutex_destroy (&pubstat_lock); + hist_free (pubstat_hist); + + bool ok = true; + + { + ddsrt_avl_iter_t it; + struct ppant *pp; + for (pp = ddsrt_avl_iter_first (&ppants_td, &ppants, &it); pp; pp = ddsrt_avl_iter_next (&it)) + if (pp->unmatched != 0) + { + char buf[256]; + printf ("[%"PRIdPID"] error: %s:%"PRIu32" failed to match %s\n", ddsrt_getpid (), pp->hostname, pp->pid, match_mask_to_string (buf, sizeof (buf), pp->unmatched)); + ok = false; + } + } + if (matchcount < minmatch) + { + printf ("[%"PRIdPID"] error: too few matching participants (%"PRIu32" instead of %"PRIu32")\n", ddsrt_getpid (), matchcount, minmatch); + ok = false; + } + if (nlost > 0 && (reliable && histdepth == 0)) + { + printf ("[%"PRIdPID"] error: %"PRIu64" samples lost\n", ddsrt_getpid (), nlost); + ok = false; + } + return ok ? 0 : 1; +} diff --git a/src/tools/ddsperf/ddsperf_types.idl b/src/tools/ddsperf/ddsperf_types.idl new file mode 100644 index 0000000..806f30d --- /dev/null +++ b/src/tools/ddsperf/ddsperf_types.idl @@ -0,0 +1,29 @@ +struct OneULong +{ + unsigned long seq; +}; +#pragma keylist OneULong + +struct Keyed32 +{ + unsigned long seq; + unsigned long keyval; + octet baggage[24]; +}; +#pragma keylist Keyed32 keyval + +struct Keyed256 +{ + unsigned long seq; + unsigned long keyval; + octet baggage[248]; +}; +#pragma keylist Keyed256 keyval + +struct KeyedSeq +{ + unsigned long seq; + unsigned long keyval; + sequence baggage; +}; +#pragma keylist KeyedSeq keyval From 386d5d30294bdaee71e4a11ca5fa999473cd0cf5 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 23 Apr 2019 13:25:40 +0200 Subject: [PATCH 041/238] remove Lease element from test config The element has long been meaningless and got deprecated in commit c3dca32a2f8dc43be79745e65adcc1066d75dc36. Signed-off-by: Erik Boasson --- src/core/ddsc/tests/config_simple_udp.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/core/ddsc/tests/config_simple_udp.xml b/src/core/ddsc/tests/config_simple_udp.xml index 27329bd..f96c737 100644 --- a/src/core/ddsc/tests/config_simple_udp.xml +++ b/src/core/ddsc/tests/config_simple_udp.xml @@ -16,9 +16,6 @@ 3 - - - 127.0.0.1 From 5a8197fa2be16c28d121bccf20bf792fdd75b9f9 Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Fri, 5 Apr 2019 15:00:48 +0200 Subject: [PATCH 042/238] Rudimentary process management. Signed-off-by: Martin Bremmer --- src/ddsrt/CMakeLists.txt | 3 +- src/ddsrt/include/dds/ddsrt/process.h | 173 ++++++++- src/ddsrt/src/process.c | 27 -- src/ddsrt/src/process/posix/process.c | 303 ++++++++++++++++ src/ddsrt/src/process/windows/process.c | 447 ++++++++++++++++++++++++ src/ddsrt/tests/CMakeLists.txt | 24 ++ src/ddsrt/tests/process.c | 284 +++++++++++++++ src/ddsrt/tests/process_app.c | 108 ++++++ src/ddsrt/tests/process_test.h.in | 42 +++ 9 files changed, 1378 insertions(+), 33 deletions(-) delete mode 100644 src/ddsrt/src/process.c create mode 100644 src/ddsrt/src/process/posix/process.c create mode 100644 src/ddsrt/src/process/windows/process.c create mode 100644 src/ddsrt/tests/process.c create mode 100644 src/ddsrt/tests/process_app.c create mode 100644 src/ddsrt/tests/process_test.h.in diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index 404f425..5b49248 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -74,7 +74,6 @@ list(APPEND sources "${source_path}/io.c" "${source_path}/log.c" "${source_path}/retcode.c" - "${source_path}/process.c" "${source_path}/strtod.c" "${source_path}/strtol.c") @@ -104,7 +103,7 @@ list(APPEND sources # network stack. In order to mix-and-match various compilers, architectures, # operating systems, etc input from the build system is required. foreach(feature atomics cdtors environ heap ifaddrs random rusage - sockets string sync threads time md5) + sockets string sync threads time md5 process) if(EXISTS "${include_path}/dds/ddsrt/${feature}.h") list(APPEND headers "${include_path}/dds/ddsrt/${feature}.h") file(GLOB diff --git a/src/ddsrt/include/dds/ddsrt/process.h b/src/ddsrt/include/dds/ddsrt/process.h index b2be585..45e7099 100644 --- a/src/ddsrt/include/dds/ddsrt/process.h +++ b/src/ddsrt/include/dds/ddsrt/process.h @@ -13,11 +13,9 @@ #define DDSRT_PROCESS_H #include "dds/export.h" +#include "dds/ddsrt/time.h" #include "dds/ddsrt/types.h" - -#if defined (__cplusplus) -extern "C" { -#endif +#include "dds/ddsrt/retcode.h" #if defined(_WIN32) typedef DWORD ddsrt_pid_t; @@ -33,6 +31,11 @@ typedef pid_t ddsrt_pid_t; #endif #endif /* _WIN32 */ + +#if defined (__cplusplus) +extern "C" { +#endif + /** * @brief Return process ID (PID) of the calling process. * @@ -41,6 +44,168 @@ typedef pid_t ddsrt_pid_t; DDS_EXPORT ddsrt_pid_t ddsrt_getpid(void); + +/** + * @brief Create new process. + * + * Creates a new process using the provided executable file. It will have + * default priority and scheduling. + * + * Process arguments are represented by argv, which can be null. If argv is + * not null, then the array must be null terminated. The argv array only has + * to contain the arguments, the executable filename doesn't have to be in + * the first element, which is normally the convention. + * + * @param[in] executable Executable file name. + * @param[in] argv Arguments array. + * @param[out] pid ID of the created process. + * + * @returns A dds_retcode_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * Process successfully created. + * @retval DDS_RETCODE_BAD_PARAMETER + * Provided file is not available or not executable. + * @retval DDS_RETCODE_NOT_ALLOWED + * Caller is not permitted to start the process. + * @retval DDS_RETCODE_OUT_OF_RESOURCES + * Not enough resources to start the process. + * @retval DDS_RETCODE_ERROR + * Process could not be created. + */ +DDS_EXPORT dds_retcode_t +ddsrt_proc_create( + const char *executable, + char *const argv[], + ddsrt_pid_t *pid); + +/** + * @brief Wait for a specific child process to have finished. + * + * This function takes a process id and will wait until the related process + * has finished or the timeout is reached. + * + * If the process finished, then the exit code of that process will be copied + * into the given 'code' argument. + * + * Internally, the timeout can be round-up to the nearest milliseconds or + * seconds, depending on the platform. + * + * See ddsrt_proc_waitpids() for waiting on all child processes. + * + * @param[in] pid Process ID (PID) to get the exit code from. + * @param[in] timemout Time within the process is expected to finish. + * @param[out] code The exit code of the process. + * + * @returns A dds_retcode_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * Process has terminated and its exit code has been captured. + * @retval DDS_RETCODE_PRECONDITION_NOT_MET + * Process is still alive (only when timeout == 0). + * @retval DDS_RETCODE_TIMEOUT + * Process is still alive (even after the timeout). + * @retval DDS_RETCODE_BAD_PARAMETER + * Negative timeout. + * @retval DDS_RETCODE_NOT_FOUND + * Process unknown. + * @retval DDS_RETCODE_ERROR + * Getting the exit code failed for an unknown reason. + */ +DDS_EXPORT dds_retcode_t +ddsrt_proc_waitpid( + ddsrt_pid_t pid, + dds_duration_t timeout, + int32_t *code); + +/** + * @brief Wait for a random child process to have finished. + * + * This function will wait until anyone of the child processes has + * finished or the timeout is reached. + * + * If a process finished, then the exit code of that process will be + * copied into the given 'code' argument. The pid of the process will + * be put in the 'pid' argument. + * + * Internally, the timeout can be round-up to the nearest milliseconds or + * seconds, depending on the platform. + * + * See ddsrt_proc_waitpid() for waiting on a specific child process. + * + * @param[in] timemout Time within a process is expected to finish. + * @param[out] pid Process ID (PID) of the finished process. + * @param[out] code The exit code of the process. + * + * @returns A dds_retcode_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * A process has terminated. + * Its exit code and pid have been captured. + * @retval DDS_RETCODE_PRECONDITION_NOT_MET + * All child processes are still alive (only when timeout == 0). + * @retval DDS_RETCODE_TIMEOUT + * All child processes are still alive (even after the timeout). + * @retval DDS_RETCODE_BAD_PARAMETER + * Negative timeout. + * @retval DDS_RETCODE_NOT_FOUND + * There are no processes to wait for. + * @retval DDS_RETCODE_ERROR + * Getting the exit code failed for an unknown reason. + */ +DDS_EXPORT dds_retcode_t +ddsrt_proc_waitpids( + dds_duration_t timeout, + ddsrt_pid_t *pid, + int32_t *code); + +/** + * @brief Checks if a process exists. + * + * @param[in] pid Process ID (PID) to check if it exists. + * + * @returns A dds_retcode_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * The process exists. + * @retval DDS_RETCODE_NOT_FOUND + * The process does not exist. + * @retval DDS_RETCODE_ERROR + * Determining if a process exists or not, failed. + */ +DDS_EXPORT dds_retcode_t +ddsrt_proc_exists( + ddsrt_pid_t pid); + +/** + * @brief Kill a process. + * + * This function will try to forcefully kill the process (identified + * by pid). + * + * When DDS_RETCODE_OK is returned, it doesn't mean that the process + * was actually killed. It only indicates that the process was + * 'told' to terminate. Call ddsrt_proc_exists() to know + * for sure if the process was killed. + * + * @param[in] pid Process ID (PID) of the process to terminate. + * + * @returns A dds_retcode_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * Kill attempt has been started. + * @retval DDS_RETCODE_BAD_PARAMETER + * Process unknown. + * @retval DDS_RETCODE_ILLEGAL_OPERATION + * Caller is not allowed to kill the process. + * @retval DDS_RETCODE_ERROR + * Kill failed for an unknown reason. + */ +DDS_EXPORT dds_retcode_t +ddsrt_proc_kill( + ddsrt_pid_t pid); + + #if defined (__cplusplus) } #endif diff --git a/src/ddsrt/src/process.c b/src/ddsrt/src/process.c deleted file mode 100644 index 4aed282..0000000 --- a/src/ddsrt/src/process.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include "dds/ddsrt/process.h" - -#if !defined(_WIN32) -# include -#endif - -ddsrt_pid_t -ddsrt_getpid(void) -{ -#if defined(_WIN32) - return GetCurrentProcessId(); -#else - /* Mapped to taskIdSelf() in VxWorks kernel mode. */ - return getpid(); -#endif -} diff --git a/src/ddsrt/src/process/posix/process.c b/src/ddsrt/src/process/posix/process.c new file mode 100644 index 0000000..f6ed5db --- /dev/null +++ b/src/ddsrt/src/process/posix/process.c @@ -0,0 +1,303 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dds/ddsrt/process.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/heap.h" + + +ddsrt_pid_t +ddsrt_getpid(void) +{ + /* Mapped to taskIdSelf() in VxWorks kernel mode. */ + return getpid(); +} + + +/* + * This'll take a argv and prefixes it with the given prefix. + * If argv is NULL, the new argv array will only contain the prefix and a NULL. + * The result array is always terminated with NULL. + */ +static char** +prefix_argv(const char *prefix, char *const argv_in[]) +{ + char **argv_out; + size_t argc = 0; + + assert(prefix); + + if (argv_in != NULL) { + while (argv_in[argc] != NULL) { + argc++; + } + } + + argv_out = ddsrt_calloc((argc + 2), sizeof(char*)); + if (argv_out) { + size_t argi; + argv_out[0] = (char*)prefix; + for (argi = 0; argi < argc; argi++) { + argv_out[argi + 1] = (char*)argv_in[argi]; + } + argv_out[argc + 1] = NULL; + } + + return argv_out; +} + + +static void no_op(int sig) +{ + (void)sig; +} + + +static dds_retcode_t +waitpids( + ddsrt_pid_t request_pid, + dds_duration_t timeout, + ddsrt_pid_t *child_pid, + int32_t *code) +{ + struct sigaction sigactold; + struct sigaction sigact; + dds_retcode_t rv; + int options = 0; + int ret; + int s; + + if (timeout < 0) { + return DDS_RETCODE_BAD_PARAMETER; + } + + if (timeout == 0) { + options = WNOHANG; + } else if (timeout != DDS_INFINITY) { + /* Round-up timemout to alarm seconds. */ + unsigned secs; + secs = (unsigned)(timeout / DDS_NSECS_IN_SEC); + if ((timeout % DDS_NSECS_IN_SEC) != 0) { + secs++; + } + /* Be sure that the SIGALRM only wakes up waitpid. */ + sigemptyset (&sigact.sa_mask); + sigact.sa_handler = no_op; + sigact.sa_flags = 0; + sigaction (SIGALRM, &sigact, &sigactold); + /* Now, set the alarm. */ + alarm(secs); + } + + ret = waitpid(request_pid, &s, options); + if (ret > 0) { + if (code) { + if (WIFEXITED(s)) { + *code = WEXITSTATUS(s); + } else { + *code = 1; + } + } + if (child_pid) { + *child_pid = ret; + } + rv = DDS_RETCODE_OK; + } else if (ret == 0) { + /* Process is still alive. */ + rv = DDS_RETCODE_PRECONDITION_NOT_MET; + } else if ((ret == -1) && (errno == EINTR)) { + /* Interrupted, + * so process(es) likely didn't change state and are/is alive. */ + rv = DDS_RETCODE_TIMEOUT; + } else if ((ret == -1) && (errno == ECHILD)) { + /* Unknown pid. */ + rv = DDS_RETCODE_NOT_FOUND; + } else { + /* Unknown error. */ + rv = DDS_RETCODE_ERROR; + } + + if ((timeout != 0) && (timeout != DDS_INFINITY)) { + /* Clean the alarm. */ + alarm(0); + /* Reset SIGALRM actions. */ + sigaction(SIGALRM, &sigactold, NULL); + } + + return rv; +} + + + +dds_retcode_t +ddsrt_proc_create( + const char *executable, + char *const argv[], + ddsrt_pid_t *pid) +{ + dds_retcode_t rv; + char **exec_argv; + int exec_fds[2]; + int exec_err; + pid_t spawn; + ssize_t nr; + + assert(executable != NULL); + assert(pid != NULL); + + /* Prefix the argv with the executable, which is the convention. */ + exec_argv = prefix_argv(executable, argv); + if (exec_argv == NULL) { + return DDS_RETCODE_OUT_OF_RESOURCES; + } + + /* Prepare pipe to know the result of the exec. */ + if (pipe(exec_fds) == -1) { + rv = DDS_RETCODE_OUT_OF_RESOURCES; + goto fail_pipe; + } + if ((fcntl(exec_fds[0], F_SETFD, fcntl(exec_fds[0], F_GETFD) | FD_CLOEXEC) == -1) || + (fcntl(exec_fds[1], F_SETFD, fcntl(exec_fds[1], F_GETFD) | FD_CLOEXEC) == -1) ){ + rv = DDS_RETCODE_ERROR; + goto fail_fctl; + } + + /* Create a new process. */ + spawn = fork(); + if (spawn == -1) + { + rv = DDS_RETCODE_ERROR; + goto fail_fork; + } + else if (spawn == 0) + { + /* Child process */ + + /* Run the executable, replacing current process. */ + execv(executable, exec_argv); + + /* If executing this, something has gone wrong */ + exec_err = errno; + (void)write(exec_fds[1], &exec_err, sizeof(int)); + close(exec_fds[1]); + close(exec_fds[0]); + ddsrt_free(exec_argv); + _exit(1); + } + else + { + /* Parent process */ + + /* Get execv result. */ + rv = DDS_RETCODE_ERROR; + close(exec_fds[1]); + nr = read(exec_fds[0], &exec_err, sizeof(int)); + if (nr == 0) { + /* Pipe closed by successful execv. */ + rv = DDS_RETCODE_OK; + } else if (nr == sizeof(int)) { + /* Translate execv error. */ + if ((exec_err == ENOENT ) || + (exec_err == ENOEXEC) ){ + rv = DDS_RETCODE_BAD_PARAMETER; + } else if (exec_err == EACCES) { + rv = DDS_RETCODE_NOT_ALLOWED; + } + } + close(exec_fds[0]); + + if (rv == DDS_RETCODE_OK) { + /* Remember child pid. */ + *pid = spawn; + } else { + /* Remove the failed fork pid from the system list. */ + waitpid(spawn, NULL, 0); + } + } + + ddsrt_free(exec_argv); + return rv; + +fail_fork: +fail_fctl: + close(exec_fds[0]); + close(exec_fds[1]); +fail_pipe: + ddsrt_free(exec_argv); + return rv; +} + + + +dds_retcode_t +ddsrt_proc_waitpid( + ddsrt_pid_t pid, + dds_duration_t timeout, + int32_t *code) +{ + if (pid > 0) { + return waitpids(pid, timeout, NULL, code); + } + return DDS_RETCODE_BAD_PARAMETER; +} + + + +dds_retcode_t +ddsrt_proc_waitpids( + dds_duration_t timeout, + ddsrt_pid_t *pid, + int32_t *code) +{ + return waitpids(0, timeout, pid, code); +} + + + +dds_retcode_t +ddsrt_proc_exists( + ddsrt_pid_t pid) +{ + if (kill(pid, 0) == 0) + return DDS_RETCODE_OK; + else if (errno == EPERM) + return DDS_RETCODE_OK; + else if (errno == ESRCH) + return DDS_RETCODE_NOT_FOUND; + else + return DDS_RETCODE_ERROR; +} + + + +dds_retcode_t +ddsrt_proc_kill( + ddsrt_pid_t pid) +{ + if (kill(pid, SIGKILL) == 0) + return DDS_RETCODE_OK; + else if (errno == EPERM) + return DDS_RETCODE_ILLEGAL_OPERATION; + else if (errno == ESRCH) + return DDS_RETCODE_BAD_PARAMETER; + else + return DDS_RETCODE_ERROR; +} diff --git a/src/ddsrt/src/process/windows/process.c b/src/ddsrt/src/process/windows/process.c new file mode 100644 index 0000000..91cebec --- /dev/null +++ b/src/ddsrt/src/process/windows/process.c @@ -0,0 +1,447 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/time.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/atomics.h" +#include "dds/ddsrt/process.h" +#include "dds/ddsrt/timeconv.h" + + +ddsrt_pid_t +ddsrt_getpid(void) +{ + return GetCurrentProcessId(); +} + + + +static HANDLE pid_to_phdl (ddsrt_pid_t pid); +static dds_retcode_t process_get_exit_code(HANDLE phdl, int32_t *code); +static dds_retcode_t process_kill (HANDLE phdl); +static char* commandline (const char *exe, char *const argv_in[]); +static BOOL child_add (HANDLE phdl); +static void child_remove (HANDLE phdl); +static DWORD child_list (HANDLE *list, DWORD max); +static HANDLE child_handle (ddsrt_pid_t pid); + + + +dds_retcode_t +ddsrt_proc_create( + const char *executable, + char *const argv[], + ddsrt_pid_t *pid) +{ + dds_retcode_t rv = DDS_RETCODE_ERROR; + PROCESS_INFORMATION process_info; + STARTUPINFO si; + char *cmd; + LPTCH environment; + + assert(executable != NULL); + assert(pid != NULL); + + cmd = commandline(executable, argv); + if (cmd == NULL) { + return DDS_RETCODE_OUT_OF_RESOURCES; + } + + memset(&si, 0, sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + + /* The new process will inherit the input/output handles. */ + /* TODO: Redirect is not working yet. */ + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + + /* Get the environment variables to pass along. */ + environment = GetEnvironmentStrings(); + if(environment){ + BOOL created; + created = CreateProcess(executable, // ApplicationName + cmd, // CommandLine + NULL, // ProcessAttributes + NULL, // ThreadAttributes + TRUE, // InheritHandles + CREATE_NO_WINDOW, // dwCreationFlags + (LPVOID)environment, // Environment + NULL, // CurrentDirectory + &si, // StartupInfo + &process_info); // ProcessInformation + if (created) { + if (child_add(process_info.hProcess)) { + *pid = process_info.dwProcessId; + rv = DDS_RETCODE_OK; + } else { + process_kill(process_info.hProcess); + rv = DDS_RETCODE_OUT_OF_RESOURCES; + } + } else { + DWORD error = GetLastError(); + if ((ERROR_FILE_NOT_FOUND == error) || + (ERROR_PATH_NOT_FOUND == error)) { + rv = DDS_RETCODE_BAD_PARAMETER; + } else if (ERROR_ACCESS_DENIED == error) { + rv = DDS_RETCODE_NOT_ALLOWED; + } + } + FreeEnvironmentStrings(environment); + } + + ddsrt_free(cmd); + + return rv; +} + + + +dds_retcode_t +ddsrt_proc_waitpid( + ddsrt_pid_t pid, + dds_duration_t timeout, + int32_t *code) +{ + dds_retcode_t rv = DDS_RETCODE_OK; + HANDLE phdl; + DWORD ret; + + if (timeout < 0) { + return DDS_RETCODE_BAD_PARAMETER; + } + + phdl = child_handle(pid); + if (phdl == 0) { + return DDS_RETCODE_NOT_FOUND; + } + + if (timeout > 0) { + ret = WaitForSingleObject(phdl, ddsrt_duration_to_msecs_ceil(timeout)); + if (ret != WAIT_OBJECT_0) { + if (ret == WAIT_TIMEOUT) { + rv = DDS_RETCODE_TIMEOUT; + } else { + rv = DDS_RETCODE_ERROR; + } + } + } + + if (rv == DDS_RETCODE_OK) { + rv = process_get_exit_code(phdl, code); + } + + if (rv == DDS_RETCODE_OK) { + child_remove(phdl); + } + + + return rv; +} + + + +dds_retcode_t +ddsrt_proc_waitpids( + dds_duration_t timeout, + ddsrt_pid_t *pid, + int32_t *code) +{ + dds_retcode_t rv = DDS_RETCODE_OK; + HANDLE hdls[MAXIMUM_WAIT_OBJECTS]; + HANDLE phdl; + DWORD cnt; + DWORD ret; + + if (timeout < 0) { + return DDS_RETCODE_BAD_PARAMETER; + } + + cnt = child_list(hdls, MAXIMUM_WAIT_OBJECTS); + if (cnt == 0) { + return DDS_RETCODE_NOT_FOUND; + } + + ret = WaitForMultipleObjects(cnt, hdls, FALSE, ddsrt_duration_to_msecs_ceil(timeout)); + if ((ret < WAIT_OBJECT_0) || (ret >= (WAIT_OBJECT_0 + cnt))) { + if (ret == WAIT_TIMEOUT) { + if (timeout == 0) { + rv = DDS_RETCODE_PRECONDITION_NOT_MET; + } else { + rv = DDS_RETCODE_TIMEOUT; + } + } else { + rv = DDS_RETCODE_ERROR; + } + } else { + /* Get the handle of the specific child that was triggered. */ + phdl = hdls[ret - WAIT_OBJECT_0]; + } + + if (rv == DDS_RETCODE_OK) { + rv = process_get_exit_code(phdl, code); + } + + if (rv == DDS_RETCODE_OK) { + if (pid) { + *pid = GetProcessId(phdl); + } + child_remove(phdl); + } + + return rv; +} + + + +dds_retcode_t +ddsrt_proc_exists( + ddsrt_pid_t pid) +{ + dds_retcode_t rv = DDS_RETCODE_NOT_FOUND; + HANDLE phdl; + + phdl = pid_to_phdl(pid); + if (phdl != 0) { + rv = process_get_exit_code(phdl, NULL); + if (rv == DDS_RETCODE_PRECONDITION_NOT_MET) { + /* Process still exists. */ + rv = DDS_RETCODE_OK; + } else if (rv == DDS_RETCODE_OK) { + /* The process has gone. */ + rv = DDS_RETCODE_NOT_FOUND; + } else { + rv = DDS_RETCODE_ERROR; + } + CloseHandle(phdl); + } + + return rv; +} + + + +dds_retcode_t +ddsrt_proc_kill( + ddsrt_pid_t pid) +{ + dds_retcode_t rv = DDS_RETCODE_BAD_PARAMETER; + HANDLE phdl; + + phdl = pid_to_phdl(pid); + if (phdl != 0) { + /* Forcefully kill. */ + rv = process_kill(phdl); + CloseHandle(phdl); + } + + return rv; +} + + + +static HANDLE +pid_to_phdl(ddsrt_pid_t pid) +{ + return OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | SYNCHRONIZE | PROCESS_TERMINATE, FALSE, pid); +} + + + +static dds_retcode_t +process_get_exit_code( + HANDLE phdl, + int32_t *code) +{ + dds_retcode_t rv = DDS_RETCODE_ERROR; + DWORD tr; + + assert(phdl != 0); + + if (GetExitCodeProcess(phdl, &tr)) { + if (tr == STILL_ACTIVE) { + rv = DDS_RETCODE_PRECONDITION_NOT_MET; + } else { + if (code) { + *code = (int32_t)tr; + } + rv = DDS_RETCODE_OK; + } + } + + return rv; +} + + + +/* Forcefully kill the given process. */ +static dds_retcode_t +process_kill(HANDLE phdl) +{ + assert(phdl != 0); + if (TerminateProcess(phdl, 1 /* exit code */) != 0) { + return DDS_RETCODE_OK; + } + return DDS_RETCODE_ERROR; +} + + + +/* Add quotes to a given string, escape it and add it to a buffer. */ +static char* +insert_char(char *buf, size_t *len, size_t *max, char c) +{ + static const size_t buf_inc = 64; + if (*len == *max) { + *max += buf_inc; + buf = ddsrt_realloc(buf, *max); + } + if (buf) { + buf[(*len)++] = c; + } + return buf; +} +static char* +stringify_cat(char *buf, size_t *len, size_t *max, const char *str) +{ + char last = '\0'; + + /* Start stringification with an opening double-quote. */ + buf = insert_char(buf, len, max, '\"'); + if (!buf) goto end; + + /* Copy and escape the string. */ + while ((*str) != '\0') { + if (*str == '\"') { + buf = insert_char(buf, len, max, '\\'); + if (!buf) goto end; + } + buf = insert_char(buf, len, max, *str); + if (!buf) goto end; + last = *str; + str++; + } + + /* For some reason, only the last backslash will be stripped. + * No need to escape the other backslashes. */ + if (last == '\\') { + buf = insert_char(buf, len, max, '\\'); + if (!buf) goto end; + } + + /* End stringification. */ + buf = insert_char(buf, len, max, '\"'); + if (!buf) goto end; + buf = insert_char(buf, len, max, ' '); + +end: + return buf; +} + + + +/* Create command line with executable and arguments. */ +static char* +commandline(const char *exe, char *const argv_in[]) +{ + char *cmd = NULL; + size_t len = 0; + size_t max = 0; + size_t argi; + + assert(exe); + + /* Add quoted and escaped executable. */ + cmd = stringify_cat(cmd, &len, &max, exe); + if (!cmd) goto end; + + /* Add quoted and escaped arguments. */ + if (argv_in != NULL) { + for (argi = 0; argv_in[argi] != NULL; argi++) { + cmd = stringify_cat(cmd, &len, &max, argv_in[argi]); + if (!cmd) goto end; + } + } + + /* Terminate command line string. */ + cmd = insert_char(cmd, &len, &max, '\0'); + +end: + return cmd; +} + + +/* Maintain a list of children to be able to wait for all them. */ +static ddsrt_atomic_voidp_t g_children[MAXIMUM_WAIT_OBJECTS] = {0}; + +static BOOL +child_update(HANDLE old, HANDLE new) +{ + BOOL updated = FALSE; + for (int i = 0; (i < MAXIMUM_WAIT_OBJECTS) && (!updated); i++) + { + updated = ddsrt_atomic_casvoidp(&(g_children[i]), old, new); + } + return updated; +} + +static BOOL +child_add(HANDLE phdl) +{ + return child_update(0, phdl); +} + +static void +child_remove(HANDLE phdl) +{ + (void)child_update(phdl, 0); +} + +static DWORD +child_list(HANDLE *list, DWORD max) +{ + HANDLE hdl; + int cnt = 0; + assert(list); + assert(max <= MAXIMUM_WAIT_OBJECTS); + for (int i = 0; (i < MAXIMUM_WAIT_OBJECTS); i++) + { + hdl = ddsrt_atomic_ldvoidp(&(g_children[i])); + if (hdl != 0) { + list[cnt++] = hdl; + } + } + return cnt; +} + +static HANDLE +child_handle(ddsrt_pid_t pid) +{ + HANDLE phdl = 0; + + for (int i = 0; (i < MAXIMUM_WAIT_OBJECTS) && (phdl == 0); i++) + { + phdl = ddsrt_atomic_ldvoidp(&(g_children[i])); + if (phdl != 0) { + if (GetProcessId(phdl) != pid) { + phdl = 0; + } + } + } + + return phdl; +} diff --git a/src/ddsrt/tests/CMakeLists.txt b/src/ddsrt/tests/CMakeLists.txt index 552cfd2..02c92ef 100644 --- a/src/ddsrt/tests/CMakeLists.txt +++ b/src/ddsrt/tests/CMakeLists.txt @@ -25,6 +25,7 @@ set(sources "random.c" "strlcpy.c" "socket.c" + "process.c" "select.c") add_cunit_executable(cunit_ddsrt ${sources}) @@ -42,3 +43,26 @@ endif() target_include_directories( cunit_ddsrt PRIVATE "$") + +# Create a separate test application that will be used to +# test process management. +add_executable(process_app process_app.c) +target_link_libraries(process_app PRIVATE ddsrt) +target_include_directories( + process_app + PRIVATE + "$") +# Force the app to be at the same location, no matter what platform or build type. +set_target_properties( + process_app + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR} ) +# Let the cunit application know the location and name of the test application. +set(process_app_name "${CMAKE_CURRENT_BINARY_DIR}/process_app${CMAKE_EXECUTABLE_SUFFIX}") +configure_file( + "process_test.h.in" "${CMAKE_CURRENT_BINARY_DIR}/include/process_test.h" @ONLY) + diff --git a/src/ddsrt/tests/process.c b/src/ddsrt/tests/process.c new file mode 100644 index 0000000..c000cf7 --- /dev/null +++ b/src/ddsrt/tests/process.c @@ -0,0 +1,284 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include "CUnit/Test.h" +#include "process_test.h" +#include "dds/ddsrt/time.h" +#include "dds/ddsrt/strtol.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/process.h" + + +/* + * Create a process that is expected to exit quickly. + * Compare the exit code with the expected exit code. + */ +static void create_and_test_exit(const char *arg, int code) +{ + dds_retcode_t ret; + ddsrt_pid_t pid; + int32_t status; + char *argv[] = { NULL, NULL }; + + argv[0] = (char*)arg; + ret = ddsrt_proc_create(TEST_APPLICATION, argv, &pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + ret = ddsrt_proc_waitpid(pid, DDS_SECS(10), &status); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); + + /* Check result. */ + CU_ASSERT_EQUAL(status, code); + + /* Garbage collection when needed. */ + if (ret != DDS_RETCODE_OK) { + ddsrt_proc_kill(pid); + } +} + + +/* + * Try to create a process without arguments. + * The exit status of the process should be PROCESS_DONE_NOTHING_EXIT_CODE. + */ +CU_Test(ddsrt_process, create) +{ + create_and_test_exit(NULL, TEST_CREATE_EXIT); +} + + +/* + * Create a process that'll sleep for a while. + * Try to kill that process. + */ +CU_Test(ddsrt_process, kill) +{ + dds_retcode_t ret; + ddsrt_pid_t pid; + + /* Sleep for 20 seconds. It should be killed before then. */ + char *argv[] = { TEST_SLEEP_ARG, "20", NULL }; + + ret = ddsrt_proc_create(TEST_APPLICATION, argv, &pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_NOT_EQUAL_FATAL(pid, 0); + + /* Check if process is running. */ + ret = ddsrt_proc_exists(pid); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); + + /* Kill it. */ + ret = ddsrt_proc_kill(pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + /* Check if process is actually gone. */ + ret = ddsrt_proc_waitpid(pid, DDS_SECS(10), NULL); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); + ret = ddsrt_proc_exists(pid); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_NOT_FOUND); +} + + +/* + * Create a process that'll return it's own pid value (reduced + * to fit the exit code range). It should match the pid that was + * returned by the process create (also reduced to be able to + * match the returned semi-pid value). + */ +CU_Test(ddsrt_process, pid) +{ + dds_retcode_t ret; + ddsrt_pid_t pid; + int32_t status; + char *argv[] = { TEST_PID_ARG, NULL }; + + ret = ddsrt_proc_create(TEST_APPLICATION, argv, &pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_NOT_EQUAL_FATAL(pid, 0); + + ret = ddsrt_proc_waitpid(pid, DDS_SECS(10), &status); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); + + /* Compare the pid values. */ + CU_ASSERT_EQUAL(status, TEST_PID_EXIT(pid)); + + /* Garbage collection when needed. */ + if (ret != DDS_RETCODE_OK) { + ddsrt_proc_kill(pid); + } +} + + +/* + * Set a environment variable in the parent process. + * Create a process that should have access to that env var. + */ +CU_Test(ddsrt_process, env) +{ + dds_retcode_t ret; + + ret = ddsrt_setenv(TEST_ENV_VAR_NAME, TEST_ENV_VAR_VALUE); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + create_and_test_exit(TEST_ENV_ARG, TEST_ENV_EXIT); +} + + +/* + * Try to create a process with an non-existing executable file. + * It should fail. + */ +CU_Test(ddsrt_process, invalid) +{ + dds_retcode_t ret; + ddsrt_pid_t pid; + + ret = ddsrt_proc_create("ProbablyNotAnValidExecutable", NULL, &pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_BAD_PARAMETER); + + /* Garbage collection when needed. */ + if (ret == DDS_RETCODE_OK) { + ddsrt_proc_kill(pid); + } +} + + +/* + * Create a process with a backslash in the argument + */ +CU_Test(ddsrt_process, arg_bslash) +{ + create_and_test_exit(TEST_BSLASH_ARG, TEST_BSLASH_EXIT); +} + + +/* + * Create a process with a double-quote in the argument + */ +CU_Test(ddsrt_process, arg_dquote) +{ + create_and_test_exit(TEST_DQUOTE_ARG, TEST_DQUOTE_EXIT); +} + + +/* + * Create two processes and wait for them simultaneously. + */ +CU_Test(ddsrt_process, waitpids) +{ + dds_retcode_t ret; + ddsrt_pid_t child; + ddsrt_pid_t pid1 = 0; + ddsrt_pid_t pid2 = 0; + int32_t status; + + /* Use retpid option to identify return values. */ + char *argv[] = { TEST_PID_ARG, NULL }; + + /* Start two processes. */ + ret = ddsrt_proc_create(TEST_APPLICATION, argv, &pid1); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); + ret = ddsrt_proc_create(TEST_APPLICATION, argv, &pid2); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); + + /* Wait for both processes to have finished. */ + while (((pid1 != 0) || (pid2 != 0)) && (ret == DDS_RETCODE_OK)) { + ret = ddsrt_proc_waitpids(DDS_SECS(10), &child, &status); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); + if (child == pid1) { + CU_ASSERT_EQUAL(status, TEST_PID_EXIT(pid1)); + pid1 = 0; + } else if (child == pid2) { + CU_ASSERT_EQUAL(status, TEST_PID_EXIT(pid2)); + pid2 = 0; + } else { + CU_ASSERT(0); + } + } + + ret = ddsrt_proc_waitpids(DDS_SECS(10), &child, &status); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_NOT_FOUND); + + /* Garbage collection when needed. */ + if (pid1 != 0) { + ddsrt_proc_kill(pid1); + } + if (pid2 != 0) { + ddsrt_proc_kill(pid2); + } +} + + +/* + * Create a sleeping process. Waiting for it should timeout. + */ +CU_Test(ddsrt_process, waitpid_timeout) +{ + dds_retcode_t ret; + ddsrt_pid_t pid; + + /* Sleep for 20 seconds. We should have a timeout before then. */ + char *argv[] = { TEST_SLEEP_ARG, "20", NULL }; + ret = ddsrt_proc_create(TEST_APPLICATION, argv, &pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_NOT_EQUAL_FATAL(pid, 0); + + /* Timeout 0 should return DDS_RETCODE_PRECONDITION_NOT_MET when alive. */ + ret = ddsrt_proc_waitpid(pid, 0, NULL); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); + + /* Valid timeout should return DDS_RETCODE_TIMEOUT when alive. */ + ret = ddsrt_proc_waitpid(pid, DDS_SECS(1), NULL); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_TIMEOUT); + + /* Kill it. */ + ret = ddsrt_proc_kill(pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + /* When killed, DDS_RETCODE_OK should be returned. */ + ret = ddsrt_proc_waitpid(pid, DDS_SECS(10), NULL); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); +} + + +/* + * Create a sleeping process. Waiting for it should timeout. + */ +CU_Test(ddsrt_process, waitpids_timeout) +{ + dds_retcode_t ret; + ddsrt_pid_t pid; + + /* Sleep for 20 seconds. We should have a timeout before then. */ + char *argv[] = { TEST_SLEEP_ARG, "20", NULL }; + ret = ddsrt_proc_create(TEST_APPLICATION, argv, &pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + CU_ASSERT_NOT_EQUAL_FATAL(pid, 0); + + /* Timeout 0 should return DDS_RETCODE_PRECONDITION_NOT_MET when alive. */ + ret = ddsrt_proc_waitpids(0, NULL, NULL); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_PRECONDITION_NOT_MET); + + /* Valid timeout should return DDS_RETCODE_TIMEOUT when alive. */ + ret = ddsrt_proc_waitpids(DDS_SECS(1), NULL, NULL); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_TIMEOUT); + + /* Kill it. */ + ret = ddsrt_proc_kill(pid); + CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + + /* When killed, DDS_RETCODE_OK should be returned. */ + ret = ddsrt_proc_waitpids(DDS_SECS(10), NULL, NULL); + CU_ASSERT_EQUAL(ret, DDS_RETCODE_OK); +} diff --git a/src/ddsrt/tests/process_app.c b/src/ddsrt/tests/process_app.c new file mode 100644 index 0000000..a0c402a --- /dev/null +++ b/src/ddsrt/tests/process_app.c @@ -0,0 +1,108 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include "process_test.h" +#include "dds/ddsrt/strtol.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/process.h" + + +static int test_create(void) +{ + printf(" Process: created without args.\n"); + return TEST_CREATE_EXIT; +} + +static int test_sleep(int argi, int argc, char **argv) +{ + argi++; + if (argi < argc) { + long long dorment; + ddsrt_strtoll(argv[argi], NULL, 0, &dorment); + printf(" Process: sleep %d seconds.\n", (int)dorment); + dds_sleepfor(DDS_SECS((int64_t)dorment)); + } else { + printf(" Process: no --sleep value.\n"); + return TEST_EXIT_WRONG_ARGS; + } + /* Expected to be destroyed before reaching this. */ + return TEST_EXIT_FAILURE; +} + +static int test_pid(void) +{ + int ret; + ddsrt_pid_t pid; + pid = ddsrt_getpid(); + ret = TEST_PID_EXIT(pid); + printf(" Process: pid %d reduced to %d exit code.\n", (int)pid, ret); + return ret; +} + +static int test_env(void) +{ + int ret = TEST_EXIT_FAILURE; + char *envptr = NULL; + if (ddsrt_getenv(TEST_ENV_VAR_NAME, &envptr) == DDS_RETCODE_OK) { + printf(" Process: env %s=%s.\n", TEST_ENV_VAR_NAME, envptr); + if (strcmp(envptr, TEST_ENV_VAR_VALUE) == 0) { + ret = TEST_ENV_EXIT; + } + } else { + printf(" Process: failed to get environment variable.\n"); + } + return ret; +} + +static int test_bslash(void) +{ + printf(" Process: backslash argument.\n"); + return TEST_BSLASH_EXIT; +} + +static int test_dquote(void) +{ + printf(" Process: double-quote argument.\n"); + return TEST_DQUOTE_EXIT; +} + + +/* + * The spawned application used in the process tests. + */ +int main(int argc, char **argv) +{ + int ret; + + if (argc == 1) { + ret = test_create(); + } else { + if (strcmp(argv[1], TEST_SLEEP_ARG) == 0) { + ret = test_sleep(1, argc, argv); + } else if (strcmp(argv[1], TEST_PID_ARG) == 0) { + ret = test_pid(); + } else if (strcmp(argv[1], TEST_ENV_ARG) == 0) { + ret = test_env(); + } else if (strcmp(argv[1], TEST_BSLASH_ARG) == 0) { + ret = test_bslash(); + } else if (strcmp(argv[1], TEST_DQUOTE_ARG) == 0) { + ret = test_dquote(); + } else { + printf(" Process: unknown argument.\n"); + ret = TEST_EXIT_WRONG_ARGS; + } + } + + return ret; +} diff --git a/src/ddsrt/tests/process_test.h.in b/src/ddsrt/tests/process_test.h.in new file mode 100644 index 0000000..25cd632 --- /dev/null +++ b/src/ddsrt/tests/process_test.h.in @@ -0,0 +1,42 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSRT_TEST_PROCESS_TEST_H +#define DDSRT_TEST_PROCESS_TEST_H + +/* Get the application name from cmake to automatically + * get the proper extension and location. */ +#define TEST_APPLICATION "@process_app_name@" + +#define TEST_SLEEP_ARG "--sleep" + +#define TEST_EXIT_GENERIC_OK (0) +#define TEST_EXIT_FAILURE (1) +#define TEST_EXIT_WRONG_ARGS (2) + +#define TEST_CREATE_ARG NULL +#define TEST_CREATE_EXIT (0) + +#define TEST_PID_ARG "--retpid" +#define TEST_PID_EXIT(pid) ((int)(int32_t)(pid % 127)) + +#define TEST_ENV_ARG "--checkenv" +#define TEST_ENV_EXIT (12) +#define TEST_ENV_VAR_NAME "TEST_ENV_VAR_NAME" +#define TEST_ENV_VAR_VALUE "TEST_ENV_VAR_VALUE" + +#define TEST_BSLASH_ARG "\\left\\\\right\\" +#define TEST_BSLASH_EXIT (int)('\\') + +#define TEST_DQUOTE_ARG "\"left\"\"right\"" +#define TEST_DQUOTE_EXIT (int)('"') + +#endif /* DDSRT_TEST_PROCESS_TEST_H */ From 597ca2528734b682ee8c80aa4d842cfdb1d46e7d Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Wed, 10 Apr 2019 17:57:29 +0200 Subject: [PATCH 043/238] Multi Process Testing framework Signed-off-by: Martin Bremmer --- docs/dev/mpt_req.md | 86 +++ docs/dev/multi_process_testing.md | 86 +++ docs/dev/pictures/mpt_flow.png | Bin 0 -> 74078 bytes docs/dev/pictures/mpt_tree.png | Bin 0 -> 19753 bytes src/CMakeLists.txt | 6 + src/ddsrt/include/dds/ddsrt/log.h | 2 +- src/mpt/CMakeLists.txt | 22 + src/mpt/mpt/CMakeLists.txt | 17 + src/mpt/mpt/cmake/MPT.cmake | 184 +++++ src/mpt/mpt/include/mpt/mpt.h | 158 +++++ src/mpt/mpt/include/mpt/private/mpt.h | 153 ++++ src/mpt/mpt/include/mpt/resource.h.in | 6 + src/mpt/mpt/src/main.c.in | 551 ++++++++++++++ src/mpt/tests/CMakeLists.txt | 19 + src/mpt/tests/basic/CMakeLists.txt | 23 + src/mpt/tests/basic/etc/config_any.xml | 30 + src/mpt/tests/basic/etc/config_specific.xml | 30 + src/mpt/tests/basic/helloworld.c | 63 ++ src/mpt/tests/basic/multi.c | 50 ++ src/mpt/tests/basic/procs/hello.c | 239 +++++++ src/mpt/tests/basic/procs/hello.h | 52 ++ src/mpt/tests/basic/procs/helloworlddata.idl | 9 + src/mpt/tests/self/CMakeLists.txt | 25 + src/mpt/tests/self/asserts.c | 711 +++++++++++++++++++ src/mpt/tests/self/environments.c | 96 +++ src/mpt/tests/self/etc/file | 0 src/mpt/tests/self/fixtures.c | 72 ++ src/mpt/tests/self/ipc.c | 29 + src/mpt/tests/self/resources.c | 30 + src/mpt/tests/self/usage.c | 186 +++++ 30 files changed, 2934 insertions(+), 1 deletion(-) create mode 100644 docs/dev/mpt_req.md create mode 100644 docs/dev/multi_process_testing.md create mode 100644 docs/dev/pictures/mpt_flow.png create mode 100644 docs/dev/pictures/mpt_tree.png create mode 100644 src/mpt/CMakeLists.txt create mode 100644 src/mpt/mpt/CMakeLists.txt create mode 100644 src/mpt/mpt/cmake/MPT.cmake create mode 100644 src/mpt/mpt/include/mpt/mpt.h create mode 100644 src/mpt/mpt/include/mpt/private/mpt.h create mode 100644 src/mpt/mpt/include/mpt/resource.h.in create mode 100644 src/mpt/mpt/src/main.c.in create mode 100644 src/mpt/tests/CMakeLists.txt create mode 100644 src/mpt/tests/basic/CMakeLists.txt create mode 100644 src/mpt/tests/basic/etc/config_any.xml create mode 100644 src/mpt/tests/basic/etc/config_specific.xml create mode 100644 src/mpt/tests/basic/helloworld.c create mode 100644 src/mpt/tests/basic/multi.c create mode 100644 src/mpt/tests/basic/procs/hello.c create mode 100644 src/mpt/tests/basic/procs/hello.h create mode 100644 src/mpt/tests/basic/procs/helloworlddata.idl create mode 100644 src/mpt/tests/self/CMakeLists.txt create mode 100644 src/mpt/tests/self/asserts.c create mode 100644 src/mpt/tests/self/environments.c create mode 100644 src/mpt/tests/self/etc/file create mode 100644 src/mpt/tests/self/fixtures.c create mode 100644 src/mpt/tests/self/ipc.c create mode 100644 src/mpt/tests/self/resources.c create mode 100644 src/mpt/tests/self/usage.c diff --git a/docs/dev/mpt_req.md b/docs/dev/mpt_req.md new file mode 100644 index 0000000..bcd2a90 --- /dev/null +++ b/docs/dev/mpt_req.md @@ -0,0 +1,86 @@ +# Eclipse Cyclone DDS Multi Process Testing Requirements + +This document present some requirements and considerations regarding the +[Multi Process Test Framework](multi_process_testing.md). + +## Requirements +1.1) To test certain Cyclone DDS features, multiple processes running Cyclone + DDS are needed to force communication through the whole stack. + +1.2) Should be buildable and runnable on platforms that support multiprocess + and filesystems including the ones used in the continues integration + context. + +1.3) Results should be easily analyzable within the continues integration + context and when running locally. This can be done by reporting the + results in a standard format like xunit or cunit. + +1.4) No processes must be left behind (f.i. deadlock in child process) when the + test finished (or timed out). + +1.5) When running tests parallel, they should not interfere with each other. + +1.6) Processes of the same test should be able to communicate (for settings, + syncing, etc). + +1.7) It should be possible to analyze output/messages/tracing of the parent + and child processes to be able to draw a proper test conclusion. + + +## Considerations +2.1) +The files that actually contain the tests, should be focused on those tests. +This means that the process management and setting up (and usage of) IPC +between test processes should be handled by a test framework so that the +test files can remain as clean as possible. + +2.2) +If possible, there shouldn't be a need for writing log files to a file system +when running the tests normally. It could be helpful, however, that these log +files are written when debugging related tests. + +2.3) +Preferably, the DDS communication between the processes should not leave +localhost. + + +## Intentions +There doesn't seem to be a 3rd party test framework that addresses our +requirements in a satisfactory manner. + +After some discussions with a few people (different people in different +meetings), it was decided to create our own framework and to go in the +following direction: + +- Process creation/destruction/etc is (re)introduced in the ddsrt.
+ [1.1/1.2] + +- The files that contain the tests, should be easy to understand and focus on + the tests themselves.
+ [2.1] + +- Other files (generated or in the framework) should take care of the + intricacies of starting/monitoring the proper processes with the proper + settings.
+ [1.4/1.6/2.1] + +- To do this, a similar approach of the current CUnit build will be used; + CMake will scan the test files and create runners according to macros within + the test files.
+ [2.1] + +- The tests should be executed by CTest. For now this means that a proper + runner exit code for pass/fail is enough. We would like to add CUnit like + output in the future.
+ [1.2/1.3] + +- The Cyclone DDS API contains the possibility to monitor generated log traces. + This means we won't be needing to monitor actual log files. Just register a + log callback and go from there.
+ [1.7/2.2] + +- The framework should be able to generate unique domain ids and unique topic + names when necessary. That way, tests won't interfere with each other when + running in parallel.
+ [1.5] + diff --git a/docs/dev/multi_process_testing.md b/docs/dev/multi_process_testing.md new file mode 100644 index 0000000..aa33f9d --- /dev/null +++ b/docs/dev/multi_process_testing.md @@ -0,0 +1,86 @@ +# Eclipse Cyclone DDS Multi Process Testing + +Some features and functionalities of Cyclone DDS can only be tested when +there's communication between processes. Examples are durability, security, +etc. To really make sure that these kind of features work, extended tests +with multiple processes are needed. + +This results in a number of [requirements](mpt_req.md). + +There doesn't seem to be a 3rd party test framework that addresses our +requirements in a satisfactory manner. Therefore, it was decided to create +our own Multi Process Testing (MPT) framework. + +This document will provide an overview of the MPT framework. + + +## Overview + +An MPT application is basically divided into two components +1. Tests +2. Runner + +The Tests are created by the developer. They don't need to worry about the +process management. They only have to provide process entry point(s), tests +and test processes that use these entry points. E.g. +```cpp +MPT_ProcessEntry(publisher, MPT_Args(int domain)) +{ + /* Publish a sample on the given domain. */ + MPT_ASSERT(success, "publisher failed"); +} +MPT_ProcessEntry(subscriber, MPT_Args(int domain)) +{ + /* Subscribe to a sample from the given domain. */ + MPT_ASSERT(success, "subscriber failed"); +} + +MPT_TestProcess(helloworld, domain0, pub, publisher, MPT_ArgValues(0)); +MPT_TestProcess(helloworld, domain0, sub, subscriber, MPT_ArgValues(0)); +MPT_Test(helloworld, domain0); + +MPT_TestProcess(helloworld, domain42, pub, publisher, MPT_ArgValues(42)); +MPT_TestProcess(helloworld, domain42, sub, subscriber, MPT_ArgValues(42)); +MPT_Test(helloworld, domain42); +``` + +There are more options, but see the +[usage test](../../src/mpt/tests/self/usage.c) for more elaborate examples. + +CMake will identify suites, tests and processes depending on those MPT +macros.
+It'll use that to generate part of the MPT Runner. The Runner takes care +of starting test(s) and handling the process management. + +The runner also takes care of preparing IPC between test processes so that +these processes can sync if they need to (NB, this will be a future extension). + + +#### Suite-Test-Process tree + +A process is related to a test and that test is related to a suite.
+A suite can have multiple tests and tests can have multiple processes.
+ +This results in the following tree quite naturally. + +Suite-Test-Process tree + + +#### Test execution + +There are 3 main ways to start an MPT application. +1. Without argument.
+ All tests will be run. +2. With suite and/or test name patterns as arguments.
+ A subset of tests will be run depending on the provided patterns.
+ This allows ctest to execute single tests. +3. With a specific suite/test/process combination as arguments.
+ An user will normally not use this. + +The third option is used by the MPT application itself to start a specific +test related process. It does so by restarting itself with the proper +suite/test/process combination as indicated by the test. This results +in the following flow. + +MPT application flow + diff --git a/docs/dev/pictures/mpt_flow.png b/docs/dev/pictures/mpt_flow.png new file mode 100644 index 0000000000000000000000000000000000000000..271e74bd4b2256079fb2525f72757e9237ad5aab GIT binary patch literal 74078 zcmc$`cUV+gwmn)HQAAJ#1O!AB1O!yFL_tKdk~2!qITrCKIVw?-faIJr1!4fn8Kj6x zE^?OqW^wv-_v^m>?!CYFzVGex#{t<@d+inG8e_~cm;ZAaG5m|<7ZC^qzWB2zatOp} z8wBD^3GONQmx}ZR2Ke7O9Z9h#h-2)3NvMo)1mY$_{K;blr})KD7Y&8}qvJJ>)3`S8 z0ts(AK0o#CYjIEQjk_ES3bmisp7!j#Ka!JVCZ4y+-B6V8We;h3NW^NK_2iwuLr-n0 zK~&SCS8QgI&6R1!*RM5ZcA5mnd5GF3aMcY@7tE$KrNnTUE*%cJykA>Vb4ig%>BfcD zBsuq`vmnlm*15S1mzz&E2IF14SX_p^@Go8@=du{tUK+L>uQSJB;N~NtZ)Rx^(^6C0 z5_q}T*yLAoaBy%Wqgg0ptPcoUMcXk6zo>5J#F z#b7YYhUV}+KKIqLxJwK>wd!1}-X+X-B-H3NhqLR*V@uayLNYfXQke9T!7)ZR;AU?yo#~nii+qzZ)=m* zL>w(>AMYvmo}&_U*FakRUj4bdF}pHcA&c8xq}w##o6#A|k+W;O4*f_>Oe{??oUh4C zK@pc8oR^tdiQF>jZAAb0QCVHxQZv53z7Ac~*!1YpqrLroF7x_3ckTp_92F=V8)w-K zj-DpqTkR4d;4rTr%-7uCsXrbqEovXKl#%J^P7#aa9O&&WkxdkkrihD-EQ1b958m3? zpkOz8&bFie;)QiZJ#xF@Jate&fC<{Y^8>$2Q+=^ky}Ra0LFC*RYXA4zWL)|9xck0& zYZNoIGXC%bx3x}tEQd73{^}P3*_elE#=0H{YfU?2E(ONAE<4MIEldUM=8MT9zDL^? z^&IAA$47_9dxP~YmE+LMXf&EP#0`2l*0p5baoo-DpkK${-hQw^dr%ySw)bf<#Vq(N) zIc$!5G98xCJdYl6nwy1ZFs2nrf7mr$SJ0>3$4>UbLL*nRa6A%W?njRV*1yv_a(r!Q zc$_A8fu`DVWo+uOy1M%E4eml?-MA8MS=mmyBXbqMF_a6JbN$iLQ8>M<1^S0CwR`36 zepykG@nHU_X0UmOv-@hp`4#ROT}#UXrG+Xw40ONQx_gb|N}bc%uXMP>o!WWo9bKo= z-tI1kb3MvsXAG8MZzB?k2(nqI7ao76fWsOPa zmY?M*E#wb!%yy>u`T5a}9CRHVUZ&v8g-#&}KvLGRD%%Xg&mA2Wn7*vFwYBzL#AyU#4%Kh-+dSft!WYj&lKZeUvOI+OFRUabUK?6*3Se7!m3UBGO z!vtM_Ta9MORr1+P;r_e|U&?jwHPbWfB*@q7OceA`PB}O{?2PBpox2+F#h0M|aC;c$ z1F`TuwbHvZG>?6RVWpGbRAOu;)pmVg(wA979u^y`W?5dGOe+>r3-fScuwbPtS%fVc zT72J6C5zj3rcJfnEaqLpJCk1mhiECh%g%c{r&J~ZMUud`lGFa`1l(%UKts)w4r=g ziHSK}f3NZ$X<1)i*E@8y5$2t-r7DeKiSu{b6N!@!8D$d=laN{1*_2h#FjxqgL7-4pr=PX`+KoKr_1?`FFa`JSU4d?>;b?kdE+3_peb^ZkgEdj;U$Pt3ds zgwU>EBr~F75k4_Zt5lA-_ZqrjnvKgIr;_dD&f=*ly~nv`S1QY){Le zfQaw z;(07lTTz<|TuM~D4)<7CmXm#{!ju|e{#|>mlJ$hOcJ*~i%4EZv^Px9*ZXI1`()KvC z4}Q8aV%u3n2Satu8*XxNaOlmDB^AD>RjV>LQd|OIW2J7tqoLtvzp^%mwLc7%$CF%z zOfoiuA82%XTG}CON@#V5G1m=gnkTNVwc+96S$NP(zfbF=3EMCJu znf~MSdG~`gF-OOpXf0%OUq3XhFQdnZJv|?1Z+dF#%$YMV0jq0jX5r_vXAh6|S8|l{ zVmZxYvm{|=WQM9_8HLkHt5sMe1P4otih2`%9vs}+8TY6tEoHaYgtl!J;pQ8`dNwdH zP*hZ;d}K!`Tnh_Q4?AI`+LRba-#^eTHy@_+a)O}N+uPgT-Y%_q1xAtz`^Q@64F$$X z!e0rFV>I$GJHF|_+;`d@GAz)n+3uAU6yJr(BlL%wUhZwpva`%<^h7(c#)A6?Qm2F_ zRnDA;ueqeQT83=9QL5DTG{t)7xTLf5HsX59*(P{C;_hP`n_{ExL8bDqEw3((X> zOyPh2&|5Kg_d1C*#(VeJ?P(BFZ&Y@vMSL#3$bz?OX>3e~?UaFmAwB<@HF676_Ug+y zd1ahZPBbgEsp$e0KhkWpy1$PYM~LVO)A7P|w03@een)F-U`PlRn?c)9iD59AqNb*s zY)EM6xga|R6Mo=FOKk1Oo3PB2qPV*EcsuY8(sLZ`0F@ zrO8D`MM-?Yf;AG70oY{Wwc-Wbkg$B}>gu+)w_)M*8nFi}UneKuLz@=hle6EweLEEb zw(n)itHN#ZJZ${@`~m`XwzD0uOy$<_L&=4Ro@oofRC1b*RQ4jQKUfbm+B`kBN`!vq zLYrtexNeuz;{(J?yVcy$ zK_VOx5%KKH;o+fdJh%16O#6=?Kj4wGi5_*SskdoqQ{XwUs{||mfVNCbOqdSl8?(pa zQ*b)DxJVvi0m0V7pkydMW!XKoWm&pq4*5f~k={d$`>xqgu_&(fudf%RQ>d*_iO)rr zf?a#;>kaMT!;8)IiM38^I+~iJFy8>{LZgm0GXzCNMI!-ClaL4;ZuVlwzpu*U_y`6y z=TGzrn5|6vd86z3Q$`$qkshm?y|U`+>NVBX=%Jyi>gs&8vTQA1*lI23x{`Y)VNTR; zbnx~}wzWw~O13hqmq$cJnea+_oYSatRYj`F%j=q&?k^P7bIN%pFD3Fi%HY0GP`J&{ zZ#Cihpva~Yp+#~lFIv;4kMw?N zndTMA?N9gSYu0d>4m^X`{j}vSyj9M1BtGcgITw~r3^1Z#*y-ozvov4RB%@O^=I7^y z{c3A#H)cCc@w$xIUA7nB)g{HQQsO3whS$-no;fa9n`}ztbAHIh#U&`{fi5)`_A4zd zU0t<;MMq7Y=#588a_yQCuZxq@GlGMIgK~?}*ocU!pFg`ZWD_A)(mYX8ijqhp2Uz{* zRberjo0o^3T$Z7YW`bN?g98Ht&CTLS%;cnQTag{6PaOGD7kf=kOeCGGCtjtw#l?I4 zM&orTLSgcck}EGx86oITPvJgii-UJwqe?E-Nc53rkd3 z+VYk->~E2gkv)?&hrv{h3M!#$hrab*?0hD?yfro1IG#`T)~#)A_hJ6j*v*H9g*^no zHskuKjQlut!9CP?cW-Z?uTRgw0Emq#1**2z#KgqL#)gld-&{8IzNfP0Fe>Gv_8l1qX(iX=!zV!$5SRhKb zwY3coy8!)yeXfT^6X*ddJw5%xF!YRVqJW!0=LffifxOS3KUa*qtMB&!idzRbi$?*&abxMXZ>yhV2|Xrzu%2dKMpzJ|4pcpzP|Mqh6_r=~5Tm7~rS0wPZm=7@O-?!2B?VFN-o1Mo_3mzL zf)i?v`{Ja+W@EKH_wN@1`G*h=3_gNgx!Qb~lZ~z9)2C0cBp>neTB1wEF}3Ey;Jr;u6hv;$g@s*(2?v~0BKiUB z@pmrh~V=rZp2+OELi=|d;I?b7|f)zB+aLKq>&1#e=(#+MEDP#zzd5At&)0J(9jKcq;@P{Z|1nZW|Rh1G&^~k3);@o}y7qZJ8q#`G;cHS@uk4TN~ z!QiOf(MkI#9{oa16?dye-vR=53z8Co*d-@*l6GD z4Q?Gklmo)*=-^-hGuq0^N?7=Hgof`WvX63E5c*2_WfLBy$z_?Dn@cO-^E?I$8_Ujr z@(|T#g*#o0OJk@SSSngtS}*_*^&UB`PJH^~^kA;4?aHRL!16`kj0?VclN(g4Gn$@?I&pJB_)Mo z2p!3!e2bQrl9KZD>C-@g%;)ALKN_DtTYIl{yW_>U1z>Zq~Z0x!l)s>FSf<7k+Nz52>Y0P83I(T)z8nM$mMHP z^+1riLi@C@zh9g+Ej`_RZypOAAZ&lQ|LQa4enx7lD^M51j(Go&5C>b^;VN50Rn;Mo z%;eY-8&L5Eeo$c=XvDPw@Dlr0*3(<PvL1W#88QhDi$7@c;<#)Y5hHmd&h(Yrt!ML8BoCUu zq6YSs&j>oLzEn~9G2I#syQ~)>&=x@M;aV-7ot@3iYwPPhb!zJB3lkGoAba{!A@8!Y zv$L>R07e$}gWyU}p8==`RLG}$p}-Rf=@J9UbmF!ehPW`f~<1=X=wh85*r{ za&m&4($U%JXm3v}4DzdESJLCNXV1a}sgA?P#}5t)(kOiS$0qyj+fzV_KJYoOr;3NS zwYLkxJV2w>EG<_cio8g9%3&jeA$zFz3^u3_9!I-P)E<2F^oHNx(#WSv6_u1wuo(og z?;Fi^35$r(-ns>lZ0}bfD?oZ>OxJfZ&LinFN%|I;Q;4Lcu#YM*p{|*JaN8cjQkX|} zcj@S!;=YTFgyjfQZ|ahzxw+eP3o*l{k*)?TK5s%$xGMn^(H`>i@s%#YmJ0G`Yg^kj zVL(T79oxoa=o&y7d3kwQDH~pw)6Nc-B)SPm5f2ZKupfhb`lTD(tEio^{pFe!026?w zlq@3x0|S?Nx|wd?yvfdP2fHu~8###NFo%M8N&(;lc!MCZ71H!9_e^a1*`}6#LES(0 zMPkWLp`iHV8LD;nGX2E9wJr#hu^-*nLV;>C*}KYoNs z3BA&1vegpF1Zb2Im8z7pQdx#a$^x$t5gjcV_#NPs52gx$euO}47oANf`+*OLnQDoFs+yV!1qBZ~%~x2E$Ge>#mjV2O zg4ZKnH_Ub^$r>vF(WS^`9j%3WO#4CJZ;RL;-L{NCQq@3fkx6u zLIShbT?Pgi8y9Km;N(2Ap?X-i`S~pD>|QI_%|jhL%7Y_mzc39cV==%~2pMA=KqW%+d+M2m$FCFtx ze{XXh&>^+^?^kMSu?|nI4t}q}gWdMG`)hu)cwK*}_Z@T_kL8gn_rpDqi5@UAO5i4| zgNFP0vkq({TP$;CQ(d=B%8*OwGFgG$DNmf!siM0z{9h280k9qT`x`e@EEeL9sjU%A zH@qEiY?T>K?KT1_7PvpR#R#|j;3*-ho*lN5NRT#7U^xJg1L9Yjg@<#qgv7P=G9u|4 z#OeoJT(S}pCWHA2S*AEQv8v<55yRcP_w6qrmWfHQsOWzpz_jeO1Qc{ETFP6azJK4Y zS+Y%Rmg@;%cqOv)bT;s<@?Q2s%$m(cN z(&_*qo>!I=GjZ74i`8pcjy9~#h1`}O>$G|pMUw-TJ#BB9xV`@}_yOZH`J4M|n z74>1uMS89kR-#$0W>CK(IcYmxb zc9>e4*6T>9Bqm#}zA-Mi zNxgMU75KjE8CRql%DF*1+agN#c%LgIU(1_kw%=f;F%+dcbarUA?r5TYNL)`(f78op#(URSZa|~? z(I~^sCytfL7E9(!y#yJkqAf1tna*!Hl3%_&U@uRI+@fq%ic<%a6CV`5-C?1`Nm={G zg<~m#JiDO>trWF%8ri;Rsfz)r4_TV5vOC!kJV1G)hW`reUmQ-0A^nyI#jMjseizct zRz)qDr@g%GWwpH-O?BO5P(M@FdQ3D@A}wzAUM@PCczQ4}(x-ZqkySA+hSz0oXp*ui zwxXm~cZhP-jlK@G_PoV+I7(*aT9^6i*WdYWKJ3K>HF-35Unbof233>!nYw>uY<0D+ zF@l zx60>wl6JIWF6UDnsnMRFlgH4~iuuvJV$no0V=z`^M)PFnNTg0^Xxvwws%CSh9IKIeJ4ARn32;XlXQBqF@?E==GwlsI%(R5RUXk_|ec~ zOxdlbXXJCwK!fTX1v!;X*TUH>+8QrH`!bIG3JjT%9yAs5z-no8*vm*!@?f}LBJHYh zE}z1ygSVkXI(-H+$0ZZ;qm7ZQ0`p|oA0Y=^2JzO*SrU|#A}n7G9VO#@am;l$|Jl*X zxlM^*wqWrU)^XhQ@krs^;2Yi+$%|%-38#ejgQb5z&*N;}TbdiVBi|a3k37rIXa7w` zWR#Jq#UVc?(Oqvak0MQGc?{O@1m#HU_aeu8yeq$o310zk-n1f^Lz63l8(92x_7BevueL&=@1BWRhSS)kFi>G z>63fX|Eyf&z2p!1%M0*-s$%~K)~G-p+}Ou4!U0SXbJeP|>}#Ubh-v!a;s)CZS2|I| zv1C%Zdtl~LDp_o~L!T$jxI&#%;tuy$%$xmMF@%vnX!k%LJ#9cN{u_N{0Bm)VGs3FZ z*uVWZ8vB1}-9LnRDPzEVjFF5C4C2E!m_7z*uc>LyFr;CJe*6G^f$h$nwBlm9v{2B) zzATL^8jAd>#`_>S7NYvTzB%7j4a)zguON*BK*@2dhJ-JGDU5^D?sRlcPR_>q`p1-% zrXVs~5XIGx4T0#vM%FVK5D?%)QBhp{u&!hc6KMxZE|M}kCnv7N&D(TT>^wUeBn_m@ zKmmn)_(WmM&dvtCN;Z~Vyy6XemC-*b_To9mDM~r*ZEdMdpiChv3My>v?YI6#kiU~< ztE2NVF)J0ThlUaWZN7Y2Mp_yLuTyC~IRe+{=;W_o z0fB*OMf&>skYiZg*eEF}!MkvQ$6@h3;m6wAk?+V$9GHvv_?neguT)f20PDJJ&RGMt z2&UlL+uK7A56i}JN~d%iRS?~{VP=5Z4PA zFJ@(R_T=IJZkkbUZ~*FZy}_9#2OXpl5DA=I zZZ;_?3HZMI&Zr~Ig-X|5n=jZGn^#O~*ST^7A;tPHG(-=j+!RXf0r@4ENNT2fvPX_tV+#PNYV_3*GT$a260>ixbMmyG>6_59G#5F}|}P|&9% z$XT^&jVvr!_|4V$pOOq^$%0FOd)?EhEKEug!cDFa zrVZ`rnm>icHDJOKy7CX=!BP992V5kOXKZv6->`x-lZ~}?){fl2>()kwh8aqOiEr*J zgh`}@Q8_s~LlS;!YRU;WpDHUrLvcmA1@KwOro;>kV z%hRf|nTEIYCIl9Q&&0kyw_JWMDe@Jh&#%3LIDs|B2n&C9`w{(jHgj9L5K=2fQ z5mD4dynp}x?OQ?$3YX&?*k6s#6v_D;w8!4@QmJ!w1|yY)3urk3#7w2&JwQaffv*Sh z1{cVEkTUNvmz9zN2SAh-#|vY)VebkPvB}ZF?ypdyD0G&@JT{{&N~6T6@a2Leh>Hl% zu(gG*$OQ;ZKY#wbeED*ZS6X*>j^FQU!AdlJ?^QGYtQi||OcjRNL5lLGUGCy6UtBFPw zoID^Ce&PTTI(NLAa}2U?dfsWHZiDTLD{Tfi2sCFtwwHxU{y*QkrHGhX|AoFW6y7Gw zdw+F%vID=^QYk9jA=CuenY5Lx&h!UqNyF`mUE`f7mm+K3dx?E38KZG4$0|foG`d65 zFSAjCJPtmV&n$Zfpp$Q}H%Ulqj&>IesykZoRnv-Z2TxLEzIe4CX6 z_X*>^V%aD0I5xI4ems`ySnkH|*caK>yL_aXwq5-3AWt$~|Indtph5rTqM5me$WryC zt*mOr58K_t^S+KsW3@krm)5!qa;%8c;unKvb%)H?>eZ+&;TQHB#33RtASga8ZTJWX2}T?aRUJ z4eC{={nm{NOU2tL9vGj;Yi|L zRYUR+=I;W7g|d_T=+(g=+YXlt%z0Fm)%TmnKaAH-u!cvwcNc!wCUDcW1XN7~x7L!U@%_jI(N2fFp2X}s?H^JV|WJl_wk4D;~6 zH0WNAA)O(e(x?oxuO71!8I{O4$e@mj_k|&E3A443!ZCYCT-$1!?YZ!Jcbk!=?@v?sreCi6WU55K?N}yZ73Qh zx+3hS^`>cA<*<=;Uk*t7bG5goLt_IS^Eg>?B^mXbpH4{*)RpR@Bf6O}9nYWcU%6uyQ^{I0*t}c_w5d;;?31bXN!xR2%n){cs zxXM#%Rw(!97^|XEIN2QSw)Q%$2n1=K0OezNj45`U?{jkAl9`!L8DHEt(|<80O7nH8 zLF2+tel*~pE>rSqEc2?Yn7U+ zFYI$hicxulA9Lrj`x;K(;l^mKHzDh>Zb9A~TNF*TWW_%*-)t^%G+iaa;VDFcdXVzNM77wf&&7;5^@gi75;;r3RlDq1;6~r%&>--p5=x zz0aK0rqjHs=?|QHc!yt8Q|HR%5Ljs2|ElQ>7L=ovjUA&cD=yEg(`2yEyxV`w>mO@d zj!*e8A`7!K5BapH$2rRzR5(d@!fdY`v=#B+8MHBQFSP8~qfR@fW0kIQ!elVTWWXT1 zi6B=-Yr!I-tXy+kvXe&RgSIEbOwM75dsuB2!m`o^ZM+D%EF+GJS<~{%pW=2Wrwo_1 zk_9{3+HGOBpL{KM)Mi9Q0Ytx8+(|sGPsTIw9=pOGZ&#HFuH@8d8e6`ekzlG^4pTlU zb^osSJDUV{5i!i}%T9SQhYK_q6Vq+W$YZn92+tWmKm{QoN1b~8u%Wb%|7yDMz=Un% zSamhaVzPxaar4q8O8y1Z!dYkaXc<@u6@_NUU7kOAmFml_X7wrdL*Q+>bTVc8+t)oT zR5lkHC?OhhZp+{#A2!mtW-7%&T(*N=&=*xky{7t5t&@>#5lO7iJJ=>GSiCS0EJyFS zQnVqkdU;uYN=3JY(?A|VNjYc*y4cw3 ziPjKp(=H-6vofQj`f{Xk*OoU>Uz$1=Ih=wv`?}tltUxLqX6|%1<$^h7e4g2&hTH4n z9*_948P9jvmDpPIHh<@tWWIr=>Th9Z@joJ^eLu(s!|q^#;%$g?E|0S`@SvdadYbZ1 z-}L^ISZ%I;vpXxS2zHqcl?$b+Ut9Ly0DYHeym%9Kr+*|=;g|ntKKswa_@%_3E;L{{ z=qSkjfFBL)Iir{V*_8(A2}U=_s!)svEtGDwXVFS@^L zVa%rhuWmh3P*!erdj2$4z-^D25|m}V-g4crUlelB$UL)7c(>1G%2;U4hYu`Xnc3NB zFa-kdvEzNl_741G;4Op)(aU})-4iq^Ljx8^ni(4peb*wlc!GO{oSYo&HzXt^H*Uno z#$u&w>&Zs&x>VKFG=2L=(mkn4Xc*)YRm-JOb|UYOOUeli7t*@t4M-tbV?RCY0aK>+0$PXONG# zcNwVpVxd%!;TWs5PAMoTK%ovxje9{?D@Xs|oO)kAj%~c0;yHsp^@fQKgmiH1L6=&< zi$Nm7T|z=)2TW{s^B*f_GZNjiyNy7zh%2cM?X;U(9qChNWOs$h>?*|CgIT?ukYW#8$rbZSc0HbqPnuuY^2iqv)6@a7ELwa zKtI3u!pni{E@LU3xef|0VAestaw8>F0EjN+mjLRzxw?{D@GvmUgF&C*;>Fm9`Ynav ziM({(3MeH!2_^_I0VnX{2;*{bRY2AZTtA8YE)F1}eE9GIIO=^nsvtgJA@$Y7(64Pr zoB&r5=webWr=LJ_w2Sqc#i-rb^;;s41t8xzfNh7%a;&tx{AeF2IJN@f6{!#BL*t&? z3Q{D zY$WXW>WdHfd^Ax=Mf3}P^e-^y--oFQi79?i4uDrta9K!6N%grYMT-${8t7%jmViOuexT$q8pIFK|TTMr!WpG|Jm#vf%YQ!EtKlol0rFW+HiX6EA? zftA(NWcc&5H)Mu|aZ$4k-)%E1t|o0g7}SzD^$pr2j0@nyJ`S?O5PyKF^{-wPKXI>B z7+8#VJx#T|PU96Ftqg`G8JUobj10nCPb|eurR#J*T?jwi^ojuj!@tivpa~ppZ}3Xlqa58 zSrPoNU0^%g0RDpFAL>hheeY>XGps*o_4YRS1b$<6p{z>qi~zYF1b>{K9z@!V;^H2- zzI_u-lLK$uym^EJr0mtRQozRX?&9d^D8<;Pd{dZMJz%gii49Rg zDc!&K_py~-5W~{*&l;(xt{8%hgvk3E#jFnI91s$Wz`zy2O}2#Sm;!8RB~2t}s?AzzPnrcOE@bvohBY z{PbsC#z|4fznR!ibP_1&VPRsb$%%%KNkK`>lcJ)c3l}ax))!w}0%Fp$XMVxKsAEM) z&$7SfZHS!vyK({YAB0deZv*VJ5EDRL-dP!k9oYc$5NIB4Vh3^6?L;os z{tamT8ZhF#ij%bz43b)e)==AGIXhn zqu%r|3smmBL~YIO!L4F)gHc+okS#x6{nXtl<38Lr^7(hgd`JfRw=@SI4So}+dk>7~ zJ3YTh!Nq46m-#DA6KNp%=l-L}qOWaQZr^9OlSg1;Z996_ayeWvmUytV+m3hi(0QIz*w1I0EIZ@=&gVhuS{~l{%pBQ?rIvt$TsC1pNTlLZ z*mLmx!1oC5R~P56{zi{_AhWXD{ht*R1&S&LlwsD`58e;#2*k_O8J5@DepEU%Zct*;YZb%{3YM+QJkd4jUO-96Sxzz?Yr@2oNv2_ z=HK{y@H!q(xmae9!Xi^05}})4j6FWov^2M?r^!`0+0XxI?)+ZV7{Tm(Ff?mM8ShO< zAh4GjX!xn%e0><&MXXW0DEBVw!a=hLtzqr(*uYrh7=y{)uU@fZRi%i63O!aY!%FiqJS z^=wUY|2Oh+{^pOdwD8TODYX!|qq|=ciSGU)i~9n}oU!Mi|7HDBKhd@OR= zklmu>O53^DPvP>n_sUht%F5x5DqmCD-2!#+8T0?bUJ#jn+J2tpGdV`dhNC9GJpC?f z&e-j=2fBE+Y%40;$6K{Y`<3eBhDRl&kr=@mr%xqtPwCCUhHoOcH2SQ*=lM)cvniqm zztcFb2$s4WCv)^G3NE2*m$!-n9SqdfhB4;sPKDAb_In6VlwE7Pt&8)dRrbw&J*MEzi{p~;7>brtR;Trv>*`)YPX{&D@Khu1U2f?N z*RV!vwRRh^gTV!KyPzAUQbS?7H3H27`;wZPOCX9#;;mDW-_O$Q9({v4OPSmVkBUd&7e4FMo&h7ch@F4>i`MBs+`-U&qMXmmDNg zkQ^ed#6ZXhM#&2q)fZi$&h9r*t*0CX8;5GQVnLE`M*a`uOm%(Hp$?9X-q6Kr`;@-s zQJ2M90&vxws7~WAD+~Wd z4^F?Ji-Rztj3s7zA&WZWQ;wBk5DRXwxBn%)y!|JD3aTnbMnD>(I5>zV0L0Jy`t59oHeEhxld1hBm zQeP5u`ot&MnSV1+Fus616<96-jxA%b-$!&yiSY%{D`8<_FwcL9hHMw)ydd+n;-LtC z4xW&)y7TBSd%OsgDS^9STV@q(4T6I8ki!RLeCcyI?PWTI0K{^XIhecq(r0xT6qFv|8!^XA|XIb~ao*BO8 z+!dxsCNR~~(arp=5)Nu-o;-O1kQZ22)&dMm7dF=iv_`8~PaHg)P*NHk+|Ij#EofVT zItECNL1LX%wRj4Wmg)IW+B!jitsUQ989(lkWKDQvFM)f7jI7F}pAnQQnkQOXV2<7Z ze;>@RVl!rwu6L3Ly+7Xnx}vmGZ@h``0RgI^N4@ele>XHECRL?5VItUgeh0~Qeg}HSv*t4tmPrkYqi6JB_S~lmoH%zSmHd_- zv{FRn%wP(00g@|(!x|uV$Rq8Tw1jfu5HULh1ugNgGtR>PSzz(%iH>OuWn`*!U#^flewf z!<8ASO7vTSFJmy*zY?#wvLA|lDmqC?K)ty%#`uBwCHM+B9^j%hQ)FBm1qB5Yr3uV7 z2dJ#T1fcVQG=u6Sjbw$I3#|VF6VRoRzK1^bQVm-@wKYg^O=9nYv3KA^E|Li!J3^&r z^UUEnmUnceYy01l@Tv_}ocDa{3SJ%%l&GO(7}Q7;j9Su@yrrlF@Mh0`a9M^0#Rtxv zQp_O~%!M-$r-2BCl?n#Fb|&zWUb*tXZmtVVEiu(B2*m2~P|Z#yU4E^{1ik0$>x9p* zF17#CuaWu13%med?(@ao-PQK{kTlN(y1$hJ1 zTie-O&xM4};^5FI5Pm;6dY|Deck_YJ_clF&mHN+mGgEQR_g%RSXHq4>pTKF3W_R<8 zyuLL<5`>-fb1_iQ36+{1O)XH=23`onxwF3?WlZp?>t3SUDkzuL+p8l7hO#m+wtGf9a7%ym)<4}+?(;f#thk)JZ5I}^;qIJ@af{|QMbEA1Gu<(_XD+C+R zR=nPVw}^z46r{h@q@)QbZG`tPE-ajbvOi_0|NcTC2o<@QVn%qd%*4~&sb85DPj0DJ z+s#8AlQxLoQ1$|WhBaUsbOE_67`SAp56nKN0)ku0$B*FN0zn8|R1UlA`oexvbb$c@ zHda>f?Uq(ng|}?((9`pR6rrMW>H7Vb;Gr`iDW)#b{dKsvl|sFV=?^57Q&v`%lhXkm z%hFPo6$+&2yr3F-E**Q^2Ft6xR(GwC6zxNLl0ev3T3cHg0`@@g-QS#-fAQim_ICG! z-w#mex$YDwa|f9gHi;(itG)Vs2Du9g>Ns*C?>qt3_v!T$-;!&sg91#YzJk)N4yWi1^WDw|X62b`(U~+@Y*~#gBY%Ih`s4}49vC)G{ z3Meyjg|%B!T#QSz#4>e@bA;Y~bM6K7F$@Z&RRBoncw4os8zF$v^^dU9swvzvrnDVQY_BcmVX=IZbam_YrkQ@3OsH5aG{ zKJX)w;*u(${rO`O{569vP{;)JsZd=5din;GfP%|w#N;d#8-adk3uWQ(1+du#goIqa zbg2{s^ok0C%a=cZeK3I=Oq-xsFD@-X0SUX~vIdg9wz~QeGjm>56%UjrW2-@v8({y2 zf})#*a5zDE&0BxBBo4Dm*?4-W8G%pPL1HHz&sZDu(dWQA0d$j8e&>P8rK{{r%JT#fulvqi}LhM@!2`!+c}W ze#8O{1RS~mr!PS6?HEo#g0kJK!cdF@kAZ3<5N<)V1{5ZA)5yrkFEq3QR$Oth8axVY zl2X#r!C2b7INC&3X($9oF}7%s@6 zL4L@1Ckx`mz~CT!y;iML_t+Q=;8v`1k3|V&CpM+<)RNQJFGKCx_SV*tU7Y4U5%m?} zXy%f5l5wY;bf+50KN5o8vv?8;!*;sSEk@lf@(HSc;jDPI1EEh2hJaWDjDV$Jcto>*eFteAm{uON_&Qn-dQ*%yC==cByyUofvXdi z7;M~b5MAIHn*3v;&s0#2bPe~6w(HtAD1k|p%Suet20I-DCEh`Fb2vSu1^J*j2M$ny z^auc@W6-Z5=umT*D9n=IyL;El);7gu9D5EI6!DcWuyb&1&2@`}4`8cuAb!?E;bH<) z`o2`cqsaNIo8dD}K2%?1JT1O1UazInzMtWWf5(pKu<}xL0vG`SspaM7&W$e2&PGEC zx0BMB5?>7#M=Pt}6K@FmYO$wGJi84xENpd^U_)l+T`1j$7Xokz6c`CSV>@|J z_bH)($KSsh2Fr4^Ix;Nm)>VI)wxst|ZbrBA_N_zhBerVu#tkpwWMAK=g8HNEbTviG z+EL2kY=dcC5k=lmYQf8JGF)MymA(Ba9DGIN^?_KX-!RpgpLH}1j)HRDU#buby8d%= zas#r0rga1yf_!RAXB5xZl7n2$-k_4}y7ucVe}p)0vKWejocujwI`2&-jL#VLvo<+m z7LK6EO+xG$4hnf)%L=*IM4eq+R^ULlQRyQnIm1?2y2poyr`%v7X8W8STTy0S0x9d` z!xfMDcJKsBj9-lo3)6vfw(34FE}GfeZouS$k2^vEEv)x!t=H+uLp;;K2) zUv-L}-L7`sU5Bp6k{>7NHY$|Iah(QBz3psBU|=hpKhj^1SIq#c4>0Hv>{5UdAVso* z+R^$mUk;VOY!4qk>a(dK+RV;Y+VFQ79?0cWFU+Q#gH#Zt4#8y&4o*0lt)5-UA(LvW zrgT(1gk!{)oQf*X;dS-`m_{@T2}SY}2>7?>p9KfdZ%%gJ3u z#UB;t0PW)-mb+GF(w_}`8JtT6=YPm%YY9JA6sHW1#7N31`mA?kWo9OgYvxG9iED&c zuYNqz?2^t?uLyB>1@paV!!=P9)HFg(u33$LcGPe}lCokMWo)Ig^qXunoFXEy%O)mw z&3>kh>?5a=L+M{HIOH4A=;mZ8YXZA69Npys zTM{gLn(PdnrOj3b1FwFou>n9x;3K`u^3Zg@KLNvZ080|mc>u1)VDFC}NYBgC<3;r@ zE-ucU7fycb?&$RvQUj1P^?P#b-LuX4jKm(Y^X2cjrprr$-m!OD1G_I z3sf+FD@x8z02BH}Z{cqbpq4txo!+kKgAzJns*)%%Wbcbe5s{HOfs?ev+2^4#>JCtb zhz&H*HH}S8K-ns=1+3Uu$f|8&X4dwM|C1(UCpZ6qz-4G+5^!3)24Dvypz5Hi88VSR zKIgtI@t*oaD7+n#ccQmmn3yoSy$OMw4A`U7((WAIb2A(RdjVP|?B&a@m}95N95C*~ z1;JNJTpUUQCG_>vVq#Qt46p?9EFMXw@pEZ!n<~Crw{8Kfh2%G!bK(pw)K+t@xdS^7 z2RnNgQx}myY1&A7Y?y-iM+rCw2DYK6PoF|A{Et5xV0yz*Rv&j~G%bf38j=AvBqe=n zZk|sw&vu?%TK=K5a5n^BaS6_+Xw@rjX_0tj2Bn-rYYH`qFT@sJ)Jx9S$$gsymueUD+mz`EJq+&t*?IQpW%Un{4iL`R6LaEL$o_P>VZ z-y_s$!kfW@O@GxN)C%agxg18Q2A;h~tH&I}l(D z4GgXd!>MicP$lZn`rJZZT0EQcg(zKk^R$is6P^Eywf6w$^6%TnFQbfvik8HuDA^=J zMvCl_y(J0R8KsPhgocJhWMt1|E32p|WhR*^Wkf2Y6n^KW@An?hbN`;_e;ogx<37H1 zi_ho!T;u&dU+3#Q&zFtOB#`Nlqxgfe#a+(jy$pVa#a&5Zr#jlxvN(}f1X=})EVdu) z!+BPfW(8`0pPp`Q&zzs>ZDEgT5@l1+vQAGg96TlNuHa^zQEqpD-A^+mIT_T>I;@)> zfY%+_(O0hMJTQJxczyFLO3m)+*`T)JbP4B4B#*>PI3C0&hL;-pib+_EKYsYotkd!O zwaS45veMF6>#wS^ty!RW+< zJR)82TGwXsa-BQUvf|TnI<{r?^^)m)@SIy)_hSn~5qbi~@^RNZ&GJkXh0_zg=3m<( z+nB{hI#+OB2wiSL_$6R7P)c%tbMMg9j*NW?Az7T+S@yeRu|0+2x?y+S0JQuqejrQ! zE_27-faq;JJU@Q^#GS3iv$|fZYvaVel`L0`WcPMx8_{$co%KuE7r4IS_U4{f8rDDZ zPg#aVVU5PZ_2Sj5K)89(Q@6CRs7P0FX+5_uWC*zk$LBtXB25I_UdaRI?3bJ4cS22~ z>`LRH>~XEV_L#?!x2$#Qx>pt+)L`k_EwfGdsw#-K)Pp0C3}Mx`6E}sm8oN8L3|KaH zYatUevyJf4I66w(J&S}7m~VL^sGMQ*9Sjr}E_py7#3ux^8jgcy`nL)S&5S7_Ny*ps z^+%9JSCHl4;K0`gB5-(JTAPdPZi#I#AB{A(w~HQrauGWb02Vss*Q*z{1^^A?KB$j7 zE*PxmW^`!0i$+nP*}QA5pTJ(ZnJ4PuvNZ9|x0$v4SB5(_+%GJQ(m;C5P1F^@vNOJs zlI}w`1MHFsK=|0d&-zXEFDqd>Tly$T%)>}4G_C4970vSIY-9-Wxsiq$W5KmLw?va7 z9wf`!w1d+Q61WvpdT<{Z+3MspdJ5Yq04S^`0tmL*z54`2B~$Gdg0)%Xq3c>(i(GFQ zE)M|(dLzNx*Vp(3ebZ(D5p2+46%{CUaMPe`3+Ccz1s^I*-LTY3#I?cSHU4&&-})(( zjKD-F`LWJwc6My!NZY5ce-5Y0)^-aeB{lU3U~^-XK3jd3qbDQ^U=k2LQ-VAZzxH1+ zAst8q<7gwzT&MmhUhHdoJC=9jOamu-`;S9Ikhv*8Ee6=T86DmI_ASmZ|AZ_hn9PlU z5@Yk`&4>ks_i41-@jrrp1`1FcDsL1OpbwPb%CrJE@)bFIo<$xTT8cT?{+-QFIg?u|&GEbpi~&PwMurSw9UKbu&xc#VCn6 zc@MvdDJ-+gmM=da9L!f`aK0FfGhg^4`rVWdc)VAwT7{%UEYhXJ8(zXGQtqt=%7x%_ z-)+fZGaRkmG65n-)8 z-wBr^58M;VTnDV& zT~$tpMM=Df@ADUZT;6x$Q@k%~2`;E5kO@FKxNx@tXp-p$k(7PI8b?9r-^yFH{@h-7 zLie0?!L+W$=fDA1Z>%BetpCuBYB<33HwL5pTaYl`ibdh@XY6}7v!1o=PHIffpKy8IQ zJ|$I6O(uU4@O`#Ji?z4P{JCrBhyZCUrA z^?>V#;;*b{EwRAzxL@<7IwYfvEG+4>EWMPcUdk`-KJXmzU%hG5?}1vHGy&>y0TGee zsVSadurvrQ<5w^=H9h%b@=zKh%@e4Uo?&_6W+hpg;K;wC@q#09d})a9T>I{M>1QwM zD*p55Mfe88e17eqVgvLrEAQVw;6N2*#450>K2*%( zqTlzG;=Ep}C|RI*T%&XWa1)-&Tf%gN3EjB?&b0i)gE+|?cIv~l;mIl&*B?51^g!U) zY9dH{%E;%|!lkgo?YBcCcO$Hc@0F)wcFjE65fvW*`7l2|YJ_;YDImqBqZmtx+28&LE3o;jCTSYz)1$xD;>=l=}bjLG+7^ATa6y6%}0F zOtb2uBCn1ta7{*2b7*m)i0J6(sL0tstPkBg>00~ovZAYZ=2;(#{v!=%={pc=Gl$JJ0<4}cWscNBPxSUx++b?dtO`<588`=P@hdzwD4i5k-897 zQR6H{>6X#jJBuq}S+Sw;$&qN{_ZgE+*@`Q^SmhaGR=>UbDrn(yyx5cB6v8iFP!_Sa=dHAn8)d&cD?bF?M(FmIju6R!h5uwn6W>r-E9 zy8Ei^^J>Lc+(zPR5&Jsu%155vQ1sYdR3QC>S}_#g&L6Y9_~+X-^%VP(m2EVN+qsSI zD}PF+s8lAg+o{X9U9o#ougOG6)Tyr>X;zfPw}tG~`&z3#?D8%S&;*IsslRSXp#gi} zyjGl7VZ`@$Yjqh@Vn3^Zsk)&%j<0A%%(c)TJ56%9&ix`zD=uDRWV;e12PAv-#*HE< zQn9>>@=Lc2fxKir6yJf}2J%L_OrD;Yl zCxThGu+r1puK8%c;cqPf?`=3v1uZKi;M?aZ0f|l=ho*in$)+o0X^MDOX3&G zVC)mGyri2g@eCoy3j)&#L`l(uvr0hqg@O_09m5v5fs8IAboBj zV^VFe`EJRn_2>ON-hbz%A_Rj?8a7;DPGr2ia{gRVyWX>Y!WrUf75p?+3zb1_L6VMW zNjH0$84|Xj#jqAkzy`n}UXktbsQJGE4(LbQY>a4O^W$v!WMa=tw@eWKZpqzrcZ(`Qk1-Km%L}g2uyQK0Z{pZ=*8Q;{tslXunDc?y zPp7-=>GJJ1d^hDxPW?Qye@l$$AtgLU@P#UJzp3!f1_Gm`pp`>LHt8g+rKd$yYWKZE z=c1z63sb2x&X_b%{rNbOhh5H6J*vtPxvGjA#RH%kQNY;H$pj-5+rg|rijI!uNN@ti z12BQX!T!h*v4fPLZU6Y7wc6|5h8SloVz{rWB7m#Vp=FB_^3jW2fir0-ph80pOCnkTu#;7C}Fk^hA>xcaN_KY!Mw z2aIa*I7GzmL$pKlSx|^r=ihX9BcrP#E35I(dWOmbtajOs(4ko_D}i2CVh;xisP zLpu0HEF?sRARtJ~LiiQ3sxMuVgPi~y)ZV?d zi@#qjikit2+dU?z8{wnJ3KAO=gT!YCbO5I8WU$#@RpklyMx-OoIT~AuPX5V$lV%-r z!I6*-1Ef91mBz)Khx6pEYxXFY4eCs6AcD$NW0`X)3k$Q=Xuu^TXCOU*%uVfft4`$$ zuTr~LR(8uOy}aC%kBzj~fRlRj<_EMNz!?>Sn=9A@BE0V+LqMB-idjljG*Kkct|Bj5 z7KJ>R^C8cl0Mj@llCC|fdIpAuQ3VBGp`#e~mS6bs9%>4Wra3lcm?zK}jCbM6HnSF7 z+x_MZ=@mh7i@pYq1uJ=ONj&&AWc%U?ME3>pXlUbTXhaD6sIO~|wwxJmIVZn*cu@dx z0=M#31PM*jh0z!&hc3=8E+pV}{Qc(v1OQAI2kTdaCxf^aVWmIMH_~6d7`X7AD?GUh zxEl$ypvn4RrI+y-49@Fc?nP7AIALUL932;@sq)v-hBN5+fPSC834B-!~~&|^N4R84on>Jm_&ER#N52pOaWnl5)yE4i1G5m zezOBrE*=A>_LW4%wWz3KWEc3^lDi=o<+kVjsNRv6hA=zid{m{S+2a>RJHI&m3T8!E zUHxG?I=Xs6>7qxEl+Gx^zmjNT3;1kiCWFAnyoc6=&8?D!Q|Bh`e!M;hfd_(skxz0p zIy&71Jv^M2{S_REkiVc6jC&I643atCgRS2YE`x-Vf&ve$j;^Dj6X*JEdk2QO(dI7) zz6U8XTsxGKl5%zHfmWSeQc^64=EJRDXy25apQ=|K@Srlv>GisZdT>Jq2CXHf_m?`E z2+8yPW!20N+!io4*U#2-|FH|6A4H!_egCdM!J~?-TyJlLLg8d!6~LWAeI_v}i6SrG z2QfioqZ4W%V85Nab{)CrNiZLJckz5|WP_b&xy6>N>({T}<3DHc^A5+peUCAw1CJAl zE9b#4jLdPmB(RdKCfINU@sm*!Wo0K|>}Y&N=Ci~~I3k{5%Hagw9Q4w$Ssoqx?aPM4 zr^qj_spIa%{F&lkHqJ2*gR&ahSrAHRsm71qIb?~)qkvhs2bimOZnwN+J-C4<%Yx+)KtO}7V#V|MZK zDgq6q%f}YB9|QoX*4~osGMRaKm+#nISjZXaQiDtY4@084*N_`yWv=2^dJ_$9R#v6A z^C=jbf+z;m6K`OHitk+ZLLUd{d%eMq?AoZSSDcy^rquQHoJK1WY+*-drohj%oE#Wa zT*w&G=(TDD;%&%aeZ_-qt)0*4a?Q3 zTm69*_vr4^cfM1gCF<1Y4G@J6eGM4*TeojtuMT*Tdx!eYz8pJ_i*cT-@{SUT6r<5} zwd>nBkyV456n7O*;QTG%Iu0%_l4%HB{MFB7%pe$K(x81|hsBvd8sY}|E8r(CZ`k?d z(WB&h_nPs5d=*1#I5s9DL&JFK<0|}7;+ES)!J0IQW;EKDIZ!3$<~>z^VcwtuyA*#E zg0zv%Y?}A#^Md{CXb z^iRxVLIlA3+K&nt`x-j+AW2*l>Z$m|8tC-eCJSfD=S7)AJnTgic6HLBl> z6SpZw)c2@uc||o8mPh>DS;kVM4KR^|=@Wvr^>%4oG3ymsFk*uIk$a5BPp(e8(Q*Z~ z;Z;m9f5PNKQ_>}Y+I2z3e}5ywW#0>nO=)xk3`lb^!n}%^!;-HGgnFqJ&Hs8?i=TkuaxSXbxd zXmYbcB{TYQNTR(y%c0kRgSZEx{eOW^JuSFSyh>y$tTffyB&xEf*2sywj@feUDW#K*-!4uItg+;8x0 zPXeNwYphC4D_3eQwBJ3zGIZ5CZ2x`R`fv-(>&D5?9~gb300v z=U)X?;xU5AvPWYL^dzJes0Uo6)U>scN1K5b3ko(g2US8_(2XLsVE>^1(IC)rJZK1I zDsA@xY^yeVv{E>cujcvmEEOYol4KcMt!wqy&pOgg!esBuIK1xq7LxiVk`vClz- zGjd%8$;4=+-{^dZS{2zwa419C26@fH%F5aC?&u{MVFW(xiA#e8;Cpa%J47}hoEBuu z$WsWNKp!J>pG_Ha-T?U9p3l$EAANC4&)RzNL&KWDz(6Hc{7UxCdRt`keh2wJ!i6;a z|1QI79UZz1E@g4SzuY1KVyt!RqR~BSeGUl~ywBMVriS_=x%?QIP*+F3HJfsS-F-M3 z+nz%?d@DX)OF?+Y4oWac_tGq_#~XiyW%h6Vy`bca?5!ANhkYHQm%tAnoXzHF128#neVqSgM0r z&nP0w9XVrVs9*3;VwRks4bx6>2eT&Wl95_J=Rj~yPfv@-X!5bGRsvUGkgKLcrA&`^ z4vzeT8MDpG(H;b7MBykZ+FVm(gMt|u-$@DLqCctw34>ix2?_aXh8W*~FL1tC6Oihh znUf;{kg;>;F$af4W8GcbuWs9gQ9^4NLjcu~PjyC@@8YFPM=CZEHk@Du&m-LK-`h4K zy>*a1Ay*Bf3=EmXkStalyH@+ZbZ!~80=yvdszWMO%@A#wuC6ZBD}ZbO4%BCAnwuk8 z2gk?b(N&~(bah=A&CY-8zaqAMvUQ#y;%0vTM4C)k7(-hKK|J`=#ocP;(~7<`YT!{k zA&_}Ewex97s{J>37+$3ri%B)Mwu7)Vqap%_G!2zG-yJv$;s3o?RK!G2uiMtHkqrUe zf6#_8P!jxSOs%Z$gocJzS67qG;pt;0G{mr&j8UsGEfv8RjJqQwX0ZM*S@=g z=m{Zh60rw&(#wPA!Lee@+1yhsjaN8jZ&p>h{eLbPhreAS6n&S5Ek*H#%YZ97yKKcU z*T{~oYz5*XB1mRFHgy=v9Lxgr#q%E=iLC^s@BDkNMQ(Csnb=E+Jg?|3ayLDXy}8GyutxSVT+EmY~rDUl7gtk~lk>-6;~XVbf726d8t+vg3ugF^gCo(c0dpYdKj#G)OWxht*@uTM zse^pTF;hV@i-?8~QF;fN8)ESDhI0YDg@rG(u3opU6J$qyBWSx{xc35}GlV#gzju(rwWoh#0rhQmmTPb;KF@7;3oi&#}_Sx1kZ)y+OQRV zL*3T~s7U_ZOAm0Mwive(ZYFl}UGe9#{|A58sG;x!g2Cwk1qFurHn|$H7ewseBJDmv zv>7^tn|CNZzylx&?WA*;c-ji8Z9t|$mr-PD-q}M=dctA{dJ~)CA~@a-w?Qyt*RHir z=%eV&MS4k24(W0SLVzuPSAI&bJ#-RCwahuWHU30cw0ylmp=E#E)tjc;5pE9+^_{y@ zy%N1VJbn(}y#h-4+xPD=dGzZ^pH&5tKh)4N!8Q{Ar)LL}g#&g1@Q$**HhcG;K_mq# zW=aZ<2|I`L18sf%>*sUHL3McC0>_IxWh`0l-TWAOX7gBD{3N=9NW?^l$PeU>fZw@_ zxr?~KfNK@+i-S1$Y~)TKOk~u5s&c^ESU4J*QF5Y0mJ!^55f?9_OhpNZ6NlziBCsHT zBjQf*z92sEm>OCwaxMNi09_^oknu}jP-Q)8uAZSj%6DJUV@fpjE6aQ%_cri{3u6dpOou_7;GYv=vGVNQ5 zPI0%mvff6cye!iKlQ_TvR@UZhV-Yl5>p8lh62+;}t<34Pr)6O9tbHw4{&vSJg2`T0uqpQufK_@M$dBb_St)ns4he$ zG8)?s0b$TnU{N_({0Ql#NP_`x*vP>FDLD!N@IQRv-)3g8w7WgH{Tp5jq@K#p@5TT+ zX(QxUDg^w#m7LMjV}VaD>pP*##(TX1_oHThTZt)@OXMmt^$`{dArX;uK7L-_`o2CZ z{}Al!An(v?CU*>gX0+D~D}$A?)8D$7es46~C9pOEoEdxoBvA$bRy~LGf9DK;w33MS z`t>%D$)x-kBf%hrCa2v(ZjSc`l!su0)9K`3T^Ol>0Q>{ju#~@273(Bhblj{XXE&2U z@jks97#ovgS~xm3hTbJ0>3pk6W-g0{;94kuT0^@KGW!NvtT}IJL1Q;5x%i&VI&8i# z+$2mf^C>D_REP%e)N{aA3sO?Rhc0{tJIXn^ee{(=cQ~2sf~^ENI^*S&M##P50xWcO zZJeD?V}VDNKICG)%iO@g?$DvVvrJ+2gXkdpog`V56qJBkA#BRIX2nkUQPgy#-YY9w zcX~9-?Daj*T{=6yghEU*cd6*D9ePL@8YALjD!4ZPA9Bzq$$X=jMQMrAC*4{G#TEtz z`{}X51awC`n7bVCy_~h&u=qH@zVhW1zENxtqlZ)1DhL*sJhX4xIJ65FC-0qniiB)1 zM8WFy1-VXiCCX3LF#?42GaLDdTOB}(iDwRnZ~+kcRZ24j{A zBkkFsAOh`Ce6g^w=&KvpPWlVw2hFK2QS#wN3LDCIGSw zIWbTw{ie4BBi%eRe-iT$u}VOz3yEo|j9FIJ&0RSba>{|%boo;H=_xz{0>{9XKwrwU z8ghhmuk)ueL0X3dG?OH5hX(Wu!g*?!th z(7Q`d*|u#PJVn?7rV6)Qy};^;S$AkO8F6e}@Ac8z`ix@YiA~r5Hg1Gk;ufZ^fwhHP z6EnJunn=kiribaaCB`zMjE5N#O%)V|I4|F^>{b_f4yCsj<){s1#TusmM-bm~`g>mK zXDoquATj2!!IG1+S338#-X<(C4X<8BH`sw7_Il$tIdEoh2i_Ax*EtWA_Mb-oT_U=Y zh4QVle_1Z1&ZP}<-Tt4|p4d_D zCcqhzAmP{w;}iScOJKMF>4I4y41pm?yV@1xEJ~Jr`_2J(z(u0So%m&w@&6_WMG1br zZ@<=1qfVxi>Gj4AiR^IAZP%XP8J*C)Sw_X#*yAuV82Mg_pm z#+Kn!cvm+4?)Yw5S&aNpK5ziU!o&ObJ*P)I!nIIwqsC#N;3&!AoJ;2gAo3Kb4_r}n zS~1eh0eo+4pbS<5Cm+>y08PhH(xXQ+#eTDTap9DS$t|$5Iy%M|lc`x!m$am0T(vN! zyvAcSyLWFA$QSa4$(fldJdN7g%=6ApPH;|U8}RRfOy%1*tiQ>!46qDiRGpxZ5Dhi8 z%-3YpK`@ix&caTK-kuyt^~_AiYcJgylUXVc*vW`)00T4&02NWmdtq|~?7_O$ zVca*G>0|yn#dEr;BvVwrF}CzH`gG9DDJUoa_gBx4yMf@+#s~dWJd*%OeUje}8{cBQZv*nf_Hf7oUA#UU(j`9mX^qH=eclsHh_@F1bJD z+dr@#tln3_{BE@w1HkW!6>A3GA61y6J)^_;)^_wwbNXR%l%%*;;LkPJQ8U3uR#;q& zI$75u=#4+mYBevfDXh>Hze0*YcI-o8PAZMi<}#D(Xl^FckkCcN%Dn-#1r&j&ehRJ| zX)D)WV|lWAs)R&|Cz?7tr6eS7jPMh?U)0svA>ImwXfMK;^z^Rwk~jw##a$e9lA1hOg$ci=4Ed%tclN`FzdoXFkf*7mF)~bZPkZFxIhYNoKc%-6fQD ze8{>TK$!4}k#yO(G?$lB`^ zKY!K6$@1}$oG&wU8v>Jx&LZFShV=r>#2Z?2_BL`RQ&XWZ^(_Alga}fh@o!n1Smh%) z%O88C5;c49a`;KOLfsyIRdI0{$J+M{RVHwv^`CASwz2csw1m%6?d%O_l?I~iF&YR( zxQrv+VwUq#NYN-{WN6642$gG5eo&154zlHc&A7n#gN&}U6|_VN z`D#JYCXf*0!N!oby?d!BACRX6DI71w4(3hN)ixC}gv|=F$~+N29zjhH%E z_TWV6axGjP#)Bo1KMK)jV6^sayAGxkVf|C%-BK8IfI+I`+wcehfMRLokZ@>*2?UK` zdP>AvA#$*wvvUr-Lu6@4$%^%JG>nysii`V>$O8X3iZZ~=!<{))KiBGO!mN~`|X=&crtEx*dRxSAT37MDkDE1 z3I1VAf))IV;d9%9H(gynL0L>)0SAGJ3;X~s&d$iT!zKVNisQ5=mbCxsavB-x>+3@` zXjqh!wL>ebH6`=Eq3@oFl08q`zpM%f-23!{C#gk8Y~3wkTE%rgd@hgA{Zh{P9RVI0 za@nc*HWr27&HP5&czIi{fO1Aq%#kCw)6=<{pO3h`bdmatW}S1I9UQcsdkV8clJ1H3 zPgaiR7aZ(@Y!+&j;iru!wGH(*8l|e~BQp>cEO1p$W~N@T5FTPKU^dKl^@o9g6p>?F zBRibzR9+%g@rNHQ1bDa{Ifm5%L1&3vvtylZc=j7#%>YOSD86E_FgBhAoJ`W)ZBs+| zm7^DtbrWo}ssf*&AT;`o*1q;mPU?YlvEN9J6^e8^D5 z#R)22aGa!<75_u)8s63o7&y`TnovxDyb|5HljsLyL7uu+R#t}f9tvF{q}1V{U)-c4 z1kads#V(b6ZKwV5$j;6A#b|D0V`L!DR@Q5S)73GmJX?bC3$<{yb~K`N!>x?!11%eL zG(oTI@%%tPf8$K;qUEaWtjyoPPm@<}hmtBhKKO!e0T>I_7w!OfHE)zIBmAdPMYz1V z_l}fWh$yER>g;U;KJn;k!1_)P{hv2e5o&uZM$D4F?n>>ZCCL%EV&wPR&A zZYxxOux$Y%;^?qTol&%bci73CXx{m^{Kp331emg19UU2%nX52-6sr|!3yA-;#fU#^5J5K1TQ5mtwbh@iqQF+oOP=Ge?!iu(B&BJ0%aU40W`qM#pQ-WK60cO z<5!TX0G)VA?^e9G_91Fc zlpv%b1y4R^+<<=9zZgYB==`B^=iP4TS)?-%@rnmd_AYJ~o32QV25S3Dnb%gzBO@&h zu;>QliC|KZUZZW-IWgK0*AA6^Fe|_nX2U}>)ZW)u)jhU+Sn{;&Q=g&v*6uAv)DBd( zyzW@DJ3-i7-XyJLtvE71&WS4J@Drx3cQ0E8iu_+xie}!&soj_LzeGUaQfJem-G7I! zxiou_DPA2fOg1;&BV3>4JP^-fu37#s-wc_!yIJ@F?ZjZW^x8jN)-&_BIB!8gTBH2W zAG^1<``ae`81uV-{#eMHJ#!bI3!hnog+)1s)@E6qx($0?u%slNHSwtWxF85O0jvQU z?j9FnTpmvmjQ@N&v|_JqShrJbSPJU^A{@z1EBdwXpIL0ErIR1{$9wFZostb0v9?$) z{LjNf6Znt#v&QnDFE~sj>|7goP2wIS&VgA(6w&N`A*xwRbc<%&7mq+2%3p7Tc5@N) z-YlVD=jILgRxzu<&%(m82)EE(4$Pzr`Ch)?=_($=>%7}16KD(ux(}_4eO!GDb? z*e)@LgYaa^SYi+5`35Lq3Ync2ULgA3+XR8+l9JiXKlrNmI}rR(wU zhXeM0t&rJ%dgw|@?%yY$m;8JftPy6KyzencB^=7kkFSTx_-o?}NhUKjLv+m)9FEWY z{6>fT^#ox*MXvHBv!F=WC+^7Ab4HUCR9`yy;ekXym!P~|u6 zgh9heN$(&kI*l6T^l5ajv7W^Uvj%mebFat(L0m?8`A;x(Q&+H2O)2$0toR=mg)l3z zo0H$ZscUHo2@6|c2r_yM$d?6zm4jytG81I!ilPT+e26uU=ErLW7ThO$>A^anr;f5} zOE5|rglvrAq{8M8>(ORWn;JAuafXMF1_EtO2rpl!>$wWglp&serm1B&G&@s|Y&~!p75dTcr&$;3$=s=Ix6tC@=fY5U?F~$u z3Zy4>@SV$;a2J$}eOXsY>M(1wSMZ_hjT0S{r*y!*i&rrnR5szI`9E~*Q}T`9BRBak zd1T|0C)+3#WK%d`>GDiXP zGL_mG#ACqk4RWYB;6QgeP`{A0bUDJSQMp37lmRVN@i-bO-@ktsv97W(GaDTlfezcQ z+#;`jHc$E1_-aM{w-qneRIuP;gme|sv0w)R;9y&~Zs&Z1?~}hF6&4sg4d}5Cd0tiZ zBK5Ol$2^~3{x)Y@@WXm>E_!eWNMwW%3%F_MXyw1T4#q+$X%emTwo#w$ zLOum{a9BSzW5ku`mt=2)!^0UTz%3=-ioIh5291>-E^9Uo1Y-b|0|oR&&8{F`Ji<*J z>NuugpsOPmp{u3U1heV8fq|MZjWJXxxK6lbQ2s-}VU%Z~Hs8eogby|}4lWqxI%{ zIN}&C&@XrsVX#fhrXi(eM2&{~RI3b-TJ&??)nTx;fE17VQZ6PTaq+?hRc-ABykB47 z;(T;of6EL51?(U`xF1R=G(iA00cCQ2=b+aD^o&eojVtHDji7N|;G^R?J7`A4qqB#v z1Ek)Xt<+uuNxIMyY{Kwk4B!G=(RcC_=g?77bqT5gN%iEk?${i>6&Zlx{!R&Rgxd!Q z(iBq8w|jQ&LJtjdMxfjUtAcO0SZ{jD|1dV5El~hECwxuD4{WL_{lc?sfcEs&qJYPp z4`|-?_xD4b>1Pg=J-JoYPyo)ro**V0;Bcv4fjvLRq=4Gew1=FI2CXF?_U1Nszf-4R zQ9%Qd=3MWdy3*?E3sDbiN*`|wiilJ$V_u{vnxFplE5al*0hufitW?<4Qlm5ft@BEG zhdxomzg~K1i^VGy&!-qQ) zLG8?M&zf|#xU3Q|y)3ks})5K-7qqDzeMG*j{H2zId-zjOWe&A#}++f z?$~{3$$uU$xe(Mg%I>{uO~mX)5x6XR^In)Ip;p|& zH2vCgHT3cxD*8lkWu;+5LQH$iTnX7V2PgQWnEk;r~pcADTA zUXt3KS^2}q^$S@}q8nTl?-wLDB@!^=Yq8w*U3WPr2_%2`j8c`fT&cBPV49#Yo*eJF zOlsfAmpJAj7Bg~S+w#h~(&MruN}L>TrxAP_31|K+=JH6NRwL=CLi^YmZ7 zx#>{}#a@`XjmGWkzr5-?vD=^C+;pXqsQs58?MeMhikI=PFJO^=J0o-j-`YjKVH<- zaP#o+fJuhh0hWaG=g(vFm_+*=xj$N3F0QT<4(I-^mi}*M2|IP7@@ce*binTuXRhH9 zf)@MN+?=>&r!`qJrKE^jE+Zx{L)4CC4s*&dw-C2ro<+Gh?pw6>F~U0!F;&;s!Z~!A zQx;?XwrR(mKpqIH3?$cM*}&wEo*OhZT(GA8M=_o|i?KWMlZIWf_rZG&1_fa(zQ>OX z@bO)Uh*%T0AGQa$D6&d`@ibIbS;O{YZ>T;sn}@+^DCc2TL8_a(J~Poj$!7!tG4^*R zuukLM*8dp0hNQRMyWgPo)6p>v7sR-v!2f8~$4>Fq6{Zl7D!S-cpkECq@Wso%|B1k9 zy_W^X1}9;rxYLS5%(f1JN3E{Kz{sFq?k%+#;&&cp_BWNIqyQnI&kUsY;sxB8hhVTU z(%1PfLcT0}3UMz%moE-ZL;%{$Tnh5Ao}j{?>y-WjtQwD5L7@y53)&_S7hoSj&H&9k zZ)$>cs$NT)c&IY+;QxhYZ&BgYEN5qX$0F75V9Gv~M=CRXDjq?D)KQc&_km<@eT|lb z{Dyk%uTAIKjX6`j4X8ZMZDB6Da^WtYlX8KM9u>uT?_PVw$gBNao!e6tm4YH^zn!d} z^V=mYJ=^o8vRpankECi1Gk1DmORR1*v0&9dK$0%gI&3p@FU}mQ;Mk zyN%FU;Bq&*#2D*St6;E)ic1R`on((rrYYGQl>Ou+AILgk;XClr;aX>Y!&Cw!4cHwy zvI_xBa3I*(O@?pZwaZXXk9^%t%%M&8=&)RP{I1CCO`%%D7y6WDAX+q%V8+$q{D9Ru z49d{(@MIY-r3;ua3ed`>5Fj|AN)@d0c5ddSTRvNA6#hMS5s3oD_KsvhliAsR!4h!F z&rfFhEdP~DmxiKh=Fu;19|Liw1Q@_PT~bwLrK~)J6s5u6vboNq$W)A#@#deda5QVk z-cfsZ?p-KXnHxSX8A)Q_g2QH2LefHJDY(VpNb~{pA4j6=qQ&unoh73Fpsp?kry7`= zZYcH44w1Wku z=gVTg?58?frGB$zDoQ5=~pI zsSmOCjWh}3cwo@~DaCuj0Bj$SDT-!#X6Bc#UL}YfRw-meCkpfv*?-4jqa^@QHjw1h z^fZn(;mB zqahd$q(-&dQIIOR1e$gBJS;d0@izlKJ;G(ql+j#W+d2~@5@`mfqJ6iI7L3r;QT7>o%ZO7=+vvkzX zZV!|xey2Xa5d&x+m8pg~k^H9LR7PT=%|Oi=>Ytqob?9_)q{dig<>gN!-rCd!R zn%N_bW;9XfKi=R@4DVqMJ&tTW)JUT)T3Ra|uNh&Q3OdR-RDZNU@n~!%vE3$UVGyy$ z6Z~Ol2zw~!o)fx|Lc^*FZw!JWNR{}*hkHUFpPZX=#0`OR1yz%9+9eu-vd;`Hw>_W} zpu)rNO``rtsaKl>+3>cjDh##F9-R;PRdpb>`4Q2-20FfsDjrP7n8#JRnE8&vW4h9WyS61`_nkuKb!khtuHYU}s>e5Ml+!>boBypY-V;kr)QbH;#b^8)9M1pT@R za|UkORv)*Wk&++|AlG8Jqyqo$V^p%B7Qo|zMkc9nkEh$DH(dsMgL4C}V|$+iRj~5g zIiH?VT=t5%%*+uK-D9Jpu6+;H=z+cbamLYgK+J2IHyoMMAbs$uB81clR;i0d)bwYH z=9O0*9LAD=zqoiD5+W=exFo1NFi~y4seXVb%9*Gj5yCO)VUW8juUoQxcd z;T{L5u4!xcpf!w`+F41A3_nXA0YS*@*s|rUjq8#ml73k$*(@elsZ*BZkleJYP$J_O z=p%7=p>fK(bZmGVMe<@}ifhoH7YQaD|GWUzzr4Vt2pS-$wMmRvMne?<+z8*t2B!0s zmHz0+;Hzva?peIj;tVwJXqIz10}KY;0&f+(&sah6as8paSyaZ#1uSbe z&j-IF7B(;(6bfQQPe7h=_CTvsAwUT%2CE-lWzL}{{Py5;Oo~9?097F{3fLQOPtT3$ zpn{gK=QJqwg-!y(eyD%oWr0Z9m;4EDZ@JSy+(S9+3QRP&>BFhbiiH37pFVZo*S55b z56Yc~3GhpQHPXpWguY)TT)UNyXm~^w7V5^hKOeaP>cW|iU)9!9BqeYD+HtwT$I;mt z?OsceRr!oqkiFsrME=$Sz&0TzCf3s2j2ULH8XE`QcVpGX2gb)n!vJb(SF=T|C1ijR zlmN&aM)@TnVE|2!{6?$~C|8mE8>4Bze}5es*(NW{r_CV&;P&GY+7cBR{R)RgICWPNenSM6{d z8t^Tv)6M{UD!jjA$o-P2OKB<3+3;C`))LB zu^qd3U&Zt3ht_xd7}9g3v;>3%1!1Uedgl&m7xx%KCz=BC@awUCFG>OsJXQeIP9=iHSj-{AG|}I|H}o4q~|h<%(syY0D?~ z-58^Z2pebxQ1*b-yS3+}xS>2khTw=n?S+@ZwuhJ;t9Qi}KOfF86froaN+_D`U{3+( zU+Z1Vz;vf3$%}}*BAqIaYzs0T0lDKsuZ=*nQCRgvu4_Pc$m!%|MC~Cg zpJui8g}$HP9I~}VNXc7dIXD>&Ve>>raXqKm?7q7#0pP5GAahL$$m~JjS?usVx1|tQ zqLU!s+ueOzCI-EPjjL9{>ZL>9(%Gq_r8Pe32VEty?~XY+A;-F?xY$u*qxaB>Hv4|O zHoU}ezkYQL)d>bFft+gv3yT6Q643E$#OJ#1{03(PXiuOSS~|K9W(AAh2X`jy~GV$`zN#Jh8ldYeC2ugEPQ(S(;utRJ0q^?f)y$_H}pZ3LpC>t8&l!h6Xid<&Z%AT$K}8^{}3U+nkx`?QUuD zfX^475U=aB^ILw^Tw{NKLaogvSs%e|+tP;kwo*P|jRO%5T^$-9ovp28CR8Jd=JDd7 zyVKGnaU2jo{Qa~OUe}gXecN-#v=h$U(_O3?xPA6!#o!xyMnegs4VxcY#DDMThgWfuD<%ndZ<%9n92^__ z1+)tkSQ4wN#Bvzg+js9M6MRHs=+fSqoR;P@(#nese#?Dmc0ED~LXM8yhFRmmcZSK* z62tsuc9;i&0T=&io5uJ5f9&&n)@&kVE~wlk--n3gUIOUA2Q|QwMI51zSNYO&Z-%@R zSC?hQ3iF323d#=u1O24J#ZP~7aiJ3EfM^i^8UEPnmITl32ncz0WR*XQNen@oh z+{w$$?e!|Uj}$XFMW_lQ3%7mbqf!*-&b_f8UJrbM?1$@A>p9X7bP;Xu&!5&z zD2{#x>!__g0lgy(PlJ6npha{8hw@AdmtXlxOE9*oGZZ_vZTt3xN@GHocX|~Oa=7Mf-2&z-uv1K&0gxZ;+gG$Al?$zn?5*MCB`jdz%Zo`HK+X8wD zkPU`YuA|r?tqR)e!OJ*b%T~Uci84WcwTF*STH8o_Q0n>fDr#yCfTmZCsMmRaTUBk# zdWLk|FI(32<_$FP&PZ?ulw(@HRaVvu^gSQt=2C6&3s7=me! zLRIdHgR17ybhZXoR*;dHT3Be3)3*^555MI+png5)I>mL@O5{tvcSl?wSbZs01rf-q zmi}R;Q3SUzw(NfYSx!o@cDk{F0UsY9f@7oxnHdS56|L%FDorU+A>pew2dG~Jt2i1@ zNMS@>gWw*Fj_^1@OI%y#n40qbvaT&0QFY|>5&-(8k-IsN>GixLg6e8}8eMD1p7dGM zsOD=$O~0rL-n;LHDZ4!0l_NTid3Cyle{*;hGQt zl^-Hnz)F(V;Pke7PBt%&-dXE{iS^}W3v#0Yrx+D&!xoMTx&*47E5pr!z9g5lXUfQ$ zBO_iFSFT)1NJu~@aQ)$P6UnmMj`kWqU9e<*wDNq$;=I*&!_eDAP*^w}L#z657>v<@ zkh_zOyN-@kN*&>+e5^KJ zr&I;@ehZtelSs3q{^z^UhVeT7+>~aiE;MDFjP)k58&&#h)oZWh55G-iQwrqWh!Uwn zE+vXvuR^1BTSJ%#J?FptHbV=ij+n+)rQWHFFU9ua75-_O3_ar&Gs)zBK4fgPvydzEQeML*&OMAx2p7Iinrq) zCB3;czvRK%aNk{=8P!K#ekpzVaI|rl*pJ~7?zk+#IEd%aQd7gZ#l+{vmoNKZU7T$~ zye*`qkS2j5z&Kk`1bY;i0D12c6Z<+l3nTU_UoWEO%4A#Pmo%&Rj1%`p0@X^t1y`-j zbNl@2=^fRP3N%U!jhH4B4(4kZx2T==p$^^0oL^P#{$6xdC{M#$*Y!T1AJ9#6ZLH^{ zSEK_=f@v<#P^Mu+#Qy=VCks5lH5(h7D;rudMg%>=lh_17|ANvJ;O9pGiH*Izr1xk$ zI{Fu6We5k$=!-_$znp4@#JMH{CAF7Z7OYiL^^fNhKPR?R=;AN2y5bpaKfj%&6Z;<9 zJk6V9tl0W}Z!DAL(2ooz4?5~*dC+ZG2tAG;=McAhhGiJ_AjXhfi;RRsw+thiH%n9L zsi@c^IT9@bAS=r<_oSSh&)@_Qx`qxqAS5EH>N&Z+XwW(Zh2(I%1B@c9i&$P9-P}aZ zX82_ZkDRx&JL0#aQ4)bAIWwGV-xap?9m!*-*j<^;m6DFy+nL_*to3y0fj7H3?l1hx ztN2Fq&i&@ZW*0g2E35~NrWSN-=Br<=ic1vgz5;^mAF~sVQ~7C+c*i-rrE@zfqZ+ zmzR;vmnmJc@NR@F!Q`z&ps(NQwy3J3ogprMQv>R+PtAk|Y@PZ&bEQShDAjDeWDAeb zR~NNIyDq8xX1>TdkQg|m`)xXMUG>6=b7+YX6*8jH;cklp4qcr9R!!k13x z@d!y~uH7Xp`P}AtXZg8ywhcO3SdG4yTAt9{8S)@i{^Tj!vBN&5xz8=K^Jgz5wY=s0 znH2QP^p(bm@!;U+F(tz14GL%Pno{}|_T1cag>`k+^sBbTS)Qq()BZb)+n>61mRpCN zo-fadgZF=TwNvGUUqz0=Ew*7AqV?v6(N(s-yD;rU85x9;$qk~BG1^i35>V_ou=TGo+ z#W`y?ZZyNZkeP8H)2^EdjAwP;TUO-kM|8LPO1Yt$_j$DoU!`}X7HmJb+U-M*?7MAS ze|_3)1&tvzF6+y{PlNy+YgVmqvxK- z9D8iZf`Rw18E?m1Nik4fCIno&ZFcjkv6vxcX8-6wfxnlQfw}7n-|@rtrjrc!hxqxV zE~g8254l&_g#A=((kjfGpMMJ7cHH;lk3K7GY2&hL`mFfjxsU8*7sJS_aLqYK-F!OP z4QzHs51WpxQM%LjV&^@B^pD&3Tzbwak;W3Gzgj78^U10c-!FV$rt#$E{Q;G}yht;r z;-%}h*#DcOvg1^|t=3@fdd*AV)$97m2N!-tzxEFunL2nQex^gwi9Mbr^9ZMv z%Qt=z8$+Ick;$%+#6-aZokp>X@tlhyvBv)4|A({pj>r1{+lQ3~O`)tLDY926La8W1 zc6LLuviEFA8c1e@Wbb6}O0u#^cA43GulqRb`uwizdtKlAzJ8C}AD_qP5$AfJulMWq zd>+qZdK!6dWujgJ%g8gN%+xDz6NGBe-6pt?x~BWX}z;d%76vC$I6uKP>CEVZFR1W+G_ z@&K0exwkNW0kaF{5|xz+DB~I$HnsM3e6SD<9iN;ugVZS@;mn;XN>h!i^r_au+6Xj4 zS+GVtYMbAGJa_i4>TaR6*|gkUMO5>j*JVaCL?RaGQd>>3V>~v*&%E;px3mx|IPJs9 z&JuMyTH@eHXcC3QGs`w*vA8?+1vS*WGT01HeK4IlX!`WwE3GRxv)azdN_gf69#i=t zbH$r%rg#QHoQ7-125am3iuZhwFJ8<~EVRvhqMpQQ)mkfFp{jPCq+x8&I^xrU5L!@jS!DB(cXjaE5Y#O99^W4^SkK=8`8-(8*YZ8=??Kg zO{tEl2$BSqYbWqAb!6cT8T5o};&Y8oDb0p^G@X15S|$9jz+ZVY8$O1QBY+)MG4fL->} z3ttSdcXZ^VegSj_)CJ5Sk<8A+%T_1Cy7CvRecr%XLyGrAf`e>svH-kPl7;K)B@iUx>B{j0`3fDZ+eDw8E zj~D!})Lyz!`q^wM#`YbSVcTN#lyIBbUf+3aD2sxG@zA5J54wToJ?;6_6W1w|s;*J< z)xL~ON>1nzSsB_)G(4H@D64o^!iXYGFu`h$vl_RffQk*iFKM)Y?3O2mAc*M z@oOJNCs>swD!lqw)4~r42%2*-T;+1r9^mP^+H>{Z&);HCT8}FSxW#iMtlzu$`90~^ zl<=kR^-8re?8fS;x1;%t65G1(*gc#1;ZA02ILj!?S`b#}Vk|11miU2d!kX6Rd&l=O9?MC7x*@?-ipg`A z@AbAYr&+pKWof^FL}a1^9M z5($(GR5MEp3r2UyGt0}$y7H`~ke>ye!5=*pGCcms*8I?aQXRB$-s)m%nhO7u#n!tJ zP#;t@+qE18?X*HBj{#HD=uHiiQQLTT_`p^NJEzP~`N{Yq6w zEcmRKtNW^M=Wz2~yP3L4r-iQJY25rfy@&hq8f{k#H=C7R&Yl^a;Qv{l=#(+%z0NW= zu)krV`F+!hk}2PZOzs_T7Shi|#U|tm>uDv8hGbL;{<0i2DS8z4+^R z8+eJOZ|Co`SKm^mPKb>+e*LPCxd+fRVwkp^HopNUIh9)D@Q67c zK0ZKTFuMV=`2g`)%RPqEn6Q9~1ad2+#^9R5QR^Gw3XZ`xxwu8DtfGR%e*yE8me$sx z0hhv2!RKY~b|vH#ZY&$O=fd}b@i^v%18z{(@FNb8FrY67lnf9OnSTU84pOvF#D31b zZuU`=Q=VIp&#PT7^tG}rZ|br*(!1}XqRIT4%iJETUq>wM?U^!V>g?Tf`bTZ| z(;%8{8Mg?|F+kBU*)6u{lN=G=4<_J_M+azWrE6yW0s_XpqqM@t(m(|#SbN9C1;Iy( z1S9%-4C|DY5!F!xYiB-welS$vR}K?!Y>-1BxxRZh1J7HD3ivV={rUN0rT}zglVAk! z!38NYu~zJ0DPk}}@Vmv%3BN%y3Fr+aNzg%Hr2SSp#PIvl3mSfC;viUqfeKjr0Jb4p zy`tSHrvHul(xo!cC7?2bKQxBqv!uyIU*@MIrT15QKiFR|{k4KMw4IvwfZNymx$oP? z(01VbmJbyiM`MoW3F9M7QwuEzc3DbCM#X9)V#cIB^9pp-A+`hye^_z&2V{v^Tpoiz z1R!91f>>GjaN+g#3e+Jygql9ClB+?W=F=S5~0{cdn%1VNFP!?v)vS5#F2ugHei zVM|K@+5e;tg!Y*F0CEh0P;SSg^IfyAe1KtAR#o9fn}m`gk&k zZda}hqccN|jueE>j)7|fnEH*_syV$yLv6^AvNkU--|vs?;G0`xj{h!h;##hoC4PCb zR~~4h<8fAJ!V2=_Y7^v%+_;4>}~s;4Dwj%u7Ip?-Qa{L5gfjBNa2Qnkr0X$_K9=nzFq7Z zusGd6WVT_h`NOWwbZ6q1cy5=wOZ!PcFPN9gx))yfHZQX||@6*gOB4ya>t@?)RrHip`(y(tgmYk;pD~xMyalG)ev7 zq>=Rt6}7{*`Bq#-Z6hI)n*X+kk4Q0K`(+uM@|@A8bQ7(`OQeCwgiDc-_N)vIZ#t2$ zSQZz*))?u_8SPBFSiGU7D(69__(nIYdtKU6A~HN-WafrcV$I@M{(D)UBU+V?bsP0& z?%_Qfyv-Te+n+vA``ZYxCU-Bkgi-C^)sjUiuFdb>;p#L>A%Vi_YVNDywKkTmN6r$_ z*K?X)XX5zV=Tg~G9((xYh22NOe3dZI4dRB^iD}!1vW5nQ&I1qZJsmUogkt7oZ3mVv zebXOMzV)SErQ5MVG_eB5k`e{iT^-Rkoxcu>=Dx`j?3|x!lE0hszHQhBh$kA!U=3sE zX*Z?|y5Gz~&@HaH*;v0e9_Tkjcf0Xz;E~Atz%ZHK4-r9Q&%%zV^cPKcZnNP$A(q7C zZW3YFSGu~=vmvr*-WYenEYXfDud-x4wlU)1>$#@4I{R(;PF5t_hgLJYpDlWQ_eMgv zH9HJPPI1}Q2a74oT_MSH>|gG!VXCF#pb@El*fD52skuG*+4`b>Smg{K-P`oCSvxr< zsgKn5Ex%Bp%xs3bMddiADJ5TWGOf$CSc@Pf9#4@c;m!JfReoft>Bg2Nzt5!p08InK zGhZDu#5#S098B2sczArp;R6s`(&vb*=y_>NbF(#4ZRuviI}X!M5}x`I-6^iZw%L!1 z^Ju*!U#v97ab&sLij`7;{VqMFHSG_YNi~#WBBUPXMOB~kla=$Y z)C(QHjLyv@51rWhwchCet-oxsbQ)FiZ|P^3G2XtqZ%cb*hwR(42)hJWk2y5XIn^{B z+4brba2J03_+dV(r>_rPBz*Lz6XoqA3I|mp$X@yS@&ZB=5Xb^~8Ih?a10PHTJ0N3# z89I(6s9>9wcAeN8tGx@Zl_wzYLMbiHh2wV;bCVDKgc=6@A~t`F#Tf)ms2A;FS_V>| zwWZ|<*bShwrAZ}W8i4dHgeYR{w~w0VCuFAXi_=%=iT+Q+>Ab6>MZ$-1#P6r_%=Cm! zKz5{bwLEGw7uU&*&);@QT$WXFVUU@ZOTO&u*zljNV?t>PX>p+4c9jp7d@F-%ij}d? zW`E%Sg(VplJ&N;$8KX}Ir9{Sc8m-o3OFWLeradh$ZaR7^*qU8l_CjP2NzpF~FP~Hy z`?^%8<=?E<6{C9Ezk@e2H#Ma8yQugw%`C>HBe%6$ip9CKr<9f_K zz$QSr;N0S31W3%_jziBXc_Ii03&u`h;1-VLlOxRW){$l^|W$ zHo$QKTClrms_oQ&jlXIlq zU~Ge6o#WresRWJM2QX+unTmi(3E2WI!l<_Il@?gk%9d>{8Jtjj}LC?Ds)-w8KdPqjR)qf6S+Uxj2KU1r83TV89#TaHCXLhX&Y8 z{YUB{M{p3?4moCVk;g)^t)a}Z5aaG~!A;##);_1)DB};1Gc@=4R+xkDY+C887ad=;)n~Lg7 z^-p(gR`iXCr54W=GDjw^UAS{)+{~E5LzXAjgKhgw@tWjedlycm7@7)#M9a(DR_x-W&`^G+oIt1nx0t|F?8;YB zRTZ=vyt*;p(ILk8<=a?9&)b9q*2T6*{{NnC^T1q?E?T~+eBbcssFjZp@gtwjt+>gn zDl0ASio?|E+G8*%!8B^tiCbZ8cNKfZzW1%8F-MJs&-oFMS_PZ3ogEe)&K*bHU$&Hg zrE!(e?XxxX_^!}%z}HQuE;d}Kho-Q-U!{1Xd1)^CU7FOzRLi^{);tA8|E1x5?n%@x z3o?JGSuyx1QL*1arW)_eYl0WA=G7Dom}aJ?NJvO3(9G7>ZopUT%p0GeUXa^aPo6}! z#0e0>GwQ^Y6cu}QaaU1D#8-xNwt9GMj(EoVM&hRQ-$Z3z11+|D&b;=+5G~`IH`CGm zV6JRrc~4uLerE_Ypwaq}ZlTWsDG5}ZNxXcFt}F&`O|6}MUaMv_IHHhWh(vHDv%ICl z5onXJJ3B8<5QtD9`a-~`$!TJ?Tl8yr*Sb@UTCW$eFvqlHZ5zG3UAcp&2-%hNmf6Jy z{%_iY8c!`_C=Tu?mpJXbxp!ihvJdOZyfo)Tv+zheC2534(CgROAYc3W-9|Vn_&0LgFv{zGl@-GZbp+0hnjKl@^fq7gNLN*BY)_5KvTs^#(YatX+@|$41)7 zLc2*FHQj_#@G*52W<8+I{ys7-X)ms^j;jR95#nU9On^neVV3!x!MLqIkQ;SVzGZwuj*S%1NSth_E#x&gXMY|L zY21U(_gwj}^Npe&{%5<3p2sI7Xy;p#lAic^{PcY?{O6kaV5Z1t=N%2_2!m=-Qf~qm z8nbt$%S!pX*JzGP|Cd>}#%FEAoyPB7%c)K2?-#{Ot~_;vRZ=)nJbInD(|1foA;H*e0z&dqFvuI7S%`=8z8?w;lth z1?&>=Goe@mrvM|2L0xfpZ^Kcek8$A|fxdk4yu7>_?p1ulSn&Grct2zeRS-twAlrg! z*6W?h!p_0bS?G`fmuJZ2anr+M6k-r)doYIbX-oYGhe;g0$;ljy7p0`i>*{>m2;_MD zQulbI4a=Wb*=bimd7|@yqOc3VAW&c6`GSre2p6M!A@W@SfZ@gmk`6Ld^Fa;S<^M84 zfeNk>?#@o+o&OG*>z+G)dY&D$8;}SQVbm)a8W91Ffj!tlsLCcDiqdhlZ6VvL^?{iF z(Qc{ytz3bxuD%;f14IW`Xu_eNgBlM+91x}>BX45H4u}tjQO%+0*;$AP#I1jmF&>8z z9BysgW$uXm2!;1D!iUr}HCIttU{Z=LlG)vy!8{@`P!P8)cvZ}P>MAPpAgzr&h(`~P z_X4gKH2L5*Ap<++(3lZ{a&}JoW_yhJ&8;Ugk=%|XGZ?qK3Wud8B;*0=0NnsSd?eiu zQJu`coW>jj01F>fP3$BV6<{T0;Ka$S7g8bi>OI}ekZEoXdSG#Os)4) z61X9b9^e_rJn{j##w*`tmLgt0zQnXN1S~~$f4I((c+E3uc4{gYTRv78t|_cBSoaPy zaTC7z<0KQdtVcT^kT2E$p}8AcM8Rl=b_3-zn1nU>hnt!D?yVKVv9y3o65jpPDBHgFG?J4DUpQ(xO z1gcJO1gSUo^_gFBB!xeJyku*1?m67~G+`&FQ@2)562JWcdG*XWH*a z9GiN0oA{(?pI-Xho6aD)zZ*s77V%3zVM%eSiJm_r+?V1)DBj$TMri|L*JmGhd+#++ zu{-0_Ia~XanBiX^FvVDTMbqwz^Lfwz_5i==uv-(}al_|N{_8Ku-q_Ecxl(OcZYWknO>z}t|{lY*|^y*vp*nj=|-!D={c)dvd>&gF;eeQjfKVbhUeTxKR zG6xwpw*CM5f!*Wzhmv_8khi=4Asb21O(|{DF*mtipCxqu%Qk7U|DZMf^DNpIUpBP` zpCcXr%T4;{&(EpJT)nzR@cWJsmmly(8>XIqYdfPJ;4)0<+{r+)#;%0C!^YZLxo_zY z^)CF&_jvAslv{BC7X>_ucs{pa%nv)_-Wgs0=l+--Ekk^ z{ZYr$BSemgwYn2bO#PmOzc|PChr1a`IQGG4%`=0wD`bb*W=R?UTl25X$k>lG1sHw& zpH{v1DIJmf7ToqkBsDN@#$%6&yIw6KSYV>3AdDLHU}=Me4``9?orvbU(E|^$0{m_h7A~Wz5JmA1Z3PM}bVoRdB}pp3eT!}|zdcnwlsCsVFI7Pz7zI;PK<|H@yKa9yak~?QBH9x8{;-kz+(w4tAnk++BVB#$oG; z0CkW~arv%EEiI()wa%4F+aDP||`($pGIq^twWvglt8S`SJfawJ?SuBqWQwP5d!RKgPs# z+sJ68bia6RLBVs&CZhXEvrz%|Ro?FJb`Zg#rIh~2M*{U##>we8E)zySBe&?e041Q$ zL1~a=_zPJtkWc)$^MLsNWxORzizho#fRQkQG)A51uFs=EdaNn+$S|rmobw>2U_p@E zyd|nv2xCaOsKMF*{VmGX^q7(ziQH_j))MBP3G5X$y$2 zzkP}B?|-3cOAH#HJK3H+=VS=i>VnUB3(v6kAsjHS%cxz7Xe;)rcdMLEo+UycIHzedaEvT>sGJO(JMpM&6;2 z?RZQx%zl1pFWx5EYumU0pB6*O&9tU4w_in>e8WtAm=4uM+>cbNg zwKsSm8V1aPB_z`0s#LhJC#`1NZ<_WXRm;;~%x1$b@vn@li^oR9NSd8kE*^X_o-`(I zlXJ{{&9XP`yq~<`zB48hl-agJE}xX1sBBVguC)}*7f`HtiSxE@+DVWUX=QpeA7 z{tQg(3HzBn)%&(Gj;lxSV3AXaLCapICuDsMjNQg&f&OlXol|bOUC$HkHqy!+d|8^U zB)7TT8fshiHR(O8PRicd(*?iccKQWseF(F3tZ3$6B-hQ!PnQ+?vi`ib%gQ~>$v4w2NeC(IC+`}3 zS>xZNtXwlCyeDLQw$&^#c3G=|##Zm+7r&cSIwyG^CGeW@m)C2O<~1K%er$rLQ@_NS zWnUk8G3PN=%T9*OP}jjbj+IY;`{S}0chFDwI0ls-sNFD`U41xl48HQEr5E5d25Nd^ z;|#L%e(Ltr)^c%hTs>)5*30|yY+K|iPgd5ZT|e#Dmi$JN$(>9)rMuxtY%oni+?~MM>$WY|osq8L+|q3C zU6&dfmB~?^LN-I2Hhr$L4-=QZHGIGJOr~P~y5m5Z*CmZTmn166=xB1}Ynq!TWJxSE z?R`^Irxxdz_je@vXKN8zK2`JdJ9ybzFXa0fuTOX&%WxrwC`>yY?z^aelV=-p1m&q|aQ1rwiN^b*;X(hMLyR zdC}Z%9kQ6aTNX1}?&{dx^2vVWbcWo7{P|+;--k{gu7yAzoi#wk*n|YA5+JZ;oOrtt zlbR}r_Ni0havLGMVO$O0vXKuF@KFB%JZ^IG0CShxBB00s(LN7a@GxI@nO)BaR9UoWGn zE)4`QII>snr;BF4Y^;;9VrYC4T>3UTb?T<5+x+n}Co)!*mSy!#%NTrS-BwKZXv?1W zOU<mES~&Sq>mMkH)0q_ zM@5@cunUmn*B_x!CRNg%Z z&kz$UZrLkt{`3Cp*EC^rcq#2HBb5wUV|7fT{%bp(sIDUt*;1Al5>C%`@?#;Jl}HUSaQ4zb}=wSK!yvL>pF@U$nI!pEaV@~YCL|waJ8wXzlZspU2}1R^gR!9 z#^alu9oI?%zRj$JB}YiSiuX%wnH=Si{Z0Rzl|SvFBoj8*-oTTrl?M;0>>V?9o{1wZ z313N@^ynZ?KGo`SN2szgv*vsJ*+I9ofZ5$`&7)%Z3_^@K?-k`#zh2(#ix1E96=po1 zb6;Dj<0uRJZPVoLUq7zyZCTp+tv~=|N9MlULUGYYrAQKz6Pp@L?qG>YkW6n_e~hk+ zvP-3NSv_y+a-olsDkE@STauD{db`4bHppNZ+{mnSNG_RNW; z%3V?~Zi!zyyrc8lY|ncY{{ew!anrYzB~O$c8d{f^RM^<7=T%?DC9z&Jb7HSlQ*}8S z)*W%rRkvRIH!KGqqISHgzXHXTaKdWZ1aHU+x8thV3ExG`Wuc6=y-*8zipwn!74;REM)vp zKPlAAw39xZ9FiAbZ?32~2@x#}L+HClzkL_5>96nwi4#OA24QPYvRA>ur!fE(OS&vC zPxU?gmywkjv9;8=4EyUtw9Gq<;@&Aq?)h%4QTyvYxKno ze6~j+S+Q0Iv4H)w#hQzPh6N#nT>ql*wrnv$J*6xX0!Nh z!P^D{H^i^Qj1krMJk)r=wbHZ;2&MqFpb|fOhS^3#OUns&K%t!YVqpRaN9Kn@#d?+G zsHi180l37(-1#%;l5g78dDyp7k047eE3;@qREZf|+*RvKkyV@ z1llu9psDnpaKMi$ad>Db=T7yZM0GKdNLjR^Xv?9~#tDTV;AqxXR!r{JmZRG~86U(7 z`rOXnDKCW9sOBVqq=0d~-OZ8NjoRWM~)!q6d9juq}XI^R_wF)&T%%!qM zcFT{tFkUI?snOw!b4xlXxwj!LdBuE1G4XlP0md(7-BWS5uW&_ah!b}Yj)WYT;(5=b z%3v6kV_UwyC@^0ZBhc}X!AhL=Rtkj`yC0ciPkk=;sVh?|esYs_f+gI)B?*#W)2$f1CWheV#(~Now5qdX~`rw8~y*=RP7)I z1=D3^4-W>X{pbZuGn{QDLa|7cm6da8sO{e8`DwC{=p>Q#hW{G59!f;cjzkYIEnT8u z#5R5VMW0;l+VqWgvxU1`1Z=*#G{@$JD)Cw2s6pS8E91YD z)g1P#FRZ8Z)H3gKt$Mn-gklWxIPYypuC zSNF8k(g#N;pKP^k)92(46S>i{uvDVd^O`Q{5<__7$m#D1MHIxYFLJ`|A4(dSMtRw$ z(q9O8GEQ4!F-ctRFjQS-yjfBtvfneYn_+YF$VGKMHA;W_i-j#no>w%;e)1)x2jGZTZ9mUA7oEwS`R6w>UpCq5J1fsaErRJlxz)^~Cyt$+*16=)>7gC3Z7ZX-JN=&*}Bb_-M*-ozS5!tER=>IrIpo zffIu>09=sMU~n8u)(hOH@qM6R(&mv|TWf3Ogbi8_vzZpy>z-+^hPh?4j;5B@VHiVz za1T{GT#$k1V2jbtPz42Q0dh&8C~TaZ0emv!!wSR&#jLENEe`irPMw*8(>#7~#$i1Z zs2kDIP>wfzTo9)Dz3q0QlY@f_>_1dguC!f8Mu~FwN>l+WaRHA^U2r?IIi2s|NsXD3 z!H)$6ZW|Lzg9Eb+lj57x8#UGYCxR2L)HRje>U1{*F3dKjTgCN1E`3F{uc>=5wOiX- z)l4zxDG|d^P`IIRp845%#_^!8f_AqLE5(C0Ve}$JvojTT8>^8Q`ffK-P04B+lSih= zK56H7bCFK3{3LjWjM4p(OB`3KZH;(x)VQt&Y419di-4C*=54|EBIEIy!y#W8?XPDpC(ZuUgtyiNTBJXRg#&CF0!O=2%aKMRO(lAi7Ekekp#9Z?v z7Z=JuLWT`uk3a|)TOG>)j(zdcC5%j+t3X4AEVxbP5o zvLq#q!axCoh>$(T%d4xPOJnG|pH9#OSPwAe2C9Cre&N>!Y4j7AcmI5}e-|T4_&t;D z)GPb0F^m(dB`6c7p-5V@veHbyRR%YEC?xlqq@~Fcu7VBY7d(M0G{`86e&N+=_`YyR z-MztoPuT8eYIuYG)zFXkhSJ0@hn33N-G5-wF(i73*G17RkJyk&^oeV8;v;kf?P&&)VEGH^o&$nI8>55W!TOad7Rl%mmpB0oCF1*2TA? z)o`S;w%)UEA1eOqAM`3w8}@sX5NV9=16%kbA9nPz@^S>Hz`IxO&1v2- zY%lD5F?qmD=*AwnG#EUEw$ICO=H1aSZ*;_AJ-+`BwB|=O2Y^%&D=zZZ-k33LCN-y8CyG+MKMDLbp!b zfXUTIUD(7AO-@es_BP^F155q#W3lc6eBk{YQjO-V6)#2gK86#F%0TnBsZRo9xP}&m2~YSrr}f^*Le`yf;t#! zg;TIAXxsslI2d#)vIV%T%mG&~vK*)ayH^zEq@tn>4*dsegwoYiRWWyN1@W(;AssTY z#;LgJ^kMeqSSzZPUef*hb)i#NOvwB*?_GscgZReMZ3I)nA`w?oV|6wWW9x#Ua3{b8 zuxdyJGHbZTk}e$%|n%&~YvyDpnncsdAdSsZRE$Hv;xvAR4Ifeg*ow#s%{8c)?B zuKNp*FiIzr@WlNF*7@rYr+V6%t4EjnP@s&P;#8+(BV6kBm zz@?dO0woswUeP9!OQ4}(L3xT$t*^?!$qkPv&UP7wv~Ykt*WA^GJIV#aIvg4Rnh#2h z!KxbPN_cp<1PN|rgp%V9#1xx`U;jAXd`t`}BMMT;s!%O}!CxCL%DJ)KU|^hDUs z_vOpC{70a%^P;mGZ$C&*PB4N6tn5Y2+Y8TUjKnc4r03Vaig26EHn>m2uM?(H3!u9A z&FP?%3<@$VH-ZTOTZDjdpuZBxOoR-)$--Ih=g+axXk!~+ zPjg#Of;0$JL`-7_b}~5s1eNUCNpRQz=Usg^9=m0<^Kr3#G#hBT-kzTCGcug;oz;bj zEF$o}AU78d{OrukgUI{{355I1H1-I)-}N`)FO8EVBPYbcSQ(u^! zZ91GKShGZMbs&>S49B-kPd^T^=jdnw?mIZw&}*AmXA0YG$z*VoeJE3MU@Or$oHhtQ zXmp_{ff*(87GUs>pLoTD=)IWiSgZOo=biwQP{I>-i_%f5?F2O&oLc-6fA6_cVCtv; znCzb#$UiWq=OdYfy^|9n*7}ErP`Z#ZV&oX}8GRC3bY%TOJ#?r%HshL7SzTS)GS^%g z(^ZR&HHYy5EL<9;BxsHBvCz|x{YXdE4TeA$a!WH4udsv)Y5bHcgQ*O5QA7ngI_68q zfJtOwXQy_O5-t>E5__n5ZeS29;fYtmc|MvvIz0Ru-cg*mq<_l>8QM<->tf(W1_rqx ztAg@`-O||kpbMj6>%GQgvRjbHpp^il2@yivfPc<9So#@YeM!Ec=5^ax0~ZpfCiZJW zf-J}!OG{USd2Zr@V2vs!wcxY`e~h^-mixxuu!4FjpDSiPIB0PjwEXz7gxd^oM*6bC zCgP zb;Eyt=-&TP75MP&VuZnQ19J6#{`~p3E4P7hgW@u_T-w8j&mxKoj&VDW*q@^f6Zl)A z6V@j+A#}X%?CcASW9QoF!=$=EQ*{Fq5f;F(as+4M4Cq=liOgm%d5dfC#&aVwqXy)g~pB)V#j^oy<}ZP)400_5d9~rJzLIoc;c&g z{=7gtWIK@`{)~ihkkSzheY`@p-#>JNd`<9UH1XU`^26sed;grxi$U^mVkG*whrrk% zy0HVE8$?7r!~~lpqToM6Wuk9?y$tpLPPYEbA^yKS?4t`iS+yB>GK*OY@K>hDua zvTq5#nxa}wzqMaMQxk}W@$K7DiV6MR+wYeV#^BURk&)*~Zr-ceq$k=S_?JB<+a*cQ z5iz%oZjv&juk#!oTsX~aI1+(0_^&>f~ zTZmqi!4Zj=@bSJLOWAgV$S~$aBEnNL9gkeKIwW+V9tW@awff5P#w zMhzx`rkI)odb@{_G!q=|%m zRW;%Vi39hjY<)@Z_mgPP(UeTBkS#L9CoTjK>6QQe5S&5!9~B)dF{5qcCEZ7OPtTdX zWO3-?XO{=tmI|*c=0rPQs%o4vv{xh~C9)Cz5j3>>TcQI3<@hE3Jan2}glNxC@1{n> z9jr8o+m4FhJE6Xja_wZl_ZG=tVIQ20vNR^h?rT0LJPudqKd#|Me&3qpynmquQBKzC zy`BJ(ZErdMTp6ytL`1i74eAYnITGwMZ=7|#v-7?jOjjS?C0zJEHCrNT!usJk^!JnD zYkvOsog%v&TLj_k65m{wAHL&vWy-90c@X8$hwVE*ekP1q=T^pZdN7DWsQql9v-IQa8;=v89Yux8>-gzCh?FJ2D zA$TBLN|_`b9AiwKRL%jB!Kz9hUT>Qg;W#f0Sec>Bqs#Z!g@nr1~d zXndU}^3ZqiTJ9wIs7Uxb)7~;FT}la>J2Z4|ElNpwO z9uNc|f3H25zGqaRqn>k0@Sc&6*Q}&#_ezCqyUlLBSX~Vsww4O7p*_-Vo9fx>3r;ct z>kjL#9d_(#i5lZAhYcniAC=hQpPU?bE|77HxNKweVBr1H&cgN zyFPu%Oxx(|5(X|s?X<~>QEGw8%?CrD!}5P*$JUtTyirgQil#hk)N)=yM{9QTgcMEp z#si0&#V(!JIaWnC%VVTcgoDS=%xykx7Z^@(<$cQNVRw%$OQUdeE%J=bx`wm!jJI;=qJe@s2IciQ^pzl}B0v{{nY>3^Z>aY#yDfgnq4JZAb6h%8 zG_S2C{V9q&?uAOyCH<8cRYA>Qwc)OgOI6#oJI9$tTk573O5?Vz%vs#i(XrkLi4D`d z*pn(d-&8C!Z{u~7$tj!g`X9TrwF){I*4Ey@C)$n@J3m}L883nuj+#&hk+ykETW?tC zQKu*;m5FZ*iSs@!if}d#R_^WU7)U>Oq1lMheW};YZGGfX(~0dZVPW_DNzeNf3jfHD zQplSWu`1rIn>d`M@uo9^+dV$5NI^j{Bc~S^`^|Y);>pDtF^ibY-}w@Z;p#%~dU)g+ zzgU%umu#ksEsD2G>55Q9j0p|2y{Flt`AUrTAa9iniGt!a0sbjJ?Mpsqa)10bUU0nA zRi1WOWTs`gDk;%a%zL(5O@FN7%%+5#Tph~0Z zTmM2=dbrDEk9*4aRFK1gsKRLO#nb*F1=BH1baL`k5+)AwKeAO`hi(M_8lLpGS*z-u zcCyoP&3u#<%ETV#0trl4Ic_kBsMi&74i#9T@1=u~&%?Q_^s>fDUrnprW6r%0l`jtyf4&0`qK{;oK6|Lt?^CPxTM!=k2i|fIQIFvXx1{* zwt3$a4t42EpHx1b?g6M7Z)ZZ~Zk$(8Q7M z3stO-$#h+&I$ovRUYi_wHS=9QM6f3$tE4!4I*j3nxpn%o-g3Gcd9k|NX`P!fJRe4_ zO{3CeT?Uf$oku6e-wQ073AD_!A6dzXwIE!xrN_3g!sID{p%{l&?i46)1k=j_oRueD z-6SuB?t`QuM(S>uvDBBHjyq1XQhqMTsdjIRjN3;Ud?)TU!{lgZiyR5Bbzx6{jLID~ zBU6P8ym|WNk+n`Ywu0r;Y?SZra#P8>u@G}o4ytT8PR;lwOAELlWdbZzldkQH0)rmB&1t3c16<+9s~U7mr>x!3Ea z;KFyV30wZawfQLeSX1tFyAk`8esX(AihhdSrFwbE-hxvl+I>WQijlN6y#kw-4(w>=@Cz%jq7Ur#jSLGogCQ zDeHYc*7n`|k;;miS6o$g8Yh`{yV*Rxdq0Eh-I8KJ=#wJenaxEu0)%-jA z+0F7-g>fUC{FY?GcbQf8q)=;1b!7T4$t&koTEq8Akg!JBE`IklAEl)JKL42^CL{>E zfX=37epHg|rc)92M7!y+H!D86Z#qr(x}Cl3sBAI6ahkPHXt&Efojm23j6$9qMHOvb zB^9%wdIb`Ng&~{L@!uUfmcJI0&i|Si6h8DjD)5Nsj{1EVMcu>9(o$-R3`^(y^_xqa9i1B>Sz3M>yA|^?PaV;yhvn$LI z6qAGFJl5|vLsIkwocjwr79!db;`VOICthWPHRLH}R2 zbN9HHhYQvsDb_V9#8E1D|4|2Yver@Ux#T_VV659Y@aEa}sD-QJ>C*uTy1N;7e6e?0 zIwM+qtKu`S?l-jwhd$rQ9WNFFPZTmAaj?0((Kf?!ESsA;fcEUq!P_@>3wcenRo}sD zQ!e@hiqB0}kpq_>dFWZHJ6Psq(i~nFP?#(5HStmJv};E=$>z6&=i{?RpCgOiSW|==rQ--ZfT42Rr#JyMSHR#ystCMZA}WQ{v6EBY`1Pu z`!lS(xcKe0%!So}xvYe=wX&4kmU4&0MeT>MnPy6TknIwiY)y)J+$wdJ>_^qo7NYyU zM7T862f+~2$d~ZAVdw+gd_{Oq?&@$8?nI0vu z?f!qYBX8CI0TrDQP|Dykr$Dzesz}Ldd%gb7TQ{Uugxl^PQr=R(1NC4ip%s*Y49-)Zpi@FLhU4OdOOl-iyq{Ji0k&)Qc%ImXcW}(fr%MYq=GMr(oS=-87DA1*E1X_~dv`HHmVmnz-nk64 zw2rWCPPpbIo#SvrmfF(@njb)UN015)!ZF;C^m4UAZHYi!0mw4HxM*i>J=U7m0~*5o zc;@mJqZ}(#w}fC2dwWPS#bzp)Abbk3*MaI1NEQqSu7saI6TmWpCrMph9bD^hcB&?|crZ0Dd;eau z;&ImBs$UM=WEtVh$n8;}O(X<-qZ=+-P zVnLwf?2gA|z|2e$Y20Pk1Cjh$h+&v3r2yZ|ehlFuYXQ9rF_#Fq1OO`Ly0(N03FaxZ zCtF#0dDAg1V`3^TFCPMYh=leP+r(KS0o;$U#jbmErs>Cz(|=URUw~^EssLI8YhV&? z<>;1#Cfz~k7#JKxkK0gQ&H|4txMyLlJM}(gX>4kO4>)UCQ;3{k@iScgVy~3s4dcwR z3VtKxKLND_TQC_sv&)z37v&5)@O9ulA>En~_X%(i3C3@PZ4f(Pk0}w}!Ba0Ufx|av z?V_)6(^%()(Z@?Q4qfN5PgYn zu35pm2tp@7^q`Mt(b2%8KQ^s~RP!G$fNZFB_9ie)`8TH(H1_S@?KGa%`XZr4FTl18 zm>wYu##bZd2+{zaFu2C6Ce3e;mG_GWaXYohIDuj=z}Pmih$BV`7@g!qX5|*6_A_=9 zZ^(MVL02S5P#=>a@+z=b9dYx@TzhXyhrPXrR20mDFvc>swe5a?^MbQ;p+*X_)q%&# z`OypboY!SB=8t`Lg>db>#w5py2)ML60JX$9K4h%Atr%K&)~J zSAb0EYsEZ`6xZL8PjnoIPm~@Qagxe(s%++;jm1!(%{>?#3w4c0cZ_PXv=gfV1hk<6 z?E{vLo`sh8)Ex zWn*^4e3K-Jq+!p>$T03EmGH!-0AkuC_6-8oj@(_K%7E)#L1w|P=(^Lsn6uESmqq(Y z^?a3Gxb=-j<=QnsYCmCNPz0|qfx(ym1JP~#Mdv*gJL&1`#&_RAJ!#;`)JIuX%3X}x z01EkyCcmt${GNd%cfey)Q$OGv1`{{i$!<~fl8j$4<^Yl(YJxd5ejwi}fMAJLDHgtN zNFgwiS3g8W1vjmj*jQ{ti1IN4*S$T0tJOQN@?xAIanf7^O|Y*5R9FVwSZxjF4ptC{ zV4(ulgoNqqm~zh+#6|uEcV&h{=FFpWa&mmb2vZ*{rGmUXmynaLq~&+zQ+V=!#trV-qe?zk6-aHG9b`6e*DPAp8ayU@PH|dFzQ2Ui2cWPW8WWJf-I2tNHF%> z*A`3?T0apJ8vgpe1F~`nEH^+u9G|V~MAZ}(KM-91{tdtzsh9wJ=@HD`1_!fml|943 z+0oIln-P#wa7YODds+&LzRAf5xB$@8i^A?4EvYvRzhqBwrZG*4G>gjvLu&7l|BeWs z>Qh{)vLU1*;XuPk7(P>TABp#4SyBH;ctG5VNf4GlMlslAJHUIuJELwQCWnv^C{p?N z?+d8~6XX(@h(MV;61qhw%g-zAR%2z9)$Q@`FT|sOWFhzyoW3)7LzwJb8zE!-0*?yl zg776nvx$6m!~RdSVuy)4j29ba>#lw*#GnE{lvh(U#F#(bG(62xa|}~OR#rny&?E!< zvfsOHZXnyCrj@^o7e$yLwrX55q*2LETsKe3+-R@GnMjoK3UGf|7^gct!~b*g`*LRw zAl7q9l>c_{>i{(D{#k(fcNEWXd^L^@SM8Ke= zk?;h=(#mejx!Zqry~^g=@0}YdObV5VIL;%s1>2vi>jsK?Ov(rL?Y!TX$=vgDgpYt- zJ_rlz!VTw6CKJekQOQe@!$gOm`y#p#f@9*bySv`qyJoN%o48JNos9XD88ML4_otwj zvd6}bt-xYoOdY9dgm<)q0IKRi?t(+@KFoy(8Z5%Yc1g0E5#v+6KL?@rI9M65RkWPw zJOeu}Jgi=W@PYez;V_AtCeLP{{7;KTC?txwDGKveBQF9Pp%aib0-|%Utzwy__w~SEf z*q_HIt9bg)JJf=AFwCu?c*39vTLP}}IT^y_^ku~J=hd@y;tU554!}&3@LHw+yjEId zcy|2Cd2TN35r4a-`B#S-@axt8%iSepN+ zoUG3k9iQw5uh`K+eq5lRM9gfM+q#qUH%<4V|2UA-eNj@6m;z6uGagnBO(K&IsC z#Y#?|?N~C)%SaMDdzj$6RVveIuS1Z;LB=1Qcbd;-!k|}{{Q-sIwwntNW`CaN>8Gq@ zJ(l0rYf!L5*QJfFNr~?qx!zP(4lbDJ5=aE2YD|+ck!4eO_(jbjLO&Ck*MayRuA^N# z7bki4_!f6FhD$x#)jEvm5^Cnw6B3mZK5J*NW z_Yi7qWnMQ@6zr%@YlllxaZCssR+19S9)(t^o*kb}&C~N>!8Zy~n%Ak&)XkKL<)Vx= zhkAykW-#y6-rkbtN^|ihdcCK`xon{V=a0cQLapNrBt9D>47K0zpcAfJ8`Uf^KDN!zd6;IZ`U4oHnQ$kZ*TVBnHDJTZf$XE-H}x$8q{1w6uq==P@`p7ndkoG)o$a$ zn$tq&*LzrskNN*^-S6S7StB-e?e`M1@%#DBsFc;a*wT2ERcTxAr5u=P(J{~Yhf!a- z*)Quiq1WmibN5O2nfvP+8C@eqqbEsE@2QAY3PKhxtfBUPHM{<^4k%|_(1+5-sIp@< z*W@*KOC)agBc})D?UwIJ2+%DIuiX5`(05*zl=gCIhRZ%KIq50snHWY5?1p#Qz^a(VZKXs5|^zs zlfc*tP^^-d^QlYrhm?UvF+pSI6yqESx#&B78S5)UQ;YmZRM1fPmJGnTD-b~p5T6iR zk@rKgT2fw~tGkaw!K-T)4Ez8hp;UsFV8~`CMHBr)v|b>;+dj}7h0f4n!))E7;=4y5 z8VS@R>m&rB4E%ug*N|9Jd2z}{dAa%c@oRADh|lkT)xz1`<@~@87EJ}Xx%~kUr}{}c zH$d;!owF4es$cEd_vY+j6DQK$QYU)S$i1AoUi2NNHsrQR zyO~-5K!LVG7EL67hVef^UlZvJn$uO+QEJh_CJHpDE5@b0+j zy*ZcWi{b$+2vorpauR88*^zlm2Mars(EEuNn8EL}9}P}u{kjCn&WPDZ*x68}ilUTS zh@nWUmZ$iKVc3>(AL(8=qM2|y zZP~`=fDGRck88hA%9`kI4`V^^aq4|>P6pYvQ;vhqojWnts!GcL(4ChkXWV<~ojkWV zv%M9Sx!u$9bG=dl&d4>`1%?b6f^`z1v5XKa&BPCLXgHBPN$$YR(;t64%OX2m7W%KT zj<#7+rX+cK)Hm&huqL^E`G-Wrk(?cZ5RDRG~*NvDI&kwJ>~U_)c! zFzotB&i-2W`U~uK7j$h?rI|ED&kt%a%W!j#dbYT&7p2f?G9x6thkltDBvmu`rOaYEhuoykuEu~UaQQixqW^0_F5h%o3owOHLIcF`<}gf z9}j--*U-BvwC$sAbp2AvlI2h9{T~}Uo|o$ung$2dEp$Y~1$YLE9$?IZ+Bo#?fV?4jOhI4Sq~bZ!rah;jPvdKV@3Juh}Vf$86r**UUR+ z<|EcnRYk=F6BEZ%e{x}gyEJZ>+Icmg^LzQ~mFB>K`Kz0ZVwIJY`t?efM$^s8m2xz5 z#1&?xvH;#Fc{sV0UWUSvsJ3kIIRZ~qxiR#YPXuqUKOEnT|3J@({oLP@#$GIuw7(~4K;rm8%utIH^4z~Y0UejyHZ&%1?$ zENfM|w7V=N_owSd3ykKtm8}T!%rPx{@E{Z>j*}v@C>=Si7rXMUaXk}{N*F9>Z+|65 z-x-zRIGkwp@0{L0w&bvyO}z4rsK%Azswr%R-TJ+)n+ZD$hd#3w`CEJJxohpyA8rjr z@uz2*M^nn9C~`9o&-Fi+fNA9Or>ai(eZnR?1Ei;^i0SSS<-T%@o7OJlCI)nimAt76 zY7+5UcDB>!+pd(3KC>;jff7q2=J%cwnj0s+?q*|&TRG!D-tw~qcOrU&h4 zoQgX=zzFSgxEiz?G2&{%Xvam23PEXxRPjA)WnWOEx!39B&K<7K`Yc~6RnoJtups%y z(Ty3~D9?_fNHsKckVyJl1RPFJ$KKC_W(KTl)reOwvQAXxd-?RIbB{Qp(xb--8sx~3 zpUl0qvJ=a~VfzgCsPi~+^`EfPlY;?murH1{T9D*Frs0~Yu0hC!eJmB&A*T$=;`i>~ zM}i7~T-m$-&9he*+$@iIQK%5{+qtR9M2n&L8(zYk-Ny$<+7Jj*TJ95k5|8SK%uC6+ zzOBgGt0~`XN!;o4Cl5br_K(<6#_hbiZz73L74!f~a+U?70y5=?AfgazFdK+*Rd?>Z zT^{-&;q{(8V!1XG70#Vo#0KIZyE&&8^`igEm5eQr%dfKAF;@Vt;#OOTs%K(3O&#X` zPf)m7&|Zd7!dk_AM2QDBX+49#BUaN4ZZ@vGbjbkJ=A2Q>lZ544+D^5VtsY-dwdV0Q z+P`QuxzB@+()Z@pyLDZQQx3-Sr|QeJ4qe$Lp#};3MXw)SdGQ^LSg0X{A9`5MdW9z-j7|2@o#st0u4S8m)GWoha5 z>ddRZ!pn32okorovVX=Febe+Am9@w697L-WE35fyI}Q2?=IO@1PunXhUnIp|Su+Yf z?$;7Yyt)74`UD$Q7UtQ;nnBB_sxsdbyHHh;WyhFcG$SI>7p$0D{k@`m%8BOL0V^u? z4GgwKMjDS8!KKA^H0iaghOm1}MCX$3=zDfg4oc|jz5Ifz^=}WXx-LNAEC~N=8PabA##C>je9!G|t#@5CPbs~Gnz;kBsk+Red) zS&2xg7i>X^=t=FNsGo(mNvwsM(EIbh$w;4yj?aJlq=)E-zPtwf`>#KWqiGREIreCc ztOvCpn|NHGKdmUc!JpiksB( zqK^UJejDp^M&Vdrq*|Wz3fpW(uNfB?w=@pGhOgbU90ftX9$`D&27;N7z#I)5=E$mK z$^DQ*V&VP{Dyp{YS7D3Lj!hM@h0CtEIFVd96-;tUJ*HH)$EHI`BTvi3cMpFgO2O{@ z{I2Q7CBA;_m@zr1-T+0%L`9X565HFmJbO`fk@85hDY2yng6A0H!q?1oxk(Qg^`Ml! zB9>IuCQHY7V7UKgVI<~Lsb$Ve zjjFQssb*3V8d4JpZ^U+3S-Mb3^%u;azmK#9m%U>uoR1-i5<2U$GSU*K46L+@yN(x5 z9&|ax86iUbM&;4dr)$_n()X=>w!f`4{oW4>$JFgN%>4&eEAa94Ma8v9JDf{F+J{vu zq-9O_E@4XAS@M*QA)lIHDDsi_f^OK@ z;zA=~0ZX(?tRxpgl^+@Ze8X?{F?QIy=92PWBNYlxRd0<@BIvPnF$v5pn*R4MIP;r?iwe+jG$h;!- z(uD;DkPK@Aw8BoVII5bcG-JdfsjDmFjEZ>++HA)3VfcA2TM6)U}`A!(xRe`viHXxA}r>R=4*f=VVV+`AS{g#mOmY-sz=xj5@fF9>{!v ztEOJ+efro{iYC0iK^=ugJ?M`?rk+u1I$T@AXAsj78{mbRY*fas{8>hDlJyJTsf0Ne zxdp@2{T*>-n?a^fsih#8M@uiI;nY!8HUEI)z=>;JobN)5dz?{R(5OuJE^Z2D8c6u3 zZ?wTP-O<%m@4^isua|hO%(zx#aG%tkYGbn@;6Su_>Oxe}6{}c!8`UU3dR0CaR&07W zzmN3@zGF(N6Ie)JeGAi!93D~U+j?Dp7=^1FE^S~L>f|{&{yRJC3nuLs;pfQb7avo| z(i*qS4bTqpo4SJr5Y|4!*si4n0BWdACcp3aHO2}U$G&e0Z407;wRn5qV$H1M$Bz?q zfY}y|ds?yLn2X-W))O-uSa8E>c#~Q2D)lR>r18^dp%qt38#ZK5Zx?xEDEi4UcyE(djXY*2Yx|a+bIysZO|B zMUm`AwcDR!*TkZX$r(QgCR*Zph?F~N5!Y>0fR_$4nIe5To{3u}BPjuO*1mN4^4va} zVF8<1iCNQSft5Mg-YvQY>RsmOD6IHU&9$%R+Mi{DgUUBjX_|f=aPe|{=@I5B7=%-E zTsCi|P~yjv*3g^7NO`b-Jk6773o#TmT*@gp<%~4*e0ae`upa)`p{5LdNeM2#=hbnA zdn7H1sSCLQNgDkO!U7^bAA^36y1AC}NuK6`FKZGL2Rm0{&QbEoMlEAcOwhyDdI-guH6*Zv3#pzuM|?w_fY(3tXyx6z2Q#Q& zYybWEiBj-N{e_AYkG@X0qd_c$OGPFHBl356cv@hp#lq!7HF{yFrSO?!%kjdM#(RK7 z*ndAi`r_5-wo#TfcF~Gni^Z7bS(4b=8l38MlC0clUjA;ELN1Gy6*`onx6RE~#80}7 z47c>M4oY;&V7p`Xbdrlf(Z}XWF21*vSqbTBY3o?*)M)@PHYzkDQ7R){X9lA8@;S3- zkK^blu3H%xcyre|!O;Ud3+7SMOHJr5`b}CFObOH4x|sAl^@ZJnfmXq5(1EaN^7XUq z>`v7mIkn8|7onnqcvJcgDvy2uIV$#OF_j+4#xz@7if?bwxcrn!AMlg)%366en=yY6 z`kpS8QGOC(F@SZ?u3b-RYh#&d&l$tV^mTvB1a+WCjNc^`3VxEr!tdmzPVB&U<_GyQ zC!HS~!1!j?4e^il&`vH3dU1d9MRFqY_Oj06iO`kb+vWxO2NJ4m{ z_2#<56WXp!Sm&4)#$kB)=6?V|(!7<=kjrsX+NKHUj%wAB>G8&HoWcYZoGqTX{VLJpR{v8q|^Ner}tiK pJP9Dr*ZCo2y!Sd17q-4=>p+J^Ui!O^{WxS{rtPe$M{GPc{2RYsz|Q~x literal 0 HcmV?d00001 diff --git a/docs/dev/pictures/mpt_tree.png b/docs/dev/pictures/mpt_tree.png new file mode 100644 index 0000000000000000000000000000000000000000..eef76442e23f6ecbc77a082060f4e3257ed2b73e GIT binary patch literal 19753 zcmc({2RxR4-#30zR%XiHD-}hV*;`UZgv`<)GP60I%Bal9C}bu=&SY=OmK7p<6WM$J zKZkx@*L`2lb>H{(-2dl(o}<@GoX2r~kK?;O4v>EdWvMSwC{~n;f~>Yn?A(C6hPGMU!BQ%YuOeZt zPmDrB`*S9Gnlm;R=4;pG0+(Y&T9IEkeRY&E%Z0*^dk|fDJx9TeuwK2=L-InSa*U{>_ zyNPc3DSSDMbG7;w|7Ho1^|wB8-~C$>@~X70wrrI{r0~FnL97^&O6krB->w}D83|df zK(5acNopDv&ZThtr$0+3_P*Y`ch9UPw#aj@n1cP(sr#eV&z*9q{^`69EmnXaZNK5`Ng#>`0=GeY@R^~v{{nTCb7Bi$yLIn$?s zfq~>wo2-{E{g}G8Lb{cM?%Z@$n6VJRe@b8HN8cA%l~|jdSSy^-IkeJfaJowt0@9r++Do%a<3EUW#GTGymA3E9%q z)8jDvu0w(i93nP@tIj7-D6c3yLbk@nMyG{A$u`LXn;~Ok<9Y8>Mc9;-d!1>T>XK{P zXmptgz3oET#{LL7X0a*WZ@uSXer9Ioox0$y44gnSm*Zn}%*QC?N;d}Gjf{+r4CG{F z%N&5@@%8C@26+xH^PB)$aDwk~RTQH-`F%Foa3)=BTTX9O*ECWlDrU%&pz zygg~5;$Z(^ui_voENr=v2fMrYh1~mxS7&FZ?9QXM{M2|)x0T7}FHgy(oqoOQve=8l zY(=R{ZQbQ(sC4n8xezyUMkQ=?bhN+Ex%%1hiv2Y#jLYs!2G)9@*m3szhXoj0P2^}# zlz-|U5D>yF={ETlW~~L8^KU7tQRj_{?Z%X}v^rq*aBqG4*^z4Y^%a}Qa#qQFZ?U7L znOW*Ck1}@WXOPI?Wi_?nXV0EJf8NmC93gUwlk+4EO_Ox@_wUEpqGMvXRH7wZmlrSx z?kZtAAM~jh85vKU5U}V>Q)WSHhrL}W-IM3cZxaW`EJ6jP&&FA-~7@bo$E! z&O;43r4l6X)ZWa{x>JtPS$uKv>wDruaqZf*`H2Vy5$jB&5}oDY;_2I8{79L^v~00$3z6EM z_KMauHZFIX>&2FDH$D^|Ds|1t&CQJ$-=7qzxMVk4-JvdB=CNh(+VtsOlbD#8TD+8% zApOenGPCFA2n^cMql;+5!k~{IKjv9>@7G~=>ufMPeaJ?Lhh=&H{$%HSt(BD(v*u`_ zgeX&qFAK2S4PH>NpFP`HMyw5!(ZU_)B1gD179!m!GMNht$;s((@Z7B{TvsMTr1z&C zN_M?V2bAXv$AUk7`cxA@qaG`2CnHWqcTpkiEnmg%MJXvMc6QTmZ&l`nh8rVzSUeVG zVVE91%%m_Ks|_;9e|YB1nXM_z{?vZOGmmaY3Q9`$*5!_O*BIJ@1I3`1W`bTmB!!$h|rEy;xo7mirOHQYVR%i9lQ z@={&ulGCpq*add;{YBOeIiEg#yTyO^{(Z50A3wkE-QAC*Zt-7;OXLbPDg z=2nk$xHEO>(WJ}f)KgLh;fFo^Y(DMgtBWaaTgy#+n3b5JQrJka@o;c(V68VbHO27X z{w#B#8}$Y`2HM-RVW;{M(}1P%dx{(d1qDs&gRvNB0gQBg6m-dp_j1QxrSODyQsP>Rpi z1r^&f8EP9rAt8J`JTEb7SFe6;Y}C&-^&K0oMU#&d6i-%!tw%!Ln>@{B;?P5 zy=of@US6B+CRmMVI`#5>c6NKkwFTASZ?G0zU0s(^bE-jiRD-Piri86}IV;v+ZHc?B zrgcn#)lbWAUStGoy1la@5HId*4YmgMW&tUW|DNY$et!Pv&!1ys8Mg-Sr*>`*XoGK% zFw6O2567cNM*Skcoy(U;V3OI8^TgyGbFWz%O!Mutmpcj zmWe?vHCyweLZK3r{0ve) z`}_M>>`w6MVvVWfs%vVl!3JBMZujmJj@P(Dt@BS>wtlUfd*!gtwZj@?JsN+%Bw}>u zIQXD%p}PNjKk>FoaQ4|S>}(07foA4JV{~eoCg6~-q?Rm@FEf=Z;_82P@r&e-6Y|=I zphrV&`G59jF+?J$#(Vs6|JC*UJ!0bGdjm%+EoocZD7iw+mXDP_fPIjmi;WYq{Qg$ug%UxX3p~P5EBs< z*^WHnQ~`sLsvaN7+3-^-eqHxVuCpL*tJ}M>6y?uP;svS9!}3rZV6lOHFY5P5i*KOSV^z)aAT=%gM*bCnVH0 zcRVaEuH1S+tWG}X$FKT@66b|Tk;bjE{CpixJ$?PNZsX2HwbL3#Mppc^b%@sSb29^V!?ZT4J~Mm5wZE6c~eM8NU~cwCntx7 zSC2J{5uD{9=3uX-r3L)8{8O?$h~UCFA@t@G72TX{j)76FSeii-pk-B+zZ}=0Z7oh2 zga_f(n%zmgnl8?=9fz-!+-@$2Pe4G-#@I)&8VxhMwY8;{szypq&LU#nZx)Z9>=|6~ zNW)@HKHXKhdiCnVhYukZ^JtFZR5^F<9FJ}m<0bpMdU~%s_KG-FV9i7P0a3v1+qYFz zR3OC5>zgxcje8^EYOkOGuJ>zwy{PT57pDp`;WLA>@!!6-PtzSfSus3We?a4)w69k8 z*5Z80f|#0jT3Q+vkIqRds+5!zA~x_wz7*Eot?t3@j+))#)0VxW^vnEYgoOO`L4jtH zTHWopJm*zy%RX33E><1^mvQORB^J-k+eStMO?(xl5Wt0ng!Ry|r1us5Jo z$pPKvD_gyO>sCU$`9o{#b>~N3`=*{wXX}SZy)X)jie25^1V@h&veDDi-*1U^o$tSt z^CLDszT$2}7(~hj=b~`ahY5N3$~Q+<`N{-MtDhAYi(y2LP18)8K|WR3dOyc%u=L0M z9MWms#`cZ7qW0sL?d-A_SxYf{Yu)M+OFkk7L?p2snZNprw4_K`+<#rz(hVk`{Y74z z<90!MBV~K(*MiU)Dua)=9#ec?S`wEGneroL@Sz~4=3O+I-JaN9n}raCO72zjppZ~Q#hO-!HCFfah4bgt2(z6RjM=J_ z6a#h##44|GCNolD+b7HiHW)(t-!SS=qu^ne78k$lZXYWjUe)`Ma5RYQ_6&zbh| zhL?K-S+Ys6)gOIrjZVZ4Za?Gr+?1?5GBQxp&=$qqN+7w`Ekw!~1lvf5Fxzd-Vk@yf z8QjTs!3}SvBMS*rui}N|32(pfoDuF9MsKesD~E_N!^muLYSO1#CY`TW-QT8TL*~#z znm&vZ97lI&XRMf`#qxNA+@2);>9VyAomcUBRk!$I+0)c-sQdXK$1~>m@XXUkB95$AIBp#qEv(ZgR&wsY&@KHE z`h$vg@Dg2u$e}q=pWdBR-}TwL$x!H7WBE=!{=APyZ(|xaw>Me0vTxk>Y;<}^ZNp3M zg_4ExP!44sU0v}Rp7i-phSl#T-LK-iT5j=A&+m|-jTqMlW=k%dFAM8GlPd3M$cuj= zE+TNtHNinB?k4#+-p0T-ZffrYkFTxPZANItcUkn&3`D&=+}_2(l&mFPZ)5|_@-(`| zYj!2f)3D|g4NPveZ)7ztPMQ^j>gM`EA8Ji0!UMN{oEWFNHgeaiW$A*Q2JfU9Ih^%= ziF4}$VPo~~uS?7RO12kKy!f)OU&WU_DNVwQCGmoD{&4QxI91o!UDRDT`2bEnD^0S7 zlYup?r%6|GoI`cB17G6UBG-Q2{pC1Ll{b19G9;dqTZ~o*Mr&=3R|)_4TYD+uy~nZ)riCIo8u34GMvtgqr7y-Jhl;f`9o_*Dz9 z;t9Op3RrKrK^Re0RR#7eSt-bEwOtuD7?{U6*U8s!-@YCB^0f7hctLvl70*cqo6=B- zagQHAe&WQ-n3!1y6OmpCr(b$(K0h92VX@B1dzD^k=AJI=Kg@h7U>UAE%MYKKG%HL9 z-l`9fcqejaj=lX9>;8;7hOr@o3G!JU=0 zF1DX&B!EnDGRCI1ww8=Z%mGrxA&-@7Dk=>x*yK4?wjmQUFff4pY_bM7@5e(a05t9? zCBQ;xqgly06{_2>ee)({+!qA|5Rd*aUynC2F>!5e4f2DJA8q^ct%!(-wBB94YJOGn5e0#f$aoS)!yEY@6E=~|FOG#o(=#SNTmVU&@?ewa5X`Z z!ulcm+S)rcHEV|dhPzD4ZWN{`I503)$TIR@ccC5V0rM3I37Mi2y1TlHy73a?wJ%89 zn!Tvym;Qq1-8r^=U-AV_QCF9xa*X@nsQSopsgzv-#jv;III_71SW2&I*mj(gWI&)xzzC-QF3n^+SG~>cdF5mmkvb9nbZnu8Q8!(hX>7?p6E%_s_tJkb)ij-j3OB zYzULM4k2WvvokXej+qi8wU57X;xPx!&(Bv^E3hG6vA<^k`=!yQbpQNjctuDgd{1lA zOhm(^o%gzgpkEEEIsQrx!;{?sud2xsy|XlFR8;O0TBeX|PPM#=f!G4JlTNRWfMBvCB(s_|L_?6E1yiJtAk^E~Q3fjtY=% zhvv$S~ zw$$g(a+o~QLMj+Bg0HPvbgPdwK<1RRI_T{HvOR@>-~~Bzw}16+l#@q zD@%~S-@JKK?is)t7!gv6CpE0ov@4JJ#;NvZ=I5!=YR>^pJci~AmD7Y(Bn8n@joXXv zv<$KCo}O3H(c8n`NSQ-KWMi${#H7q^4YSvcaox9&nmImplS9nkR?v|BlLw5j3v+gfslm3vGw}xP%YHDP}#5sDrscLV+IDdlwcAtE024S)v zIg6C@e1CfS*{uef(j_IpNg(Zn_}|((DeHspv%v1Tx<%Cj(KA?L~JuNGw`^F(Wa!yN5}#RHMO)j zq;vb`Ak~2k2Z3&FZ5QJt-C=Pssyh{DALOo*xwR}PkNq%aE^&| zprzH&hM1d|TGi9D+sKn4GoPK zyKRYo5YOmCN0_ZACoexcJA3Vv*6rIPfHhH4Qog(T+J13Zmd&RlNP|NqY<;ee+jIM> zI(bB7aqy(jj=hX|I)$Vh+YEu*Xp zV%oa83?%qPUO%M*vAJzh}Y*R`c-iFf|`&03Zf4=kR(IZXG&;e^m&H2usx3;k%CnF0E4i=^*dHndX zn#lGTZKYP6$JJQFYuS3dU|t}h3maQMwt?VCGt8}f>LRw+{&ab2YD)c$n2>~o2jtiB z==IlkN;oQ1!?aCIkd*G#t5-ceJqS)1&8HFuQ>l|>c*%ae9$@#}T*0j;yfMxBz`lfs zhr=h(A7C+h=hkz~TGiqtF0r$JHW$2q_b#KTtxOnaDg(OLgmh)B-FBfRp}gxPl4#R= zdwcs*1kW9@AR4s5DNB-7q1hJtgk%}G_z_OY;PNJxi3lR^{FtMcD3>dd3AL)xONYqfB+N%w0;@V zM1Wgs1L-&_>LFP|_n4x}X~q}uQI$g~)&q2qRo^f%0dvmkV-6mo;$h80VHg~~o1Zv^ zgw}Le3h-pk)$=UA!&dC~0w@>rP`GaaNTvuL-9fuLroDrR?xMXnvgj|35b+y(EGdr2 z+W9V#oYUMnd@2e#co>O;-4#4MJTwN@@8a%C>(ux-iJX8$kwBWR9(1j@0#mX0?P(!u zk*|EA%~E>5wKkd|KqhjN2LRVl+^y_7(|?HrrGuJ?e7aVbdjVF5G8j>`{rBx8YVcbJ`{&6 zS$=Nr!ylhgrq-W4d4fQ81?AS>eF4xV|IPQ>@^*M__{+zyAL5D zA@~F|B$2$-0qW7jw`}e9{JYIMAezBXODUD zkL#e&qizP+_Q5Xo-q}z~B=hV@Ri}|dKpu*HodfApEiXSN{o|M}?#ULCibzp2dDnI? z1TPp@OiA>$*05r=0oZAyGzv2N?v2{KiJ|t^!^d?9-aclnA|0WWr`0Xq#S^|d)xwJP zp>ky6suW@hHk;u=?f%RUkk!^f5d!jjU|&Y7pohZ>ob)0?cYv%96^aZx={aV4;n_#r z1a7#bqNvLhx*`K%0czhaqlWeKF|YD^Xy(gLUubB z>azRRDAb$n&9M+Zqhh#q8w()blG|Na&l^C{0#n$YtlZ>$vLG+-gMQvw0JF}XwHPdQ z?ds}U79c)$?CL44yLazCeE18{+&A;Her)o76gsF?mTs&I>1;BsM_gbr(TP(Md#fEl zyhpJ}0iOY&uT8~XKHzXoO*?R3Kp?fivc|>jcj=nEZk_~`5o~{B0n0{jcaShK8zB#^ z;MZ1q88n_(;lG~8ecvz$ABYSO2TJ||Ook_H35tk_2uO(p1UeoH127vU^WlAWC$YzbRiTL*{Ss#}C4B){^o?!fNaFOAj!e%{&L?LJ6@idHtpahNHZ zit7WL1;h9C>q)s^y?L{chXeODGBQF(M@K-;46G$&fJmYd5WoQ2xi*MlW3G>ep1#-F zM8v_#DVSc!zaBRszEHZ}vT&c#TRkYb#SYWP2U-M>Ce+8%)P1J#xDsS`%q_7Tw^ABd z<79+!2Wf-$O;kU%E1nk%Cl{Adk^RK-L{q%y_L)$;O2`3Fn^hbk66`)bCC)Yu4uXF^ ze7q~Wuc)XP#(DhDm#@Z2+%%>XgAj@0N&R2To}ZQ^n2XJoI26wd*%JHhk5n!X%H74W zg{U6>vQ)XObQfp%B-|UbYD5_ZZLKOA;|ztMmC+BK`ZH=spDLU2vrV2Gmwbb zj;Z?4d;geI4Q$FYi|C*`MdR98ev?C+uV>*-H>hQ%NZ#7mgmz>_2B)sOjYkh|XE26w zzP|bnf;Pxx2GgtAEy2TO@ZQgHO}If_R#t)7wO(<0#KhryKL(yl`Vl%xLmdWr02b?F z#Xc`l!!uqlDP(AetQII|p4a0}Q$T+X)-Z?tS@kQ$l{vm$!O6+-2~{j-jFUikM4vLO zD3}*XFL-%ZWmR!Dao`K=Bn~QoL3k%KrB4db}V_5vA>I{=bLgl#67tqIu*kz|k_rZgokRxr(56qrUp$$@E ztKJyG47In1Mn|8uF_V~miNupr;1CwyL4NzexXcX*ke8>fMT^>vPQ_#9dq7K}pV8&k zD!K7%sNw){aL_Qg7#bRScW{TqlnoZ*Oa3 zwP6vm&^9u9vzz;%x6dQ zM$SO>mF%$x509<~*13EqnPVcA44%T7L(zz`aH>G6IP~$h_t?nh(pZ7@z*(E2+y^g9 zmmsy0dp0v;u?39HbBd&_EH$!8z|{ZcEN6o(UDw&!`TF%Ricvts<0_&V4gaDHzbt)q zqlksrr@6J&*=7igah$YCk-g&nB{nwM{lxry;nSy2U$~&@Df<5_&rz2W&Ej)?Utfl% zYt={q#;2-`sY^2MFHWz6XKe-aNSBx)Yf|aEP>S+^4yvGLN47uO9Xrv zENzUnwKeENK<*SRWC_OY1Pe?2t5>2ngQcl)ZdaskG&VKynUu#u1`-jGXIgWtXtAfi z-%wloZb2XDQUU@3`uh4HeMnADCdHQrx~d~6ZWYgSe4U`qm1d02{}Zr4OJjAQd}t{f zfZp%KTMtLi1e*<6_#=r&5WtdhgmvpUW%u3O+&n$^0p$VMvkn{-hT4fk_C+{^*-3l}dhFuf0ceoJvG z*#k}&Y%PeifQ&<&AsHi(`9Ev-wFbn~Tp{I?dj`G1meK=CAZRPt+uIv?&S0{kVmO_p z^++$y`LtON7a(_-IHVxRsqv=*zXdx_?pb~PWj3F_Ztiu)jhUn@XASbw5>8|)@>odg z=ryq9%5-f3X=sTY=C@kp5{ohbP^hW3JZ16J)79MoVA-bUW8&MlcL7USuA?{y!kZy0 zpTRSCRR|Y>!FRg$ihl&;V1O#y-OeNn)pa;~_H252xo3Bl5!gQ)D=WZN-g#UsUHzuo z+}sQbm$Iy4Jp6d)1xj4)DY%KtaszkNIRht<4#mdC0{;$p1;lJSB}Sg33-lrWdHMMO z!@SSSyW!ch;?v7`jD%`9Bg1{t%FJuX`Z&l$Q z5()e`9WAWd5Bx6b)tjM;OnJ8?22F|jI}#9_QX6vRoO4jd}9`(m2?k@l!B_<&*| zx7F!GMjL2r0N6{4i;X?E?y*&ac?NcHcR=uf6-ZHwJpB*fA<_hRV71>Eq;s8}oCn|4 zua%UQ-&WjRRsZ~(_8VRp$GNGk&G}%u$?@@iA?WxZr#|eUJmQlcFW6>r=Xt|ohxeQB#pUuO?Y*mRC6tebmUB^0(CEhc zQL!n=$jE?4b6+Uqeo7_7rbqdtMbj`;(_|?;xtiUi=Ay@@EfGgm&BY+JU?yk;G(S5T^8h>SZfTL|w>-tcbcr4ZU5S{Q5b0230;MjQS37CBrNw?0W zHj6ywOZL^6=AslFU#i4OfqqE{YW!X9sa&>M03vcW+AX9u%cul~SQrKd%+_k@H=Qy` zd-7S?K{kv7`Z97nn_f~`_rKWo5%)BKs$3hlHSx@Igc|HRix7hdHE8eq5jSt_Jliyd zZq}-T@e-NxHO0p@RG*ItdM!{s8PqWR>03I=^qqNkAQB^^_gMHN=h3pn!fyfdSp|+e zleiU+#@;ORXQplFxysp?`S`oIL{WeR&~|oA@92Bt_HD%FU3t3vF1l_ z>{8{r47UJ(9|R)+XTR z;N$Ht5Yml*s4y3f0d_{|9-b|jkr_q1dkOVC*6Ep`Y?lW5N7$scVhR)&T26C~boz%@DIr-Weg^Rn-yfA)t6b~w zoD6P~33daZ;Uwhb3q@FWkYkDh1`U?1uCC5~^SamldS{{=y1MaF=xq=*u7M!LGqG?K ze}?A>1q+Lbj?Srrzd33D-d=q+1&9g%V|cP`-LVx6As^i3PHiAOeCrOb`4N~D4u2kN zRxC*+XvhjM2cF68uU@}C&?{;_2;}YCa~g+PG=R?B@_ts-{L1^>pbNBJdY9+%X?i7(?hbP_N2j>U2_aT66uo76Yt1N3&LeGPP-!gM}`C7iSyRy+u_7 zk2S1H@=&~K-vvrJK9Ko<%Y&aX70a-;;#h$OgmbWBS3w220!SYSI#%~?$jVl&v`WXn zd?~Q`A*pbbD68PcV}rccO*S}B5&jW$SRnOIfB!yIoo@OEtRE1bG1Jijo(}=U&sU0| zq-wYevN19H@n>BYOkYm{uz8a=60}Zl#GOGr?!bSLE39Fnc_E$G3r2Lh;h(w{rx!5_ zb~Qi}Izp;;G18|^)z~8CBI0JaN!V=1{yBc2N{=GX|!K zg-I5M6-l^z4+OeDp*(CE-Rul&*rW7-9BGN*nNdV5a-@Ai@e(D{C_h*9ylkh~RnOBa zdlyF!#%MX^EZgDngh#hC5Uh~`^)#b1Tw0XyZ4f!s4lmc2zxy~Yo71P9QHaW)C%twp z|Lm|*OwlfNaScITA{NX&FrHl2LD6HxFDHXF_bm@RdTbwb_Pyh?a5$60b)YVPR zxHCZ{LU!_GN=b?MA=?cCk+{A+$xpjqOctKF@1k@2r*g%eO3)Aq$vuPNv(J>Mb9-?= zoBt>pX80J)@L)>G8taheC*i$3cPck-}!=jtVYp6_sv&0LpSWXEU|-6J?>s%S6CY?_T5hQX}lUL7B=j3z-+z!-FnP{pix5ZfVq#*ga_aH?BN}q<$SOT+OT46v?cn2yTKs}k$H&?M)!#C(U^`=}^E|Z{2`E=GMFy`Hd zSvdZdMfGpy(zXLQIH->3@9N3}d8nlO`l>!XL;7U7ffK~=X4dnEI(u1%N#054GV&4Xf z>s^8UT2d1+v^Vbz`B@^AsOW!yk5_i_@*bBaX(9aNpDcR@?A!k0Q)yn~(#<}b3L*L+ z>D@)|#fdNtC@G5`d~BJT9nB5%K` zVz-Gq-eWXExBQ&qp_+DZ>?h&*xR4jCtE&*LBjghZumPCmR*SWLh?y^%0x9i%;TQl1 zA#{R87E%MGB;X?k`M+RPmpk+g4B|m{1JuUHkNg2O_A{MO0|V71C1!E1ryv!Axq{67 zLwb5x{BA9S4JQbF6%-I+W^%H)r$-&6m?Qee#>_zM_FJ!{-^h64?S048R4IslZ8|yR z%8^Sg=nco@=EDtI+-^?;EsI~utH(+^&U6B?VT^H>;Y-^-)Zsp%H+yOviywtkCg z+;F!Tim^CVo{}*Eh=b5M1tIi85Yei60u9{pDJLf;CI%)Rh|0Y-dGdxn(2w$iJA!-# z2n?7(P-?1#<=T#XE_yTtNJ}30NvPrhGYpdnu`d`h@DndM-+%ak2${n;FAely=v@fx zcmOfJFToSfZS}X%Vh0nuGe4^oqa4CK@Z-nNL7qaVjLxLr>S5%m4MM#G+@~O`VPGUj z1V@guI<7k~?&Cp#eo)E*<0!r#iQo`fppGU)>W5bFAaC}i0H$YIzGQ%zn%W5{eZaH{ z2nZH_X1cjS$d6<4?){W#sx8Tdeg_i7FSJWE>_lBh3vLCyvR= zGjmMpB5vXTp_ceGrYwo0qDe^UDL^pZRjf4pZ!BzVFtZ;D{K%Lrz_{C#o|`N4o_@ZR z=@FOf3Z-_z^bIm0k6O_LSFCgNzk6#-#=XZ@Hs#w4?bpzlI5;|5{rEHi`v$26bC+b} z;+ojsSpbOu2&SzpEcA2kH-n@Yv`j#1Of|=BbZV(Lq+W4#-I{2M`kS(ejfNT4%YO`! zI~2FG)S-Hzs{wxib{wWDRDqz5X6{)|mrd_1zm0i*+@4-M+H;JM)4^D5WT=)Ev5RbYZaEd9vde%!JgDE3F$u%B|GjE`byaz@7D#5coC#Jx{lO;eoNSxR zRuZQQb!q<0#f;U;s|$C0Hmn~E0*bc#>90zZfC}-1s2hhAC<+x)y7-w`?imyw^~^c7 znpgph0@f4BQ^6G(d2m(?0(OpCtmpGw3IOSl%k0@maVWk*Z~>LGWsB&i#>r(i@!yO? z3_A=kYf8WU@Qm<6Z(dV?iEGb6#q6x~TMCaMHWbQucz}|48z5!W@cYV2nFZsTC&s{a zpc0Hze)dV$s_{ax;=T*2(4Y?G5<$ zc|;CV2GDxt3GdyM=3XT<9tstoP(7*$90AJX34?FxGvrQKcpPfvPUUjXYYdP(ZBoFU zSdqt(57#Swf?Q++4Klhy14BvGqnD7YrIeo|F&(rNOd0SL`5FoS6<&x$Q7C@e)7dV_ z*D6^Pt4D>AtG#_F10bMQ|NN3b2%jKb`TH*?!}TDig@&$c zm=;kX4IP8=Is+W|zO}a!qG%7PQRX|3>ci`L9}Tw$Tf-8--waXt{G8EJX}Vnk8?%F zArJlcU&1>mo1hkNr0&!f@dklw(0bPQ@4r_nPMX{hgD)dXc~bnA|Bg4*5D8|Ph9bo` z8t4D~k|e$NQyn5A=#~!!GL0wGl9EiJ+Tp~htB{y7a#72|_{%(of}Dlo*(^kv`TF8L zh#1245biA3+4=czriWN&1nMK70?NO)zfl2j+W7eHY{mX8QY{D@&ENmn7SZ-=ED8P* zSLpHv_RXKKQ6WPFoF+IhfaBKJ*Fox3hg}sg3DqrCaX;vNfK^7YAyj8lZmt7xfm5yV zEKq!d)JgVaLC0E698O{uP=uI(dx9l z`rt2{i*xIRQK9W^$XMKB;}OM6+hB#${2TKBnKB|&G~E5&m#zOB6+|+3Ad;CJ3{H=W z_wJv$nEM`<3!?qon3sfPp^tBL^A>7rYKx#ssshYUE%IJ~m8m9a@p26WLIvO)bYIQ` zj!_h&Kw2%=wzQ~~40vuWPlSh`tm6T)_fLiCz$`iNM{qbhAf@hifFy!h0_Iswq-G8P;Nf7bKJ%ef>%u)>v#BmVjZ$X^~#NQ*v>X%hiiXis^ z=mNCYz?A{F1_FjyaOV)NLKH2z)~N+9Jd86UD$1nX;}WRPd3Y=Vn71Fv1~fk{t=_sI zDk=&}-k>5D0x@M}Wd;&Ia6PFEl0S)2=Ff|#%tRtXhr@w__!HTu-{A+IFS(tTk&)NO z_907~<-63>|5cBLNYR+oGyaDvj!?xZurOK!R_Gnky*-d(ZGaAWl?I^gWdoEp z!SXzw(KWMhfABi?BP9*Z#!?-NG!#`sV!3}+zRU=dUa*g=!B^I-YiKhIS3*h$8mat; zKfXP32l=9w*2`T3X`#9GZ2-rsVM9QYkMdg9Fj>0XN*T~@eo`(sKmTk+;izDygR^r8 zh-)E722Kf@pT1Z@EV)MG<@VF6JgI#2{eJ+mqfp`A+y1GHTtFmHvsHs^Kf=(k=!Tx% zm8V-qP^p9JRJB=&sJg|9b*X}+1>Qd}<6@qtAHsNPv|_UVo7ZRmwuvp))lL)COiIC) z{~GH;eN)p3xx)e)A5rGB%`#uW%{I!SYsA4H-J{m+C*~3Rx*(^%hnHaN7K2U0x&$S^ zOR5|_76Co$1*kvz5UvT=F(=K8BL{QqQ9=qlbesXK+_4|J0vH@2qZR9SXr zz=vs}kSpw-{qG5s)S?C71NI5Pv@G;@`otQQ2%?GcCYN$qX%@M2=MLn-@M?)#oARx9 z!2Z?0U<>0!Z%ssj>=g3OmtXvKp;``rV350^#1xF}wEpFy(S7SPC{#M4qD)hfsT>+J zI;6dUPzQXdEDox0;rPe525j_qO9FNj`|spQs7~MQMpSiO9hBxaNOQwmRPNpTpqHJ5 zD2viAb*u!)^YdFzgi28FXL*YoEWEKxNKNgB zLT$^U6|W^FC%^v$3kWKrE`sRC3&_&Wr}eNV7!bzeCJNEOX!3xzM@AYUNbbU{Kpn=w zGhP%*63}75R8a}82+abG+!zg8Z(dj^jshcbt3`claRI&OSb(7U9R5? zo#i>Kq2oiP5w1}MB{#wiQOo}8$WvP=8@J;jHw56;4S-uz8jY)>GV;_B?EipAqPz@7 zJnuuQ^YW3i^TxB|9Doq%T)%Fbt>?2pzW`(*j*Ma&b~?1DxB(t(&{}dGb+y=25Kz=s;g-A*0 z5ZBxIlYtZG;G94V~ht)1?hb$hA;#w)YhX=dCBEZDrODrjvvVs31kpyxt{|(mzbDXabckg_(qVvK)vczq1_mS z-0*Ub^O(r2E(<^*`wDCpW@ff)_&kr((z+lbdj*gtgAxZ(-k&&8u{9Z!kdOe%aAjuK zx5>$4a|J`f^g)1!0!h6DGX>fLsN;v1cJSo<@BsW0unTyh0EAZ?13d?|NNP3_<|Q@m zAHcxDDJh8tLlyjVtS)4z*fFCN4e-KpEr4`HY+zlPFsg)_5U|szL7Q&nx2&u_P$a#3 zr{rl~&0M}(fSL#{N{|&Pn*Oe>t-ZQ? zb6<^psly_G!u0=Cl)L?@1m%S!sK)vKeVt7@*w?VPP?Qhw;opp|oH4D%e^$oV_EQPN zcm!Ve6skLX@9^~EtQ@@q z1s-p#89Q5!pgg>Hylqvj`}qWbNQIYCNGw&Kkg^OXx5ND2%-{kXkUToUA(LPvay4Hn z38FJEe^9%_t35!x`rrPE_&S-N<2GG5sLGJvF9_Q?7@?cjde`**F1#)brJ|^&kR^BP G$^QrWss&&G literal 0 HcmV?d00001 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cc63136..e56d494 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -186,5 +186,11 @@ endif() add_subdirectory(examples) +if (BUILD_TESTING) + # Multi Process Tests + add_subdirectory(mpt) +endif() + + # Pull-in CPack and support for generating Config.cmake and packages. include(Packaging) diff --git a/src/ddsrt/include/dds/ddsrt/log.h b/src/ddsrt/include/dds/ddsrt/log.h index 4a08a46..360f9c6 100644 --- a/src/ddsrt/include/dds/ddsrt/log.h +++ b/src/ddsrt/include/dds/ddsrt/log.h @@ -107,7 +107,7 @@ typedef struct { /** Function signature that log and trace callbacks must adhere too. */ typedef void(*dds_log_write_fn_t)(void *, const dds_log_data_t *); -extern uint32_t *const dds_log_mask; +DDS_EXPORT extern uint32_t *const dds_log_mask; /** * @brief Get currently enabled log and trace categories. diff --git a/src/mpt/CMakeLists.txt b/src/mpt/CMakeLists.txt new file mode 100644 index 0000000..4b759c7 --- /dev/null +++ b/src/mpt/CMakeLists.txt @@ -0,0 +1,22 @@ +# +# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +# v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# +cmake_minimum_required(VERSION 3.7) + +option(MPT_ENABLE_SELFTEST "Enable multi-process test-framework self test" OFF) + +set(MPT_CMAKE "${CMAKE_CURRENT_SOURCE_DIR}/mpt/cmake/MPT.cmake") +set(MPT_SOURCE_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") +set(MPT_BINARY_ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}") + +add_subdirectory(mpt) +add_subdirectory(tests) + diff --git a/src/mpt/mpt/CMakeLists.txt b/src/mpt/mpt/CMakeLists.txt new file mode 100644 index 0000000..a81fbe5 --- /dev/null +++ b/src/mpt/mpt/CMakeLists.txt @@ -0,0 +1,17 @@ +# +# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +# v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# + + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/include/mpt/resource.h.in" "${CMAKE_CURRENT_BINARY_DIR}/include/mpt/resource.h" @ONLY) + + diff --git a/src/mpt/mpt/cmake/MPT.cmake b/src/mpt/mpt/cmake/MPT.cmake new file mode 100644 index 0000000..fd50b5b --- /dev/null +++ b/src/mpt/mpt/cmake/MPT.cmake @@ -0,0 +1,184 @@ +# +# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +# v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# +set(MPT_DIR "${CMAKE_CURRENT_LIST_DIR}/..") + + + +function(parse_mpt_fixtures INPUT TEST_DISABLED TEST_TIMEOUT TEST_XFAIL) + set(s "[ \t\r\n]") + if(INPUT MATCHES ".disabled${s}*=${s}*([tT][rR][uU][eE]|[0-9]+)") + set(${TEST_DISABLED} "TRUE" PARENT_SCOPE) + else() + set(${TEST_DISABLED} "FALSE" PARENT_SCOPE) + endif() + + if(INPUT MATCHES ".timeout${s}*=${s}*([0-9]+)") + set(${TEST_TIMEOUT} "${CMAKE_MATCH_1}" PARENT_SCOPE) + else() + set(${TEST_TIMEOUT} "0" PARENT_SCOPE) + endif() + + if(INPUT MATCHES ".xfail${s}*=${s}*([tT][rR][uU][eE]|[0-9]+)") + set(${TEST_XFAIL} "true" PARENT_SCOPE) + else() + set(${TEST_XFAIL} "false" PARENT_SCOPE) + endif() +endfunction() + + + +function(process_mpt_source_file SOURCE_FILE SUITES TESTS PROCESSES) + unset(tests) + unset(processes) + set(x "\\*") + set(s "[ \t\r\n]") + set(s_or_x "[ \t\r\n\\*]") + set(w "[_a-zA-Z0-9]") + set(ident_expr "(${s}*${w}+${s}*)") + # Very basic type recognition, only things that contain word characters and + # pointers are handled. And since this script does not actually have to + # compile any code, type checking is left to the compiler. An error (or + # warning) will be thrown if something is off. + # + # The "type" regular expression below will match things like: + # - + # - * + # - * * + set(type_expr "(${s}*${w}+${x}*${s}+${s_or_x}*)+") + set(param_expr "${type_expr}${ident_expr}") + # Test fixture support (based on test fixtures as implemented in Criterion), + # to enable per-test (de)initializers, which is very different from + # per-suite (de)initializers, and timeouts. + # + # The following fixtures are supported: + # - init + # - fini + # - disabled + # - timeout + set(data_expr "(${s}*,${s}*\\.${w}+${s}*=[^,\\)]+)*") + + file(READ "${SOURCE_FILE}" content) + + # MPT_Test + set(test_expr "MPT_Test${s}*\\(${ident_expr},${ident_expr}${data_expr}\\)") + string(REGEX MATCHALL "${test_expr}" matches "${content}") + foreach(match ${matches}) + string(REGEX REPLACE "${test_expr}" "\\1" suite "${match}") + string(REGEX REPLACE "${test_expr}" "\\2" test "${match}") + # Remove leading and trailing whitespace + string(STRIP "${suite}" suite) + string(STRIP "${test}" test) + + # Extract fixtures that must be handled by CMake (.disabled and .timeout). + parse_mpt_fixtures("${match}" disabled timeout xfail) + list(APPEND tests "${suite}:${test}:${disabled}:${timeout}:${xfail}") + list(APPEND suites "${suite}") + endforeach() + + # MPT_TestProcess + set(process_expr "MPT_TestProcess${s}*\\(${ident_expr},${ident_expr},${ident_expr}") + string(REGEX MATCHALL "${process_expr}" matches "${content}") + foreach(match ${matches}) + string(REGEX REPLACE "${process_expr}" "\\1" suite "${match}") + string(REGEX REPLACE "${process_expr}" "\\2" test "${match}") + string(REGEX REPLACE "${process_expr}" "\\3" id "${match}") + # Remove leading and trailing whitespace + string(STRIP "${suite}" suite) + string(STRIP "${test}" test) + string(STRIP "${id}" id) + + list(APPEND processes "${suite}:${test}:${id}") + endforeach() + + set(${PROCESSES} ${processes} PARENT_SCOPE) + set(${TESTS} ${tests} PARENT_SCOPE) + set(${SUITES} ${suites} PARENT_SCOPE) +endfunction() + + + +function(add_mpt_executable TARGET) + set(sources) + set(processes) + + foreach(source ${ARGN}) + if((EXISTS "${source}" OR EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${source}")) + unset(processes) + unset(tests) + unset(suites) + + # Disable missing-field-initializers warnings as not having to specify + # every member, aka fixture, is intended behavior. + if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang" OR + ${CMAKE_C_COMPILER_ID} STREQUAL "AppleClang" OR + ${CMAKE_C_COMPILER_ID} STREQUAL "GNU") + set_property( + SOURCE "${source}" + PROPERTY COMPILE_FLAGS -Wno-missing-field-initializers) + endif() + + process_mpt_source_file("${source}" suites tests processes) + + foreach(suite ${suites}) + set(addsuites "${addsuites}\n mpt_add_suite(mpt_suite_new(\"${suite}\"));") + endforeach() + + foreach(testcase ${tests}) + string(REPLACE ":" ";" testcase ${testcase}) + list(GET testcase 0 suite) + list(GET testcase 1 test) + list(GET testcase 2 disabled) + list(GET testcase 3 timeout) + list(GET testcase 4 xfail) + set(addtests "${addtests}\n mpt_add_test(\"${suite}\", mpt_test_new(\"${test}\", ${timeout}, ${xfail}));") + + # Add this test to ctest. + set(ctest "${TARGET}_${suite}_${test}") + add_test( + NAME ${ctest} + COMMAND ${TARGET} -s ${suite} -t ${test}) + set_property(TEST ${ctest} PROPERTY TIMEOUT ${timeout}) + set_property(TEST ${ctest} PROPERTY DISABLED ${disabled}) + endforeach() + + foreach(process ${processes}) + string(REPLACE ":" ";" process ${process}) + list(GET process 0 suite) + list(GET process 1 test) + list(GET process 2 id) + set(addprocs "${addprocs}\n mpt_add_process(\"${suite}\", \"${test}\", mpt_process_new(\"${id}\", MPT_TestProcessName(${suite}, ${test}, ${id})));") + set(procdecls "${procdecls}\nextern MPT_TestProcessDeclaration(${suite}, ${test}, ${id});") + endforeach() + + list(APPEND sources "${source}") + endif() + endforeach() + + configure_file( + "${MPT_DIR}/src/main.c.in" "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.c" @ONLY) + + add_executable( + ${TARGET} "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.c" ${sources}) + + target_include_directories(${TARGET} PRIVATE "${MPT_DIR}/include" "${MPT_BINARY_ROOT_DIR}/mpt/include") + target_link_libraries(${TARGET} PRIVATE ddsc) + + # We need the 'expand environment variables' feature that is present in the + # 'util' module. However, it is currently not possible to properly link to + # that module on Windows. In the near future, the utils will be migrated to + # ddsrt, after which we automatically have access to expand_envvars. + # But until then, use this very ugly (but quick) hack to solve our immediate + # build issues. + target_include_directories(${TARGET} PRIVATE "${CMAKE_SOURCE_DIR}/util/include") + target_sources(${TARGET} PRIVATE "${CMAKE_SOURCE_DIR}/util/src/ut_expand_envvars.c") +endfunction() + diff --git a/src/mpt/mpt/include/mpt/mpt.h b/src/mpt/mpt/include/mpt/mpt.h new file mode 100644 index 0000000..8d0522a --- /dev/null +++ b/src/mpt/mpt/include/mpt/mpt.h @@ -0,0 +1,158 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef MPT_H_INCLUDED +#define MPT_H_INCLUDED + +#include +#include +#include "mpt/resource.h" +#include "mpt/private/mpt.h" +#include "dds/ddsrt/environ.h" + + +/* Environment name/value pair. */ +typedef struct mpt_env_ { + const char *name; + const char *value; +} mpt_env_t; + + +/* Process entry argument definitions. */ +#define MPT_Args(...) MPT_ProcessArgsSyntax, __VA_ARGS__ +#define MPT_NoArgs() MPT_ProcessArgsSyntax + +#define MPT_ArgValues(...) MPT_ProcessArgs, __VA_ARGS__ +#define MPT_NoArgValues() MPT_ProcessArgs + + +/* Process entry definition. */ +#define MPT_ProcessEntry(process, args)\ +void MPT_ProcessEntryName(process)(args) + + +/* IPC functions. */ +#define MPT_Send(str) mpt_ipc_send(MPT_ProcessArgs, str); +#define MPT_Wait(str) mpt_ipc_wait(MPT_ProcessArgs, str); + + +/* + * MPT_TestProcess generates a wrapper function that takes care of + * per-process initialization, environment settings, + * deinitialization and the actual process entry call. + */ +#define MPT_TestProcess(suite, test, name, process, args, ...) \ +MPT_TestInitDeclaration(suite, test); \ +MPT_TestFiniDeclaration(suite, test); \ +MPT_TestProcessDeclaration(suite, test, name) \ +{ \ + mpt_data_t data = MPT_Fixture(__VA_ARGS__); \ + \ + /* Always export the process name. */ \ + /* This can be used to generate unique log files fi. */ \ + ddsrt_setenv("MPT_PROCESS_NAME", \ + MPT_XSTR(MPT_TestProcessName(suite, test, name))); \ + \ + /* Initialize test related stuff first. */ \ + MPT_TestInitName(suite, test)(); \ + \ + /* Pre-process initialization. */ \ + mpt_export_env(data.environment); \ + if (data.init != NULL) { \ + data.init(); \ + } \ + \ + /* Execute the actual process entry function. */ \ + MPT_ProcessEntryName(process)(args); \ + \ + /* Teardown process and test. */ \ + if (data.fini != NULL) { \ + data.fini(); \ + } \ + MPT_TestFiniName(suite, test)(); \ +} + + +/* + * MPT_Test generates wrapper functions that take care of + * per-test initialization, environment settings and + * deinitialization. + * This is also used by CMake to determine the ctest timeout + * and disabled settings. + */ +#define MPT_Test(suite, test, ...) \ +MPT_TestInitDeclaration(suite, test) \ +{ \ + mpt_data_t data = MPT_Fixture(__VA_ARGS__); \ + mpt_export_env(data.environment); \ + if (data.init != NULL) { \ + data.init(); \ + } \ +} \ +MPT_TestFiniDeclaration(suite, test) \ +{ \ + mpt_data_t data = MPT_Fixture(__VA_ARGS__); \ + if (data.fini != NULL) { \ + data.fini(); \ + } \ +} + + +/* + * Test asserts. + * Printing is supported eg MPT_ASSERT_EQ(a, b, "foo: %s", bar") + */ +#define MPT_ASSERT(cond, ...) MPT__ASSERT__(cond, MPT_FATAL_NO, __VA_ARGS__) + +#define MPT_ASSERT_FAIL(...) MPT_ASSERT(0, __VA_ARGS__) + +#define MPT_ASSERT_EQ(value, expected, ...) MPT_ASSERT((value == expected), __VA_ARGS__) +#define MPT_ASSERT_NEQ(value, expected, ...) MPT_ASSERT((value != expected), __VA_ARGS__) +#define MPT_ASSERT_LEQ(value, expected, ...) MPT_ASSERT((value <= expected), __VA_ARGS__) +#define MPT_ASSERT_GEQ(value, expected, ...) MPT_ASSERT((value >= expected), __VA_ARGS__) +#define MPT_ASSERT_LT(value, expected, ...) MPT_ASSERT((value < expected), __VA_ARGS__) +#define MPT_ASSERT_GT(value, expected, ...) MPT_ASSERT((value > expected), __VA_ARGS__) + +#define MPT_ASSERT_NULL(value, ...) MPT_ASSERT((value == NULL), __VA_ARGS__) +#define MPT_ASSERT_NOT_NULL(value, ...) MPT_ASSERT((value != NULL), __VA_ARGS__) + +#define MPT_ASSERT_STR_EQ(value, expected, ...) MPT_ASSERT((MPT_STRCMP(value, expected, 1) == 0), __VA_ARGS__) +#define MPT_ASSERT_STR_NEQ(value, expected, ...) MPT_ASSERT((MPT_STRCMP(value, expected, 0) != 0), __VA_ARGS__) +#define MPT_ASSERT_STR_EMPTY(value, ...) MPT_ASSERT((MPT_STRLEN(value, 1) == 0), __VA_ARGS__) +#define MPT_ASSERT_STR_NOT_EMPTY(value, ...) MPT_ASSERT((MPT_STRLEN(value, 0) > 0), __VA_ARGS__) + + +/* Fatal just means that control is returned to the parent function. */ +#define MPT_ASSERT_FATAL(cond, ...) MPT__ASSERT__(cond, MPT_FATAL_YES, __VA_ARGS__) + +#define MPT_ASSERT_FATAL_FAIL(...) MPT_ASSERT_FATAL(0, __VA_ARGS__) + +#define MPT_ASSERT_FATAL_EQ(value, expected, ...) MPT_ASSERT_FATAL((value == expected), __VA_ARGS__) +#define MPT_ASSERT_FATAL_NEQ(value, expected, ...) MPT_ASSERT_FATAL((value != expected), __VA_ARGS__) +#define MPT_ASSERT_FATAL_LEQ(value, expected, ...) MPT_ASSERT_FATAL((value <= expected), __VA_ARGS__) +#define MPT_ASSERT_FATAL_GEQ(value, expected, ...) MPT_ASSERT_FATAL((value >= expected), __VA_ARGS__) +#define MPT_ASSERT_FATAL_LT(value, expected, ...) MPT_ASSERT_FATAL((value < expected), __VA_ARGS__) +#define MPT_ASSERT_FATAL_GT(value, expected, ...) MPT_ASSERT_FATAL((value > expected), __VA_ARGS__) + +#define MPT_ASSERT_FATAL_NULL(value, ...) MPT_ASSERT_FATAL((value == NULL), __VA_ARGS__) +#define MPT_ASSERT_FATAL_NOT_NULL(value, ...) MPT_ASSERT_FATAL((value != NULL), __VA_ARGS__) + +#define MPT_ASSERT_FATAL_STR_EQ(value, expected, ...) MPT_ASSERT_FATAL((MPT_STRCMP(value, expected, 1) == 0), __VA_ARGS__) +#define MPT_ASSERT_FATAL_STR_NEQ(value, expected, ...) MPT_ASSERT_FATAL((MPT_STRCMP(value, expected, 0) != 0), __VA_ARGS__) +#define MPT_ASSERT_FATAL_STR_EMPTY(value, ...) MPT_ASSERT_FATAL((MPT_STRLEN(value, 1) == 0), __VA_ARGS__) +#define MPT_ASSERT_FATAL_STR_NOT_EMPTY(value, ...) MPT_ASSERT_FATAL((MPT_STRLEN(value, 0) > 0), __VA_ARGS__) + + +/* Helpful function to check for patterns in log callbacks. */ +int mpt_patmatch(const char *pat, const char *str); + + +#endif /* MPT_H_INCLUDED */ diff --git a/src/mpt/mpt/include/mpt/private/mpt.h b/src/mpt/mpt/include/mpt/private/mpt.h new file mode 100644 index 0000000..e167e1d --- /dev/null +++ b/src/mpt/mpt/include/mpt/private/mpt.h @@ -0,0 +1,153 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef MPT_PRIVATE_H_INCLUDED +#define MPT_PRIVATE_H_INCLUDED + +#include +#include + + +/* + * Just some helpful macros. + */ +#define MPT_XSTR(s) MPT_STR(s) +#define MPT_STR(s) #s + +#define MPT_STRCMP(value, expected, err) \ + (((value != NULL) && (expected != NULL)) ? strcmp(value, expected) : err) + +#define MPT_STRLEN(value, err) \ + ((value != NULL) ? strlen(value) : err) + +#define MPT_ProcessArgs mpt__args__, mpt__retval__ +#define MPT_ProcessArgsSyntax \ + const mpt_data_t *mpt__args__, mpt_retval_t *mpt__retval__ + + + +/* + * Name and declaration macros. + */ +#define MPT_ProcessEntryName(process) \ + MPT_ProcessEntry__ ## process + +#define MPT_TestInitName(suite, test) \ + MPT_TestInit__##suite##_##test + +#define MPT_TestInitDeclaration(suite, test) \ +void MPT_TestInitName(suite, test)(void) + +#define MPT_TestFiniName(suite, test) \ + MPT_TestFini__##suite##_##test + +#define MPT_TestFiniDeclaration(suite, test) \ +void MPT_TestFiniName(suite, test)(void) + +#define MPT_TestProcessName(suite, test, name) \ + MPT_TestProcess__##suite##_##test##_##name + +#define MPT_TestProcessDeclaration(suite, test, name) \ +void MPT_TestProcessName(suite, test, name) (MPT_ProcessArgsSyntax) + + + +/* + * MPT Assert impl. + */ +typedef enum { + MPT_SUCCESS = 0, + MPT_FAILURE +} mpt_retval_t; + +#define MPT_FATAL_YES 1 +#define MPT_FATAL_NO 0 + +#ifdef _WIN32 +/* Microsoft Visual Studio does not expand __VA_ARGS__ correctly. */ +#define MPT__ASSERT__(...) MPT__ASSERT____((__VA_ARGS__)) +#define MPT__ASSERT____(tuple) MPT__ASSERT___ tuple +#else +#define MPT__ASSERT__(...) MPT__ASSERT___(__VA_ARGS__) +#endif /* _WIN32 */ + +#define MPT__ASSERT___(cond, fatal, ...) \ + do { \ + (void)mpt__args__; /* Satisfy compiler. */ \ + if (!(cond)) { \ + if (*mpt__retval__ == MPT_SUCCESS) { \ + *mpt__retval__ = MPT_FAILURE; \ + } \ + printf("MPT_FAIL(%s, %d):\n", __FILE__, __LINE__); \ + printf(__VA_ARGS__); \ + printf("\n"); \ + if (fatal == MPT_FATAL_YES) { \ + return; \ + } \ + } \ + } while(0) + + + +/* + * MPT Fixture impl. + */ +struct mpt_env_; + +typedef void(*mpt_init_func_t)(void); +typedef void(*mpt_fini_func_t)(void); + +typedef struct { + /* Test and process fixtures. */ + mpt_init_func_t init; + mpt_fini_func_t fini; + struct mpt_env_ *environment; + /* Test fixtures. */ + bool disabled; + int timeout; + bool xfail; + /* IPC information. */ + int todo; +} mpt_data_t; + +/* Microsoft Visual Studio does not like empty struct initializers, i.e. + no fixtures are specified. To work around that issue MPT_Fixture inserts a + NULL initializer as fall back. */ +#define MPT_Comma() , +#define MPT_Reduce(one, ...) one + +#ifdef _WIN32 +/* Microsoft Visual Studio does not expand __VA_ARGS__ correctly. */ +#define MPT_Fixture__(...) MPT_Fixture____((__VA_ARGS__)) +#define MPT_Fixture____(tuple) MPT_Fixture___ tuple +#else +#define MPT_Fixture__(...) MPT_Fixture___(__VA_ARGS__) +#endif /* _WIN32 */ + +#define MPT_Fixture___(throw, away, value, ...) value + +#define MPT_Fixture_(throwaway, ...) \ + MPT_Fixture__(throwaway, ((mpt_data_t){ 0 }), ((mpt_data_t){ __VA_ARGS__ })) + +#define MPT_Fixture(...) \ + MPT_Fixture_( MPT_Comma MPT_Reduce(__VA_ARGS__,) (), __VA_ARGS__ ) + + + +/* + * MPT Support functions. + */ +void mpt_export_env(const struct mpt_env_ *env); +void mpt_ipc_send(MPT_ProcessArgsSyntax, const char *str); +void mpt_ipc_wait(MPT_ProcessArgsSyntax, const char *str); + + +#endif /* MPT_PRIVATE_H_INCLUDED */ diff --git a/src/mpt/mpt/include/mpt/resource.h.in b/src/mpt/mpt/include/mpt/resource.h.in new file mode 100644 index 0000000..13c5711 --- /dev/null +++ b/src/mpt/mpt/include/mpt/resource.h.in @@ -0,0 +1,6 @@ +#ifndef MPT_RESOURCE_H_INCLUDED +#define MPT_RESOURCE_H_INCLUDED + +#define MPT_SOURCE_ROOT_DIR "@MPT_SOURCE_ROOT_DIR@" + +#endif /* MPT_RESOURCE_H_INCLUDED */ diff --git a/src/mpt/mpt/src/main.c.in b/src/mpt/mpt/src/main.c.in new file mode 100644 index 0000000..31f0689 --- /dev/null +++ b/src/mpt/mpt/src/main.c.in @@ -0,0 +1,551 @@ +#include +#include +#include +#include +#include "mpt/mpt.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/process.h" +#include "dds/ddsrt/environ.h" +#include "dds/util/ut_expand_envvars.h" + +#ifndef _WIN32 +#include +#else +#define EX_USAGE (64) +#define EX_SOFTWARE (70) +#endif /* _WIN32 */ + + + +/************************************************ + * Support functions. + ************************************************/ +int +mpt_patmatch(const char *pat, const char *str) +{ + while (*pat) { + if (*pat == '?') { + /* any character will do */ + if (*str++ == 0) { + return 0; + } + pat++; + } else if (*pat == '*') { + /* collapse a sequence of wildcards, requiring as many + characters in str as there are ?s in the sequence */ + while (*pat == '*' || *pat == '?') { + if (*pat == '?' && *str++ == 0) { + return 0; + } + pat++; + } + /* try matching on all positions where str matches pat */ + while (*str) { + if (*str == *pat && mpt_patmatch(pat+1, str+1)) { + return 1; + } + str++; + } + return *pat == 0; + } else { + /* only an exact match */ + if (*str++ != *pat++) { + return 0; + } + } + } + + return *str == 0; +} + +void +mpt_export_env(const mpt_env_t *env) +{ + if (env) { + while ((env->name != NULL) && (env->value != NULL)) { + char *expanded = ut_expand_envvars(env->value); + ddsrt_setenv(env->name, expanded); + ddsrt_free(expanded); + env++; + } + } +} + +void +mpt_ipc_send(MPT_ProcessArgsSyntax, const char *str) +{ + (void)str; + (void)mpt__args__; + /* TODO: implement. */ + MPT_ASSERT(0, "mpt_ipc_send not implemented"); +} + +void +mpt_ipc_wait(MPT_ProcessArgsSyntax, const char *str) +{ + (void)str; + (void)mpt__args__; + /* TODO: implement. */ + MPT_ASSERT(0, "mpt_ipc_wait not implemented"); +} + + + +/************************************************ + * Processes. + ************************************************/ +@procdecls@ + +typedef void(*mpt_func_proc_t)( + const mpt_data_t *mpt__args__, mpt_retval_t *mpt__retval__); + +typedef struct mpt_process_ { + const char* name; + ddsrt_pid_t pid; + mpt_func_proc_t process; + struct mpt_process_ *next; +} mpt_process_t; + +static mpt_process_t* +mpt_process_new(const char* name, mpt_func_proc_t process) +{ + mpt_process_t *proc; + proc = ddsrt_malloc(sizeof(mpt_process_t)); + proc->pid = 0; + proc->name = name; + proc->process = process; + proc->next = NULL; + return proc; +} + +static void +mpt_process_freelist(mpt_process_t *proc) +{ + if (proc) { + mpt_process_freelist(proc->next); + if (proc->pid != 0) { + printf("Process %s kill(%d)\n", proc->name, (int)proc->pid); + ddsrt_proc_kill(proc->pid); + } + ddsrt_free(proc); + } +} + + + +/************************************************ + * Tests. + ************************************************/ +typedef struct mpt_test_ { + const char* name; + bool xfail; + dds_duration_t timeout; + mpt_process_t *procs; + struct mpt_test_ *next; +} mpt_test_t; + +static mpt_test_t* +mpt_test_new(const char* name, int secs, bool xf) +{ + mpt_test_t *test; + test = ddsrt_malloc(sizeof(mpt_test_t)); + test->procs = NULL; + test->name = name; + test->xfail = xf; + + /* This test will stop after a given timeout. However, when running in + * ctest, we'd like to use the ctest provided timeout functionality. + * So, make sure that the 'manual' timeout takes longer than the ctest + * timeout. */ + if (secs == 0) { + test->timeout = DDS_SECS(1600); + } else { + test->timeout = DDS_SECS(secs * 2); + } + + return test; +} + +static void +mpt_test_freelist(mpt_test_t *test) +{ + if (test) { + mpt_process_freelist(test->procs); + mpt_test_freelist(test->next); + } + ddsrt_free(test); +} + +static void +mpt_test_add_process(mpt_test_t *test, mpt_process_t *proc) +{ + /* Prepend */ + proc->next = test->procs; + test->procs = proc; +} + + + +/************************************************ + * Suites. + ************************************************/ +typedef struct mpt_suite_ { + const char* name; + mpt_test_t *tests; + struct mpt_suite_ *next; +} mpt_suite_t; + +static mpt_suite_t* +mpt_suite_new(const char* name) +{ + mpt_suite_t *suite; + suite = ddsrt_malloc(sizeof(mpt_suite_t)); + suite->tests = NULL; + suite->name = name; + return suite; +} + +static void +mpt_suite_freelist(mpt_suite_t *suite) +{ + if (suite) { + mpt_test_freelist(suite->tests); + mpt_suite_freelist(suite->next); + } + ddsrt_free(suite); +} + +static void +mpt_suite_add_test(mpt_suite_t *suite, mpt_test_t *test) +{ + /* Prepend */ + test->next = suite->tests; + suite->tests = test; +} + +static mpt_test_t* +mpt_suite_find_test( + mpt_suite_t *suite, const char *tname) +{ + mpt_test_t *found = suite->tests; + while (found) { + if (mpt_patmatch(tname, found->name)) { + break; + } + found = found->next; + } + return found; +} + + + +/************************************************ + * Root. + ************************************************/ +mpt_suite_t *root = NULL; + +static void +mpt_add_suite(mpt_suite_t *suite) +{ + /* Prepend */ + suite->next = root; + root = suite; +} + +static mpt_suite_t* +mpt_find_suite(const char *sname) +{ + mpt_suite_t *found = root; + while (found) { + if (mpt_patmatch(sname, found->name)) { + break; + } + found = found->next; + } + return found; +} + +static void +mpt_add_test(const char *sname, mpt_test_t *test) +{ + mpt_suite_t *suite = mpt_find_suite(sname); + assert(suite); + mpt_suite_add_test(suite, test); +} + +static void +mpt_add_process(const char *sname, const char *tname, mpt_process_t *proc) +{ + mpt_suite_t *suite = mpt_find_suite(sname); + mpt_test_t *test = mpt_suite_find_test(suite, tname); + assert(suite); + assert(test); + mpt_test_add_process(test, proc); +} + +static void +mpt_free(void) +{ + mpt_suite_freelist(root); + root = NULL; +} + + + +/************************************************ + * Runner. + ************************************************/ +static int +mpt_run_test(const char *exe, mpt_suite_t *suite, mpt_test_t *test) +{ + int result = EXIT_SUCCESS; + mpt_process_t *proc; + dds_retcode_t retcode; + char *argv[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + + argv[0] = "-s"; + argv[1] = (char*)suite->name; + argv[2] = "-t"; + argv[3] = (char*)test->name; + + /* Start the processes. */ + proc = test->procs; + while ((proc) && (result == EXIT_SUCCESS)) { + if (proc == test->procs) { + printf("\n\n"); + printf("=====================================================\n"); + printf("Suite: %s\n", suite->name); + printf("Test: %s\n", test->name); + printf("=====================================================\n"); + } + argv[4] = "-p"; + argv[5] = (char*)proc->name; + retcode = ddsrt_proc_create(exe, argv, &proc->pid); + if (retcode != DDS_RETCODE_OK) { + printf("Start %s::%s::%s failed\n", suite->name, test->name, proc->name); + proc->pid = 0; + result = EXIT_FAILURE; + } + proc = proc->next; + } + + /* Wait for the processes. */ + retcode = DDS_RETCODE_OK; + while ((result == EXIT_SUCCESS) && (retcode == DDS_RETCODE_OK)) { + int32_t status; + ddsrt_pid_t pid; + /* A second/third/etc wait will restart the timeout. + * This means that the end timeout can take longer than the requested + * test timeout. However, that's good enough for our purpose. */ + retcode = ddsrt_proc_waitpids(test->timeout, &pid, &status); + if (retcode == DDS_RETCODE_OK) { + proc = test->procs; + while (proc) { + if (proc->pid == pid) { + break; + } + proc = proc->next; + } + if (proc) { + proc->pid = 0; + if (status != 0) { + printf("Process %s::%s::%s failed (%d)\n", suite->name, test->name, proc->name, status); + result = EXIT_FAILURE; + } + } else { + printf("Wait for processes of %s::%s return unknown pid %d\n", suite->name, test->name, (int)pid); + result = EXIT_FAILURE; + } + } else if (retcode != DDS_RETCODE_NOT_FOUND) { + printf("Wait for processes of %s::%s failed (%d)\n", suite->name, test->name, (int)retcode); + result = EXIT_FAILURE; + } + } + + /* Be sure to kill all remaining processes when needed. */ + if (result != EXIT_SUCCESS) { + proc = test->procs; + while (proc) { + if (proc->pid != 0) { + printf("Process %s::%s::%s kill(%d)\n", suite->name, test->name, proc->name, (int)proc->pid); + ddsrt_proc_kill(proc->pid); + ddsrt_proc_waitpid(proc->pid, DDS_SECS(10), NULL); + proc->pid = 0; + } + proc = proc->next; + } + } + + /* Revert result when we expect the test to have failed. */ + if (test->xfail) { + result = ((result == EXIT_SUCCESS) ? EXIT_FAILURE : EXIT_SUCCESS); + } + + return result; +} + +static int +mpt_run_tests(const char *exe, const char *spattern, const char *tpattern) +{ + int result = EXIT_SUCCESS; + mpt_suite_t *suite = root; + while (suite) { + if (mpt_patmatch(spattern, suite->name)) { + mpt_test_t *test = suite->tests; + while (test) { + if (mpt_patmatch(tpattern, test->name)) { + int run = mpt_run_test(exe, suite, test); + if (run != EXIT_SUCCESS) { + result = run; + } + } + test = test->next; + } + } + suite = suite->next; + } + return result; +} + +static int +mpt_run_proc(mpt_process_t *proc) +{ + mpt_retval_t retval = MPT_SUCCESS; + mpt_data_t args; + proc->process(&args, &retval); + return (retval == MPT_SUCCESS) ? EXIT_SUCCESS : EXIT_FAILURE; +} + +static int +mpt_run_procs(const char *spattern, const char *tpattern, const char *ppattern) +{ + int result = EXIT_SUCCESS; + mpt_suite_t *suite = root; + while (suite) { + if (mpt_patmatch(spattern, suite->name)) { + mpt_test_t *test = suite->tests; + while (test) { + if (mpt_patmatch(tpattern, test->name)) { + mpt_process_t *proc = test->procs; + while (proc) { + if (mpt_patmatch(ppattern, proc->name)) { + int run = mpt_run_proc(proc); + if (run != EXIT_SUCCESS) { + result = run; + } + } + proc = proc->next; + } + } + test = test->next; + } + } + suite = suite->next; + } + return result; +} + + + +/************************************************ + * Main functionality. + ************************************************/ +static struct { + bool print_help; + const char *suite; + const char *test; + const char *process; +} opts = { + false, + "*", + "*", + NULL +}; + +static int parse_options(int argc, char *argv[]) +{ + int err = 0; + + for (int i = 1; err == 0 && i < argc; i++) { + switch ((argv[i][0] == '-') ? argv[i][1] : 0) { + case 'h': + opts.print_help = true; + break; + case 's': + if ((i+1) < argc) { + opts.suite = argv[++i]; + break; + } + /* FALLS THROUGH */ + case 't': + if ((i+1) < argc) { + opts.test = argv[++i]; + break; + } + /* FALLS THROUGH */ + case 'p': + if ((i+1) < argc) { + opts.process = argv[++i]; + break; + } + /* FALLS THROUGH */ + default: + err = 1; + break; + } + } + + return err; +} + +static void usage(const char *name) +{ + fprintf(stderr, "Usage: %s OPTIONS\n", name); + fprintf(stderr, "Try '%s -h' for more information\n", name); +} + +static void help(const char *name) +{ + printf("Usage: %s [OPTIONS]\n", name); + printf("\n"); + printf("Possible options:\n"); + printf(" -h display this help and exit\n"); + printf(" -s PATTERN run only tests in suites matching pattern\n"); + printf(" -t PATTERN run only test matching pattern\n"); + printf(" -p PROCESS run only process matching pattern\n"); + printf("\n"); + printf("Exit codes:\n"); + printf(" %-2d Successful termination\n", EXIT_SUCCESS); + printf(" %-2d One or more failing test cases\n", EXIT_FAILURE); + printf(" %-2d Command line usage error\n", EX_USAGE); + printf(" %-2d Internal software error\n", EX_SOFTWARE); +} + +int main(int argc, char *argv[]) +{ + int result = EXIT_SUCCESS; + + if (parse_options(argc, argv) != 0) { + usage(argv[0]); + return EX_USAGE; + } else if (opts.print_help) { + help(argv[0]); + return result; + } + + atexit(mpt_free); + @addsuites@ + @addtests@ + @addprocs@ + + if (opts.process == NULL) { + /* Run test(s). */ + result = mpt_run_tests(argv[0], opts.suite, opts.test); + } else { + /* Run process(es). */ + result = mpt_run_procs(opts.suite, opts.test, opts.process); + } + + return result; +} + diff --git a/src/mpt/tests/CMakeLists.txt b/src/mpt/tests/CMakeLists.txt new file mode 100644 index 0000000..91a9183 --- /dev/null +++ b/src/mpt/tests/CMakeLists.txt @@ -0,0 +1,19 @@ +# +# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +# v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# +cmake_minimum_required(VERSION 3.7) + +if(MPT_ENABLE_SELFTEST) + add_subdirectory(self) +endif() + +add_subdirectory(basic) + diff --git a/src/mpt/tests/basic/CMakeLists.txt b/src/mpt/tests/basic/CMakeLists.txt new file mode 100644 index 0000000..cb2efba --- /dev/null +++ b/src/mpt/tests/basic/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +# v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# +include(${MPT_CMAKE}) + +set(sources + "procs/hello.c" + "helloworld.c" + "multi.c") + +add_mpt_executable(mpt_basic ${sources}) + +idlc_generate(mpt_basic_helloworlddata_lib "procs/helloworlddata.idl") +target_link_libraries(mpt_basic PRIVATE mpt_basic_helloworlddata_lib) + diff --git a/src/mpt/tests/basic/etc/config_any.xml b/src/mpt/tests/basic/etc/config_any.xml new file mode 100644 index 0000000..68e0e0a --- /dev/null +++ b/src/mpt/tests/basic/etc/config_any.xml @@ -0,0 +1,30 @@ + + + + any + + + + auto + true + true + + + lax + + + + diff --git a/src/mpt/tests/basic/etc/config_specific.xml b/src/mpt/tests/basic/etc/config_specific.xml new file mode 100644 index 0000000..2ae3286 --- /dev/null +++ b/src/mpt/tests/basic/etc/config_specific.xml @@ -0,0 +1,30 @@ + + + + ${DOMAIN_ID} + + + + auto + true + true + + + lax + + + + diff --git a/src/mpt/tests/basic/helloworld.c b/src/mpt/tests/basic/helloworld.c new file mode 100644 index 0000000..c959edb --- /dev/null +++ b/src/mpt/tests/basic/helloworld.c @@ -0,0 +1,63 @@ +#include "dds/dds.h" +#include "mpt/mpt.h" +#include "mpt/resource.h" /* MPT_SOURCE_ROOT_DIR */ +#include "procs/hello.h" /* publisher and subscriber entry points. */ + + +/* + * Tests to check simple communication between a publisher and subscriber. + * The published text should be received by the subscriber. + */ + + +/* Environments */ +static mpt_env_t environment_any[] = { + { "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/basic/etc" }, + { "CYCLONEDDS_URI", "file://${ETC_DIR}/config_any.xml" }, + { NULL, NULL } +}; +static mpt_env_t environment_42[] = { + { "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/basic/etc" }, + { "DOMAIN_ID", "42" }, + { "CYCLONEDDS_URI", "file://${ETC_DIR}/config_specific.xml" }, + { NULL, NULL } +}; + + + +/********************************************************************** + * No CYCLONEDDS_URI set. + **********************************************************************/ +#define TEST_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "hello_def", 1, "No environment set") +MPT_TestProcess(helloworld, default, pub, hello_publisher, TEST_ARGS); +MPT_TestProcess(helloworld, default, sub, hello_subscriber, TEST_ARGS); +MPT_Test(helloworld, default, .init=hello_init, .fini=hello_fini); +#undef TEST_ARGS + + + +/********************************************************************** + * Config domain is any. Test domain is default. + **********************************************************************/ +#define TEST_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "hello_any", 1, "Some nice text over any domain") +MPT_TestProcess(helloworld, domain_any, pub, hello_publisher, TEST_ARGS); +MPT_TestProcess(helloworld, domain_any, sub, hello_subscriber, TEST_ARGS); +MPT_Test(helloworld, domain_any, .init=hello_init, .fini=hello_fini, .environment=environment_any); +#undef TEST_ARGS + + + +/********************************************************************** + * Pub: Config domain is any. Test domain is 42. + * Sub: Config domain is 42 (through DOMAIN_ID env). Test domain is default. + **********************************************************************/ +#define TEST_PUB_ARGS MPT_ArgValues(42, "hello_42", 1, "Now domain 42 is used") +#define TEST_SUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "hello_42", 1, "Now domain 42 is used") +MPT_TestProcess(helloworld, domain_42, pub, hello_publisher, TEST_PUB_ARGS, .environment=environment_any); +MPT_TestProcess(helloworld, domain_42, sub, hello_subscriber, TEST_SUB_ARGS, .environment=environment_42); +MPT_Test(helloworld, domain_42, .init=hello_init, .fini=hello_fini); +#undef TEST_SUB_ARGS +#undef TEST_PUB_ARGS + + + diff --git a/src/mpt/tests/basic/multi.c b/src/mpt/tests/basic/multi.c new file mode 100644 index 0000000..4ed5743 --- /dev/null +++ b/src/mpt/tests/basic/multi.c @@ -0,0 +1,50 @@ +#include "mpt/mpt.h" +#include "procs/hello.h" + + +/* + * Tests to check communication between multiple publisher(s) and subscriber(s). + */ + + +/* + * The publisher expects 2 publication matched. + * The subscribers expect 1 sample each. + */ +#define TEST_PUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubsubsub", 2, "pubsubsub") +#define TEST_SUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubsubsub", 1, "pubsubsub") +MPT_TestProcess(multi, pubsubsub, pub, hello_publisher, TEST_PUB_ARGS); +MPT_TestProcess(multi, pubsubsub, sub1, hello_subscriber, TEST_SUB_ARGS); +MPT_TestProcess(multi, pubsubsub, sub2, hello_subscriber, TEST_SUB_ARGS); +MPT_Test(multi, pubsubsub, .init=hello_init, .fini=hello_fini); +#undef TEST_SUB_ARGS +#undef TEST_PUB_ARGS + + +/* + * The publishers expect 1 publication matched each. + * The subscriber expects 2 samples. + */ +#define TEST_PUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubpubsub", 1, "pubpubsub") +#define TEST_SUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubpubsub", 2, "pubpubsub") +MPT_TestProcess(multi, pubpubsub, pub1, hello_publisher, TEST_PUB_ARGS); +MPT_TestProcess(multi, pubpubsub, pub2, hello_publisher, TEST_PUB_ARGS); +MPT_TestProcess(multi, pubpubsub, sub, hello_subscriber, TEST_SUB_ARGS); +MPT_Test(multi, pubpubsub, .init=hello_init, .fini=hello_fini); +#undef TEST_SUB_ARGS +#undef TEST_PUB_ARGS + + +/* + * The publishers expect 2 publication matched each. + * The subscribers expect 2 samples each. + */ +#define TEST_PUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubpubsubsub", 2, "pubpubsubsub") +#define TEST_SUB_ARGS MPT_ArgValues(DDS_DOMAIN_DEFAULT, "multi_pubpubsubsub", 2, "pubpubsubsub") +MPT_TestProcess(multi, pubpubsubsub, pub1, hello_publisher, TEST_PUB_ARGS); +MPT_TestProcess(multi, pubpubsubsub, pub2, hello_publisher, TEST_PUB_ARGS); +MPT_TestProcess(multi, pubpubsubsub, sub1, hello_subscriber, TEST_SUB_ARGS); +MPT_TestProcess(multi, pubpubsubsub, sub2, hello_subscriber, TEST_SUB_ARGS); +MPT_Test(multi, pubpubsubsub, .init=hello_init, .fini=hello_fini); +#undef TEST_SUB_ARGS +#undef TEST_PUB_ARGS diff --git a/src/mpt/tests/basic/procs/hello.c b/src/mpt/tests/basic/procs/hello.c new file mode 100644 index 0000000..2c68a84 --- /dev/null +++ b/src/mpt/tests/basic/procs/hello.c @@ -0,0 +1,239 @@ +#include +#include +#include + +#include "mpt/mpt.h" + +#include "dds/dds.h" +#include "helloworlddata.h" + +#include "dds/ddsrt/time.h" +#include "dds/ddsrt/strtol.h" +#include "dds/ddsrt/process.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/cdtors.h" +#include "dds/ddsrt/sync.h" + + +/* An array of one message (aka sample in dds terms) will be used. */ +#define MAX_SAMPLES 1 + +static int g_publication_matched_count = 0; +static ddsrt_mutex_t g_mutex; +static ddsrt_cond_t g_cond; + +static void +publication_matched_cb( + dds_entity_t writer, + const dds_publication_matched_status_t status, + void* arg) +{ + (void)arg; + (void)writer; + ddsrt_mutex_lock(&g_mutex); + g_publication_matched_count = (int)status.current_count; + ddsrt_cond_broadcast(&g_cond); + ddsrt_mutex_unlock(&g_mutex); +} + +static void +data_available_cb( + dds_entity_t reader, + void* arg) +{ + (void)arg; + (void)reader; + ddsrt_mutex_lock(&g_mutex); + ddsrt_cond_broadcast(&g_cond); + ddsrt_mutex_unlock(&g_mutex); +} + +void +hello_init(void) +{ + ddsrt_init(); + ddsrt_mutex_init(&g_mutex); + ddsrt_cond_init(&g_cond); +} + +void +hello_fini(void) +{ + ddsrt_cond_destroy(&g_cond); + ddsrt_mutex_destroy(&g_mutex); + ddsrt_fini(); +} + + +/* + * The HelloWorld publisher. + * It waits for a publication matched, and then writes a sample. + * It quits when the publication matched has been reset again. + */ +MPT_ProcessEntry(hello_publisher, + MPT_Args(dds_domainid_t domainid, + const char *topic_name, + int sub_cnt, + const char *text)) +{ + HelloWorldData_Msg msg; + dds_listener_t *listener; + dds_entity_t participant; + dds_entity_t topic; + dds_entity_t writer; + dds_return_t rc; + dds_qos_t *qos; + int id = (int)ddsrt_getpid(); + + assert(topic_name); + assert(text); + + printf("=== [Publisher(%d)] Start(%d) ...\n", id, domainid); + + /* + * A reliable volatile sample, written after publication matched, can still + * be lost when the subscriber wasn't able to match its subscription yet. + * Use transient_local reliable to make sure the sample is received. + */ + qos = dds_create_qos(); + dds_qset_durability(qos, DDS_DURABILITY_TRANSIENT_LOCAL); + dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_SECS(10)); + + /* Use listener to get number of publications matched. */ + listener = dds_create_listener(NULL); + MPT_ASSERT_FATAL_NOT_NULL(listener, "Could not create listener"); + dds_lset_publication_matched(listener, publication_matched_cb); + + /* Create a Writer. */ + participant = dds_create_participant (domainid, NULL, NULL); + MPT_ASSERT_FATAL_GT(participant, 0, "Could not create participant: %s\n", dds_strretcode(-participant)); + + topic = dds_create_topic ( + participant, &HelloWorldData_Msg_desc, topic_name, qos, NULL); + MPT_ASSERT_FATAL_GT(topic, 0, "Could not create topic: %s\n", dds_strretcode(-topic)); + + writer = dds_create_writer (participant, topic, qos, listener); + MPT_ASSERT_FATAL_GT(writer, 0, "Could not create writer: %s\n", dds_strretcode(-writer)); + + /* Wait for expected nr of subscriber(s). */ + ddsrt_mutex_lock(&g_mutex); + while (g_publication_matched_count != sub_cnt) { + ddsrt_cond_waitfor(&g_cond, &g_mutex, DDS_INFINITY); + } + ddsrt_mutex_unlock(&g_mutex); + + /* Write sample. */ + msg.userID = (int32_t)id; + msg.message = (char*)text; + printf("=== [Publisher(%d)] Send: { %d, %s }\n", id, msg.userID, msg.message); + rc = dds_write (writer, &msg); + MPT_ASSERT_EQ(rc, DDS_RETCODE_OK, "Could not write sample\n"); + + /* Wait for subscriber(s) to have finished. */ + ddsrt_mutex_lock(&g_mutex); + while (g_publication_matched_count != 0) { + ddsrt_cond_waitfor(&g_cond, &g_mutex, DDS_INFINITY); + } + ddsrt_mutex_unlock(&g_mutex); + + rc = dds_delete (participant); + MPT_ASSERT_EQ(rc, DDS_RETCODE_OK, "Teardown failed\n"); + + dds_delete_listener(listener); + dds_delete_qos(qos); + + printf("=== [Publisher(%d)] Done\n", id); +} + + +/* + * The HelloWorld subscriber. + * It waits for sample(s) and checks the content. + */ +MPT_ProcessEntry(hello_subscriber, + MPT_Args(dds_domainid_t domainid, + const char *topic_name, + int sample_cnt, + const char *text)) +{ + HelloWorldData_Msg *msg; + void *samples[MAX_SAMPLES]; + dds_sample_info_t infos[MAX_SAMPLES]; + dds_listener_t *listener; + dds_entity_t participant; + dds_entity_t topic; + dds_entity_t reader; + dds_return_t rc; + dds_qos_t *qos; + int recv_cnt; + int id = (int)ddsrt_getpid(); + + assert(topic_name); + assert(text); + + printf("--- [Subscriber(%d)] Start(%d) ...\n", id, domainid); + + /* + * A reliable volatile sample, written after publication matched, can still + * be lost when the subscriber wasn't able to match its subscription yet. + * Use transient_local reliable to make sure the sample is received. + */ + qos = dds_create_qos(); + dds_qset_durability(qos, DDS_DURABILITY_TRANSIENT_LOCAL); + dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_SECS(10)); + + /* Use listener to get data available trigger. */ + listener = dds_create_listener(NULL); + MPT_ASSERT_FATAL_NOT_NULL(listener, "Could not create listener"); + dds_lset_data_available(listener, data_available_cb); + + /* Create a Reader. */ + participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL); + MPT_ASSERT_FATAL_GT(participant, 0, "Could not create participant: %s\n", dds_strretcode(-participant)); + topic = dds_create_topic ( + participant, &HelloWorldData_Msg_desc, topic_name, qos, NULL); + MPT_ASSERT_FATAL_GT(topic, 0, "Could not create topic: %s\n", dds_strretcode(-topic)); + reader = dds_create_reader (participant, topic, qos, listener); + MPT_ASSERT_FATAL_GT(reader, 0, "Could not create reader: %s\n", dds_strretcode(-reader)); + + printf("--- [Subscriber(%d)] Waiting for %d sample(s) ...\n", id, sample_cnt); + + /* Initialize sample buffer, by pointing the void pointer within + * the buffer array to a valid sample memory location. */ + samples[0] = HelloWorldData_Msg__alloc (); + + /* Wait until expected nr of samples have been taken. */ + ddsrt_mutex_lock(&g_mutex); + recv_cnt = 0; + while (recv_cnt < sample_cnt) { + /* Use a take with mask to work around the #146 issue. */ + rc = dds_take_mask(reader, samples, infos, MAX_SAMPLES, MAX_SAMPLES, DDS_NEW_VIEW_STATE); + MPT_ASSERT_GEQ(rc, 0, "Could not read: %s\n", dds_strretcode(-rc)); + + /* Check if we read some data and it is valid. */ + if ((rc > 0) && (infos[0].valid_data)) { + /* Print Message. */ + msg = (HelloWorldData_Msg*)samples[0]; + printf("--- [Subscriber(%d)] Received: { %d, %s }\n", id, + msg->userID, msg->message); + MPT_ASSERT_STR_EQ(msg->message, text, + "Messages do not match: \"%s\" vs \"%s\"\n", + msg->message, text); + recv_cnt++; + } else { + ddsrt_cond_waitfor(&g_cond, &g_mutex, DDS_INFINITY); + } + } + ddsrt_mutex_unlock(&g_mutex); + + /* Free the data location. */ + HelloWorldData_Msg_free (samples[0], DDS_FREE_ALL); + + rc = dds_delete (participant); + MPT_ASSERT_EQ(rc, DDS_RETCODE_OK, "Teardown failed\n"); + + dds_delete_listener(listener); + dds_delete_qos(qos); + + printf("--- [Subscriber(%d)] Done\n", id); +} diff --git a/src/mpt/tests/basic/procs/hello.h b/src/mpt/tests/basic/procs/hello.h new file mode 100644 index 0000000..b1d1772 --- /dev/null +++ b/src/mpt/tests/basic/procs/hello.h @@ -0,0 +1,52 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +/** @file + * + * @brief DDS C Communication Status API + * + * This header file defines the public API of the Communication Status in the + * Eclipse Cyclone DDS C language binding. + */ +#ifndef MPT_BASIC_PROCS_HELLO_H +#define MPT_BASIC_PROCS_HELLO_H + +#include +#include + +#include "dds/dds.h" +#include "mpt/mpt.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +void hello_init(void); +void hello_fini(void); + +MPT_ProcessEntry(hello_publisher, + MPT_Args(dds_domainid_t domainid, + const char *topic_name, + int sub_cnt, + const char *text)); + +MPT_ProcessEntry(hello_subscriber, + MPT_Args(dds_domainid_t domainid, + const char *topic_name, + int sample_cnt, + const char *text)); + +#if defined (__cplusplus) +} +#endif + +#endif /* MPT_BASIC_PROCS_HELLO_H */ diff --git a/src/mpt/tests/basic/procs/helloworlddata.idl b/src/mpt/tests/basic/procs/helloworlddata.idl new file mode 100644 index 0000000..9561d75 --- /dev/null +++ b/src/mpt/tests/basic/procs/helloworlddata.idl @@ -0,0 +1,9 @@ +module HelloWorldData +{ + struct Msg + { + long userID; + string message; + }; + #pragma keylist Msg userID +}; diff --git a/src/mpt/tests/self/CMakeLists.txt b/src/mpt/tests/self/CMakeLists.txt new file mode 100644 index 0000000..8203b5d --- /dev/null +++ b/src/mpt/tests/self/CMakeLists.txt @@ -0,0 +1,25 @@ +# +# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +# v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# +include(${MPT_CMAKE}) + +message(STATUS "MPT selftest enabled: some test will fail deliberately") + +set(sources + "asserts.c" + "environments.c" + "fixtures.c" + "ipc.c" + "resources.c" + "usage.c") + +add_mpt_executable(mpt_self ${sources}) + diff --git a/src/mpt/tests/self/asserts.c b/src/mpt/tests/self/asserts.c new file mode 100644 index 0000000..72495a1 --- /dev/null +++ b/src/mpt/tests/self/asserts.c @@ -0,0 +1,711 @@ +#include +#include +#include "mpt/mpt.h" +#include "dds/ddsrt/time.h" + +static int dummy; + + + +/************************************************************ + * Test MPT_ASSERT + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT, MPT_Args(const char *exp, int cond)) +{ + assert(exp); + MPT_ASSERT(cond, "MPT_ASSERT(%d), 1st, expect: %s", cond, exp); + MPT_ASSERT(cond, "MPT_ASSERT(%d), 2nd, expect: %s", cond, exp); +} +MPT_TestProcess(MPT_ASSERT, pass, id, proc_MPT_ASSERT, MPT_ArgValues("PASS", 1)); +MPT_TestProcess(MPT_ASSERT, fail, id, proc_MPT_ASSERT, MPT_ArgValues("FAIL", 0)); +MPT_Test(MPT_ASSERT, pass, .xfail=false); +MPT_Test(MPT_ASSERT, fail, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FAIL + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FAIL, MPT_NoArgs()) +{ + MPT_ASSERT_FAIL("MPT_ASSERT_FAIL(), 1st, expect a fail, always"); + MPT_ASSERT_FAIL("MPT_ASSERT_FAIL(), 2nd, expect a fail, always"); +} +MPT_TestProcess(MPT_ASSERT_FAIL, call, id, proc_MPT_ASSERT_FAIL, MPT_NoArgValues()); +MPT_Test(MPT_ASSERT_FAIL, call, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_EQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_EQ_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%d, %d), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%d, %d), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_EQ_int, eq, id, proc_MPT_ASSERT_EQ_int, MPT_ArgValues("PASS", 1, 1)); +MPT_TestProcess(MPT_ASSERT_EQ_int, lt, id, proc_MPT_ASSERT_EQ_int, MPT_ArgValues("FAIL", 1, 2)); +MPT_TestProcess(MPT_ASSERT_EQ_int, gt, id, proc_MPT_ASSERT_EQ_int, MPT_ArgValues("FAIL", 3, 2)); +MPT_Test(MPT_ASSERT_EQ_int, eq, .xfail=false); +MPT_Test(MPT_ASSERT_EQ_int, lt, .xfail=true); +MPT_Test(MPT_ASSERT_EQ_int, gt, .xfail=true); + + +MPT_ProcessEntry(proc_MPT_ASSERT_EQ_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%f, %f), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%f, %f), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_EQ_double, eq, id, proc_MPT_ASSERT_EQ_double, MPT_ArgValues("PASS", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_EQ_double, lt, id, proc_MPT_ASSERT_EQ_double, MPT_ArgValues("FAIL", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_EQ_double, gt, id, proc_MPT_ASSERT_EQ_double, MPT_ArgValues("FAIL", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_EQ_double, eq, .xfail=false); +MPT_Test(MPT_ASSERT_EQ_double, lt, .xfail=true); +MPT_Test(MPT_ASSERT_EQ_double, gt, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_NEQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_NEQ_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%d, %d), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%d, %d), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_NEQ_int, eq, id, proc_MPT_ASSERT_NEQ_int, MPT_ArgValues("FAIL", 1, 1)); +MPT_TestProcess(MPT_ASSERT_NEQ_int, lt, id, proc_MPT_ASSERT_NEQ_int, MPT_ArgValues("PASS", 1, 2)); +MPT_TestProcess(MPT_ASSERT_NEQ_int, gt, id, proc_MPT_ASSERT_NEQ_int, MPT_ArgValues("PASS", 3, 2)); +MPT_Test(MPT_ASSERT_NEQ_int, eq, .xfail=true); +MPT_Test(MPT_ASSERT_NEQ_int, lt, .xfail=false); +MPT_Test(MPT_ASSERT_NEQ_int, gt, .xfail=false); + + +MPT_ProcessEntry(proc_MPT_ASSERT_NEQ_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%f, %f), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%f, %f), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_NEQ_double, eq, id, proc_MPT_ASSERT_NEQ_double, MPT_ArgValues("FAIL", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_NEQ_double, lt, id, proc_MPT_ASSERT_NEQ_double, MPT_ArgValues("PASS", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_NEQ_double, gt, id, proc_MPT_ASSERT_NEQ_double, MPT_ArgValues("PASS", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_NEQ_double, eq, .xfail=true); +MPT_Test(MPT_ASSERT_NEQ_double, lt, .xfail=false); +MPT_Test(MPT_ASSERT_NEQ_double, gt, .xfail=false); + + + +/************************************************************ + * Test MPT_ASSERT_LEQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_LEQ_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%d, %d), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%d, %d), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_LEQ_int, eq, id, proc_MPT_ASSERT_LEQ_int, MPT_ArgValues("PASS", 1, 1)); +MPT_TestProcess(MPT_ASSERT_LEQ_int, lt, id, proc_MPT_ASSERT_LEQ_int, MPT_ArgValues("PASS", 1, 2)); +MPT_TestProcess(MPT_ASSERT_LEQ_int, gt, id, proc_MPT_ASSERT_LEQ_int, MPT_ArgValues("FAIL", 3, 2)); +MPT_Test(MPT_ASSERT_LEQ_int, eq, .xfail=false); +MPT_Test(MPT_ASSERT_LEQ_int, lt, .xfail=false); +MPT_Test(MPT_ASSERT_LEQ_int, gt, .xfail=true); + + +MPT_ProcessEntry(proc_MPT_ASSERT_LEQ_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%f, %f), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%f, %f), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_LEQ_double, eq, id, proc_MPT_ASSERT_LEQ_double, MPT_ArgValues("PASS", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_LEQ_double, lt, id, proc_MPT_ASSERT_LEQ_double, MPT_ArgValues("PASS", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_LEQ_double, gt, id, proc_MPT_ASSERT_LEQ_double, MPT_ArgValues("FAIL", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_LEQ_double, eq, .xfail=false); +MPT_Test(MPT_ASSERT_LEQ_double, lt, .xfail=false); +MPT_Test(MPT_ASSERT_LEQ_double, gt, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_GEQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_GEQ_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%d, %d), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%d, %d), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_GEQ_int, eq, id, proc_MPT_ASSERT_GEQ_int, MPT_ArgValues("PASS", 1, 1)); +MPT_TestProcess(MPT_ASSERT_GEQ_int, lt, id, proc_MPT_ASSERT_GEQ_int, MPT_ArgValues("FAIL", 1, 2)); +MPT_TestProcess(MPT_ASSERT_GEQ_int, gt, id, proc_MPT_ASSERT_GEQ_int, MPT_ArgValues("PASS", 3, 2)); +MPT_Test(MPT_ASSERT_GEQ_int, eq, .xfail=false); +MPT_Test(MPT_ASSERT_GEQ_int, lt, .xfail=true); +MPT_Test(MPT_ASSERT_GEQ_int, gt, .xfail=false); + + +MPT_ProcessEntry(proc_MPT_ASSERT_GEQ_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%f, %f), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%f, %f), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_GEQ_double, eq, id, proc_MPT_ASSERT_GEQ_double, MPT_ArgValues("PASS", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_GEQ_double, lt, id, proc_MPT_ASSERT_GEQ_double, MPT_ArgValues("FAIL", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_GEQ_double, gt, id, proc_MPT_ASSERT_GEQ_double, MPT_ArgValues("PASS", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_GEQ_double, eq, .xfail=false); +MPT_Test(MPT_ASSERT_GEQ_double, lt, .xfail=true); +MPT_Test(MPT_ASSERT_GEQ_double, gt, .xfail=false); + + + +/************************************************************ + * Test MPT_ASSERT_LT + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_LT_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%d, %d), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%d, %d), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_LT_int, eq, id, proc_MPT_ASSERT_LT_int, MPT_ArgValues("FAIL", 1, 1)); +MPT_TestProcess(MPT_ASSERT_LT_int, lt, id, proc_MPT_ASSERT_LT_int, MPT_ArgValues("PASS", 1, 2)); +MPT_TestProcess(MPT_ASSERT_LT_int, gt, id, proc_MPT_ASSERT_LT_int, MPT_ArgValues("FAIL", 3, 2)); +MPT_Test(MPT_ASSERT_LT_int, eq, .xfail=true); +MPT_Test(MPT_ASSERT_LT_int, lt, .xfail=false); +MPT_Test(MPT_ASSERT_LT_int, gt, .xfail=true); + + +MPT_ProcessEntry(proc_MPT_ASSERT_LT_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%f, %f), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%f, %f), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_LT_double, eq, id, proc_MPT_ASSERT_LT_double, MPT_ArgValues("FAIL", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_LT_double, lt, id, proc_MPT_ASSERT_LT_double, MPT_ArgValues("PASS", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_LT_double, gt, id, proc_MPT_ASSERT_LT_double, MPT_ArgValues("FAIL", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_LT_double, eq, .xfail=true); +MPT_Test(MPT_ASSERT_LT_double, lt, .xfail=false); +MPT_Test(MPT_ASSERT_LT_double, gt, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_GT + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_GT_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%d, %d), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%d, %d), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_GT_int, eq, id, proc_MPT_ASSERT_GT_int, MPT_ArgValues("FAIL", 1, 1)); +MPT_TestProcess(MPT_ASSERT_GT_int, lt, id, proc_MPT_ASSERT_GT_int, MPT_ArgValues("FAIL", 1, 2)); +MPT_TestProcess(MPT_ASSERT_GT_int, gt, id, proc_MPT_ASSERT_GT_int, MPT_ArgValues("PASS", 3, 2)); +MPT_Test(MPT_ASSERT_GT_int, eq, .xfail=true); +MPT_Test(MPT_ASSERT_GT_int, lt, .xfail=true); +MPT_Test(MPT_ASSERT_GT_int, gt, .xfail=false); + + +MPT_ProcessEntry(proc_MPT_ASSERT_GT_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%f, %f), 1st expect: %s", val1, val2, exp); + MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%f, %f), 2nd expect: %s", val1, val2, exp); +} +MPT_TestProcess(MPT_ASSERT_GT_double, eq, id, proc_MPT_ASSERT_GT_double, MPT_ArgValues("FAIL", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_GT_double, lt, id, proc_MPT_ASSERT_GT_double, MPT_ArgValues("FAIL", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_GT_double, gt, id, proc_MPT_ASSERT_GT_double, MPT_ArgValues("PASS", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_GT_double, eq, .xfail=true); +MPT_Test(MPT_ASSERT_GT_double, lt, .xfail=true); +MPT_Test(MPT_ASSERT_GT_double, gt, .xfail=false); + + + +/************************************************************ + * Test MPT_ASSERT_NULL + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_NULL, MPT_Args(const char *exp, const void* ptr)) +{ + assert(exp); + MPT_ASSERT_NULL(ptr, "MPT_ASSERT_NULL(%p), expect: %s", ptr, exp); +} +MPT_TestProcess(MPT_ASSERT_NULL, addr, id, proc_MPT_ASSERT_NULL, MPT_ArgValues("FAIL", &dummy)); +MPT_TestProcess(MPT_ASSERT_NULL, null, id, proc_MPT_ASSERT_NULL, MPT_ArgValues("PASS", NULL)); +MPT_Test(MPT_ASSERT_NULL, addr, .xfail=true); +MPT_Test(MPT_ASSERT_NULL, null, .xfail=false); + + + +/************************************************************ + * Test MPT_ASSERT_NOT_NULL + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_NOT_NULL, MPT_Args(const char *exp, const void* ptr)) +{ + assert(exp); + MPT_ASSERT_NOT_NULL(ptr, "MPT_ASSERT_NOT_NULL(%p), expect: %s", ptr, exp); +} +MPT_TestProcess(MPT_ASSERT_NOT_NULL, addr, id, proc_MPT_ASSERT_NOT_NULL, MPT_ArgValues("PASS", &dummy)); +MPT_TestProcess(MPT_ASSERT_NOT_NULL, null, id, proc_MPT_ASSERT_NOT_NULL, MPT_ArgValues("FAIL", NULL)); +MPT_Test(MPT_ASSERT_NOT_NULL, addr, .xfail=false); +MPT_Test(MPT_ASSERT_NOT_NULL, null, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_STR_EQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_STR_EQ, MPT_Args(const char *exp, const char* val1, const char* val2)) +{ + assert(exp); + MPT_ASSERT_STR_EQ(val1, val2, "MPT_ASSERT_STR_EQ(%s, %s), expect: %s", + val1 ? val1 : "", + val2 ? val2 : "", + exp); +} +MPT_TestProcess(MPT_ASSERT_STR_EQ, eq, id, proc_MPT_ASSERT_STR_EQ, MPT_ArgValues("PASS", "foo", "foo")); +MPT_TestProcess(MPT_ASSERT_STR_EQ, neq, id, proc_MPT_ASSERT_STR_EQ, MPT_ArgValues("FAIL", "foo", "bar")); +MPT_TestProcess(MPT_ASSERT_STR_EQ, null1, id, proc_MPT_ASSERT_STR_EQ, MPT_ArgValues("FAIL", NULL, "foo")); +MPT_TestProcess(MPT_ASSERT_STR_EQ, null2, id, proc_MPT_ASSERT_STR_EQ, MPT_ArgValues("FAIL", "foo", NULL)); +MPT_Test(MPT_ASSERT_STR_EQ, eq, .xfail=false); +MPT_Test(MPT_ASSERT_STR_EQ, neq, .xfail=true); +MPT_Test(MPT_ASSERT_STR_EQ, null1, .xfail=true); +MPT_Test(MPT_ASSERT_STR_EQ, null2, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_STR_NEQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_STR_NEQ, MPT_Args(const char *exp, const char* val1, const char* val2)) +{ + assert(exp); + MPT_ASSERT_STR_NEQ(val1, val2, "MPT_ASSERT_STR_NEQ(%s, %s), expect: %s", + val1 ? val1 : "", + val2 ? val2 : "", + exp); +} +MPT_TestProcess(MPT_ASSERT_STR_NEQ, eq, id, proc_MPT_ASSERT_STR_NEQ, MPT_ArgValues("FAIL", "foo", "foo")); +MPT_TestProcess(MPT_ASSERT_STR_NEQ, neq, id, proc_MPT_ASSERT_STR_NEQ, MPT_ArgValues("PASS", "foo", "bar")); +MPT_TestProcess(MPT_ASSERT_STR_NEQ, null1, id, proc_MPT_ASSERT_STR_NEQ, MPT_ArgValues("FAIL", NULL, "foo")); +MPT_TestProcess(MPT_ASSERT_STR_NEQ, null2, id, proc_MPT_ASSERT_STR_NEQ, MPT_ArgValues("FAIL", "foo", NULL)); +MPT_Test(MPT_ASSERT_STR_NEQ, eq, .xfail=true); +MPT_Test(MPT_ASSERT_STR_NEQ, neq, .xfail=false); +MPT_Test(MPT_ASSERT_STR_NEQ, null1, .xfail=true); +MPT_Test(MPT_ASSERT_STR_NEQ, null2, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_STR_EMPTY + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_STR_EMPTY, MPT_Args(const char *exp, const char* val)) +{ + assert(exp); + MPT_ASSERT_STR_EMPTY(val, "MPT_ASSERT_STR_EMPTY(%s), expect: %s", + val ? val : "", + exp); +} +MPT_TestProcess(MPT_ASSERT_STR_EMPTY, nempty, id, proc_MPT_ASSERT_STR_EMPTY, MPT_ArgValues("FAIL", "foo")); +MPT_TestProcess(MPT_ASSERT_STR_EMPTY, empty, id, proc_MPT_ASSERT_STR_EMPTY, MPT_ArgValues("PASS", "")); +MPT_TestProcess(MPT_ASSERT_STR_EMPTY, null, id, proc_MPT_ASSERT_STR_EMPTY, MPT_ArgValues("FAIL", NULL)); +MPT_Test(MPT_ASSERT_STR_EMPTY, nempty, .xfail=true); +MPT_Test(MPT_ASSERT_STR_EMPTY, empty, .xfail=false); +MPT_Test(MPT_ASSERT_STR_EMPTY, null, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_STR_NOT_EMPTY + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_STR_NOT_EMPTY, MPT_Args(const char *exp, const char* val)) +{ + assert(exp); + MPT_ASSERT_STR_NOT_EMPTY(val, "MPT_ASSERT_STR_NOT_EMPTY(%s), expect: %s", + val ? val : "", + exp); +} +MPT_TestProcess(MPT_ASSERT_STR_NOT_EMPTY, nempty, id, proc_MPT_ASSERT_STR_NOT_EMPTY, MPT_ArgValues("PASS", "foo")); +MPT_TestProcess(MPT_ASSERT_STR_NOT_EMPTY, empty, id, proc_MPT_ASSERT_STR_NOT_EMPTY, MPT_ArgValues("FAIL", "")); +MPT_TestProcess(MPT_ASSERT_STR_NOT_EMPTY, null, id, proc_MPT_ASSERT_STR_NOT_EMPTY, MPT_ArgValues("FAIL", NULL)); +MPT_Test(MPT_ASSERT_STR_NOT_EMPTY, nempty, .xfail=false); +MPT_Test(MPT_ASSERT_STR_NOT_EMPTY, empty, .xfail=true); +MPT_Test(MPT_ASSERT_STR_NOT_EMPTY, null, .xfail=true); + + + +/*****************************************************************************/ + + + +/************************************************************ + * Test MPT_ASSERT_FATAL + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL, MPT_Args(const char *exp, int cond)) +{ + assert(exp); + MPT_ASSERT_FATAL(cond, "MPT_ASSERT_FATAL(%d), expect: %s", cond, exp); + MPT_ASSERT(cond, "MPT_ASSERT(%d) after a fatal", cond); +} + +MPT_TestProcess(MPT_ASSERT_FATAL, pass, id, proc_MPT_ASSERT_FATAL, MPT_ArgValues("PASS", 1)); +MPT_Test(MPT_ASSERT_FATAL, pass, .xfail=false); + +MPT_TestProcess(MPT_ASSERT_FATAL, fail, id, proc_MPT_ASSERT_FATAL, MPT_ArgValues("FAIL", 0)); +MPT_Test(MPT_ASSERT_FATAL, fail, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_FAIL + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_FAIL, MPT_NoArgs()) +{ + MPT_ASSERT_FATAL_FAIL("MPT_ASSERT_FATAL_FAIL(), expect a fail, always"); + MPT_ASSERT_FAIL("MPT_ASSERT_FAIL() after a fatal"); +} + +MPT_TestProcess(MPT_ASSERT_FATAL_FAIL, fail, id, proc_MPT_ASSERT_FATAL_FAIL, MPT_NoArgValues()); +MPT_Test(MPT_ASSERT_FATAL_FAIL, fail, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_EQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_EQ_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_EQ(val1, val2, "MPT_ASSERT_FATAL_EQ(%d, %d), expect: %s", val1, val2, exp); + MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%d, %d) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_EQ_int, eq, id, proc_MPT_ASSERT_FATAL_EQ_int, MPT_ArgValues("PASS", 1, 1)); +MPT_TestProcess(MPT_ASSERT_FATAL_EQ_int, lt, id, proc_MPT_ASSERT_FATAL_EQ_int, MPT_ArgValues("FAIL", 1, 2)); +MPT_TestProcess(MPT_ASSERT_FATAL_EQ_int, gt, id, proc_MPT_ASSERT_FATAL_EQ_int, MPT_ArgValues("FAIL", 3, 2)); +MPT_Test(MPT_ASSERT_FATAL_EQ_int, eq, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_EQ_int, lt, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_EQ_int, gt, .xfail=true); + + +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_EQ_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_EQ(val1, val2, "MPT_ASSERT_FATAL_EQ(%f, %f), expect: %s", val1, val2, exp); + MPT_ASSERT_EQ(val1, val2, "MPT_ASSERT_EQ(%f, %f) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_EQ_double, eq, id, proc_MPT_ASSERT_FATAL_EQ_double, MPT_ArgValues("PASS", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_FATAL_EQ_double, lt, id, proc_MPT_ASSERT_FATAL_EQ_double, MPT_ArgValues("FAIL", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_FATAL_EQ_double, gt, id, proc_MPT_ASSERT_FATAL_EQ_double, MPT_ArgValues("FAIL", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_FATAL_EQ_double, eq, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_EQ_double, lt, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_EQ_double, gt, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_NEQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_NEQ_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_NEQ(val1, val2, "MPT_ASSERT_FATAL_NEQ(%d, %d), expect: %s", val1, val2, exp); + MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%d, %d) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_int, eq, id, proc_MPT_ASSERT_FATAL_NEQ_int, MPT_ArgValues("FAIL", 1, 1)); +MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_int, lt, id, proc_MPT_ASSERT_FATAL_NEQ_int, MPT_ArgValues("PASS", 1, 2)); +MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_int, gt, id, proc_MPT_ASSERT_FATAL_NEQ_int, MPT_ArgValues("PASS", 3, 2)); +MPT_Test(MPT_ASSERT_FATAL_NEQ_int, eq, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_NEQ_int, lt, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_NEQ_int, gt, .xfail=false); + + +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_NEQ_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_NEQ(val1, val2, "MPT_ASSERT_FATAL_NEQ(%f, %f), expect: %s", val1, val2, exp); + MPT_ASSERT_NEQ(val1, val2, "MPT_ASSERT_NEQ(%f, %f) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_double, eq, id, proc_MPT_ASSERT_FATAL_NEQ_double, MPT_ArgValues("FAIL", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_double, lt, id, proc_MPT_ASSERT_FATAL_NEQ_double, MPT_ArgValues("PASS", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_FATAL_NEQ_double, gt, id, proc_MPT_ASSERT_FATAL_NEQ_double, MPT_ArgValues("PASS", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_FATAL_NEQ_double, eq, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_NEQ_double, lt, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_NEQ_double, gt, .xfail=false); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_LEQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_LEQ_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_LEQ(val1, val2, "MPT_ASSERT_FATAL_LEQ(%d, %d), expect: %s", val1, val2, exp); + MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%d, %d) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_int, eq, id, proc_MPT_ASSERT_FATAL_LEQ_int, MPT_ArgValues("PASS", 1, 1)); +MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_int, lt, id, proc_MPT_ASSERT_FATAL_LEQ_int, MPT_ArgValues("PASS", 1, 2)); +MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_int, gt, id, proc_MPT_ASSERT_FATAL_LEQ_int, MPT_ArgValues("FAIL", 3, 2)); +MPT_Test(MPT_ASSERT_FATAL_LEQ_int, eq, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_LEQ_int, lt, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_LEQ_int, gt, .xfail=true); + + +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_LEQ_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_LEQ(val1, val2, "MPT_ASSERT_FATAL_LEQ(%f, %f), expect: %s", val1, val2, exp); + MPT_ASSERT_LEQ(val1, val2, "MPT_ASSERT_LEQ(%f, %f) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_double, eq, id, proc_MPT_ASSERT_FATAL_LEQ_double, MPT_ArgValues("PASS", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_double, lt, id, proc_MPT_ASSERT_FATAL_LEQ_double, MPT_ArgValues("PASS", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_FATAL_LEQ_double, gt, id, proc_MPT_ASSERT_FATAL_LEQ_double, MPT_ArgValues("FAIL", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_FATAL_LEQ_double, eq, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_LEQ_double, lt, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_LEQ_double, gt, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_GEQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_GEQ_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_GEQ(val1, val2, "MPT_ASSERT_FATAL_GEQ(%d, %d), expect: %s", val1, val2, exp); + MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%d, %d) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_int, eq, id, proc_MPT_ASSERT_FATAL_GEQ_int, MPT_ArgValues("PASS", 1, 1)); +MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_int, lt, id, proc_MPT_ASSERT_FATAL_GEQ_int, MPT_ArgValues("FAIL", 1, 2)); +MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_int, gt, id, proc_MPT_ASSERT_FATAL_GEQ_int, MPT_ArgValues("PASS", 3, 2)); +MPT_Test(MPT_ASSERT_FATAL_GEQ_int, eq, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_GEQ_int, lt, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_GEQ_int, gt, .xfail=false); + + +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_GEQ_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_GEQ(val1, val2, "MPT_ASSERT_FATAL_GEQ(%f, %f), expect: %s", val1, val2, exp); + MPT_ASSERT_GEQ(val1, val2, "MPT_ASSERT_GEQ(%f, %f) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_double, eq, id, proc_MPT_ASSERT_FATAL_GEQ_double, MPT_ArgValues("PASS", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_double, lt, id, proc_MPT_ASSERT_FATAL_GEQ_double, MPT_ArgValues("FAIL", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_FATAL_GEQ_double, gt, id, proc_MPT_ASSERT_FATAL_GEQ_double, MPT_ArgValues("PASS", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_FATAL_GEQ_double, eq, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_GEQ_double, lt, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_GEQ_double, gt, .xfail=false); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_LT + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_LT_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_LT(val1, val2, "MPT_ASSERT_FATAL_LT(%d, %d), expect: %s", val1, val2, exp); + MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%d, %d) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_LT_int, eq, id, proc_MPT_ASSERT_FATAL_LT_int, MPT_ArgValues("FAIL", 1, 1)); +MPT_TestProcess(MPT_ASSERT_FATAL_LT_int, lt, id, proc_MPT_ASSERT_FATAL_LT_int, MPT_ArgValues("PASS", 1, 2)); +MPT_TestProcess(MPT_ASSERT_FATAL_LT_int, gt, id, proc_MPT_ASSERT_FATAL_LT_int, MPT_ArgValues("FAIL", 3, 2)); +MPT_Test(MPT_ASSERT_FATAL_LT_int, eq, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_LT_int, lt, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_LT_int, gt, .xfail=true); + + +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_LT_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_LT(val1, val2, "MPT_ASSERT_FATAL_LT(%f, %f), expect: %s", val1, val2, exp); + MPT_ASSERT_LT(val1, val2, "MPT_ASSERT_LT(%f, %f) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_LT_double, eq, id, proc_MPT_ASSERT_FATAL_LT_double, MPT_ArgValues("FAIL", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_FATAL_LT_double, lt, id, proc_MPT_ASSERT_FATAL_LT_double, MPT_ArgValues("PASS", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_FATAL_LT_double, gt, id, proc_MPT_ASSERT_FATAL_LT_double, MPT_ArgValues("FAIL", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_FATAL_LT_double, eq, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_LT_double, lt, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_LT_double, gt, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_GT + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_GT_int, MPT_Args(const char *exp, int val1, int val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_GT(val1, val2, "MPT_ASSERT_FATAL_GT(%d, %d), expect: %s", val1, val2, exp); + MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%d, %d) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_GT_int, eq, id, proc_MPT_ASSERT_FATAL_GT_int, MPT_ArgValues("FAIL", 1, 1)); +MPT_TestProcess(MPT_ASSERT_FATAL_GT_int, lt, id, proc_MPT_ASSERT_FATAL_GT_int, MPT_ArgValues("FAIL", 1, 2)); +MPT_TestProcess(MPT_ASSERT_FATAL_GT_int, gt, id, proc_MPT_ASSERT_FATAL_GT_int, MPT_ArgValues("PASS", 3, 2)); +MPT_Test(MPT_ASSERT_FATAL_GT_int, eq, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_GT_int, lt, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_GT_int, gt, .xfail=false); + + +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_GT_double, MPT_Args(const char *exp, double val1, double val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_GT(val1, val2, "MPT_ASSERT_FATAL_GT(%f, %f), expect: %s", val1, val2, exp); + MPT_ASSERT_GT(val1, val2, "MPT_ASSERT_GT(%f, %f) after a fatal", val1, val2); +} +MPT_TestProcess(MPT_ASSERT_FATAL_GT_double, eq, id, proc_MPT_ASSERT_FATAL_GT_double, MPT_ArgValues("FAIL", 1.1, 1.1)); +MPT_TestProcess(MPT_ASSERT_FATAL_GT_double, lt, id, proc_MPT_ASSERT_FATAL_GT_double, MPT_ArgValues("FAIL", 1.1, 1.2)); +MPT_TestProcess(MPT_ASSERT_FATAL_GT_double, gt, id, proc_MPT_ASSERT_FATAL_GT_double, MPT_ArgValues("PASS", 1.3, 1.2)); +MPT_Test(MPT_ASSERT_FATAL_GT_double, eq, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_GT_double, lt, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_GT_double, gt, .xfail=false); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_NULL + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_NULL, MPT_Args(const char *exp, const void* ptr)) +{ + assert(exp); + MPT_ASSERT_FATAL_NULL(ptr, "MPT_ASSERT_FATAL_NULL(%p), expect: %s", ptr, exp); +} +MPT_TestProcess(MPT_ASSERT_FATAL_NULL, addr, id, proc_MPT_ASSERT_FATAL_NULL, MPT_ArgValues("FAIL", &dummy)); +MPT_TestProcess(MPT_ASSERT_FATAL_NULL, null, id, proc_MPT_ASSERT_FATAL_NULL, MPT_ArgValues("PASS", NULL)); +MPT_Test(MPT_ASSERT_FATAL_NULL, addr, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_NULL, null, .xfail=false); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_NOT_NULL + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_NOT_NULL, MPT_Args(const char *exp, const void* ptr)) +{ + assert(exp); + MPT_ASSERT_FATAL_NOT_NULL(ptr, "MPT_ASSERT_FATAL_NOT_NULL(%p), expect: %s", ptr, exp); +} +MPT_TestProcess(MPT_ASSERT_FATAL_NOT_NULL, addr, id, proc_MPT_ASSERT_FATAL_NOT_NULL, MPT_ArgValues("PASS", &dummy)); +MPT_TestProcess(MPT_ASSERT_FATAL_NOT_NULL, null, id, proc_MPT_ASSERT_FATAL_NOT_NULL, MPT_ArgValues("FAIL", NULL)); +MPT_Test(MPT_ASSERT_FATAL_NOT_NULL, addr, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_NOT_NULL, null, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_STR_EQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_STR_EQ, MPT_Args(const char *exp, const char* val1, const char* val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_STR_EQ(val1, val2, "MPT_ASSERT_FATAL_STR_EQ(%s, %s), expect: %s", + val1 ? val1 : "", + val2 ? val2 : "", + exp); +} +MPT_TestProcess(MPT_ASSERT_FATAL_STR_EQ, eq, id, proc_MPT_ASSERT_FATAL_STR_EQ, MPT_ArgValues("PASS", "foo", "foo")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_EQ, neq, id, proc_MPT_ASSERT_FATAL_STR_EQ, MPT_ArgValues("FAIL", "foo", "bar")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_EQ, null1, id, proc_MPT_ASSERT_FATAL_STR_EQ, MPT_ArgValues("FAIL", NULL, "foo")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_EQ, null2, id, proc_MPT_ASSERT_FATAL_STR_EQ, MPT_ArgValues("FAIL", "foo", NULL)); +MPT_Test(MPT_ASSERT_FATAL_STR_EQ, eq, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_STR_EQ, neq, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_STR_EQ, null1, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_STR_EQ, null2, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_STR_NEQ + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_STR_NEQ, MPT_Args(const char *exp, const char* val1, const char* val2)) +{ + assert(exp); + MPT_ASSERT_FATAL_STR_NEQ(val1, val2, "MPT_ASSERT_FATAL_STR_NEQ(%s, %s), expect: %s", + val1 ? val1 : "", + val2 ? val2 : "", + exp); +} +MPT_TestProcess(MPT_ASSERT_FATAL_STR_NEQ, eq, id, proc_MPT_ASSERT_FATAL_STR_NEQ, MPT_ArgValues("FAIL", "foo", "foo")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_NEQ, neq, id, proc_MPT_ASSERT_FATAL_STR_NEQ, MPT_ArgValues("PASS", "foo", "bar")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_NEQ, null1, id, proc_MPT_ASSERT_FATAL_STR_NEQ, MPT_ArgValues("FAIL", NULL, "foo")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_NEQ, null2, id, proc_MPT_ASSERT_FATAL_STR_NEQ, MPT_ArgValues("FAIL", "foo", NULL)); +MPT_Test(MPT_ASSERT_FATAL_STR_NEQ, eq, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_STR_NEQ, neq, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_STR_NEQ, null1, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_STR_NEQ, null2, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_STR_EMPTY + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_STR_EMPTY, MPT_Args(const char *exp, const char* val)) +{ + assert(exp); + MPT_ASSERT_FATAL_STR_EMPTY(val, "MPT_ASSERT_FATAL_STR_EMPTY(%s), expect: %s", + val ? val : "", + exp); +} +MPT_TestProcess(MPT_ASSERT_FATAL_STR_EMPTY, nempty, id, proc_MPT_ASSERT_FATAL_STR_EMPTY, MPT_ArgValues("FAIL", "foo")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_EMPTY, empty, id, proc_MPT_ASSERT_FATAL_STR_EMPTY, MPT_ArgValues("PASS", "")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_EMPTY, null, id, proc_MPT_ASSERT_FATAL_STR_EMPTY, MPT_ArgValues("FAIL", NULL)); +MPT_Test(MPT_ASSERT_FATAL_STR_EMPTY, nempty, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_STR_EMPTY, empty, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_STR_EMPTY, null, .xfail=true); + + + +/************************************************************ + * Test MPT_ASSERT_FATAL_STR_NOT_EMPTY + ************************************************************/ +MPT_ProcessEntry(proc_MPT_ASSERT_FATAL_STR_NOT_EMPTY, MPT_Args(const char *exp, const char* val)) +{ + assert(exp); + MPT_ASSERT_FATAL_STR_NOT_EMPTY(val, "MPT_ASSERT_FATAL_STR_NOT_EMPTY(%s), expect: %s", + val ? val : "", + exp); +} +MPT_TestProcess(MPT_ASSERT_FATAL_STR_NOT_EMPTY, nempty, id, proc_MPT_ASSERT_FATAL_STR_NOT_EMPTY, MPT_ArgValues("PASS", "foo")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_NOT_EMPTY, empty, id, proc_MPT_ASSERT_FATAL_STR_NOT_EMPTY, MPT_ArgValues("FAIL", "")); +MPT_TestProcess(MPT_ASSERT_FATAL_STR_NOT_EMPTY, null, id, proc_MPT_ASSERT_FATAL_STR_NOT_EMPTY, MPT_ArgValues("FAIL", NULL)); +MPT_Test(MPT_ASSERT_FATAL_STR_NOT_EMPTY, nempty, .xfail=false); +MPT_Test(MPT_ASSERT_FATAL_STR_NOT_EMPTY, empty, .xfail=true); +MPT_Test(MPT_ASSERT_FATAL_STR_NOT_EMPTY, null, .xfail=true); + + + +/*****************************************************************************/ + + + +/************************************************************ + * Test propagation, + * Check if failure/success is actually propagated to ctest. + ************************************************************/ +MPT_ProcessEntry(proc_propagation, MPT_Args(const char *exp, int cond, dds_duration_t delay)) +{ + assert(exp); + if (delay > 0) { + dds_sleepfor(delay); + } + MPT_ASSERT(cond, "MPT_ASSERT(%d), expect: %s", cond, exp); +} +/* This should pass in the ctest results. */ +MPT_TestProcess(propagation, pass, id1, proc_propagation, MPT_ArgValues("PASS", 1, 0)); +MPT_TestProcess(propagation, pass, id2, proc_propagation, MPT_ArgValues("PASS", 1, 0)); +MPT_Test(propagation, pass); +/* This should fail in the ctest results. */ +MPT_TestProcess(propagation, fail_1st, id1, proc_propagation, MPT_ArgValues("FAIL", 0, 0)); +MPT_TestProcess(propagation, fail_1st, id2, proc_propagation, MPT_ArgValues("PASS", 1, DDS_SECS(1))); +MPT_Test(propagation, fail_1st); +/* This should fail in the ctest results. */ +MPT_TestProcess(propagation, fail_2nd, id1, proc_propagation, MPT_ArgValues("PASS", 1, 0)); +MPT_TestProcess(propagation, fail_2nd, id2, proc_propagation, MPT_ArgValues("FAIL", 0, DDS_SECS(1))); +MPT_Test(propagation, fail_2nd); + diff --git a/src/mpt/tests/self/environments.c b/src/mpt/tests/self/environments.c new file mode 100644 index 0000000..9b6dc97 --- /dev/null +++ b/src/mpt/tests/self/environments.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include "mpt/mpt.h" +#include "mpt/resource.h" /* MPT_SOURCE_ROOT_DIR */ +#include "dds/ddsrt/environ.h" + + + +/************************************************************ + * Process + ************************************************************/ +MPT_ProcessEntry(proc_environments, MPT_Args(mpt_env_t *exp)) +{ + assert(exp); + while ((exp->name != NULL) && (exp->value != NULL)) { + /* The environment variable value should match the expected value. */ + char *ptr = NULL; + ddsrt_getenv(exp->name, &ptr); + if (ptr) { + MPT_ASSERT((strcmp(exp->value, ptr) == 0), "%s: found \"%s\", expected \"%s\"", exp->name, ptr, exp->value); + } else { + MPT_ASSERT(0, "Expected \"%s\" not found in environment", exp->name); + } + exp++; + } +} + + + +/************************************************************ + * Basic environment tests + ************************************************************/ +static mpt_env_t environ_basic[] = { + { "MY_ENV_VAR1", "1" }, + { "MY_ENV_VAR2", "2" }, + { NULL, NULL } +}; + +MPT_TestProcess(environment, proc, id, proc_environments, MPT_ArgValues(environ_basic), .environment=environ_basic); +MPT_Test(environment, proc); + +MPT_TestProcess(environment, test, id, proc_environments, MPT_ArgValues(environ_basic)); +MPT_Test(environment, test, .environment=environ_basic); + + + +/************************************************************ + * Expanding variables environment tests + ************************************************************/ +static mpt_env_t environ_expand[] = { + { "1", "b" }, + { "2", "${1}l" }, + { "3", "${2}aat" }, + { "4", "bla${1}${2}a${3}" }, + { NULL, NULL } +}; +static mpt_env_t expect_expand[] = { + { "1", "b" }, + { "2", "bl" }, + { "3", "blaat" }, + { "4", "blabblablaat" }, + { NULL, NULL } +}; + +MPT_TestProcess(environment, expand_proc, id, proc_environments, MPT_ArgValues(expect_expand), .environment=environ_expand); +MPT_Test(environment, expand_proc); + +MPT_TestProcess(environment, expand_test, id, proc_environments, MPT_ArgValues(expect_expand)); +MPT_Test(environment, expand_test, .environment=environ_expand); + + + +/************************************************************ + * Environment inheritance test + ************************************************************/ +static mpt_env_t environ_test[] = { + { "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/self/etc" }, + { "OVERRULE", "NO" }, + { NULL, NULL } +}; +static mpt_env_t environ_proc[] = { + { "CYCLONE_URI", "file://${ETC_DIR}/ospl.xml" }, + { "OVERRULE", "YES" }, + { "EXTRA", "proc" }, + { NULL, NULL } +}; +static mpt_env_t environ_test_proc[] = { + { "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/self/etc" }, + { "CYCLONE_URI", "file://"MPT_SOURCE_ROOT_DIR"/tests/self/etc/ospl.xml" }, + { "OVERRULE", "YES" }, + { "EXTRA", "proc" }, + { NULL, NULL } +}; +MPT_TestProcess(environment, inheritance, id, proc_environments, MPT_ArgValues(environ_test_proc), .environment=environ_proc); +MPT_Test(environment, inheritance, .environment=environ_test); diff --git a/src/mpt/tests/self/etc/file b/src/mpt/tests/self/etc/file new file mode 100644 index 0000000..e69de29 diff --git a/src/mpt/tests/self/fixtures.c b/src/mpt/tests/self/fixtures.c new file mode 100644 index 0000000..25b5782 --- /dev/null +++ b/src/mpt/tests/self/fixtures.c @@ -0,0 +1,72 @@ +#include +#include "mpt/mpt.h" +#include "mpt/resource.h" /* MPT_SOURCE_ROOT_DIR */ +#include "dds/ddsrt/time.h" + + + +/************************************************************ + * Support functions + ************************************************************/ +static int g_initcnt = 0; +static void init_inc(void) +{ + g_initcnt++; +}; + + + +/************************************************************ + * Processes + ************************************************************/ +MPT_ProcessEntry(proc_initcnt, MPT_Args(int init)) +{ + MPT_ASSERT((g_initcnt == init), "init count: %d vs %d", g_initcnt, init); +} + +MPT_ProcessEntry(proc_sleep, MPT_Args(dds_duration_t delay)) +{ + MPT_ASSERT((delay > 0), "basically just to satisfy the compiler"); + dds_sleepfor(delay); +} + + + +/************************************************************ + * Init fixture tests + ************************************************************/ +MPT_TestProcess(init, none, id, proc_initcnt, MPT_ArgValues(0)); +MPT_Test(init, none); + +MPT_TestProcess(init, null, id, proc_initcnt, MPT_ArgValues(0), .init=NULL); +MPT_Test(init, null, .init=NULL); + +MPT_TestProcess(init, proc, id, proc_initcnt, MPT_ArgValues(1), .init=init_inc); +MPT_Test(init, proc); + +MPT_TestProcess(init, test, id, proc_initcnt, MPT_ArgValues(1)); +MPT_Test(init, test, .init=init_inc); + +MPT_TestProcess(init, test_proc, id, proc_initcnt, MPT_ArgValues(2), .init=init_inc); +MPT_Test(init, test_proc, .init=init_inc); + + + +/************************************************************ + * Disable fixture tests + ************************************************************/ +MPT_TestProcess(disabled, _true, id, proc_initcnt, MPT_ArgValues(0)); +MPT_Test(disabled, _true, .disabled=true); + +MPT_TestProcess(disabled, _false, id, proc_initcnt, MPT_ArgValues(0)); +MPT_Test(disabled, _false, .disabled=false); + + + +/************************************************************ + * Timeout fixture tests + ************************************************************/ +/* See if a child process is killed when the parent is killed. + * This can only really be done manually, unfortunately. */ +MPT_TestProcess(timeout, child_culling, id, proc_sleep, MPT_ArgValues(DDS_SECS(120))); +MPT_Test(timeout, child_culling, .timeout=1); diff --git a/src/mpt/tests/self/ipc.c b/src/mpt/tests/self/ipc.c new file mode 100644 index 0000000..932c6e6 --- /dev/null +++ b/src/mpt/tests/self/ipc.c @@ -0,0 +1,29 @@ +#include +#include "mpt/mpt.h" + + + +/************************************************************ + * Processes + ************************************************************/ +MPT_ProcessEntry(proc_ipc_send, MPT_NoArgs()) +{ + /* This will fail and cause an internal MPT assert as long + * as IPC is not yet implemented. */ + MPT_Send("todo: implement"); +} +MPT_ProcessEntry(proc_ipc_wait, MPT_NoArgs()) +{ + /* This will fail and cause an internal MPT assert as long + * as IPC is not yet implemented. */ + MPT_Wait("todo: implement"); +} + + + +/************************************************************ + * Tests + ************************************************************/ +MPT_TestProcess(ipc, TODO, id1, proc_ipc_send, MPT_NoArgValues()); +MPT_TestProcess(ipc, TODO, id2, proc_ipc_wait, MPT_NoArgValues()); +MPT_Test(ipc, TODO); diff --git a/src/mpt/tests/self/resources.c b/src/mpt/tests/self/resources.c new file mode 100644 index 0000000..9cba731 --- /dev/null +++ b/src/mpt/tests/self/resources.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include "mpt/mpt.h" +#include "mpt/resource.h" /* MPT_SOURCE_ROOT_DIR */ + +/************************************************************ + * Processes + ************************************************************/ +MPT_ProcessEntry(proc_file, MPT_NoArgs()) +{ + const char *test_file = MPT_SOURCE_ROOT_DIR"/tests/self/etc/file"; +#if _WIN32 + struct _stat buffer; + int ret = _stat(test_file,&buffer); +#else + struct stat buffer; + int ret = stat(test_file,&buffer); +#endif + MPT_ASSERT((ret == 0), "%s", test_file); +} + + + +/************************************************************ + * Test if MPT_SOURCE_ROOT_DIR is a valid location. + ************************************************************/ +MPT_TestProcess(resources, root_dir, id, proc_file, MPT_NoArgValues()); +MPT_Test(resources, root_dir); + diff --git a/src/mpt/tests/self/usage.c b/src/mpt/tests/self/usage.c new file mode 100644 index 0000000..1621810 --- /dev/null +++ b/src/mpt/tests/self/usage.c @@ -0,0 +1,186 @@ +#include +#include "mpt/mpt.h" +#include "mpt/resource.h" /* MPT_SOURCE_ROOT_DIR */ + + +/****************************************************************************** + * First, we need a process entry-point that can be used in tests. + *****************************************************************************/ +/* | name | arguments | */ +MPT_ProcessEntry(proc_noargs, MPT_NoArgs()) +{ + // Do stuff + + // The test processes will use asserts to indicate success/failures. + MPT_ASSERT(1, "The problem is: %s", "existential crisis"); + + // No need to return anything, that's handled by the assert calls. +} + +/****************************************************************************** + * A process entry-point can have arguments. + *****************************************************************************/ +/* | name | arguments | */ +MPT_ProcessEntry(proc_args, MPT_Args(int domain, const char* text)) +{ + int expected = 1; + MPT_ASSERT(expected == domain, "proc_args(%d, %s)", domain, text); +} + +/****************************************************************************** + * Process entry-points can communicate to be able to sync fi. + *****************************************************************************/ +MPT_ProcessEntry(proc_recv, MPT_NoArgs()) +{ + /* This will wait until another process sends the same string. */ + MPT_Wait("some state reached"); +} +MPT_ProcessEntry(proc_send, MPT_NoArgs()) +{ + /* If this fails, an internal MPT_ASSERT will be triggered. + * The same is true for MPT_Wait(). */ + MPT_Send("some state reached"); +} + + + +/****************************************************************************** + * Test: suitename_testA + ****************************************************************************** + * A simple test that starts two processes. Because a test can use the same + * process entry-point to start multiple processes, each process has to have + * its own unique id within the test. + */ +/* | process identification | entry-point | arguments | */ +MPT_TestProcess(suitename, testA, id1, proc_noargs, MPT_NoArgValues()); +MPT_TestProcess(suitename, testA, id2, proc_noargs, MPT_NoArgValues()); +MPT_Test(suitename, testA); + + + + +/****************************************************************************** + * Test: suitename_testB + ****************************************************************************** + * Of course, different processes can be started as well. + * Argument values are provided per test process. + */ +MPT_TestProcess(suitename, testB, id1, proc_noargs, MPT_NoArgValues( )); +MPT_TestProcess(suitename, testB, id2, proc_args, MPT_ArgValues(1, "2")); +MPT_TestProcess(suitename, testB, id3, proc_args, MPT_ArgValues(1, "3")); +MPT_Test(suitename, testB); + + + + +/****************************************************************************** + * Test: suitename_testC + ****************************************************************************** + * The processes can have different or equal 'system environments'. + */ +mpt_env_t environment_C1[] = { + { "CYCLONEDDS_URI", "file://config1.xml" }, + { "PERMISSIONS", "file://permissions.p7s" }, + { "GOVERNANCE", "file://governance.p7s" }, + { NULL, NULL } +}; +mpt_env_t environment_C2[] = { + { "CYCLONEDDS_URI", "file://config2.xml" }, + { "PERMISSIONS", "file://permissions.p7s" }, + { "GOVERNANCE", "file://governance.p7s" }, + { NULL, NULL } +}; +MPT_TestProcess(suitename, testC, id1, proc_noargs, MPT_NoArgValues(), .environment=environment_C1); +MPT_TestProcess(suitename, testC, id2, proc_noargs, MPT_NoArgValues(), .environment=environment_C1); +MPT_TestProcess(suitename, testC, id3, proc_noargs, MPT_NoArgValues(), .environment=environment_C2); +MPT_Test(suitename, testC); + + + + +/****************************************************************************** + * Test: suitename_testD + ****************************************************************************** + * The two environments in the previous example are partly the same. + * It's possible set the environment on test level. The environment variables + * related to the test are set before the ones related to a process. This + * means that a process can overrule variables. + * + * The following test is the same as the previous one. + */ +mpt_env_t environment_D1[] = { + { "CYCLONEDDS_URI", "file://config1.xml" }, + { "PERMISSIONS", "file://permissions.p7s" }, + { "GOVERNANCE", "file://governance.p7s" }, + { NULL, NULL } +}; +mpt_env_t environment_D2[] = { + { "CYCLONEDDS_URI", "file://config2.xml" }, + { NULL, NULL } +}; +MPT_TestProcess(suitename, testD, id1, proc_noargs, MPT_NoArgValues()); +MPT_TestProcess(suitename, testD, id2, proc_noargs, MPT_NoArgValues()); +MPT_TestProcess(suitename, testD, id3, proc_noargs, MPT_NoArgValues(), .environment=environment_D2); +MPT_Test(suitename, testD, .environment=environment_D1); + + + + +/****************************************************************************** + * Test: suitename_testE + ****************************************************************************** + * Environment variables will be expanded. + * Also, the MPT_SOURCE_ROOT_DIR define contains a string to that particular + * directory. + * This can be combined to easily point to files. + */ +mpt_env_t environment_E[] = { + { "ETC_DIR", MPT_SOURCE_ROOT_DIR"/tests/self/etc" }, + { "CYCLONEDDS_URI", "file://${ETC_DIR}/config.xml" }, + { NULL, NULL } +}; +MPT_TestProcess(suitename, testE, id, proc_noargs, MPT_NoArgValues(), .environment=environment_E); +MPT_Test(suitename, testE); + + + + +/****************************************************************************** + * Test: suitename_testF + ****************************************************************************** + * The processes and tests can use init/fini fixtures. + * The test init is executed before the process init. + * The process fini is executed before the test fini. + */ +void proc_setup(void) { /* do stuff */ } +void proc_teardown(void) { /* do stuff */ } +void test_setup(void) { /* do stuff */ } +void test_teardown(void) { /* do stuff */ } +MPT_TestProcess(suitename, testF, id1, proc_noargs, MPT_NoArgValues(), .init=proc_setup); +MPT_TestProcess(suitename, testF, id2, proc_noargs, MPT_NoArgValues(), .fini=proc_teardown); +MPT_TestProcess(suitename, testF, id3, proc_noargs, MPT_NoArgValues(), .init=proc_setup, .fini=proc_teardown); +MPT_Test(suitename, testF, .init=test_setup, .fini=test_teardown); + + + + +/****************************************************************************** + * Test: suitename_testG + ****************************************************************************** + * The timeout and disable options are handled by test fixtures. + */ +MPT_TestProcess(suitename, testG, id1, proc_noargs, MPT_NoArgValues()); +MPT_TestProcess(suitename, testG, id2, proc_noargs, MPT_NoArgValues()); +MPT_Test(suitename, testG, .timeout=10, .disabled=true); + + + + +/****************************************************************************** + * Test: suitename_testH + ****************************************************************************** + * See the process entries to notice the MPT Send/Wait IPC. + */ +MPT_TestProcess(suitename, testH, id1, proc_recv, MPT_NoArgValues()); +MPT_TestProcess(suitename, testH, id2, proc_send, MPT_NoArgValues()); +MPT_Test(suitename, testH); From 077939939140091f62283ab9eeb02d019d443ab7 Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Thu, 11 Apr 2019 14:10:08 +0200 Subject: [PATCH 044/238] Moved expand_envvars. Signed-off-by: Martin Bremmer --- src/core/ddsi/src/q_config.c | 1 + src/ddsrt/include/dds/ddsrt/environ.h | 44 +++++++++++ src/ddsrt/tests/environ.c | 105 +++++++++++++++++++++++++- src/mpt/mpt/cmake/MPT.cmake | 9 --- src/mpt/mpt/src/main.c.in | 3 +- 5 files changed, 150 insertions(+), 12 deletions(-) diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 5a412e8..bf1781d 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -22,6 +22,7 @@ #include "dds/ddsrt/string.h" #include "dds/ddsrt/strtod.h" #include "dds/ddsrt/misc.h" +#include "dds/ddsrt/environ.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" #include "dds/ddsrt/avl.h" diff --git a/src/ddsrt/include/dds/ddsrt/environ.h b/src/ddsrt/include/dds/ddsrt/environ.h index 48953c2..67a8c29 100644 --- a/src/ddsrt/include/dds/ddsrt/environ.h +++ b/src/ddsrt/include/dds/ddsrt/environ.h @@ -96,6 +96,50 @@ ddsrt_unsetenv( const char *name) ddsrt_nonnull_all; +/** + * @brief Expand environment variables within string. + * + * Expands ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, but not $X. + * + * The result string should be freed with ddsrt_free(). + * + * @param[in] string String to expand. + * + * @returns Allocated char*. + * + * @retval NULL + * Expansion failed. + * @retval Pointer + * Copy of the string argument with the environment + * variables expanded. + */ +DDS_EXPORT char* +ddsrt_expand_envvars( + const char *string); + +/** + * @brief Expand environment variables within string. + * + * Expands $X, ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, $ and \ + * can be escaped with \. + * + * The result string should be freed with ddsrt_free(). + * + * @param[in] string String to expand. + * + * @returns Allocated char*. + * + * @retval NULL + * Expansion failed. + * @retval Pointer + * Copy of the string argument with the environment + * variables expanded. + */ +DDS_EXPORT char* +ddsrt_expand_envvars_sh( + const char *string); + + #if defined(__cplusplus) } #endif diff --git a/src/ddsrt/tests/environ.c b/src/ddsrt/tests/environ.c index 56f7468..b69acf4 100644 --- a/src/ddsrt/tests/environ.c +++ b/src/ddsrt/tests/environ.c @@ -14,6 +14,7 @@ #include "CUnit/Theory.h" #include "dds/ddsrt/environ.h" #include "dds/ddsrt/misc.h" +#include "dds/ddsrt/heap.h" CU_TheoryDataPoints(ddsrt_environ, bad_name) = { CU_DataPoints(const char *, "", "foo=") @@ -91,8 +92,110 @@ CU_Test(ddsrt_environ, getenv) CU_ASSERT_STRING_EQUAL(ptr, "bar"); } - /* Ensure environement is as it was. */ + /* Ensure environment is as it was. */ rc = ddsrt_unsetenv(name); CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK); } +CU_TheoryDataPoints(ddsrt_environ, expand) = { + CU_DataPoints(const char *, + "${X}", "$X", "X", "${Y}", "${Q}", "${X", + "${X:-ALT}", "${Q:-ALT}", "${X:-${Y}}", "${Q:-${Y}}", "${X:-$Y}", "${Q:-$Y}", "${X:-}", "${Q:-}", + "${X:+SET}", "${Q:+SET}", "${X:+${Y}}", "${Q:+${Y}}", "${X:+$Y}", "${Q:+$Y}", "${X:+}", "${Q:+}", + "${X:?SET}", "${Q:?SET}", "${X:?${Y}}", "${Q:?${Y}}", "${X:?$Y}", "${Q:?$Y}", "${X:?}", "${Q:?}"), + CU_DataPoints(const char *, + "TEST", "$X", "X", "FOO", "", NULL, + "TEST", "ALT", "TEST", "FOO", "TEST", "$Y", "TEST", "", + "SET", "", "FOO", "", "$Y", "", "", "", + "TEST", NULL, "TEST", NULL, "TEST", NULL, "TEST", NULL) +}; +CU_Theory((const char *var, const char *expect), ddsrt_environ, expand) +{ + dds_retcode_t rc; + static const char x_name[] = "X"; + static const char x_value[] = "TEST"; + static const char y_name[] = "Y"; + static const char y_value[] = "FOO"; + char *ptr; + + /* Ensure that the vars are not used yet. */ + rc = ddsrt_unsetenv(x_name); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); + rc = ddsrt_unsetenv(y_name); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); + + /* Set the env vars to check expansion. */ + rc = ddsrt_setenv(x_name, x_value); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); + rc = ddsrt_setenv(y_name, y_value); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); + + /* Expand a string with available environment variables. */ + ptr = ddsrt_expand_envvars(var); + if (ptr) { + /* printf("==== %10s: expand(%s), expect(%s))\n", var, ptr, expect); */ + CU_ASSERT_STRING_EQUAL(ptr, expect); + ddsrt_free(ptr); + } else { + /* printf("==== %10s: expand(), expect())\n", var ? var : ""); */ + CU_ASSERT_PTR_NULL(expect); + } + + /* Ensure to reset the environment is as it was. */ + rc = ddsrt_unsetenv(y_name); + CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK); + rc = ddsrt_unsetenv(x_name); + CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK); +} + + +CU_TheoryDataPoints(ddsrt_environ, expand_sh) = { + CU_DataPoints(const char *, + "${X}", "$X", "X", "${Y}", "${Q}", "${X", + "${X:-ALT}", "${Q:-ALT}", "${X:-${Y}}", "${Q:-${Y}}", "${X:-$Y}", "${Q:-$Y}", "${X:-}", "${Q:-}", + "${X:+SET}", "${Q:+SET}", "${X:+${Y}}", "${Q:+${Y}}", "${X:+$Y}", "${Q:+$Y}", "${X:+}", "${Q:+}", + "${X:?SET}", "${Q:?SET}", "${X:?${Y}}", "${Q:?${Y}}", "${X:?$Y}", "${Q:?$Y}", "${X:?}", "${Q:?}"), + CU_DataPoints(const char *, + "TEST", "TEST", "X", "FOO", "", NULL, + "TEST", "ALT", "TEST", "FOO", "TEST", "FOO", "TEST", "", + "SET", "", "FOO", "", "FOO", "", "", "", + "TEST", NULL, "TEST", NULL, "TEST", NULL, "TEST", NULL) +}; +CU_Theory((const char *var, const char *expect), ddsrt_environ, expand_sh) +{ + dds_retcode_t rc; + static const char x_name[] = "X"; + static const char x_value[] = "TEST"; + static const char y_name[] = "Y"; + static const char y_value[] = "FOO"; + char *ptr; + + /* Ensure that the vars are not used yet. */ + rc = ddsrt_unsetenv(x_name); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); + rc = ddsrt_unsetenv(y_name); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); + + /* Set the env vars to check expansion. */ + rc = ddsrt_setenv(x_name, x_value); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); + rc = ddsrt_setenv(y_name, y_value); + CU_ASSERT_EQUAL_FATAL(rc, DDS_RETCODE_OK); + + /* Expand a string with available environment variables. */ + ptr = ddsrt_expand_envvars_sh(var); + if (ptr) { + /* printf("==== %10s: expand(%s), expect(%s))\n", var, ptr, expect); */ + CU_ASSERT_STRING_EQUAL(ptr, expect); + ddsrt_free(ptr); + } else { + /* printf("==== %10s: expand(), expect())\n", var ? var : ""); */ + CU_ASSERT_PTR_NULL(expect); + } + + /* Ensure to reset the environment is as it was. */ + rc = ddsrt_unsetenv(y_name); + CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK); + rc = ddsrt_unsetenv(x_name); + CU_ASSERT_EQUAL(rc, DDS_RETCODE_OK); +} diff --git a/src/mpt/mpt/cmake/MPT.cmake b/src/mpt/mpt/cmake/MPT.cmake index fd50b5b..a9fad3d 100644 --- a/src/mpt/mpt/cmake/MPT.cmake +++ b/src/mpt/mpt/cmake/MPT.cmake @@ -171,14 +171,5 @@ function(add_mpt_executable TARGET) target_include_directories(${TARGET} PRIVATE "${MPT_DIR}/include" "${MPT_BINARY_ROOT_DIR}/mpt/include") target_link_libraries(${TARGET} PRIVATE ddsc) - - # We need the 'expand environment variables' feature that is present in the - # 'util' module. However, it is currently not possible to properly link to - # that module on Windows. In the near future, the utils will be migrated to - # ddsrt, after which we automatically have access to expand_envvars. - # But until then, use this very ugly (but quick) hack to solve our immediate - # build issues. - target_include_directories(${TARGET} PRIVATE "${CMAKE_SOURCE_DIR}/util/include") - target_sources(${TARGET} PRIVATE "${CMAKE_SOURCE_DIR}/util/src/ut_expand_envvars.c") endfunction() diff --git a/src/mpt/mpt/src/main.c.in b/src/mpt/mpt/src/main.c.in index 31f0689..fb5aaba 100644 --- a/src/mpt/mpt/src/main.c.in +++ b/src/mpt/mpt/src/main.c.in @@ -6,7 +6,6 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/process.h" #include "dds/ddsrt/environ.h" -#include "dds/util/ut_expand_envvars.h" #ifndef _WIN32 #include @@ -63,7 +62,7 @@ mpt_export_env(const mpt_env_t *env) { if (env) { while ((env->name != NULL) && (env->value != NULL)) { - char *expanded = ut_expand_envvars(env->value); + char *expanded = ddsrt_expand_envvars(env->value); ddsrt_setenv(env->name, expanded); ddsrt_free(expanded); env++; From 955f933ae2a011a883a580618b592b9854932a88 Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Thu, 11 Apr 2019 14:17:47 +0200 Subject: [PATCH 045/238] Fixed proc compile warning. Signed-off-by: Martin Bremmer --- src/ddsrt/src/process/posix/process.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ddsrt/src/process/posix/process.c b/src/ddsrt/src/process/posix/process.c index f6ed5db..d9c4c72 100644 --- a/src/ddsrt/src/process/posix/process.c +++ b/src/ddsrt/src/process/posix/process.c @@ -22,6 +22,7 @@ #include "dds/ddsrt/process.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/heap.h" +#include "dds/ddsrt/log.h" ddsrt_pid_t @@ -196,7 +197,9 @@ ddsrt_proc_create( /* If executing this, something has gone wrong */ exec_err = errno; - (void)write(exec_fds[1], &exec_err, sizeof(int)); + if (write(exec_fds[1], &exec_err, sizeof(int)) < (ssize_t)sizeof(int)) { + DDS_ERROR("Could not write proc error pipe.\n"); + } close(exec_fds[1]); close(exec_fds[0]); ddsrt_free(exec_argv); From 289322a33d3efa2161775540dd9d63d4f804788b Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Fri, 19 Apr 2019 14:42:31 +0200 Subject: [PATCH 046/238] Improved mpt default timeout. Signed-off-by: Martin Bremmer --- src/mpt/CMakeLists.txt | 1 + src/mpt/mpt/cmake/MPT.cmake | 4 +--- src/mpt/mpt/include/mpt/mpt.h | 1 - src/mpt/mpt/include/mpt/resource.h.in | 1 + src/mpt/mpt/src/main.c.in | 5 ++--- src/mpt/tests/self/fixtures.c | 3 +++ 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/mpt/CMakeLists.txt b/src/mpt/CMakeLists.txt index 4b759c7..5c9ec7f 100644 --- a/src/mpt/CMakeLists.txt +++ b/src/mpt/CMakeLists.txt @@ -16,6 +16,7 @@ option(MPT_ENABLE_SELFTEST "Enable multi-process test-framework self test" OFF) set(MPT_CMAKE "${CMAKE_CURRENT_SOURCE_DIR}/mpt/cmake/MPT.cmake") set(MPT_SOURCE_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") set(MPT_BINARY_ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}") +set(MPT_DEFAULT_TIMEOUT "60") add_subdirectory(mpt) add_subdirectory(tests) diff --git a/src/mpt/mpt/cmake/MPT.cmake b/src/mpt/mpt/cmake/MPT.cmake index a9fad3d..fa57c2b 100644 --- a/src/mpt/mpt/cmake/MPT.cmake +++ b/src/mpt/mpt/cmake/MPT.cmake @@ -11,8 +11,6 @@ # set(MPT_DIR "${CMAKE_CURRENT_LIST_DIR}/..") - - function(parse_mpt_fixtures INPUT TEST_DISABLED TEST_TIMEOUT TEST_XFAIL) set(s "[ \t\r\n]") if(INPUT MATCHES ".disabled${s}*=${s}*([tT][rR][uU][eE]|[0-9]+)") @@ -24,7 +22,7 @@ function(parse_mpt_fixtures INPUT TEST_DISABLED TEST_TIMEOUT TEST_XFAIL) if(INPUT MATCHES ".timeout${s}*=${s}*([0-9]+)") set(${TEST_TIMEOUT} "${CMAKE_MATCH_1}" PARENT_SCOPE) else() - set(${TEST_TIMEOUT} "0" PARENT_SCOPE) + set(${TEST_TIMEOUT} "${MPT_DEFAULT_TIMEOUT}" PARENT_SCOPE) endif() if(INPUT MATCHES ".xfail${s}*=${s}*([tT][rR][uU][eE]|[0-9]+)") diff --git a/src/mpt/mpt/include/mpt/mpt.h b/src/mpt/mpt/include/mpt/mpt.h index 8d0522a..719c9d6 100644 --- a/src/mpt/mpt/include/mpt/mpt.h +++ b/src/mpt/mpt/include/mpt/mpt.h @@ -154,5 +154,4 @@ MPT_TestFiniDeclaration(suite, test) \ /* Helpful function to check for patterns in log callbacks. */ int mpt_patmatch(const char *pat, const char *str); - #endif /* MPT_H_INCLUDED */ diff --git a/src/mpt/mpt/include/mpt/resource.h.in b/src/mpt/mpt/include/mpt/resource.h.in index 13c5711..258e597 100644 --- a/src/mpt/mpt/include/mpt/resource.h.in +++ b/src/mpt/mpt/include/mpt/resource.h.in @@ -2,5 +2,6 @@ #define MPT_RESOURCE_H_INCLUDED #define MPT_SOURCE_ROOT_DIR "@MPT_SOURCE_ROOT_DIR@" +#define MPT_DEFAULT_TIMEOUT (@MPT_DEFAULT_TIMEOUT@) /* Seconds. */ #endif /* MPT_RESOURCE_H_INCLUDED */ diff --git a/src/mpt/mpt/src/main.c.in b/src/mpt/mpt/src/main.c.in index fb5aaba..14ca113 100644 --- a/src/mpt/mpt/src/main.c.in +++ b/src/mpt/mpt/src/main.c.in @@ -157,10 +157,9 @@ mpt_test_new(const char* name, int secs, bool xf) * So, make sure that the 'manual' timeout takes longer than the ctest * timeout. */ if (secs == 0) { - test->timeout = DDS_SECS(1600); - } else { - test->timeout = DDS_SECS(secs * 2); + secs = MPT_DEFAULT_TIMEOUT; } + test->timeout = DDS_SECS(secs + 5); return test; } diff --git a/src/mpt/tests/self/fixtures.c b/src/mpt/tests/self/fixtures.c index 25b5782..a07bc6f 100644 --- a/src/mpt/tests/self/fixtures.c +++ b/src/mpt/tests/self/fixtures.c @@ -70,3 +70,6 @@ MPT_Test(disabled, _false, .disabled=false); * This can only really be done manually, unfortunately. */ MPT_TestProcess(timeout, child_culling, id, proc_sleep, MPT_ArgValues(DDS_SECS(120))); MPT_Test(timeout, child_culling, .timeout=1); + +MPT_TestProcess(timeout, default_timeout, id, proc_sleep, MPT_ArgValues(DDS_SECS(120))); +MPT_Test(timeout, default_timeout); From 5a04db973ad1b4d6c8d5ff1fa8dbcd68d9665338 Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Wed, 24 Apr 2019 15:13:30 +0200 Subject: [PATCH 047/238] Be sure to not trigger the SIGCHLD Signed-off-by: Martin Bremmer --- src/ddsrt/src/process/posix/process.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ddsrt/src/process/posix/process.c b/src/ddsrt/src/process/posix/process.c index d9c4c72..d42877f 100644 --- a/src/ddsrt/src/process/posix/process.c +++ b/src/ddsrt/src/process/posix/process.c @@ -181,6 +181,9 @@ ddsrt_proc_create( goto fail_fctl; } + /* Be sure to not trigger the SIGCHLD. */ + signal(SIGCHLD, SIG_DFL); + /* Create a new process. */ spawn = fork(); if (spawn == -1) From 14a62ae3cb126caaf3f4f40a125d3a447b470a5d Mon Sep 17 00:00:00 2001 From: Martin Bremmer Date: Thu, 25 Apr 2019 13:29:11 +0200 Subject: [PATCH 048/238] Removed expand_envvars.h Signed-off-by: Martin Bremmer --- src/core/ddsi/src/q_config.c | 1 - src/ddsrt/CMakeLists.txt | 1 - src/ddsrt/include/dds/ddsrt/expand_envvars.h | 31 -------------------- src/ddsrt/src/expand_envvars.c | 1 - 4 files changed, 34 deletions(-) delete mode 100644 src/ddsrt/include/dds/ddsrt/expand_envvars.h diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index bf1781d..f3ea0a7 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -33,7 +33,6 @@ #include "dds/ddsi/q_error.h" #include "dds/ddsrt/xmlparser.h" -#include "dds/ddsrt/expand_envvars.h" #include "dds/version.h" diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index 5b49248..cda6f18 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -79,7 +79,6 @@ list(APPEND sources list(APPEND headers "${source_path}/dds/ddsrt/avl.h" - "${source_path}/dds/ddsrt/expand_envvars.h" "${source_path}/dds/ddsrt/fibheap.h" "${source_path}/dds/ddsrt/hopscotch.h" "${source_path}/dds/ddsrt/thread_pool.h") diff --git a/src/ddsrt/include/dds/ddsrt/expand_envvars.h b/src/ddsrt/include/dds/ddsrt/expand_envvars.h deleted file mode 100644 index d7b66f4..0000000 --- a/src/ddsrt/include/dds/ddsrt/expand_envvars.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef DDSRT_EXPAND_ENVVARS_H -#define DDSRT_EXPAND_ENVVARS_H - -#include "dds/export.h" - -#if defined (__cplusplus) -extern "C" { -#endif - - /* Expands ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, but not $X */ - DDS_EXPORT char *ddsrt_expand_envvars(const char *string); - - /* Expands $X, ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, $ and \ can be escaped with \ */ - DDS_EXPORT char *ddsrt_expand_envvars_sh(const char *string); - -#if defined (__cplusplus) -} -#endif - -#endif diff --git a/src/ddsrt/src/expand_envvars.c b/src/ddsrt/src/expand_envvars.c index ded0d0a..dbaa33a 100644 --- a/src/ddsrt/src/expand_envvars.c +++ b/src/ddsrt/src/expand_envvars.c @@ -19,7 +19,6 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" #include "dds/ddsrt/string.h" -#include "dds/ddsrt/expand_envvars.h" typedef char * (*expand_fn)(const char *src0); From 5f9aed1c8759138eb14036ad4cf71fe798ee164e Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 25 Apr 2019 11:43:19 +0200 Subject: [PATCH 049/238] address a handful of compiler warnings in ddsperf These are fortunately all false positives. Signed-off-by: Erik Boasson --- src/tools/ddsperf/ddsperf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index 51874a4..7052233 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -664,7 +664,7 @@ static dds_instance_handle_t get_pphandle_for_pubhandle (dds_instance_handle_t p dds_sample_info_t info; if ((n = dds_read_instance (rd_publications, &msg, &info, 1, 1, pubhandle)) < 0) error2 ("dds_read_instance(rd_publications, %"PRIx64") failed: %d\n", pubhandle, (int) n); - else if (n == 0 || !info.valid_data) + if (n == 0 || !info.valid_data) { printf ("get_pong_writer: publication handle %"PRIx64" not found\n", pubhandle); fflush (stdout); @@ -772,7 +772,7 @@ static bool process_data (dds_entity_t rd, struct subthread_arg *arg) { if (iseq[i].valid_data) { - uint32_t seq, keyval, size; + uint32_t seq = 0, keyval = 0, size = 0; switch (topicsel) { case KS: { KeyedSeq *d = (KeyedSeq *) mseq[i]; keyval = d->keyval; seq = d->seq; size = 12 + d->baggage._length; } break; @@ -783,7 +783,7 @@ static bool process_data (dds_entity_t rd, struct subthread_arg *arg) (void) check_eseq (&eseq_admin, seq, keyval, size, iseq[i].publication_handle); if (iseq[i].source_timestamp & 1) { - dds_entity_t wr_pong = 0; + dds_entity_t wr_pong; if ((wr_pong = get_pong_writer (iseq[i].publication_handle)) != 0) { dds_return_t rc; From ae323ab0ca0bac5182a24d7faee83a98babc7c31 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 29 Apr 2019 09:24:18 +0200 Subject: [PATCH 050/238] make internal header files more C++ friendly Generally one doesn't need to include any internal header files in an application, but the (unstable) interface for application-defined sample representation and serialization does require including some. It turns out a keyword clash had to be resolved (typename => type_name) and that a whole bunch of them were missing the #ifdef __cplusplus / extern "C" bit. It further turned out that one had to pull in nearly all of the type definitions, including some typedefs that are illegal in C++, e.g., typedef struct os_sockWaitset *os_sockWaitset; C++ is right to forbid this, but Cyclone's header files were wrong to force inclusion of so much irrelevant stuff. This commit leaves these typedefs in place, but eliminates a few header file inclusions to avoid the problem. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds__guardcond.h | 8 +++ src/core/ddsc/src/dds__readcond.h | 8 +++ src/core/ddsc/src/dds__serdata_builtintopic.h | 8 +++ src/core/ddsc/src/dds_init.c | 1 + src/core/ddsc/src/dds_instance.c | 2 +- src/core/ddsc/src/dds_read.c | 1 + src/core/ddsc/src/dds_reader.c | 1 + src/core/ddsc/src/dds_serdata_builtintopic.c | 2 +- src/core/ddsc/src/dds_sertopic_builtintopic.c | 9 +-- src/core/ddsc/src/dds_topic.c | 12 ++-- src/core/ddsc/src/dds_whc.c | 1 + src/core/ddsc/src/dds_writer.c | 1 + src/core/ddsi/include/dds/ddsi/ddsi_ipaddr.h | 10 ++- src/core/ddsi/include/dds/ddsi/ddsi_mcgroup.h | 8 +++ src/core/ddsi/include/dds/ddsi/ddsi_raweth.h | 8 +++ .../ddsi/include/dds/ddsi/ddsi_rhc_plugin.h | 8 +++ src/core/ddsi/include/dds/ddsi/ddsi_serdata.h | 65 ++++++++++++++----- .../include/dds/ddsi/ddsi_serdata_default.h | 8 +++ .../ddsi/include/dds/ddsi/ddsi_sertopic.h | 18 +++-- src/core/ddsi/include/dds/ddsi/ddsi_ssl.h | 8 +++ src/core/ddsi/include/dds/ddsi/ddsi_tcp.h | 16 +++++ src/core/ddsi/include/dds/ddsi/ddsi_tran.h | 17 ++++- src/core/ddsi/include/dds/ddsi/ddsi_udp.h | 8 +++ src/core/ddsi/include/dds/ddsi/q_bitset.h | 8 +++ src/core/ddsi/include/dds/ddsi/q_bswap.h | 8 +-- src/core/ddsi/include/dds/ddsi/q_debmon.h | 10 ++- src/core/ddsi/include/dds/ddsi/q_entity.h | 8 ++- src/core/ddsi/include/dds/ddsi/q_freelist.h | 8 +++ src/core/ddsi/include/dds/ddsi/q_init.h | 8 +++ .../include/dds/ddsi/q_inverse_uint32_set.h | 8 +++ src/core/ddsi/include/dds/ddsi/q_radmin.h | 1 - src/core/ddsi/include/dds/ddsi/q_xmsg.h | 1 + src/core/ddsi/src/ddsi_eth.h | 8 +++ src/core/ddsi/src/ddsi_ipaddr.c | 1 + src/core/ddsi/src/ddsi_mcgroup.c | 1 + src/core/ddsi/src/ddsi_raweth.c | 1 + src/core/ddsi/src/ddsi_serdata_default.c | 1 + src/core/ddsi/src/ddsi_sertopic.c | 4 +- src/core/ddsi/src/ddsi_tcp.c | 1 + src/core/ddsi/src/ddsi_tran.c | 1 + src/core/ddsi/src/ddsi_udp.c | 1 + src/core/ddsi/src/q_debmon.c | 2 +- src/core/ddsi/src/q_entity.c | 6 +- src/core/ddsi/src/q_plist.c | 1 + src/core/ddsi/src/q_receive.c | 4 +- src/core/ddsi/src/q_transmit.c | 4 +- src/ddsrt/include/dds/ddsrt/atomics/arm.h | 9 ++- src/ddsrt/include/dds/ddsrt/atomics/gcc.h | 9 ++- src/ddsrt/include/dds/ddsrt/atomics/msvc.h | 9 ++- src/ddsrt/include/dds/ddsrt/atomics/sun.h | 7 ++ src/ddsrt/include/dds/ddsrt/cdtors.h | 8 +++ src/ddsrt/include/dds/ddsrt/md5.h | 7 +- src/ddsrt/include/dds/ddsrt/retcode.h | 8 +++ src/ddsrt/include/dds/ddsrt/rusage.h | 8 +++ src/ddsrt/include/dds/ddsrt/sockets.h | 8 +++ src/ddsrt/include/dds/ddsrt/strtod.h | 8 +++ 56 files changed, 345 insertions(+), 60 deletions(-) diff --git a/src/core/ddsc/src/dds__guardcond.h b/src/core/ddsc/src/dds__guardcond.h index 7d57643..f317dc5 100644 --- a/src/core/ddsc/src/dds__guardcond.h +++ b/src/core/ddsc/src/dds__guardcond.h @@ -14,10 +14,18 @@ #include "dds__entity.h" +#if defined (__cplusplus) +extern "C" { +#endif + dds_guardcond* dds_create_guardcond( dds_participant *pp); DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_guardcond, DDS_KIND_COND_GUARD) +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsc/src/dds__readcond.h b/src/core/ddsc/src/dds__readcond.h index aa0494e..f76137c 100644 --- a/src/core/ddsc/src/dds__readcond.h +++ b/src/core/ddsc/src/dds__readcond.h @@ -14,6 +14,10 @@ #include "dds__entity.h" +#if defined (__cplusplus) +extern "C" { +#endif + dds_readcond * dds_create_readcond( dds_reader *rd, @@ -21,4 +25,8 @@ dds_create_readcond( uint32_t mask, dds_querycondition_filter_fn filter); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsc/src/dds__serdata_builtintopic.h b/src/core/ddsc/src/dds__serdata_builtintopic.h index 6afe2d1..1c4d548 100644 --- a/src/core/ddsc/src/dds__serdata_builtintopic.h +++ b/src/core/ddsc/src/dds__serdata_builtintopic.h @@ -16,6 +16,10 @@ #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_sertopic.h" +#if defined (__cplusplus) +extern "C" { +#endif + struct ddsi_serdata_builtintopic { struct ddsi_serdata c; nn_guid_t key; @@ -39,4 +43,8 @@ extern const struct ddsi_serdata_ops ddsi_serdata_ops_builtintopic; struct ddsi_sertopic *new_sertopic_builtintopic (enum ddsi_sertopic_builtintopic_type type, const char *name, const char *typename); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index d51bfb0..9e74180 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -30,6 +30,7 @@ #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_gc.h" +#include "dds/ddsi/q_globals.h" #include "dds/version.h" #define DOMAIN_ID_MIN 0 diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index 25156fe..903d7ee 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -22,7 +22,7 @@ #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" - +#include "dds/ddsi/q_globals.h" dds_return_t dds_writedispose( diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 37e35ec..2791a44 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -19,6 +19,7 @@ #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_ephash.h" #include "dds/ddsi/q_entity.h" +#include "dds/ddsi/q_globals.h" #include "dds/ddsi/ddsi_sertopic.h" static dds_retcode_t dds_read_lock (dds_entity_t hdl, dds_reader **reader, dds_readcond **condition, bool only_reader) diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 6ce57b9..be86ed3 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -23,6 +23,7 @@ #include "dds__topic.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" +#include "dds/ddsi/q_globals.h" #include "dds__builtin.h" #include "dds/ddsi/ddsi_sertopic.h" diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index 33da2ca..5cbd47b 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -91,7 +91,7 @@ static void set_topic_type_from_sertopic (struct ddsi_serdata_builtintopic *d, c } if (!(d->xqos.present & QP_TYPE_NAME)) { - d->xqos.type_name = dds_string_dup (tp->typename); + d->xqos.type_name = dds_string_dup (tp->type_name); d->xqos.present |= QP_TYPE_NAME; } } diff --git a/src/core/ddsc/src/dds_sertopic_builtintopic.c b/src/core/ddsc/src/dds_sertopic_builtintopic.c index 05c9544..7773a13 100644 --- a/src/core/ddsc/src/dds_sertopic_builtintopic.c +++ b/src/core/ddsc/src/dds_sertopic_builtintopic.c @@ -21,6 +21,7 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_freelist.h" #include "dds/ddsi/ddsi_sertopic.h" +#include "dds/ddsi/ddsi_iid.h" #include "dds__serdata_builtintopic.h" /* FIXME: sertopic /= ddstopic so a lot of stuff needs to be moved here from dds_topic.c and the free function needs to be implemented properly */ @@ -30,10 +31,10 @@ struct ddsi_sertopic *new_sertopic_builtintopic (enum ddsi_sertopic_builtintopic struct ddsi_sertopic_builtintopic *tp = ddsrt_malloc (sizeof (*tp)); tp->c.iid = ddsi_iid_gen(); tp->c.name = dds_string_dup (name); - tp->c.typename = dds_string_dup (typename); - const size_t name_typename_size = strlen (tp->c.name) + 1 + strlen (tp->c.typename) + 1; - tp->c.name_typename = dds_alloc (name_typename_size); - snprintf (tp->c.name_typename, name_typename_size, "%s/%s", tp->c.name, tp->c.typename); + tp->c.type_name = dds_string_dup (typename); + const size_t name_typename_size = strlen (tp->c.name) + 1 + strlen (tp->c.type_name) + 1; + tp->c.name_type_name = dds_alloc (name_typename_size); + snprintf (tp->c.name_type_name, name_typename_size, "%s/%s", tp->c.name, tp->c.type_name); tp->c.ops = &ddsi_sertopic_ops_builtintopic; tp->c.serdata_ops = &ddsi_serdata_ops_builtintopic; tp->c.serdata_basehash = ddsi_sertopic_compute_serdata_basehash (tp->c.serdata_ops); diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index f834f00..747976c 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -35,7 +35,7 @@ DECL_ENTITY_LOCK_UNLOCK(extern inline, dds_topic) const ddsrt_avl_treedef_t dds_topictree_def = DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY ( offsetof (struct ddsi_sertopic, avlnode), - offsetof (struct ddsi_sertopic, name_typename), + offsetof (struct ddsi_sertopic, name_type_name), (int (*) (const void *, const void *)) strcmp, 0 ); @@ -285,7 +285,7 @@ static bool dupdef_qos_ok(const dds_qos_t *qos, const struct ddsi_sertopic *st) static bool sertopic_equivalent (const struct ddsi_sertopic *a, const struct ddsi_sertopic *b) { - if (strcmp (a->name_typename, b->name_typename) != 0) + if (strcmp (a->name_type_name, b->name_type_name) != 0) return false; if (a->serdata_basehash != b->serdata_basehash) return false; @@ -447,9 +447,9 @@ dds_create_topic( st->c.iid = ddsi_iid_gen (); st->c.status_cb = dds_topic_status_cb; st->c.status_cb_entity = NULL; /* set by dds_create_topic_arbitrary */ - st->c.name_typename = key; + st->c.name_type_name = key; st->c.name = dds_string_dup (name); - st->c.typename = dds_string_dup (typename); + st->c.type_name = dds_string_dup (typename); st->c.ops = &ddsi_sertopic_ops_default; st->c.serdata_ops = desc->m_nkeys ? &ddsi_serdata_ops_cdr : &ddsi_serdata_ops_cdr_nokey; st->c.serdata_basehash = ddsi_sertopic_compute_serdata_basehash (st->c.serdata_ops); @@ -471,7 +471,7 @@ dds_create_topic( /* Set Topic meta data (for SEDP publication) */ plist.qos.topic_name = dds_string_dup (st->c.name); - plist.qos.type_name = dds_string_dup (st->c.typename); + plist.qos.type_name = dds_string_dup (st->c.type_name); plist.qos.present |= (QP_TOPIC_NAME | QP_TYPE_NAME); if (desc->m_meta) { plist.type_description = dds_string_dup (desc->m_meta); @@ -643,7 +643,7 @@ dds_get_type_name( ret = DDS_ERRNO(rc); goto fail; } - (void)snprintf(name, size, "%s", t->m_stopic->typename); + (void)snprintf(name, size, "%s", t->m_stopic->type_name); dds_topic_unlock(t); ret = DDS_RETCODE_OK; fail: diff --git a/src/core/ddsc/src/dds_whc.c b/src/core/ddsc/src/dds_whc.c index 5408c69..b63ca62 100644 --- a/src/core/ddsc/src/dds_whc.c +++ b/src/core/ddsc/src/dds_whc.c @@ -27,6 +27,7 @@ #include "dds/ddsi/q_time.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_freelist.h" +#include "dds/ddsi/q_globals.h" #define USE_EHH 0 diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index f98d70c..b36bfc9 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -14,6 +14,7 @@ #include "dds/dds.h" #include "dds/version.h" #include "dds/ddsi/q_config.h" +#include "dds/ddsi/q_globals.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_xmsg.h" diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_ipaddr.h b/src/core/ddsi/include/dds/ddsi/ddsi_ipaddr.h index 3bc6f2f..9c7f1d3 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_ipaddr.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_ipaddr.h @@ -14,11 +14,19 @@ #include "dds/ddsi/ddsi_tran.h" -enum ddsi_nearby_address_result ddsi_ipaddr_is_nearby_address (ddsi_tran_factory_t tran, const nn_locator_t *loc, size_t ninterf, const struct nn_interface interf[]); +#if defined (__cplusplus) +extern "C" { +#endif + +enum ddsi_nearby_address_result ddsi_ipaddr_is_nearby_address (ddsi_tran_factory_t tran, const nn_locator_t *loc, size_t ninterf, const struct nn_interface *interf); enum ddsi_locator_from_string_result ddsi_ipaddr_from_string (ddsi_tran_factory_t tran, nn_locator_t *loc, const char *str, int32_t kind); int ddsi_ipaddr_compare (const struct sockaddr *const sa1, const struct sockaddr *const sa2); char *ddsi_ipaddr_to_string (ddsi_tran_factory_t tran, char *dst, size_t sizeof_dst, const nn_locator_t *loc, int with_port); void ddsi_ipaddr_to_loc (nn_locator_t *dst, const struct sockaddr *src, int32_t kind); void ddsi_ipaddr_from_loc (struct sockaddr_storage *dst, const nn_locator_t *src); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_mcgroup.h b/src/core/ddsi/include/dds/ddsi/ddsi_mcgroup.h index 018237a..f4dc36f 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_mcgroup.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_mcgroup.h @@ -14,6 +14,10 @@ #include "dds/ddsi/ddsi_tran.h" +#if defined (__cplusplus) +extern "C" { +#endif + struct nn_group_membership; struct nn_group_membership *new_group_membership (void); @@ -23,4 +27,8 @@ int ddsi_leave_mc (ddsi_tran_conn_t conn, const nn_locator_t *srcip, const nn_lo void ddsi_transfer_group_membership (ddsi_tran_conn_t conn, ddsi_tran_conn_t newconn); int ddsi_rejoin_transferred_mcgroups (ddsi_tran_conn_t conn); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_raweth.h b/src/core/ddsi/include/dds/ddsi/ddsi_raweth.h index e81472e..da60a24 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_raweth.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_raweth.h @@ -12,6 +12,14 @@ #ifndef DDSI_RAWETH_H #define DDSI_RAWETH_H +#if defined (__cplusplus) +extern "C" { +#endif + int ddsi_raweth_init (void); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h b/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h index 57c8813..1d37ecf 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_rhc_plugin.h @@ -12,6 +12,10 @@ #ifndef DDSI_RHC_PLUGIN_H #define DDSI_RHC_PLUGIN_H +#if defined (__cplusplus) +extern "C" { +#endif + struct rhc; struct nn_xqos; struct ddsi_tkmap_instance; @@ -42,4 +46,8 @@ struct ddsi_rhc_plugin DDS_EXPORT void make_proxy_writer_info(struct proxy_writer_info *pwr_info, const struct entity_common *e, const struct nn_xqos *xqos); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h index 0bddb32..866910a 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h @@ -16,6 +16,10 @@ #include "dds/ddsi/q_time.h" #include "dds/ddsi/ddsi_sertopic.h" +#if defined (__cplusplus) +extern "C" { +#endif + struct nn_rdata; struct nn_keyhash; @@ -40,37 +44,62 @@ struct ddsi_serdata { nn_mtime_t twrite; /* write time, not source timestamp, set post-throttling */ }; -/* Serialised size of sample: uint32_t because the protocol can't handle samples larger than 4GB anyway */ +/* Serialised size of sample inclusive of DDSI encoding header + - uint32_t because the protocol can't handle samples larger than 4GB anyway + - FIXME: get the encoding header out of the serialised data */ typedef uint32_t (*ddsi_serdata_size_t) (const struct ddsi_serdata *d); /* Free a serdata (called by unref when refcount goes to 0) */ typedef void (*ddsi_serdata_free_t) (struct ddsi_serdata *d); -/* Construct a serdata from a fragchain received over the network */ +/* Construct a serdata from a fragchain received over the network + - "kind" is KEY or DATA depending on the type of payload + - "size" is the serialised size of the sample, inclusive of DDSI encoding header + - the first fragchain always contains the encoding header in its entirety + - fragchains may overlap, though I have never seen any DDS implementation + actually send such nasty fragments + - FIXME: get the encoding header out of the serialised data */ typedef struct ddsi_serdata * (*ddsi_serdata_from_ser_t) (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, const struct nn_rdata *fragchain, size_t size); /* Construct a serdata from a keyhash (an SDK_KEY by definition) */ typedef struct ddsi_serdata * (*ddsi_serdata_from_keyhash_t) (const struct ddsi_sertopic *topic, const struct nn_keyhash *keyhash); -/* Construct a serdata from an application sample */ +/* Construct a serdata from an application sample + - "kind" is KEY or DATA depending on the operation invoked by the application; + e.g., write results in kind = DATA, dispose in kind = KEY. The important bit + is to not assume anything of the contents of non-key fields if kind = KEY + unless additional application knowledge is available */ typedef struct ddsi_serdata * (*ddsi_serdata_from_sample_t) (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, const void *sample); -/* Construct a topic-less serdata with a keyvalue given a normal serdata (either key or data) - used for tkmap */ +/* Construct a topic-less serdata with just a keyvalue given a normal serdata (either key or data) + - used for mapping key values to instance ids in tkmap + - two reasons: size (keys are typically smaller than samples), and data in tkmap + is shared across topics + - whether a serdata is topicless or not is known from the context, and the topic + field may have any value for a topicless serdata (so in some cases, one can + simply do "return ddsi_serdata_ref(d);" + */ typedef struct ddsi_serdata * (*ddsi_serdata_to_topicless_t) (const struct ddsi_serdata *d); -/* Fill buffer with 'size' bytes of serialised data, starting from 'off'; 0 <= off < off+sz <= - alignup4(size(d)) */ +/* Fill buffer with 'size' bytes of serialised data, starting from 'off' + - 0 <= off < off+sz <= alignup4(size(d)) + - bytes at offsets 0 .. 3 are DDSI encoding header, size(d) includes that header + - what to copy for bytes in [size(d), alignup4(size(d))) depends on the serdata + implementation, the protocol treats them as undefined + - FIXME: get the encoding header out of the serialised data */ typedef void (*ddsi_serdata_to_ser_t) (const struct ddsi_serdata *d, size_t off, size_t sz, void *buf); -/* Provide a pointer to 'size' bytes of serialised data, starting from 'off'; 0 <= off < off+sz <= - alignup4(size(d)); it must remain valid until the corresponding call to to_ser_unref. Multiple - calls to to_ser_ref() may be issued in parallel, the separate ref/unref bit is there to at least - have the option of lazily creating the serialised representation and freeing it when no one needs - it, while the sample itself remains valid */ +/* Provide a pointer to 'size' bytes of serialised data, starting from 'off' + - see ddsi_serdata_to_ser_t above + - instead of copying, this gives a reference that must remain valid until the + corresponding call to to_ser_unref + - multiple calls to to_ser_ref() may be issued in parallel + - lazily creating the serialised representation is allowed (though I'm not sure + how that would work with knowing the serialised size beforehand ...) */ typedef struct ddsi_serdata * (*ddsi_serdata_to_ser_ref_t) (const struct ddsi_serdata *d, size_t off, size_t sz, ddsrt_iovec_t *ref); -/* Release a lock on serialised data, ref must be a pointer previously obtained by calling - to_ser_ref(d, off, sz) for some offset off. */ +/* Release a lock on serialised data + - ref was previousy filled by ddsi_serdata_to_ser_ref_t */ typedef void (*ddsi_serdata_to_ser_unref_t) (struct ddsi_serdata *d, const ddsrt_iovec_t *ref); /* Turn serdata into an application sample (or just the key values if only key values are @@ -83,11 +112,11 @@ typedef void (*ddsi_serdata_to_ser_unref_t) (struct ddsi_serdata *d, const ddsrt by the caller.) */ typedef bool (*ddsi_serdata_to_sample_t) (const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim); -/* Create a sample from a topicless serdata, as returned by serdata_to_topicless. This sample - obviously has just the key fields filled in, and is used for generating invalid samples. */ +/* Create a sample from a topicless serdata, as returned by serdata_to_topicless. This sample + obviously has just the key fields filled in and is used for generating invalid samples. */ typedef bool (*ddsi_serdata_topicless_to_sample_t) (const struct ddsi_sertopic *topic, const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim); -/* Test key values of two serdatas for equality. The two will have the same ddsi_serdata_ops, +/* Test key values of two serdatas for equality. The two will have the same ddsi_serdata_ops, but are not necessarily of the same topic (one can decide to never consider them equal if they are of different topics, of course; but the nice thing about _not_ doing that is that all instances with a certain key value with have the same instance id, and that in turn makes @@ -166,4 +195,8 @@ DDS_EXPORT inline bool ddsi_serdata_eqkey (const struct ddsi_serdata *a, const s return a->ops->eqkey (a, b); } +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h index 7775e1c..c61bb97 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h @@ -22,6 +22,10 @@ #include "dds/dds.h" #include "dds__topic.h" +#if defined (__cplusplus) +extern "C" { +#endif + #if DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN #define CDR_BE 0x0000 #define CDR_LE 0x0100 @@ -125,4 +129,8 @@ extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_rawcdr; struct serdatapool * ddsi_serdatapool_new (void); void ddsi_serdatapool_free (struct serdatapool * pool); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h index edd0b02..172af62 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_sertopic.h @@ -16,6 +16,10 @@ #include "dds/ddsrt/avl.h" #include "dds/ddsc/dds_public_alloc.h" +#if defined (__cplusplus) +extern "C" { +#endif + struct ddsi_serdata; struct ddsi_serdata_ops; @@ -29,9 +33,9 @@ struct ddsi_sertopic { const struct ddsi_sertopic_ops *ops; const struct ddsi_serdata_ops *serdata_ops; uint32_t serdata_basehash; - char *name_typename; + char *name_type_name; char *name; - char *typename; + char *type_name; uint64_t iid; ddsrt_atomic_uint32_t refc; /* counts refs from entities, not from data */ @@ -39,12 +43,14 @@ struct ddsi_sertopic { struct dds_topic * status_cb_entity; }; +/* Called when the refcount dropped to zero */ typedef void (*ddsi_sertopic_deinit_t) (struct ddsi_sertopic *tp); -/* Release any memory allocated by ddsi_sertopic_to_sample */ +/* Zero out a sample, used for generating samples from just a key value and in cleaning up + after dds_return_loan */ typedef void (*ddsi_sertopic_zero_samples_t) (const struct ddsi_sertopic *d, void *samples, size_t count); -/* Release any memory allocated by ddsi_sertopic_to_sample */ +/* (Re)allocate an array of samples, used in growing loaned sample arrays in dds_read */ typedef void (*ddsi_sertopic_realloc_samples_t) (void **ptrs, const struct ddsi_sertopic *d, void *old, size_t oldcount, size_t count); /* Release any memory allocated by ddsi_sertopic_to_sample (also undo sertopic_alloc_sample if "op" so requests) */ @@ -86,4 +92,8 @@ DDS_EXPORT inline void ddsi_sertopic_free_sample (const struct ddsi_sertopic *tp ddsi_sertopic_free_samples (tp, &sample, 1, op); } +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_ssl.h b/src/core/ddsi/include/dds/ddsi/ddsi_ssl.h index 493289e..edddd26 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_ssl.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_ssl.h @@ -20,8 +20,16 @@ #endif #include +#if defined (__cplusplus) +extern "C" { +#endif + struct ddsi_ssl_plugins; void ddsi_ssl_config_plugin (struct ddsi_ssl_plugins *plugin); +#if defined (__cplusplus) +} +#endif + #endif #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_tcp.h b/src/core/ddsi/include/dds/ddsi/ddsi_tcp.h index bdf28d9..380dac3 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_tcp.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_tcp.h @@ -18,6 +18,10 @@ #include "dds/ddsi/ddsi_ssl.h" +#if defined (__cplusplus) +extern "C" { +#endif + struct ddsi_ssl_plugins { bool (*init) (void); @@ -31,8 +35,20 @@ struct ddsi_ssl_plugins SSL * (*accept) (BIO *bio, ddsrt_socket_t *sock); }; +#if defined (__cplusplus) +} +#endif + +#endif + +#if defined (__cplusplus) +extern "C" { #endif int ddsi_tcp_init (void); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_tran.h b/src/core/ddsi/include/dds/ddsi/ddsi_tran.h index fa10474..11b48cb 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_tran.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_tran.h @@ -14,9 +14,16 @@ /* DDSI Transport module */ -#include "dds/ddsi/q_globals.h" +#include "dds/ddsrt/ifaddrs.h" +#include "dds/ddsrt/atomics.h" #include "dds/ddsi/q_protocol.h" +#if defined (__cplusplus) +extern "C" { +#endif + +struct nn_interface; + /* Types supporting handles */ #define DDSI_TRAN_CONN 1 @@ -69,7 +76,7 @@ enum ddsi_nearby_address_result { DNAR_SAME }; -typedef enum ddsi_nearby_address_result (*ddsi_is_nearby_address_fn_t) (ddsi_tran_factory_t tran, const nn_locator_t *loc, size_t ninterf, const struct nn_interface interf[]); +typedef enum ddsi_nearby_address_result (*ddsi_is_nearby_address_fn_t) (ddsi_tran_factory_t tran, const nn_locator_t *loc, size_t ninterf, const struct nn_interface *interf); enum ddsi_locator_from_string_result { AFSR_OK, /* conversion succeeded */ @@ -239,7 +246,7 @@ void ddsi_conn_transfer_group_membership (ddsi_tran_conn_t conn, ddsi_tran_conn_ int ddsi_conn_rejoin_transferred_mcgroups (ddsi_tran_conn_t conn); int ddsi_is_mcaddr (const nn_locator_t *loc); int ddsi_is_ssm_mcaddr (const nn_locator_t *loc); -enum ddsi_nearby_address_result ddsi_is_nearby_address (const nn_locator_t *loc, size_t ninterf, const struct nn_interface interf[]); +enum ddsi_nearby_address_result ddsi_is_nearby_address (const nn_locator_t *loc, size_t ninterf, const struct nn_interface *interf); enum ddsi_locator_from_string_result ddsi_locator_from_string (nn_locator_t *loc, const char *str); @@ -271,4 +278,8 @@ inline ddsi_tran_conn_t ddsi_listener_accept (ddsi_tran_listener_t listener) { void ddsi_listener_unblock (ddsi_tran_listener_t listener); void ddsi_listener_free (ddsi_tran_listener_t listener); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_udp.h b/src/core/ddsi/include/dds/ddsi/ddsi_udp.h index 4dece96..1305dab 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_udp.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_udp.h @@ -12,6 +12,14 @@ #ifndef _DDSI_UDP_H_ #define _DDSI_UDP_H_ +#if defined (__cplusplus) +extern "C" { +#endif + int ddsi_udp_init (void); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/q_bitset.h b/src/core/ddsi/include/dds/ddsi/q_bitset.h index ec81027..630d16a 100644 --- a/src/core/ddsi/include/dds/ddsi/q_bitset.h +++ b/src/core/ddsi/include/dds/ddsi/q_bitset.h @@ -18,6 +18,10 @@ #include "dds/ddsi/q_unused.h" +#if defined (__cplusplus) +extern "C" { +#endif + inline int nn_bitset_isset (uint32_t numbits, const uint32_t *bits, uint32_t idx) { return idx < numbits && (bits[idx/32] & (UINT32_C(1) << (31 - (idx%32)))); @@ -52,4 +56,8 @@ inline void nn_bitset_one (uint32_t numbits, uint32_t *bits) } } +#if defined (__cplusplus) +} +#endif + #endif /* NN_BITSET_H */ diff --git a/src/core/ddsi/include/dds/ddsi/q_bswap.h b/src/core/ddsi/include/dds/ddsi/q_bswap.h index 7478f87..6f8cbff 100644 --- a/src/core/ddsi/include/dds/ddsi/q_bswap.h +++ b/src/core/ddsi/include/dds/ddsi/q_bswap.h @@ -19,6 +19,10 @@ #include "dds/ddsi/q_rtps.h" /* for nn_guid_t, nn_guid_prefix_t */ #include "dds/ddsi/q_protocol.h" /* for nn_sequence_number_t */ +#if defined (__cplusplus) +extern "C" { +#endif + inline uint16_t bswap2u (uint16_t x) { return (uint16_t) ((x >> 8) | (x << 8)); @@ -84,10 +88,6 @@ inline void bswapSN (nn_sequence_number_t *sn) #define fromBE8u(x) (x) #endif -#if defined (__cplusplus) -extern "C" { -#endif - nn_guid_prefix_t nn_hton_guid_prefix (nn_guid_prefix_t p); nn_guid_prefix_t nn_ntoh_guid_prefix (nn_guid_prefix_t p); nn_entityid_t nn_hton_entityid (nn_entityid_t e); diff --git a/src/core/ddsi/include/dds/ddsi/q_debmon.h b/src/core/ddsi/include/dds/ddsi/q_debmon.h index d6e4c1c..77348c2 100644 --- a/src/core/ddsi/include/dds/ddsi/q_debmon.h +++ b/src/core/ddsi/include/dds/ddsi/q_debmon.h @@ -12,6 +12,10 @@ #ifndef Q_DEBMON_H #define Q_DEBMON_H +#if defined (__cplusplus) +extern "C" { +#endif + struct debug_monitor; typedef int (*debug_monitor_cpf_t) (ddsi_tran_conn_t conn, const char *fmt, ...); typedef int (*debug_monitor_plugin_t) (ddsi_tran_conn_t conn, debug_monitor_cpf_t cpf, void *arg); @@ -20,4 +24,8 @@ struct debug_monitor *new_debug_monitor (int port); void add_debug_monitor_plugin (struct debug_monitor *dm, debug_monitor_plugin_t fn, void *arg); void free_debug_monitor (struct debug_monitor *dm); -#endif /* defined(__ospli_osplo__q_debmon__) */ +#if defined (__cplusplus) +} +#endif + +#endif diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index f6f1f8e..f606786 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -14,6 +14,7 @@ #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/avl.h" +#include "dds/ddsrt/sync.h" #include "dds/ddsi/q_rtps.h" #include "dds/ddsi/q_protocol.h" #include "dds/ddsi/q_lat_estim.h" @@ -32,11 +33,14 @@ struct xevent; struct nn_reorder; struct nn_defrag; struct nn_dqueue; +struct nn_rsample_info; +struct nn_rdata; struct addrset; struct ddsi_sertopic; struct whc; struct nn_xqos; struct nn_plist; +struct lease; struct proxy_group; struct proxy_endpoint_common; @@ -159,7 +163,7 @@ struct participant unsigned bes; /* built-in endpoint set */ unsigned prismtech_bes; /* prismtech-specific extension of built-in endpoints set */ unsigned is_ddsi2_pp: 1; /* true for the "federation leader", the ddsi2 participant itself in OSPL; FIXME: probably should use this for broker mode as well ... */ - nn_plist_t *plist; /* settings/QoS for this participant */ + struct nn_plist *plist; /* settings/QoS for this participant */ struct xevent *spdp_xevent; /* timed event for periodically publishing SPDP */ struct xevent *pmd_update_xevent; /* timed event for periodically publishing ParticipantMessageData */ nn_locator_t m_locator; @@ -294,7 +298,7 @@ struct proxy_participant unsigned bes; /* built-in endpoint set */ unsigned prismtech_bes; /* prismtech-specific extension of built-in endpoints set */ nn_guid_t privileged_pp_guid; /* if this PP depends on another PP for its SEDP writing */ - nn_plist_t *plist; /* settings/QoS for this participant */ + struct nn_plist *plist; /* settings/QoS for this participant */ ddsrt_atomic_voidp_t lease; /* lease object for this participant, for automatic leases */ struct addrset *as_default; /* default address set to use for user data traffic */ struct addrset *as_meta; /* default address set to use for discovery traffic */ diff --git a/src/core/ddsi/include/dds/ddsi/q_freelist.h b/src/core/ddsi/include/dds/ddsi/q_freelist.h index 8e40ff7..8fcafa7 100644 --- a/src/core/ddsi/include/dds/ddsi/q_freelist.h +++ b/src/core/ddsi/include/dds/ddsi/q_freelist.h @@ -15,6 +15,10 @@ #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/sync.h" +#if defined (__cplusplus) +extern "C" { +#endif + #define FREELIST_SIMPLE 1 #define FREELIST_ATOMIC_LIFO 2 #define FREELIST_DOUBLE 3 @@ -74,4 +78,8 @@ bool nn_freelist_push (struct nn_freelist *fl, void *elem); void *nn_freelist_pushmany (struct nn_freelist *fl, void *first, void *last, uint32_t n); void *nn_freelist_pop (struct nn_freelist *fl); +#if defined (__cplusplus) +} +#endif + #endif /* NN_FREELIST_H */ diff --git a/src/core/ddsi/include/dds/ddsi/q_init.h b/src/core/ddsi/include/dds/ddsi/q_init.h index c9794f0..a1f9cef 100644 --- a/src/core/ddsi/include/dds/ddsi/q_init.h +++ b/src/core/ddsi/include/dds/ddsi/q_init.h @@ -12,7 +12,15 @@ #ifndef Q_INIT_H #define Q_INIT_H +#if defined (__cplusplus) +extern "C" { +#endif + int create_multicast_sockets(void); int joinleave_spdp_defmcip (int dojoin); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/q_inverse_uint32_set.h b/src/core/ddsi/include/dds/ddsi/q_inverse_uint32_set.h index d48cf96..cd93009 100644 --- a/src/core/ddsi/include/dds/ddsi/q_inverse_uint32_set.h +++ b/src/core/ddsi/include/dds/ddsi/q_inverse_uint32_set.h @@ -14,6 +14,10 @@ #include "dds/ddsrt/avl.h" +#if defined (__cplusplus) +extern "C" { +#endif + struct inverse_uint32_set_node { ddsrt_avl_node_t avlnode; uint32_t min, max; @@ -29,4 +33,8 @@ void inverse_uint32_set_fini(struct inverse_uint32_set *set); int inverse_uint32_set_alloc(uint32_t * const id, struct inverse_uint32_set *set); void inverse_uint32_set_free(struct inverse_uint32_set *set, uint32_t id); +#if defined (__cplusplus) +} +#endif + #endif diff --git a/src/core/ddsi/include/dds/ddsi/q_radmin.h b/src/core/ddsi/include/dds/ddsi/q_radmin.h index e61c029..95df0a7 100644 --- a/src/core/ddsi/include/dds/ddsi/q_radmin.h +++ b/src/core/ddsi/include/dds/ddsi/q_radmin.h @@ -14,7 +14,6 @@ #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/threads.h" -#include "dds/ddsi/q_rtps.h" #include "dds/ddsi/ddsi_tran.h" #if defined (__cplusplus) diff --git a/src/core/ddsi/include/dds/ddsi/q_xmsg.h b/src/core/ddsi/include/dds/ddsi/q_xmsg.h index 9236c44..ef634a9 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xmsg.h +++ b/src/core/ddsi/include/dds/ddsi/q_xmsg.h @@ -29,6 +29,7 @@ struct proxy_writer; struct nn_prismtech_participant_version_info; struct nn_prismtech_writer_info; +struct nn_prismtech_eotinfo; struct nn_xmsgpool; struct nn_xmsg_data; struct nn_xmsg; diff --git a/src/core/ddsi/src/ddsi_eth.h b/src/core/ddsi/src/ddsi_eth.h index 60d17b7..472d3e7 100644 --- a/src/core/ddsi/src/ddsi_eth.h +++ b/src/core/ddsi/src/ddsi_eth.h @@ -14,6 +14,14 @@ #include "dds/ddsi/ddsi_tran.h" +#if defined (__cplusplus) +extern "C" { +#endif + int ddsi_eth_enumerate_interfaces(ddsi_tran_factory_t fact, ddsrt_ifaddrs_t **ifs); +#if defined (__cplusplus) +} +#endif + #endif /* DDSI_ETH_H */ diff --git a/src/core/ddsi/src/ddsi_ipaddr.c b/src/core/ddsi/src/ddsi_ipaddr.c index c124b89..88b00c5 100644 --- a/src/core/ddsi/src/ddsi_ipaddr.c +++ b/src/core/ddsi/src/ddsi_ipaddr.c @@ -18,6 +18,7 @@ #include "dds/ddsi/ddsi_ipaddr.h" #include "dds/ddsi/q_nwif.h" #include "dds/ddsi/q_config.h" +#include "dds/ddsi/q_globals.h" int ddsi_ipaddr_compare (const struct sockaddr *const sa1, const struct sockaddr *const sa2) { diff --git a/src/core/ddsi/src/ddsi_mcgroup.c b/src/core/ddsi/src/ddsi_mcgroup.c index 51ca755..4fc2eb1 100644 --- a/src/core/ddsi/src/ddsi_mcgroup.c +++ b/src/core/ddsi/src/ddsi_mcgroup.c @@ -20,6 +20,7 @@ #include "dds/ddsi/ddsi_mcgroup.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" +#include "dds/ddsi/q_globals.h" #include "dds/ddsrt/avl.h" struct nn_group_membership_node { diff --git a/src/core/ddsi/src/ddsi_raweth.c b/src/core/ddsi/src/ddsi_raweth.c index be789b9..98cb1d5 100644 --- a/src/core/ddsi/src/ddsi_raweth.c +++ b/src/core/ddsi/src/ddsi_raweth.c @@ -18,6 +18,7 @@ #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_error.h" #include "dds/ddsi/q_pcap.h" +#include "dds/ddsi/q_globals.h" #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index c7c2cf9..03e340e 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -24,6 +24,7 @@ #include "dds/ddsi/ddsi_tkmap.h" #include "dds__stream.h" #include "dds/ddsi/q_radmin.h" +#include "dds/ddsi/q_globals.h" #include "dds/ddsi/ddsi_serdata_default.h" #define MAX_POOL_SIZE 16384 diff --git a/src/core/ddsi/src/ddsi_sertopic.c b/src/core/ddsi/src/ddsi_sertopic.c index c4971b2..a309289 100644 --- a/src/core/ddsi/src/ddsi_sertopic.c +++ b/src/core/ddsi/src/ddsi_sertopic.c @@ -37,9 +37,9 @@ void ddsi_sertopic_unref (struct ddsi_sertopic *sertopic) if (ddsrt_atomic_dec32_ov (&sertopic->refc) == 1) { ddsi_sertopic_deinit (sertopic); - ddsrt_free (sertopic->name_typename); + ddsrt_free (sertopic->name_type_name); ddsrt_free (sertopic->name); - ddsrt_free (sertopic->typename); + ddsrt_free (sertopic->type_name); ddsrt_free (sertopic); } } diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index 0adbd73..2a48e78 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -25,6 +25,7 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_entity.h" +#include "dds/ddsi/q_globals.h" #define INVALID_PORT (~0u) diff --git a/src/core/ddsi/src/ddsi_tran.c b/src/core/ddsi/src/ddsi_tran.c index 1d07228..c1ef648 100644 --- a/src/core/ddsi/src/ddsi_tran.c +++ b/src/core/ddsi/src/ddsi_tran.c @@ -19,6 +19,7 @@ #include "dds/ddsi/ddsi_tran.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" +#include "dds/ddsi/q_globals.h" static ddsi_tran_factory_t ddsi_tran_factories = NULL; diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index 0ab4489..628c7e0 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -25,6 +25,7 @@ #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_pcap.h" +#include "dds/ddsi/q_globals.h" extern void ddsi_factory_conn_init (ddsi_tran_factory_t factory, ddsi_tran_conn_t conn); diff --git a/src/core/ddsi/src/q_debmon.c b/src/core/ddsi/src/q_debmon.c index 2e5358a..35ed218 100644 --- a/src/core/ddsi/src/q_debmon.c +++ b/src/core/ddsi/src/q_debmon.c @@ -121,7 +121,7 @@ static int print_any_endpoint_common (ddsi_tran_conn_t conn, const char *label, if (xqos->partition.n > 1) cpf (conn, "}"); x += cpf (conn, ".%s/%s", topic && topic->name ? topic->name : (xqos->present & QP_TOPIC_NAME) ? xqos->topic_name : "(null)", - topic && topic->typename ? topic->typename : (xqos->present & QP_TYPE_NAME) ? xqos->type_name : "(null)"); + topic && topic->type_name ? topic->type_name : (xqos->present & QP_TYPE_NAME) ? xqos->type_name : "(null)"); } cpf (conn, "\n"); return x; diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 25ef9ea..31437b0 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -2383,7 +2383,7 @@ static void new_reader_writer_common (const struct nn_guid *guid, const struct d PGUID (*guid), partition, partition_suffix, topic ? topic->name : "(null)", - topic ? topic->typename : "(null)"); + topic ? topic->type_name : "(null)"); } static void endpoint_common_init (struct entity_common *e, struct endpoint_common *c, enum entity_kind kind, const struct nn_guid *guid, const struct nn_guid *group_guid, struct participant *pp) @@ -2415,7 +2415,7 @@ static int set_topic_type_name (nn_xqos_t *xqos, const struct ddsi_sertopic * to if (!(xqos->present & QP_TYPE_NAME) && topic) { xqos->present |= QP_TYPE_NAME; - xqos->type_name = ddsrt_strdup (topic->typename); + xqos->type_name = ddsrt_strdup (topic->type_name); } if (!(xqos->present & QP_TOPIC_NAME) && topic) { @@ -2881,7 +2881,7 @@ struct local_orphan_writer *new_local_orphan_writer (nn_entityid_t entityid, str struct writer *wr; nn_mtime_t tnow = now_mt (); - DDS_LOG(DDS_LC_DISCOVERY, "new_local_orphan_writer(%s/%s)\n", topic->name, topic->typename); + DDS_LOG(DDS_LC_DISCOVERY, "new_local_orphan_writer(%s/%s)\n", topic->name, topic->type_name); lowr = ddsrt_malloc (sizeof (*lowr)); wr = &lowr->wr; diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index d44cec1..c02a63d 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -28,6 +28,7 @@ #include "dds/ddsi/q_xmsg.h" #include "dds/ddsi/q_config.h" +#include "dds/ddsi/q_globals.h" #include "dds/ddsi/q_protocol.h" /* for NN_STATUSINFO_... */ #include "dds/ddsi/q_radmin.h" /* for nn_plist_quickscan */ #include "dds/ddsi/q_static_assert.h" diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 520c334..4ae45ce 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -1885,7 +1885,7 @@ static struct ddsi_serdata *extract_sample_from_data "data(application, vendor %u.%u): %x:%x:%x:%x #%"PRId64": deserialization %s/%s failed (%s)\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (guid), sampleinfo->seq, - topic->name, topic->typename, + topic->name, topic->type_name, failmsg ? failmsg : "for reasons unknown" ); } @@ -2388,7 +2388,7 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con if (gap_was_valuable) { const char *tname = pwr->c.topic ? pwr->c.topic->name : "(null)"; - const char *ttname = pwr->c.topic ? pwr->c.topic->typename : "(null)"; + const char *ttname = pwr->c.topic ? pwr->c.topic->type_name : "(null)"; DDS_WARNING ("dropping oversize (%u > %u) sample %"PRId64" from remote writer %x:%x:%x:%x %s/%s\n", sampleinfo->size, config.max_sample_size, sampleinfo->seq, PGUIDPREFIX (rst->src_guid_prefix), msg->writerId.u, diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 4d67295..c83c008 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -868,7 +868,7 @@ static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct nn_plist char ppbuf[1024]; int tmp; const char *tname = wr->topic ? wr->topic->name : "(null)"; - const char *ttname = wr->topic ? wr->topic->typename : "(null)"; + const char *ttname = wr->topic ? wr->topic->type_name : "(null)"; ppbuf[0] = '\0'; tmp = sizeof (ppbuf) - 1; DDS_TRACE("write_sample %x:%x:%x:%x #%"PRId64"", PGUID (wr->e.guid), seq); @@ -1043,7 +1043,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * char ppbuf[1024]; int tmp; const char *tname = wr->topic ? wr->topic->name : "(null)"; - const char *ttname = wr->topic ? wr->topic->typename : "(null)"; + const char *ttname = wr->topic ? wr->topic->type_name : "(null)"; ppbuf[0] = '\0'; tmp = sizeof (ppbuf) - 1; DDS_WARNING ("dropping oversize (%u > %u) sample from local writer %x:%x:%x:%x %s/%s:%s%s\n", diff --git a/src/ddsrt/include/dds/ddsrt/atomics/arm.h b/src/ddsrt/include/dds/ddsrt/atomics/arm.h index e0b0d1c..863e483 100644 --- a/src/ddsrt/include/dds/ddsrt/atomics/arm.h +++ b/src/ddsrt/include/dds/ddsrt/atomics/arm.h @@ -12,6 +12,10 @@ #ifndef DDSRT_ATOMICS_ARM_H #define DDSRT_ATOMICS_ARM_H +#if defined (__cplusplus) +extern "C" { +#endif + #if !defined(__arm__) #define __arm__ #endif @@ -209,5 +213,8 @@ inline void ddsrt_atomic_fence_rel (void) { ddsrt_atomic_fence (); } -#endif /* DDSRT_ATOMICS_ARM_H */ +#if defined (__cplusplus) +} +#endif +#endif /* DDSRT_ATOMICS_ARM_H */ diff --git a/src/ddsrt/include/dds/ddsrt/atomics/gcc.h b/src/ddsrt/include/dds/ddsrt/atomics/gcc.h index 0c62272..4da5f29 100644 --- a/src/ddsrt/include/dds/ddsrt/atomics/gcc.h +++ b/src/ddsrt/include/dds/ddsrt/atomics/gcc.h @@ -14,6 +14,10 @@ #include "dds/ddsrt/misc.h" +#if defined (__cplusplus) +extern "C" { +#endif + #if ( DDSRT_HAVE_ATOMIC64 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) || \ (!DDSRT_HAVE_ATOMIC64 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) # define DDSRT_HAVE_ATOMIC_LIFO 1 @@ -287,5 +291,8 @@ inline void ddsrt_atomic_fence_rel (void) { ddsrt_atomic_fence (); } -#endif /* DDSRT_ATOMICS_GCC_H */ +#if defined (__cplusplus) +} +#endif +#endif /* DDSRT_ATOMICS_GCC_H */ diff --git a/src/ddsrt/include/dds/ddsrt/atomics/msvc.h b/src/ddsrt/include/dds/ddsrt/atomics/msvc.h index 01260aa..e4418e1 100644 --- a/src/ddsrt/include/dds/ddsrt/atomics/msvc.h +++ b/src/ddsrt/include/dds/ddsrt/atomics/msvc.h @@ -14,6 +14,10 @@ #include "dds/ddsrt/misc.h" +#if defined (__cplusplus) +extern "C" { +#endif + /* x86 has supported 64-bit CAS for a long time, so Windows ought to provide all the interlocked operations for 64-bit operands on x86 platforms, but it doesn't. */ @@ -295,5 +299,8 @@ inline void ddsrt_atomic_fence_rel (void) { #undef DDSRT_ATOMIC_PTROP -#endif /* DDSRT_ATOMICS_MSVC_H */ +#if defined (__cplusplus) +} +#endif +#endif /* DDSRT_ATOMICS_MSVC_H */ diff --git a/src/ddsrt/include/dds/ddsrt/atomics/sun.h b/src/ddsrt/include/dds/ddsrt/atomics/sun.h index bd364d4..74a7469 100644 --- a/src/ddsrt/include/dds/ddsrt/atomics/sun.h +++ b/src/ddsrt/include/dds/ddsrt/atomics/sun.h @@ -11,6 +11,10 @@ */ #include +#if defined (__cplusplus) +extern "C" { +#endif + #define DDSRT_ATOMIC64_SUPPORT 1 /* LD, ST */ @@ -239,3 +243,6 @@ inline void ddsrt_atomic_fence_rel (void) { membar_exit (); } +#if defined (__cplusplus) +} +#endif diff --git a/src/ddsrt/include/dds/ddsrt/cdtors.h b/src/ddsrt/include/dds/ddsrt/cdtors.h index 0b3e733..89e8cdb 100644 --- a/src/ddsrt/include/dds/ddsrt/cdtors.h +++ b/src/ddsrt/include/dds/ddsrt/cdtors.h @@ -15,10 +15,18 @@ #include "dds/export.h" #include "dds/ddsrt/sync.h" +#if defined (__cplusplus) +extern "C" { +#endif + DDS_EXPORT void ddsrt_init(void); DDS_EXPORT void ddsrt_fini(void); DDS_EXPORT ddsrt_mutex_t *ddsrt_get_singleton_mutex(void); +#if defined (__cplusplus) +} +#endif + #endif /* DDSRT_CDTORS_H */ diff --git a/src/ddsrt/include/dds/ddsrt/md5.h b/src/ddsrt/include/dds/ddsrt/md5.h index 4777d04..5d0f167 100644 --- a/src/ddsrt/include/dds/ddsrt/md5.h +++ b/src/ddsrt/include/dds/ddsrt/md5.h @@ -63,6 +63,7 @@ #define DDSRT_MD5_H #include +#include "dds/export.h" /* * This package supports both compile-time and run-time determination of CPU @@ -90,13 +91,13 @@ extern "C" #endif /* Initialize the algorithm. */ -void ddsrt_md5_init(ddsrt_md5_state_t *pms); +DDS_EXPORT void ddsrt_md5_init(ddsrt_md5_state_t *pms); /* Append a string to the message. */ -void ddsrt_md5_append(ddsrt_md5_state_t *pms, const ddsrt_md5_byte_t *data, unsigned nbytes); +DDS_EXPORT void ddsrt_md5_append(ddsrt_md5_state_t *pms, const ddsrt_md5_byte_t *data, unsigned nbytes); /* Finish the message and return the digest. */ -void ddsrt_md5_finish(ddsrt_md5_state_t *pms, ddsrt_md5_byte_t digest[16]); +DDS_EXPORT void ddsrt_md5_finish(ddsrt_md5_state_t *pms, ddsrt_md5_byte_t digest[16]); #ifdef __cplusplus } /* end extern "C" */ diff --git a/src/ddsrt/include/dds/ddsrt/retcode.h b/src/ddsrt/include/dds/ddsrt/retcode.h index 8651e22..f57626d 100644 --- a/src/ddsrt/include/dds/ddsrt/retcode.h +++ b/src/ddsrt/include/dds/ddsrt/retcode.h @@ -5,6 +5,10 @@ #include "dds/export.h" +#if defined (__cplusplus) +extern "C" { +#endif + typedef int32_t dds_retcode_t; /* @@ -86,4 +90,8 @@ typedef int32_t dds_retcode_t; */ DDS_EXPORT const char *dds_strretcode(dds_retcode_t ret); +#if defined (__cplusplus) +} +#endif + #endif /* DDS_RETCODE_H */ diff --git a/src/ddsrt/include/dds/ddsrt/rusage.h b/src/ddsrt/include/dds/ddsrt/rusage.h index 2147876..040ce2e 100644 --- a/src/ddsrt/include/dds/ddsrt/rusage.h +++ b/src/ddsrt/include/dds/ddsrt/rusage.h @@ -17,6 +17,10 @@ #include "dds/ddsrt/time.h" #include "dds/ddsrt/retcode.h" +#if defined (__cplusplus) +extern "C" { +#endif + typedef struct { dds_time_t utime; /* User CPU time used. */ dds_time_t stime; /* System CPU time used. */ @@ -47,4 +51,8 @@ typedef struct { */ DDS_EXPORT dds_retcode_t ddsrt_getrusage(int who, ddsrt_rusage_t *usage); +#if defined (__cplusplus) +} +#endif + #endif /* DDSRT_RUSAGE_H */ diff --git a/src/ddsrt/include/dds/ddsrt/sockets.h b/src/ddsrt/include/dds/ddsrt/sockets.h index 645af42..ec5efa3 100644 --- a/src/ddsrt/include/dds/ddsrt/sockets.h +++ b/src/ddsrt/include/dds/ddsrt/sockets.h @@ -14,6 +14,10 @@ #include "dds/ddsrt/sockets/posix.h" #endif +#if defined (__cplusplus) +extern "C" { +#endif + #define INET_ADDRSTRLEN_EXTENDED (INET_ADDRSTRLEN + 6) /* ":12345" */ #if DDSRT_HAVE_IPV6 @@ -261,4 +265,8 @@ ddsrt_gethostbyname( ddsrt_hostent_t **hentp); #endif +#if defined (__cplusplus) +} +#endif + #endif /* DDSRT_SOCKETS_H */ diff --git a/src/ddsrt/include/dds/ddsrt/strtod.h b/src/ddsrt/include/dds/ddsrt/strtod.h index 739ee94..f8bb511 100644 --- a/src/ddsrt/include/dds/ddsrt/strtod.h +++ b/src/ddsrt/include/dds/ddsrt/strtod.h @@ -22,6 +22,10 @@ #include "dds/export.h" #include "dds/ddsrt/retcode.h" +#if defined (__cplusplus) +extern "C" { +#endif + /** * @brief Convert a string to a double precision floating point number. * @@ -72,4 +76,8 @@ ddsrt_dtostr(double src, char *str, size_t size); DDS_EXPORT int ddsrt_ftostr(float src, char *str, size_t size); +#if defined (__cplusplus) +} +#endif + #endif /* DDSRT_STRTOD_H */ From 02aaadbd20a1b29113e9fc597238e8219cd5a946 Mon Sep 17 00:00:00 2001 From: YuSheng Date: Tue, 30 Apr 2019 01:09:40 +0800 Subject: [PATCH 051/238] add RPATH for compiled tools to find the libddsc.so (#153) * add RPATH for compiled tools to find the libddsc.so Signed-off-by: YuSheng --- src/CMakeLists.txt | 5 +++++ src/tools/pubsub/CMakeLists.txt | 1 + 2 files changed, 6 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e56d494..d1539dd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -154,6 +154,11 @@ endif() include(GNUInstallDirs) include(AnalyzeBuild) +if(APPLE) + set(CMAKE_INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR}") +else() + set(CMAKE_INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") +endif() # Include Coverage before CTest so that COVERAGE_COMMAND can be modified # in the Coverage module should that ever be necessary. include(Coverage) diff --git a/src/tools/pubsub/CMakeLists.txt b/src/tools/pubsub/CMakeLists.txt index f7244c7..62a9494 100644 --- a/src/tools/pubsub/CMakeLists.txt +++ b/src/tools/pubsub/CMakeLists.txt @@ -11,6 +11,7 @@ # add_executable(pubsub pubsub.c common.c testtype.c porting.c) target_link_libraries(pubsub ddsc) + if(WIN32) target_compile_definitions(pubsub PRIVATE _CRT_SECURE_NO_WARNINGS) endif() From dc7b64396b3714258aae884eb733bcf3f5dcfebb Mon Sep 17 00:00:00 2001 From: Jeroen Koekkoek Date: Mon, 29 Apr 2019 15:57:14 +0200 Subject: [PATCH 052/238] Fix warnings related to fixed type integers Signed-off-by: Jeroen Koekkoek --- src/core/ddsc/src/dds_init.c | 6 +- src/core/ddsc/src/dds_qos.c | 2 +- src/core/ddsc/src/dds_rhc.c | 26 ++-- src/core/ddsc/src/dds_write.c | 4 +- src/core/ddsi/include/dds/ddsi/q_rtps.h | 1 + src/core/ddsi/src/ddsi_tcp.c | 18 +-- src/core/ddsi/src/ddsi_threadmon.c | 2 +- src/core/ddsi/src/ddsi_udp.c | 14 +-- src/core/ddsi/src/q_ddsi_discovery.c | 72 +++++------ src/core/ddsi/src/q_entity.c | 154 ++++++++++++------------ src/core/ddsi/src/q_init.c | 16 +-- src/core/ddsi/src/q_lease.c | 16 +-- src/core/ddsi/src/q_nwif.c | 6 +- src/core/ddsi/src/q_plist.c | 44 +++---- src/core/ddsi/src/q_radmin.c | 32 ++--- src/core/ddsi/src/q_receive.c | 120 +++++++++--------- src/core/ddsi/src/q_sockwaitset.c | 2 +- src/core/ddsi/src/q_thread.c | 2 +- src/core/ddsi/src/q_transmit.c | 20 +-- src/core/ddsi/src/q_xevent.c | 38 +++--- src/core/ddsi/src/q_xmsg.c | 16 +-- src/tools/ddsperf/ddsperf.c | 4 +- 22 files changed, 308 insertions(+), 307 deletions(-) diff --git a/src/core/ddsc/src/dds_init.c b/src/core/ddsc/src/dds_init.c index 9e74180..9db9187 100644 --- a/src/core/ddsc/src/dds_init.c +++ b/src/core/ddsc/src/dds_init.c @@ -96,7 +96,7 @@ dds_init(dds_domainid_t domain) { if (domain < 0 || domain > 230) { - DDS_ERROR("requested domain id %d is out of range\n", domain); + DDS_ERROR("requested domain id %"PRId32" is out of range\n", domain); ret = DDS_ERRNO(DDS_RETCODE_ERROR); goto fail_config_domainid; } @@ -106,7 +106,7 @@ dds_init(dds_domainid_t domain) } else if (domain != config.domainId.value) { - DDS_ERROR("requested domain id %d is inconsistent with configured value %d\n", domain, config.domainId.value); + DDS_ERROR("requested domain id %"PRId32" is inconsistent with configured value %"PRId32"\n", domain, config.domainId.value); ret = DDS_ERRNO(DDS_RETCODE_ERROR); goto fail_config_domainid; } @@ -298,7 +298,7 @@ dds__check_domain( if (domain != dds_global.m_default_domain) { DDS_ERROR("Inconsistent domain configuration detected: domain on " - "configuration: %d, domain %d\n", dds_global.m_default_domain, domain); + "configuration: %"PRId32", domain %"PRId32"\n", dds_global.m_default_domain, domain); ret = DDS_ERRNO(DDS_RETCODE_ERROR); } } diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index d95add8..b53d046 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -537,7 +537,7 @@ void dds_qset_partition return ; } if(n && !ps) { - DDS_ERROR("Argument ps is NULL, but n (%u) > 0", n); + DDS_ERROR("Argument ps is NULL, but n (%"PRIu32") > 0", n); return ; } diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index 74133c0..79a134a 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -1757,7 +1757,7 @@ static int dds_rhc_read_w_qminv (struct rhc *rhc, bool lock, void **values, dds_ ddsrt_mutex_lock (&rhc->lock); } - TRACE ("read_w_qminv(%p,%p,%p,%u,%x,%p) - inst %u nonempty %u disp %u nowr %u new %u samples %u+%u read %u+%u\n", + TRACE ("read_w_qminv(%p,%p,%p,%"PRIu32",%x,%p) - inst %"PRIu32" nonempty %"PRIu32" disp %"PRIu32" nowr %"PRIu32" new %"PRIu32" samples %"PRIu32"+%"PRIu32" read %"PRIu32"+%"PRIu32"\n", (void *) rhc, (void *) values, (void *) info_seq, max_samples, qminv, (void *) cond, rhc->n_instances, rhc->n_nonempty_instances, rhc->n_not_alive_disposed, rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, rhc->n_invsamples, @@ -1858,7 +1858,7 @@ static int dds_rhc_read_w_qminv (struct rhc *rhc, bool lock, void **values, dds_ } while (inst != end && n < max_samples); } - TRACE ("read: returning %u\n", n); + TRACE ("read: returning %"PRIu32"\n", n); assert (rhc_check_counts_locked (rhc, true, false)); ddsrt_mutex_unlock (&rhc->lock); @@ -1880,7 +1880,7 @@ static int dds_rhc_take_w_qminv (struct rhc *rhc, bool lock, void **values, dds_ ddsrt_mutex_lock (&rhc->lock); } - TRACE ("take_w_qminv(%p,%p,%p,%u,%x) - inst %u nonempty %u disp %u nowr %u new %u samples %u+%u read %u+%u\n", + TRACE ("take_w_qminv(%p,%p,%p,%"PRIu32",%x) - inst %"PRIu32" nonempty %"PRIu32" disp %"PRIu32" nowr %"PRIu32" new %"PRIu32" samples %"PRIu32"+%"PRIu32" read %"PRIu32"+%"PRIu32"\n", (void*) rhc, (void*) values, (void*) info_seq, max_samples, qminv, rhc->n_instances, rhc->n_nonempty_instances, rhc->n_not_alive_disposed, rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, @@ -2020,7 +2020,7 @@ static int dds_rhc_take_w_qminv (struct rhc *rhc, bool lock, void **values, dds_ inst = inst1; } } - TRACE ("take: returning %u\n", n); + TRACE ("take: returning %"PRIu32"\n", n); assert (rhc_check_counts_locked (rhc, true, false)); ddsrt_mutex_unlock (&rhc->lock); @@ -2043,7 +2043,7 @@ static int dds_rhc_takecdr_w_qminv (struct rhc *rhc, bool lock, struct ddsi_serd ddsrt_mutex_lock (&rhc->lock); } - TRACE ("take_w_qminv(%p,%p,%p,%u,%x) - inst %u nonempty %u disp %u nowr %u new %u samples %u+%u read %u+%u\n", + TRACE ("take_w_qminv(%p,%p,%p,%"PRIu32",%x) - inst %"PRIu32" nonempty %"PRIu32" disp %"PRIu32" nowr %"PRIu32" new %"PRIu32" samples %"PRIu32"+%"PRIu32" read %"PRIu32"+%"PRIu32"\n", (void*) rhc, (void*) values, (void*) info_seq, max_samples, qminv, rhc->n_instances, rhc->n_nonempty_instances, rhc->n_not_alive_disposed, rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, @@ -2172,7 +2172,7 @@ static int dds_rhc_takecdr_w_qminv (struct rhc *rhc, bool lock, struct ddsi_serd inst = inst1; } } - TRACE ("take: returning %u\n", n); + TRACE ("take: returning %"PRIu32"\n", n); assert (rhc_check_counts_locked (rhc, true, false)); ddsrt_mutex_unlock (&rhc->lock); @@ -2205,7 +2205,7 @@ static uint32_t rhc_get_cond_trigger (struct rhc_instance * const inst, const dd m = m && !inst_is_empty (inst); break; default: - DDS_FATAL("update_readconditions: sample_states invalid: %x\n", c->m_sample_states); + DDS_FATAL("update_readconditions: sample_states invalid: %"PRIx32"\n", c->m_sample_states); } return m ? 1 : 0; } @@ -2221,7 +2221,7 @@ static bool cond_is_sample_state_dependent (const struct dds_readcond *cond) case 0: return false; default: - DDS_FATAL("update_readconditions: sample_states invalid: %x\n", cond->m_sample_states); + DDS_FATAL("update_readconditions: sample_states invalid: %"PRIx32"\n", cond->m_sample_states); return false; } } @@ -2322,7 +2322,7 @@ bool dds_rhc_add_readcondition (dds_readcond *cond) if (cond->m_entity.m_trigger) dds_entity_status_signal (&cond->m_entity); - TRACE ("add_readcondition(%p, %x, %x, %x) => %p qminv %x ; rhc %u conds\n", + TRACE ("add_readcondition(%p, %"PRIx32", %"PRIx32", %"PRIx32") => %p qminv %"PRIx32" ; rhc %"PRIu32" conds\n", (void *) rhc, cond->m_sample_states, cond->m_view_states, cond->m_instance_states, (void *) cond, cond->m_qminv, rhc->nconds); @@ -2362,10 +2362,10 @@ static bool update_conditions_locked (struct rhc *rhc, bool called_from_insert, dds_readcond *iter; bool m_pre, m_post; - TRACE ("update_conditions_locked(%p %p) - inst %u nonempty %u disp %u nowr %u new %u samples %u read %u\n", + TRACE ("update_conditions_locked(%p %p) - inst %"PRIu32" nonempty %"PRIu32" disp %"PRIu32" nowr %"PRIu32" new %"PRIu32" samples %"PRIu32" read %"PRIu32"\n", (void *) rhc, (void *) inst, rhc->n_instances, rhc->n_nonempty_instances, rhc->n_not_alive_disposed, rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, rhc->n_vread); - TRACE (" read -[%d,%d]+[%d,%d] qcmask -[%x,%x]+[%x,%x]\n", + TRACE (" read -[%d,%d]+[%d,%d] qcmask -[%"PRIx32",%"PRIx32"]+[%"PRIx32",%"PRIx32"]\n", trig_qc->dec_invsample_read, trig_qc->dec_sample_read, trig_qc->inc_invsample_read, trig_qc->inc_sample_read, trig_qc->dec_conds_invsample, trig_qc->dec_conds_sample, trig_qc->inc_conds_invsample, trig_qc->inc_conds_sample); @@ -2404,7 +2404,7 @@ static bool update_conditions_locked (struct rhc *rhc, bool called_from_insert, m_post = m_post && (post->c.has_read + post->c.has_not_read); break; default: - DDS_FATAL ("update_readconditions: sample_states invalid: %x\n", iter->m_sample_states); + DDS_FATAL ("update_readconditions: sample_states invalid: %"PRIx32"\n", iter->m_sample_states); } TRACE (" cond %p %08"PRIx32": ", (void *) iter, iter->m_query.m_qcmask); @@ -2464,7 +2464,7 @@ static bool update_conditions_locked (struct rhc *rhc, bool called_from_insert, mdelta += (trig_qc->inc_conds_sample & qcmask) != 0; break; default: - DDS_FATAL ("update_readconditions: sample_states invalid: %x\n", iter->m_sample_states); + DDS_FATAL ("update_readconditions: sample_states invalid: %"PRIx32"\n", iter->m_sample_states); } if (m_pre == m_post) diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index 98a590b..032141a 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -106,7 +106,7 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay unsigned i; make_proxy_writer_info (&pwr_info, &wr->e, wr->xqos); for (i = 0; rdary[i]; i++) { - DDS_TRACE ("reader %x:%x:%x:%x\n", PGUID (rdary[i]->e.guid)); + DDS_TRACE ("reader "PGUIDFMT"\n", PGUID (rdary[i]->e.guid)); if ((ret = try_store (rdary[i]->rhc, &pwr_info, payload, tk, &max_block_ms)) != DDS_RETCODE_OK) break; } @@ -135,7 +135,7 @@ static dds_return_t deliver_locally (struct writer *wr, struct ddsi_serdata *pay struct reader *rd; if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL) { - DDS_TRACE("reader-via-guid %x:%x:%x:%x\n", PGUID (rd->e.guid)); + DDS_TRACE("reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid)); /* Copied the return value ignore from DDSI deliver_user_data() function. */ if ((ret = try_store (rd->rhc, &pwr_info, payload, tk, &max_block_ms)) != DDS_RETCODE_OK) break; diff --git a/src/core/ddsi/include/dds/ddsi/q_rtps.h b/src/core/ddsi/include/dds/ddsi/q_rtps.h index 731fbd9..57e3d0a 100644 --- a/src/core/ddsi/include/dds/ddsi/q_rtps.h +++ b/src/core/ddsi/include/dds/ddsi/q_rtps.h @@ -37,6 +37,7 @@ typedef int64_t seqno_t; #define PGUIDPREFIX(gp) (gp).u[0], (gp).u[1], (gp).u[2] #define PGUID(g) PGUIDPREFIX ((g).prefix), (g).entityid.u +#define PGUIDFMT "%"PRIx32":%"PRIx32":%"PRIx32":%"PRIx32 /* predefined entity ids; here viewed as an unsigned int, on the network as four bytes corresponding to the integer in network byte diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index 2a48e78..8d7ec2b 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -154,7 +154,7 @@ static unsigned short get_socket_port (ddsrt_socket_t socket) ret = ddsrt_getsockname(socket, (struct sockaddr *)&addr, &addrlen); if (ret != DDS_RETCODE_OK) { - DDS_ERROR("ddsi_tcp_get_socket_port: ddsrt_getsockname retcode %d\n", ret); + DDS_ERROR("ddsi_tcp_get_socket_port: ddsrt_getsockname retcode %"PRId32"\n", ret); return 0; } return ddsrt_sockaddr_get_port((struct sockaddr *)&addr); @@ -435,7 +435,7 @@ static ssize_t ddsi_tcp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s } else { - DDS_LOG(DDS_LC_TCP, "%s read: sock %"PRIdSOCK" error %d\n", ddsi_name, tcp->m_sock, rc); + DDS_LOG(DDS_LC_TCP, "%s read: sock %"PRIdSOCK" error %"PRId32"\n", ddsi_name, tcp->m_sock, rc); break; } } @@ -500,7 +500,7 @@ static ssize_t ddsi_tcp_block_write } else { - DDS_LOG(DDS_LC_TCP, "%s write: sock %"PRIdSOCK" error %d\n", ddsi_name, conn->m_sock, rc); + DDS_LOG(DDS_LC_TCP, "%s write: sock %"PRIdSOCK" error %"PRId32"\n", ddsi_name, conn->m_sock, rc); break; } } @@ -638,7 +638,7 @@ static ssize_t ddsi_tcp_conn_write (ddsi_tran_conn_t base, const nn_locator_t *d break; default: if (! conn->m_base.m_closed && (conn->m_sock != DDSRT_INVALID_SOCKET)) - DDS_WARNING("%s write failed on socket %"PRIdSOCK" with errno %d\n", ddsi_name, conn->m_sock, rc); + DDS_WARNING("%s write failed on socket %"PRIdSOCK" with errno %"PRId32"\n", ddsi_name, conn->m_sock, rc); break; } } @@ -775,11 +775,11 @@ static ddsi_tran_conn_t ddsi_tcp_accept (ddsi_tran_listener_t listener) { (void)ddsrt_getsockname (tl->m_sock, (struct sockaddr *) &addr, &addrlen); sockaddr_to_string_with_port(buff, sizeof(buff), (struct sockaddr *)&addr); - DDS_LOG((rc == DDS_RETCODE_OK) ? DDS_LC_ERROR : DDS_LC_FATAL, "%s accept failed on socket %"PRIdSOCK" at %s retcode %d\n", ddsi_name, tl->m_sock, buff, rc); + DDS_LOG((rc == DDS_RETCODE_OK) ? DDS_LC_ERROR : DDS_LC_FATAL, "%s accept failed on socket %"PRIdSOCK" at %s retcode %"PRId32"\n", ddsi_name, tl->m_sock, buff, rc); } else if (getpeername (sock, (struct sockaddr *) &addr, &addrlen) == -1) { - DDS_WARNING("%s accepted new socket %"PRIdSOCK" on socket %"PRIdSOCK" but no peer address, errno %d\n", ddsi_name, sock, tl->m_sock, rc); + DDS_WARNING("%s accepted new socket %"PRIdSOCK" on socket %"PRIdSOCK" but no peer address, errno %"PRId32"\n", ddsi_name, sock, tl->m_sock, rc); ddsrt_close (sock); } else @@ -886,7 +886,7 @@ static ddsi_tran_listener_t ddsi_tcp_create_listener (int port, ddsi_tran_qos_t ret = ddsrt_getsockname(sock, (struct sockaddr *)&addr, &addrlen); if (ret != DDS_RETCODE_OK) { - DDS_ERROR("ddsi_tcp_create_listener: ddsrt_getsockname returned %d\n", ret); + DDS_ERROR("ddsi_tcp_create_listener: ddsrt_getsockname returned %"PRId32"\n", ret); ddsi_tcp_sock_free(sock, NULL); ddsrt_free(tl); return NULL; @@ -958,7 +958,7 @@ static void ddsi_tcp_unblock_listener (ddsi_tran_listener_t listener) ret = ddsrt_getsockname(tl->m_sock, (struct sockaddr *)&addr, &addrlen); if (ret != DDS_RETCODE_OK) { - DDS_WARNING("%s failed to get listener address error %d\n", ddsi_name, ret); + DDS_WARNING("%s failed to get listener address error %"PRId32"\n", ddsi_name, ret); } else { switch (addr.ss_family) { case AF_INET: @@ -988,7 +988,7 @@ static void ddsi_tcp_unblock_listener (ddsi_tran_listener_t listener) { char buff[DDSI_LOCSTRLEN]; sockaddr_to_string_with_port(buff, sizeof(buff), (struct sockaddr *)&addr); - DDS_WARNING("%s failed to connect to own listener (%s) error %d\n", ddsi_name, buff, ret); + DDS_WARNING("%s failed to connect to own listener (%s) error %"PRId32"\n", ddsi_name, buff, ret); } } ddsi_tcp_sock_free (sock, NULL); diff --git a/src/core/ddsi/src/ddsi_threadmon.c b/src/core/ddsi/src/ddsi_threadmon.c index 755848c..f257261 100644 --- a/src/core/ddsi/src/ddsi_threadmon.c +++ b/src/core/ddsi/src/ddsi_threadmon.c @@ -88,7 +88,7 @@ static uint32_t threadmon_thread (struct ddsi_threadmon *sl) vtime_t vt = thread_states.ts[i].vtime; bool alive = vtime_asleep_p (vt) || vtime_asleep_p (sl->av_ary[i].vt) || vtime_gt (vt, sl->av_ary[i].vt); n_alive += (unsigned) alive; - DDS_TRACE(" %u(%s):%c:%x->%x", i, thread_states.ts[i].name, alive ? 'a' : 'd', sl->av_ary[i].vt, vt); + DDS_TRACE(" %u(%s):%c:%"PRIx32"->%"PRIx32, i, thread_states.ts[i].name, alive ? 'a' : 'd', sl->av_ary[i].vt, vt); sl->av_ary[i].vt = vt; if (sl->av_ary[i].alive != alive) { diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index 628c7e0..53135f1 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -103,7 +103,7 @@ static ssize_t ddsi_udp_conn_read (ddsi_tran_conn_t conn, unsigned char * buf, s else if (rc != DDS_RETCODE_BAD_PARAMETER && rc != DDS_RETCODE_NO_CONNECTION) { - DDS_ERROR("UDP recvmsg sock %d: ret %d retcode %d\n", (int) ((ddsi_udp_conn_t) conn)->m_sock, (int) ret, rc); + DDS_ERROR("UDP recvmsg sock %d: ret %d retcode %"PRId32"\n", (int) ((ddsi_udp_conn_t) conn)->m_sock, (int) ret, rc); ret = -1; } return ret; @@ -168,7 +168,7 @@ static ssize_t ddsi_udp_conn_write (ddsi_tran_conn_t conn, const nn_locator_t *d rc != DDS_RETCODE_NOT_ALLOWED && rc != DDS_RETCODE_NO_CONNECTION) { - DDS_ERROR("ddsi_udp_conn_write failed with retcode %d\n", rc); + DDS_ERROR("ddsi_udp_conn_write failed with retcode %"PRId32"\n", rc); } return (rc == DDS_RETCODE_OK ? ret : -1); } @@ -220,7 +220,7 @@ static unsigned short get_socket_port (ddsrt_socket_t socket) ret = ddsrt_getsockname (socket, (struct sockaddr *)&addr, &addrlen); if (ret != DDS_RETCODE_OK) { - DDS_ERROR("ddsi_udp_get_socket_port: getsockname returned %d\n", ret); + DDS_ERROR("ddsi_udp_get_socket_port: getsockname returned %"PRId32"\n", ret); return 0; } @@ -273,7 +273,7 @@ static ddsi_tran_conn_t ddsi_udp_create_conn DDS_TRACE ( - "ddsi_udp_create_conn %s socket %"PRIdSOCK" port %u\n", + "ddsi_udp_create_conn %s socket %"PRIdSOCK" port %"PRIu32"\n", mcast ? "multicast" : "unicast", uc->m_sock, uc->m_base.m_base.m_port @@ -284,7 +284,7 @@ static ddsi_tran_conn_t ddsi_udp_create_conn dds_retcode_t rc; rc = ddsrt_setsockopt(sock, IPPROTO_IP, IP_TOS, (char *)&uc->m_diffserv, sizeof(uc->m_diffserv)); if (rc != DDS_RETCODE_OK) - DDS_ERROR("ddsi_udp_create_conn: set diffserv retcode %d\n", rc); + DDS_ERROR("ddsi_udp_create_conn: set diffserv retcode %"PRId32"\n", rc); } #endif } @@ -294,7 +294,7 @@ static ddsi_tran_conn_t ddsi_udp_create_conn { DDS_ERROR ( - "UDP make_socket failed for %s port %u\n", + "UDP make_socket failed for %s port %"PRIu32"\n", mcast ? "multicast" : "unicast", port ); @@ -395,7 +395,7 @@ static void ddsi_udp_release_conn (ddsi_tran_conn_t conn) ddsi_udp_conn_t uc = (ddsi_udp_conn_t) conn; DDS_TRACE ( - "ddsi_udp_release_conn %s socket %"PRIdSOCK" port %u\n", + "ddsi_udp_release_conn %s socket %"PRIdSOCK" port %"PRIu32"\n", conn->m_base.m_multicast ? "multicast" : "unicast", uc->m_sock, uc->m_base.m_base.m_port diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 12ab0bc..98e89f7 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -198,11 +198,11 @@ int spdp_write (struct participant *pp) return 0; } - DDS_TRACE("spdp_write(%x:%x:%x:%x)\n", PGUID (pp->e.guid)); + DDS_TRACE("spdp_write("PGUIDFMT")\n", PGUID (pp->e.guid)); if ((wr = get_builtin_writer (pp, NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)) == NULL) { - DDS_TRACE("spdp_write(%x:%x:%x:%x) - builtin participant writer not found\n", PGUID (pp->e.guid)); + DDS_TRACE("spdp_write("PGUIDFMT") - builtin participant writer not found\n", PGUID (pp->e.guid)); return 0; } @@ -307,7 +307,7 @@ int spdp_write (struct participant *pp) size = strlen(node) + strlen(DDS_VERSION) + strlen(DDS_HOST_NAME) + strlen(DDS_TARGET_NAME) + 4; /* + ///'\0' */ ps.prismtech_participant_version_info.internals = ddsrt_malloc(size); (void) snprintf(ps.prismtech_participant_version_info.internals, size, "%s/%s/%s/%s", node, DDS_VERSION, DDS_HOST_NAME, DDS_TARGET_NAME); - DDS_TRACE("spdp_write(%x:%x:%x:%x) - internals: %s\n", PGUID (pp->e.guid), ps.prismtech_participant_version_info.internals); + DDS_TRACE("spdp_write("PGUIDFMT") - internals: %s\n", PGUID (pp->e.guid), ps.prismtech_participant_version_info.internals); } /* Participant QoS's insofar as they are set, different from the default, and mapped to the SPDP data, rather than to the PrismTech-specific CMParticipant endpoint. Currently, that means just USER_DATA. */ @@ -335,7 +335,7 @@ int spdp_dispose_unregister (struct participant *pp) if ((wr = get_builtin_writer (pp, NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)) == NULL) { - DDS_TRACE("spdp_dispose_unregister(%x:%x:%x:%x) - builtin participant writer not found\n", PGUID (pp->e.guid)); + DDS_TRACE("spdp_dispose_unregister("PGUIDFMT") - builtin participant writer not found\n", PGUID (pp->e.guid)); return 0; } @@ -416,7 +416,7 @@ static int handle_SPDP_dead (const struct receiver_state *rst, nn_wctime_t times if (datap->present & PP_PARTICIPANT_GUID) { guid = datap->participant_guid; - DDS_LOG(DDS_LC_DISCOVERY, " %x:%x:%x:%x", PGUID (guid)); + DDS_LOG(DDS_LC_DISCOVERY, " %"PRIx32":%"PRIx32":%"PRIx32":%"PRIx32, PGUID (guid)); assert (guid.entityid.u == NN_ENTITYID_PARTICIPANT); if (delete_proxy_participant_by_guid (&guid, timestamp, 0) < 0) { @@ -481,7 +481,7 @@ static void make_participants_dependent_on_ddsi2 (const nn_guid_t *ddsi2guid, nn { if (vendor_is_eclipse_or_opensplice (pp->vendor) && pp->e.guid.prefix.u[0] == ddsi2guid->prefix.u[0] && !pp->is_ddsi2_pp) { - DDS_TRACE("proxy participant %x:%x:%x:%x depends on ddsi2 %x:%x:%x:%x", PGUID (pp->e.guid), PGUID (*ddsi2guid)); + DDS_TRACE("proxy participant "PGUIDFMT" depends on ddsi2 "PGUIDFMT, PGUID (pp->e.guid), PGUID (*ddsi2guid)); ddsrt_mutex_lock (&pp->e.lock); pp->privileged_pp_guid = *ddsi2guid; ddsrt_mutex_unlock (&pp->e.lock); @@ -501,7 +501,7 @@ static void make_participants_dependent_on_ddsi2 (const nn_guid_t *ddsi2guid, nn if (pp != NULL) { - DDS_TRACE("make_participants_dependent_on_ddsi2: ddsi2 %x:%x:%x:%x is no more, delete %x:%x:%x:%x\n", PGUID (*ddsi2guid), PGUID (pp->e.guid)); + DDS_TRACE("make_participants_dependent_on_ddsi2: ddsi2 "PGUIDFMT" is no more, delete "PGUIDFMT"\n", PGUID (*ddsi2guid), PGUID (pp->e.guid)); delete_proxy_participant_by_guid (&pp->e.guid, timestamp, 1); } } @@ -569,7 +569,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time if (is_deleted_participant_guid (&datap->participant_guid, DPG_REMOTE)) { - DDS_LOG(DDS_LC_TRACE, "SPDP ST0 %x:%x:%x:%x (recently deleted)", PGUID (datap->participant_guid)); + DDS_LOG(DDS_LC_TRACE, "SPDP ST0 "PGUIDFMT" (recently deleted)", PGUID (datap->participant_guid)); return 1; } @@ -579,7 +579,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time islocal = 1; if (islocal) { - DDS_LOG(DDS_LC_TRACE, "SPDP ST0 %x:%x:%x:%x (local %d)", islocal, PGUID (datap->participant_guid)); + DDS_LOG(DDS_LC_TRACE, "SPDP ST0 "PGUIDFMT" (local %d)", PGUID (datap->participant_guid), islocal); return 0; } } @@ -590,7 +590,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time are even skipping the automatic lease renewal. Therefore do it regardless of config.arrival_of_data_asserts_pp_and_ep_liveliness. */ - DDS_LOG(DDS_LC_TRACE, "SPDP ST0 %x:%x:%x:%x (known)", PGUID (datap->participant_guid)); + DDS_LOG(DDS_LC_TRACE, "SPDP ST0 "PGUIDFMT" (known)", PGUID (datap->participant_guid)); lease_renew (ddsrt_atomic_ldvoidp (&proxypp->lease), now_et ()); ddsrt_mutex_lock (&proxypp->e.lock); if (proxypp->implicitly_created) @@ -603,7 +603,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time return 0; } - DDS_LOG(DDS_LC_DISCOVERY, "SPDP ST0 %x:%x:%x:%x bes %x ptbes %x NEW", PGUID (datap->participant_guid), builtin_endpoint_set, prismtech_builtin_endpoint_set); + DDS_LOG(DDS_LC_DISCOVERY, "SPDP ST0 "PGUIDFMT" bes %x ptbes %x NEW", PGUID (datap->participant_guid), builtin_endpoint_set, prismtech_builtin_endpoint_set); if (datap->present & PP_PARTICIPANT_LEASE_DURATION) { @@ -643,7 +643,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time if ((builtin_endpoint_set & bes_sedp_announcer_mask) != bes_sedp_announcer_mask && memcmp (&privileged_pp_guid, &datap->participant_guid, sizeof (nn_guid_t)) != 0) { - DDS_LOG(DDS_LC_DISCOVERY, " (depends on %x:%x:%x:%x)", PGUID (privileged_pp_guid)); + DDS_LOG(DDS_LC_DISCOVERY, " (depends on "PGUIDFMT")", PGUID (privileged_pp_guid)); /* never expire lease for this proxy: it won't actually expire until the "privileged" one expires anyway */ lease_duration = nn_to_ddsi_duration (T_NEVER); @@ -659,7 +659,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time { privileged_pp_guid.prefix = ddsi2->e.guid.prefix; lease_duration = nn_to_ddsi_duration (T_NEVER); - DDS_LOG(DDS_LC_DISCOVERY, " (depends on %x:%x:%x:%x)", PGUID (privileged_pp_guid)); + DDS_LOG(DDS_LC_DISCOVERY, " (depends on "PGUIDFMT")", PGUID (privileged_pp_guid)); } } else @@ -772,7 +772,7 @@ static int handle_SPDP_alive (const struct receiver_state *rst, nn_wctime_t time of DDSI2. */ if (ephash_lookup_proxy_participant_guid (&privileged_pp_guid) == NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "make_participants_dependent_on_ddsi2: ddsi2 %x:%x:%x:%x is no more, delete %x:%x:%x:%x\n", PGUID (privileged_pp_guid), PGUID (datap->participant_guid)); + DDS_LOG(DDS_LC_DISCOVERY, "make_participants_dependent_on_ddsi2: ddsi2 "PGUIDFMT" is no more, delete "PGUIDFMT"\n", PGUID (privileged_pp_guid), PGUID (datap->participant_guid)); delete_proxy_participant_by_guid (&datap->participant_guid, timestamp, 1); } } @@ -943,7 +943,7 @@ static int sedp_write_endpoint nn_xmsg_addpar_sentinel (mpayload); nn_plist_fini (&ps); - DDS_LOG(DDS_LC_DISCOVERY, "sedp: write for %x:%x:%x:%x via %x:%x:%x:%x\n", PGUID (*epguid), PGUID (wr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "sedp: write for "PGUIDFMT" via "PGUIDFMT"\n", PGUID (*epguid), PGUID (wr->e.guid)); ret = write_mpayload (wr, alive, PID_ENDPOINT_GUID, mpayload); nn_xmsg_free (mpayload); return ret; @@ -953,7 +953,7 @@ static struct writer *get_sedp_writer (const struct participant *pp, unsigned en { struct writer *sedp_wr = get_builtin_writer (pp, entityid); if (sedp_wr == NULL) - DDS_FATAL("sedp_write_writer: no SEDP builtin writer %x for %x:%x:%x:%x\n", entityid, PGUID (pp->e.guid)); + DDS_FATAL("sedp_write_writer: no SEDP builtin writer %x for "PGUIDFMT"\n", entityid, PGUID (pp->e.guid)); return sedp_wr; } @@ -1036,14 +1036,14 @@ static struct proxy_participant *implicitly_create_proxypp (const nn_guid_t *ppg { nn_vendorid_t actual_vendorid; /* Some endpoint that we discovered through the DS, but then it must have at least some locators */ - DDS_TRACE(" from-DS %x:%x:%x:%x", PGUID (privguid)); + DDS_TRACE(" from-DS %"PRIx32":%"PRIx32":%"PRIx32":%"PRIx32, PGUID (privguid)); /* avoid "no address" case, so we never create the proxy participant for nothing (FIXME: rework some of this) */ if (!(datap->present & (PP_UNICAST_LOCATOR | PP_MULTICAST_LOCATOR))) { DDS_TRACE(" data locator absent\n"); goto err; } - DDS_TRACE(" new-proxypp %x:%x:%x:%x\n", PGUID (*ppguid)); + DDS_TRACE(" new-proxypp "PGUIDFMT"\n", PGUID (*ppguid)); /* We need to handle any source of entities, but we really want to try to keep the GIDs (and certainly the systemId component) unchanged for OSPL. The new proxy participant will take the GID from the GUID if it is from a "modern" OSPL that advertises it includes all GIDs in @@ -1076,7 +1076,7 @@ static struct proxy_participant *implicitly_create_proxypp (const nn_guid_t *ppg } else { struct addrset *as_default, *as_meta; nn_plist_t tmp_plist; - DDS_TRACE(" from-ddsi2 %x:%x:%x:%x", PGUID (privguid)); + DDS_TRACE(" from-ddsi2 "PGUIDFMT, PGUID (privguid)); nn_plist_init_empty (&pp_plist); ddsrt_mutex_lock (&privpp->e.lock); @@ -1118,7 +1118,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat if (!(datap->present & PP_ENDPOINT_GUID)) E (" no guid?\n", err); - DDS_LOG(DDS_LC_DISCOVERY, " %x:%x:%x:%x", PGUID (datap->endpoint_guid)); + DDS_LOG(DDS_LC_DISCOVERY, " "PGUIDFMT, PGUID (datap->endpoint_guid)); ppguid.prefix = datap->endpoint_guid.prefix; ppguid.entityid.u = NN_ENTITYID_PARTICIPANT; @@ -1141,7 +1141,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat if ((pp = implicitly_create_proxypp (&ppguid, datap, src_guid_prefix, vendorid, timestamp)) == NULL) E ("?\n", err); /* Repeat regular SEDP trace for convenience */ - DDS_LOG(DDS_LC_DISCOVERY, "SEDP ST0 %x:%x:%x:%x (cont)", PGUID (datap->endpoint_guid)); + DDS_LOG(DDS_LC_DISCOVERY, "SEDP ST0 "PGUIDFMT" (cont)", PGUID (datap->endpoint_guid)); } xqos = &datap->qos; @@ -1200,7 +1200,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat if (vendor_is_cloud (vendorid) && pp->implicitly_created && memcmp(&pp->privileged_pp_guid.prefix, src_guid_prefix, sizeof(pp->privileged_pp_guid.prefix)) != 0) { nn_etime_t never = { T_NEVER }; - DDS_LOG(DDS_LC_DISCOVERY, " %x:%x:%x:%x attach-to-DS %x:%x:%x:%x", PGUID(pp->e.guid), PGUIDPREFIX(*src_guid_prefix), pp->privileged_pp_guid.entityid.u); + DDS_LOG(DDS_LC_DISCOVERY, " "PGUIDFMT" attach-to-DS "PGUIDFMT, PGUID(pp->e.guid), PGUIDPREFIX(*src_guid_prefix), pp->privileged_pp_guid.entityid.u); ddsrt_mutex_lock (&pp->e.lock); pp->privileged_pp_guid.prefix = *src_guid_prefix; lease_set_expiry(ddsrt_atomic_ldvoidp(&pp->lease), never); @@ -1253,7 +1253,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, nn_plist_t *dat if ((datap->endpoint_guid.entityid.u & NN_ENTITYID_SOURCE_MASK) == NN_ENTITYID_SOURCE_VENDOR && !vendor_is_eclipse_or_prismtech (vendorid)) { - DDS_LOG(DDS_LC_DISCOVERY, "ignoring vendor-specific endpoint %x:%x:%x:%x\n", PGUID (datap->endpoint_guid)); + DDS_LOG(DDS_LC_DISCOVERY, "ignoring vendor-specific endpoint "PGUIDFMT"\n", PGUID (datap->endpoint_guid)); } else { @@ -1310,7 +1310,7 @@ static void handle_SEDP_dead (nn_plist_t *datap, nn_wctime_t timestamp) DDS_LOG(DDS_LC_DISCOVERY, " no guid?\n"); return; } - DDS_LOG(DDS_LC_DISCOVERY, " %x:%x:%x:%x", PGUID (datap->endpoint_guid)); + DDS_LOG(DDS_LC_DISCOVERY, " "PGUIDFMT, PGUID (datap->endpoint_guid)); if (is_writer_entityid (datap->endpoint_guid.entityid)) { res = delete_proxy_writer (&datap->endpoint_guid, timestamp, 0); @@ -1394,7 +1394,7 @@ int sedp_write_topic (struct participant *pp, const struct nn_plist *datap) nn_plist_addtomsg (mpayload, datap, ~(uint64_t)0, delta); nn_xmsg_addpar_sentinel (mpayload); - DDS_TRACE("sedp: write topic %s via %x:%x:%x:%x\n", datap->qos.topic_name, PGUID (sedp_wr->e.guid)); + DDS_TRACE("sedp: write topic %s via "PGUIDFMT"\n", datap->qos.topic_name, PGUID (sedp_wr->e.guid)); ret = write_mpayload (sedp_wr, 1, PID_TOPIC_NAME, mpayload); nn_xmsg_free (mpayload); return ret; @@ -1441,7 +1441,7 @@ int sedp_write_cm_participant (struct participant *pp, int alive) } nn_xmsg_addpar_sentinel (mpayload); - DDS_TRACE("sedp: write CMParticipant ST%x for %x:%x:%x:%x via %x:%x:%x:%x\n", + DDS_TRACE("sedp: write CMParticipant ST%x for "PGUIDFMT" via "PGUIDFMT"\n", alive ? 0 : NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER, PGUID (pp->e.guid), PGUID (sedp_wr->e.guid)); ret = write_mpayload (sedp_wr, alive, PID_PARTICIPANT_GUID, mpayload); nn_xmsg_free (mpayload); @@ -1514,7 +1514,7 @@ int sedp_write_cm_publisher (const struct nn_plist *datap, int alive) if ((pp = group_guid_to_participant (&datap->group_guid)) == NULL) { - DDS_TRACE("sedp: write CMPublisher alive:%d for %x:%x:%x:%x dropped: no participant\n", + DDS_TRACE("sedp: write CMPublisher alive:%d for "PGUIDFMT" dropped: no participant\n", alive, PGUID (datap->group_guid)); return 0; } @@ -1550,7 +1550,7 @@ int sedp_write_cm_subscriber (const struct nn_plist *datap, int alive) if ((pp = group_guid_to_participant (&datap->group_guid)) == NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "sedp: write CMSubscriber alive:%d for %x:%x:%x:%x dropped: no participant\n", + DDS_LOG(DDS_LC_DISCOVERY, "sedp: write CMSubscriber alive:%d for "PGUIDFMT" dropped: no participant\n", alive, PGUID (datap->group_guid)); return 0; } @@ -1583,7 +1583,7 @@ static void handle_SEDP_GROUP_alive (nn_plist_t *datap /* note: potentially modi if (!(datap->present & PP_GROUP_GUID)) E (" no guid?\n", err); - DDS_LOG(DDS_LC_DISCOVERY, " %x:%x:%x:%x", PGUID (datap->group_guid)); + DDS_LOG(DDS_LC_DISCOVERY, " %"PRIx32"%"PRIx32"%"PRIx32"%"PRIx32, PGUID (datap->group_guid)); ppguid.prefix = datap->group_guid.prefix; ppguid.entityid.u = NN_ENTITYID_PARTICIPANT; @@ -1608,7 +1608,7 @@ static void handle_SEDP_GROUP_dead (nn_plist_t *datap, nn_wctime_t timestamp) DDS_LOG(DDS_LC_DISCOVERY, " no guid?\n"); return; } - DDS_LOG(DDS_LC_DISCOVERY, " %x:%x:%x:%x\n", PGUID (datap->group_guid)); + DDS_LOG(DDS_LC_DISCOVERY, " "PGUIDFMT"\n", PGUID (datap->group_guid)); delete_proxy_group (&datap->group_guid, timestamp, 0); } @@ -1757,7 +1757,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH, 0, &src)) < 0) { if (plist_ret != Q_ERR_INCOMPATIBLE) - DDS_WARNING("data(builtin, vendor %u.%u): %x:%x:%x:%x #%"PRId64": invalid inline qos\n", + DDS_WARNING("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": invalid inline qos\n", src.vendorid.id[0], src.vendorid.id[1], PGUID (srcguid), sampleinfo->seq); goto done_upd_deliv; } @@ -1781,7 +1781,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str { if (datasz == 0 || !(data_smhdr_flags & DATA_FLAG_DATAFLAG)) { - DDS_WARNING("data(builtin, vendor %u.%u): %x:%x:%x:%x #%"PRId64": " + DDS_WARNING("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": " "built-in data but no payload\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (srcguid), sampleinfo->seq); @@ -1795,7 +1795,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str hasn't been checked fully yet. */ if (!(data_smhdr_flags & DATA_FLAG_KEYFLAG)) { - DDS_WARNING("data(builtin, vendor %u.%u): %x:%x:%x:%x #%"PRId64": " + DDS_WARNING("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": " "dispose/unregister of built-in data but payload not just key\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (srcguid), sampleinfo->seq); @@ -1837,7 +1837,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str pid = PID_ENDPOINT_GUID; break; default: - DDS_LOG(DDS_LC_DISCOVERY, "data(builtin, vendor %u.%u): %x:%x:%x:%x #%"PRId64": mapping keyhash to ENDPOINT_GUID", + DDS_LOG(DDS_LC_DISCOVERY, "data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": mapping keyhash to ENDPOINT_GUID", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (srcguid), sampleinfo->seq); pid = PID_ENDPOINT_GUID; @@ -1854,7 +1854,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str } else { - DDS_WARNING("data(builtin, vendor %u.%u): %x:%x:%x:%x #%"PRId64": " + DDS_WARNING("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": " "dispose/unregister with no content\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (srcguid), sampleinfo->seq); @@ -1882,7 +1882,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str handle_SEDP_GROUP (sampleinfo->rst, timestamp, statusinfo, datap, datasz); break; default: - DDS_LOG (DDS_LC_DISCOVERY, "data(builtin, vendor %u.%u): %x:%x:%x:%x #%"PRId64": not handled\n", + DDS_LOG (DDS_LC_DISCOVERY, "data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": not handled\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (srcguid), sampleinfo->seq); break; diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 31437b0..beba3f8 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -338,7 +338,7 @@ int is_deleted_participant_guid (const struct nn_guid *guid, unsigned for_what) static void remove_deleted_participant_guid (const struct nn_guid *guid, unsigned for_what) { struct deleted_participant *n; - DDS_LOG(DDS_LC_DISCOVERY, "remove_deleted_participant_guid(%x:%x:%x:%x for_what=%x)\n", PGUID (*guid), for_what); + DDS_LOG(DDS_LC_DISCOVERY, "remove_deleted_participant_guid("PGUIDFMT" for_what=%x)\n", PGUID (*guid), for_what); ddsrt_mutex_lock (&deleted_participants_lock); if ((n = ddsrt_avl_lookup (&deleted_participants_treedef, &deleted_participants, guid)) != NULL) { @@ -380,7 +380,7 @@ int pp_allocate_entityid(nn_entityid_t *id, unsigned kind, struct participant *p } else { - DDS_ERROR("pp_allocate_entityid(%x:%x:%x:%x): all ids in use\n", PGUID(pp->e.guid)); + DDS_ERROR("pp_allocate_entityid("PGUIDFMT"): all ids in use\n", PGUID(pp->e.guid)); ret = Q_ERR_OUT_OF_IDS; } ddsrt_mutex_unlock (&pp->e.lock); @@ -431,12 +431,12 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis else { ddsrt_mutex_unlock (&gv.participant_set_lock); - DDS_ERROR("new_participant(%x:%x:%x:%x, %x) failed: max participants reached\n", PGUID (*ppguid), flags); + DDS_ERROR("new_participant("PGUIDFMT", %x) failed: max participants reached\n", PGUID (*ppguid), flags); return Q_ERR_OUT_OF_IDS; } } - DDS_LOG(DDS_LC_DISCOVERY, "new_participant(%x:%x:%x:%x, %x)\n", PGUID (*ppguid), flags); + DDS_LOG(DDS_LC_DISCOVERY, "new_participant("PGUIDFMT", %x)\n", PGUID (*ppguid), flags); pp = ddsrt_malloc (sizeof (*pp)); @@ -454,7 +454,7 @@ int new_participant_guid (const nn_guid_t *ppguid, unsigned flags, const nn_plis if (dds_get_log_mask() & DDS_LC_DISCOVERY) { - DDS_LOG(DDS_LC_DISCOVERY, "PARTICIPANT %x:%x:%x:%x QOS={", PGUID (pp->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "PARTICIPANT "PGUIDFMT" QOS={", PGUID (pp->e.guid)); nn_log_xqos(DDS_LC_DISCOVERY, &pp->plist->qos); DDS_LOG(DDS_LC_DISCOVERY, "}\n"); } @@ -692,7 +692,7 @@ static struct participant *ref_participant (struct participant *pp, const struct stguid = *guid_of_refing_entity; else memset (&stguid, 0, sizeof (stguid)); - DDS_LOG(DDS_LC_DISCOVERY, "ref_participant(%x:%x:%x:%x @ %p <- %x:%x:%x:%x @ %p) user %d builtin %d\n", + DDS_LOG(DDS_LC_DISCOVERY, "ref_participant("PGUIDFMT" @ %p <- "PGUIDFMT" @ %p) user %"PRId32" builtin %"PRId32"\n", PGUID (pp->e.guid), (void*)pp, PGUID (stguid), (void*)guid_of_refing_entity, pp->user_refc, pp->builtin_refc); ddsrt_mutex_unlock (&pp->refc_lock); return pp; @@ -733,7 +733,7 @@ static void unref_participant (struct participant *pp, const struct nn_guid *gui stguid = *guid_of_refing_entity; else memset (&stguid, 0, sizeof (stguid)); - DDS_LOG(DDS_LC_DISCOVERY, "unref_participant(%x:%x:%x:%x @ %p <- %x:%x:%x:%x @ %p) user %d builtin %d\n", + DDS_LOG(DDS_LC_DISCOVERY, "unref_participant("PGUIDFMT" @ %p <- "PGUIDFMT" @ %p) user %"PRId32" builtin %"PRId32"\n", PGUID (pp->e.guid), (void*)pp, PGUID (stguid), (void*)guid_of_refing_entity, pp->user_refc, pp->builtin_refc); if (pp->user_refc == 0 && (pp->bes != 0 || pp->prismtech_bes != 0) && !pp->builtins_deleted) @@ -845,7 +845,7 @@ static void unref_participant (struct participant *pp, const struct nn_guid *gui static void gc_delete_participant (struct gcreq *gcreq) { struct participant *pp = gcreq->arg; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_participant(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (pp->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_participant(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pp->e.guid)); gcreq_free (gcreq); unref_participant (pp, NULL); } @@ -1235,7 +1235,7 @@ static void rebuild_writer_addrset (struct writer *wr) wr->as = newas; unref_addrset (oldas); - DDS_LOG(DDS_LC_DISCOVERY, "rebuild_writer_addrset(%x:%x:%x:%x):", PGUID (wr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "rebuild_writer_addrset("PGUIDFMT"):", PGUID (wr->e.guid)); nn_log_addrset(DDS_LC_DISCOVERY, "", wr->as); DDS_LOG(DDS_LC_DISCOVERY, "\n"); } @@ -1461,14 +1461,14 @@ static void update_reader_init_acknack_count (const struct nn_guid *rd_guid, nn_ /* Update the initial acknack sequence number for the reader. See also reader_add_connection(). */ - DDS_LOG(DDS_LC_DISCOVERY, "update_reader_init_acknack_count (%x:%x:%x:%x, %d): ", PGUID (*rd_guid), count); + DDS_LOG(DDS_LC_DISCOVERY, "update_reader_init_acknack_count ("PGUIDFMT", %"PRId32"): ", PGUID (*rd_guid), count); if ((rd = ephash_lookup_reader_guid (rd_guid)) != NULL) { ddsrt_mutex_lock (&rd->e.lock); - DDS_LOG(DDS_LC_DISCOVERY, "%d -> ", rd->init_acknack_count); + DDS_LOG(DDS_LC_DISCOVERY, "%"PRId32" -> ", rd->init_acknack_count); if (count > rd->init_acknack_count) rd->init_acknack_count = count; - DDS_LOG(DDS_LC_DISCOVERY, "%d\n", count); + DDS_LOG(DDS_LC_DISCOVERY, "%"PRId32"\n", count); ddsrt_mutex_unlock (&rd->e.lock); } else @@ -1538,7 +1538,7 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) ddsrt_mutex_lock (&prd->e.lock); if (prd->deleting) { - DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x) - prd is being deleted\n", + DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - prd is being deleted\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); pretend_everything_acked = 1; } @@ -1566,14 +1566,14 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) m->seq = wr->seq; if (ddsrt_avl_lookup_ipath (&wr_readers_treedef, &wr->readers, &prd->e.guid, &path)) { - DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x) - already connected\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - already connected\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); ddsrt_mutex_unlock (&wr->e.lock); nn_lat_estim_fini (&m->hb_to_ack_latency); ddsrt_free (m); } else { - DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x) - ack seq %"PRId64"\n", PGUID (wr->e.guid), PGUID (prd->e.guid), m->seq); + DDS_LOG(DDS_LC_DISCOVERY, " writer_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - ack seq %"PRId64"\n", PGUID (wr->e.guid), PGUID (prd->e.guid), m->seq); ddsrt_avl_insert_ipath (&wr_readers_treedef, &wr->readers, m, &path); rebuild_writer_addrset (wr); wr->num_reliable_readers += m->is_reliable; @@ -1623,13 +1623,13 @@ static void writer_add_local_connection (struct writer *wr, struct reader *rd) ddsrt_mutex_lock (&wr->e.lock); if (ddsrt_avl_lookup_ipath (&wr_local_readers_treedef, &wr->local_readers, &rd->e.guid, &path)) { - DDS_LOG(DDS_LC_DISCOVERY, " writer_add_local_connection(wr %x:%x:%x:%x rd %x:%x:%x:%x) - already connected\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, " writer_add_local_connection(wr "PGUIDFMT" rd "PGUIDFMT") - already connected\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); ddsrt_mutex_unlock (&wr->e.lock); ddsrt_free (m); return; } - DDS_LOG(DDS_LC_DISCOVERY, " writer_add_local_connection(wr %x:%x:%x:%x rd %x:%x:%x:%x)", PGUID (wr->e.guid), PGUID (rd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, " writer_add_local_connection(wr "PGUIDFMT" rd "PGUIDFMT")", PGUID (wr->e.guid), PGUID (rd->e.guid)); m->rd_guid = rd->e.guid; ddsrt_avl_insert_ipath (&wr_local_readers_treedef, &wr->local_readers, m, &path); local_reader_ary_insert (&wr->rdary, rd); @@ -1684,19 +1684,19 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, writer will always see monotonically increasing sequence numbers from one particular reader. This is then used for the pwr_rd_match initialization */ - DDS_LOG(DDS_LC_DISCOVERY, " reader %x:%x:%x:%x init_acknack_count = %d\n", PGUID (rd->e.guid), rd->init_acknack_count); + DDS_LOG(DDS_LC_DISCOVERY, " reader "PGUIDFMT" init_acknack_count = %"PRId32"\n", PGUID (rd->e.guid), rd->init_acknack_count); *init_count = rd->init_acknack_count; if (ddsrt_avl_lookup_ipath (&rd_writers_treedef, &rd->writers, &pwr->e.guid, &path)) { - DDS_LOG(DDS_LC_DISCOVERY, " reader_add_connection(pwr %x:%x:%x:%x rd %x:%x:%x:%x) - already connected\n", + DDS_LOG(DDS_LC_DISCOVERY, " reader_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT") - already connected\n", PGUID (pwr->e.guid), PGUID (rd->e.guid)); ddsrt_mutex_unlock (&rd->e.lock); ddsrt_free (m); } else { - DDS_LOG(DDS_LC_DISCOVERY, " reader_add_connection(pwr %x:%x:%x:%x rd %x:%x:%x:%x)\n", + DDS_LOG(DDS_LC_DISCOVERY, " reader_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT")\n", PGUID (pwr->e.guid), PGUID (rd->e.guid)); ddsrt_avl_insert_ipath (&rd_writers_treedef, &rd->writers, m, &path); ddsrt_mutex_unlock (&rd->e.lock); @@ -1744,13 +1744,13 @@ static void reader_add_local_connection (struct reader *rd, struct writer *wr) if (ddsrt_avl_lookup_ipath (&rd_local_writers_treedef, &rd->local_writers, &wr->e.guid, &path)) { - DDS_LOG(DDS_LC_DISCOVERY, " reader_add_local_connection(wr %x:%x:%x:%x rd %x:%x:%x:%x) - already connected\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, " reader_add_local_connection(wr "PGUIDFMT" rd "PGUIDFMT") - already connected\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); ddsrt_mutex_unlock (&rd->e.lock); ddsrt_free (m); } else { - DDS_LOG(DDS_LC_DISCOVERY, " reader_add_local_connection(wr %x:%x:%x:%x rd %x:%x:%x:%x)\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, " reader_add_local_connection(wr "PGUIDFMT" rd "PGUIDFMT")\n", PGUID (wr->e.guid), PGUID (rd->e.guid)); ddsrt_avl_insert_ipath (&rd_local_writers_treedef, &rd->local_writers, m, &path); ddsrt_mutex_unlock (&rd->e.lock); @@ -1787,7 +1787,7 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader pwr->ddsi2direct_cbarg = rd->ddsi2direct_cbarg; } - DDS_LOG(DDS_LC_DISCOVERY, " proxy_writer_add_connection(pwr %x:%x:%x:%x rd %x:%x:%x:%x)", + DDS_LOG(DDS_LC_DISCOVERY, " proxy_writer_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT")", PGUID (pwr->e.guid), PGUID (rd->e.guid)); m->rd_guid = rd->e.guid; m->tcreate = now_mt (); @@ -1880,7 +1880,7 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader already_matched: assert (is_builtin_entityid (pwr->e.guid.entityid, pwr->c.vendor) ? (pwr->c.topic == NULL) : (pwr->c.topic != NULL)); - DDS_LOG(DDS_LC_DISCOVERY, " proxy_writer_add_connection(pwr %x:%x:%x:%x rd %x:%x:%x:%x) - already connected\n", + DDS_LOG(DDS_LC_DISCOVERY, " proxy_writer_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT") - already connected\n", PGUID (pwr->e.guid), PGUID (rd->e.guid)); ddsrt_mutex_unlock (&pwr->e.lock); ddsrt_free (m); @@ -1898,14 +1898,14 @@ static void proxy_reader_add_connection (struct proxy_reader *prd, struct writer prd->c.topic = ddsi_sertopic_ref (wr->topic); if (ddsrt_avl_lookup_ipath (&prd_writers_treedef, &prd->writers, &wr->e.guid, &path)) { - DDS_LOG(DDS_LC_DISCOVERY, " proxy_reader_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x) - already connected\n", + DDS_LOG(DDS_LC_DISCOVERY, " proxy_reader_add_connection(wr "PGUIDFMT" prd "PGUIDFMT") - already connected\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); ddsrt_mutex_unlock (&prd->e.lock); ddsrt_free (m); } else { - DDS_LOG(DDS_LC_DISCOVERY, " proxy_reader_add_connection(wr %x:%x:%x:%x prd %x:%x:%x:%x)\n", + DDS_LOG(DDS_LC_DISCOVERY, " proxy_reader_add_connection(wr "PGUIDFMT" prd "PGUIDFMT")\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); ddsrt_avl_insert_ipath (&prd_writers_treedef, &prd->writers, m, &path); ddsrt_mutex_unlock (&prd->e.lock); @@ -2259,7 +2259,7 @@ static void generic_do_match (struct entity_common *e, nn_mtime_t tnow) enum entity_kind mkind = generic_do_match_mkind(e->kind); if (!is_builtin_entityid (e->guid.entityid, NN_VENDORID_ECLIPSE)) { - DDS_LOG(DDS_LC_DISCOVERY, "match_%s_with_%ss(%s %x:%x:%x:%x) scanning all %ss\n", + DDS_LOG(DDS_LC_DISCOVERY, "match_%s_with_%ss(%s "PGUIDFMT") scanning all %ss\n", generic_do_match_kindstr_us (e->kind), generic_do_match_kindstr_us (mkind), generic_do_match_kindabbrev (e->kind), PGUID (e->guid), generic_do_match_kindstr(mkind)); @@ -2280,7 +2280,7 @@ static void generic_do_match (struct entity_common *e, nn_mtime_t tnow) /* Built-ins have fixed QoS */ nn_entityid_t tgt_ent = builtin_entityid_match (e->guid.entityid); enum entity_kind pkind = generic_do_match_isproxy (e) ? EK_PARTICIPANT : EK_PROXY_PARTICIPANT; - DDS_LOG(DDS_LC_DISCOVERY, "match_%s_with_%ss(%s %x:%x:%x:%x) scanning %sparticipants tgt=%x\n", + DDS_LOG(DDS_LC_DISCOVERY, "match_%s_with_%ss(%s "PGUIDFMT") scanning %sparticipants tgt=%"PRIx32"\n", generic_do_match_kindstr_us (e->kind), generic_do_match_kindstr_us (mkind), generic_do_match_kindabbrev (e->kind), PGUID (e->guid), generic_do_match_isproxy (e) ? "" : "proxy ", @@ -2311,7 +2311,7 @@ static void generic_do_local_match (struct entity_common *e, nn_mtime_t tnow) /* never a need for local matches on discovery endpoints */ return; mkind = generic_do_local_match_mkind(e->kind); - DDS_LOG(DDS_LC_DISCOVERY, "match_%s_with_%ss(%s %x:%x:%x:%x) scanning all %ss\n", + DDS_LOG(DDS_LC_DISCOVERY, "match_%s_with_%ss(%s "PGUIDFMT") scanning all %ss\n", generic_do_match_kindstr_us (e->kind), generic_do_match_kindstr_us (mkind), generic_do_match_kindabbrev (e->kind), PGUID (e->guid), generic_do_match_kindstr(mkind)); @@ -2378,7 +2378,7 @@ static void new_reader_writer_common (const struct nn_guid *guid, const struct d if (xqos->partition.n > 1) partition_suffix = "+"; } - DDS_LOG(DDS_LC_DISCOVERY, "new_%s(guid %x:%x:%x:%x, %s%s.%s/%s)\n", + DDS_LOG(DDS_LC_DISCOVERY, "new_%s(guid "PGUIDFMT", %s%s.%s/%s)\n", is_writer_entityid (guid->entityid) ? "writer" : "reader", PGUID (*guid), partition, partition_suffix, @@ -2607,7 +2607,7 @@ unsigned remove_acked_messages (struct writer *wr, struct whc_state *whcst, stru writer_clear_retransmitting (wr); if (wr->state == WRST_LINGERING && whcst->unacked_bytes == 0) { - DDS_LOG(DDS_LC_DISCOVERY, "remove_acked_messages: deleting lingering writer %x:%x:%x:%x\n", PGUID (wr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "remove_acked_messages: deleting lingering writer "PGUIDFMT"\n", PGUID (wr->e.guid)); delete_writer_nolinger_locked (wr); } return n; @@ -2646,7 +2646,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se assert (wr->xqos->aliased == 0); set_topic_type_name (wr->xqos, topic); - DDS_LOG(DDS_LC_DISCOVERY, "WRITER %x:%x:%x:%x QOS={", PGUID (wr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "WRITER "PGUIDFMT" QOS={", PGUID (wr->e.guid)); nn_log_xqos (DDS_LC_DISCOVERY, wr->xqos); DDS_LOG(DDS_LC_DISCOVERY, "}\n"); @@ -2738,7 +2738,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se wr->supports_ssm = 1; wr->ssm_as = new_addrset (); add_to_addrset (wr->ssm_as, &loc); - DDS_LOG(DDS_LC_DISCOVERY, "writer %x:%x:%x:%x: ssm=%d", PGUID (wr->e.guid), wr->supports_ssm); + DDS_LOG(DDS_LC_DISCOVERY, "writer "PGUIDFMT": ssm=%d", PGUID (wr->e.guid), wr->supports_ssm); nn_log_addrset (DDS_LC_DISCOVERY, "", wr->ssm_as); DDS_LOG(DDS_LC_DISCOVERY, "\n"); } @@ -2751,7 +2751,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se if (!is_builtin_entityid (wr->e.guid.entityid, ownvendorid)) { struct config_channel_listelem *channel = find_channel (wr->xqos->transport_priority); - DDS_LOG(DDS_LC_DISCOVERY, "writer %x:%x:%x:%x: transport priority %d => channel '%s' priority %d\n", + DDS_LOG(DDS_LC_DISCOVERY, "writer "PGUIDFMT": transport priority %d => channel '%s' priority %d\n", PGUID (wr->e.guid), wr->xqos->transport_priority.value, channel->name, channel->priority); wr->evq = channel->evq ? channel->evq : gv.xevents; } @@ -2779,7 +2779,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se if (wr->xqos->liveliness.kind != NN_AUTOMATIC_LIVELINESS_QOS || nn_from_ddsi_duration (wr->xqos->liveliness.lease_duration) != T_NEVER) { - DDS_LOG(DDS_LC_DISCOVERY, "writer %x:%x:%x:%x: incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n", PGUID (wr->e.guid), (int) wr->xqos->liveliness.kind, nn_from_ddsi_duration (wr->xqos->liveliness.lease_duration)); + DDS_LOG(DDS_LC_DISCOVERY, "writer "PGUIDFMT": incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n", PGUID (wr->e.guid), (int) wr->xqos->liveliness.kind, nn_from_ddsi_duration (wr->xqos->liveliness.lease_duration)); } wr->lease_duration = T_NEVER; /* FIXME */ @@ -2862,7 +2862,7 @@ dds_retcode_t new_writer (struct writer **wr_out, struct nn_guid *wrguid, const if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "new_writer - participant %x:%x:%x:%x not found\n", PGUID (*ppguid)); + DDS_LOG(DDS_LC_DISCOVERY, "new_writer - participant "PGUIDFMT" not found\n", PGUID (*ppguid)); return DDS_RETCODE_NOT_FOUND; } /* participant can't be freed while we're mucking around cos we are @@ -2900,7 +2900,7 @@ struct local_orphan_writer *new_local_orphan_writer (nn_entityid_t entityid, str static void gc_delete_writer (struct gcreq *gcreq) { struct writer *wr = gcreq->arg; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_writer(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (wr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_writer(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (wr->e.guid)); gcreq_free (gcreq); /* We now allow GC while blocked on a full WHC, but we still don't allow deleting a writer while blocked on it. The writer's state must be DELETING by the time we get here, and that means the transmit path is no longer blocked. It doesn't imply that the write thread is no longer in throttle_writer(), just that if it is, it will soon return from there. Therefore, block until it isn't throttling anymore. We can safely lock the writer, as we're on the separate GC thread. */ @@ -2959,7 +2959,7 @@ static void gc_delete_writer (struct gcreq *gcreq) static void gc_delete_writer_throttlewait (struct gcreq *gcreq) { struct writer *wr = gcreq->arg; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_writer_throttlewait(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (wr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_writer_throttlewait(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (wr->e.guid)); /* We now allow GC while blocked on a full WHC, but we still don't allow deleting a writer while blocked on it. The writer's state must be DELETING by the time we get here, and that means the transmit path is no longer blocked. It doesn't imply that the write thread is no longer in throttle_writer(), just that if it is, it will soon return from there. Therefore, block until it isn't throttling anymore. We can safely lock the writer, as we're on the separate GC thread. */ assert (wr->state == WRST_DELETING); ddsrt_mutex_lock (&wr->e.lock); @@ -2972,7 +2972,7 @@ static void gc_delete_writer_throttlewait (struct gcreq *gcreq) static void writer_set_state (struct writer *wr, enum writer_state newstate) { ASSERT_MUTEX_HELD (&wr->e.lock); - DDS_LOG(DDS_LC_DISCOVERY, "writer_set_state(%x:%x:%x:%x) state transition %d -> %d\n", PGUID (wr->e.guid), wr->state, newstate); + DDS_LOG(DDS_LC_DISCOVERY, "writer_set_state("PGUIDFMT") state transition %d -> %d\n", PGUID (wr->e.guid), wr->state, newstate); assert (newstate > wr->state); if (wr->state == WRST_OPERATIONAL) { @@ -2989,7 +2989,7 @@ static void writer_set_state (struct writer *wr, enum writer_state newstate) int delete_writer_nolinger_locked (struct writer *wr) { - DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid %x:%x:%x:%x) ...\n", PGUID (wr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (wr->e.guid)); ASSERT_MUTEX_HELD (&wr->e.lock); ddsi_plugin.builtintopic_write (&wr->e, now(), false); local_reader_ary_setinvalid (&wr->rdary); @@ -3011,10 +3011,10 @@ int delete_writer_nolinger (const struct nn_guid *guid) assert (is_writer_entityid (guid->entityid)); if ((wr = ephash_lookup_writer_guid (guid)) == NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid %x:%x:%x:%x) - unknown guid\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid "PGUIDFMT") - unknown guid\n", PGUID (*guid)); return Q_ERR_UNKNOWN_ENTITY; } - DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid %x:%x:%x:%x) ...\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (*guid)); ddsrt_mutex_lock (&wr->e.lock); delete_writer_nolinger_locked (wr); ddsrt_mutex_unlock (&wr->e.lock); @@ -3034,10 +3034,10 @@ int delete_writer (const struct nn_guid *guid) struct whc_state whcst; if ((wr = ephash_lookup_writer_guid (guid)) == NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid %x:%x:%x:%x) - unknown guid\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid "PGUIDFMT") - unknown guid\n", PGUID (*guid)); return Q_ERR_UNKNOWN_ENTITY; } - DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid %x:%x:%x:%x) ...\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid "PGUIDFMT") ...\n", PGUID (*guid)); ddsrt_mutex_lock (&wr->e.lock); /* If no unack'ed data, don't waste time or resources (expected to @@ -3047,7 +3047,7 @@ int delete_writer (const struct nn_guid *guid) whc_get_state(wr->whc, &whcst); if (whcst.unacked_bytes == 0) { - DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid %x:%x:%x:%x) - no unack'ed samples\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid "PGUIDFMT") - no unack'ed samples\n", PGUID (*guid)); delete_writer_nolinger_locked (wr); ddsrt_mutex_unlock (&wr->e.lock); } @@ -3059,7 +3059,7 @@ int delete_writer (const struct nn_guid *guid) ddsrt_mutex_unlock (&wr->e.lock); tsched = add_duration_to_mtime (now_mt (), config.writer_linger_duration); mtime_to_sec_usec (&tsec, &tusec, tsched); - DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid %x:%x:%x:%x) - unack'ed samples, will delete when ack'd or at t = %"PRId32".%06"PRId32"\n", + DDS_LOG(DDS_LC_DISCOVERY, "delete_writer(guid "PGUIDFMT") - unack'ed samples, will delete when ack'd or at t = %"PRId32".%06"PRId32"\n", PGUID (*guid), tsec, tusec); qxev_delete_writer (tsched, &wr->e.guid); } @@ -3078,7 +3078,7 @@ void writer_exit_startup_mode (struct writer *wr) cnt += remove_acked_messages (wr, &whcst, &deferred_free_list); cnt += whc_downgrade_to_volatile (wr->whc, &whcst); writer_clear_retransmitting (wr); - DDS_LOG(DDS_LC_DISCOVERY, " %x:%x:%x:%x: dropped %u samples\n", PGUID(wr->e.guid), cnt); + DDS_LOG(DDS_LC_DISCOVERY, " "PGUIDFMT": dropped %u samples\n", PGUID(wr->e.guid), cnt); } ddsrt_mutex_unlock (&wr->e.lock); whc_free_deferred_free_list (wr->whc, deferred_free_list); @@ -3237,7 +3237,7 @@ static dds_retcode_t new_reader_guid if (dds_get_log_mask() & DDS_LC_DISCOVERY) { - DDS_LOG(DDS_LC_DISCOVERY, "READER %x:%x:%x:%x QOS={", PGUID (rd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "READER "PGUIDFMT" QOS={", PGUID (rd->e.guid)); nn_log_xqos (DDS_LC_DISCOVERY, rd->xqos); DDS_LOG(DDS_LC_DISCOVERY, "}\n"); } @@ -3268,7 +3268,7 @@ static dds_retcode_t new_reader_guid if (rd->xqos->liveliness.kind != NN_AUTOMATIC_LIVELINESS_QOS || nn_from_ddsi_duration (rd->xqos->liveliness.lease_duration) != T_NEVER) { - DDS_LOG(DDS_LC_DISCOVERY, "reader %x:%x:%x:%x: incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n", PGUID (rd->e.guid), (int) rd->xqos->liveliness.kind, nn_from_ddsi_duration (rd->xqos->liveliness.lease_duration)); + DDS_LOG(DDS_LC_DISCOVERY, "reader "PGUIDFMT": incorrectly treating it as of automatic liveliness kind with lease duration = inf (%d, %"PRId64")\n", PGUID (rd->e.guid), (int) rd->xqos->liveliness.kind, nn_from_ddsi_duration (rd->xqos->liveliness.lease_duration)); } #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS @@ -3302,7 +3302,7 @@ static dds_retcode_t new_reader_guid addrset_forall (rd->as, join_mcast_helper, gv.data_conn_mc); if (dds_get_log_mask() & DDS_LC_DISCOVERY) { - DDS_LOG(DDS_LC_DISCOVERY, "READER %x:%x:%x:%x locators={", PGUID (rd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "READER "PGUIDFMT" locators={", PGUID (rd->e.guid)); nn_log_addrset(DDS_LC_DISCOVERY, "", rd->as); DDS_LOG(DDS_LC_DISCOVERY, "}\n"); } @@ -3320,7 +3320,7 @@ static dds_retcode_t new_reader_guid } #ifdef DDSI_INCLUDE_SSM if (rd->favours_ssm) - DDS_LOG(DDS_LC_DISCOVERY, "READER %x:%x:%x:%x ssm=%d\n", PGUID (rd->e.guid), rd->favours_ssm); + DDS_LOG(DDS_LC_DISCOVERY, "READER "PGUIDFMT" ssm=%d\n", PGUID (rd->e.guid), rd->favours_ssm); #endif #endif @@ -3355,7 +3355,7 @@ dds_retcode_t new_reader if ((pp = ephash_lookup_participant_guid (ppguid)) == NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "new_reader - participant %x:%x:%x:%x not found\n", PGUID (*ppguid)); + DDS_LOG(DDS_LC_DISCOVERY, "new_reader - participant "PGUIDFMT" not found\n", PGUID (*ppguid)); return DDS_RETCODE_NOT_FOUND; } rdguid->prefix = pp->e.guid.prefix; @@ -3368,7 +3368,7 @@ static void gc_delete_reader (struct gcreq *gcreq) { /* see gc_delete_writer for comments */ struct reader *rd = gcreq->arg; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_reader(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (rd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_reader(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (rd->e.guid)); gcreq_free (gcreq); while (!ddsrt_avl_is_empty (&rd->writers)) @@ -3417,10 +3417,10 @@ int delete_reader (const struct nn_guid *guid) assert (!is_writer_entityid (guid->entityid)); if ((rd = ephash_lookup_reader_guid (guid)) == NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid %x:%x:%x:%x) - unknown guid\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid "PGUIDFMT") - unknown guid\n", PGUID (*guid)); return Q_ERR_UNKNOWN_ENTITY; } - DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid %x:%x:%x:%x) ...\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_reader_guid(guid "PGUIDFMT") ...\n", PGUID (*guid)); ddsi_plugin.builtintopic_write (&rd->e, now(), false); ephash_remove_reader_guid (rd); gcreq_reader (rd); @@ -3754,7 +3754,7 @@ static void unref_proxy_participant (struct proxy_participant *proxypp, struct p { assert (proxypp->endpoints == NULL); ddsrt_mutex_unlock (&proxypp->e.lock); - DDS_LOG(DDS_LC_DISCOVERY, "unref_proxy_participant(%x:%x:%x:%x): refc=0, freeing\n", PGUID (proxypp->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "unref_proxy_participant("PGUIDFMT"): refc=0, freeing\n", PGUID (proxypp->e.guid)); unref_addrset (proxypp->as_default); @@ -3771,7 +3771,7 @@ static void unref_proxy_participant (struct proxy_participant *proxypp, struct p { assert (refc == 1); ddsrt_mutex_unlock (&proxypp->e.lock); - DDS_LOG(DDS_LC_DISCOVERY, "unref_proxy_participant(%x:%x:%x:%x): refc=%u, no endpoints, implicitly created, deleting\n", PGUID (proxypp->e.guid), (unsigned) refc); + DDS_LOG(DDS_LC_DISCOVERY, "unref_proxy_participant("PGUIDFMT"): refc=%u, no endpoints, implicitly created, deleting\n", PGUID (proxypp->e.guid), (unsigned) refc); delete_proxy_participant_by_guid(&proxypp->e.guid, tnow, 1); /* Deletion is still (and has to be) asynchronous. A parallel endpoint creation may or may not succeed, and if it succeeds it will be deleted along with the proxy participant. So "your @@ -3780,14 +3780,14 @@ static void unref_proxy_participant (struct proxy_participant *proxypp, struct p else { ddsrt_mutex_unlock (&proxypp->e.lock); - DDS_LOG(DDS_LC_DISCOVERY, "unref_proxy_participant(%x:%x:%x:%x): refc=%u\n", PGUID (proxypp->e.guid), (unsigned) refc); + DDS_LOG(DDS_LC_DISCOVERY, "unref_proxy_participant("PGUIDFMT"): refc=%u\n", PGUID (proxypp->e.guid), (unsigned) refc); } } static void gc_delete_proxy_participant (struct gcreq *gcreq) { struct proxy_participant *proxypp = gcreq->arg; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_participant(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (proxypp->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_participant(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (proxypp->e.guid)); gcreq_free (gcreq); unref_proxy_participant (proxypp, NULL); } @@ -3820,7 +3820,7 @@ static void delete_or_detach_dependent_pp (struct proxy_participant *p, struct p { nn_etime_t texp = add_duration_to_etime (now_et(), config.ds_grace_period); /* Clear dependency (but don't touch entity id, which must be 0x1c1) and set the lease ticking */ - DDS_LOG(DDS_LC_DISCOVERY, "%x:%x:%x:%x detach-from-DS %x:%x:%x:%x\n", PGUID(p->e.guid), PGUID(proxypp->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, PGUIDFMT" detach-from-DS "PGUIDFMT"\n", PGUID(p->e.guid), PGUID(proxypp->e.guid)); memset (&p->privileged_pp_guid.prefix, 0, sizeof (p->privileged_pp_guid.prefix)); lease_set_expiry (ddsrt_atomic_ldvoidp (&p->lease), texp); ddsrt_mutex_unlock (&p->e.lock); @@ -3833,7 +3833,7 @@ static void delete_ppt (struct proxy_participant * proxypp, nn_wctime_t timestam int ret; /* if any proxy participants depend on this participant, delete them */ - DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt(%x:%x:%x:%x) - deleting dependent proxy participants\n", PGUID (proxypp->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt("PGUIDFMT") - deleting dependent proxy participants\n", PGUID (proxypp->e.guid)); { struct ephash_enum_proxy_participant est; struct proxy_participant *p; @@ -3850,11 +3850,11 @@ static void delete_ppt (struct proxy_participant * proxypp, nn_wctime_t timestam if (isimplicit) proxypp->lease_expired = 1; - DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt(%x:%x:%x:%x) - deleting groups\n", PGUID (proxypp->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt("PGUIDFMT") - deleting groups\n", PGUID (proxypp->e.guid)); while (!ddsrt_avl_is_empty (&proxypp->groups)) delete_proxy_group_locked (ddsrt_avl_root (&proxypp_groups_treedef, &proxypp->groups), timestamp, isimplicit); - DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt(%x:%x:%x:%x) - deleting endpoints\n", PGUID (proxypp->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_ppt("PGUIDFMT") - deleting endpoints\n", PGUID (proxypp->e.guid)); c = proxypp->endpoints; while (c) { @@ -3915,7 +3915,7 @@ int delete_proxy_participant_by_guid (const struct nn_guid * guid, nn_wctime_t t { struct proxy_participant * ppt; - DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_participant_by_guid(%x:%x:%x:%x) ", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_participant_by_guid("PGUIDFMT") ", PGUID (*guid)); ddsrt_mutex_lock (&gv.lock); ppt = ephash_lookup_proxy_participant_guid (guid); if (ppt == NULL) @@ -3959,7 +3959,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct ppguid.entityid.u = NN_ENTITYID_PARTICIPANT; if ((proxypp = ephash_lookup_proxy_participant_guid (&ppguid)) == NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "new_proxy_group(%x:%x:%x:%x) - unknown participant\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "new_proxy_group("PGUIDFMT") - unknown participant\n", PGUID (*guid)); return 0; } else @@ -3976,7 +3976,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct is_sub = 1; break; default: - DDS_WARNING("new_proxy_group: unrecognised entityid: %x\n", guid->entityid.u); + DDS_WARNING("new_proxy_group: unrecognised entityid: %"PRIx32"\n", guid->entityid.u); return Q_ERR_INVALID_DATA; } ddsrt_mutex_lock (&proxypp->e.lock); @@ -3991,7 +3991,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct else { /* Always have a guid, may not have a gid */ - DDS_LOG(DDS_LC_DISCOVERY, "new_proxy_group(%x:%x:%x:%x): new\n", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "new_proxy_group("PGUIDFMT"): new\n", PGUID (*guid)); pgroup = ddsrt_malloc (sizeof (*pgroup)); pgroup->guid = *guid; pgroup->proxypp = proxypp; @@ -4002,7 +4002,7 @@ int new_proxy_group (const struct nn_guid *guid, const char *name, const struct if (name) { assert (xqos != NULL); - DDS_LOG(DDS_LC_DISCOVERY, "new_proxy_group(%x:%x:%x:%x): setting name (%s) and qos\n", PGUID (*guid), name); + DDS_LOG(DDS_LC_DISCOVERY, "new_proxy_group("PGUIDFMT"): setting name (%s) and qos\n", PGUID (*guid), name); pgroup->name = ddsrt_strdup (name); pgroup->xqos = nn_xqos_dup (xqos); nn_xqos_mergein_missing (pgroup->xqos, is_sub ? &gv.default_xqos_sub : &gv.default_xqos_pub); @@ -4020,7 +4020,7 @@ static void delete_proxy_group_locked (struct proxy_group *pgroup, nn_wctime_t t (void)timestamp; (void)isimplicit; assert ((pgroup->xqos != NULL) == (pgroup->name != NULL)); - DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_group_locked %x:%x:%x:%x\n", PGUID (pgroup->guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_group_locked "PGUIDFMT"\n", PGUID (pgroup->guid)); ddsrt_avl_delete (&proxypp_groups_treedef, &proxypp->groups, pgroup); /* Publish corresponding built-in topic only if it is not a place holder: in that case we haven't announced its presence and @@ -4105,7 +4105,7 @@ int new_proxy_writer (const struct nn_guid *ppguid, const struct nn_guid *guid, if ((proxypp = ephash_lookup_proxy_participant_guid (ppguid)) == NULL) { - DDS_WARNING("new_proxy_writer(%x:%x:%x:%x): proxy participant unknown\n", PGUID (*guid)); + DDS_WARNING("new_proxy_writer("PGUIDFMT"): proxy participant unknown\n", PGUID (*guid)); return Q_ERR_UNKNOWN_ENTITY; } @@ -4277,7 +4277,7 @@ void update_proxy_reader (struct proxy_reader * prd, struct addrset * as) static void gc_delete_proxy_writer (struct gcreq *gcreq) { struct proxy_writer *pwr = gcreq->arg; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (pwr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pwr->e.guid)); gcreq_free (gcreq); while (!ddsrt_avl_is_empty (&pwr->readers)) @@ -4299,7 +4299,7 @@ int delete_proxy_writer (const struct nn_guid *guid, nn_wctime_t timestamp, int { struct proxy_writer *pwr; (void)isimplicit; - DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_writer (%x:%x:%x:%x) ", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_writer ("PGUIDFMT") ", PGUID (*guid)); ddsrt_mutex_lock (&gv.lock); if ((pwr = ephash_lookup_proxy_writer_guid (guid)) == NULL) { @@ -4337,7 +4337,7 @@ int new_proxy_reader (const struct nn_guid *ppguid, const struct nn_guid *guid, if ((proxypp = ephash_lookup_proxy_participant_guid (ppguid)) == NULL) { - DDS_WARNING("new_proxy_reader(%x:%x:%x:%x): proxy participant unknown\n", PGUID (*guid)); + DDS_WARNING("new_proxy_reader("PGUIDFMT"): proxy participant unknown\n", PGUID (*guid)); return Q_ERR_UNKNOWN_ENTITY; } @@ -4416,7 +4416,7 @@ static void proxy_reader_set_delete_and_ack_all_messages (struct proxy_reader *p static void gc_delete_proxy_reader (struct gcreq *gcreq) { struct proxy_reader *prd = gcreq->arg; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_reader(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (prd->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_reader(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (prd->e.guid)); gcreq_free (gcreq); while (!ddsrt_avl_is_empty (&prd->writers)) @@ -4435,7 +4435,7 @@ int delete_proxy_reader (const struct nn_guid *guid, nn_wctime_t timestamp, int { struct proxy_reader *prd; (void)isimplicit; - DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_reader (%x:%x:%x:%x) ", PGUID (*guid)); + DDS_LOG(DDS_LC_DISCOVERY, "delete_proxy_reader ("PGUIDFMT") ", PGUID (*guid)); ddsrt_mutex_lock (&gv.lock); if ((prd = ephash_lookup_proxy_reader_guid (guid)) == NULL) { @@ -4496,7 +4496,7 @@ static void gc_delete_proxy_writer_dqueue_bubble_cb (struct gcreq *gcreq) { /* delete proxy_writer, phase 3 */ struct proxy_writer *pwr = gcreq->arg; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer_dqueue_bubble(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (pwr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer_dqueue_bubble(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pwr->e.guid)); gcreq_requeue (gcreq, gc_delete_proxy_writer); } @@ -4505,7 +4505,7 @@ static void gc_delete_proxy_writer_dqueue (struct gcreq *gcreq) /* delete proxy_writer, phase 2 */ struct proxy_writer *pwr = gcreq->arg; struct nn_dqueue *dqueue = pwr->dqueue; - DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer_dqueue(%p, %x:%x:%x:%x)\n", (void *) gcreq, PGUID (pwr->e.guid)); + DDS_LOG(DDS_LC_DISCOVERY, "gc_delete_proxy_writer_dqueue(%p, "PGUIDFMT")\n", (void *) gcreq, PGUID (pwr->e.guid)); nn_dqueue_enqueue_callback (dqueue, (void (*) (void *)) gc_delete_proxy_writer_dqueue_bubble_cb, gcreq); } diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index ee25e6c..c6e4a8f 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -647,7 +647,7 @@ int joinleave_spdp_defmcip (int dojoin) unref_addrset (as); if (arg.errcount) { - DDS_ERROR("rtps_init: failed to join multicast groups for domain %d participant %d\n", config.domainId.value, config.participantIndex); + DDS_ERROR("rtps_init: failed to join multicast groups for domain %"PRId32" participant %d\n", config.domainId.value, config.participantIndex); return -1; } return 0; @@ -679,7 +679,7 @@ int create_multicast_sockets(void) gv.disc_conn_mc = disc; gv.data_conn_mc = data; - DDS_TRACE("Multicast Ports: discovery %d data %d \n", + DDS_TRACE("Multicast Ports: discovery %"PRIu32" data %"PRIu32" \n", ddsi_conn_port (gv.disc_conn_mc), ddsi_conn_port (gv.data_conn_mc)); return 1; @@ -1060,7 +1060,7 @@ int rtps_init (void) { if (make_uc_sockets (&port_disc_uc, &port_data_uc, config.participantIndex) < 0) { - DDS_ERROR("rtps_init: failed to create unicast sockets for domain %d participant %d\n", config.domainId.value, config.participantIndex); + DDS_ERROR("rtps_init: failed to create unicast sockets for domain %"PRId32" participant %d\n", config.domainId.value, config.participantIndex); goto err_unicast_sockets; } } @@ -1078,13 +1078,13 @@ int rtps_init (void) continue; else /* Oops! */ { - DDS_ERROR("rtps_init: failed to create unicast sockets for domain %d participant %d\n", config.domainId.value, ppid); + DDS_ERROR("rtps_init: failed to create unicast sockets for domain %"PRId32" participant %d\n", config.domainId.value, ppid); goto err_unicast_sockets; } } if (ppid > config.maxAutoParticipantIndex) { - DDS_ERROR("rtps_init: failed to find a free participant index for domain %d\n", config.domainId.value); + DDS_ERROR("rtps_init: failed to find a free participant index for domain %"PRId32"\n", config.domainId.value); goto err_unicast_sockets; } config.participantIndex = ppid; @@ -1093,9 +1093,9 @@ int rtps_init (void) { assert(0); } - DDS_LOG(DDS_LC_CONFIG, "rtps_init: uc ports: disc %u data %u\n", port_disc_uc, port_data_uc); + DDS_LOG(DDS_LC_CONFIG, "rtps_init: uc ports: disc %"PRIu32" data %"PRIu32"\n", port_disc_uc, port_data_uc); } - DDS_LOG(DDS_LC_CONFIG, "rtps_init: domainid %d participantid %d\n", config.domainId.value, config.participantIndex); + DDS_LOG(DDS_LC_CONFIG, "rtps_init: domainid %"PRId32" participantid %d\n", config.domainId.value, config.participantIndex); if (config.pcap_file && *config.pcap_file) { @@ -1115,7 +1115,7 @@ int rtps_init (void) if (gv.m_factory->m_connless) { if (!(config.many_sockets_mode == MSM_NO_UNICAST && config.allowMulticast)) - DDS_TRACE("Unicast Ports: discovery %d data %d\n", ddsi_conn_port (gv.disc_conn_uc), ddsi_conn_port (gv.data_conn_uc)); + DDS_TRACE("Unicast Ports: discovery %"PRIu32" data %"PRIu32"\n", ddsi_conn_port (gv.disc_conn_uc), ddsi_conn_port (gv.data_conn_uc)); if (config.allowMulticast) { diff --git a/src/core/ddsi/src/q_lease.c b/src/core/ddsi/src/q_lease.c index 22dc1f4..4ec8892 100644 --- a/src/core/ddsi/src/q_lease.c +++ b/src/core/ddsi/src/q_lease.c @@ -108,7 +108,7 @@ struct lease *lease_new (nn_etime_t texpire, int64_t tdur, struct entity_common struct lease *l; if ((l = ddsrt_malloc (sizeof (*l))) == NULL) return NULL; - DDS_TRACE("lease_new(tdur %"PRId64" guid %x:%x:%x:%x) @ %p\n", tdur, PGUID (e->guid), (void *) l); + DDS_TRACE("lease_new(tdur %"PRId64" guid "PGUIDFMT") @ %p\n", tdur, PGUID (e->guid), (void *) l); l->tdur = tdur; l->tend = texpire; l->tsched.v = TSCHED_NOT_ON_HEAP; @@ -118,7 +118,7 @@ struct lease *lease_new (nn_etime_t texpire, int64_t tdur, struct entity_common void lease_register (struct lease *l) { - DDS_TRACE("lease_register(l %p guid %x:%x:%x:%x)\n", (void *) l, PGUID (l->entity->guid)); + DDS_TRACE("lease_register(l %p guid "PGUIDFMT")\n", (void *) l, PGUID (l->entity->guid)); ddsrt_mutex_lock (&gv.leaseheap_lock); lock_lease (l); assert (l->tsched.v == TSCHED_NOT_ON_HEAP); @@ -136,7 +136,7 @@ void lease_register (struct lease *l) void lease_free (struct lease *l) { - DDS_TRACE("lease_free(l %p guid %x:%x:%x:%x)\n", (void *) l, PGUID (l->entity->guid)); + DDS_TRACE("lease_free(l %p guid "PGUIDFMT")\n", (void *) l, PGUID (l->entity->guid)); ddsrt_mutex_lock (&gv.leaseheap_lock); if (l->tsched.v != TSCHED_NOT_ON_HEAP) ddsrt_fibheap_delete (&lease_fhdef, &gv.leaseheap, l); @@ -167,9 +167,9 @@ void lease_renew (struct lease *l, nn_etime_t tnowE) int32_t tsec, tusec; DDS_TRACE(" L("); if (l->entity->guid.entityid.u == NN_ENTITYID_PARTICIPANT) - DDS_TRACE(":%x", l->entity->guid.entityid.u); + DDS_TRACE(":%"PRIx32, l->entity->guid.entityid.u); else - DDS_TRACE("%x:%x:%x:%x", PGUID (l->entity->guid)); + DDS_TRACE(""PGUIDFMT"", PGUID (l->entity->guid)); etime_to_sec_usec (&tsec, &tusec, tend_new); DDS_TRACE(" %"PRId32".%06"PRId32")", tsec, tusec); } @@ -233,7 +233,7 @@ int64_t check_and_handle_lease_expiration (nn_etime_t tnowE) continue; } - DDS_LOG(DDS_LC_DISCOVERY, "lease expired: l %p guid %x:%x:%x:%x tend %"PRId64" < now %"PRId64"\n", (void *) l, PGUID (g), l->tend.v, tnowE.v); + DDS_LOG(DDS_LC_DISCOVERY, "lease expired: l %p guid "PGUIDFMT" tend %"PRId64" < now %"PRId64"\n", (void *) l, PGUID (g), l->tend.v, tnowE.v); /* If the proxy participant is relying on another participant for writing its discovery data (on the privileged participant, @@ -266,7 +266,7 @@ int64_t check_and_handle_lease_expiration (nn_etime_t tnowE) if ((proxypp = ephash_lookup_proxy_participant_guid (&g)) != NULL && ephash_lookup_proxy_participant_guid (&proxypp->privileged_pp_guid) != NULL) { - DDS_LOG(DDS_LC_DISCOVERY, "but postponing because privileged pp %x:%x:%x:%x is still live\n", + DDS_LOG(DDS_LC_DISCOVERY, "but postponing because privileged pp "PGUIDFMT" is still live\n", PGUID (proxypp->privileged_pp_guid)); l->tsched = l->tend = add_duration_to_etime (tnowE, 200 * T_MILLISECOND); unlock_lease (l); @@ -350,7 +350,7 @@ void handle_PMD (UNUSED_ARG (const struct receiver_state *rst), nn_wctime_t time nn_guid_prefix_t p = nn_ntoh_guid_prefix (pmd->participantGuidPrefix); unsigned kind = ntohl (pmd->kind); unsigned length = bswap ? bswap4u (pmd->length) : pmd->length; - DDS_TRACE(" pp %x:%x:%x kind %u data %u", p.u[0], p.u[1], p.u[2], kind, length); + DDS_TRACE(" pp %"PRIx32":%"PRIx32":%"PRIx32" kind %u data %u", p.u[0], p.u[1], p.u[2], kind, length); if (len - sizeof (struct CDRHeader) - offsetof (ParticipantMessageData_t, value) < length) debug_print_rawdata (" SHORT2", pmd->value, len - sizeof (struct CDRHeader) - offsetof (ParticipantMessageData_t, value)); else diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index 6e8cbef..3f5ac27 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -123,13 +123,13 @@ static int set_rcvbuf (ddsrt_socket_t socket) { /* NN_ERROR does more than just DDS_ERROR(), hence the duplication */ if (config.socket_min_rcvbuf_size.isdefault) - DDS_LOG(DDS_LC_CONFIG, "failed to increase socket receive buffer size to %u bytes, continuing with %u bytes\n", socket_min_rcvbuf_size, ReceiveBufferSize); + DDS_LOG(DDS_LC_CONFIG, "failed to increase socket receive buffer size to %"PRIu32" bytes, continuing with %"PRIu32" bytes\n", socket_min_rcvbuf_size, ReceiveBufferSize); else - DDS_ERROR("failed to increase socket receive buffer size to %u bytes, continuing with %u bytes\n", socket_min_rcvbuf_size, ReceiveBufferSize); + DDS_ERROR("failed to increase socket receive buffer size to %"PRIu32" bytes, continuing with %"PRIu32" bytes\n", socket_min_rcvbuf_size, ReceiveBufferSize); } else { - DDS_LOG(DDS_LC_CONFIG, "socket receive buffer size set to %u bytes\n", ReceiveBufferSize); + DDS_LOG(DDS_LC_CONFIG, "socket receive buffer size set to %"PRIu32" bytes\n", ReceiveBufferSize); } } return 0; diff --git a/src/core/ddsi/src/q_plist.c b/src/core/ddsi/src/q_plist.c index c02a63d..a83f9f9 100644 --- a/src/core/ddsi/src/q_plist.c +++ b/src/core/ddsi/src/q_plist.c @@ -257,7 +257,7 @@ static int alias_stringseq (nn_stringseq_t *strseq, const struct dd *dd) seq += sizeof (uint32_t); if (strseq->n >= UINT_MAX / sizeof(*strs)) { - DDS_TRACE("plist/alias_stringseq: length %u out of range\n", strseq->n); + DDS_TRACE("plist/alias_stringseq: length %"PRIu32" out of range\n", strseq->n); return Q_ERR_INVALID; } else if (strseq->n == 0) @@ -1185,7 +1185,7 @@ static int valid_participant_guid (const nn_guid_t *g, UNUSED_ARG (const struct return 0; else { - DDS_TRACE("plist/valid_participant_guid: prefix is 0 but entityid is not (%u)\n", g->entityid.u); + DDS_TRACE("plist/valid_participant_guid: prefix is 0 but entityid is not (%"PRIu32")\n", g->entityid.u); return Q_ERR_INVALID; } } @@ -1195,7 +1195,7 @@ static int valid_participant_guid (const nn_guid_t *g, UNUSED_ARG (const struct } else { - DDS_TRACE("plist/valid_participant_guid: entityid not a participant entityid (%u)\n", g->entityid.u); + DDS_TRACE("plist/valid_participant_guid: entityid not a participant entityid (%"PRIu32")\n", g->entityid.u); return Q_ERR_INVALID; } } @@ -1209,7 +1209,7 @@ static int valid_group_guid (const nn_guid_t *g, UNUSED_ARG (const struct dd *dd return 0; else { - DDS_TRACE("plist/valid_group_guid: prefix is 0 but entityid is not (%u)\n", g->entityid.u); + DDS_TRACE("plist/valid_group_guid: prefix is 0 but entityid is not (%"PRIu32")\n", g->entityid.u); return Q_ERR_INVALID; } } @@ -1234,7 +1234,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) return 0; else { - DDS_TRACE("plist/valid_endpoint_guid: prefix is 0 but entityid is not (%x)\n", g->entityid.u); + DDS_TRACE("plist/valid_endpoint_guid: prefix is 0 but entityid is not (%"PRIx32")\n", g->entityid.u); return Q_ERR_INVALID; } } @@ -1253,7 +1253,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) return 0; else { - DDS_TRACE("plist/valid_endpoint_guid[src=USER,proto=%u.%u]: invalid kind (%x)\n", + DDS_TRACE("plist/valid_endpoint_guid[src=USER,proto=%u.%u]: invalid kind (%"PRIx32")\n", dd->protocol_version.major, dd->protocol_version.minor, g->entityid.u & NN_ENTITYID_KIND_MASK); return Q_ERR_INVALID; @@ -1278,7 +1278,7 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) return 0; else { - DDS_TRACE("plist/valid_endpoint_guid[src=BUILTIN,proto=%u.%u]: invalid entityid (%x)\n", + DDS_TRACE("plist/valid_endpoint_guid[src=BUILTIN,proto=%u.%u]: invalid entityid (%"PRIx32")\n", dd->protocol_version.major, dd->protocol_version.minor, g->entityid.u); return Q_ERR_INVALID; } @@ -1302,14 +1302,14 @@ static int valid_endpoint_guid (const nn_guid_t *g, const struct dd *dd) return 0; else { - DDS_TRACE("plist/valid_endpoint_guid[src=VENDOR,proto=%u.%u]: unexpected entityid (%x)\n", + DDS_TRACE("plist/valid_endpoint_guid[src=VENDOR,proto=%u.%u]: unexpected entityid (%"PRIx32")\n", dd->protocol_version.major, dd->protocol_version.minor, g->entityid.u); return 0; } } } default: - DDS_TRACE("plist/valid_endpoint_guid: invalid source (%x)\n", g->entityid.u); + DDS_TRACE("plist/valid_endpoint_guid: invalid source (%"PRIx32")\n", g->entityid.u); return Q_ERR_INVALID; } } @@ -1329,7 +1329,7 @@ static int do_guid (nn_guid_t *dst, uint64_t *present, uint64_t fl, int (*valid) that has long since changed (even if I don't know exactly when) */ if (fl == PP_PARTICIPANT_GUID && vendor_is_twinoaks (dd->vendorid) && dst->entityid.u == 0 && ! NN_STRICT_P) { - DDS_LOG(DDS_LC_DISCOVERY, "plist(vendor %u.%u): rewriting invalid participant guid %x:%x:%x:%x\n", + DDS_LOG(DDS_LC_DISCOVERY, "plist(vendor %u.%u): rewriting invalid participant guid "PGUIDFMT, dd->vendorid.id[0], dd->vendorid.id[1], PGUID (*dst)); dst->entityid.u = NN_ENTITYID_PARTICIPANT; } @@ -2122,9 +2122,9 @@ static int init_one_parameter dest->aliased |= PP_PRISMTECH_EOTINFO; if (dds_get_log_mask() & DDS_LC_PLIST) { - DDS_LOG(DDS_LC_PLIST, "eotinfo: txn %u {", q->transactionId); + DDS_LOG(DDS_LC_PLIST, "eotinfo: txn %"PRIu32" {", q->transactionId); for (i = 0; i < q->n; i++) - DDS_LOG(DDS_LC_PLIST, " %x:%u", q->tids[i].writer_entityid.u, q->tids[i].transactionId); + DDS_LOG(DDS_LC_PLIST, " %"PRIx32":%"PRIu32, q->tids[i].writer_entityid.u, q->tids[i].transactionId); DDS_LOG(DDS_LC_PLIST, " }\n"); } return 0; @@ -3421,12 +3421,12 @@ void nn_log_xqos (uint32_t cat, const nn_xqos_t *xqos) DDS_LOG(cat, "}"); }); DO (GROUP_DATA, { - LOGB1 ("group_data=%u<", xqos->group_data.length); + LOGB1 ("group_data=%"PRIu32"<", xqos->group_data.length); log_octetseq (cat, xqos->group_data.length, xqos->group_data.value); DDS_LOG(cat, ">"); }); DO (TOPIC_DATA, { - LOGB1 ("topic_data=%u<", xqos->topic_data.length); + LOGB1 ("topic_data=%"PRIu32"<", xqos->topic_data.length); log_octetseq (cat, xqos->topic_data.length, xqos->topic_data.value); DDS_LOG(cat, ">"); }); @@ -3434,25 +3434,25 @@ void nn_log_xqos (uint32_t cat, const nn_xqos_t *xqos) DO (DURABILITY_SERVICE, { LOGB0 ("durability_service="); DDS_LOG(cat, FMT_DUR, PRINTARG_DUR (xqos->durability_service.service_cleanup_delay)); - DDS_LOG(cat, ":{%d:%d}", xqos->durability_service.history.kind, xqos->durability_service.history.depth); - DDS_LOG(cat, ":{%d:%d:%d}", xqos->durability_service.resource_limits.max_samples, xqos->durability_service.resource_limits.max_instances, xqos->durability_service.resource_limits.max_samples_per_instance); + DDS_LOG(cat, ":{%u:%"PRId32"}", xqos->durability_service.history.kind, xqos->durability_service.history.depth); + DDS_LOG(cat, ":{%"PRId32":%"PRId32":%"PRId32"}", xqos->durability_service.resource_limits.max_samples, xqos->durability_service.resource_limits.max_instances, xqos->durability_service.resource_limits.max_samples_per_instance); }); DO (DEADLINE, { LOGB1 ("deadline="FMT_DUR, PRINTARG_DUR (xqos->deadline.deadline)); }); DO (LATENCY_BUDGET, { LOGB1 ("latency_budget="FMT_DUR, PRINTARG_DUR (xqos->latency_budget.duration)); }); DO (LIVELINESS, { LOGB2 ("liveliness=%d:"FMT_DUR, xqos->liveliness.kind, PRINTARG_DUR (xqos->liveliness.lease_duration)); }); DO (RELIABILITY, { LOGB2 ("reliability=%d:"FMT_DUR, xqos->reliability.kind, PRINTARG_DUR (xqos->reliability.max_blocking_time)); }); DO (DESTINATION_ORDER, { LOGB1 ("destination_order=%d", xqos->destination_order.kind); }); - DO (HISTORY, { LOGB2 ("history=%d:%d", xqos->history.kind, xqos->history.depth); }); - DO (RESOURCE_LIMITS, { LOGB3 ("resource_limits=%d:%d:%d", xqos->resource_limits.max_samples, xqos->resource_limits.max_instances, xqos->resource_limits.max_samples_per_instance); }); - DO (TRANSPORT_PRIORITY, { LOGB1 ("transport_priority=%d", xqos->transport_priority.value); }); + DO (HISTORY, { LOGB2 ("history=%d:%"PRId32, xqos->history.kind, xqos->history.depth); }); + DO (RESOURCE_LIMITS, { LOGB3 ("resource_limits=%"PRId32":%"PRId32":%"PRId32, xqos->resource_limits.max_samples, xqos->resource_limits.max_instances, xqos->resource_limits.max_samples_per_instance); }); + DO (TRANSPORT_PRIORITY, { LOGB1 ("transport_priority=%"PRId32, xqos->transport_priority.value); }); DO (LIFESPAN, { LOGB1 ("lifespan="FMT_DUR, PRINTARG_DUR (xqos->lifespan.duration)); }); DO (USER_DATA, { - LOGB1 ("user_data=%u<", xqos->user_data.length); + LOGB1 ("user_data=%"PRIu32"<", xqos->user_data.length); log_octetseq (cat, xqos->user_data.length, xqos->user_data.value); DDS_LOG(cat, ">"); }); DO (OWNERSHIP, { LOGB1 ("ownership=%d", xqos->ownership.kind); }); - DO (OWNERSHIP_STRENGTH, { LOGB1 ("ownership_strength=%d", xqos->ownership_strength.value); }); + DO (OWNERSHIP_STRENGTH, { LOGB1 ("ownership_strength=%"PRId32, xqos->ownership_strength.value); }); DO (TIME_BASED_FILTER, { LOGB1 ("time_based_filter="FMT_DUR, PRINTARG_DUR (xqos->time_based_filter.minimum_separation)); }); DO (PRISMTECH_READER_DATA_LIFECYCLE, { LOGB5 ("reader_data_lifecycle="FMT_DUR":"FMT_DUR":%u:%u:%d", PRINTARG_DUR (xqos->reader_data_lifecycle.autopurge_nowriter_samples_delay), PRINTARG_DUR (xqos->reader_data_lifecycle.autopurge_disposed_samples_delay), xqos->reader_data_lifecycle.autopurge_dispose_all, xqos->reader_data_lifecycle.enable_invalid_samples, (int) xqos->reader_data_lifecycle.invalid_sample_visibility); }); DO (PRISMTECH_WRITER_DATA_LIFECYCLE, { @@ -3473,7 +3473,7 @@ void nn_log_xqos (uint32_t cat, const nn_xqos_t *xqos) DO (PRISMTECH_ENTITY_FACTORY, { LOGB1 ("entity_factory=%u", xqos->entity_factory.autoenable_created_entities); }); DO (PRISMTECH_SYNCHRONOUS_ENDPOINT, { LOGB1 ("synchronous_endpoint=%u", xqos->synchronous_endpoint.value); }); DO (RTI_TYPECODE, { - LOGB1 ("rti_typecode=%u<", xqos->rti_typecode.length); + LOGB1 ("rti_typecode=%"PRIu32"<", xqos->rti_typecode.length); log_octetseq (cat, xqos->rti_typecode.length, xqos->rti_typecode.value); DDS_LOG(cat, ">"); }); diff --git a/src/core/ddsi/src/q_radmin.c b/src/core/ddsi/src/q_radmin.c index 4a739fd..a45d4e0 100644 --- a/src/core/ddsi/src/q_radmin.c +++ b/src/core/ddsi/src/q_radmin.c @@ -484,7 +484,7 @@ static void *nn_rbuf_alloc (struct nn_rbufpool *rbufpool) /* Note: only one thread calls nn_rmsg_new on a pool */ uint32_t asize = max_rmsg_size_w_hdr (rbufpool->max_rmsg_size); struct nn_rbuf *rb; - DDS_LOG(DDS_LC_RADMIN, "rmsg_rbuf_alloc(%p, %u)\n", (void *) rbufpool, asize); + DDS_LOG(DDS_LC_RADMIN, "rmsg_rbuf_alloc(%p, %"PRIu32")\n", (void *) rbufpool, asize); ASSERT_RBUFPOOL_OWNER (rbufpool); rb = rbufpool->current; assert (rb != NULL); @@ -501,7 +501,7 @@ static void *nn_rbuf_alloc (struct nn_rbufpool *rbufpool) assert ((uint32_t) (rb->u.raw + rb->size - rb->freeptr) >= asize); } - DDS_LOG(DDS_LC_RADMIN, "rmsg_rbuf_alloc(%p, %u) = %p\n", (void *) rbufpool, asize, (void *) rb->freeptr); + DDS_LOG(DDS_LC_RADMIN, "rmsg_rbuf_alloc(%p, %"PRIu32") = %p\n", (void *) rbufpool, asize, (void *) rb->freeptr); #if USE_VALGRIND VALGRIND_MEMPOOL_ALLOC (rbufpool, rb->freeptr, asize); #endif @@ -540,7 +540,7 @@ struct nn_rmsg *nn_rmsg_new (struct nn_rbufpool *rbufpool) void nn_rmsg_setsize (struct nn_rmsg *rmsg, uint32_t size) { uint32_t size8 = align8uint32 (size); - DDS_LOG(DDS_LC_RADMIN, "rmsg_setsize(%p, %u => %u)\n", (void *) rmsg, size, size8); + DDS_LOG(DDS_LC_RADMIN, "rmsg_setsize(%p, %"PRIu32" => %"PRIu32")\n", (void *) rmsg, size, size8); ASSERT_RBUFPOOL_OWNER (rmsg->chunk.rbuf->rbufpool); ASSERT_RMSG_UNCOMMITTED (rmsg); assert (ddsrt_atomic_ld32 (&rmsg->refcount) == RMSG_REFCOUNT_UNCOMMITTED_BIAS); @@ -601,7 +601,7 @@ void nn_rmsg_commit (struct nn_rmsg *rmsg) happens to be such that any asynchronous activities have completed before we got to commit. */ struct nn_rmsg_chunk *chunk = rmsg->lastchunk; - DDS_LOG(DDS_LC_RADMIN, "rmsg_commit(%p) refcount 0x%x last-chunk-size %u\n", + DDS_LOG(DDS_LC_RADMIN, "rmsg_commit(%p) refcount 0x%"PRIx32" last-chunk-size %"PRIu32"\n", (void *) rmsg, rmsg->refcount.v, chunk->size); ASSERT_RBUFPOOL_OWNER (chunk->rbuf->rbufpool); ASSERT_RMSG_UNCOMMITTED (rmsg); @@ -665,7 +665,7 @@ void *nn_rmsg_alloc (struct nn_rmsg *rmsg, uint32_t size) struct nn_rbuf *rbuf = chunk->rbuf; uint32_t size8 = align8uint32 (size); void *ptr; - DDS_LOG(DDS_LC_RADMIN, "rmsg_alloc(%p, %u => %u)\n", (void *) rmsg, size, size8); + DDS_LOG(DDS_LC_RADMIN, "rmsg_alloc(%p, %"PRIu32" => %"PRIu32")\n", (void *) rmsg, size, size8); ASSERT_RBUFPOOL_OWNER (rbuf->rbufpool); ASSERT_RMSG_UNCOMMITTED (rmsg); assert ((chunk->size % 8) == 0); @@ -675,12 +675,12 @@ void *nn_rmsg_alloc (struct nn_rmsg *rmsg, uint32_t size) { struct nn_rbufpool *rbufpool = rbuf->rbufpool; struct nn_rmsg_chunk *newchunk; - DDS_LOG(DDS_LC_RADMIN, "rmsg_alloc(%p, %u) limit hit - new chunk\n", (void *) rmsg, size); + DDS_LOG(DDS_LC_RADMIN, "rmsg_alloc(%p, %"PRIu32") limit hit - new chunk\n", (void *) rmsg, size); commit_rmsg_chunk (chunk); newchunk = nn_rbuf_alloc (rbufpool); if (newchunk == NULL) { - DDS_WARNING ("nn_rmsg_alloc: can't allocate more memory (%u bytes) ... giving up\n", size); + DDS_WARNING ("nn_rmsg_alloc: can't allocate more memory (%"PRIu32" bytes) ... giving up\n", size); return NULL; } init_rmsg_chunk (newchunk, rbufpool->current); @@ -690,7 +690,7 @@ void *nn_rmsg_alloc (struct nn_rmsg *rmsg, uint32_t size) ptr = chunk->u.payload + chunk->size; chunk->size += size8; - DDS_LOG(DDS_LC_RADMIN, "rmsg_alloc(%p, %u) = %p\n", (void *) rmsg, size, ptr); + DDS_LOG(DDS_LC_RADMIN, "rmsg_alloc(%p, %"PRIu32") = %p\n", (void *) rmsg, size, ptr); #if USE_VALGRIND if (chunk == &rmsg->chunk) { VALGRIND_MEMPOOL_CHANGE (rbuf->rbufpool, rmsg, rmsg, offsetof (struct nn_rmsg, chunk.u.payload) + chunk->size); @@ -717,7 +717,7 @@ struct nn_rdata *nn_rdata_new (struct nn_rmsg *rmsg, uint32_t start, uint32_t en #ifndef NDEBUG ddsrt_atomic_st32 (&d->refcount_bias_added, 0); #endif - DDS_LOG(DDS_LC_RADMIN, "rdata_new(%p, bytes [%u,%u), submsg @ %u, payload @ %u) = %p\n", (void *) rmsg, start, endp1, NN_RDATA_SUBMSG_OFF (d), NN_RDATA_PAYLOAD_OFF (d), (void *) d); + DDS_LOG(DDS_LC_RADMIN, "rdata_new(%p, bytes [%"PRIu32",%"PRIu32"), submsg @ %u, payload @ %u) = %p\n", (void *) rmsg, start, endp1, NN_RDATA_SUBMSG_OFF (d), NN_RDATA_PAYLOAD_OFF (d), (void *) d); return d; } @@ -931,7 +931,7 @@ static int defrag_try_merge_with_succ (struct nn_rsample_defrag *sample, struct { struct nn_defrag_iv *succ; - DDS_LOG(DDS_LC_RADMIN, " defrag_try_merge_with_succ(%p [%u..%u)):\n", + DDS_LOG(DDS_LC_RADMIN, " defrag_try_merge_with_succ(%p [%"PRIu32"..%"PRIu32")):\n", (void *) node, node->min, node->maxp1); if (node == sample->lastfrag) { @@ -942,7 +942,7 @@ static int defrag_try_merge_with_succ (struct nn_rsample_defrag *sample, struct succ = ddsrt_avl_find_succ (&rsample_defrag_fragtree_treedef, &sample->fragtree, node); assert (succ != NULL); - DDS_LOG(DDS_LC_RADMIN, " succ is %p [%u..%u)\n", (void *) succ, succ->min, succ->maxp1); + DDS_LOG(DDS_LC_RADMIN, " succ is %p [%"PRIu32"..%"PRIu32")\n", (void *) succ, succ->min, succ->maxp1); if (succ->min > node->maxp1) { DDS_LOG(DDS_LC_RADMIN, " gap between node and succ\n"); @@ -1147,7 +1147,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct /* relatively expensive test: lastfrag, tree must be consistent */ assert (dfsample->lastfrag == ddsrt_avl_find_max (&rsample_defrag_fragtree_treedef, &dfsample->fragtree)); - DDS_LOG(DDS_LC_RADMIN, " lastfrag %p [%u..%u)\n", + DDS_LOG(DDS_LC_RADMIN, " lastfrag %p [%"PRIu32"..%"PRIu32")\n", (void *) dfsample->lastfrag, dfsample->lastfrag->min, dfsample->lastfrag->maxp1); @@ -1164,7 +1164,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct /* Slow path: find preceding fragment by tree search */ predeq = ddsrt_avl_lookup_pred_eq (&rsample_defrag_fragtree_treedef, &dfsample->fragtree, &min); assert (predeq); - DDS_LOG(DDS_LC_RADMIN, " slow path: predeq = lookup %u => %p [%u..%u)\n", + DDS_LOG(DDS_LC_RADMIN, " slow path: predeq = lookup %"PRIu32" => %p [%"PRIu32"..%"PRIu32")\n", min, (void *) predeq, predeq->min, predeq->maxp1); } @@ -1213,7 +1213,7 @@ static struct nn_rsample *defrag_add_fragment (struct nn_rsample *sample, struct fragment in the chain adds value); but doesn't overlap with predeq so the tree structure doesn't change even though the key does change */ - DDS_LOG(DDS_LC_RADMIN, " extending succ %p [%u..%u) at head\n", + DDS_LOG(DDS_LC_RADMIN, " extending succ %p [%"PRIu32"..%"PRIu32") at head\n", (void *) succ, succ->min, succ->maxp1); nn_rdata_addbias (rdata); rdata->nextfrag = succ->first; @@ -1336,7 +1336,7 @@ struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata consistent. Max_sample must be consistent with tree */ assert (defrag->max_sample == ddsrt_avl_find_max (&defrag_sampletree_treedef, &defrag->sampletree)); max_seq = defrag->max_sample ? defrag->max_sample->u.defrag.seq : 0; - DDS_LOG(DDS_LC_RADMIN, "defrag_rsample(%p, %p [%u..%u) msg %p, %p seq %"PRId64" size %u) max_seq %p %"PRId64":\n", + DDS_LOG(DDS_LC_RADMIN, "defrag_rsample(%p, %p [%"PRIu32"..%"PRIu32") msg %p, %p seq %"PRId64" size %"PRIu32") max_seq %p %"PRId64":\n", (void *) defrag, (void *) rdata, rdata->min, rdata->maxp1, (void *) rdata->rmsg, (void *) sampleinfo, sampleinfo->seq, sampleinfo->size, (void *) defrag->max_sample, max_seq); @@ -2230,7 +2230,7 @@ nn_reorder_result_t nn_reorder_gap (struct nn_rsample_chain *sc, struct nn_reord } else if (coalesced->u.reorder.min <= reorder->next_seq) { - DDS_LOG(DDS_LC_RADMIN, " coalesced = [%"PRId64",%"PRId64") @ %p containing %d samples\n", + DDS_LOG(DDS_LC_RADMIN, " coalesced = [%"PRId64",%"PRId64") @ %p containing %"PRId32" samples\n", coalesced->u.reorder.min, coalesced->u.reorder.maxp1, (void *) coalesced, coalesced->u.reorder.n_samples); ddsrt_avl_delete (&reorder_sampleivtree_treedef, &reorder->sampleivtree, coalesced); diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 4ae45ce..5aae883 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -93,7 +93,7 @@ static void maybe_set_reader_in_sync (struct proxy_writer *pwr, struct pwr_rd_ma case PRMSS_OUT_OF_SYNC: if (nn_reorder_next_seq (wn->u.not_in_sync.reorder) - 1 >= wn->u.not_in_sync.end_of_out_of_sync_seq) { - DDS_TRACE(" msr_in_sync(%x:%x:%x:%x out-of-sync to tlcatchup)", PGUID (wn->rd_guid)); + DDS_TRACE(" msr_in_sync("PGUIDFMT" out-of-sync to tlcatchup)", PGUID (wn->rd_guid)); wn->in_sync = PRMSS_TLCATCHUP; maybe_set_reader_in_sync (pwr, wn, last_deliv_seq); } @@ -627,14 +627,14 @@ static void force_heartbeat_to_peer (struct writer *wr, const struct whc_state * } add_Gap (m, wr, prd, seq, seq+1, 1, &bits); add_Heartbeat (m, wr, whcst, hbansreq, prd->e.guid.entityid, 1); - DDS_TRACE("force_heartbeat_to_peer: %x:%x:%x:%x -> %x:%x:%x:%x - whc empty, queueing gap #%"PRId64" + heartbeat for transmit\n", + DDS_TRACE("force_heartbeat_to_peer: "PGUIDFMT" -> "PGUIDFMT" - whc empty, queueing gap #%"PRId64" + heartbeat for transmit\n", PGUID (wr->e.guid), PGUID (prd->e.guid), seq); } else { /* Send a Heartbeat just to this peer */ add_Heartbeat (m, wr, whcst, hbansreq, prd->e.guid.entityid, 0); - DDS_TRACE("force_heartbeat_to_peer: %x:%x:%x:%x -> %x:%x:%x:%x - queue for transmit\n", + DDS_TRACE("force_heartbeat_to_peer: "PGUIDFMT" -> "PGUIDFMT" - queue for transmit\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); } qxev_msg (wr->evq, m); @@ -729,7 +729,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac src.entityid = msg->readerId; dst.prefix = rst->dst_guid_prefix; dst.entityid = msg->writerId; - DDS_TRACE("ACKNACK(%s#%d:%"PRId64"/%u:", msg->smhdr.flags & ACKNACK_FLAG_FINAL ? "F" : "", + DDS_TRACE("ACKNACK(%s#%"PRId32":%"PRId64"/%"PRIu32":", msg->smhdr.flags & ACKNACK_FLAG_FINAL ? "F" : "", *countp, fromSN (msg->readerSNState.bitmap_base), msg->readerSNState.numbits); for (i = 0; i < msg->readerSNState.numbits; i++) DDS_TRACE("%c", nn_bitset_isset (msg->readerSNState.numbits, msg->readerSNState.bits, i) ? '1' : '0'); @@ -737,13 +737,13 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac if (!rst->forme) { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not-for-me)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst)); return 1; } if ((wr = ephash_lookup_writer_guid (&dst)) == NULL) { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x?)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT"?)", PGUID (src), PGUID (dst)); return 1; } /* Always look up the proxy reader -- even though we don't need for @@ -752,7 +752,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac only retrieve it when needed. */ if ((prd = ephash_lookup_proxy_reader_guid (&src)) == NULL) { - DDS_TRACE(" %x:%x:%x:%x? -> %x:%x:%x:%x)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst)); return 1; } @@ -762,14 +762,14 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac if (!wr->reliable) /* note: reliability can't be changed */ { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not a reliable writer!)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not a reliable writer!)", PGUID (src), PGUID (dst)); return 1; } ddsrt_mutex_lock (&wr->e.lock); if ((rn = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &src)) == NULL) { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not a connection)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not a connection)", PGUID (src), PGUID (dst)); goto out; } @@ -789,10 +789,10 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac if (!accept_ack_or_hb_w_timeout (*countp, &rn->next_acknack, tnow, &rn->t_acknack_accepted, is_preemptive_ack)) { - DDS_TRACE(" [%x:%x:%x:%x -> %x:%x:%x:%x])", PGUID (src), PGUID (dst)); + DDS_TRACE(" ["PGUIDFMT" -> "PGUIDFMT"])", PGUID (src), PGUID (dst)); goto out; } - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT"", PGUID (src), PGUID (dst)); /* Update latency estimates if we have a timestamp -- won't actually work so well if the timestamp can be a left over from some other @@ -851,7 +851,7 @@ static int handle_AckNack (struct receiver_state *rst, nn_etime_t tnow, const Ac rn->seq = wr->seq; } ddsrt_avl_augment_update (&wr_readers_treedef, rn); - DDS_LOG(DDS_LC_THROTTLE, "writer %x:%x:%x:%x considering reader %x:%x:%x:%x responsive again\n", PGUID (wr->e.guid), PGUID (rn->prd_guid)); + DDS_LOG(DDS_LC_THROTTLE, "writer "PGUIDFMT" considering reader "PGUIDFMT" responsive again\n", PGUID (wr->e.guid), PGUID (rn->prd_guid)); } /* Second, the NACK bits (literally, that is). To do so, attempt to @@ -1143,7 +1143,7 @@ static void handle_Heartbeat_helper (struct pwr_rd_match * const wn, struct hand /* Not supposed to respond to repeats and old heartbeats. */ if (!accept_ack_or_hb_w_timeout (msg->count, &wn->next_heartbeat, arg->tnow, &wn->t_heartbeat_accepted, 0)) { - DDS_TRACE(" (%x:%x:%x:%x)", PGUID (wn->rd_guid)); + DDS_TRACE(" ("PGUIDFMT")", PGUID (wn->rd_guid)); return; } @@ -1154,7 +1154,7 @@ static void handle_Heartbeat_helper (struct pwr_rd_match * const wn, struct hand refseq = nn_reorder_next_seq (pwr->reorder) - 1; else refseq = nn_reorder_next_seq (wn->u.not_in_sync.reorder) - 1; - DDS_TRACE(" %x:%x:%x:%x@%"PRId64"%s", PGUID (wn->rd_guid), refseq, (wn->in_sync == PRMSS_SYNC) ? "(sync)" : (wn->in_sync == PRMSS_TLCATCHUP) ? "(tlcatchup)" : ""); + DDS_TRACE(" "PGUIDFMT"@%"PRId64"%s", PGUID (wn->rd_guid), refseq, (wn->in_sync == PRMSS_SYNC) ? "(sync)" : (wn->in_sync == PRMSS_TLCATCHUP) ? "(tlcatchup)" : ""); /* Reschedule AckNack transmit if deemed appropriate; unreliable readers have acknack_xevent == NULL and can't do this. @@ -1214,17 +1214,17 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct dst.prefix = rst->dst_guid_prefix; dst.entityid = msg->readerId; - DDS_TRACE("HEARTBEAT(%s#%d:%"PRId64"..%"PRId64" ", msg->smhdr.flags & HEARTBEAT_FLAG_FINAL ? "F" : "", msg->count, firstseq, lastseq); + DDS_TRACE("HEARTBEAT(%s#%"PRId32":%"PRId64"..%"PRId64" ", msg->smhdr.flags & HEARTBEAT_FLAG_FINAL ? "F" : "", msg->count, firstseq, lastseq); if (!rst->forme) { - DDS_TRACE("%x:%x:%x:%x -> %x:%x:%x:%x not-for-me)", PGUID (src), PGUID (dst)); + DDS_TRACE(""PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst)); return 1; } if ((pwr = ephash_lookup_proxy_writer_guid (&src)) == NULL) { - DDS_TRACE("%x:%x:%x:%x? -> %x:%x:%x:%x)", PGUID (src), PGUID (dst)); + DDS_TRACE(""PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst)); return 1; } @@ -1232,7 +1232,7 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct if (pwr->assert_pp_lease) lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); - DDS_TRACE("%x:%x:%x:%x -> %x:%x:%x:%x:", PGUID (src), PGUID (dst)); + DDS_TRACE(""PGUIDFMT" -> "PGUIDFMT":", PGUID (src), PGUID (dst)); ddsrt_mutex_lock (&pwr->e.lock); @@ -1311,7 +1311,7 @@ static int handle_Heartbeat (struct receiver_state *rst, nn_etime_t tnow, struct if (wn->u.not_in_sync.end_of_tl_seq == MAX_SEQ_NUMBER) { wn->u.not_in_sync.end_of_out_of_sync_seq = wn->u.not_in_sync.end_of_tl_seq = fromSN (msg->lastSN); - DDS_TRACE(" end-of-tl-seq(rd %x:%x:%x:%x #%"PRId64")", PGUID(wn->rd_guid), wn->u.not_in_sync.end_of_tl_seq); + DDS_TRACE(" end-of-tl-seq(rd "PGUIDFMT" #%"PRId64")", PGUID(wn->rd_guid), wn->u.not_in_sync.end_of_tl_seq); } maybe_set_reader_in_sync (pwr, wn, last_deliv_seq); } @@ -1343,16 +1343,16 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime dst.prefix = rst->dst_guid_prefix; dst.entityid = msg->readerId; - DDS_TRACE("HEARTBEATFRAG(#%d:%"PRId64"/[1,%u]", msg->count, seq, fragnum+1); + DDS_TRACE("HEARTBEATFRAG(#%"PRId32":%"PRId64"/[1,%u]", msg->count, seq, fragnum+1); if (!rst->forme) { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not-for-me)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst)); return 1; } if ((pwr = ephash_lookup_proxy_writer_guid (&src)) == NULL) { - DDS_TRACE(" %x:%x:%x:%x? -> %x:%x:%x:%x)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst)); return 1; } @@ -1360,7 +1360,7 @@ static int handle_HeartbeatFrag (struct receiver_state *rst, UNUSED_ARG(nn_etime if (pwr->assert_pp_lease) lease_renew (ddsrt_atomic_ldvoidp (&pwr->c.proxypp->lease), tnow); - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT"", PGUID (src), PGUID (dst)); ddsrt_mutex_lock (&pwr->e.lock); if (seq > pwr->last_seq) @@ -1459,19 +1459,19 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N dst.prefix = rst->dst_guid_prefix; dst.entityid = msg->writerId; - DDS_TRACE("NACKFRAG(#%d:%"PRId64"/%u/%u:", *countp, seq, msg->fragmentNumberState.bitmap_base, msg->fragmentNumberState.numbits); + DDS_TRACE("NACKFRAG(#%"PRId32":%"PRId64"/%u/%"PRIu32":", *countp, seq, msg->fragmentNumberState.bitmap_base, msg->fragmentNumberState.numbits); for (i = 0; i < msg->fragmentNumberState.numbits; i++) DDS_TRACE("%c", nn_bitset_isset (msg->fragmentNumberState.numbits, msg->fragmentNumberState.bits, i) ? '1' : '0'); if (!rst->forme) { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not-for-me)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst)); return 1; } if ((wr = ephash_lookup_writer_guid (&dst)) == NULL) { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x?)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT"?)", PGUID (src), PGUID (dst)); return 1; } /* Always look up the proxy reader -- even though we don't need for @@ -1480,7 +1480,7 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N only retrieve it when needed. */ if ((prd = ephash_lookup_proxy_reader_guid (&src)) == NULL) { - DDS_TRACE(" %x:%x:%x:%x? -> %x:%x:%x:%x)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst)); return 1; } @@ -1490,25 +1490,25 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N if (!wr->reliable) /* note: reliability can't be changed */ { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not a reliable writer)", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not a reliable writer)", PGUID (src), PGUID (dst)); return 1; } ddsrt_mutex_lock (&wr->e.lock); if ((rn = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &src)) == NULL) { - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x not a connection", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT" not a connection", PGUID (src), PGUID (dst)); goto out; } /* Ignore old NackFrags (see also handle_AckNack) */ if (*countp < rn->next_nackfrag) { - DDS_TRACE(" [%x:%x:%x:%x -> %x:%x:%x:%x]", PGUID (src), PGUID (dst)); + DDS_TRACE(" ["PGUIDFMT" -> "PGUIDFMT"]", PGUID (src), PGUID (dst)); goto out; } rn->next_nackfrag = *countp + 1; - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT"", PGUID (src), PGUID (dst)); /* Resend the requested fragments if we still have the sample, send a Gap if we don't have them anymore. */ @@ -1569,7 +1569,7 @@ static int handle_NackFrag (struct receiver_state *rst, nn_etime_t tnow, const N static int handle_InfoDST (struct receiver_state *rst, const InfoDST_t *msg, const nn_guid_prefix_t *dst_prefix) { rst->dst_guid_prefix = nn_ntoh_guid_prefix (msg->guid_prefix); - DDS_TRACE("INFODST(%x:%x:%x)", PGUIDPREFIX (rst->dst_guid_prefix)); + DDS_TRACE("INFODST(%"PRIx32":%"PRIx32":%"PRIx32")", PGUIDPREFIX (rst->dst_guid_prefix)); if (rst->dst_guid_prefix.u[0] == 0 && rst->dst_guid_prefix.u[1] == 0 && rst->dst_guid_prefix.u[2] == 0) { if (dst_prefix) @@ -1591,7 +1591,7 @@ static int handle_InfoSRC (struct receiver_state *rst, const InfoSRC_t *msg) rst->src_guid_prefix = nn_ntoh_guid_prefix (msg->guid_prefix); rst->protocol_version = msg->version; rst->vendor = msg->vendorid; - DDS_TRACE("INFOSRC(%x:%x:%x vendor %u.%u)", + DDS_TRACE("INFOSRC(%"PRIx32":%"PRIx32":%"PRIx32" vendor %u.%u)", PGUIDPREFIX (rst->src_guid_prefix), rst->vendor.id[0], rst->vendor.id[1]); return 1; } @@ -1710,7 +1710,7 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm dst.entityid = msg->readerId; gapstart = fromSN (msg->gapStart); listbase = fromSN (msg->gapList.bitmap_base); - DDS_TRACE("GAP(%"PRId64"..%"PRId64"/%u ", gapstart, listbase, msg->gapList.numbits); + DDS_TRACE("GAP(%"PRId64"..%"PRId64"/%"PRIu32" ", gapstart, listbase, msg->gapList.numbits); /* There is no _good_ reason for a writer to start the bitmap with a 1 bit, but check for it just in case, to reduce the number of @@ -1722,13 +1722,13 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm if (!rst->forme) { - DDS_TRACE("%x:%x:%x:%x -> %x:%x:%x:%x not-for-me)", PGUID (src), PGUID (dst)); + DDS_TRACE(""PGUIDFMT" -> "PGUIDFMT" not-for-me)", PGUID (src), PGUID (dst)); return 1; } if ((pwr = ephash_lookup_proxy_writer_guid (&src)) == NULL) { - DDS_TRACE("%x:%x:%x:%x? -> %x:%x:%x:%x)", PGUID (src), PGUID (dst)); + DDS_TRACE(""PGUIDFMT"? -> "PGUIDFMT")", PGUID (src), PGUID (dst)); return 1; } @@ -1739,11 +1739,11 @@ static int handle_Gap (struct receiver_state *rst, nn_etime_t tnow, struct nn_rm ddsrt_mutex_lock (&pwr->e.lock); if ((wn = ddsrt_avl_lookup (&pwr_readers_treedef, &pwr->readers, &dst)) == NULL) { - DDS_TRACE("%x:%x:%x:%x -> %x:%x:%x:%x not a connection)", PGUID (src), PGUID (dst)); + DDS_TRACE(PGUIDFMT" -> "PGUIDFMT" not a connection)", PGUID (src), PGUID (dst)); ddsrt_mutex_unlock (&pwr->e.lock); return 1; } - DDS_TRACE("%x:%x:%x:%x -> %x:%x:%x:%x", PGUID (src), PGUID (dst)); + DDS_TRACE(PGUIDFMT" -> "PGUIDFMT, PGUID (src), PGUID (dst)); if (!pwr->have_seen_heartbeat && pwr->n_reliable_readers > 0) { @@ -1831,8 +1831,8 @@ static struct ddsi_serdata *extract_sample_from_data { const struct proxy_writer *pwr = sampleinfo->pwr; nn_guid_t guid = pwr ? pwr->e.guid : null_guid; /* can't be null _yet_, but that might change some day */ - DDS_TRACE("data(application, vendor %u.%u): %x:%x:%x:%x #%"PRId64 - ": write without proper payload (data_smhdr_flags 0x%x size %u)\n", + DDS_TRACE("data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64 + ": write without proper payload (data_smhdr_flags 0x%x size %"PRIu32")\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (guid), sampleinfo->seq, data_smhdr_flags, sampleinfo->size); @@ -1882,7 +1882,7 @@ static struct ddsi_serdata *extract_sample_from_data nn_guid_t guid = pwr ? pwr->e.guid : null_guid; /* can't be null _yet_, but that might change some day */ DDS_WARNING ( - "data(application, vendor %u.%u): %x:%x:%x:%x #%"PRId64": deserialization %s/%s failed (%s)\n", + "data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": deserialization %s/%s failed (%s)\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (guid), sampleinfo->seq, topic->name, topic->type_name, @@ -1988,7 +1988,7 @@ static int deliver_user_data (const struct nn_rsample_info *sampleinfo, const st if ((plist_ret = nn_plist_init_frommsg (&qos, NULL, PP_STATUSINFO | PP_KEYHASH | PP_COHERENT_SET | PP_PRISMTECH_EOTINFO, 0, &src)) < 0) { if (plist_ret != Q_ERR_INCOMPATIBLE) - DDS_WARNING ("data(application, vendor %u.%u): %x:%x:%x:%x #%"PRId64": invalid inline qos\n", + DDS_WARNING ("data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": invalid inline qos\n", src.vendorid.id[0], src.vendorid.id[1], PGUID (pwr->e.guid), sampleinfo->seq); return 0; } @@ -2047,7 +2047,7 @@ retry: unsigned i; for (i = 0; rdary[i]; i++) { - DDS_TRACE("reader %x:%x:%x:%x\n", PGUID (rdary[i]->e.guid)); + DDS_TRACE("reader "PGUIDFMT"\n", PGUID (rdary[i]->e.guid)); if (! (ddsi_plugin.rhc_plugin.rhc_store_fn) (rdary[i]->rhc, &pwr_info, payload, tk)) { if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock); @@ -2078,7 +2078,7 @@ retry: struct reader *rd; if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL) { - DDS_TRACE("reader-via-guid %x:%x:%x:%x\n", PGUID (rd->e.guid)); + DDS_TRACE("reader-via-guid "PGUIDFMT"\n", PGUID (rd->e.guid)); (void) (ddsi_plugin.rhc_plugin.rhc_store_fn) (rd->rhc, &pwr_info, payload, tk); } } @@ -2090,7 +2090,7 @@ retry: else { struct reader *rd = ephash_lookup_reader_guid (rdguid);; - DDS_TRACE(" %"PRId64"=>%x:%x:%x:%x%s\n", sampleinfo->seq, PGUID (*rdguid), rd ? "" : "?"); + DDS_TRACE(" %"PRId64"=>"PGUIDFMT"%s\n", sampleinfo->seq, PGUID (*rdguid), rd ? "" : "?"); while (rd && ! (ddsi_plugin.rhc_plugin.rhc_store_fn) (rd->rhc, &pwr_info, payload, tk) && ephash_lookup_proxy_writer_guid (&pwr->e.guid)) { if (pwr_locked) ddsrt_mutex_unlock (&pwr->e.lock); @@ -2166,7 +2166,7 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct nn_guid_t src; src.prefix = rst->src_guid_prefix; src.entityid = msg->writerId; - DDS_TRACE(" %x:%x:%x:%x? -> %x:%x:%x:%x", PGUID (src), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT"? -> "PGUIDFMT, PGUID (src), PGUID (dst)); return; } @@ -2195,14 +2195,14 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct if (!pwr->have_seen_heartbeat && pwr->n_reliable_readers > 0) { ddsrt_mutex_unlock (&pwr->e.lock); - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x: no heartbeat seen yet", PGUID (pwr->e.guid), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT": no heartbeat seen yet", PGUID (pwr->e.guid), PGUID (dst)); return; } if (ddsrt_avl_is_empty (&pwr->readers) || pwr->local_matching_inprogress) { ddsrt_mutex_unlock (&pwr->e.lock); - DDS_TRACE(" %x:%x:%x:%x -> %x:%x:%x:%x: no readers", PGUID (pwr->e.guid), PGUID (dst)); + DDS_TRACE(" "PGUIDFMT" -> "PGUIDFMT": no readers", PGUID (pwr->e.guid), PGUID (dst)); return; } @@ -2359,7 +2359,7 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con cause periodic warnings. */ if (msg->writerId.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER) { - DDS_WARNING ("dropping oversize (%u > %u) SPDP sample %"PRId64" from remote writer %x:%x:%x:%x\n", + DDS_WARNING ("dropping oversize (%"PRIu32" > %"PRIu32") SPDP sample %"PRId64" from remote writer "PGUIDFMT"\n", sampleinfo->size, config.max_sample_size, sampleinfo->seq, PGUIDPREFIX (rst->src_guid_prefix), msg->writerId.u); } @@ -2389,7 +2389,7 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con { const char *tname = pwr->c.topic ? pwr->c.topic->name : "(null)"; const char *ttname = pwr->c.topic ? pwr->c.topic->type_name : "(null)"; - DDS_WARNING ("dropping oversize (%u > %u) sample %"PRId64" from remote writer %x:%x:%x:%x %s/%s\n", + DDS_WARNING ("dropping oversize (%"PRIu32" > %"PRIu32") sample %"PRId64" from remote writer "PGUIDFMT" %s/%s\n", sampleinfo->size, config.max_sample_size, sampleinfo->seq, PGUIDPREFIX (rst->src_guid_prefix), msg->writerId.u, tname, ttname); @@ -2399,7 +2399,7 @@ static void drop_oversize (struct receiver_state *rst, struct nn_rmsg *rmsg, con static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const Data_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap, struct nn_dqueue **deferred_wakeup) { - DDS_TRACE("DATA(%x:%x:%x:%x -> %x:%x:%x:%x #%"PRId64"", + DDS_TRACE("DATA("PGUIDFMT" -> "PGUIDFMT" #%"PRId64, PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, PGUIDPREFIX (rst->dst_guid_prefix), msg->x.readerId.u, fromSN (msg->x.writerSN)); @@ -2443,7 +2443,7 @@ static int handle_Data (struct receiver_state *rst, nn_etime_t tnow, struct nn_r static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct nn_rmsg *rmsg, const DataFrag_t *msg, size_t size, struct nn_rsample_info *sampleinfo, unsigned char *datap, struct nn_dqueue **deferred_wakeup) { - DDS_TRACE("DATAFRAG(%x:%x:%x:%x -> %x:%x:%x:%x #%"PRId64"/[%u..%u]", + DDS_TRACE("DATAFRAG("PGUIDFMT" -> "PGUIDFMT" #%"PRId64"/[%u..%u]", PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, PGUIDPREFIX (rst->dst_guid_prefix), msg->x.readerId.u, fromSN (msg->x.writerSN), @@ -2463,7 +2463,7 @@ static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct uint32_t begin, endp1; if (msg->x.writerId.u == NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER) { - DDS_WARNING ("DATAFRAG(%x:%x:%x:%x #%"PRId64" -> %x:%x:%x:%x) - fragmented builtin data not yet supported\n", + DDS_WARNING ("DATAFRAG("PGUIDFMT" #%"PRId64" -> "PGUIDFMT") - fragmented builtin data not yet supported\n", PGUIDPREFIX (rst->src_guid_prefix), msg->x.writerId.u, fromSN (msg->x.writerSN), PGUIDPREFIX (rst->dst_guid_prefix), msg->x.readerId.u); return 1; @@ -2496,7 +2496,7 @@ static int handle_DataFrag (struct receiver_state *rst, nn_etime_t tnow, struct here */ endp1 = msg->sampleSize; } - DDS_TRACE("/[%u..%u) of %u", begin, endp1, msg->sampleSize); + DDS_TRACE("/[%"PRIu32"..%"PRIu32") of %"PRIu32, begin, endp1, msg->sampleSize); rdata = nn_rdata_new (rmsg, begin, endp1, submsg_offset, payload_offset); @@ -2910,7 +2910,7 @@ static int handle_submsg_sequence #endif /* DDSI_INCLUDE_ENCRYPTION */ break; default: - DDS_TRACE("(unknown id %u?)\n", sm->pt_infocontainer.id); + DDS_TRACE("(unknown id %"PRIu32"?)\n", sm->pt_infocontainer.id); } } break; @@ -2919,7 +2919,7 @@ static int handle_submsg_sequence #if 0 state = "parse:msg_len"; #endif - DDS_TRACE("MSG_LEN(%u)", ((MsgLen_t*) sm)->length); + DDS_TRACE("MSG_LEN(%"PRIu32")", ((MsgLen_t*) sm)->length); break; } case SMID_PT_ENTITY_ID: @@ -3086,7 +3086,7 @@ static bool do_packet else if (hdr->version.major != RTPS_MAJOR || (hdr->version.major == RTPS_MAJOR && hdr->version.minor < RTPS_MINOR_MINIMUM)) { if ((hdr->version.major == RTPS_MAJOR && hdr->version.minor < RTPS_MINOR_MINIMUM)) - DDS_TRACE("HDR(%x:%x:%x vendor %d.%d) len %lu\n, version mismatch: %d.%d\n", + DDS_TRACE("HDR(%"PRIx32":%"PRIx32":%"PRIx32" vendor %d.%d) len %lu\n, version mismatch: %d.%d\n", PGUIDPREFIX (hdr->guid_prefix), hdr->vendorid.id[0], hdr->vendorid.id[1], (unsigned long) sz, hdr->version.major, hdr->version.minor); if (NN_PEDANTIC_P) malformed_packet_received_nosubmsg (buff, sz, "header", hdr->vendorid); @@ -3099,7 +3099,7 @@ static bool do_packet { char addrstr[DDSI_LOCSTRLEN]; ddsi_locator_to_string(addrstr, sizeof(addrstr), &srcloc); - DDS_TRACE("HDR(%x:%x:%x vendor %d.%d) len %lu from %s\n", + DDS_TRACE("HDR(%"PRIx32":%"PRIx32":%"PRIx32" vendor %d.%d) len %lu from %s\n", PGUIDPREFIX (hdr->guid_prefix), hdr->vendorid.id[0], hdr->vendorid.id[1], (unsigned long) sz, addrstr); } @@ -3173,7 +3173,7 @@ static void rebuild_local_participant_set (struct thread_state1 * const ts1, str struct ephash_enum_participant est; struct participant *pp; unsigned nps_alloc; - DDS_TRACE("pp set gen changed: local %u global %"PRIu32"\n", lps->gen, ddsrt_atomic_ld32(&gv.participant_set_generation)); + DDS_TRACE("pp set gen changed: local %"PRIu32" global %"PRIu32"\n", lps->gen, ddsrt_atomic_ld32(&gv.participant_set_generation)); thread_state_awake (ts1); restart: lps->gen = ddsrt_atomic_ld32 (&gv.participant_set_generation); @@ -3201,7 +3201,7 @@ static void rebuild_local_participant_set (struct thread_state1 * const ts1, str { lps->ps[lps->nps].m_conn = pp->m_conn; lps->ps[lps->nps].guid_prefix = pp->e.guid.prefix; - DDS_TRACE(" pp %x:%x:%x:%x handle %"PRIdSOCK"\n", PGUID (pp->e.guid), ddsi_conn_handle (pp->m_conn)); + DDS_TRACE(" pp "PGUIDFMT" handle %"PRIdSOCK"\n", PGUID (pp->e.guid), ddsi_conn_handle (pp->m_conn)); lps->nps++; } } diff --git a/src/core/ddsi/src/q_sockwaitset.c b/src/core/ddsi/src/q_sockwaitset.c index 7d811e7..f8a761f 100644 --- a/src/core/ddsi/src/q_sockwaitset.c +++ b/src/core/ddsi/src/q_sockwaitset.c @@ -873,7 +873,7 @@ os_sockWaitsetCtx os_sockWaitsetWait (os_sockWaitset ws) dds_retcode_t rc = ddsrt_select (fdmax, rdset, NULL, NULL, DDS_INFINITY, &n); if (rc != DDS_RETCODE_OK && rc != DDS_RETCODE_INTERRUPTED && rc != DDS_RETCODE_TRY_AGAIN) { - DDS_WARNING("os_sockWaitsetWait: select failed, retcode = %d", rc); + DDS_WARNING("os_sockWaitsetWait: select failed, retcode = %"PRId32, rc); break; } } diff --git a/src/core/ddsi/src/q_thread.c b/src/core/ddsi/src/q_thread.c index 9ca93fc..e8ed142 100644 --- a/src/core/ddsi/src/q_thread.c +++ b/src/core/ddsi/src/q_thread.c @@ -275,7 +275,7 @@ dds_retcode_t create_thread (struct thread_state1 **ts1, const char *name, uint3 if (!tprops->stack_size.isdefault) tattr.stackSize = tprops->stack_size.value; } - DDS_TRACE("create_thread: %s: class %d priority %d stack %u\n", name, (int) tattr.schedClass, tattr.schedPriority, tattr.stackSize); + DDS_TRACE("create_thread: %s: class %d priority %"PRId32" stack %"PRIu32"\n", name, (int) tattr.schedClass, tattr.schedPriority, tattr.stackSize); if (ddsrt_thread_create (&tid, name, &tattr, &create_thread_wrapper, ctxt) != DDS_RETCODE_OK) { diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index c83c008..7401d3b 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -185,11 +185,11 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru } } - DDS_TRACE("writer_hbcontrol: wr %x:%x:%x:%x ", PGUID (wr->e.guid)); + DDS_TRACE("writer_hbcontrol: wr "PGUIDFMT" ", PGUID (wr->e.guid)); if (prd_guid == NULL) DDS_TRACE("multicasting "); else - DDS_TRACE("unicasting to prd %x:%x:%x:%x ", PGUID (*prd_guid)); + DDS_TRACE("unicasting to prd "PGUIDFMT" ", PGUID (*prd_guid)); DDS_TRACE("(rel-prd %d seq-eq-max %d seq %"PRId64" maxseq %"PRId64")\n", wr->num_reliable_readers, ddsrt_avl_is_empty (&wr->readers) ? -1 : root_rdmatch (wr)->num_reliable_readers_where_seq_equals_max, @@ -209,7 +209,7 @@ struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const stru struct proxy_reader *prd; if ((prd = ephash_lookup_proxy_reader_guid (prd_guid)) == NULL) { - DDS_TRACE("writer_hbcontrol: wr %x:%x:%x:%x unknown prd %x:%x:%x:%x\n", PGUID (wr->e.guid), PGUID (*prd_guid)); + DDS_TRACE("writer_hbcontrol: wr "PGUIDFMT" unknown prd "PGUIDFMT"\n", PGUID (wr->e.guid), PGUID (*prd_guid)); nn_xmsg_free (msg); return NULL; } @@ -308,7 +308,7 @@ struct nn_xmsg *writer_hbcontrol_piggyback (struct writer *wr, const struct whc_ if (msg) { - DDS_TRACE("heartbeat(wr %x:%x:%x:%x%s) piggybacked, resched in %g s (min-ack %"PRId64"%s, avail-seq %"PRId64", xmit %"PRId64")\n", + DDS_TRACE("heartbeat(wr "PGUIDFMT"%s) piggybacked, resched in %g s (min-ack %"PRId64"%s, avail-seq %"PRId64", xmit %"PRId64")\n", PGUID (wr->e.guid), *hbansreq ? "" : " final", (hbc->tsched.v == T_NEVER) ? POS_INFINITY_DOUBLE : (double) (hbc->tsched.v - tnow.v) / 1e9, @@ -635,7 +635,7 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli nn_xmsg_serdata (*pmsg, serdata, fragstart, fraglen); nn_xmsg_submsg_setnext (*pmsg, sm_marker); #if 0 - DDS_TRACE("queue data%s %x:%x:%x:%x #%lld/%u[%u..%u)\n", + DDS_TRACE("queue data%s "PGUIDFMT" #%lld/%u[%u..%u)\n", fragging ? "frag" : "", PGUID (wr->e.guid), seq, fragnum+1, fragstart, fragstart + fraglen); #endif @@ -871,10 +871,10 @@ static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct nn_plist const char *ttname = wr->topic ? wr->topic->type_name : "(null)"; ppbuf[0] = '\0'; tmp = sizeof (ppbuf) - 1; - DDS_TRACE("write_sample %x:%x:%x:%x #%"PRId64"", PGUID (wr->e.guid), seq); + DDS_TRACE("write_sample "PGUIDFMT" #%"PRId64, PGUID (wr->e.guid), seq); if (plist != 0 && (plist->present & PP_COHERENT_SET)) DDS_TRACE(" C#%"PRId64"", fromSN (plist->coherent_set_seqno)); - DDS_TRACE(": ST%u %s/%s:%s%s\n", serdata->statusinfo, tname, ttname, ppbuf, tmp < (int) sizeof (ppbuf) ? "" : " (trunc)"); + DDS_TRACE(": ST%"PRIu32" %s/%s:%s%s\n", serdata->statusinfo, tname, ttname, ppbuf, tmp < (int) sizeof (ppbuf) ? "" : " (trunc)"); } assert (wr->reliable || have_reliable_subs (wr) == 0); @@ -960,7 +960,7 @@ static dds_retcode_t throttle_writer (struct thread_state1 * const ts1, struct n assert (!is_builtin_entityid(wr->e.guid.entityid, NN_VENDORID_ECLIPSE)); } - DDS_LOG(DDS_LC_THROTTLE, "writer %x:%x:%x:%x waiting for whc to shrink below low-water mark (whc %"PRIuSIZE" low=%u high=%u)\n", PGUID (wr->e.guid), whcst.unacked_bytes, wr->whc_low, wr->whc_high); + DDS_LOG(DDS_LC_THROTTLE, "writer "PGUIDFMT" waiting for whc to shrink below low-water mark (whc %"PRIuSIZE" low=%"PRIu32" high=%"PRIu32")\n", PGUID (wr->e.guid), whcst.unacked_bytes, wr->whc_low, wr->whc_high); wr->throttling++; wr->throttle_count++; @@ -1007,7 +1007,7 @@ static dds_retcode_t throttle_writer (struct thread_state1 * const ts1, struct n ddsrt_cond_broadcast (&wr->throttle_cond); } - DDS_LOG(DDS_LC_THROTTLE, "writer %x:%x:%x:%x done waiting for whc to shrink below low-water mark (whc %"PRIuSIZE" low=%u high=%u)\n", PGUID (wr->e.guid), whcst.unacked_bytes, wr->whc_low, wr->whc_high); + DDS_LOG(DDS_LC_THROTTLE, "writer "PGUIDFMT" done waiting for whc to shrink below low-water mark (whc %"PRIuSIZE" low=%"PRIu32" high=%"PRIu32")\n", PGUID (wr->e.guid), whcst.unacked_bytes, wr->whc_low, wr->whc_high); return result; } @@ -1046,7 +1046,7 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * const char *ttname = wr->topic ? wr->topic->type_name : "(null)"; ppbuf[0] = '\0'; tmp = sizeof (ppbuf) - 1; - DDS_WARNING ("dropping oversize (%u > %u) sample from local writer %x:%x:%x:%x %s/%s:%s%s\n", + DDS_WARNING ("dropping oversize (%"PRIu32" > %"PRIu32") sample from local writer "PGUIDFMT" %s/%s:%s%s\n", ddsi_serdata_size (serdata), config.max_sample_size, PGUID (wr->e.guid), tname, ttname, ppbuf, tmp < (int) sizeof (ppbuf) ? "" : " (trunc)"); diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index bbeb9c2..e4b107b 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -196,7 +196,7 @@ static void trace_msg (const char *func, const struct nn_xmsg *m) seqno_t wrseq; nn_fragment_number_t wrfragid; nn_xmsg_guid_seq_fragid (m, &wrguid, &wrseq, &wrfragid); - DDS_TRACE(" %s(%x:%x:%x:%x/%"PRId64"/%u)", func, PGUID (wrguid), wrseq, wrfragid); + DDS_TRACE(" %s("PGUIDFMT"/%"PRId64"/%u)", func, PGUID (wrguid), wrseq, wrfragid); } } #else @@ -604,7 +604,7 @@ static void handle_xevk_heartbeat (struct nn_xpack *xp, struct xevent *ev, nn_mt if ((wr = ephash_lookup_writer_guid (&ev->u.heartbeat.wr_guid)) == NULL) { - DDS_TRACE("heartbeat(wr %x:%x:%x:%x) writer gone\n", + DDS_TRACE("heartbeat(wr "PGUIDFMT") writer gone\n", PGUID (ev->u.heartbeat.wr_guid)); return; } @@ -631,7 +631,7 @@ static void handle_xevk_heartbeat (struct nn_xpack *xp, struct xevent *ev, nn_mt t_next.v = tnow.v + writer_hbcontrol_intv (wr, &whcst, tnow); } - DDS_TRACE("heartbeat(wr %x:%x:%x:%x%s) %s, resched in %g s (min-ack %"PRId64"%s, avail-seq %"PRId64", xmit %"PRId64")\n", + DDS_TRACE("heartbeat(wr "PGUIDFMT"%s) %s, resched in %g s (min-ack %"PRId64"%s, avail-seq %"PRId64", xmit %"PRId64")\n", PGUID (wr->e.guid), hbansreq ? "" : " final", msg ? "sent" : "suppressed", @@ -826,7 +826,7 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p nn_xmsg_shrink (msg, sm_marker, ACKNACK_SIZE (an->readerSNState.numbits)); nn_xmsg_submsg_setnext (msg, sm_marker); - DDS_TRACE("acknack %x:%x:%x:%x -> %x:%x:%x:%x: #%d:%"PRId64"/%u:", + DDS_TRACE("acknack "PGUIDFMT" -> "PGUIDFMT": #%"PRId32":%"PRId64"/%"PRIu32":", PGUID (rwn->rd_guid), PGUID (pwr->e.guid), rwn->count, base, an->readerSNState.numbits); for (ui = 0; ui != an->readerSNState.numbits; ui++) @@ -857,7 +857,7 @@ static void add_AckNack (struct nn_xmsg *msg, struct proxy_writer *pwr, struct p *countp = ++pwr->nackfragcount; nn_xmsg_submsg_setnext (msg, sm_marker); - DDS_TRACE(" + nackfrag #%d:%"PRId64"/%u/%u:", *countp, fromSN (nf->writerSN), nf->fragmentNumberState.bitmap_base, nf->fragmentNumberState.numbits); + DDS_TRACE(" + nackfrag #%"PRId32":%"PRId64"/%u/%"PRIu32":", *countp, fromSN (nf->writerSN), nf->fragmentNumberState.bitmap_base, nf->fragmentNumberState.numbits); for (ui = 0; ui != nf->fragmentNumberState.numbits; ui++) DDS_TRACE("%c", nn_bitset_isset (nf->fragmentNumberState.numbits, nf->fragmentNumberState.bits, ui) ? '1' : '0'); } @@ -922,12 +922,12 @@ static void handle_xevk_acknack (UNUSED_ARG (struct nn_xpack *xp), struct xevent eventually. */ resched_xevent_if_earlier (ev, add_duration_to_mtime (tnow, config.auto_resched_nack_delay)); } - DDS_TRACE("send acknack(rd %x:%x:%x:%x -> pwr %x:%x:%x:%x)\n", + DDS_TRACE("send acknack(rd "PGUIDFMT" -> pwr "PGUIDFMT")\n", PGUID (ev->u.acknack.rd_guid), PGUID (ev->u.acknack.pwr_guid)); } else { - DDS_TRACE("skip acknack(rd %x:%x:%x:%x -> pwr %x:%x:%x:%x): no address\n", + DDS_TRACE("skip acknack(rd "PGUIDFMT" -> pwr "PGUIDFMT"): no address\n", PGUID (ev->u.acknack.rd_guid), PGUID (ev->u.acknack.pwr_guid)); msg = NULL; } @@ -1009,7 +1009,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e if ((pp = ephash_lookup_participant_guid (&ev->u.spdp.pp_guid)) == NULL) { - DDS_TRACE("handle_xevk_spdp %x:%x:%x:%x - unknown guid\n", + DDS_TRACE("handle_xevk_spdp "PGUIDFMT" - unknown guid\n", PGUID (ev->u.spdp.pp_guid)); if (ev->u.spdp.directed) delete_xevent (ev); @@ -1018,7 +1018,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e if ((spdp_wr = get_builtin_writer (pp, NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)) == NULL) { - DDS_TRACE("handle_xevk_spdp %x:%x:%x:%x - spdp writer of participant not found\n", + DDS_TRACE("handle_xevk_spdp "PGUIDFMT" - spdp writer of participant not found\n", PGUID (ev->u.spdp.pp_guid)); if (ev->u.spdp.directed) delete_xevent (ev); @@ -1040,7 +1040,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e prd = ephash_lookup_proxy_reader_guid (&guid); do_write = (prd != NULL); if (!do_write) - DDS_TRACE("xmit spdp: no proxy reader %x:%x:%x:%x\n", PGUID (guid)); + DDS_TRACE("xmit spdp: no proxy reader "PGUIDFMT"\n", PGUID (guid)); } if (do_write && !resend_spdp_sample_by_guid_key (spdp_wr, &ev->u.spdp.pp_guid, prd)) @@ -1065,7 +1065,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e } else { - DDS_TRACE("xmit spdp: suppressing early spdp response from %x:%x:%x:%x to %x:%x:%x:%x\n", + DDS_TRACE("xmit spdp: suppressing early spdp response from "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x\n", PGUID (pp->e.guid), PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_PARTICIPANT); } #endif @@ -1080,7 +1080,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e else { nn_mtime_t tnext = add_duration_to_mtime (tnow, T_SECOND); - DDS_TRACE("xmit spdp %x:%x:%x:%x to %x:%x:%x:%x (resched %gs)\n", + DDS_TRACE("xmit spdp "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x (resched %gs)\n", PGUID (pp->e.guid), PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER, (double)(tnext.v - tnow.v) / 1e9); @@ -1107,7 +1107,7 @@ static void handle_xevk_spdp (UNUSED_ARG (struct nn_xpack *xp), struct xevent *e intv = config.spdp_interval; tnext = add_duration_to_mtime (tnow, intv); - DDS_TRACE("xmit spdp %x:%x:%x:%x to %x:%x:%x:%x (resched %gs)\n", + DDS_TRACE("xmit spdp "PGUIDFMT" to %"PRIx32":%"PRIx32":%"PRIx32":%x (resched %gs)\n", PGUID (pp->e.guid), PGUIDPREFIX (ev->u.spdp.dest_proxypp_guid_prefix), NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER, (double)(tnext.v - tnow.v) / 1e9); @@ -1128,7 +1128,7 @@ static void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack if ((wr = get_builtin_writer (pp, NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER)) == NULL) { - DDS_TRACE("write_pmd_message(%x:%x:%x:%x) - builtin pmd writer not found\n", PGUID (pp->e.guid)); + DDS_TRACE("write_pmd_message("PGUIDFMT") - builtin pmd writer not found\n", PGUID (pp->e.guid)); return; } @@ -1178,7 +1178,7 @@ static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_ if (intv == T_NEVER) { tnext.v = T_NEVER; - DDS_TRACE("resched pmd(%x:%x:%x:%x): never\n", PGUID (pp->e.guid)); + DDS_TRACE("resched pmd("PGUIDFMT"): never\n", PGUID (pp->e.guid)); } else { @@ -1188,7 +1188,7 @@ static void handle_xevk_pmd_update (struct thread_state1 * const ts1, struct nn_ tnext.v = tnow.v + intv - 2 * T_SECOND; else tnext.v = tnow.v + 4 * intv / 5; - DDS_TRACE("resched pmd(%x:%x:%x:%x): %gs\n", PGUID (pp->e.guid), (double)(tnext.v - tnow.v) / 1e9); + DDS_TRACE("resched pmd("PGUIDFMT"): %gs\n", PGUID (pp->e.guid), (double)(tnext.v - tnow.v) / 1e9); } resched_xevent_if_earlier (ev, tnext); @@ -1213,7 +1213,7 @@ static void handle_xevk_end_startup_mode (UNUSED_ARG (struct nn_xpack *xp), stru static void handle_xevk_delete_writer (UNUSED_ARG (struct nn_xpack *xp), struct xevent *ev, UNUSED_ARG (nn_mtime_t tnow)) { /* don't worry if the writer is already gone by the time we get here. */ - DDS_TRACE("handle_xevk_delete_writer: %x:%x:%x:%x\n", PGUID (ev->u.delete_writer.guid)); + DDS_TRACE("handle_xevk_delete_writer: "PGUIDFMT"\n", PGUID (ev->u.delete_writer.guid)); delete_writer_nolinger (&ev->u.delete_writer.guid); delete_xevent (ev); } @@ -1439,7 +1439,7 @@ void qxev_prd_entityid (struct proxy_reader * prd, nn_guid_prefix_t * id) msg = nn_xmsg_new (gv.xmsgpool, id, sizeof (EntityId_t), NN_XMSG_KIND_CONTROL); if (nn_xmsg_setdstPRD (msg, prd) == 0) { - DDS_TRACE(" qxev_prd_entityid (%x:%x:%x)\n", PGUIDPREFIX (*id)); + DDS_TRACE(" qxev_prd_entityid (%"PRIx32":%"PRIx32":%"PRIx32")\n", PGUIDPREFIX (*id)); nn_xmsg_add_entityid (msg); ddsrt_mutex_lock (&gv.xevents->lock); ev = qxev_common_nt (gv.xevents, XEVK_ENTITYID); @@ -1466,7 +1466,7 @@ void qxev_pwr_entityid (struct proxy_writer * pwr, nn_guid_prefix_t * id) msg = nn_xmsg_new (gv.xmsgpool, id, sizeof (EntityId_t), NN_XMSG_KIND_CONTROL); if (nn_xmsg_setdstPWR (msg, pwr) == 0) { - DDS_TRACE(" qxev_pwr_entityid (%x:%x:%x)\n", PGUIDPREFIX (*id)); + DDS_TRACE(" qxev_pwr_entityid (%"PRIx32":%"PRIx32":%"PRIx32")\n", PGUIDPREFIX (*id)); nn_xmsg_add_entityid (msg); ddsrt_mutex_lock (&pwr->evq->lock); ev = qxev_common_nt (pwr->evq, XEVK_ENTITYID); diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 6e3a6ef..3e8e0fa 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -590,7 +590,7 @@ int nn_xmsg_setdstPRD (struct nn_xmsg *m, const struct proxy_reader *prd) } else { - DDS_WARNING("nn_xmsg_setdstPRD: no address for %x:%x:%x:%x", PGUID (prd->e.guid)); + DDS_WARNING("nn_xmsg_setdstPRD: no address for "PGUIDFMT"", PGUID (prd->e.guid)); return Q_ERR_NO_ADDRESS; } } @@ -603,7 +603,7 @@ int nn_xmsg_setdstPWR (struct nn_xmsg *m, const struct proxy_writer *pwr) nn_xmsg_setdst1 (m, &pwr->e.guid.prefix, &loc); return 0; } - DDS_WARNING("nn_xmsg_setdstPRD: no address for %x:%x:%x:%x", PGUID (pwr->e.guid)); + DDS_WARNING("nn_xmsg_setdstPRD: no address for "PGUIDFMT, PGUID (pwr->e.guid)); return Q_ERR_NO_ADDRESS; } @@ -659,7 +659,7 @@ int nn_xmsg_merge_rexmit_destinations_wrlock_held (struct nn_xmsg *m, const stru assert (m->kindspecific.data.readerId_off != 0); assert (madd->kindspecific.data.readerId_off != 0); - DDS_TRACE(" (%x:%x:%x:%x#%"PRId64"/%u:", + DDS_TRACE(" ("PGUIDFMT"#%"PRId64"/%u:", PGUID (m->kindspecific.data.wrguid), m->kindspecific.data.wrseq, m->kindspecific.data.wrfragid + 1); switch (m->dstmode) @@ -1359,7 +1359,7 @@ static void nn_xpack_send_real (struct nn_xpack * xp) if (dds_get_log_mask() & DDS_LC_TRACE) { int i; - DDS_TRACE("nn_xpack_send %u:", xp->msg_len.length); + DDS_TRACE("nn_xpack_send %"PRIu32":", xp->msg_len.length); for (i = 0; i < (int) xp->niov; i++) { DDS_TRACE(" %p:%lu", (void *) xp->iov[i].iov_base, (unsigned long) xp->iov[i].iov_len); @@ -1412,7 +1412,7 @@ static void nn_xpack_send_real (struct nn_xpack * xp) DDS_TRACE(" ]\n"); if (calls) { - DDS_LOG(DDS_LC_TRAFFIC, "traffic-xmit (%lu) %u\n", (unsigned long) calls, xp->msg_len.length); + DDS_LOG(DDS_LC_TRAFFIC, "traffic-xmit (%lu) %"PRIu32"\n", (unsigned long) calls, xp->msg_len.length); } nn_xmsg_chain_release (&xp->included_msgs); nn_xpack_reinit (xp); @@ -1641,7 +1641,7 @@ int nn_xpack_addmsg (struct nn_xpack *xp, struct nn_xmsg *m, const uint32_t flag But do make sure we can't run out of iovecs. */ assert (niov + NN_XMSG_MAX_SUBMESSAGE_IOVECS <= NN_XMSG_MAX_MESSAGE_IOVECS); - DDS_TRACE("xpack_addmsg %p %p %u(", (void *) xp, (void *) m, flags); + DDS_TRACE("xpack_addmsg %p %p %"PRIu32"(", (void *) xp, (void *) m, flags); switch (m->kind) { case NN_XMSG_KIND_CONTROL: @@ -1649,7 +1649,7 @@ int nn_xpack_addmsg (struct nn_xpack *xp, struct nn_xmsg *m, const uint32_t flag break; case NN_XMSG_KIND_DATA: case NN_XMSG_KIND_DATA_REXMIT: - DDS_TRACE("%s(%x:%x:%x:%x:#%"PRId64"/%u)", + DDS_TRACE("%s("PGUIDFMT":#%"PRId64"/%u)", (m->kind == NN_XMSG_KIND_DATA) ? "data" : "rexmit", PGUID (m->kindspecific.data.wrguid), m->kindspecific.data.wrseq, @@ -1784,7 +1784,7 @@ int nn_xpack_addmsg (struct nn_xpack *xp, struct nn_xmsg *m, const uint32_t flag if (xpo_niov > 0 && sz > config.max_msg_size) { - DDS_TRACE(" => now niov %d sz %"PRIuSIZE" > max_msg_size %u, nn_xpack_send niov %d sz %u now\n", (int) niov, sz, config.max_msg_size, (int) xpo_niov, xpo_sz); + DDS_TRACE(" => now niov %d sz %"PRIuSIZE" > max_msg_size %"PRIu32", nn_xpack_send niov %d sz %"PRIu32" now\n", (int) niov, sz, config.max_msg_size, (int) xpo_niov, xpo_sz); xp->msg_len.length = xpo_sz; xp->niov = xpo_niov; nn_xpack_send (xp, false); diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index 7052233..ca6dc3d 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -624,7 +624,7 @@ static int check_eseq (struct eseq_admin *ea, uint32_t seq, uint32_t keyval, uin uint32_t *eseq; if (keyval >= ea->nkeys) { - printf ("received key %u >= nkeys %u\n", keyval, ea->nkeys); + printf ("received key %"PRIu32" >= nkeys %u\n", keyval, ea->nkeys); exit (3); } ddsrt_mutex_lock (&ea->lock); @@ -1315,7 +1315,7 @@ static void print_stats (dds_time_t tstart, dds_time_t tnow, dds_time_t tprev) prefix, x->pubhandle, (double) x->min / 1e3, (double) x->sum / (double) x->cnt / 1e3, (double) x->max / 1e3, x->cnt); else - printf ("%s %s:%d min %.3fus mean %.3fus max %.3fus cnt %"PRIu32"\n", + printf ("%s %s:%"PRIu32" min %.3fus mean %.3fus max %.3fus cnt %"PRIu32"\n", prefix, pp->hostname, pp->pid, (double) x->min / 1e3, (double) x->sum / (double) x->cnt / 1e3, (double) x->max / 1e3, x->cnt); ddsrt_mutex_unlock (&disc_lock); From 23fe452967df61a8bf253ed69c6bb8e89824c233 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 2 May 2019 11:14:07 +0800 Subject: [PATCH 053/238] out-of-bounds write nn_bitset_one w multiple of 32 nn_bitset_one sets the specified number of bits by first memset'ing the words, then clearing bits set in a final partial word. It mishandled the case where the number of bits is a multiple of 32, clearing the entire word following the last one it was to touch. Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_bitset.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/ddsi/include/dds/ddsi/q_bitset.h b/src/core/ddsi/include/dds/ddsi/q_bitset.h index 630d16a..a359f82 100644 --- a/src/core/ddsi/include/dds/ddsi/q_bitset.h +++ b/src/core/ddsi/include/dds/ddsi/q_bitset.h @@ -49,6 +49,7 @@ inline void nn_bitset_one (uint32_t numbits, uint32_t *bits) memset (bits, 0xff, 4 * ((numbits + 31) / 32)); /* clear bits "accidentally" set */ + if ((numbits % 32) != 0) { const uint32_t k = numbits / 32; const uint32_t n = numbits % 32; From f0844986155038dd20272725eb38867acf991ad5 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 2 May 2019 11:19:41 +0800 Subject: [PATCH 054/238] ddsperf: fix calculation of data rate in Mb/s Multiplying time-in-ns since previous output line by 1e9 instead of dividing it by 1e9 resulted in bit rate showing up as 0Mb/s. Signed-off-by: Erik Boasson --- src/tools/ddsperf/ddsperf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index ca6dc3d..8dd8656 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -1298,7 +1298,7 @@ static void print_stats (dds_time_t tstart, dds_time_t tnow, dds_time_t tprev) if (nrecv > 0) { printf ("%s ntot %"PRIu64" delta: %"PRIu64" lost %"PRIu64" rate %.2f Mb/s\n", - prefix, tot_nrecv, nrecv, nlost, (double) nrecv_bytes * 8 / 1e6 / (1e9 * (double) (tnow - tprev))); + prefix, tot_nrecv, nrecv, nlost, (double) nrecv_bytes * 8 * 1e3 / (double) (tnow - tprev)); } } From c16babcd736afecbb369e17950bc74d306a92132 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 2 May 2019 11:23:35 +0800 Subject: [PATCH 055/238] limit WHC, serdata, xmsg freelist memory use (#168) High sample rates require rather high rates of allocating and freeing WHC nodes, serialised samples (serdata), and RTPS message fragments (xmsg). A bunch of dedicated parallel allocators help take some pressure off the regular malloc/free calls. However, these used to gobble up memory like crazy, in part because of rather generous limits, and in part because there was no restriction on the size of the samples that would be cached, and it could end up caching large numbers of multi-MB samples. It should be noted that there is no benefit to caching large samples anyway, because the sample rate will be that much lower. This commit reduces the maximum number of entries for all three cases, it furthermore limits the maximum size of a serdata or xmsg that can be cached, and finally instead of instantiating a separate allocator for WHC nodes per WHC, it now shares one across all WHCs. Total memory use should now be limited to a couple of MB. The caching can be disabled by setting ``FREELIST_TYPE`` to ``FREELIST_NONE`` in ``q_freelist.h``. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_whc.c | 38 +++++++++++++++------ src/core/ddsi/include/dds/ddsi/q_freelist.h | 10 ++++-- src/core/ddsi/src/ddsi_serdata_default.c | 9 +++-- src/core/ddsi/src/q_freelist.c | 32 ++++++++++++++++- src/core/ddsi/src/q_transmit.c | 10 ++++-- src/core/ddsi/src/q_xmsg.c | 10 ++++-- 6 files changed, 89 insertions(+), 20 deletions(-) diff --git a/src/core/ddsc/src/dds_whc.c b/src/core/ddsc/src/dds_whc.c index b63ca62..2992990 100644 --- a/src/core/ddsc/src/dds_whc.c +++ b/src/core/ddsc/src/dds_whc.c @@ -88,7 +88,6 @@ struct whc_impl { seqno_t max_drop_seq; /* samples in whc with seq <= max_drop_seq => transient-local */ struct whc_intvnode *open_intv; /* interval where next sample will go (usually) */ struct whc_node *maxseq_node; /* NULL if empty; if not in open_intv, open_intv is empty */ - struct nn_freelist freelist; /* struct whc_node *; linked via whc_node::next_seq */ #if USE_EHH struct ddsrt_ehh *seq_hash; #else @@ -124,7 +123,7 @@ static struct whc_node *whc_findseq (const struct whc_impl *whc, seqno_t seq); static void insert_whcn_in_hash (struct whc_impl *whc, struct whc_node *whcn); static void whc_delete_one (struct whc_impl *whc, struct whc_node *whcn); static int compare_seq (const void *va, const void *vb); -static void free_deferred_free_list (struct whc_impl *whc, struct whc_node *deferred_free_list); +static void free_deferred_free_list (struct whc_node *deferred_free_list); static void get_state_locked(const struct whc_impl *whc, struct whc_state *st); static unsigned whc_default_remove_acked_messages_full (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list); @@ -159,6 +158,17 @@ static const struct whc_ops whc_ops = { .free = whc_default_free }; +/* Number of instantiated WHCs and a global freelist for WHC nodes that gets + initialized lazily and cleaned up automatically when the last WHC is freed. + Protected by dds_global.m_mutex. + + sizeof (whc_node) on 64-bit machines ~ 100 bytes, so this is ~1MB + 8k entries seems to be roughly the amount needed for minimum samples, + maximum message size and a short round-trip time */ +#define MAX_FREELIST_SIZE 8192 +static uint32_t whc_count; +static struct nn_freelist whc_node_freelist; + #if USE_EHH static uint32_t whc_seq_entry_hash (const void *vn) { @@ -379,8 +389,10 @@ struct whc *whc_new (int is_transient_local, unsigned hdepth, unsigned tldepth) whc->open_intv = intv; whc->maxseq_node = NULL; - /* hack */ - nn_freelist_init (&whc->freelist, UINT32_MAX, offsetof (struct whc_node, next_seq)); + ddsrt_mutex_lock (&dds_global.m_mutex); + if (whc_count++ == 0) + nn_freelist_init (&whc_node_freelist, MAX_FREELIST_SIZE, offsetof (struct whc_node, next_seq)); + ddsrt_mutex_unlock (&dds_global.m_mutex); check_whc (whc); return (struct whc *)whc; @@ -425,7 +437,11 @@ DDSRT_WARNING_MSVC_ON(6001); } ddsrt_avl_free (&whc_seq_treedef, &whc->seq, ddsrt_free); - nn_freelist_fini (&whc->freelist, ddsrt_free); + + ddsrt_mutex_lock (&dds_global.m_mutex); + if (--whc_count == 0) + nn_freelist_fini (&whc_node_freelist, ddsrt_free); + ddsrt_mutex_unlock (&dds_global.m_mutex); #if USE_EHH ddsrt_ehh_free (whc->seq_hash); @@ -753,11 +769,11 @@ static void whc_delete_one (struct whc_impl *whc, struct whc_node *whcn) if (whcn_tmp->next_seq) whcn_tmp->next_seq->prev_seq = whcn_tmp->prev_seq; whcn_tmp->next_seq = NULL; - free_deferred_free_list (whc, whcn_tmp); + free_deferred_free_list (whcn_tmp); whc->seq_size--; } -static void free_deferred_free_list (struct whc_impl *whc, struct whc_node *deferred_free_list) +static void free_deferred_free_list (struct whc_node *deferred_free_list) { if (deferred_free_list) { @@ -769,7 +785,7 @@ static void free_deferred_free_list (struct whc_impl *whc, struct whc_node *defe if (!cur->borrowed) free_whc_node_contents (cur); } - cur = nn_freelist_pushmany (&whc->freelist, deferred_free_list, last, n); + cur = nn_freelist_pushmany (&whc_node_freelist, deferred_free_list, last, n); while (cur) { struct whc_node *tmp = cur; @@ -781,8 +797,8 @@ static void free_deferred_free_list (struct whc_impl *whc, struct whc_node *defe static void whc_default_free_deferred_free_list (struct whc *whc_generic, struct whc_node *deferred_free_list) { - struct whc_impl * const whc = (struct whc_impl *)whc_generic; - free_deferred_free_list(whc, deferred_free_list); + (void) whc_generic; + free_deferred_free_list (deferred_free_list); } static unsigned whc_default_remove_acked_messages_noidx (struct whc_impl *whc, seqno_t max_drop_seq, struct whc_node **deferred_free_list) @@ -1028,7 +1044,7 @@ static struct whc_node *whc_default_insert_seq (struct whc_impl *whc, seqno_t ma { struct whc_node *newn = NULL; - if ((newn = nn_freelist_pop (&whc->freelist)) == NULL) + if ((newn = nn_freelist_pop (&whc_node_freelist)) == NULL) newn = ddsrt_malloc (sizeof (*newn)); newn->seq = seq; newn->plist = plist; diff --git a/src/core/ddsi/include/dds/ddsi/q_freelist.h b/src/core/ddsi/include/dds/ddsi/q_freelist.h index 8fcafa7..75b4fc0 100644 --- a/src/core/ddsi/include/dds/ddsi/q_freelist.h +++ b/src/core/ddsi/include/dds/ddsi/q_freelist.h @@ -19,7 +19,7 @@ extern "C" { #endif -#define FREELIST_SIMPLE 1 +#define FREELIST_NONE 1 #define FREELIST_ATOMIC_LIFO 2 #define FREELIST_DOUBLE 3 @@ -33,7 +33,13 @@ extern "C" { #endif #endif -#if FREELIST_TYPE == FREELIST_ATOMIC_LIFO +#if FREELIST_TYPE == FREELIST_NONE + +struct nn_freelist { + char dummy; +}; + +#elif FREELIST_TYPE == FREELIST_ATOMIC_LIFO struct nn_freelist { ddsrt_atomic_lifo_t x; diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index 03e340e..167cc8b 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -27,7 +27,12 @@ #include "dds/ddsi/q_globals.h" #include "dds/ddsi/ddsi_serdata_default.h" -#define MAX_POOL_SIZE 16384 +/* 8k entries in the freelist seems to be roughly the amount needed to send + minimum-size (well, 4 bytes) samples as fast as possible over loopback + while using large messages -- actually, it stands to reason that this would + be the same as the WHC node pool size */ +#define MAX_POOL_SIZE 8192 +#define MAX_SIZE_FOR_POOL 256 #define CLEAR_PADDING 0 #ifndef NDEBUG @@ -205,7 +210,7 @@ static void serdata_default_free(struct ddsi_serdata *dcmn) { struct ddsi_serdata_default *d = (struct ddsi_serdata_default *)dcmn; assert(ddsrt_atomic_ld32(&d->c.refc) == 0); - if (!nn_freelist_push (&gv.serpool->freelist, d)) + if (d->size > MAX_SIZE_FOR_POOL || !nn_freelist_push (&gv.serpool->freelist, d)) dds_free (d); } diff --git a/src/core/ddsi/src/q_freelist.c b/src/core/ddsi/src/q_freelist.c index 78e2a77..fd7aef7 100644 --- a/src/core/ddsi/src/q_freelist.c +++ b/src/core/ddsi/src/q_freelist.c @@ -18,7 +18,37 @@ #include "dds/ddsrt/threads.h" #include "dds/ddsi/q_freelist.h" -#if FREELIST_TYPE == FREELIST_ATOMIC_LIFO +#if FREELIST_TYPE == FREELIST_NONE + +void nn_freelist_init (struct nn_freelist *fl, uint32_t max, off_t linkoff) +{ + (void) fl; (void) max; (void) linkoff; +} + +void nn_freelist_fini (struct nn_freelist *fl, void (*free) (void *elem)) +{ + (void) fl; (void) free; +} + +bool nn_freelist_push (struct nn_freelist *fl, void *elem) +{ + (void) fl; (void) elem; + return false; +} + +void *nn_freelist_pushmany (struct nn_freelist *fl, void *first, void *last, uint32_t n) +{ + (void) fl; (void) first; (void) last; (void) n; + return first; +} + +void *nn_freelist_pop (struct nn_freelist *fl) +{ + (void) fl; + return NULL; +} + +#elif FREELIST_TYPE == FREELIST_ATOMIC_LIFO void nn_freelist_init (struct nn_freelist *fl, uint32_t max, off_t linkoff) { diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 7401d3b..3a208ba 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -400,7 +400,9 @@ void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_sta static int create_fragment_message_simple (struct writer *wr, seqno_t seq, struct ddsi_serdata *serdata, struct nn_xmsg **pmsg) { #define TEST_KEYHASH 0 - const size_t expected_inline_qos_size = 4+8+20+4 + 32; + /* actual expected_inline_qos_size is typically 0, but always claiming 32 bytes won't make + a difference, so no point in being precise */ + const size_t expected_inline_qos_size = /* statusinfo */ 8 + /* keyhash */ 20 + /* sentinel */ 4; struct nn_xmsg_marker sm_marker; unsigned char contentflag = 0; Data_t *data; @@ -423,6 +425,7 @@ static int create_fragment_message_simple (struct writer *wr, seqno_t seq, struc ASSERT_MUTEX_HELD (&wr->e.lock); + /* INFO_TS: 12 bytes, Data_t: 24 bytes, expected inline QoS: 32 => should be single chunk */ if ((*pmsg = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, sizeof (InfoTimestamp_t) + sizeof (Data_t) + expected_inline_qos_size, NN_XMSG_KIND_DATA)) == NULL) return Q_ERR_OUT_OF_MEMORY; @@ -484,7 +487,9 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli Expected inline QoS size: header(4) + statusinfo(8) + keyhash(20) + sentinel(4). Plus some spare cos I can't be bothered. */ const int set_smhdr_flags_asif_data = config.buggy_datafrag_flags_mode; - const size_t expected_inline_qos_size = 4+8+20+4 + 32; + /* actual expected_inline_qos_size is typically 0, but always claiming 32 bytes won't make + a difference, so no point in being precise */ + const size_t expected_inline_qos_size = /* statusinfo */ 8 + /* keyhash */ 20 + /* sentinel */ 4; struct nn_xmsg_marker sm_marker; void *sm; Data_DataFrag_common_t *ddcmn; @@ -508,6 +513,7 @@ int create_fragment_message (struct writer *wr, seqno_t seq, const struct nn_pli fragging = (config.fragment_size < size); + /* INFO_TS: 12 bytes, DataFrag_t: 36 bytes, expected inline QoS: 32 => should be single chunk */ if ((*pmsg = nn_xmsg_new (gv.xmsgpool, &wr->e.guid.prefix, sizeof (InfoTimestamp_t) + sizeof (DataFrag_t) + expected_inline_qos_size, xmsg_kind)) == NULL) return Q_ERR_OUT_OF_MEMORY; diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 3e8e0fa..3c0eae0 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -241,13 +241,18 @@ static size_t align4u (size_t x) Great expectations, but so far still wanting. */ +/* We need about as many as will fit in a message; an otherwise unadorned data message is ~ 40 bytes + for a really small sample, no key hash, no status info, and message sizes are (typically) < 64kB + so we can expect not to need more than ~ 1600 xmsg at a time. Powers-of-two are nicer :) */ +#define MAX_FREELIST_SIZE 2048 + static void nn_xmsg_realfree (struct nn_xmsg *m); struct nn_xmsgpool *nn_xmsgpool_new (void) { struct nn_xmsgpool *pool; pool = ddsrt_malloc (sizeof (*pool)); - nn_freelist_init (&pool->freelist, UINT32_MAX, offsetof (struct nn_xmsg, link.older)); + nn_freelist_init (&pool->freelist, MAX_FREELIST_SIZE, offsetof (struct nn_xmsg, link.older)); return pool; } @@ -352,7 +357,8 @@ void nn_xmsg_free (struct nn_xmsg *m) unref_addrset (m->dstaddr.all.as); unref_addrset (m->dstaddr.all.as_group); } - if (!nn_freelist_push (&pool->freelist, m)) + /* Only cache the smallest xmsgs; data messages store the payload by reference and are small */ + if (m->maxsz > NN_XMSG_CHUNK_SIZE || !nn_freelist_push (&pool->freelist, m)) { nn_xmsg_realfree (m); } From c0e9f8a12212f9199610afe39e0ffcf1673f6488 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 2 May 2019 15:22:28 +0800 Subject: [PATCH 056/238] ddsperf latnecy should include median, 90% and 99% Signed-off-by: Erik Boasson --- src/tools/ddsperf/ddsperf.c | 67 ++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index 8dd8656..f93cc61 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -39,6 +39,8 @@ #define UDATA_MAGIC "DDSPerf:" #define UDATA_MAGIC_SIZE (sizeof (UDATA_MAGIC) - 1) +#define PINGPONG_RAWSIZE 20000 + enum topicsel { KS, /* KeyedSeq type: seq#, key, sequence-of-octet */ K32, /* Keyed32 type: seq#, key, array-of-24-octet (sizeof = 32) */ @@ -158,6 +160,7 @@ struct eseq_stat { uint64_t nrecv; uint64_t nlost; uint64_t nrecv_bytes; + uint32_t last_size; /* stats printer state */ uint64_t nrecv_ref; @@ -190,6 +193,7 @@ struct subthread_arg_pongstat { uint64_t min, max; uint64_t sum; uint32_t cnt; + uint64_t *raw; }; /* Pong statistics is stored in n array of npongstat entries @@ -636,6 +640,7 @@ static int check_eseq (struct eseq_admin *ea, uint32_t seq, uint32_t keyval, uin ea->stats[i].nrecv++; ea->stats[i].nrecv_bytes += size; ea->stats[i].nlost += seq - e; + ea->stats[i].last_size = size; ddsrt_mutex_unlock (&ea->lock); return seq == e; } @@ -650,6 +655,7 @@ static int check_eseq (struct eseq_admin *ea, uint32_t seq, uint32_t keyval, uin memset (&ea->stats[ea->nph], 0, sizeof (ea->stats[ea->nph])); ea->stats[ea->nph].nrecv = 1; ea->stats[ea->nph].nrecv_bytes = size; + ea->stats[ea->nph].last_size = size; ea->nph++; ddsrt_mutex_unlock (&ea->lock); return 1; @@ -694,6 +700,8 @@ static bool update_roundtrip (dds_instance_handle_t pubhandle, uint64_t tdelta, if (tdelta < x->min) x->min = tdelta; if (tdelta > x->max) x->max = tdelta; x->sum += tdelta; + if (x->cnt < PINGPONG_RAWSIZE) + x->raw[x->cnt] = tdelta; x->cnt++; ddsrt_mutex_unlock (&pongstat_lock); return allseen; @@ -704,6 +712,8 @@ static bool update_roundtrip (dds_instance_handle_t pubhandle, uint64_t tdelta, x->pphandle = get_pphandle_for_pubhandle (pubhandle); x->min = x->max = x->sum = tdelta; x->cnt = 1; + x->raw = malloc (PINGPONG_RAWSIZE * sizeof (*x->raw)); + x->raw[0] = tdelta; npongstat++; ddsrt_mutex_unlock (&pongstat_lock); return allseen; @@ -1264,6 +1274,13 @@ static void set_data_available_listener (dds_entity_t rd, const char *rd_name, d dds_delete_listener (listener); } +static int cmp_uint64 (const void *va, const void *vb) +{ + const uint64_t *a = va; + const uint64_t *b = vb; + return (*a == *b) ? 0 : (*a < *b) ? -1 : 1; +} + static void print_stats (dds_time_t tstart, dds_time_t tnow, dds_time_t tprev) { char prefix[128]; @@ -1281,6 +1298,7 @@ static void print_stats (dds_time_t tstart, dds_time_t tnow, dds_time_t tprev) { struct eseq_admin * const ea = &eseq_admin; uint64_t tot_nrecv = 0, nrecv = 0, nrecv_bytes = 0, nlost = 0; + uint32_t last_size = 0; ddsrt_mutex_lock (&ea->lock); for (uint32_t i = 0; i < ea->nph; i++) { @@ -1289,6 +1307,7 @@ static void print_stats (dds_time_t tstart, dds_time_t tnow, dds_time_t tprev) nrecv += x->nrecv - x->nrecv_ref; nlost += x->nlost - x->nlost_ref; nrecv_bytes += x->nrecv_bytes - x->nrecv_bytes_ref; + last_size = x->last_size; x->nrecv_ref = x->nrecv; x->nlost_ref = x->nlost; x->nrecv_bytes_ref = x->nrecv_bytes; @@ -1297,33 +1316,53 @@ static void print_stats (dds_time_t tstart, dds_time_t tnow, dds_time_t tprev) if (nrecv > 0) { - printf ("%s ntot %"PRIu64" delta: %"PRIu64" lost %"PRIu64" rate %.2f Mb/s\n", - prefix, tot_nrecv, nrecv, nlost, (double) nrecv_bytes * 8 * 1e3 / (double) (tnow - tprev)); + printf ("%s size %"PRIu32" ntot %"PRIu64" delta: %"PRIu64" lost %"PRIu64" rate %.2f Mb/s\n", + prefix, last_size, tot_nrecv, nrecv, nlost, (double) nrecv_bytes * 8 * 1e3 / (double) (tnow - tprev)); } } + uint64_t *newraw = malloc (PINGPONG_RAWSIZE * sizeof (*newraw)); ddsrt_mutex_lock (&pongstat_lock); for (uint32_t i = 0; i < npongstat; i++) { struct subthread_arg_pongstat * const x = &pongstat[i]; - if (x->cnt > 0) + struct subthread_arg_pongstat y = *x; + x->raw = newraw; + x->min = UINT64_MAX; + x->max = x->sum = x->cnt = 0; + /* pongstat entries get added at the end, npongstat only grows: so can safely + unlock the stats in between nodes for calculating percentiles */ + ddsrt_mutex_unlock (&pongstat_lock); + + if (y.cnt > 0) { + const uint32_t rawcnt = (y.cnt > PINGPONG_RAWSIZE) ? PINGPONG_RAWSIZE : y.cnt; + char ppinfo[128]; struct ppant *pp; ddsrt_mutex_lock (&disc_lock); - if ((pp = ddsrt_avl_lookup (&ppants_td, &ppants, &x->pphandle)) == NULL) - printf ("%s %"PRIx64" min %.3fus mean %.3fus max %.3fus cnt %"PRIu32"\n", - prefix, x->pubhandle, (double) x->min / 1e3, - (double) x->sum / (double) x->cnt / 1e3, (double) x->max / 1e3, x->cnt); + if ((pp = ddsrt_avl_lookup (&ppants_td, &ppants, &y.pphandle)) == NULL) + snprintf (ppinfo, sizeof (ppinfo), "%"PRIx64, y.pubhandle); else - printf ("%s %s:%"PRIu32" min %.3fus mean %.3fus max %.3fus cnt %"PRIu32"\n", - prefix, pp->hostname, pp->pid, (double) x->min / 1e3, - (double) x->sum / (double) x->cnt / 1e3, (double) x->max / 1e3, x->cnt); + snprintf (ppinfo, sizeof (ppinfo), "%s:%"PRIu32, pp->hostname, pp->pid); ddsrt_mutex_unlock (&disc_lock); - x->min = UINT64_MAX; - x->max = x->sum = x->cnt = 0; + + qsort (y.raw, rawcnt, sizeof (*y.raw), cmp_uint64); + printf ("%s %s mean %.3fus min %.3fus 50%% %.3fus 90%% %.3fus 99%% %.3fus max %.3fus cnt %"PRIu32"\n", + prefix, ppinfo, + (double) y.sum / (double) y.cnt / 1e3, + (double) y.min / 1e3, + (double) y.raw[rawcnt - (rawcnt + 1) / 2] / 1e3, + (double) y.raw[rawcnt - (rawcnt + 9) / 10] / 1e3, + (double) y.raw[rawcnt - (rawcnt + 99) / 100] / 1e3, + (double) y.max / 1e3, + y.cnt); } + newraw = y.raw; + + ddsrt_mutex_lock (&pongstat_lock); } ddsrt_mutex_unlock (&pongstat_lock); + free (newraw); fflush (stdout); } @@ -1644,6 +1683,10 @@ int main (int argc, char *argv[]) error3 ("-n%u invalid: topic OU has no key\n", nkeyvals); if (topicsel != KS && baggagesize != 0) error3 ("-z%u invalid: only topic KS has a sequence\n", baggagesize); + if (baggagesize != 0 && baggagesize < 12) + error3 ("-z%u invalid: too small to allow for overhead\n", baggagesize); + else if (baggagesize > 0) + baggagesize -= 12; ddsrt_avl_init (&ppants_td, &ppants); ddsrt_fibheap_init (&ppants_to_match_fhd, &ppants_to_match); From 780a494d2c09f78e75ffcd05abdfd6bfc8b9d6a9 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 2 May 2019 16:26:28 +0800 Subject: [PATCH 057/238] make ddsperf polling/waitset mode selectable again Signed-off-by: Erik Boasson --- src/tools/ddsperf/ddsperf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/ddsperf/ddsperf.c b/src/tools/ddsperf/ddsperf.c index f93cc61..cef4870 100644 --- a/src/tools/ddsperf/ddsperf.c +++ b/src/tools/ddsperf/ddsperf.c @@ -1493,7 +1493,7 @@ static int string_int_map_lookup (const struct string_int_map_elem *elems, const for (size_t i = 0; elems[i].name; i++) { if (strcmp (elems[i].name, str) == 0) - return elems[match].value; + return elems[i].value; else if (len >= 3 && strlen (elems[i].name) >= 3 && strncmp (elems[i].name, str, len) == 0) { if (match == SIZE_MAX) From baadb2b690607f9b3a606720d65e518a07e6fceb Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 4 May 2019 13:20:30 +0800 Subject: [PATCH 058/238] remove legacy configuration settings These settings all constitute settings from the long history of the DDSI stack predating Eclipse Cyclone DDS and can reasonably be presumed never to have been used in Cyclone. Their removal is therefore not expected to break backwards compatibility (which would be anyway be limited to Cyclone complaining about undefined settings at startup): * Tracing/Timestamps[@absolute]: has always been ignored * Tracing/Timestamps: has always been ignored * General/EnableLoopback: ignored for quite some time, before that changing it from the default resulted in crashes. * General/StartupModeDuration: it did what it advertised (retain data in the history caches of volatile writers as-if they were transient-local with a durability history setting of keep-last 1 for the first few seconds after startup of the DDSI stack) but had no purpose other than complicating things as the volatile readers ignored the data anyway. * General/StartupModeCoversTransient: see previous -- and besides, transient data is not supported yet in Cyclone. * Compatibility/RespondToRtiInitZeroAckWithInvalidHeartbeat: arguably a good setting given that DDSI < 2.3 explicitly requires that all HEARTBEAT messages sent by a writer advertise the existence of at least 1 sample, but this has been fixed in DDSI 2.3. As this requirement was never respected by most DDSI implementations, there is no point in retaining the setting, while it does remove a rather tricky problem immediately after writer startup involving the conjuring up of a sample that was annihilated immediately before it could have been observed. That conjuring up (as it turns out) can cause a malformed message to go out (one that is harmless in itself). Fixing the generation of that malformed message while the entire point of the trick is moot in DDSI 2.3 is a bit silly. Note that full DDSI 2.3 compliance needs a bit more work, so not bumping the DDSI protocol version number yet. * Compatibility/AckNackNumbitsEmptySet: changing it from 0 breaks compatibility with (at least) RTI Connext, and its reason for existence disappers with a fix in DDSI 2.3. * Internal/AggressiveKeepLastWhc: changing the setting from the default made no sense whatsoever in Cyclone -- it would only add flow-control and potentially block a keep-last writer where the spec forbids that. * Internal/LegacyFragmentation: a left-over from almost a decade ago when it was discovered that the specification was inconsistent in the use of the message header flags for fragmented data, and this stack for a while used the non-common interpretation. There is no reasonable way of making the two modes compatible, and this setting merely existed to deal with the compatibility issue with some ancient OpenSplice DDS version. * Durability/Encoding: historical junk. * WatchDog and Lease: never had any function in Cyclone. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_writer.c | 29 +- src/core/ddsi/include/dds/ddsi/q_config.h | 24 +- src/core/ddsi/include/dds/ddsi/q_entity.h | 3 - src/core/ddsi/include/dds/ddsi/q_globals.h | 7 - src/core/ddsi/include/dds/ddsi/q_misc.h | 2 +- src/core/ddsi/include/dds/ddsi/q_xevent.h | 1 - src/core/ddsi/src/q_config.c | 3656 ++++++++++---------- src/core/ddsi/src/q_ddsi_discovery.c | 2 +- src/core/ddsi/src/q_entity.c | 48 +- src/core/ddsi/src/q_init.c | 13 - src/core/ddsi/src/q_receive.c | 55 +- src/core/ddsi/src/q_transmit.c | 28 +- src/core/ddsi/src/q_xevent.c | 43 - 13 files changed, 1771 insertions(+), 2140 deletions(-) diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index b36bfc9..f144e35 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -313,38 +313,13 @@ dds_writer_qos_set( static struct whc *make_whc(const dds_qos_t *qos) { - bool startup_mode; bool handle_as_transient_local; unsigned hdepth, tldepth; - /* Startup mode causes the writer to treat data in its WHC as if - transient-local, for the first few seconds after startup of the - DDSI service. It is done for volatile reliable writers only - (which automatically excludes all builtin writers) or for all - writers except volatile best-effort & transient-local ones. - - Which one to use depends on whether merge policies are in effect - in durability. If yes, then durability will take care of all - transient & persistent data; if no, DDSI discovery usually takes - too long and this'll save you. - - Note: may still be cleared, if it turns out we are not maintaining - an index at all (e.g., volatile KEEP_ALL) */ - if (config.startup_mode_full) { - startup_mode = gv.startup_mode && - (qos->durability.kind >= NN_TRANSIENT_DURABILITY_QOS || - (qos->durability.kind == NN_VOLATILE_DURABILITY_QOS && - qos->reliability.kind != NN_BEST_EFFORT_RELIABILITY_QOS)); - } else { - startup_mode = gv.startup_mode && - (qos->durability.kind == NN_VOLATILE_DURABILITY_QOS && - qos->reliability.kind != NN_BEST_EFFORT_RELIABILITY_QOS); - } - /* Construct WHC -- if aggressive_keep_last1 is set, the WHC will drop all samples for which a later update is available. This forces it to maintain a tlidx. */ handle_as_transient_local = (qos->durability.kind == NN_TRANSIENT_LOCAL_DURABILITY_QOS); - if (!config.aggressive_keep_last_whc || qos->history.kind == NN_KEEP_ALL_HISTORY_QOS) + if (qos->history.kind == NN_KEEP_ALL_HISTORY_QOS) hdepth = 0; else hdepth = (unsigned)qos->history.depth; @@ -353,8 +328,6 @@ static struct whc *make_whc(const dds_qos_t *qos) tldepth = 0; else tldepth = (unsigned)qos->durability_service.history.depth; - } else if (startup_mode) { - tldepth = (hdepth == 0) ? 1 : hdepth; } else { tldepth = 0; } diff --git a/src/core/ddsi/include/dds/ddsi/q_config.h b/src/core/ddsi/include/dds/ddsi/q_config.h index c313682..50ceb51 100644 --- a/src/core/ddsi/include/dds/ddsi/q_config.h +++ b/src/core/ddsi/include/dds/ddsi/q_config.h @@ -237,7 +237,6 @@ struct config FILE *tracingOutputFile; char *tracingOutputFileName; int tracingTimestamps; - int tracingRelativeTimestamps; int tracingAppendToFile; unsigned allowMulticast; enum transport_selector transport_selector; @@ -254,7 +253,6 @@ struct config char *assumeMulticastCapable; int64_t spdp_interval; int64_t spdp_response_delay_max; - int64_t startup_mode_duration; int64_t lease_duration; int64_t const_hb_intv_sched; int64_t const_hb_intv_sched_min; @@ -263,8 +261,6 @@ struct config enum retransmit_merging retransmit_merging; int64_t retransmit_merging_period; int squash_participants; - int startup_mode_full; - int forward_all_messages; int liveliness_monitoring; int noprogress_log_stacktraces; int64_t liveliness_monitoring_interval; @@ -278,10 +274,6 @@ struct config unsigned delivery_queue_maxsamples; - int enableLoopback; - enum durability_cdr durability_cdr; - - int buggy_datafrag_flags_mode; int do_topic_discovery; uint32_t max_msg_size; @@ -298,9 +290,7 @@ struct config int tcp_use_peeraddr_for_unicast; #ifdef DDSI_INCLUDE_SSL - /* SSL support for TCP */ - int ssl_enable; int ssl_verify; int ssl_verify_client; @@ -310,17 +300,13 @@ struct config char * ssl_key_pass; char * ssl_ciphers; struct ssl_min_version ssl_min_version; - #endif /* Thread pool configuration */ - int tp_enable; uint32_t tp_threads; uint32_t tp_max_threads; - int advertise_builtin_topic_writers; - #ifdef DDSI_INCLUDE_NETWORK_CHANNELS struct config_channel_listelem *channels; struct config_channel_listelem *max_channel; /* channel with highest prio; always computed */ @@ -343,7 +329,6 @@ struct config uint32_t rmsg_chunk_size; /**<< size of a chunk in the receive buffer */ uint32_t rbuf_size; /* << size of a single receiver buffer */ enum besmode besmode; - int aggressive_keep_last_whc; int conservative_builtin_reader_startup; int meas_hb_to_ack_latency; int suppress_spdp_multicast; @@ -389,8 +374,6 @@ struct config int explicitly_publish_qos_set_to_default; enum many_sockets_mode many_sockets_mode; int arrival_of_data_asserts_pp_and_ep_liveliness; - int acknack_numbits_emptyset; - int respond_to_rti_init_zero_ack_with_invalid_heartbeat; int assume_rti_has_pmd_endpoints; int port_dg; @@ -406,14 +389,9 @@ struct config int initial_deaf; int initial_mute; int64_t initial_deaf_mute_reset; + int use_multicast_if_mreqn; struct prune_deleted_ppant prune_deleted_ppant; - - /* not used by ddsi2, only validated; user layer directly accesses - the configuration tree */ - ddsrt_sched_t watchdog_sched_class; - int32_t watchdog_sched_priority; - q__schedPrioClass watchdog_sched_priority_class; }; struct ddsi_plugin diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index f606786..4c0c4bd 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -233,8 +233,6 @@ struct writer enum writer_state state; unsigned reliable: 1; /* iff 1, writer is reliable <=> heartbeat_xevent != NULL */ unsigned handle_as_transient_local: 1; /* controls whether data is retained in WHC */ - unsigned aggressive_keep_last: 1; /* controls whether KEEP_LAST will overwrite samples that haven't been ACK'd yet */ - unsigned startup_mode: 1; /* causes data to be treated as T-L for a while */ unsigned include_keyhash: 1; /* iff 1, this writer includes a keyhash; keyless topics => include_keyhash = 0 */ unsigned retransmitting: 1; /* iff 1, this writer is currently retransmitting */ #ifdef DDSI_INCLUDE_SSM @@ -570,7 +568,6 @@ void update_proxy_writer (struct proxy_writer * pwr, struct addrset *as); int new_proxy_group (const struct nn_guid *guid, const char *name, const struct nn_xqos *xqos, nn_wctime_t timestamp); void delete_proxy_group (const struct nn_guid *guid, nn_wctime_t timestamp, int isimplicit); -void writer_exit_startup_mode (struct writer *wr); uint64_t writer_instance_id (const struct nn_guid *guid); /* Call this to empty all address sets of all writers to stop all outgoing traffic, or to diff --git a/src/core/ddsi/include/dds/ddsi/q_globals.h b/src/core/ddsi/include/dds/ddsi/q_globals.h index 517b699..857bd4c 100644 --- a/src/core/ddsi/include/dds/ddsi/q_globals.h +++ b/src/core/ddsi/include/dds/ddsi/q_globals.h @@ -223,13 +223,6 @@ struct q_globals { /* Flag cleared when stopping (receive threads). FIXME. */ int rtps_keepgoing; - /* Startup mode causes data to be treated as transient-local with - depth 1 (i.e., stored in the WHCs and regurgitated on request) to - cover the start-up delay of the discovery protocols. Because all - discovery data is shared, this is strictly a start-up issue of the - service. */ - int startup_mode; - /* Start time of the DDSI2 service, for logging relative time stamps, should I ever so desire. */ nn_wctime_t tstart; diff --git a/src/core/ddsi/include/dds/ddsi/q_misc.h b/src/core/ddsi/include/dds/ddsi/q_misc.h index dcc4224..f410ebb 100644 --- a/src/core/ddsi/include/dds/ddsi/q_misc.h +++ b/src/core/ddsi/include/dds/ddsi/q_misc.h @@ -29,7 +29,7 @@ inline nn_sequence_number_t toSN (seqno_t n) { return x; } -unsigned char normalize_data_datafrag_flags (const SubmessageHeader_t *smhdr, int datafrag_as_data); +unsigned char normalize_data_datafrag_flags (const SubmessageHeader_t *smhdr); #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS int WildcardOverlap(char * p1, char * p2); diff --git a/src/core/ddsi/include/dds/ddsi/q_xevent.h b/src/core/ddsi/include/dds/ddsi/q_xevent.h index 3ab7242..ef356f4 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xevent.h +++ b/src/core/ddsi/include/dds/ddsi/q_xevent.h @@ -61,7 +61,6 @@ DDS_EXPORT struct xevent *qxev_heartbeat (struct xeventq *evq, nn_mtime_t tsched DDS_EXPORT struct xevent *qxev_acknack (struct xeventq *evq, nn_mtime_t tsched, const nn_guid_t *pwr_guid, const nn_guid_t *rd_guid); DDS_EXPORT struct xevent *qxev_spdp (nn_mtime_t tsched, const nn_guid_t *pp_guid, const nn_guid_t *proxypp_guid); DDS_EXPORT struct xevent *qxev_pmd_update (nn_mtime_t tsched, const nn_guid_t *pp_guid); -DDS_EXPORT struct xevent *qxev_end_startup_mode (nn_mtime_t tsched); DDS_EXPORT struct xevent *qxev_delete_writer (nn_mtime_t tsched, const nn_guid_t *guid); /* cb will be called with now = T_NEVER if the event is still enqueued when when xeventq_free starts cleaning up */ diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index f3ea0a7..6c22b64 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -53,57 +53,57 @@ struct q_security_plugins q_security_plugin = { NULL, NULL, NULL, NULL, NULL, NU #endif struct unit { - const char *name; - int64_t multiplier; + const char *name; + int64_t multiplier; }; struct cfgelem { - const char *name; - const struct cfgelem *children; - const struct cfgelem *attributes; - int multiplicity; - const char *defvalue; /* NULL -> no default */ - int relative_offset; - int elem_offset; - init_fun_t init; - update_fun_t update; - free_fun_t free; - print_fun_t print; - const char *description; + const char *name; + const struct cfgelem *children; + const struct cfgelem *attributes; + int multiplicity; + const char *defvalue; /* NULL -> no default */ + int relative_offset; + int elem_offset; + init_fun_t init; + update_fun_t update; + free_fun_t free; + print_fun_t print; + const char *description; }; struct cfgst_nodekey { - const struct cfgelem *e; + const struct cfgelem *e; }; struct cfgst_node { - ddsrt_avl_node_t avlnode; - struct cfgst_nodekey key; - int count; - int failed; - int is_default; + ddsrt_avl_node_t avlnode; + struct cfgst_nodekey key; + int count; + int failed; + int is_default; }; struct cfgst { - ddsrt_avl_tree_t found; - struct config *cfg; - /* error flag set so that we can continue parsing for some errors and still fail properly */ - int error; + ddsrt_avl_tree_t found; + struct config *cfg; + /* error flag set so that we can continue parsing for some errors and still fail properly */ + int error; - /* path_depth, isattr and path together control the formatting of - error messages by cfg_error() */ - int path_depth; - int isattr[MAX_PATH_DEPTH]; - const struct cfgelem *path[MAX_PATH_DEPTH]; - void *parent[MAX_PATH_DEPTH]; + /* path_depth, isattr and path together control the formatting of + error messages by cfg_error() */ + int path_depth; + int isattr[MAX_PATH_DEPTH]; + const struct cfgelem *path[MAX_PATH_DEPTH]; + void *parent[MAX_PATH_DEPTH]; }; /* "trace" is special: it enables (nearly) everything */ static const char *logcat_names[] = { - "fatal", "error", "warning", "info", "config", "discovery", "data", "radmin", "timing", "traffic", "topic", "tcp", "plist", "whc", "throttle", "rhc", "trace", NULL + "fatal", "error", "warning", "info", "config", "discovery", "data", "radmin", "timing", "traffic", "topic", "tcp", "plist", "whc", "throttle", "rhc", "trace", NULL }; static const uint32_t logcat_codes[] = { - DDS_LC_FATAL, DDS_LC_ERROR, DDS_LC_WARNING, DDS_LC_INFO, DDS_LC_CONFIG, DDS_LC_DISCOVERY, DDS_LC_DATA, DDS_LC_RADMIN, DDS_LC_TIMING, DDS_LC_TRAFFIC, DDS_LC_TOPIC, DDS_LC_TCP, DDS_LC_PLIST, DDS_LC_WHC, DDS_LC_THROTTLE, DDS_LC_RHC, DDS_LC_ALL + DDS_LC_FATAL, DDS_LC_ERROR, DDS_LC_WARNING, DDS_LC_INFO, DDS_LC_CONFIG, DDS_LC_DISCOVERY, DDS_LC_DATA, DDS_LC_RADMIN, DDS_LC_TIMING, DDS_LC_TRAFFIC, DDS_LC_TOPIC, DDS_LC_TCP, DDS_LC_PLIST, DDS_LC_WHC, DDS_LC_THROTTLE, DDS_LC_RHC, DDS_LC_ALL }; /* "trace" is special: it enables (nearly) everything */ @@ -115,12 +115,12 @@ static const uint32_t xcheck_codes[] = { }; /* We want the tracing/verbosity settings to be fixed while parsing -the configuration, so we update this variable instead. */ + the configuration, so we update this variable instead. */ static uint32_t enabled_logcats; static int cfgst_node_cmp(const void *va, const void *vb); static const ddsrt_avl_treedef_t cfgst_found_treedef = -DDSRT_AVL_TREEDEF_INITIALIZER(offsetof(struct cfgst_node, avlnode), offsetof(struct cfgst_node, key), cfgst_node_cmp, 0); + DDSRT_AVL_TREEDEF_INITIALIZER(offsetof(struct cfgst_node, avlnode), offsetof(struct cfgst_node, key), cfgst_node_cmp, 0); #define DU(fname) static int uf_##fname (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int first, const char *value) #define PF(fname) static void pf_##fname (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, int is_default) @@ -135,7 +135,6 @@ DU(boolean_default); #if 0 PF(boolean_default); #endif -DUPF(negated_boolean); DUPF(string); DU(tracingOutputFileName); DU(verbosity); @@ -143,8 +142,8 @@ DUPF(logcat); DUPF(xcheck); DUPF(int); DUPF(uint); -DUPF(int32); #if 0 +DUPF(int32); DUPF(uint32); #endif DU(natint); @@ -162,7 +161,6 @@ PF(duration); DUPF(standards_conformance); DUPF(besmode); DUPF(retransmit_merging); -DUPF(sched_prio_class); DUPF(sched_class); DUPF(maybe_memsize); DUPF(maybe_int32); @@ -173,7 +171,6 @@ DUPF(cipher); DUPF(bandwidth); #endif DUPF(domainId); -DUPF(durability_cdr); DUPF(transport_selector); DUPF(many_sockets_mode); DU(deaf_mute); @@ -221,17 +218,16 @@ DI(if_thread_properties); #define DEPRECATED_ATTR(name) "|" name, NULL, NULL /* MOVED: whereto must be a path relative to DDSI2Service, may not be used in/for lists and only for elements, may not be chained */ #define MOVED(name, whereto) ">" name, NULL, NULL, 0, whereto, 0, 0, 0, 0, 0, 0, NULL -static const struct cfgelem timestamp_cfgattrs[] = { - { ATTR("absolute"), 1, "false", ABSOFF(tracingRelativeTimestamps), 0, uf_negated_boolean, 0, pf_negated_boolean, - "

This option has no effect

" }, - END_MARKER -}; - +#if 0 +#define BLURB(text) text +#else +#define BLURB(text) NULL +#endif static const struct cfgelem general_cfgelems[] = { - { LEAF("NetworkInterfaceAddress"), 1, "auto", ABSOFF(networkAddressString), 0, uf_networkAddress, ff_free, pf_networkAddress, - "

This element specifies the preferred network interface for use by DDSI2E. The preferred network interface determines the IP address that DDSI2E advertises in the discovery protocol (but see also General/ExternalNetworkAddress), and is also the only interface over which multicasts are transmitted. The interface can be identified by its IP address, network interface name or network portion of the address. If the value \"auto\" is entered here, DDSI2E will select what it considers the most suitable interface.

" }, - { LEAF("MulticastRecvNetworkInterfaceAddresses"), 1, "preferred", ABSOFF(networkRecvAddressStrings), 0, uf_networkAddresses, ff_networkAddresses, pf_networkAddresses, - "

This element specifies on which network interfaces DDSI2E listens to multicasts. The following options are available:

\n\ + { LEAF("NetworkInterfaceAddress"), 1, "auto", ABSOFF(networkAddressString), 0, uf_networkAddress, ff_free, pf_networkAddress, + BLURB("

This element specifies the preferred network interface for use by DDSI2E. The preferred network interface determines the IP address that DDSI2E advertises in the discovery protocol (but see also General/ExternalNetworkAddress), and is also the only interface over which multicasts are transmitted. The interface can be identified by its IP address, network interface name or network portion of the address. If the value \"auto\" is entered here, DDSI2E will select what it considers the most suitable interface.

") }, + { LEAF("MulticastRecvNetworkInterfaceAddresses"), 1, "preferred", ABSOFF(networkRecvAddressStrings), 0, uf_networkAddresses, ff_networkAddresses, pf_networkAddresses, + BLURB("

This element specifies on which network interfaces DDSI2E listens to multicasts. The following options are available:

\n\
    \n\
  • all: listen for multicasts on all multicast-capable interfaces; or
  • \n\
  • any: listen for multicasts on the operating system default interface; or
  • \n\ @@ -239,177 +235,169 @@ static const struct cfgelem general_cfgelems[] = {
  • none: does not listen for multicasts on any interface; or
  • \n\
  • a comma-separated list of network addresses: configures DDSI2E to listen for multicasts on all of the listed addresses.
  • \n\
\n\ -

If DDSI2E is in IPv6 mode and the address of the preferred network interface is a link-local address, \"all\" is treated as a synonym for \"preferred\" and a comma-separated list is treated as \"preferred\" if it contains the preferred interface and as \"none\" if not.

" }, -{ LEAF("ExternalNetworkAddress"), 1, "auto", ABSOFF(externalAddressString), 0, uf_networkAddress, ff_free, pf_networkAddress, -"

This element allows explicitly overruling the network address DDSI2E advertises in the discovery protocol, which by default is the address of the preferred network interface (General/NetworkInterfaceAddress), to allow DDSI2E to communicate across a Network Address Translation (NAT) device.

" }, -{ LEAF("ExternalNetworkMask"), 1, "0.0.0.0", ABSOFF(externalMaskString), 0, uf_string, ff_free, pf_string, -"

This element specifies the network mask of the external network address. This element is relevant only when an external network address (General/ExternalNetworkAddress) is explicitly configured. In this case locators received via the discovery protocol that are within the same external subnet (as defined by this mask) will be translated to an internal address by replacing the network portion of the external address with the corresponding portion of the preferred network interface address. This option is IPv4-only.

" }, -{ LEAF("AllowMulticast"), 1, "true", ABSOFF(allowMulticast), 0, uf_allow_multicast, 0, pf_allow_multicast, -"

This element controls whether DDSI2E uses multicasts for data traffic.

\n\ +

If DDSI2E is in IPv6 mode and the address of the preferred network interface is a link-local address, \"all\" is treated as a synonym for \"preferred\" and a comma-separated list is treated as \"preferred\" if it contains the preferred interface and as \"none\" if not.

") }, + { LEAF("ExternalNetworkAddress"), 1, "auto", ABSOFF(externalAddressString), 0, uf_networkAddress, ff_free, pf_networkAddress, + BLURB("

This element allows explicitly overruling the network address DDSI2E advertises in the discovery protocol, which by default is the address of the preferred network interface (General/NetworkInterfaceAddress), to allow DDSI2E to communicate across a Network Address Translation (NAT) device.

") }, + { LEAF("ExternalNetworkMask"), 1, "0.0.0.0", ABSOFF(externalMaskString), 0, uf_string, ff_free, pf_string, + BLURB("

This element specifies the network mask of the external network address. This element is relevant only when an external network address (General/ExternalNetworkAddress) is explicitly configured. In this case locators received via the discovery protocol that are within the same external subnet (as defined by this mask) will be translated to an internal address by replacing the network portion of the external address with the corresponding portion of the preferred network interface address. This option is IPv4-only.

") }, + { LEAF("AllowMulticast"), 1, "true", ABSOFF(allowMulticast), 0, uf_allow_multicast, 0, pf_allow_multicast, + BLURB("

This element controls whether DDSI2E uses multicasts for data traffic.

\n\

It is a comma-separated list of some of the following keywords: \"spdp\", \"asm\", \"ssm\", or either of \"false\" or \"true\".

\n\
    \n\
  • spdp: enables the use of ASM (any-source multicast) for participant discovery, joining the multicast group on the discovery socket, transmitting SPDP messages to this group, but never advertising nor using any multicast address in any discovery message, thus forcing unicast communications for all endpoint discovery and user data.
  • \n\
  • asm: enables the use of ASM for all traffic (including SPDP)
  • \n\
  • ssm: enables the use of SSM (source-specific multicast) for all non-SPDP traffic (if supported)
  • \n\
\n\ -

When set to \"false\" all multicasting is disabled. The default, \"true\" enables full use of multicasts. Listening for multicasts can be controlled by General/MulticastRecvNetworkInterfaceAddresses.

" }, -{ LEAF("MulticastTimeToLive"), 1, "32", ABSOFF(multicast_ttl), 0, uf_natint_255, 0, pf_int, -"

This element specifies the time-to-live setting for outgoing multicast packets.

" }, -{ LEAF("DontRoute"), 1, "false", ABSOFF(dontRoute), 0, uf_boolean, 0, pf_boolean, -"

This element allows setting the SO_DONTROUTE option for outgoing packets, to bypass the local routing tables. This is generally useful only when the routing tables cannot be trusted, which is highly unusual.

" }, -{ LEAF ("UseIPv6"), 1, "default", ABSOFF (compat_use_ipv6), 0, uf_boolean_default, 0, pf_nop, -"

Deprecated (use Transport instead)

" }, -{ LEAF ("Transport"), 1, "default", ABSOFF (transport_selector), 0, uf_transport_selector, 0, pf_transport_selector, -"

This element allows selecting the transport to be used (udp, udp6, tcp, tcp6, raweth)

" }, -{ LEAF("EnableMulticastLoopback"), 1, "true", ABSOFF(enableMulticastLoopback), 0, uf_boolean, 0, pf_boolean, -"

This element specifies whether DDSI2E allows IP multicast packets to be visible to all DDSI participants in the same node, including itself. It must be \"true\" for intra-node multicast communications, but if a node runs only a single DDSI2E service and does not host any other DDSI-capable programs, it should be set to \"false\" for improved performance.

" }, -{ DEPRECATED_LEAF("EnableLoopback"), 1, "false", ABSOFF(enableLoopback), 0, uf_boolean, 0, pf_boolean, -"

This element specifies whether DDSI packets are visible to all DDSI participants in the same process. It must be \"true\" for intra-process communications, i.e. a reader and writer communicating in the same address space. If enabled and using multicast then EnableMulticastLoopback must also be enabled.

" }, -{ LEAF("StartupModeDuration"), 1, "2 s", ABSOFF(startup_mode_duration), 0, uf_duration_ms_1hr, 0, pf_duration, -"

This element specifies how long the DDSI2E remains in its \"startup\" mode. While in \"startup\" mode all volatile reliable data published on the local node is retained as-if it were transient-local data, allowing existing readers on remote nodes to obtain the data even though discovering them takes some time. Best-effort data by definition need not arrive, and transient and persistent data are covered by the durability service.

\n\ -

Once the system is stable, DDSI2E keeps track of the existence of remote readers whether or not matching writers exist locally, avoiding this discovery delay and ensuring this is merely a node startup issue.

\n\ -

Setting General/StartupModeDuration to 0s will disable it.

" }, -{ LEAF("StartupModeCoversTransient"), 1, "true", ABSOFF(startup_mode_full), 0, uf_boolean, 0, pf_boolean, -"

This element configures whether startup-mode should also cover transient and persistent data, for configurations where the durability service does not take care of it. Configurations without defined merge policies best leave this enabled.

" }, -{ LEAF("MaxMessageSize"), 1, "4096 B", ABSOFF(max_msg_size), 0, uf_memsize, 0, pf_memsize, -"

This element specifies the maximum size of the UDP payload that DDSI2E will generate. DDSI2E will try to maintain this limit within the bounds of the DDSI specification, which means that in some cases (especially for very low values of MaxMessageSize) larger payloads may sporadically be observed (currently up to 1192 B).

\n\ -

On some networks it may be necessary to set this item to keep the packetsize below the MTU to prevent IP fragmentation. In those cases, it is generally advisable to also consider reducing Internal/FragmentSize.

" }, -{ LEAF("FragmentSize"), 1, "1280 B", ABSOFF(fragment_size), 0, uf_memsize, 0, pf_memsize, -"

This element specifies the size of DDSI sample fragments generated by DDSI2E. Samples larger than FragmentSize are fragmented into fragments of FragmentSize bytes each, except the last one, which may be smaller. The DDSI spec mandates a minimum fragment size of 1025 bytes, but DDSI2E will do whatever size is requested, accepting fragments of which the size is at least the minimum of 1025 and FragmentSize.

" }, -END_MARKER +

When set to \"false\" all multicasting is disabled. The default, \"true\" enables full use of multicasts. Listening for multicasts can be controlled by General/MulticastRecvNetworkInterfaceAddresses.

") }, + { LEAF("MulticastTimeToLive"), 1, "32", ABSOFF(multicast_ttl), 0, uf_natint_255, 0, pf_int, + BLURB("

This element specifies the time-to-live setting for outgoing multicast packets.

") }, + { LEAF("DontRoute"), 1, "false", ABSOFF(dontRoute), 0, uf_boolean, 0, pf_boolean, + BLURB("

This element allows setting the SO_DONTROUTE option for outgoing packets, to bypass the local routing tables. This is generally useful only when the routing tables cannot be trusted, which is highly unusual.

") }, + { LEAF ("UseIPv6"), 1, "default", ABSOFF (compat_use_ipv6), 0, uf_boolean_default, 0, pf_nop, + BLURB("

Deprecated (use Transport instead)

") }, + { LEAF ("Transport"), 1, "default", ABSOFF (transport_selector), 0, uf_transport_selector, 0, pf_transport_selector, + BLURB("

This element allows selecting the transport to be used (udp, udp6, tcp, tcp6, raweth)

") }, + { LEAF("EnableMulticastLoopback"), 1, "true", ABSOFF(enableMulticastLoopback), 0, uf_boolean, 0, pf_boolean, + BLURB("

This element specifies whether DDSI2E allows IP multicast packets to be visible to all DDSI participants in the same node, including itself. It must be \"true\" for intra-node multicast communications, but if a node runs only a single DDSI2E service and does not host any other DDSI-capable programs, it should be set to \"false\" for improved performance.

") }, + { LEAF("MaxMessageSize"), 1, "4096 B", ABSOFF(max_msg_size), 0, uf_memsize, 0, pf_memsize, + BLURB("

This element specifies the maximum size of the UDP payload that DDSI2E will generate. DDSI2E will try to maintain this limit within the bounds of the DDSI specification, which means that in some cases (especially for very low values of MaxMessageSize) larger payloads may sporadically be observed (currently up to 1192 B).

\n\ +

On some networks it may be necessary to set this item to keep the packetsize below the MTU to prevent IP fragmentation. In those cases, it is generally advisable to also consider reducing Internal/FragmentSize.

") }, + { LEAF("FragmentSize"), 1, "1280 B", ABSOFF(fragment_size), 0, uf_memsize, 0, pf_memsize, + BLURB("

This element specifies the size of DDSI sample fragments generated by DDSI2E. Samples larger than FragmentSize are fragmented into fragments of FragmentSize bytes each, except the last one, which may be smaller. The DDSI spec mandates a minimum fragment size of 1025 bytes, but DDSI2E will do whatever size is requested, accepting fragments of which the size is at least the minimum of 1025 and FragmentSize.

") }, + END_MARKER }; #ifdef DDSI_INCLUDE_ENCRYPTION static const struct cfgelem securityprofile_cfgattrs[] = { - { ATTR("Name"), 1, NULL, RELOFF(config_securityprofile_listelem, name), 0, uf_string, ff_free, pf_string, - "

This attribute specifies the name of this DDSI2E security profile. Two security profiles cannot have the same name.

" }, - { ATTR("Cipher"), 1, "null", RELOFF(config_securityprofile_listelem, cipher), 0, uf_cipher, 0, pf_cipher, - "

This attribute specifies the cipher to be used for encrypting traffic over network partitions secured by this security profile. The possible ciphers are:

\n\ + { ATTR("Name"), 1, NULL, RELOFF(config_securityprofile_listelem, name), 0, uf_string, ff_free, pf_string, + BLURB("

This attribute specifies the name of this DDSI2E security profile. Two security profiles cannot have the same name.

") }, + { ATTR("Cipher"), 1, "null", RELOFF(config_securityprofile_listelem, cipher), 0, uf_cipher, 0, pf_cipher, + BLURB("

This attribute specifies the cipher to be used for encrypting traffic over network partitions secured by this security profile. The possible ciphers are:

\n\
  • aes128: AES with a 128-bit key;
  • \n\
  • aes192: AES with a 192-bit key;
  • \n\
  • aes256: AES with a 256-bit key;
  • \n\
  • blowfish: the Blowfish cipher with a 128 bit key;
  • \n\
  • null: no encryption;
\n\ -

SHA1 is used on conjunction with all ciphers except \"null\" to ensure data integrity.

" }, -{ ATTR("CipherKey"), 1, "", RELOFF(config_securityprofile_listelem, key), 0, uf_string, ff_free, pf_key, -"

The CipherKey attribute is used to define the secret key required by the cipher selected using the Cipher attribute. The value can be a URI referencing an external file containing the secret key, or the secret key can be defined in-place as a string value.

\n\ +

SHA1 is used on conjunction with all ciphers except \"null\" to ensure data integrity.

") }, + { ATTR("CipherKey"), 1, "", RELOFF(config_securityprofile_listelem, key), 0, uf_string, ff_free, pf_key, + BLURB("

The CipherKey attribute is used to define the secret key required by the cipher selected using the Cipher attribute. The value can be a URI referencing an external file containing the secret key, or the secret key can be defined in-place as a string value.

\n\

The key must be specified as a hexadecimal string with each character representing 4 bits of the key. E.g., 1ABC represents the 16-bit key 0001 1010 1011 1100. The key should not follow a well-known pattern and must exactly match the key length of the selected cipher.

\n\

A malformed key will cause the security profile to be marked as invalid, and disable all network partitions secured by the (invalid) security profile to prevent information leaks.

\n\ -

As all DDS applications require read access to the XML configuration file, for security reasons it is recommended to store the secret key in an external file in the file system, referenced by its URI. The file should be protected against read and write access from other users on the host.

" }, -END_MARKER +

As all DDS applications require read access to the XML configuration file, for security reasons it is recommended to store the secret key in an external file in the file system, referenced by its URI. The file should be protected against read and write access from other users on the host.

") }, + END_MARKER }; static const struct cfgelem security_cfgelems[] = { - { LEAF_W_ATTRS("SecurityProfile", securityprofile_cfgattrs), 0, 0, ABSOFF(securityProfiles), if_security_profile, 0, 0, 0, - "

This element defines a DDSI2E security profile.

" }, - END_MARKER + { LEAF_W_ATTRS("SecurityProfile", securityprofile_cfgattrs), 0, 0, ABSOFF(securityProfiles), if_security_profile, 0, 0, 0, + BLURB("

This element defines a DDSI2E security profile.

") }, + END_MARKER }; #endif /* DDSI_INCLUDE_ENCRYPTION */ #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS static const struct cfgelem networkpartition_cfgattrs[] = { - { ATTR("Name"), 1, NULL, RELOFF(config_networkpartition_listelem, name), 0, uf_string, ff_free, pf_string, - "

This attribute specifies the name of this DDSI2E network partition. Two network partitions cannot have the same name.

" }, - { ATTR("Address"), 1, NULL, RELOFF(config_networkpartition_listelem, address_string), 0, uf_string, ff_free, pf_string, - "

This attribute specifies the multicast addresses associated with the network partition as a comma-separated list. Readers matching this network partition (cf. Partitioning/PartitionMappings) will listen for multicasts on all of these addresses and advertise them in the discovery protocol. The writers will select the most suitable address from the addresses advertised by the readers.

" }, - { ATTR("Connected"), 1, "true", RELOFF(config_networkpartition_listelem, connected), 0, uf_boolean, 0, pf_boolean, - "

This attribute is a placeholder.

" }, + { ATTR("Name"), 1, NULL, RELOFF(config_networkpartition_listelem, name), 0, uf_string, ff_free, pf_string, + BLURB("

This attribute specifies the name of this DDSI2E network partition. Two network partitions cannot have the same name.

") }, + { ATTR("Address"), 1, NULL, RELOFF(config_networkpartition_listelem, address_string), 0, uf_string, ff_free, pf_string, + BLURB("

This attribute specifies the multicast addresses associated with the network partition as a comma-separated list. Readers matching this network partition (cf. Partitioning/PartitionMappings) will listen for multicasts on all of these addresses and advertise them in the discovery protocol. The writers will select the most suitable address from the addresses advertised by the readers.

") }, + { ATTR("Connected"), 1, "true", RELOFF(config_networkpartition_listelem, connected), 0, uf_boolean, 0, pf_boolean, + BLURB("

This attribute is a placeholder.

") }, #ifdef DDSI_INCLUDE_ENCRYPTION - { ATTR("SecurityProfile"), 1, "null", RELOFF(config_networkpartition_listelem, profileName), 0, uf_string, ff_free, pf_string, - "

This attribute selects the DDSI2E security profile for encrypting the traffic mapped to this DDSI2E network partition. The default \"null\" means the network partition is unsecured; any other name refers to a security profile defined using the Security/SecurityProfile elements.

" }, + { ATTR("SecurityProfile"), 1, "null", RELOFF(config_networkpartition_listelem, profileName), 0, uf_string, ff_free, pf_string, + BLURB("

This attribute selects the DDSI2E security profile for encrypting the traffic mapped to this DDSI2E network partition. The default \"null\" means the network partition is unsecured; any other name refers to a security profile defined using the Security/SecurityProfile elements.

") }, #endif /* DDSI_INCLUDE_ENCRYPTION */ - END_MARKER + END_MARKER }; static const struct cfgelem networkpartitions_cfgelems[] = { - { LEAF_W_ATTRS("NetworkPartition", networkpartition_cfgattrs), 0, 0, ABSOFF(networkPartitions), if_network_partition, 0, 0, 0, - "

This element defines a DDSI2E network partition.

" }, - END_MARKER + { LEAF_W_ATTRS("NetworkPartition", networkpartition_cfgattrs), 0, 0, ABSOFF(networkPartitions), if_network_partition, 0, 0, 0, + BLURB("

This element defines a DDSI2E network partition.

") }, + END_MARKER }; static const struct cfgelem ignoredpartitions_cfgattrs[] = { - { ATTR("DCPSPartitionTopic"), 1, NULL, RELOFF(config_ignoredpartition_listelem, DCPSPartitionTopic), 0, uf_string, ff_free, pf_string, - "

This attribute specifies a partition and a topic expression, separated by a single '.', that are used to determine if a given partition and topic will be ignored or not. The expressions may use the usual wildcards '*' and '?'. DDSI2E will consider an wildcard DCPS partition to match an expression iff there exists a string that satisfies both expressions.

" }, - END_MARKER + { ATTR("DCPSPartitionTopic"), 1, NULL, RELOFF(config_ignoredpartition_listelem, DCPSPartitionTopic), 0, uf_string, ff_free, pf_string, + BLURB("

This attribute specifies a partition and a topic expression, separated by a single '.', that are used to determine if a given partition and topic will be ignored or not. The expressions may use the usual wildcards '*' and '?'. DDSI2E will consider an wildcard DCPS partition to match an expression iff there exists a string that satisfies both expressions.

") }, + END_MARKER }; static const struct cfgelem ignoredpartitions_cfgelems[] = { - { LEAF_W_ATTRS("IgnoredPartition", ignoredpartitions_cfgattrs), 0, 0, ABSOFF(ignoredPartitions), if_ignored_partition, 0, 0, 0, - "

This element can be used to prevent certain combinations of DCPS partition and topic from being transmitted over the network. DDSI2E will complete ignore readers and writers for which all DCPS partitions as well as their topic is ignored, not even creating DDSI readers and writers to mirror the DCPS ones.

" }, - END_MARKER + { LEAF_W_ATTRS("IgnoredPartition", ignoredpartitions_cfgattrs), 0, 0, ABSOFF(ignoredPartitions), if_ignored_partition, 0, 0, 0, + BLURB("

This element can be used to prevent certain combinations of DCPS partition and topic from being transmitted over the network. DDSI2E will complete ignore readers and writers for which all DCPS partitions as well as their topic is ignored, not even creating DDSI readers and writers to mirror the DCPS ones.

") }, + END_MARKER }; static const struct cfgelem partitionmappings_cfgattrs[] = { - { ATTR("NetworkPartition"), 1, NULL, RELOFF(config_partitionmapping_listelem, networkPartition), 0, uf_string, ff_free, pf_string, - "

This attribute specifies which DDSI2E network partition is to be used for DCPS partition/topic combinations matching the DCPSPartitionTopic attribute within this PartitionMapping element.

" }, - { ATTR("DCPSPartitionTopic"), 1, NULL, RELOFF(config_partitionmapping_listelem, DCPSPartitionTopic), 0, uf_string, ff_free, pf_string, - "

This attribute specifies a partition and a topic expression, separated by a single '.', that are used to determine if a given partition and topic maps to the DDSI2E network partition named by the NetworkPartition attribute in this PartitionMapping element. The expressions may use the usual wildcards '*' and '?'. DDSI2E will consider a wildcard DCPS partition to match an expression if there exists a string that satisfies both expressions.

" }, - END_MARKER + { ATTR("NetworkPartition"), 1, NULL, RELOFF(config_partitionmapping_listelem, networkPartition), 0, uf_string, ff_free, pf_string, + BLURB("

This attribute specifies which DDSI2E network partition is to be used for DCPS partition/topic combinations matching the DCPSPartitionTopic attribute within this PartitionMapping element.

") }, + { ATTR("DCPSPartitionTopic"), 1, NULL, RELOFF(config_partitionmapping_listelem, DCPSPartitionTopic), 0, uf_string, ff_free, pf_string, + BLURB("

This attribute specifies a partition and a topic expression, separated by a single '.', that are used to determine if a given partition and topic maps to the DDSI2E network partition named by the NetworkPartition attribute in this PartitionMapping element. The expressions may use the usual wildcards '*' and '?'. DDSI2E will consider a wildcard DCPS partition to match an expression if there exists a string that satisfies both expressions.

") }, + END_MARKER }; static const struct cfgelem partitionmappings_cfgelems[] = { - { LEAF_W_ATTRS("PartitionMapping", partitionmappings_cfgattrs), 0, 0, ABSOFF(partitionMappings), if_partition_mapping, 0, 0, 0, - "

This element defines a mapping from a DCPS partition/topic combination to a DDSI2E network partition. This allows partitioning data flows by using special multicast addresses for part of the data and possibly also encrypting the data flow.

" }, - END_MARKER + { LEAF_W_ATTRS("PartitionMapping", partitionmappings_cfgattrs), 0, 0, ABSOFF(partitionMappings), if_partition_mapping, 0, 0, 0, + BLURB("

This element defines a mapping from a DCPS partition/topic combination to a DDSI2E network partition. This allows partitioning data flows by using special multicast addresses for part of the data and possibly also encrypting the data flow.

") }, + END_MARKER }; static const struct cfgelem partitioning_cfgelems[] = { - { GROUP("NetworkPartitions", networkpartitions_cfgelems), - "

The NetworkPartitions element specifies the DDSI2E network partitions.

" }, - { GROUP("IgnoredPartitions", ignoredpartitions_cfgelems), - "

The IgnoredPartitions element specifies DCPS partition/topic combinations that are not distributed over the network.

" }, - { GROUP("PartitionMappings", partitionmappings_cfgelems), - "

The PartitionMappings element specifies the mapping from DCPS partition/topic combinations to DDSI2E network partitions.

" }, - END_MARKER + { GROUP("NetworkPartitions", networkpartitions_cfgelems), + BLURB("

The NetworkPartitions element specifies the DDSI2E network partitions.

") }, + { GROUP("IgnoredPartitions", ignoredpartitions_cfgelems), + BLURB("

The IgnoredPartitions element specifies DCPS partition/topic combinations that are not distributed over the network.

") }, + { GROUP("PartitionMappings", partitionmappings_cfgelems), + BLURB("

The PartitionMappings element specifies the mapping from DCPS partition/topic combinations to DDSI2E network partitions.

") }, + END_MARKER }; #endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */ #ifdef DDSI_INCLUDE_NETWORK_CHANNELS static const struct cfgelem channel_cfgelems[] = { #ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING - { LEAF("DataBandwidthLimit"), 1, "inf", RELOFF(config_channel_listelem, data_bandwidth_limit), 0, uf_bandwidth, 0, pf_bandwidth, - "

This element specifies the maximum transmit rate of new samples and directly related data, for this channel. Bandwidth limiting uses a leaky bucket scheme. The default value \"inf\" means DDSI2E imposes no limitation, the underlying operating system and hardware will likely limit the maimum transmit rate.

" }, - { LEAF("AuxiliaryBandwidthLimit"), 1, "inf", RELOFF(config_channel_listelem, auxiliary_bandwidth_limit), 0, uf_bandwidth, 0, pf_bandwidth, - "

This element specifies the maximum transmit rate of auxiliary traffic on this channel (e.g. retransmits, heartbeats, etc). Bandwidth limiting uses a leaky bucket scheme. The default value \"inf\" means DDSI2E imposes no limitation, the underlying operating system and hardware will likely limit the maimum transmit rate.

" }, + { LEAF("DataBandwidthLimit"), 1, "inf", RELOFF(config_channel_listelem, data_bandwidth_limit), 0, uf_bandwidth, 0, pf_bandwidth, + BLURB("

This element specifies the maximum transmit rate of new samples and directly related data, for this channel. Bandwidth limiting uses a leaky bucket scheme. The default value \"inf\" means DDSI2E imposes no limitation, the underlying operating system and hardware will likely limit the maimum transmit rate.

") }, + { LEAF("AuxiliaryBandwidthLimit"), 1, "inf", RELOFF(config_channel_listelem, auxiliary_bandwidth_limit), 0, uf_bandwidth, 0, pf_bandwidth, + BLURB("

This element specifies the maximum transmit rate of auxiliary traffic on this channel (e.g. retransmits, heartbeats, etc). Bandwidth limiting uses a leaky bucket scheme. The default value \"inf\" means DDSI2E imposes no limitation, the underlying operating system and hardware will likely limit the maimum transmit rate.

") }, #endif - { LEAF("DiffServField"), 1, "0", RELOFF(config_channel_listelem, diffserv_field), 0, uf_natint, 0, pf_int, - "

This element describes the DiffServ setting the channel will apply to the networking messages. This parameter determines the value of the diffserv field of the IP version 4 packets sent on this channel which allows QoS setting to be applied to the network traffic send on this channel.
\n\ + { LEAF("DiffServField"), 1, "0", RELOFF(config_channel_listelem, diffserv_field), 0, uf_natint, 0, pf_int, + BLURB("

This element describes the DiffServ setting the channel will apply to the networking messages. This parameter determines the value of the diffserv field of the IP version 4 packets sent on this channel which allows QoS setting to be applied to the network traffic send on this channel.
\n\ Windows platform support for setting the diffserv field is dependent on the OS version.
\n\ For Windows versions XP SP2 and 2003 to use the diffserv field the following parameter should be added to the register:

\n\ HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\TcpIp\\Parameters\\DisableUserTOSSetting

\n\ The type of this parameter is a DWORD and its value should be set to 0 to allow setting of the diffserv field.

\n\ For Windows version 7 or higher a new API (qWAVE) has been introduced. For these platforms the specified diffserv value is mapped to one of the support traffic types.\n\ The mapping is as follows: 1-8 background traffic; 9-40 excellent traffic; 41-55 audio/video traffic; 56 voice traffic; 57-63 control traffic.\n\ -When an application is run without Administrative priveleges then only the diffserv value of 0, 8, 40 or 56 is allowed.

" }, -END_MARKER +When an application is run without Administrative priveleges then only the diffserv value of 0, 8, 40 or 56 is allowed.

") }, + END_MARKER }; static const struct cfgelem channel_cfgattrs[] = { - { ATTR("Name"), 1, NULL, RELOFF(config_channel_listelem, name), 0, uf_string, ff_free, pf_string, - "

This attribute specifies name of this channel. The name should uniquely identify the channel.

" }, - { ATTR("TransportPriority"), 1, "0", RELOFF(config_channel_listelem, priority), 0, uf_natint, 0, pf_int, - "

This attribute sets the transport priority threshold for the channel. Each DCPS data writer has a \"transport_priority\" QoS and this QoS is used to select a channel for use by this writer. The selected channel is the one with the largest threshold not greater than the writer's transport priority, and if no such channel exists, the channel with the lowest threshold.

" }, - END_MARKER + { ATTR("Name"), 1, NULL, RELOFF(config_channel_listelem, name), 0, uf_string, ff_free, pf_string, + BLURB("

This attribute specifies name of this channel. The name should uniquely identify the channel.

") }, + { ATTR("TransportPriority"), 1, "0", RELOFF(config_channel_listelem, priority), 0, uf_natint, 0, pf_int, + BLURB("

This attribute sets the transport priority threshold for the channel. Each DCPS data writer has a \"transport_priority\" QoS and this QoS is used to select a channel for use by this writer. The selected channel is the one with the largest threshold not greater than the writer's transport priority, and if no such channel exists, the channel with the lowest threshold.

") }, + END_MARKER }; static const struct cfgelem channels_cfgelems[] = { - { MGROUP("Channel", channel_cfgelems, channel_cfgattrs), 42, 0, ABSOFF(channels), if_channel, 0, 0, 0, - "

This element defines a channel.

" }, - END_MARKER + { MGROUP("Channel", channel_cfgelems, channel_cfgattrs), 42, 0, ABSOFF(channels), if_channel, 0, 0, 0, + BLURB("

This element defines a channel.

") }, + END_MARKER }; #endif /* DDSI_INCLUDE_NETWORK_CHANNELS */ static const struct cfgelem thread_properties_sched_cfgelems[] = { - { LEAF("Class"), 1, "default", RELOFF(config_thread_properties_listelem, sched_class), 0, uf_sched_class, 0, pf_sched_class, - "

This element specifies the thread scheduling class (realtime, timeshare or default). The user may need special privileges from the underlying operating system to be able to assign some of the privileged scheduling classes.

" }, - { LEAF("Priority"), 1, "default", RELOFF(config_thread_properties_listelem, sched_priority), 0, uf_maybe_int32, 0, pf_maybe_int32, - "

This element specifies the thread priority (decimal integer or default). Only priorities that are supported by the underlying operating system can be assigned to this element. The user may need special privileges from the underlying operating system to be able to assign some of the privileged priorities.

" }, - END_MARKER + { LEAF("Class"), 1, "default", RELOFF(config_thread_properties_listelem, sched_class), 0, uf_sched_class, 0, pf_sched_class, + BLURB("

This element specifies the thread scheduling class (realtime, timeshare or default). The user may need special privileges from the underlying operating system to be able to assign some of the privileged scheduling classes.

") }, + { LEAF("Priority"), 1, "default", RELOFF(config_thread_properties_listelem, sched_priority), 0, uf_maybe_int32, 0, pf_maybe_int32, + BLURB("

This element specifies the thread priority (decimal integer or default). Only priorities that are supported by the underlying operating system can be assigned to this element. The user may need special privileges from the underlying operating system to be able to assign some of the privileged priorities.

") }, + END_MARKER }; static const struct cfgelem thread_properties_cfgattrs[] = { - { ATTR("Name"), 1, NULL, RELOFF(config_thread_properties_listelem, name), 0, uf_string, ff_free, pf_string, - "

The Name of the thread for which properties are being set. The following threads exist:

\n\ + { ATTR("Name"), 1, NULL, RELOFF(config_thread_properties_listelem, name), 0, uf_string, ff_free, pf_string, + BLURB("

The Name of the thread for which properties are being set. The following threads exist:

\n\
  • gc: garbage collector thread involved in deleting entities;
  • \n\
  • recv: receive thread, taking data from the network and running the protocol state machine;
  • \n\
  • dq.builtins: delivery thread for DDSI-builtin data, primarily for discovery;
  • \n\ @@ -417,370 +405,352 @@ static const struct cfgelem thread_properties_cfgattrs[] = {
  • tev: general timed-event handling, retransmits and discovery;
  • \n\
  • xmit.CHAN: transmit thread for channel CHAN;
  • \n\
  • dq.CHAN: delivery thread for channel CHAN;
  • \n\ -
  • tev.CHAN: timed-even thread for channel CHAN.
" }, -END_MARKER +
  • tev.CHAN: timed-even thread for channel CHAN.
  • ") }, + END_MARKER }; static const struct cfgelem thread_properties_cfgelems[] = { - { GROUP("Scheduling", thread_properties_sched_cfgelems), - "

    This element configures the scheduling properties of the thread.

    " }, - { LEAF("StackSize"), 1, "default", RELOFF(config_thread_properties_listelem, stack_size), 0, uf_maybe_memsize, 0, pf_maybe_memsize, - "

    This element configures the stack size for this thread. The default value default leaves the stack size at the operating system default.

    " }, - END_MARKER + { GROUP("Scheduling", thread_properties_sched_cfgelems), + BLURB("

    This element configures the scheduling properties of the thread.

    ") }, + { LEAF("StackSize"), 1, "default", RELOFF(config_thread_properties_listelem, stack_size), 0, uf_maybe_memsize, 0, pf_maybe_memsize, + BLURB("

    This element configures the stack size for this thread. The default value default leaves the stack size at the operating system default.

    ") }, + END_MARKER }; static const struct cfgelem threads_cfgelems[] = { - { MGROUP("Thread", thread_properties_cfgelems, thread_properties_cfgattrs), 1000, 0, ABSOFF(thread_properties), if_thread_properties, 0, 0, 0, - "

    This element is used to set thread properties.

    " }, - END_MARKER + { MGROUP("Thread", thread_properties_cfgelems, thread_properties_cfgattrs), 1000, 0, ABSOFF(thread_properties), if_thread_properties, 0, 0, 0, + BLURB("

    This element is used to set thread properties.

    ") }, + END_MARKER }; static const struct cfgelem compatibility_cfgelems[] = { - { LEAF("StandardsConformance"), 1, "lax", ABSOFF(standards_conformance), 0, uf_standards_conformance, 0, pf_standards_conformance, - "

    This element sets the level of standards conformance of this instance of the DDSI2E Service. Stricter conformance typically means less interoperability with other implementations. Currently three modes are defined:

    \n\ + { LEAF("StandardsConformance"), 1, "lax", ABSOFF(standards_conformance), 0, uf_standards_conformance, 0, pf_standards_conformance, + BLURB("

    This element sets the level of standards conformance of this instance of the DDSI2E Service. Stricter conformance typically means less interoperability with other implementations. Currently three modes are defined:

    \n\
    • pedantic: very strictly conform to the specification, ultimately for compliancy testing, but currently of little value because it adheres even to what will most likely turn out to be editing errors in the DDSI standard. Arguably, as long as no errata have been published it is the current text that is in effect, and that is what pedantic currently does.
    • \n\
    • strict: a slightly less strict view of the standard than does pedantic: it follows the established behaviour where the standard is obviously in error.
    • \n\
    • lax: attempt to provide the smoothest possible interoperability, anticipating future revisions of elements in the standard in areas that other implementations do not adhere to, even though there is no good reason not to.
    \n\ -

    The default setting is \"lax\".

    " }, -{ LEAF("ExplicitlyPublishQosSetToDefault"), 1, "false", ABSOFF(explicitly_publish_qos_set_to_default), 0, uf_boolean, 0, pf_boolean, -"

    This element specifies whether QoS settings set to default values are explicitly published in the discovery protocol. Implementations are to use the default value for QoS settings not published, which allows a significant reduction of the amount of data that needs to be exchanged for the discovery protocol, but this requires all implementations to adhere to the default values specified by the specifications.

    \n\ -

    When interoperability is required with an implementation that does not follow the specifications in this regard, setting this option to true will help.

    " }, -{ LEAF ("ManySocketsMode"), 1, "single", ABSOFF (many_sockets_mode), 0, uf_many_sockets_mode, 0, pf_many_sockets_mode, -"

    This option specifies whether a network socket will be created for each domain participant on a host. The specification seems to assume that each participant has a unique address, and setting this option will ensure this to be the case. This is not the defeault.

    \n\ -

    Disabling it slightly improves performance and reduces network traffic somewhat. It also causes the set of port numbers needed by DDSI2E to become predictable, which may be useful for firewall and NAT configuration.

    " }, -{ LEAF("ArrivalOfDataAssertsPpAndEpLiveliness"), 1, "true", ABSOFF(arrival_of_data_asserts_pp_and_ep_liveliness), 0, uf_boolean, 0, pf_boolean, -"

    When set to true, arrival of a message from a peer asserts liveliness of that peer. When set to false, only SPDP and explicit lease renewals have this effect.

    " }, -{ LEAF("AckNackNumbitsEmptySet"), 1, "0", ABSOFF(acknack_numbits_emptyset), 0, uf_natint, 0, pf_int, -"

    This element governs the representation of an acknowledgement message that does not also negatively-acknowledge some samples. If set to 0, the generated acknowledgements have an invalid form and will be reject by the strict and pedantic conformance modes, but several other implementation require this setting for smooth interoperation.

    \n\ -

    If set to 1, all acknowledgements sent by DDSI2E adhere the form of acknowledgement messages allowed by the standard, but this causes problems when interoperating with these other implementations. The strict and pedantic standards conformance modes always overrule an AckNackNumbitsEmptySet=0 to prevent the transmitting of invalid messages.

    " }, -{ LEAF("RespondToRtiInitZeroAckWithInvalidHeartbeat"), 1, "false", ABSOFF(respond_to_rti_init_zero_ack_with_invalid_heartbeat), 0, uf_boolean, 0, pf_boolean, -"

    This element allows a closer mimicking of the behaviour of some other DDSI implementations, albeit at the cost of generating even more invalid messages. Setting it to true ensures a Heartbeat can be sent at any time when a remote node requests one, setting it to false delays it until a valid one can be sent.

    \n\ -

    The latter is fully compliant with the specification, and no adverse effects have been observed. It is the default.

    " }, -{ LEAF("AssumeRtiHasPmdEndpoints"), 1, "false", ABSOFF(assume_rti_has_pmd_endpoints), 0, uf_boolean, 0, pf_boolean, -"

    This option assumes ParticipantMessageData endpoints required by the liveliness protocol are present in RTI participants even when not properly advertised by the participant discovery protocol.

    " }, -END_MARKER +

    The default setting is \"lax\".

    ") }, + { LEAF("ExplicitlyPublishQosSetToDefault"), 1, "false", ABSOFF(explicitly_publish_qos_set_to_default), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element specifies whether QoS settings set to default values are explicitly published in the discovery protocol. Implementations are to use the default value for QoS settings not published, which allows a significant reduction of the amount of data that needs to be exchanged for the discovery protocol, but this requires all implementations to adhere to the default values specified by the specifications.

    \n\ +

    When interoperability is required with an implementation that does not follow the specifications in this regard, setting this option to true will help.

    ") }, + { LEAF ("ManySocketsMode"), 1, "single", ABSOFF (many_sockets_mode), 0, uf_many_sockets_mode, 0, pf_many_sockets_mode, + BLURB("

    This option specifies whether a network socket will be created for each domain participant on a host. The specification seems to assume that each participant has a unique address, and setting this option will ensure this to be the case. This is not the defeault.

    \n\ +

    Disabling it slightly improves performance and reduces network traffic somewhat. It also causes the set of port numbers needed by DDSI2E to become predictable, which may be useful for firewall and NAT configuration.

    ") }, + { LEAF("ArrivalOfDataAssertsPpAndEpLiveliness"), 1, "true", ABSOFF(arrival_of_data_asserts_pp_and_ep_liveliness), 0, uf_boolean, 0, pf_boolean, + BLURB("

    When set to true, arrival of a message from a peer asserts liveliness of that peer. When set to false, only SPDP and explicit lease renewals have this effect.

    ") }, + { LEAF("AssumeRtiHasPmdEndpoints"), 1, "false", ABSOFF(assume_rti_has_pmd_endpoints), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This option assumes ParticipantMessageData endpoints required by the liveliness protocol are present in RTI participants even when not properly advertised by the participant discovery protocol.

    ") }, + END_MARKER }; static const struct cfgelem unsupp_test_cfgelems[] = { - { LEAF("XmitLossiness"), 1, "0", ABSOFF(xmit_lossiness), 0, uf_int, 0, pf_int, - "

    This element controls the fraction of outgoing packets to drop, specified as samples per thousand.

    " }, - END_MARKER + { LEAF("XmitLossiness"), 1, "0", ABSOFF(xmit_lossiness), 0, uf_int, 0, pf_int, + BLURB("

    This element controls the fraction of outgoing packets to drop, specified as samples per thousand.

    ") }, + END_MARKER }; static const struct cfgelem unsupp_watermarks_cfgelems[] = { - { LEAF("WhcLow"), 1, "1 kB", ABSOFF(whc_lowwater_mark), 0, uf_memsize, 0, pf_memsize, - "

    This element sets the low-water mark for the DDSI2E WHCs, expressed in bytes. A suspended writer resumes transmitting when its DDSI2E WHC shrinks to this size.

    " }, - { LEAF("WhcHigh"), 1, "100 kB", ABSOFF(whc_highwater_mark), 0, uf_memsize, 0, pf_memsize, - "

    This element sets the maximum allowed high-water mark for the DDSI2E WHCs, expressed in bytes. A writer is suspended when the WHC reaches this size.

    " }, - { LEAF("WhcHighInit"), 1, "30 kB", ABSOFF(whc_init_highwater_mark), 0, uf_maybe_memsize, 0, pf_maybe_memsize, - "

    This element sets the initial level of the high-water mark for the DDSI2E WHCs, expressed in bytes.

    " }, - { LEAF("WhcAdaptive|WhcAdaptative"), 1, "true", ABSOFF(whc_adaptive), 0, uf_boolean, 0, pf_boolean, - "

    This element controls whether DDSI2E will adapt the high-water mark to current traffic conditions, based on retransmit requests and transmit pressure.

    " }, - END_MARKER + { LEAF("WhcLow"), 1, "1 kB", ABSOFF(whc_lowwater_mark), 0, uf_memsize, 0, pf_memsize, + BLURB("

    This element sets the low-water mark for the DDSI2E WHCs, expressed in bytes. A suspended writer resumes transmitting when its DDSI2E WHC shrinks to this size.

    ") }, + { LEAF("WhcHigh"), 1, "100 kB", ABSOFF(whc_highwater_mark), 0, uf_memsize, 0, pf_memsize, + BLURB("

    This element sets the maximum allowed high-water mark for the DDSI2E WHCs, expressed in bytes. A writer is suspended when the WHC reaches this size.

    ") }, + { LEAF("WhcHighInit"), 1, "30 kB", ABSOFF(whc_init_highwater_mark), 0, uf_maybe_memsize, 0, pf_maybe_memsize, + BLURB("

    This element sets the initial level of the high-water mark for the DDSI2E WHCs, expressed in bytes.

    ") }, + { LEAF("WhcAdaptive|WhcAdaptative"), 1, "true", ABSOFF(whc_adaptive), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element controls whether DDSI2E will adapt the high-water mark to current traffic conditions, based on retransmit requests and transmit pressure.

    ") }, + END_MARKER }; static const struct cfgelem control_topic_cfgattrs[] = { - { DEPRECATED_ATTR("Enable"), 1, "false", ABSOFF(enable_control_topic), 0, uf_boolean, 0, pf_boolean, - "

    This element controls whether DDSI2E should create a topic to control DDSI2E's behaviour dynamically.

    " - }, - { DEPRECATED_ATTR("InitialReset"), 1, "inf", ABSOFF(initial_deaf_mute_reset), 0, uf_duration_inf, 0, pf_duration, - "

    This element controls after how much time an initial deaf/mute state will automatically reset.

    " - }, - END_MARKER + { DEPRECATED_ATTR("Enable"), 1, "false", ABSOFF(enable_control_topic), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element controls whether DDSI2E should create a topic to control DDSI2E's behaviour dynamically.

    ") }, + { DEPRECATED_ATTR("InitialReset"), 1, "inf", ABSOFF(initial_deaf_mute_reset), 0, uf_duration_inf, 0, pf_duration, + BLURB("

    This element controls after how much time an initial deaf/mute state will automatically reset.

    ") }, + END_MARKER }; static const struct cfgelem control_topic_cfgelems[] = { - { DEPRECATED_LEAF ("Deaf"), 1, "false", ABSOFF (initial_deaf), 0, uf_deaf_mute, 0, pf_boolean, - "

    This element controls whether DDSI2E defaults to deaf mode or to normal mode. This controls both the initial behaviour and what behaviour it auto-reverts to.

    " }, - { DEPRECATED_LEAF ("Mute"), 1, "false", ABSOFF (initial_mute), 0, uf_deaf_mute, 0, pf_boolean, - "

    This element controls whether DDSI2E defaults to mute mode or to normal mode. This controls both the initial behaviour and what behaviour it auto-reverts to.

    " }, - END_MARKER + { DEPRECATED_LEAF ("Deaf"), 1, "false", ABSOFF (initial_deaf), 0, uf_deaf_mute, 0, pf_boolean, + BLURB("

    This element controls whether DDSI2E defaults to deaf mode or to normal mode. This controls both the initial behaviour and what behaviour it auto-reverts to.

    ") }, + { DEPRECATED_LEAF ("Mute"), 1, "false", ABSOFF (initial_mute), 0, uf_deaf_mute, 0, pf_boolean, + BLURB("

    This element controls whether DDSI2E defaults to mute mode or to normal mode. This controls both the initial behaviour and what behaviour it auto-reverts to.

    ") }, + END_MARKER }; static const struct cfgelem rediscovery_blacklist_duration_attrs[] = { - { ATTR("enforce"), 1, "false", ABSOFF(prune_deleted_ppant.enforce_delay), 0, uf_boolean, 0, pf_boolean, - "

    This attribute controls whether the configured time during which recently deleted participants will not be rediscovered (i.e., \"black listed\") is enforced and following complete removal of the participant in DDSI2E, or whether it can be rediscovered earlier provided all traces of that participant have been removed already.

    " }, - END_MARKER + { ATTR("enforce"), 1, "false", ABSOFF(prune_deleted_ppant.enforce_delay), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This attribute controls whether the configured time during which recently deleted participants will not be rediscovered (i.e., \"black listed\") is enforced and following complete removal of the participant in DDSI2E, or whether it can be rediscovered earlier provided all traces of that participant have been removed already.

    ") }, + END_MARKER }; static const struct cfgelem heartbeat_interval_attrs[] = { - { ATTR ("min"), 1, "5 ms", ABSOFF (const_hb_intv_min), 0, uf_duration_inf, 0, pf_duration, - "

    This attribute sets the minimum interval that must have passed since the most recent heartbeat from a writer, before another asynchronous (not directly related to writing) will be sent.

    " }, - { ATTR ("minsched"), 1, "20 ms", ABSOFF (const_hb_intv_sched_min), 0, uf_duration_inf, 0, pf_duration, - "

    This attribute sets the minimum interval for periodic heartbeats. Other events may still cause heartbeats to go out.

    " }, - { ATTR ("max"), 1, "8 s", ABSOFF (const_hb_intv_sched_max), 0, uf_duration_inf, 0, pf_duration, - "

    This attribute sets the maximum interval for periodic heartbeats.

    " }, - END_MARKER + { ATTR ("min"), 1, "5 ms", ABSOFF (const_hb_intv_min), 0, uf_duration_inf, 0, pf_duration, + BLURB("

    This attribute sets the minimum interval that must have passed since the most recent heartbeat from a writer, before another asynchronous (not directly related to writing) will be sent.

    ") }, + { ATTR ("minsched"), 1, "20 ms", ABSOFF (const_hb_intv_sched_min), 0, uf_duration_inf, 0, pf_duration, + BLURB("

    This attribute sets the minimum interval for periodic heartbeats. Other events may still cause heartbeats to go out.

    ") }, + { ATTR ("max"), 1, "8 s", ABSOFF (const_hb_intv_sched_max), 0, uf_duration_inf, 0, pf_duration, + BLURB("

    This attribute sets the maximum interval for periodic heartbeats.

    ") }, + END_MARKER }; static const struct cfgelem liveliness_monitoring_attrs[] = { { ATTR("StackTraces"), 1, "true", ABSOFF(noprogress_log_stacktraces), 0, uf_boolean, 0, pf_boolean, - "

    This element controls whether or not to write stack traces to the DDSI2 trace when a thread fails to make progress (on select platforms only).

    " }, + BLURB("

    This element controls whether or not to write stack traces to the DDSI2 trace when a thread fails to make progress (on select platforms only).

    ") }, { ATTR("Interval"), 1, "1s", ABSOFF(liveliness_monitoring_interval), 0, uf_duration_100ms_1hr, 0, pf_duration, - "

    This element controls the interval at which to check whether threads have been making progress.

    " }, + BLURB("

    This element controls the interval at which to check whether threads have been making progress.

    ") }, END_MARKER }; static const struct cfgelem multiple_recv_threads_attrs[] = { { ATTR("maxretries"), 1, "4294967295", ABSOFF(recv_thread_stop_maxretries), 0, uf_uint, 0, pf_uint, - "

    Receive threads dedicated to a single socket can only be triggered for termination by sending a packet. Reception of any packet will do, so termination failure due to packet loss is exceedingly unlikely, but to eliminate all risks, it will retry as many times as specified by this attribute before aborting.

    " }, + BLURB("

    Receive threads dedicated to a single socket can only be triggered for termination by sending a packet. Reception of any packet will do, so termination failure due to packet loss is exceedingly unlikely, but to eliminate all risks, it will retry as many times as specified by this attribute before aborting.

    ") }, END_MARKER }; static const struct cfgelem unsupp_cfgelems[] = { - { MOVED("MaxMessageSize", "General/MaxMessageSize") }, - { MOVED("FragmentSize", "General/FragmentSize") }, - { LEAF("DeliveryQueueMaxSamples"), 1, "256", ABSOFF(delivery_queue_maxsamples), 0, uf_uint, 0, pf_uint, - "

    This element controls the Maximum size of a delivery queue, expressed in samples. Once a delivery queue is full, incoming samples destined for that queue are dropped until space becomes available again.

    " }, - { LEAF("PrimaryReorderMaxSamples"), 1, "64", ABSOFF(primary_reorder_maxsamples), 0, uf_uint, 0, pf_uint, - "

    This element sets the maximum size in samples of a primary re-order administration. Each proxy writer has one primary re-order administration to buffer the packet flow in case some packets arrive out of order. Old samples are forwarded to secondary re-order administrations associated with readers in need of historical data.

    " }, - { LEAF("SecondaryReorderMaxSamples"), 1, "16", ABSOFF(secondary_reorder_maxsamples), 0, uf_uint, 0, pf_uint, - "

    This element sets the maximum size in samples of a secondary re-order administration. The secondary re-order administration is per reader in need of historical data.

    " }, - { LEAF("DefragUnreliableMaxSamples"), 1, "4", ABSOFF(defrag_unreliable_maxsamples), 0, uf_uint, 0, pf_uint, - "

    This element sets the maximum number of samples that can be defragmented simultaneously for a best-effort writers.

    " }, - { LEAF("DefragReliableMaxSamples"), 1, "16", ABSOFF(defrag_reliable_maxsamples), 0, uf_uint, 0, pf_uint, - "

    This element sets the maximum number of samples that can be defragmented simultaneously for a reliable writer. This has to be large enough to handle retransmissions of historical data in addition to new samples.

    " }, - { LEAF("BuiltinEndpointSet"), 1, "writers", ABSOFF(besmode), 0, uf_besmode, 0, pf_besmode, - "

    This element controls which participants will have which built-in endpoints for the discovery and liveliness protocols. Valid values are:

    \n\ + { MOVED("MaxMessageSize", "General/MaxMessageSize") }, + { MOVED("FragmentSize", "General/FragmentSize") }, + { LEAF("DeliveryQueueMaxSamples"), 1, "256", ABSOFF(delivery_queue_maxsamples), 0, uf_uint, 0, pf_uint, + BLURB("

    This element controls the Maximum size of a delivery queue, expressed in samples. Once a delivery queue is full, incoming samples destined for that queue are dropped until space becomes available again.

    ") }, + { LEAF("PrimaryReorderMaxSamples"), 1, "64", ABSOFF(primary_reorder_maxsamples), 0, uf_uint, 0, pf_uint, + BLURB("

    This element sets the maximum size in samples of a primary re-order administration. Each proxy writer has one primary re-order administration to buffer the packet flow in case some packets arrive out of order. Old samples are forwarded to secondary re-order administrations associated with readers in need of historical data.

    ") }, + { LEAF("SecondaryReorderMaxSamples"), 1, "16", ABSOFF(secondary_reorder_maxsamples), 0, uf_uint, 0, pf_uint, + BLURB("

    This element sets the maximum size in samples of a secondary re-order administration. The secondary re-order administration is per reader in need of historical data.

    ") }, + { LEAF("DefragUnreliableMaxSamples"), 1, "4", ABSOFF(defrag_unreliable_maxsamples), 0, uf_uint, 0, pf_uint, + BLURB("

    This element sets the maximum number of samples that can be defragmented simultaneously for a best-effort writers.

    ") }, + { LEAF("DefragReliableMaxSamples"), 1, "16", ABSOFF(defrag_reliable_maxsamples), 0, uf_uint, 0, pf_uint, + BLURB("

    This element sets the maximum number of samples that can be defragmented simultaneously for a reliable writer. This has to be large enough to handle retransmissions of historical data in addition to new samples.

    ") }, + { LEAF("BuiltinEndpointSet"), 1, "writers", ABSOFF(besmode), 0, uf_besmode, 0, pf_besmode, + BLURB("

    This element controls which participants will have which built-in endpoints for the discovery and liveliness protocols. Valid values are:

    \n\
    • full: all participants have all endpoints;
    • \n\
    • writers: all participants have the writers, but just one has the readers;
    • \n\
    • minimal: only one participant has built-in endpoints.
    \n\ -

    The default is writers, as this is thought to be compliant and reasonably efficient. Minimal may or may not be compliant but is most efficient, and full is inefficient but certain to be compliant. See also Internal/ConservativeBuiltinReaderStartup.

    " }, -{ LEAF("AggressiveKeepLastWhc|AggressiveKeepLast1Whc"), 1, "true", ABSOFF(aggressive_keep_last_whc), 0, uf_boolean, 0, pf_boolean, -"

    This element controls whether to drop a reliable sample from a DDSI2E WHC before all readers have acknowledged it as soon as a later sample becomes available. It only affects DCPS data writers with a history QoS setting of KEEP_LAST with depth 1. The default setting, false, mimics the behaviour of the OpenSplice RT networking and is necessary to make the behaviour of wait_for_acknowledgements() consistent across the networking services.

    " }, -{ LEAF("ConservativeBuiltinReaderStartup"), 1, "false", ABSOFF(conservative_builtin_reader_startup), 0, uf_boolean, 0, pf_boolean, -"

    This element forces all DDSI2E built-in discovery-related readers to request all historical data, instead of just one for each \"topic\". There is no indication that any of the current DDSI implementations requires changing of this setting, but it is conceivable that an implementation might track which participants have been informed of the existence of endpoints and which have not been, refusing communication with those that have \"can't\" know.

    \n\ -

    Should it be necessary to hide DDSI2E's shared discovery behaviour, set this to true and Internal/BuiltinEndpointSet to full.

    " }, -{ LEAF("MeasureHbToAckLatency"), 1, "false", ABSOFF(meas_hb_to_ack_latency), 0, uf_boolean, 0, pf_boolean, -"

    This element enables heartbeat-to-ack latency among DDSI2E services by prepending timestamps to Heartbeat and AckNack messages and calculating round trip times. This is non-standard behaviour. The measured latencies are quite noisy and are currently not used anywhere.

    " }, -{ LEAF("SuppressSPDPMulticast"), 1, "false", ABSOFF(suppress_spdp_multicast), 0, uf_boolean, 0, pf_boolean, -"

    The element controls whether the mandatory multicasting of the participant discovery packets occurs. Completely disabling multicasting requires this element be set to true, and generally requires explicitly listing peers to ping for unicast discovery.

    \n\ -

    See also General/AllowMulticast.

    " }, -{ LEAF("UnicastResponseToSPDPMessages"), 1, "true", ABSOFF(unicast_response_to_spdp_messages), 0, uf_boolean, 0, pf_boolean, -"

    This element controls whether the response to a newly discovered participant is sent as a unicasted SPDP packet, instead of rescheduling the periodic multicasted one. There is no known benefit to setting this to false.

    " }, -{ LEAF("SynchronousDeliveryPriorityThreshold"), 1, "0", ABSOFF(synchronous_delivery_priority_threshold), 0, uf_int, 0, pf_int, -"

    This element controls whether samples sent by a writer with QoS settings latency_budget <= SynchronousDeliveryLatencyBound and transport_priority greater than or equal to this element's value will be delivered synchronously from the \"recv\" thread, all others will be delivered asynchronously through delivery queues. This reduces latency at the expense of aggregate bandwidth.

    " }, -{ LEAF("SynchronousDeliveryLatencyBound"), 1, "inf", ABSOFF(synchronous_delivery_latency_bound), 0, uf_duration_inf, 0, pf_duration, -"

    This element controls whether samples sent by a writer with QoS settings transport_priority >= SynchronousDeliveryPriorityThreshold and a latency_budget at most this element's value will be delivered synchronously from the \"recv\" thread, all others will be delivered asynchronously through delivery queues. This reduces latency at the expense of aggregate bandwidth.

    " }, -{ LEAF("MaxParticipants"), 1, "0", ABSOFF(max_participants), 0, uf_natint, 0, pf_int, -"

    This elements configures the maximum number of DCPS domain participants this DDSI2E instance is willing to service. 0 is unlimited.

    " }, -{ LEAF("AccelerateRexmitBlockSize"), 1, "0", ABSOFF(accelerate_rexmit_block_size), 0, uf_uint, 0, pf_uint, -"

    Proxy readers that are assumed to sill be retrieving historical data get this many samples retransmitted when they NACK something, even if some of these samples have sequence numbers outside the set covered by the NACK.

    " }, -{ LEAF("RetransmitMerging"), 1, "adaptive", ABSOFF(retransmit_merging), 0, uf_retransmit_merging, 0, pf_retransmit_merging, -"

    This elements controls the addressing and timing of retransmits. Possible values are:

    \n\ +

    The default is writers, as this is thought to be compliant and reasonably efficient. Minimal may or may not be compliant but is most efficient, and full is inefficient but certain to be compliant. See also Internal/ConservativeBuiltinReaderStartup.

    ") }, + { LEAF("ConservativeBuiltinReaderStartup"), 1, "false", ABSOFF(conservative_builtin_reader_startup), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element forces all DDSI2E built-in discovery-related readers to request all historical data, instead of just one for each \"topic\". There is no indication that any of the current DDSI implementations requires changing of this setting, but it is conceivable that an implementation might track which participants have been informed of the existence of endpoints and which have not been, refusing communication with those that have \"can't\" know.

    \n\ +

    Should it be necessary to hide DDSI2E's shared discovery behaviour, set this to true and Internal/BuiltinEndpointSet to full.

    ") }, + { LEAF("MeasureHbToAckLatency"), 1, "false", ABSOFF(meas_hb_to_ack_latency), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element enables heartbeat-to-ack latency among DDSI2E services by prepending timestamps to Heartbeat and AckNack messages and calculating round trip times. This is non-standard behaviour. The measured latencies are quite noisy and are currently not used anywhere.

    ") }, + { LEAF("SuppressSPDPMulticast"), 1, "false", ABSOFF(suppress_spdp_multicast), 0, uf_boolean, 0, pf_boolean, + BLURB("

    The element controls whether the mandatory multicasting of the participant discovery packets occurs. Completely disabling multicasting requires this element be set to true, and generally requires explicitly listing peers to ping for unicast discovery.

    \n\ +

    See also General/AllowMulticast.

    ") }, + { LEAF("UnicastResponseToSPDPMessages"), 1, "true", ABSOFF(unicast_response_to_spdp_messages), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element controls whether the response to a newly discovered participant is sent as a unicasted SPDP packet, instead of rescheduling the periodic multicasted one. There is no known benefit to setting this to false.

    ") }, + { LEAF("SynchronousDeliveryPriorityThreshold"), 1, "0", ABSOFF(synchronous_delivery_priority_threshold), 0, uf_int, 0, pf_int, + BLURB("

    This element controls whether samples sent by a writer with QoS settings latency_budget <= SynchronousDeliveryLatencyBound and transport_priority greater than or equal to this element's value will be delivered synchronously from the \"recv\" thread, all others will be delivered asynchronously through delivery queues. This reduces latency at the expense of aggregate bandwidth.

    ") }, + { LEAF("SynchronousDeliveryLatencyBound"), 1, "inf", ABSOFF(synchronous_delivery_latency_bound), 0, uf_duration_inf, 0, pf_duration, + BLURB("

    This element controls whether samples sent by a writer with QoS settings transport_priority >= SynchronousDeliveryPriorityThreshold and a latency_budget at most this element's value will be delivered synchronously from the \"recv\" thread, all others will be delivered asynchronously through delivery queues. This reduces latency at the expense of aggregate bandwidth.

    ") }, + { LEAF("MaxParticipants"), 1, "0", ABSOFF(max_participants), 0, uf_natint, 0, pf_int, + BLURB("

    This elements configures the maximum number of DCPS domain participants this DDSI2E instance is willing to service. 0 is unlimited.

    ") }, + { LEAF("AccelerateRexmitBlockSize"), 1, "0", ABSOFF(accelerate_rexmit_block_size), 0, uf_uint, 0, pf_uint, + BLURB("

    Proxy readers that are assumed to sill be retrieving historical data get this many samples retransmitted when they NACK something, even if some of these samples have sequence numbers outside the set covered by the NACK.

    ") }, + { LEAF("RetransmitMerging"), 1, "adaptive", ABSOFF(retransmit_merging), 0, uf_retransmit_merging, 0, pf_retransmit_merging, + BLURB("

    This elements controls the addressing and timing of retransmits. Possible values are:

    \n\
    • never: retransmit only to the NACK-ing reader;
    • \n \
    • adaptive: attempt to combine retransmits needed for reliability, but send historical (transient-local) data to the requesting reader only;
    • \n\
    • always: do not distinguish between different causes, always try to merge.
    \n\ -

    The default is adaptive. See also Internal/RetransmitMergingPeriod.

    " }, -{ LEAF("RetransmitMergingPeriod"), 1, "5 ms", ABSOFF(retransmit_merging_period), 0, uf_duration_us_1s, 0, pf_duration, -"

    This setting determines the size of the time window in which a NACK of some sample is ignored because a retransmit of that sample has been multicasted too recently. This setting has no effect on unicasted retransmits.

    \n\ -

    See also Internal/RetransmitMerging.

    " }, -{ LEAF_W_ATTRS("HeartbeatInterval", heartbeat_interval_attrs), 1, "100 ms", ABSOFF(const_hb_intv_sched), 0, uf_duration_inf, 0, pf_duration, - "

    This elemnents allows configuring the base interval for sending writer heartbeats and the bounds within it can vary.

    " }, -{ LEAF("MaxQueuedRexmitBytes"), 1, "50 kB", ABSOFF(max_queued_rexmit_bytes), 0, uf_memsize, 0, pf_memsize, -"

    This setting limits the maximum number of bytes queued for retransmission. The default value of 0 is unlimited unless an AuxiliaryBandwidthLimit has been set, in which case it becomes NackDelay * AuxiliaryBandwidthLimit. It must be large enough to contain the largest sample that may need to be retransmitted.

    " }, -{ LEAF("MaxQueuedRexmitMessages"), 1, "200", ABSOFF(max_queued_rexmit_msgs), 0, uf_uint, 0, pf_uint, -"

    This settings limits the maximum number of samples queued for retransmission.

    " }, -{ LEAF("LeaseDuration"), 1, "10 s", ABSOFF(lease_duration), 0, uf_duration_ms_1hr, 0, pf_duration, -"

    This setting controls the default participant lease duration.

    " }, -{ LEAF("WriterLingerDuration"), 1, "1 s", ABSOFF(writer_linger_duration), 0, uf_duration_ms_1hr, 0, pf_duration, -"

    This setting controls the maximum duration for which actual deletion of a reliable writer with unacknowledged data in its history will be postponed to provide proper reliable transmission.

    " }, -{ LEAF("MinimumSocketReceiveBufferSize"), 1, "default", ABSOFF(socket_min_rcvbuf_size), 0, uf_maybe_memsize, 0, pf_maybe_memsize, -"

    This setting controls the minimum size of socket receive buffers. The operating system provides some size receive buffer upon creation of the socket, this option can be used to increase the size of the buffer beyond that initially provided by the operating system. If the buffer size cannot be increased to the specified size, an error is reported.

    \n\ -

    The default setting is the word \"default\", which means DDSI2E will attempt to increase the buffer size to 1MB, but will silently accept a smaller buffer should that attempt fail.

    " }, -{ LEAF("MinimumSocketSendBufferSize"), 1, "64 KiB", ABSOFF(socket_min_sndbuf_size), 0, uf_memsize, 0, pf_memsize, -"

    This setting controls the minimum size of socket send buffers. This setting can only increase the size of the send buffer, if the operating system by default creates a larger buffer, it is left unchanged.

    " }, -{ LEAF("NackDelay"), 1, "10 ms", ABSOFF(nack_delay), 0, uf_duration_ms_1hr, 0, pf_duration, -"

    This setting controls the delay between receipt of a HEARTBEAT indicating missing samples and a NACK (ignored when the HEARTBEAT requires an answer). However, no NACK is sent if a NACK had been scheduled already for a response earlier than the delay requests: then that NACK will incorporate the latest information.

    " }, -{ LEAF("AutoReschedNackDelay"), 1, "1 s", ABSOFF(auto_resched_nack_delay), 0, uf_duration_inf, 0, pf_duration, -"

    This setting controls the interval with which a reader will continue NACK'ing missing samples in the absence of a response from the writer, as a protection mechanism against writers incorrectly stopping the sending of HEARTBEAT messages.

    " }, -{ LEAF("PreEmptiveAckDelay"), 1, "10 ms", ABSOFF(preemptive_ack_delay), 0, uf_duration_ms_1hr, 0, pf_duration, -"

    This setting controls the delay between the discovering a remote writer and sending a pre-emptive AckNack to discover the range of data available.

    " }, -{ LEAF("ScheduleTimeRounding"), 1, "0 ms", ABSOFF(schedule_time_rounding), 0, uf_duration_ms_1hr, 0, pf_duration, -"

    This setting allows the timing of scheduled events to be rounded up so that more events can be handled in a single cycle of the event queue. The default is 0 and causes no rounding at all, i.e. are scheduled exactly, whereas a value of 10ms would mean that events are rounded up to the nearest 10 milliseconds.

    " }, +

    The default is adaptive. See also Internal/RetransmitMergingPeriod.

    ") }, + { LEAF("RetransmitMergingPeriod"), 1, "5 ms", ABSOFF(retransmit_merging_period), 0, uf_duration_us_1s, 0, pf_duration, + BLURB("

    This setting determines the size of the time window in which a NACK of some sample is ignored because a retransmit of that sample has been multicasted too recently. This setting has no effect on unicasted retransmits.

    \n\ +

    See also Internal/RetransmitMerging.

    ") }, + { LEAF_W_ATTRS("HeartbeatInterval", heartbeat_interval_attrs), 1, "100 ms", ABSOFF(const_hb_intv_sched), 0, uf_duration_inf, 0, pf_duration, + BLURB("

    This elemnents allows configuring the base interval for sending writer heartbeats and the bounds within it can vary.

    ") }, + { LEAF("MaxQueuedRexmitBytes"), 1, "50 kB", ABSOFF(max_queued_rexmit_bytes), 0, uf_memsize, 0, pf_memsize, + BLURB("

    This setting limits the maximum number of bytes queued for retransmission. The default value of 0 is unlimited unless an AuxiliaryBandwidthLimit has been set, in which case it becomes NackDelay * AuxiliaryBandwidthLimit. It must be large enough to contain the largest sample that may need to be retransmitted.

    ") }, + { LEAF("MaxQueuedRexmitMessages"), 1, "200", ABSOFF(max_queued_rexmit_msgs), 0, uf_uint, 0, pf_uint, + BLURB("

    This settings limits the maximum number of samples queued for retransmission.

    ") }, + { LEAF("LeaseDuration"), 1, "10 s", ABSOFF(lease_duration), 0, uf_duration_ms_1hr, 0, pf_duration, + BLURB("

    This setting controls the default participant lease duration.

    ") }, + { LEAF("WriterLingerDuration"), 1, "1 s", ABSOFF(writer_linger_duration), 0, uf_duration_ms_1hr, 0, pf_duration, + BLURB("

    This setting controls the maximum duration for which actual deletion of a reliable writer with unacknowledged data in its history will be postponed to provide proper reliable transmission.

    ") }, + { LEAF("MinimumSocketReceiveBufferSize"), 1, "default", ABSOFF(socket_min_rcvbuf_size), 0, uf_maybe_memsize, 0, pf_maybe_memsize, + BLURB("

    This setting controls the minimum size of socket receive buffers. The operating system provides some size receive buffer upon creation of the socket, this option can be used to increase the size of the buffer beyond that initially provided by the operating system. If the buffer size cannot be increased to the specified size, an error is reported.

    \n\ +

    The default setting is the word \"default\", which means DDSI2E will attempt to increase the buffer size to 1MB, but will silently accept a smaller buffer should that attempt fail.

    ") }, + { LEAF("MinimumSocketSendBufferSize"), 1, "64 KiB", ABSOFF(socket_min_sndbuf_size), 0, uf_memsize, 0, pf_memsize, + BLURB("

    This setting controls the minimum size of socket send buffers. This setting can only increase the size of the send buffer, if the operating system by default creates a larger buffer, it is left unchanged.

    ") }, + { LEAF("NackDelay"), 1, "10 ms", ABSOFF(nack_delay), 0, uf_duration_ms_1hr, 0, pf_duration, + BLURB("

    This setting controls the delay between receipt of a HEARTBEAT indicating missing samples and a NACK (ignored when the HEARTBEAT requires an answer). However, no NACK is sent if a NACK had been scheduled already for a response earlier than the delay requests: then that NACK will incorporate the latest information.

    ") }, + { LEAF("AutoReschedNackDelay"), 1, "1 s", ABSOFF(auto_resched_nack_delay), 0, uf_duration_inf, 0, pf_duration, + BLURB("

    This setting controls the interval with which a reader will continue NACK'ing missing samples in the absence of a response from the writer, as a protection mechanism against writers incorrectly stopping the sending of HEARTBEAT messages.

    ") }, + { LEAF("PreEmptiveAckDelay"), 1, "10 ms", ABSOFF(preemptive_ack_delay), 0, uf_duration_ms_1hr, 0, pf_duration, + BLURB("

    This setting controls the delay between the discovering a remote writer and sending a pre-emptive AckNack to discover the range of data available.

    ") }, + { LEAF("ScheduleTimeRounding"), 1, "0 ms", ABSOFF(schedule_time_rounding), 0, uf_duration_ms_1hr, 0, pf_duration, + BLURB("

    This setting allows the timing of scheduled events to be rounded up so that more events can be handled in a single cycle of the event queue. The default is 0 and causes no rounding at all, i.e. are scheduled exactly, whereas a value of 10ms would mean that events are rounded up to the nearest 10 milliseconds.

    ") }, #ifdef DDSI_INCLUDE_BANDWIDTH_LIMITING -{ LEAF("AuxiliaryBandwidthLimit"), 1, "inf", ABSOFF(auxiliary_bandwidth_limit), 0, uf_bandwidth, 0, pf_bandwidth, -"

    This element specifies the maximum transmit rate of auxiliary traffic not bound to a specific channel, such as discovery traffic, as well as auxiliary traffic related to a certain channel if that channel has elected to share this global AuxiliaryBandwidthLimit. Bandwidth limiting uses a leaky bucket scheme. The default value \"inf\" means DDSI2E imposes no limitation, the underlying operating system and hardware will likely limit the maimum transmit rate.

    " }, + { LEAF("AuxiliaryBandwidthLimit"), 1, "inf", ABSOFF(auxiliary_bandwidth_limit), 0, uf_bandwidth, 0, pf_bandwidth, + BLURB("

    This element specifies the maximum transmit rate of auxiliary traffic not bound to a specific channel, such as discovery traffic, as well as auxiliary traffic related to a certain channel if that channel has elected to share this global AuxiliaryBandwidthLimit. Bandwidth limiting uses a leaky bucket scheme. The default value \"inf\" means DDSI2E imposes no limitation, the underlying operating system and hardware will likely limit the maimum transmit rate.

    ") }, #endif -{ LEAF("DDSI2DirectMaxThreads"), 1, "1", ABSOFF(ddsi2direct_max_threads), 0, uf_uint, 0, pf_uint, -"

    This element sets the maximum number of extra threads for an experimental, undocumented and unsupported direct mode.

    " }, -{ LEAF("SquashParticipants"), 1, "false", ABSOFF(squash_participants), 0, uf_boolean, 0, pf_boolean, -"

    This element controls whether DDSI2E advertises all the domain participants it serves in DDSI (when set to false), or rather only one domain participant (the one corresponding to the DDSI2E process; when set to true). In the latter case DDSI2E becomes the virtual owner of all readers and writers of all domain participants, dramatically reducing discovery traffic (a similar effect can be obtained by setting Internal/BuiltinEndpointSet to \"minimal\" but with less loss of information).

    " }, -{ LEAF("LegacyFragmentation"), 1, "false", ABSOFF(buggy_datafrag_flags_mode), 0, uf_boolean, 0, pf_boolean, -"

    This option enables a backwards-compatible, non-compliant setting and interpretation of the control flags in fragmented data messages. To be enabled only when requiring interoperability between compliant and non-compliant versions of DDSI2E for large messages.

    " }, -{ LEAF("SPDPResponseMaxDelay"), 1, "0 ms", ABSOFF(spdp_response_delay_max), 0, uf_duration_ms_1s, 0, pf_duration, -"

    Maximum pseudo-random delay in milliseconds between discovering a remote participant and responding to it.

    " }, -{ LEAF("LateAckMode"), 1, "false", ABSOFF(late_ack_mode), 0, uf_boolean, 0, pf_boolean, -"

    Ack a sample only when it has been delivered, instead of when committed to delivering it.

    " }, -{ LEAF("ForwardAllMessages"), 1, "false", ABSOFF(forward_all_messages), 0, uf_boolean, 0, pf_boolean, -"

    Forward all messages from a writer, rather than trying to forward each sample only once. The default of trying to forward each sample only once filters out duplicates for writers in multiple partitions under nearly all circumstances, but may still publish the odd duplicate. Note: the current implementation also can lose in contrived test cases, that publish more than 2**32 samples using a single data writer in conjunction with carefully controlled management of the writer history via cooperating local readers.

    " }, -{ LEAF("RetryOnRejectBestEffort"), 1, "false", ABSOFF(retry_on_reject_besteffort), 0, uf_boolean, 0, pf_boolean, -"

    Whether or not to locally retry pushing a received best-effort sample into the reader caches when resource limits are reached.

    " }, -{ LEAF("GenerateKeyhash"), 1, "false", ABSOFF(generate_keyhash), 0, uf_boolean, 0, pf_boolean, -"

    When true, include keyhashes in outgoing data for topics with keys.

    " }, -{ LEAF("MaxSampleSize"), 1, "2147483647 B", ABSOFF(max_sample_size), 0, uf_memsize, 0, pf_memsize, -"

    This setting controls the maximum (CDR) serialised size of samples that DDSI2E will forward in either direction. Samples larger than this are discarded with a warning.

    " }, -{ LEAF("WriteBatch"), 1, "false", ABSOFF(whc_batch), 0, uf_boolean, 0, pf_boolean, -"

    This element enables the batching of write operations. By default each write operation writes through the write cache and out onto the transport. Enabling write batching causes multiple small write operations to be aggregated within the write cache into a single larger write. This gives greater throughput at the expense of latency. Currently there is no mechanism for the write cache to automatically flush itself, so that if write batching is enabled, the application may havee to use the dds_write_flush function to ensure thta all samples are written.

    " }, -{ LEAF_W_ATTRS("LivelinessMonitoring", liveliness_monitoring_attrs), 1, "false", ABSOFF(liveliness_monitoring), 0, uf_boolean, 0, pf_boolean, -"

    This element controls whether or not implementation should internally monitor its own liveliness. If liveliness monitoring is enabled, stack traces can be dumped automatically when some thread appears to have stopped making progress.

    " }, -{ LEAF("MonitorPort"), 1, "-1", ABSOFF(monitor_port), 0, uf_int, 0, pf_int, -"

    This element allows configuring a service that dumps a text description of part the internal state to TCP clients. By default (-1), this is disabled; specifying 0 means a kernel-allocated port is used; a positive number is used as the TCP port number.

    " }, -{ LEAF("AssumeMulticastCapable"), 1, "", ABSOFF(assumeMulticastCapable), 0, uf_string, ff_free, pf_string, -"

    This element controls which network interfaces are assumed to be capable of multicasting even when the interface flags returned by the operating system state it is not (this provides a workaround for some platforms). It is a comma-separated lists of patterns (with ? and * wildcards) against which the interface names are matched.

    " }, -{ LEAF("PrioritizeRetransmit"), 1, "true", ABSOFF(prioritize_retransmit), 0, uf_boolean, 0, pf_boolean, -"

    This element controls whether retransmits are prioritized over new data, speeding up recovery.

    " }, -{ LEAF("UseMulticastIfMreqn"), 1, "0", ABSOFF(use_multicast_if_mreqn), 0, uf_int, 0, pf_int, -"

    Do not use.

    " }, -{ LEAF("SendAsync"), 1, "false", ABSOFF(xpack_send_async), 0, uf_boolean, 0, pf_boolean, -"

    This element controls whether the actual sending of packets occurs on the same thread that prepares them, or is done asynchronously by another thread.

    " }, -{ LEAF_W_ATTRS("RediscoveryBlacklistDuration", rediscovery_blacklist_duration_attrs), 1, "10s", ABSOFF(prune_deleted_ppant.delay), 0, uf_duration_inf, 0, pf_duration, -"

    This element controls for how long a remote participant that was previously deleted will remain on a blacklist to prevent rediscovery, giving the software on a node time to perform any cleanup actions it needs to do. To some extent this delay is required internally by DDSI2E, but in the default configuration with the 'enforce' attribute set to false, DDSI2E will reallow rediscovery as soon as it has cleared its internal administration. Setting it to too small a value may result in the entry being pruned from the blacklist before DDSI2E is ready, it is therefore recommended to set it to at least several seconds.

    " }, + { LEAF("DDSI2DirectMaxThreads"), 1, "1", ABSOFF(ddsi2direct_max_threads), 0, uf_uint, 0, pf_uint, + BLURB("

    This element sets the maximum number of extra threads for an experimental, undocumented and unsupported direct mode.

    ") }, + { LEAF("SquashParticipants"), 1, "false", ABSOFF(squash_participants), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element controls whether DDSI2E advertises all the domain participants it serves in DDSI (when set to false), or rather only one domain participant (the one corresponding to the DDSI2E process; when set to true). In the latter case DDSI2E becomes the virtual owner of all readers and writers of all domain participants, dramatically reducing discovery traffic (a similar effect can be obtained by setting Internal/BuiltinEndpointSet to \"minimal\" but with less loss of information).

    ") }, + { LEAF("SPDPResponseMaxDelay"), 1, "0 ms", ABSOFF(spdp_response_delay_max), 0, uf_duration_ms_1s, 0, pf_duration, + BLURB("

    Maximum pseudo-random delay in milliseconds between discovering a remote participant and responding to it.

    ") }, + { LEAF("LateAckMode"), 1, "false", ABSOFF(late_ack_mode), 0, uf_boolean, 0, pf_boolean, + BLURB("

    Ack a sample only when it has been delivered, instead of when committed to delivering it.

    ") }, + { LEAF("RetryOnRejectBestEffort"), 1, "false", ABSOFF(retry_on_reject_besteffort), 0, uf_boolean, 0, pf_boolean, + BLURB("

    Whether or not to locally retry pushing a received best-effort sample into the reader caches when resource limits are reached.

    ") }, + { LEAF("GenerateKeyhash"), 1, "false", ABSOFF(generate_keyhash), 0, uf_boolean, 0, pf_boolean, + BLURB("

    When true, include keyhashes in outgoing data for topics with keys.

    ") }, + { LEAF("MaxSampleSize"), 1, "2147483647 B", ABSOFF(max_sample_size), 0, uf_memsize, 0, pf_memsize, + BLURB("

    This setting controls the maximum (CDR) serialised size of samples that DDSI2E will forward in either direction. Samples larger than this are discarded with a warning.

    ") }, + { LEAF("WriteBatch"), 1, "false", ABSOFF(whc_batch), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element enables the batching of write operations. By default each write operation writes through the write cache and out onto the transport. Enabling write batching causes multiple small write operations to be aggregated within the write cache into a single larger write. This gives greater throughput at the expense of latency. Currently there is no mechanism for the write cache to automatically flush itself, so that if write batching is enabled, the application may havee to use the dds_write_flush function to ensure thta all samples are written.

    ") }, + { LEAF_W_ATTRS("LivelinessMonitoring", liveliness_monitoring_attrs), 1, "false", ABSOFF(liveliness_monitoring), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element controls whether or not implementation should internally monitor its own liveliness. If liveliness monitoring is enabled, stack traces can be dumped automatically when some thread appears to have stopped making progress.

    ") }, + { LEAF("MonitorPort"), 1, "-1", ABSOFF(monitor_port), 0, uf_int, 0, pf_int, + BLURB("

    This element allows configuring a service that dumps a text description of part the internal state to TCP clients. By default (-1), this is disabled; specifying 0 means a kernel-allocated port is used; a positive number is used as the TCP port number.

    ") }, + { LEAF("AssumeMulticastCapable"), 1, "", ABSOFF(assumeMulticastCapable), 0, uf_string, ff_free, pf_string, + BLURB("

    This element controls which network interfaces are assumed to be capable of multicasting even when the interface flags returned by the operating system state it is not (this provides a workaround for some platforms). It is a comma-separated lists of patterns (with ? and * wildcards) against which the interface names are matched.

    ") }, + { LEAF("PrioritizeRetransmit"), 1, "true", ABSOFF(prioritize_retransmit), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element controls whether retransmits are prioritized over new data, speeding up recovery.

    ") }, + { LEAF("UseMulticastIfMreqn"), 1, "0", ABSOFF(use_multicast_if_mreqn), 0, uf_int, 0, pf_int, + BLURB("

    Do not use.

    ") }, + { LEAF("SendAsync"), 1, "false", ABSOFF(xpack_send_async), 0, uf_boolean, 0, pf_boolean, + BLURB("

    This element controls whether the actual sending of packets occurs on the same thread that prepares them, or is done asynchronously by another thread.

    ") }, + { LEAF_W_ATTRS("RediscoveryBlacklistDuration", rediscovery_blacklist_duration_attrs), 1, "10s", ABSOFF(prune_deleted_ppant.delay), 0, uf_duration_inf, 0, pf_duration, + BLURB("

    This element controls for how long a remote participant that was previously deleted will remain on a blacklist to prevent rediscovery, giving the software on a node time to perform any cleanup actions it needs to do. To some extent this delay is required internally by DDSI2E, but in the default configuration with the 'enforce' attribute set to false, DDSI2E will reallow rediscovery as soon as it has cleared its internal administration. Setting it to too small a value may result in the entry being pruned from the blacklist before DDSI2E is ready, it is therefore recommended to set it to at least several seconds.

    ") }, { LEAF_W_ATTRS("MultipleReceiveThreads", multiple_recv_threads_attrs), 1, "true", ABSOFF(multiple_recv_threads), 0, uf_boolean, 0, pf_boolean, - "

    This element controls whether all traffic is handled by a single receive thread or whether multiple receive threads may be used to improve latency. Currently multiple receive threads are only used for connectionless transport (e.g., UDP) and ManySocketsMode not set to single (the default).

    " }, -{ MGROUP("ControlTopic", control_topic_cfgelems, control_topic_cfgattrs), 1, 0, 0, 0, 0, 0, 0, 0, -"

    The ControlTopic element allows configured whether DDSI2E provides a special control interface via a predefined topic or not.

    " }, -{ GROUP("Test", unsupp_test_cfgelems), -"

    Testing options.

    " }, -{ GROUP("Watermarks", unsupp_watermarks_cfgelems), -"

    Watermarks for flow-control.

    " }, -{ LEAF("EnableExpensiveChecks"), 1, "", ABSOFF(enabled_xchecks), 0, uf_xcheck, 0, pf_xcheck, - "

    This element enables expensive checks in builds with assertions enabled and is ignored otherwise. Recognised categories are:

    \n\ + BLURB("

    This element controls whether all traffic is handled by a single receive thread or whether multiple receive threads may be used to improve latency. Currently multiple receive threads are only used for connectionless transport (e.g., UDP) and ManySocketsMode not set to single (the default).

    ") }, + { MGROUP("ControlTopic", control_topic_cfgelems, control_topic_cfgattrs), 1, 0, 0, 0, 0, 0, 0, 0, + BLURB("

    The ControlTopic element allows configured whether DDSI2E provides a special control interface via a predefined topic or not.

    ") }, + { GROUP("Test", unsupp_test_cfgelems), + BLURB("

    Testing options.

    ") }, + { GROUP("Watermarks", unsupp_watermarks_cfgelems), + BLURB("

    Watermarks for flow-control.

    ") }, + { LEAF("EnableExpensiveChecks"), 1, "", ABSOFF(enabled_xchecks), 0, uf_xcheck, 0, pf_xcheck, + BLURB("

    This element enables expensive checks in builds with assertions enabled and is ignored otherwise. Recognised categories are:

    \n\
    ") }, diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 498e069..7765f59 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -397,10 +397,10 @@ static int known_channel_p (const struct q_globals *gv, const char *name) static int check_thread_properties (const struct q_globals *gv) { #ifdef DDSI_INCLUDE_NETWORK_CHANNELS - static const char *fixed[] = { "recv", "tev", "gc", "lease", "dq.builtins", "debmon", NULL }; + static const char *fixed[] = { "recv", "tev", "gc", "lease", "dq.builtins", "debmon", "fsm", NULL }; static const char *chanprefix[] = { "xmit.", "tev.","dq.",NULL }; #else - static const char *fixed[] = { "recv", "tev", "gc", "lease", "dq.builtins", "xmit.user", "dq.user", "debmon", NULL }; + static const char *fixed[] = { "recv", "tev", "gc", "lease", "dq.builtins", "xmit.user", "dq.user", "debmon", "fsm", NULL }; #endif const struct config_thread_properties_listelem *e; int ok = 1, i; diff --git a/src/security/core/CMakeLists.txt b/src/security/core/CMakeLists.txt index b0701e9..836bc70 100644 --- a/src/security/core/CMakeLists.txt +++ b/src/security/core/CMakeLists.txt @@ -55,3 +55,4 @@ install( COMPONENT dev) add_subdirectory(tests) +add_subdirectory(tests/plugin_loading) diff --git a/src/security/core/include/dds/security/core/dds_security_fsm.h b/src/security/core/include/dds/security/core/dds_security_fsm.h index db6374a..198c1c4 100644 --- a/src/security/core/include/dds/security/core/dds_security_fsm.h +++ b/src/security/core/include/dds/security/core/dds_security_fsm.h @@ -14,14 +14,18 @@ #define DDS_SECURITY_FSM_H #include "dds/ddsrt/time.h" -#include "dds/ddsrt/threads.h" +#include "dds/ddsi/q_globals.h" #if defined (__cplusplus) extern "C" { #endif -#define DDS_SECURITY_FSM_EVENT_AUTO (-1) -#define DDS_SECURITY_FSM_EVENT_TIMEOUT (-2) +#define DDS_SECURITY_FSM_EVENT_AUTO (-1) +#define DDS_SECURITY_FSM_EVENT_TIMEOUT (-2) +#define DDS_SECURITY_FSM_EVENT_DELETE (-3) + +struct dds_security_fsm; +struct dds_security_fsm_control; typedef enum { DDS_SECURITY_FSM_DEBUG_ACT_DISPATCH, @@ -29,13 +33,6 @@ typedef enum { DDS_SECURITY_FSM_DEBUG_ACT_HANDLING } DDS_SECURITY_FSM_DEBUG_ACT; -struct dds_security_fsm; -struct dds_security_fsm_context; - -typedef ddsrt_thread_t (*dds_security_fsm_thread_create_func)(const char *name, ddsrt_thread_routine_t f, void *arg); - -typedef void (*dds_security_fsm_thread_destroy_func)( ddsrt_thread_t tid); - /** * Template for user-defined state methods. * It is allowed to call dds_security_fsm_dispatch() from within a dispatch function. @@ -62,8 +59,7 @@ typedef struct dds_security_fsm_state { * It is not allowed to call any fsm API functions from within this * debug callback. */ -typedef void (*dds_security_fsm_debug)(struct dds_security_fsm *fsm, DDS_SECURITY_FSM_DEBUG_ACT act, - const dds_security_fsm_state *current, int event_id, void *arg); +typedef void (*dds_security_fsm_debug)(struct dds_security_fsm *fsm, DDS_SECURITY_FSM_DEBUG_ACT act, const dds_security_fsm_state *current, int event_id, void *arg); /** * Transition definitions @@ -80,34 +76,6 @@ typedef struct dds_security_fsm_transition { const dds_security_fsm_state *end; } dds_security_fsm_transition; -/** - * Create a new fsm context - * Creates an fsm context. The fsm context manages the global state of the fsm's created within - * this context. The fsm context uses a number of threads to control the state machined allocated - * to this context. A thread create callback has to be provided to created the threads in the - * context of the caller. - * - * @param thr_create_func a callback function used to created the threads used to manage - * the allocated state machines - * - * @return Returns the new fsm context on success. Null on failure. - */ -DDS_EXPORT struct dds_security_fsm_context * -dds_security_fsm_context_create( dds_security_fsm_thread_create_func thr_create_func); - -/** - * Destroys a fsm context - * The function clears the fsm context and stops the associated threads. The thread destroy - * function is called to allow the caller to free resources associated with the threads and - * to wait for the threads to exit. - * - * @param context the context to be destroyed - * @param thr_destroy_func a callback function used to wait a thread to terminate - * the allocated state machine - */ -DDS_EXPORT void -dds_security_fsm_context_destroy(struct dds_security_fsm_context *context, - dds_security_fsm_thread_destroy_func thr_destroy_func); /** * Create a new fsm @@ -121,8 +89,8 @@ dds_security_fsm_context_destroy(struct dds_security_fsm_context *context, * @return Returns the new created state machine on success. Null on failure. */ DDS_EXPORT struct dds_security_fsm * -dds_security_fsm_create(struct dds_security_fsm_context *context, - const dds_security_fsm_transition *transitions, int size, void *arg); +dds_security_fsm_create(struct dds_security_fsm_control *control, const dds_security_fsm_transition *transitions, uint32_t size, void *arg); + /** * Start a fsm @@ -164,20 +132,10 @@ dds_security_fsm_set_debug(struct dds_security_fsm *fsm, dds_security_fsm_debug * * @param fsm The state machine * @param event_id Indicate where to transisition to (outcome of current state) + * @param prio Indicates if the event has to be scheduled with priority. */ DDS_EXPORT void -dds_security_fsm_dispatch(struct dds_security_fsm *fsm, int32_t event_id); - -/** - * Dispatches the next event with priority - * Assignment for the state machine to transisiton to the next state. - * This event will be placed at the top of the event list. - * - * @param fsm The state machine - * @param event_id Indicate where to transisition to (outcome of current state) - */ -DDS_EXPORT void -dds_security_fsm_dispatch_direct(struct dds_security_fsm *fsm, int32_t event_id); +dds_security_fsm_dispatch(struct dds_security_fsm *fsm, int32_t event_id, bool prio); /** * Retrieve the current state of a given state machine @@ -190,17 +148,7 @@ DDS_EXPORT const dds_security_fsm_state* dds_security_fsm_current_state(struct dds_security_fsm *fsm); /** - * Clean the given state machine - * Cleaning up the given state machine. This will abort all timeouts for - * this state machine and remove all events from the internals. - * - * @param fsm The state machine to clean. - */ -DDS_EXPORT void -dds_security_fsm_cleanup(struct dds_security_fsm *fsm); - -/** - * Freeing the state machine. + * Free the state machine. * Stops all running timeouts and events and cleaning all memory * related to this machine. * @@ -212,11 +160,51 @@ dds_security_fsm_cleanup(struct dds_security_fsm *fsm); * not block. It will garbage collect when the event has been * handled. * - * @param fsm The state machine to free + * @param fsm The state machine to be removed */ -DDS_EXPORT void /* Implicit cleanup. */ +DDS_EXPORT void dds_security_fsm_free(struct dds_security_fsm *fsm); +/** + * Create a new fsm control context, + * The fsm control context manages the global state of the fsm's created within + * this context. The fsm control a thread to control the state machined allocated + * to this control. + * + * @param gv The global settings. + * + * @return Returns the new fsm control on success. Null on failure. + */ +DDS_EXPORT struct dds_security_fsm_control * +dds_security_fsm_control_create (struct q_globals *gv); + +/** + * Frees the fsm control and the allocated fsm's. + * A precondition is that the fsm control is stopped. + * + * @param control The fsm control to be freed. + */ +DDS_EXPORT void +dds_security_fsm_control_free(struct dds_security_fsm_control *control); + +/** + * Starts the thread that handles the events and timeouts associated + * with the fsm that are managed by this fsm control. + * + * @param control The fsm control to be started. + */ +DDS_EXPORT dds_return_t +dds_security_fsm_control_start (struct dds_security_fsm_control *control, const char *name); + +/** + * Stops the thread that handles the events and timeouts. + * + * @param control The fsm control to be started. + */ +DDS_EXPORT void +dds_security_fsm_control_stop(struct dds_security_fsm_control *control); + + #if defined (__cplusplus) } #endif diff --git a/src/security/core/src/dds_security_fsm.c b/src/security/core/src/dds_security_fsm.c index 220b017..4fa9d8e 100644 --- a/src/security/core/src/dds_security_fsm.c +++ b/src/security/core/src/dds_security_fsm.c @@ -9,91 +9,87 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ - #include #include -#include "dds/security/core/dds_security_fsm.h" -#include "dds/ddsrt/threads.h" +#include + #include "dds/ddsrt/sync.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/retcode.h" #include "dds/ddsrt/time.h" #include "dds/ddsrt/timeconv.h" -#include +#include "dds/ddsrt/fibheap.h" +#include "dds/ddsi/q_thread.h" +#include "dds/security/core/dds_security_fsm.h" -typedef struct dds_security_fsm { - const dds_security_fsm_transition *transitions; - int size; - void *arg; - const dds_security_fsm_state *current; - dds_time_t current_state_endtime; - ddsrt_atomic_uint32_t ref_cnt; - dds_security_fsm_debug debug_func; - struct dds_security_fsm_context *context; - struct dds_security_fsm *next; - struct dds_security_fsm *prev; -} dds_security_fsm; - -typedef struct fsm_event { +struct fsm_event +{ struct dds_security_fsm *fsm; int event_id; struct fsm_event *next; struct fsm_event *prev; -} fsm_event; +}; -typedef struct fsm_state_timeout { +typedef enum fsm_timeout_kind { + FSM_TIMEOUT_STATE, + FSM_TIMEOUT_OVERALL +} fsm_timeout_kind_t; + +struct fsm_timer_event +{ + ddsrt_fibheap_node_t heapnode; struct dds_security_fsm *fsm; + fsm_timeout_kind_t kind; dds_time_t endtime; -} fsm_state_timeout; +}; -typedef struct fsm_overall_timeout { - struct dds_security_fsm *fsm; - dds_time_t endtime; - dds_security_fsm_action func; - struct fsm_overall_timeout *next; - struct fsm_overall_timeout *prev; -} fsm_overall_timeout; +struct dds_security_fsm +{ + struct dds_security_fsm *next_fsm; + struct dds_security_fsm *prev_fsm; + bool active; + struct dds_security_fsm_control *control; + const dds_security_fsm_transition *transitions; + uint32_t size; + void *arg; + const dds_security_fsm_state *current; + struct fsm_timer_event state_timeout_event; + struct fsm_timer_event overall_timeout_event; + dds_security_fsm_action overall_timeout_action; + dds_security_fsm_debug debug_func; +}; -typedef struct dds_security_fsm_context { - ddsrt_thread_t fsm_tid; - ddsrt_thread_t fsm_timeout_tid; - bool fsm_teardown; - fsm_event *fsm_queue; - fsm_overall_timeout *fsm_overall_timeouts; - ddsrt_mutex_t fsm_fsms_mutex; - dds_security_fsm *fsm_fsms; - fsm_state_timeout *fsm_next_state_timeout; - ddsrt_mutex_t fsm_state_timeout_mutex; - ddsrt_cond_t fsm_event_cond; - ddsrt_mutex_t fsm_event_cond_mutex; +struct dds_security_fsm_control +{ + ddsrt_mutex_t lock; + ddsrt_cond_t cond; + struct thread_state1 *ts; + struct q_globals *gv; + struct dds_security_fsm *first_fsm; + struct dds_security_fsm *last_fsm; + struct fsm_event *event_queue; + ddsrt_fibheap_t timers; + bool running; +}; - // Overall timeout guard - ddsrt_cond_t fsm_overall_timeout_cond; - ddsrt_mutex_t fsm_overall_timeout_cond_mutex; -} dds_security_fsm_context; +static int compare_timer_event (const void *va, const void *vb); +static void fsm_delete (struct dds_security_fsm_control *control, struct dds_security_fsm *fsm); -static dds_security_fsm_context *fsm_context = NULL; +const ddsrt_fibheap_def_t timer_events_fhdef = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct fsm_timer_event, heapnode), compare_timer_event); -// Thread safe initialization of the Generic State Machine Utility -bool dds_security_fsm_initialized = false; -static ddsrt_atomic_uint32_t _fsmInitCount = DDSRT_ATOMIC_UINT32_INIT(0); +static int compare_timer_event (const void *va, const void *vb) +{ + const struct fsm_timer_event *a = va; + const struct fsm_timer_event *b = vb; + return (a->endtime == b->endtime) ? 0 : (a->endtime < b->endtime) ? -1 : 1; +} -static void fsm_dispatch(struct dds_security_fsm *fsm, int event_id, int lifo) { - fsm_event *event; - dds_security_fsm_context *context; - - assert(fsm); - - if (fsm->size < 0) { - /* This fsm is cleaned up (but probably not freed yet). - * So, ignore the new event. */ - return; - } - - context = fsm->context; - assert(context); +static void fsm_dispatch (struct dds_security_fsm *fsm, int event_id, bool lifo) +{ + struct dds_security_fsm_control *control = fsm->control; + struct fsm_event *event; if (fsm->debug_func) { fsm->debug_func(fsm, @@ -101,7 +97,7 @@ static void fsm_dispatch(struct dds_security_fsm *fsm, int event_id, int lifo) { fsm->current, event_id, fsm->arg); } - event = ddsrt_malloc(sizeof(fsm_event)); + event = ddsrt_malloc (sizeof(struct fsm_event)); event->fsm = fsm; event->event_id = event_id; event->next = NULL; @@ -109,641 +105,422 @@ static void fsm_dispatch(struct dds_security_fsm *fsm, int event_id, int lifo) { if (lifo) { /* Insert event at the top of the event list */ - if (context->fsm_queue) { - context->fsm_queue->prev = event; + if (control->event_queue) { + control->event_queue->prev = event; } - event->next = context->fsm_queue; - context->fsm_queue = event; + event->next = control->event_queue; + control->event_queue = event; } else { /* Insert FIFO event */ - if (context->fsm_queue) { - fsm_event *last = context->fsm_queue; + if (control->event_queue) { + struct fsm_event *last = control->event_queue; while (last->next != NULL ) { last = last->next; } last->next = event; event->prev = last; } else { - context->fsm_queue = event; + control->event_queue = event; } } } -static void fsm_set_next_state_timeout(dds_security_fsm_context *context, - dds_security_fsm *ignore) { - dds_security_fsm *fsm; +static void set_state_timer (struct dds_security_fsm *fsm) +{ + struct dds_security_fsm_control *control = fsm->control; - ddsrt_mutex_lock(&context->fsm_event_cond_mutex); - - // reset the current time - context->fsm_next_state_timeout->endtime = DDS_NEVER; - context->fsm_next_state_timeout->fsm = NULL; - - fsm = context->fsm_fsms; - while (fsm) { - if ((fsm->current) && (fsm->current->timeout) && (fsm != ignore)) { - // first set the endtime of this state (if not set) - if (fsm->current_state_endtime == 0) { - fsm->current_state_endtime = ddsrt_time_add_duration(dds_time(), - fsm->current->timeout); - } - // Initialize the current endtime - if (context->fsm_next_state_timeout->fsm == NULL) { - context->fsm_next_state_timeout->endtime = fsm->current_state_endtime; - context->fsm_next_state_timeout->fsm = fsm; - } else if (fsm->current_state_endtime - < context->fsm_next_state_timeout->endtime) { - context->fsm_next_state_timeout->endtime = fsm->current_state_endtime; - context->fsm_next_state_timeout->fsm = fsm; - } - } - fsm = fsm->next; + if (fsm->current && fsm->current->timeout > 0 && fsm->current->timeout != DDS_NEVER) + { + fsm->state_timeout_event.endtime = ddsrt_time_add_duration (dds_time(), fsm->current->timeout); + ddsrt_fibheap_insert (&timer_events_fhdef, &control->timers, &fsm->state_timeout_event); } - - ddsrt_mutex_unlock(&context->fsm_event_cond_mutex); + else + fsm->state_timeout_event.endtime = DDS_NEVER; } -static void fsm_state_change(fsm_event *event) { - dds_security_fsm *fsm = event->fsm; - dds_security_fsm_context *context = fsm->context; +static void clear_state_timer (struct dds_security_fsm *fsm) +{ + struct dds_security_fsm_control *control = fsm->control; + + if (fsm->current && fsm->state_timeout_event.endtime != DDS_NEVER) + ddsrt_fibheap_delete (&timer_events_fhdef, &control->timers, &fsm->state_timeout_event); +} + +static void clear_overall_timer (struct dds_security_fsm *fsm) +{ + struct dds_security_fsm_control *control = fsm->control; + + if (fsm->current && fsm->overall_timeout_event.endtime != DDS_NEVER) + ddsrt_fibheap_delete (&timer_events_fhdef, &control->timers, &fsm->overall_timeout_event); +} + +static dds_time_t first_timeout (struct dds_security_fsm_control *control) +{ + struct fsm_timer_event *min; + if ((min = ddsrt_fibheap_min (&timer_events_fhdef, &control->timers)) != NULL) + return min->endtime; + return DDS_NEVER; +} + +static void fsm_check_auto_state_change (struct dds_security_fsm *fsm) +{ + if (fsm->current) + { + uint32_t i; + + for (i = 0; i < fsm->size; i++) + { + if (fsm->transitions[i].begin == fsm->current && fsm->transitions[i].event_id == DDS_SECURITY_FSM_EVENT_AUTO) + { + fsm_dispatch (fsm, DDS_SECURITY_FSM_EVENT_AUTO, true); + break; + } + } + } +} + +static void fsm_state_change (struct dds_security_fsm_control *control, struct fsm_event *event) +{ + struct dds_security_fsm *fsm = event->fsm; int event_id = event->event_id; - int i, j; + uint32_t i; - if (fsm->debug_func) { - fsm->debug_func(fsm, DDS_SECURITY_FSM_DEBUG_ACT_HANDLING, fsm->current, event_id, - fsm->arg); - } + if (fsm->active) + { + if (fsm->debug_func) + fsm->debug_func (fsm, DDS_SECURITY_FSM_DEBUG_ACT_HANDLING, fsm->current, event_id, fsm->arg); - for (i = 0; !context->fsm_teardown && i < fsm->size; i++) { - if ((fsm->transitions[i].begin == fsm->current) - && (fsm->transitions[i].event_id == event_id)) { - /* Transition. */ - if (fsm->transitions[i].func) { - fsm->transitions[i].func(fsm, fsm->arg); - } - /* New state. */ - fsm->current = fsm->transitions[i].end; - if (fsm->current) { - if (fsm->current->func) { - fsm->current->func(fsm, fsm->arg); - } - /* Reset timeout. */ - fsm->current_state_endtime = ddsrt_time_add_duration(dds_time(), - fsm->current->timeout); - /* Check if an auto transition is to be dispatched */ - for (j = 0; j < fsm->size; j++) { - if ((fsm->transitions[j].begin == fsm->current) - && (fsm->transitions[j].event_id == DDS_SECURITY_FSM_EVENT_AUTO)) { - dds_security_fsm_dispatch_direct(fsm, DDS_SECURITY_FSM_EVENT_AUTO); - } - } + for (i = 0; i < fsm->size; i++) + { + if ((fsm->transitions[i].begin == fsm->current) && (fsm->transitions[i].event_id == event_id)) + { + clear_state_timer (fsm); + fsm->current = fsm->transitions[i].end; + set_state_timer (fsm); + + ddsrt_mutex_unlock (&control->lock); + if (fsm->transitions[i].func) + fsm->transitions[i].func (fsm, fsm->arg); + if (fsm->current && fsm->current->func) + fsm->current->func (fsm, fsm->arg); + ddsrt_mutex_lock (&control->lock); + fsm_check_auto_state_change (fsm); + break; } } } + else if (event_id == DDS_SECURITY_FSM_EVENT_DELETE) + fsm_delete (control, fsm); + } -static uint32_t -fsm_thread(void *a) { - dds_security_fsm_context *context = a; - dds_duration_t dur_to_wait; - dds_time_t now = DDS_TIME_INVALID; - fsm_event *event; +static void fsm_handle_timeout (struct dds_security_fsm_control *control, struct fsm_timer_event *timer_event) +{ + struct dds_security_fsm *fsm = timer_event->fsm; - while (!context->fsm_teardown) { - event = NULL; - - ddsrt_mutex_lock(&context->fsm_event_cond_mutex); - if (!context->fsm_queue) { - if (context->fsm_next_state_timeout->endtime == DDS_NEVER) { - dur_to_wait = DDS_NEVER; - } else { - now = dds_time(); - dur_to_wait = context->fsm_next_state_timeout->endtime - now; - } - if (dur_to_wait > 0) { - if (ddsrt_cond_waitfor(&context->fsm_event_cond, - &context->fsm_event_cond_mutex, dur_to_wait) == false) { - if (context->fsm_next_state_timeout->fsm) { - /* Next timeout could have changed. */ - if (context->fsm_next_state_timeout->endtime != DDS_NEVER - && (context->fsm_next_state_timeout->endtime - now <= 0)) { - fsm_dispatch(context->fsm_next_state_timeout->fsm, - DDS_SECURITY_FSM_EVENT_TIMEOUT, 1); - } - } - } - } else { - if (context->fsm_next_state_timeout->fsm) { - fsm_dispatch(context->fsm_next_state_timeout->fsm, - DDS_SECURITY_FSM_EVENT_TIMEOUT, 1); - } - } - } else { - event = context->fsm_queue; - context->fsm_queue = context->fsm_queue->next; - if (context->fsm_queue) { - context->fsm_queue->prev = NULL; - } - ddsrt_atomic_inc32(&(event->fsm->ref_cnt)); + if (fsm->active) + { + switch (timer_event->kind) + { + case FSM_TIMEOUT_STATE: + fsm_dispatch (fsm, DDS_SECURITY_FSM_EVENT_TIMEOUT, true); + break; + case FSM_TIMEOUT_OVERALL: + ddsrt_mutex_unlock (&control->lock); + if (fsm->overall_timeout_action) + fsm->overall_timeout_action (fsm, fsm->arg); + ddsrt_mutex_lock (&control->lock); + break; } - ddsrt_mutex_unlock(&context->fsm_event_cond_mutex); - - if (event) { - fsm_state_change(event); - if (ddsrt_atomic_dec32_nv(&(event->fsm->ref_cnt)) == 0) { - ddsrt_free(event->fsm); - } - ddsrt_free(event); - } - fsm_set_next_state_timeout(context, NULL); } + + /* mark timer event as being processed */ + timer_event->endtime = DDS_NEVER; +} + +static uint32_t handle_events (struct dds_security_fsm_control *control) +{ + struct thread_state1 * const ts1 = lookup_thread_state (); + + ddsrt_mutex_lock (&control->lock); + thread_state_awake (ts1, control->gv); + while (control->running) + { + if (control->event_queue) + { + struct fsm_event *event = control->event_queue; + + control->event_queue = event->next; + if (control->event_queue) + control->event_queue->prev = NULL; + fsm_state_change (control, event); + ddsrt_free (event); + } + else + { + dds_time_t timeout = first_timeout (control); + + if (timeout > dds_time ()) + { + thread_state_asleep (ts1); + (void)ddsrt_cond_waituntil( &control->cond, &control->lock, timeout); + thread_state_awake (ts1, control->gv); + } + else + { + struct fsm_timer_event *timer_event = ddsrt_fibheap_extract_min (&timer_events_fhdef, &control->timers); + fsm_handle_timeout (control, timer_event); + } + } + } + thread_state_asleep (ts1); + ddsrt_mutex_unlock (&control->lock); + return 0; } -static fsm_overall_timeout * -fsm_get_first_overall_timeout(dds_security_fsm_context *context) { - fsm_overall_timeout *timeout; - fsm_overall_timeout *first_timeout; - dds_time_t first_time = DDS_NEVER; +void dds_security_fsm_set_timeout (struct dds_security_fsm *fsm, dds_security_fsm_action action, dds_duration_t timeout) +{ + assert(fsm); + assert(fsm->control); + assert(timeout > 0); - timeout = context->fsm_overall_timeouts; - first_timeout = context->fsm_overall_timeouts; - while (timeout) { - if (timeout->endtime < first_time) { - first_time = timeout->endtime; - first_timeout = timeout; + ddsrt_mutex_lock (&fsm->control->lock); + if (fsm->active) + { + if (timeout != DDS_NEVER) + { + clear_overall_timer(fsm); + fsm->overall_timeout_action = action; + fsm->overall_timeout_event.endtime = ddsrt_time_add_duration(dds_time(), timeout); + ddsrt_fibheap_insert (&timer_events_fhdef, &fsm->control->timers, &fsm->overall_timeout_event); + if (fsm->overall_timeout_event.endtime < first_timeout(fsm->control)) + ddsrt_cond_signal (&fsm->control->cond); } - timeout = timeout->next; + else + clear_overall_timer (fsm); } - - return first_timeout; + ddsrt_mutex_unlock (&fsm->control->lock); } -static void fsm_remove_overall_timeout_from_list(dds_security_fsm_context *context, - fsm_overall_timeout *timeout) { - fsm_overall_timeout *tmp_next_timeout; - fsm_overall_timeout *tmp_prev_timeout; +void dds_security_fsm_dispatch (struct dds_security_fsm *fsm, int32_t event_id, bool prio) +{ + assert(fsm); + assert(fsm->control); - if (timeout) { - - tmp_next_timeout = timeout->next; - tmp_prev_timeout = timeout->prev; - if (tmp_prev_timeout) { - tmp_prev_timeout->next = tmp_next_timeout; - } - if (tmp_next_timeout) { - tmp_next_timeout->prev = tmp_prev_timeout; - } - - if (timeout == context->fsm_overall_timeouts) { - context->fsm_overall_timeouts = tmp_next_timeout; - } - - ddsrt_free(timeout); - timeout = NULL; + ddsrt_mutex_lock (&fsm->control->lock); + if (fsm->active) + { + fsm_dispatch (fsm, event_id, prio); + ddsrt_cond_signal (&fsm->control->cond); } + ddsrt_mutex_unlock (&fsm->control->lock); } -static uint32_t -fsm_run_timeout(void *arg) { - dds_security_fsm_context *context = arg; - dds_return_t result; - fsm_overall_timeout *to; - dds_time_t time_to_wait; - dds_time_t now; +const dds_security_fsm_state * dds_security_fsm_current_state (struct dds_security_fsm *fsm) +{ + const dds_security_fsm_state *state; - while (!context->fsm_teardown) { - ddsrt_mutex_lock(&context->fsm_overall_timeout_cond_mutex); - to = fsm_get_first_overall_timeout(context); - if (to) { - struct dds_security_fsm *fsm = to->fsm; - ddsrt_atomic_inc32(&(fsm->ref_cnt)); + assert(fsm); + assert(fsm->active); - result = DDS_RETCODE_TIMEOUT; - now = dds_time(); - if (to->endtime > now) { - time_to_wait = to->endtime - now; - result = ddsrt_cond_waitfor(&context->fsm_overall_timeout_cond, - &context->fsm_overall_timeout_cond_mutex, time_to_wait); - } + ddsrt_mutex_lock (&fsm->control->lock); + state = fsm->current; + ddsrt_mutex_unlock (&fsm->control->lock); - if (result == DDS_RETCODE_TIMEOUT) { - /* Prevent calling timeout when the fsm has been cleaned. */ - dds_security_fsm_action func = to->func; - fsm_remove_overall_timeout_from_list(context, to); - if (fsm->size > 0) { - ddsrt_mutex_unlock(&context->fsm_overall_timeout_cond_mutex); - func(fsm, fsm->arg); - ddsrt_mutex_lock(&context->fsm_overall_timeout_cond_mutex); - } - } - - if (ddsrt_atomic_dec32_nv(&(fsm->ref_cnt)) == 0) { - ddsrt_free(fsm); - } - } else { - ddsrt_cond_wait(&context->fsm_overall_timeout_cond, - &context->fsm_overall_timeout_cond_mutex); - } - ddsrt_mutex_unlock(&context->fsm_overall_timeout_cond_mutex); - } - return 0; + return state; } -static void fsm_remove_fsm_list(dds_security_fsm *fsm) { - dds_security_fsm_context *context; - dds_security_fsm *tmp_next_fsm; - dds_security_fsm *tmp_prev_fsm; +void dds_security_fsm_set_debug (struct dds_security_fsm *fsm, dds_security_fsm_debug func) +{ + assert(fsm); - if (fsm) { - context = fsm->context; - - ddsrt_mutex_lock(&context->fsm_fsms_mutex); - tmp_next_fsm = fsm->next; - tmp_prev_fsm = fsm->prev; - if (tmp_prev_fsm) { - tmp_prev_fsm->next = tmp_next_fsm; - } - if (tmp_next_fsm) { - tmp_next_fsm->prev = tmp_prev_fsm; - } - if (fsm == context->fsm_fsms) { - context->fsm_fsms = tmp_next_fsm; - } - ddsrt_mutex_unlock(&context->fsm_fsms_mutex); - - ddsrt_mutex_lock(&context->fsm_overall_timeout_cond_mutex); - ddsrt_cond_signal(&context->fsm_overall_timeout_cond); - ddsrt_mutex_unlock(&context->fsm_overall_timeout_cond_mutex); - } + ddsrt_mutex_lock (&fsm->control->lock); + fsm->debug_func = func; + ddsrt_mutex_unlock (&fsm->control->lock); } -static ddsrt_thread_t fsm_thread_create( const char *name, - ddsrt_thread_routine_t f, void *arg) { - ddsrt_thread_t tid; - ddsrt_threadattr_t threadAttr; +static bool fsm_validate (const dds_security_fsm_transition *transitions, uint32_t size) +{ + uint32_t i; - ddsrt_threadattr_init(&threadAttr); - if (ddsrt_thread_create(&tid, name, &threadAttr, f, arg) != DDS_RETCODE_OK) { - memset(&tid, 0, sizeof(ddsrt_thread_t)); - } - return tid; -} -#ifdef AT_PROC_EXIT_IMPLEMENTED -static void fsm_thread_destroy( ddsrt_thread_t tid) { - uint32_t thread_result; - - (void) ddsrt_thread_join( tid, &thread_result); -} -#endif - -struct dds_security_fsm_context * -dds_security_fsm_context_create( dds_security_fsm_thread_create_func thr_create_func) { - struct dds_security_fsm_context *context; - - context = ddsrt_malloc(sizeof(*context)); - - context->fsm_next_state_timeout = ddsrt_malloc(sizeof(fsm_state_timeout)); - context->fsm_next_state_timeout->endtime = DDS_NEVER; - context->fsm_next_state_timeout->fsm = NULL; - - context->fsm_teardown = false; - context->fsm_queue = NULL; - context->fsm_overall_timeouts = NULL; - context->fsm_fsms = NULL; - - (void) ddsrt_mutex_init( &context->fsm_fsms_mutex ); - - // Overall timeout guard - (void) ddsrt_mutex_init( &context->fsm_overall_timeout_cond_mutex ); - (void) ddsrt_cond_init( &context->fsm_overall_timeout_cond ); - - // State timeouts - (void) ddsrt_mutex_init(&context->fsm_state_timeout_mutex ); - - // Events - (void) ddsrt_mutex_init(&context->fsm_event_cond_mutex ); - (void) ddsrt_cond_init(&context->fsm_event_cond ); - - context->fsm_tid = thr_create_func( "dds_security_fsm", fsm_thread, context); - context->fsm_timeout_tid = thr_create_func( "dds_security_fsm_timeout", - fsm_run_timeout, context); - - return context; -} - -void dds_security_fsm_context_destroy(dds_security_fsm_context *context, - dds_security_fsm_thread_destroy_func thr_destroy_func) { - if (context) { - context->fsm_teardown = true; - - ddsrt_mutex_lock( &context->fsm_overall_timeout_cond_mutex); - ddsrt_cond_signal( &context->fsm_overall_timeout_cond); - ddsrt_mutex_unlock( &context->fsm_overall_timeout_cond_mutex); - - ddsrt_mutex_lock(&context->fsm_event_cond_mutex); - ddsrt_cond_signal(&context->fsm_event_cond); - ddsrt_mutex_unlock(&context->fsm_event_cond_mutex); - - thr_destroy_func( context->fsm_tid); - ddsrt_mutex_destroy(&context->fsm_event_cond_mutex); - ddsrt_cond_destroy(&context->fsm_event_cond); - - thr_destroy_func( context->fsm_timeout_tid); - ddsrt_mutex_destroy(&context->fsm_fsms_mutex); - ddsrt_mutex_destroy(&context->fsm_overall_timeout_cond_mutex); - ddsrt_cond_destroy(&context->fsm_overall_timeout_cond); - - ddsrt_free(context->fsm_next_state_timeout); - } -} -#ifdef AT_PROC_EXIT_IMPLEMENTED -static void fsm_fini(void) { - dds_security_fsm_context_destroy(fsm_context, NULL, fsm_thread_destroy); - - /* os_osExit(); ???? */ -} - -#endif -static bool fsm_init_once(void) { - bool ret = true; - uint32_t initCount; - - initCount = ddsrt_atomic_inc32_nv(&_fsmInitCount); - - if (initCount == 1) { - assert( dds_security_fsm_initialized == false ); - - /* ddsrt_osInit(); ??? */ - - fsm_context = dds_security_fsm_context_create( fsm_thread_create); - - if (fsm_context) { - /* os_procAtExit( fsm_fini ); ??? */ - dds_security_fsm_initialized = true; - } else { - ret = false; - } - } else { - if (dds_security_fsm_initialized == false) { - /* Another thread is currently initializing the fsm. Since - * both results (osr_fsm and osr_timeout) should be ddsrt_resultSuccess - * a sleep is performed, to ensure that (if succeeded) successive - * init calls will also actually pass. - */ - dds_sleepfor( DDS_MSECS( 100 )); - } - if (dds_security_fsm_initialized == false) { - /* Initialization did not succeed, undo increment and return error */ - initCount = ddsrt_atomic_dec32_nv(&_fsmInitCount); - ret = false; - } - } - return ret; -} - -static int /* 1 = ok, other = error */ -fsm_validate(const dds_security_fsm_transition *transitions, int size) { - int i; - - for (i = 0; i < size; i++) { + for (i = 0; i < size; i++) + { /* It needs to have a start. */ - if ((transitions[i].begin == NULL ) - && (transitions[i].event_id == DDS_SECURITY_FSM_EVENT_AUTO)) { - return 1; - } + if (transitions[i].begin && transitions[i].event_id == DDS_SECURITY_FSM_EVENT_AUTO) + return true; } - - return 0; + return true; } -struct dds_security_fsm * -dds_security_fsm_create(struct dds_security_fsm_context *context, - const dds_security_fsm_transition *transitions, int size, void *arg) { - struct dds_security_fsm* fsm = NULL; - struct dds_security_fsm_context *ctx = NULL; - - assert(transitions); - assert(size > 0); - - if (context == NULL) { - if (fsm_init_once()) { - ctx = fsm_context; - } - } else { - ctx = context; +static void add_fsm_to_list (struct dds_security_fsm_control *control, struct dds_security_fsm *fsm) +{ + fsm->next_fsm = NULL; + fsm->prev_fsm = control->last_fsm; + if (control->last_fsm) + { + assert(control->first_fsm != NULL); + control->last_fsm->next_fsm = fsm; } + else + { + assert(control->first_fsm == NULL); + control->first_fsm = fsm; + } + control->last_fsm = fsm; +} - if (ctx) { - if (fsm_validate(transitions, size) == 1) { - fsm = ddsrt_malloc(sizeof(struct dds_security_fsm)); - fsm->transitions = transitions; - fsm->size = size; - fsm->arg = arg; - fsm->current = NULL; - fsm->debug_func = NULL; - fsm->next = NULL; - fsm->prev = NULL; - fsm->context = ctx; - ddsrt_atomic_st32( &fsm->ref_cnt, 1 ); - fsm->current_state_endtime = 0; +static void remove_fsm_from_list (struct dds_security_fsm_control *control, struct dds_security_fsm *fsm) +{ + if (fsm->prev_fsm) + fsm->prev_fsm->next_fsm = fsm->next_fsm; + else + control->first_fsm = fsm->next_fsm; - ddsrt_mutex_lock(&fsm->context->fsm_fsms_mutex); - if (fsm->context->fsm_fsms) { - dds_security_fsm *last = fsm->context->fsm_fsms; - while (last->next != NULL ) { - last = last->next; - } - last->next = fsm; - fsm->prev = last; - } else { - fsm->context->fsm_fsms = fsm; - } - ddsrt_mutex_unlock(&fsm->context->fsm_fsms_mutex); - } + if (fsm->next_fsm) + fsm->next_fsm->prev_fsm = fsm->prev_fsm; + else + control->last_fsm = fsm->prev_fsm; +} + +struct dds_security_fsm * dds_security_fsm_create (struct dds_security_fsm_control *control, const dds_security_fsm_transition *transitions, uint32_t size, void *arg) +{ + struct dds_security_fsm *fsm = NULL; + + assert(control); + assert(transitions); + + if (fsm_validate (transitions, size)) + { + fsm = ddsrt_malloc (sizeof(struct dds_security_fsm)); + fsm->transitions = transitions; + fsm->size = size; + fsm->arg = arg; + fsm->current = NULL; + fsm->debug_func = NULL; + fsm->overall_timeout_action = NULL; + fsm->state_timeout_event.kind = FSM_TIMEOUT_STATE; + fsm->state_timeout_event.endtime = DDS_NEVER; + fsm->state_timeout_event.fsm = fsm; + fsm->overall_timeout_event.kind = FSM_TIMEOUT_OVERALL; + fsm->overall_timeout_event.endtime = DDS_NEVER; + fsm->overall_timeout_event.fsm = fsm; + fsm->active = true; + fsm->next_fsm = NULL; + fsm->prev_fsm = NULL; + fsm->control = control; + + ddsrt_mutex_lock (&control->lock); + add_fsm_to_list (control, fsm); + ddsrt_mutex_unlock (&control->lock); } return fsm; } -void dds_security_fsm_start(struct dds_security_fsm *fsm) { - assert(fsm); - dds_security_fsm_dispatch(fsm, DDS_SECURITY_FSM_EVENT_AUTO); +void +dds_security_fsm_start (struct dds_security_fsm *fsm) +{ + dds_security_fsm_dispatch(fsm, DDS_SECURITY_FSM_EVENT_AUTO, false); } -void dds_security_fsm_set_timeout(struct dds_security_fsm *fsm, dds_security_fsm_action func, - dds_time_t timeout) { - fsm_overall_timeout *to; - dds_security_fsm_context *context; - - assert(fsm); - - context = fsm->context; - assert(context); - - to = ddsrt_malloc(sizeof(fsm_overall_timeout)); - to->fsm = fsm; - to->func = func; - to->endtime = ddsrt_time_add_duration( dds_time(), timeout); - to->next = NULL; - to->prev = NULL; - - ddsrt_mutex_lock(&context->fsm_overall_timeout_cond_mutex); - if (context->fsm_overall_timeouts) { - fsm_overall_timeout *last = context->fsm_overall_timeouts; - while (last->next != NULL ) { - last = last->next; - } - last->next = to; - to->prev = last; - } else { - context->fsm_overall_timeouts = to; - } - ddsrt_cond_signal(&context->fsm_overall_timeout_cond); - ddsrt_mutex_unlock(&context->fsm_overall_timeout_cond_mutex); -} - -void dds_security_fsm_set_debug(struct dds_security_fsm *fsm, dds_security_fsm_debug func) { - dds_security_fsm_context *context; - - assert(fsm); - - context = fsm->context; - assert(context); - - ddsrt_mutex_lock(&context->fsm_overall_timeout_cond_mutex); - fsm->debug_func = func; - ddsrt_mutex_unlock(&context->fsm_overall_timeout_cond_mutex); -} - -void dds_security_fsm_dispatch(struct dds_security_fsm *fsm, int32_t event_id) { - dds_security_fsm_context *context; - - assert(fsm); - - context = fsm->context; - assert(context); - - ddsrt_mutex_lock(&context->fsm_event_cond_mutex); - fsm_dispatch(fsm, event_id, 0); - ddsrt_cond_signal(&context->fsm_event_cond); - ddsrt_mutex_unlock(&context->fsm_event_cond_mutex); -} - -void dds_security_fsm_dispatch_direct(struct dds_security_fsm *fsm, int32_t event_id) { - dds_security_fsm_context *context; - - assert(fsm); - - context = fsm->context; - assert(context); - - ddsrt_mutex_lock(&context->fsm_event_cond_mutex); - fsm_dispatch(fsm, event_id, 1); - ddsrt_cond_signal(&context->fsm_event_cond); - ddsrt_mutex_unlock(&context->fsm_event_cond_mutex); -} - -const dds_security_fsm_state* -dds_security_fsm_current_state(struct dds_security_fsm *fsm) { - assert(fsm); - return fsm->current; -} - -void dds_security_fsm_cleanup(struct dds_security_fsm *fsm) { - dds_security_fsm_context *context; - fsm_event *event; - fsm_event *tmp_prev_event; - fsm_event *tmp_next_event; - fsm_overall_timeout *timeout; - - assert(fsm); - - context = fsm->context; - assert(context); - - // Signal the timeout thread. - // First hold to lock to the overall timeout list - // so that the next timeout can't be determined until - // we've done removing the overall timeout of this fsm - - // Signal the thread so that it's not using timeout structs - ddsrt_mutex_lock(&context->fsm_overall_timeout_cond_mutex); - ddsrt_cond_signal(&context->fsm_overall_timeout_cond); - - timeout = context->fsm_overall_timeouts; - - // Search the overall timeout of this fsm - while (timeout) { - if (timeout->fsm == fsm) { - break; - } - timeout = timeout->next; - } - fsm_remove_overall_timeout_from_list(context, timeout); - ddsrt_mutex_unlock(&context->fsm_overall_timeout_cond_mutex); - - /* The current fsm could be the one that would trigger a possible timeout. - * Reset the state timeout and make sure it's not the current fsm. */ - fsm_set_next_state_timeout(context, fsm); - - /* Now, remove all possible events from the queue related to the fsm. */ - ddsrt_mutex_lock(&context->fsm_event_cond_mutex); - event = context->fsm_queue; - while (event) { - if (event->fsm == fsm) { - tmp_next_event = event->next; - tmp_prev_event = event->prev; - if (tmp_prev_event) { - tmp_prev_event->next = tmp_next_event; - } - if (tmp_next_event) { - tmp_next_event->prev = tmp_prev_event; - } - if (event == context->fsm_queue) { - context->fsm_queue = tmp_next_event; - } - ddsrt_free(event); - event = tmp_next_event; - } else { - event = event->next; - } - } - ddsrt_cond_signal(&context->fsm_event_cond); - ddsrt_mutex_unlock(&context->fsm_event_cond_mutex); -} - -void dds_security_fsm_free(struct dds_security_fsm *fsm) { - ddsrt_tid_t self = ddsrt_gettid_for_thread( ddsrt_thread_self() ); - dds_security_fsm_context *context; - - assert(fsm); - - context = fsm->context; - assert(context); - - /* Indicate termination. */ - fsm->size = -1; - - /* Cleanup stuff. */ - dds_security_fsm_cleanup(fsm); - fsm_remove_fsm_list(fsm); - - /* Is this being freed from the FSM context? */ - if ((self == ddsrt_gettid_for_thread( context->fsm_tid ) ) - || (self == ddsrt_gettid_for_thread( context->fsm_timeout_tid ) ) ) { - /* Yes. - * Just reduce the reference count and let the garbage collection be - * done by the FSM context after event handling. */ - ddsrt_atomic_dec32(&(fsm->ref_cnt)); - } else { - /* No. - * Block the outside thread until a possible concurrent event - * has being handled. */ - while (ddsrt_atomic_ld32( &(fsm->ref_cnt)) > 1) { - /* Currently, an event is still being handled for this FSM. */ - dds_sleepfor( 10 * DDS_NSECS_IN_MSEC ); - } - /* We have the only reference, so it's safe to free the FSM. */ - ddsrt_free(fsm); +static void fsm_deactivate (struct dds_security_fsm *fsm, bool gen_del_event) +{ + if (fsm->active) + { + fsm->active = false; + clear_state_timer (fsm); + clear_overall_timer (fsm); + fsm->current = NULL; + if (gen_del_event) + fsm_dispatch (fsm, DDS_SECURITY_FSM_EVENT_DELETE, false); } } + +void dds_security_fsm_free (struct dds_security_fsm *fsm) +{ + struct dds_security_fsm_control *control; + + assert(fsm); + assert(fsm->control); + + control = fsm->control; + ddsrt_mutex_lock (&control->lock); + fsm_deactivate (fsm, true); + ddsrt_mutex_unlock (&control->lock); +} + +static void fsm_delete (struct dds_security_fsm_control *control, struct dds_security_fsm *fsm) +{ + fsm_deactivate (fsm, false); + remove_fsm_from_list (control, fsm); + ddsrt_free(fsm); +} + +struct dds_security_fsm_control * dds_security_fsm_control_create (struct q_globals *gv) +{ + struct dds_security_fsm_control *control; + + control = ddsrt_malloc (sizeof(*control)); + control->running = false; + control->event_queue = NULL; + control->first_fsm = NULL; + control->last_fsm = NULL; + control->gv = gv; + ddsrt_mutex_init (&control->lock); + ddsrt_cond_init (&control->cond); + ddsrt_fibheap_init (&timer_events_fhdef, &control->timers); + + return control; +} + +void dds_security_fsm_control_free (struct dds_security_fsm_control *control) +{ + struct dds_security_fsm *fsm; + struct fsm_event *event; + + assert(control); + assert(!control->running); + + while ((fsm = control->first_fsm) != NULL) + { + control->first_fsm = fsm->next_fsm; + fsm_deactivate (fsm, false); + ddsrt_free (fsm); + } + while ((event = control->event_queue) != NULL) + { + control->event_queue = event->next; + ddsrt_free (event); + } + + ddsrt_cond_destroy (&control->cond); + ddsrt_mutex_destroy (&control->lock); + ddsrt_free (control); +} + +dds_return_t dds_security_fsm_control_start (struct dds_security_fsm_control *control, const char *name) +{ + dds_return_t rc; + const char *fsm_name = name ? name : "fsm"; + + assert(control); + + control->running = true; + rc = create_thread (&control->ts, control->gv, fsm_name, (uint32_t (*) (void *)) handle_events, control); + + return rc; +} + +void dds_security_fsm_control_stop (struct dds_security_fsm_control *control) +{ + assert(control); + assert(control->running); + + ddsrt_mutex_lock (&control->lock); + control->running = false; + ddsrt_cond_signal (&control->cond); + ddsrt_mutex_unlock (&control->lock); + + join_thread (control->ts); + control->ts = NULL; +} diff --git a/src/security/core/tests/CMakeLists.txt b/src/security/core/tests/CMakeLists.txt index e002ba4..40a6650 100644 --- a/src/security/core/tests/CMakeLists.txt +++ b/src/security/core/tests/CMakeLists.txt @@ -27,13 +27,10 @@ target_include_directories( "$>" "$" "$" - "$" + "$" + "$" ) target_link_libraries(cunit_security_core PRIVATE ddsc security_api) target_include_directories(cunit_security_core PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") - - - -# configure_file("config_env.h.in" "config_env.h") \ No newline at end of file diff --git a/src/security/core/tests/tc_fsm.c b/src/security/core/tests/tc_fsm.c index 442b921..c2c7647 100644 --- a/src/security/core/tests/tc_fsm.c +++ b/src/security/core/tests/tc_fsm.c @@ -1,43 +1,45 @@ -#include "dds/security/core/dds_security_fsm.h" -#include "dds/ddsrt/sync.h" -#include "dds/ddsrt/misc.h" +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ #include #include + +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/misc.h" + #include "CUnit/CUnit.h" #include "CUnit/Test.h" +#include "dds/dds.h" +#include "dds__types.h" +#include "dds__entity.h" +#include "dds/security/core/dds_security_fsm.h" #define CHECK_BIT(var, pos) ((var) & (1<<(pos))) #define FSM_AUTH_ARG 10 -#define DB_TC_PRINT_DEBUG (false) +#define DB_TC_PRINT_DEBUG (true) -static struct dds_security_fsm *fsm_auth; -static struct dds_security_fsm *fsm_test; -static struct dds_security_fsm *fsm_timeout; -static struct dds_security_fsm *fsm_timeout2; -static struct dds_security_fsm *fsm_timeout3; +static dds_entity_t g_participant = 0; +static struct dds_security_fsm_control *g_fsm_control = NULL; +static const dds_duration_t msec100 = DDS_MSECS(100); -static uint32_t visited_auth = 0; -static uint32_t visited_test = 0; -static uint32_t visited_timeout = 0; +//static int fsm_arg = FSM_AUTH_ARG; -uint32_t correct_fsm = 0; -uint32_t correct_arg = 0; -uint32_t correct_fsm_timeout = 0; -uint32_t correct_arg_timeout = 0; -static ddsrt_cond_t stop_timeout_cond; -static ddsrt_mutex_t stop_timeout_cond_mutex; -static uint32_t stop_timeout_cond_cnt = 0; -static int validate_remote_identity_first = 1; -static int begin_handshake_reply_first = 1; -static int do_stuff_counter = 0; -static int do_other_stuff_counter = 0; -/* +/********************************************************************** * Authentication State Machine properties and methods - */ + **********************************************************************/ + typedef enum { VALIDATION_PENDING_RETRY, VALIDATION_FAILED, @@ -48,8 +50,16 @@ typedef enum { PluginReturn_MAX } PluginReturn; -static PluginReturn validate_remote_identity(void) { +static struct dds_security_fsm *fsm_auth; +static uint32_t visited_auth = 0; +static uint32_t correct_fsm = 0; +static uint32_t correct_arg = 0; +static int validate_remote_identity_first = 1; +static int begin_handshake_reply_first = 1; + +static PluginReturn validate_remote_identity(void) +{ if (DB_TC_PRINT_DEBUG) { printf("validate_remote_identity - %d\n", validate_remote_identity_first); } @@ -60,8 +70,8 @@ static PluginReturn validate_remote_identity(void) { return VALIDATION_PENDING_HANDSHAKE_MESSAGE; } -static PluginReturn begin_handshake_reply(void) { - +static PluginReturn begin_handshake_reply(void) +{ if (DB_TC_PRINT_DEBUG) { printf("begin_handshake_reply - %d\n", begin_handshake_reply_first); } @@ -72,12 +82,14 @@ static PluginReturn begin_handshake_reply(void) { return VALIDATION_OK_FINAL_MESSAGE; } -static PluginReturn get_shared_secret(void) { +static PluginReturn get_shared_secret(void) +{ return VALIDATION_OK; } /* State actions. */ -static void fsm_validate_remote_identity(struct dds_security_fsm *fsm, void *arg) { +static void fsm_validate_remote_identity(struct dds_security_fsm *fsm, void *arg) +{ PluginReturn ret; DDSRT_UNUSED_ARG(arg); @@ -88,10 +100,11 @@ static void fsm_validate_remote_identity(struct dds_security_fsm *fsm, void *arg printf("[%p] State %s (ret %d)\n", fsm, __FUNCTION__, (int) ret); } - dds_security_fsm_dispatch(fsm, (int32_t) ret); + dds_security_fsm_dispatch(fsm, (int32_t) ret, false); } -static void fsm_begin_handshake_reply(struct dds_security_fsm *fsm, void *arg) { +static void fsm_begin_handshake_reply(struct dds_security_fsm *fsm, void *arg) +{ PluginReturn ret; DDSRT_UNUSED_ARG(arg); @@ -105,18 +118,18 @@ static void fsm_begin_handshake_reply(struct dds_security_fsm *fsm, void *arg) { printf("[%p] State %s (ret %d)\n", fsm, __FUNCTION__, (int) ret); } - dds_security_fsm_dispatch(fsm, (int32_t) ret); + dds_security_fsm_dispatch(fsm, (int32_t) ret, false); } /* A few states from the handshake state-machine. */ -static dds_security_fsm_state StateValidateRemoteIdentity = { - fsm_validate_remote_identity, 0}; +static dds_security_fsm_state StateValidateRemoteIdentity = {fsm_validate_remote_identity, 0}; static dds_security_fsm_state StateValRemIdentityRetryWait = {NULL, 100000000}; static dds_security_fsm_state StateHandshakeInitMessageWait = {NULL, 0}; static dds_security_fsm_state StateBeginHandshakeReply = {fsm_begin_handshake_reply, 0}; static dds_security_fsm_state StateBeginHsReplyWait = {NULL, 100000000}; -static void a(struct dds_security_fsm *fsm, void *arg) { +static void a(struct dds_security_fsm *fsm, void *arg) +{ int *fsm_arg; if (DB_TC_PRINT_DEBUG) { @@ -141,7 +154,8 @@ static void a(struct dds_security_fsm *fsm, void *arg) { visited_auth |= 1UL << 0; } -static void b(struct dds_security_fsm *fsm, void *arg) { +static void b(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); if (DB_TC_PRINT_DEBUG) @@ -149,7 +163,8 @@ static void b(struct dds_security_fsm *fsm, void *arg) { visited_auth |= 1UL << 1; } -static void c(struct dds_security_fsm *fsm, void *arg) { +static void c(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); if (DB_TC_PRINT_DEBUG) @@ -157,7 +172,8 @@ static void c(struct dds_security_fsm *fsm, void *arg) { visited_auth |= 1UL << 2; } -static void d(struct dds_security_fsm *fsm, void *arg) { +static void d(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); if (DB_TC_PRINT_DEBUG) @@ -165,7 +181,8 @@ static void d(struct dds_security_fsm *fsm, void *arg) { visited_auth |= 1UL << 3; } -static void e(struct dds_security_fsm *fsm, void *arg) { +static void e(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); if (DB_TC_PRINT_DEBUG) @@ -173,7 +190,8 @@ static void e(struct dds_security_fsm *fsm, void *arg) { visited_auth |= 1UL << 4; } -static void f(struct dds_security_fsm *fsm, void *arg) { +static void f(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); if (DB_TC_PRINT_DEBUG) @@ -181,7 +199,8 @@ static void f(struct dds_security_fsm *fsm, void *arg) { visited_auth |= 1UL << 5; } -static void g(struct dds_security_fsm *fsm, void *arg) { +static void g(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); if (DB_TC_PRINT_DEBUG) @@ -189,7 +208,8 @@ static void g(struct dds_security_fsm *fsm, void *arg) { visited_auth |= 1UL << 6; } -static void h(struct dds_security_fsm *fsm, void *arg) { +static void h(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); if (DB_TC_PRINT_DEBUG) @@ -233,34 +253,35 @@ static void h(struct dds_security_fsm *fsm, void *arg) { * .-. * '-' */ -dds_security_fsm_transition HandshakeTransistions[] = - {{NULL, DDS_SECURITY_FSM_EVENT_AUTO, a, &StateValidateRemoteIdentity}, // NULL state is the start state - {&StateValidateRemoteIdentity, VALIDATION_PENDING_RETRY, b, - &StateValRemIdentityRetryWait}, - {&StateValidateRemoteIdentity, - VALIDATION_PENDING_HANDSHAKE_MESSAGE, c, - &StateHandshakeInitMessageWait}, - {&StateValRemIdentityRetryWait, - DDS_SECURITY_FSM_EVENT_TIMEOUT, d, &StateValidateRemoteIdentity}, - { - &StateHandshakeInitMessageWait, SHM_MSG_RECEIVED, e, - &StateBeginHandshakeReply}, - {&StateBeginHandshakeReply, - VALIDATION_PENDING_RETRY, f, &StateBeginHsReplyWait}, - { - &StateBeginHandshakeReply, VALIDATION_OK, g, NULL}, // Reaching NULL means end of state-diagram - {&StateBeginHsReplyWait, DDS_SECURITY_FSM_EVENT_TIMEOUT, h, - &StateBeginHandshakeReply},}; +static dds_security_fsm_transition HandshakeTransistions[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, a, &StateValidateRemoteIdentity}, // NULL state is the start state + {&StateValidateRemoteIdentity, VALIDATION_PENDING_RETRY, b, &StateValRemIdentityRetryWait}, + {&StateValidateRemoteIdentity, VALIDATION_PENDING_HANDSHAKE_MESSAGE, c, &StateHandshakeInitMessageWait}, + {&StateValRemIdentityRetryWait, DDS_SECURITY_FSM_EVENT_TIMEOUT, d, &StateValidateRemoteIdentity}, + {&StateHandshakeInitMessageWait, SHM_MSG_RECEIVED, e, &StateBeginHandshakeReply}, + {&StateBeginHandshakeReply, VALIDATION_PENDING_RETRY, f, &StateBeginHsReplyWait}, + {&StateBeginHandshakeReply, VALIDATION_OK, g, NULL}, // Reaching NULL means end of state-diagram + {&StateBeginHsReplyWait, DDS_SECURITY_FSM_EVENT_TIMEOUT, h, &StateBeginHandshakeReply} +}; +static const uint32_t HandshakeTransistionsSize = sizeof(HandshakeTransistions)/sizeof(HandshakeTransistions[0]); -/* + +/********************************************************************** * Example State Machine properties and methods - */ + **********************************************************************/ + typedef enum { eventX, eventY, eventZ, } test_events; +static struct dds_security_fsm *fsm_test; +static uint32_t visited_test = 0; +static int do_stuff_counter = 0; +static int do_other_stuff_counter = 0; + /* The functions called from the state-machine. */ -static void doStart(struct dds_security_fsm *fsm, void *arg) { +static void doStart(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); if (DB_TC_PRINT_DEBUG) @@ -268,7 +289,8 @@ static void doStart(struct dds_security_fsm *fsm, void *arg) { visited_test |= 1UL << 0; } -static void doRestart(struct dds_security_fsm *fsm, void *arg) { +static void doRestart(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); if (DB_TC_PRINT_DEBUG) @@ -276,7 +298,8 @@ static void doRestart(struct dds_security_fsm *fsm, void *arg) { visited_test |= 1UL << 1; } -static void doEventStuff(struct dds_security_fsm *fsm, void *arg) { +static void doEventStuff(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); if (DB_TC_PRINT_DEBUG) @@ -284,8 +307,8 @@ static void doEventStuff(struct dds_security_fsm *fsm, void *arg) { visited_test |= 1UL << 4; } -static void doStuff(struct dds_security_fsm *fsm, void *arg) { - +static void doStuff(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); @@ -294,15 +317,16 @@ static void doStuff(struct dds_security_fsm *fsm, void *arg) { } visited_test |= 1UL << 2; - if (do_stuff_counter == 0) { - dds_security_fsm_dispatch(fsm, eventZ); + if (do_stuff_counter < 2) { + dds_security_fsm_dispatch(fsm, eventZ, false); } else if (do_stuff_counter == 2) { - dds_security_fsm_dispatch(fsm, eventY); + dds_security_fsm_dispatch(fsm, eventY, false); } ++do_stuff_counter; } -static void doOtherStuff(struct dds_security_fsm *fsm, void *arg) { +static void doOtherStuff(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); @@ -311,43 +335,54 @@ static void doOtherStuff(struct dds_security_fsm *fsm, void *arg) { } visited_test |= 1UL << 3; if (do_other_stuff_counter == 0) { - dds_security_fsm_dispatch(fsm, DDS_SECURITY_FSM_EVENT_AUTO); + dds_security_fsm_dispatch(fsm, DDS_SECURITY_FSM_EVENT_AUTO, false); } + if (do_other_stuff_counter == 1) { - dds_security_fsm_dispatch(fsm, eventY); + dds_security_fsm_dispatch(fsm, eventY, false); } else if (do_other_stuff_counter == 2) { - dds_security_fsm_dispatch(fsm, eventX); + dds_security_fsm_dispatch(fsm, eventX, false); } ++do_other_stuff_counter; } -dds_security_fsm_state StateA = {doStuff, 0}; -dds_security_fsm_state StateB = {doStuff, 100000000}; -dds_security_fsm_state StateC = {NULL, 0}; -dds_security_fsm_state StateD = {doOtherStuff, 0}; +static dds_security_fsm_state StateA = {doStuff, 0}; +static dds_security_fsm_state StateB = {doStuff, 100000000}; +static dds_security_fsm_state StateC = {NULL, 0}; +static dds_security_fsm_state StateD = {doOtherStuff, 0}; -dds_security_fsm_transition transitions[] = { - {NULL, DDS_SECURITY_FSM_EVENT_AUTO, doStart, &StateA}, // NULL state is the start state - {&StateA, eventZ, NULL, &StateB}, - {&StateA, eventY, doOtherStuff, &StateC}, - {&StateB, eventX, NULL, NULL}, // Reaching NULL means end of state-diagram - {&StateB, eventZ, doRestart, &StateA}, - {&StateC, DDS_SECURITY_FSM_EVENT_AUTO, - doEventStuff, &StateD}, - {&StateD, eventY, doEventStuff, &StateD}, - { - &StateD, eventX, doStuff, NULL}, // Reaching NULL means end of state-diagram +static dds_security_fsm_transition Transitions[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, doStart, &StateA}, // NULL state is the start state + {&StateA, eventZ, NULL, &StateB}, + {&StateA, eventY, doOtherStuff, &StateC}, + {&StateB, eventX, NULL, NULL}, // Reaching NULL means end of state-diagram + {&StateB, eventZ, doRestart, &StateA}, + {&StateC, DDS_SECURITY_FSM_EVENT_AUTO, doEventStuff, &StateD}, + {&StateD, eventY, doEventStuff, &StateD}, + {&StateD, eventX, doStuff, NULL}, // Reaching NULL means end of sttimeoutate-diagram }; +static const uint32_t TransitionsSize = sizeof(Transitions)/sizeof(Transitions[0]); -/* + +/********************************************************************** * Timeout State Machine properties and methods - */ + **********************************************************************/ + typedef enum { eventToTimeout, eventToEnd, } timeout_events; -/* The functions callld from the state-machine. */ -static void doInterupt(struct dds_security_fsm *fsm, void *arg) { +static struct dds_security_fsm *fsm_timeout; +static uint32_t visited_timeout = 0; +static uint32_t correct_fsm_timeout = 0; +static uint32_t correct_arg_timeout = 0; +static ddsrt_cond_t stop_timeout_cond; +static ddsrt_mutex_t stop_timeout_cond_mutex; +static uint32_t stop_timeout_cond_cnt = 0; + +/* The functions called from the state-machine. */ +static void doInterupt(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); if (DB_TC_PRINT_DEBUG) { @@ -356,7 +391,8 @@ static void doInterupt(struct dds_security_fsm *fsm, void *arg) { visited_timeout |= 1UL << 0; } -static void doTimeout(struct dds_security_fsm *fsm, void *arg) { +static void doTimeout(struct dds_security_fsm *fsm, void *arg) +{ dds_duration_t delay4 = 4 * DDS_NSECS_IN_SEC; DDSRT_UNUSED_ARG(arg); @@ -377,10 +413,11 @@ static void doTimeout(struct dds_security_fsm *fsm, void *arg) { printf("Transition <<<< %s %d\n", __FUNCTION__, stop_timeout_cond_cnt); } - dds_security_fsm_dispatch(fsm, eventToTimeout); + dds_security_fsm_dispatch(fsm, eventToTimeout, false); } -static void TimeoutCallback(struct dds_security_fsm *fsm, void *arg) { +static void TimeoutCallback(struct dds_security_fsm *fsm, void *arg) +{ int *fsm_arg; if (DB_TC_PRINT_DEBUG) { @@ -405,7 +442,8 @@ static void TimeoutCallback(struct dds_security_fsm *fsm, void *arg) { } } -static void TimeoutCallback2(struct dds_security_fsm *fsm, void *arg) { +static void TimeoutCallback2(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); if (DB_TC_PRINT_DEBUG) { @@ -414,86 +452,121 @@ static void TimeoutCallback2(struct dds_security_fsm *fsm, void *arg) { visited_timeout |= 1UL << 3; } -dds_security_fsm_state StateTimeout = {doTimeout, 0}; -dds_security_fsm_state StateInterupt = {doInterupt, 0}; +static dds_security_fsm_state StateTimeout = {doTimeout, 0};static int fsm_arg = FSM_AUTH_ARG; -dds_security_fsm_transition timeout_transitions[] = {{NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, - &StateTimeout}, // NULL state is the start state - {&StateTimeout, eventToTimeout, NULL, &StateInterupt}, - {&StateInterupt, - eventToEnd, NULL, NULL}, // Reaching NULL means end of state-diagram +static dds_security_fsm_state StateInterupt = {doInterupt, 0}; + +static const dds_security_fsm_transition TimeoutTransitions[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateTimeout}, // NULL state is the start state + {&StateTimeout, eventToTimeout, NULL, &StateInterupt}, + {&StateInterupt,eventToEnd, NULL, NULL}, // Reaching NULL means end of state-diagram }; +static const uint32_t TimeoutTransitionsSize = sizeof(TimeoutTransitions)/sizeof(TimeoutTransitions[0]); + + +/********************************************************************** + * Parallel Timeout State Machines properties and methods + **********************************************************************/ + +static struct dds_security_fsm *fsm_timeout1; +static struct dds_security_fsm *fsm_timeout2; +static struct dds_security_fsm *fsm_timeout3; static dds_time_t time0 = 0; static dds_time_t time1 = 0; static dds_time_t time2 = 0; static dds_time_t time3 = 0; -static void StateParTime1(struct dds_security_fsm *fsm, void *arg) { +static void StateParTime1(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); time1 = dds_time(); } -static void StateParTime2(struct dds_security_fsm *fsm, void *arg) { +static void StateParTime2(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); time2 = dds_time(); } -static void StateParTime3(struct dds_security_fsm *fsm, void *arg) { +static void StateParTime3(struct dds_security_fsm *fsm, void *arg) +{ DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(arg); time3 = dds_time(); } -dds_security_fsm_state StateParTimeout1 = {NULL, DDS_NSECS_IN_SEC}; -dds_security_fsm_state StateParTimeout2 = {NULL, 2 * DDS_NSECS_IN_SEC}; -dds_security_fsm_state StateParTimeout3 = {NULL, DDS_NSECS_IN_SEC}; +static dds_security_fsm_state StateParTimeout1 = {NULL, DDS_SECS(1)}; +static dds_security_fsm_state StateParTimeout2 = {NULL, DDS_SECS(2)}; +static dds_security_fsm_state StateParTimeout3 = {NULL, DDS_SECS(1)}; -dds_security_fsm_transition par_timeout_transitions_1[] = {{NULL, DDS_SECURITY_FSM_EVENT_AUTO, - NULL, &StateParTimeout1}, // NULL state is the start state - {&StateParTimeout1, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime1, NULL}, // Reaching NULL means end of state-diagram +static dds_security_fsm_transition ParallelTimeoutTransitions_1[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateParTimeout1}, // NULL state is the startfsm_control_thread state + {&StateParTimeout1, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime1, NULL}, // Reaching NULL means end of state-diagram }; +static const uint32_t ParallelTimeoutTransitionsSize_1 = sizeof(ParallelTimeoutTransitions_1) / sizeof(ParallelTimeoutTransitions_1[0]); -dds_security_fsm_transition par_timeout_transitions_2[] = {{NULL, DDS_SECURITY_FSM_EVENT_AUTO, - NULL, &StateParTimeout2}, // NULL state is the start state - {&StateParTimeout2, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime2, NULL}, // Reaching NULL means end of state-diagram +static dds_security_fsm_transition ParallelTimeoutTransitions_2[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateParTimeout2}, // NULL state is the start state + {&StateParTimeout2, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime2, NULL}, // Reaching NULL means end of state-diagram }; +static const uint32_t ParallelTimeoutTransitionsSize_2 = sizeof(ParallelTimeoutTransitions_2) / sizeof(ParallelTimeoutTransitions_2[0]); -dds_security_fsm_transition par_timeout_transitions_3[] = {{NULL, DDS_SECURITY_FSM_EVENT_AUTO, - NULL, &StateParTimeout3}, // NULL state is the start state - {&StateParTimeout3, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime3, NULL}, // Reaching NULL means end of state-diagram +static dds_security_fsm_transition ParallelTimeoutTransitions_3[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateParTimeout3}, // NULL state is the start state + {&StateParTimeout3, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime3, NULL}, // Reaching NULL means end of state-diagram }; +static const uint32_t ParallelTimeoutTransitionsSize_3 = sizeof(ParallelTimeoutTransitions_3) / sizeof(ParallelTimeoutTransitions_3[0]); -int fsm_arg = FSM_AUTH_ARG; -dds_time_t delay1 = DDS_NSECS_IN_SEC; -dds_time_t delay2 = 2 * DDS_NSECS_IN_SEC; -dds_time_t delay30 = 30 * DDS_NSECS_IN_SEC; -int timeout; -static const dds_duration_t msec100 = 100 * DDS_NSECS_IN_MSEC; -static void init_testcase(void) { - (void) ddsrt_mutex_init(&stop_timeout_cond_mutex); - (void) ddsrt_cond_init(&stop_timeout_cond); + +static void fsm_control_init(void) +{ + dds_return_t rc; + struct dds_entity *e; + + g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); + CU_ASSERT_FATAL(g_participant > 0); + + rc = dds_entity_pin(g_participant, &e); + CU_ASSERT_FATAL(rc == 0); + + g_fsm_control = dds_security_fsm_control_create (&e->m_domain->gv); + CU_ASSERT_FATAL (g_fsm_control != NULL); + + dds_entity_unpin (e); + + rc = dds_security_fsm_control_start (g_fsm_control, NULL); + CU_ASSERT_FATAL(rc == 0); + + ddsrt_mutex_init(&stop_timeout_cond_mutex); + ddsrt_cond_init(&stop_timeout_cond); } -static void fini_testcase(void) { +static void fsm_control_fini(void) +{ ddsrt_cond_destroy(&stop_timeout_cond); ddsrt_mutex_destroy(&stop_timeout_cond_mutex); + + dds_security_fsm_control_stop(g_fsm_control); + dds_security_fsm_control_free(g_fsm_control); + + dds_delete(g_participant); } -CU_Test(ddssec_fsm, create, .init = init_testcase, .fini = fini_testcase) { +CU_Test(ddssec_fsm, create, .init = fsm_control_init, .fini = fsm_control_fini) +{ + dds_time_t delay30 = DDS_SECS(30); + int timeout; /* * Test single running state machine * Check creation of a single State Machine */ - - fsm_auth = dds_security_fsm_create(NULL, HandshakeTransistions, - sizeof(HandshakeTransistions) / sizeof(HandshakeTransistions[0]), - &fsm_arg); + fsm_auth = dds_security_fsm_create(g_fsm_control, HandshakeTransistions, HandshakeTransistionsSize, &fsm_arg); CU_ASSERT_FATAL(fsm_auth != NULL) // set a delay that doesn't expire. Should be terminate when fsm is freed. @@ -506,21 +579,20 @@ CU_Test(ddssec_fsm, create, .init = init_testcase, .fini = fini_testcase) { // Wait for the last state to occur timeout = 100; /* 10 sec */ - while ((dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait) - && (timeout > 0)) { + while ((dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait) && (timeout > 0)) { dds_sleepfor(msec100); timeout--; } CU_ASSERT(timeout > 0); - dds_security_fsm_dispatch(fsm_auth, SHM_MSG_RECEIVED); + dds_security_fsm_dispatch(fsm_auth, SHM_MSG_RECEIVED, false); timeout = 100; /* 10 sec */ while ((dds_security_fsm_current_state(fsm_auth) != NULL) && (timeout > 0)) { dds_sleepfor(msec100); timeout--; } - CU_ASSERT(timeout > 0); + CU_ASSERT( CHECK_BIT(visited_auth, 0) && CHECK_BIT(visited_auth, 1) && CHECK_BIT(visited_auth, 2) && CHECK_BIT(visited_auth, 3) && CHECK_BIT(visited_auth, 4) && CHECK_BIT(visited_auth, 5) && @@ -539,54 +611,61 @@ CU_Test(ddssec_fsm, create, .init = init_testcase, .fini = fini_testcase) { /* * Test multiple (2) running state machines */ -CU_Test(ddssec_fsm, multiple, .init = init_testcase, .fini = fini_testcase) { +CU_Test(ddssec_fsm, multiple, .init = fsm_control_init, .fini = fsm_control_fini) +{ + int timeout; /*Check creation of multiple (2) State Machines*/ validate_remote_identity_first = 0; begin_handshake_reply_first = 0; visited_auth = 0; + visited_test = 0; + + fsm_auth = dds_security_fsm_create(g_fsm_control, HandshakeTransistions, HandshakeTransistionsSize, NULL); + CU_ASSERT_FATAL(fsm_auth != NULL); + + fsm_test = dds_security_fsm_create(g_fsm_control, Transitions, TransitionsSize, NULL); + CU_ASSERT_FATAL(fsm_test != NULL); - fsm_auth = dds_security_fsm_create(NULL, HandshakeTransistions, - sizeof(HandshakeTransistions) / sizeof(HandshakeTransistions[0]), NULL); - fsm_test = dds_security_fsm_create(NULL, transitions, - sizeof(transitions) / sizeof(transitions[0]), NULL); - CU_ASSERT_FALSE(fsm_auth == NULL || fsm_test == NULL); dds_security_fsm_start(fsm_auth); dds_security_fsm_start(fsm_test); - /*Check the results of multiple running State Machines */ + /* Check the results of multiple running State Machines */ - // Wait for the last state to occur + /* Wait for the last state to occur */ timeout = 100; /* 10 sec */ - while ((dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait) - && (timeout > 0)) { + while ((dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait) && (timeout > 0)) { dds_sleepfor(100 * DDS_NSECS_IN_MSEC); timeout--; } CU_ASSERT_FATAL(timeout > 0); + timeout = 100; /* 10 sec */ - dds_security_fsm_dispatch(fsm_auth, SHM_MSG_RECEIVED); + dds_security_fsm_dispatch(fsm_auth, SHM_MSG_RECEIVED, false); while ((dds_security_fsm_current_state(fsm_auth) != NULL) && (timeout > 0)) { dds_sleepfor(100 * DDS_NSECS_IN_MSEC); timeout--; } CU_ASSERT_FATAL(timeout > 0); + // not all bits are set since we're running the state machine a second time CU_ASSERT_FATAL( CHECK_BIT(visited_auth, 0) && !CHECK_BIT(visited_auth, 1) && CHECK_BIT(visited_auth, 2) && !CHECK_BIT(visited_auth, 3) && CHECK_BIT(visited_auth, 4) && !CHECK_BIT(visited_auth, 5) && CHECK_BIT(visited_auth, 6) && !CHECK_BIT(visited_auth, 7)); + /* Wait for the last state to occur */ timeout = 100; /* 10 sec */ - // Wait for the last state to occur while ((dds_security_fsm_current_state(fsm_test) != NULL) && timeout > 0) { dds_sleepfor(100 * DDS_NSECS_IN_MSEC); timeout--; } CU_ASSERT_FATAL(timeout > 0); - CU_ASSERT_FATAL( + + CU_ASSERT( CHECK_BIT(visited_test, 0) && CHECK_BIT(visited_test, 1) && CHECK_BIT(visited_test, 2) && CHECK_BIT(visited_test, 3)); + dds_security_fsm_free(fsm_auth); dds_security_fsm_free(fsm_test); @@ -595,13 +674,15 @@ CU_Test(ddssec_fsm, multiple, .init = init_testcase, .fini = fini_testcase) { /** * Check creation of State Machine for timeout purposes */ -CU_Test(ddssec_fsm, timeout, .init = init_testcase, .fini = fini_testcase) { +CU_Test(ddssec_fsm, timeout, .init = fsm_control_init, .fini = fsm_control_fini) +{ + dds_time_t delay1 = DDS_SECS(1); + int timeout; /* * Test timeout monitoring of state machines */ - fsm_timeout = dds_security_fsm_create(NULL, timeout_transitions, - sizeof(timeout_transitions) / sizeof(timeout_transitions[0]), &fsm_arg); + fsm_timeout = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg); CU_ASSERT(fsm_timeout != NULL); dds_security_fsm_set_timeout(fsm_timeout, TimeoutCallback, delay1); @@ -627,15 +708,19 @@ CU_Test(ddssec_fsm, timeout, .init = init_testcase, .fini = fini_testcase) { /** * Check the double global timeout */ -CU_Test(ddssec_fsm, double_timeout, .init = init_testcase, .fini = fini_testcase) { +CU_Test(ddssec_fsm, double_timeout, .init = fsm_control_init, .fini = fsm_control_fini) +{ + dds_time_t delay1 = DDS_SECS(1); + dds_time_t delay2 = DDS_SECS(2); + int timeout; visited_timeout = 0; - fsm_timeout = dds_security_fsm_create(NULL, timeout_transitions, - sizeof(timeout_transitions) / sizeof(timeout_transitions[0]), &fsm_arg); + fsm_timeout = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg); CU_ASSERT(fsm_timeout != NULL); - fsm_timeout2 = dds_security_fsm_create(NULL, timeout_transitions, - sizeof(timeout_transitions) / sizeof(timeout_transitions[0]), &fsm_arg); + + fsm_timeout2 = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg); CU_ASSERT(fsm_timeout2 != NULL); + dds_security_fsm_set_timeout(fsm_timeout, TimeoutCallback, delay1); dds_security_fsm_set_timeout(fsm_timeout2, TimeoutCallback2, delay2); dds_security_fsm_start(fsm_timeout); @@ -646,7 +731,7 @@ CU_Test(ddssec_fsm, double_timeout, .init = init_testcase, .fini = fini_testcase timeout--; } CU_ASSERT(CHECK_BIT(visited_timeout, 2)); - dds_security_fsm_cleanup(fsm_timeout); +// dds_security_fsm_cleanup(fsm_timeout); timeout = 100; /* 10 sec */ while ((CHECK_BIT(visited_timeout, 3) == 0) && (timeout > 0)) { dds_sleepfor(100 * DDS_NSECS_IN_MSEC); @@ -664,40 +749,41 @@ CU_Test(ddssec_fsm, double_timeout, .init = init_testcase, .fini = fini_testcase /** * Check parallel state timeouts */ -CU_Test(ddssec_fsm, parallel_timeout, .init = init_testcase, .fini = fini_testcase) { - visited_timeout = 0; - fsm_timeout = dds_security_fsm_create(NULL, par_timeout_transitions_1, - sizeof(par_timeout_transitions_1) / sizeof(par_timeout_transitions_1[0]), - &fsm_arg); - CU_ASSERT(fsm_timeout != NULL); - fsm_timeout2 = dds_security_fsm_create(NULL, par_timeout_transitions_2, - sizeof(par_timeout_transitions_2) / sizeof(par_timeout_transitions_2[0]), - &fsm_arg); - CU_ASSERT(fsm_timeout2 != NULL); - fsm_timeout3 = dds_security_fsm_create(NULL, par_timeout_transitions_3, - sizeof(par_timeout_transitions_3) / sizeof(par_timeout_transitions_3[0]), - &fsm_arg); - CU_ASSERT(fsm_timeout3 != NULL); +CU_Test(ddssec_fsm, parallel_timeout, .init = fsm_control_init, .fini = fsm_control_fini) +{ dds_duration_t delta1; dds_duration_t delta2; dds_duration_t delta3; + int timeout; + + visited_timeout = 0; + + fsm_timeout1 = dds_security_fsm_create(g_fsm_control, ParallelTimeoutTransitions_1, ParallelTimeoutTransitionsSize_1, &fsm_arg); + CU_ASSERT_FATAL(fsm_timeout1 != NULL); + + fsm_timeout2 = dds_security_fsm_create(g_fsm_control, ParallelTimeoutTransitions_2, ParallelTimeoutTransitionsSize_2, &fsm_arg); + CU_ASSERT_FATAL(fsm_timeout2 != NULL); + + fsm_timeout3 = dds_security_fsm_create(g_fsm_control, ParallelTimeoutTransitions_3, ParallelTimeoutTransitionsSize_3, &fsm_arg); + CU_ASSERT_FATAL(fsm_timeout3 != NULL); time0 = dds_time(); - dds_security_fsm_start(fsm_timeout); + dds_security_fsm_start(fsm_timeout1); dds_security_fsm_start(fsm_timeout2); dds_security_fsm_start(fsm_timeout3); /* Wait for both to end. */ - timeout = 100; /* 10 sec */ + timeout = 300; /* 10 sec */ /* First, they have to be started. */ - while (((dds_security_fsm_current_state(fsm_timeout) == NULL) + while (((dds_security_fsm_current_state(fsm_timeout1) == NULL) || (dds_security_fsm_current_state(fsm_timeout2) == NULL) || (dds_security_fsm_current_state(fsm_timeout3) == NULL)) && (timeout > 0)) { dds_sleepfor(100 * DDS_NSECS_IN_MSEC); timeout--; } + /* Then, they have to have ended. */ - while (((dds_security_fsm_current_state(fsm_timeout) != NULL) + while (((dds_security_fsm_current_state(fsm_timeout1) != NULL) || (dds_security_fsm_current_state(fsm_timeout2) != NULL) || (dds_security_fsm_current_state(fsm_timeout3) != NULL)) && (timeout > 0)) { dds_sleepfor(100 * DDS_NSECS_IN_MSEC); @@ -727,7 +813,7 @@ CU_Test(ddssec_fsm, parallel_timeout, .init = init_testcase, .fini = fini_testca CU_ASSERT(delta3 > 750 * DDS_NSECS_IN_MSEC); CU_ASSERT(delta3 < 1250 * DDS_NSECS_IN_MSEC); - dds_security_fsm_free(fsm_timeout); + dds_security_fsm_free(fsm_timeout1); dds_security_fsm_free(fsm_timeout2); dds_security_fsm_free(fsm_timeout3); @@ -736,11 +822,13 @@ CU_Test(ddssec_fsm, parallel_timeout, .init = init_testcase, .fini = fini_testca /** * Delete with event timeout */ -CU_Test(ddssec_fsm, delete_with_timeout, .init = init_testcase, .fini = fini_testcase) { +CU_Test(ddssec_fsm, delete_with_timeout, .init = fsm_control_init, .fini = fsm_control_fini) +{ + int timeout; + + fsm_timeout = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg); + CU_ASSERT (fsm_timeout != NULL) - fsm_timeout = dds_security_fsm_create(NULL, timeout_transitions, - sizeof(timeout_transitions) / sizeof(timeout_transitions[0]), &fsm_arg); - CU_ASSERT (fsm_timeout != NULL); visited_timeout = 0; dds_security_fsm_start(fsm_timeout); From 97c3025e54db892e6c03129248bf218336a3cd91 Mon Sep 17 00:00:00 2001 From: Joao Rebelo Date: Mon, 25 Nov 2019 13:07:34 +0100 Subject: [PATCH 092/238] Add timed callback dispatcher to security core Dispatchers are added to a custom linked list while each dispatcher owns a fibheap of callbacks that are ordered by expiry timestamp. A seperate fibheap is use for each dispatcher to allow disabling and enabling of each dispatcher. A new and free function is added that creates a timed_cd_data object that is used by every public function. A thread is initialized at object creation instead of using a counter. Add a protection for the terminate flag. Signed-off-by: Joao Rebelo --- src/security/core/CMakeLists.txt | 10 +- .../dds/security/core/dds_security_timed_cb.h | 183 ++++++ src/security/core/src/dds_security_timed_cb.c | 329 +++++++++++ src/security/core/tests/CMakeLists.txt | 1 + src/security/core/tests/dds_security_core.c | 546 ++++++++++++++++++ 5 files changed, 1066 insertions(+), 3 deletions(-) create mode 100644 src/security/core/include/dds/security/core/dds_security_timed_cb.h create mode 100644 src/security/core/src/dds_security_timed_cb.c create mode 100644 src/security/core/tests/dds_security_core.c diff --git a/src/security/core/CMakeLists.txt b/src/security/core/CMakeLists.txt index 836bc70..8719946 100644 --- a/src/security/core/CMakeLists.txt +++ b/src/security/core/CMakeLists.txt @@ -15,6 +15,7 @@ PREPEND(srcs_security_core "${CMAKE_CURRENT_LIST_DIR}/src" dds_security_plugins.c shared_secret.c dds_security_fsm.c + dds_security_timed_cb.c ) PREPEND(hdrs_public_security_core "${CMAKE_CURRENT_LIST_DIR}/include/security/core" @@ -24,6 +25,7 @@ PREPEND(hdrs_public_security_core "${CMAKE_CURRENT_LIST_DIR}/include/security/co dds_security_plugins.h dds_security_fsm.h shared_secret.h + dds_security_timed_cb.h ) if(NOT WIN32) @@ -49,10 +51,12 @@ target_include_directories(security_core ) #target_link_libraries(security_core PRIVATE ddsrt security_api) +if(BUILD_TESTING) + add_subdirectory(tests) + add_subdirectory(tests/plugin_loading) +endif() + install( DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/include/dds/security/core/" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/dds/security/core/" COMPONENT dev) - -add_subdirectory(tests) -add_subdirectory(tests/plugin_loading) diff --git a/src/security/core/include/dds/security/core/dds_security_timed_cb.h b/src/security/core/include/dds/security/core/dds_security_timed_cb.h new file mode 100644 index 0000000..6a883d6 --- /dev/null +++ b/src/security/core/include/dds/security/core/dds_security_timed_cb.h @@ -0,0 +1,183 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#ifndef DDS_SECURITY_TIMED_CALLBACK_H +#define DDS_SECURITY_TIMED_CALLBACK_H + +#include "dds/export.h" +#include "dds/ddsrt/time.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +/** + * The dispatcher that will trigger the timed callbacks. + */ +struct dds_security_timed_dispatcher_t; + +struct dds_security_timed_cb_data_t; + +/** + * The callback is triggered by two causes: + * 1. The trigger timeout has been reached. + * 2. The related dispatcher is being deleted. + */ +typedef enum { + DDS_SECURITY_TIMED_CB_KIND_TIMEOUT, + DDS_SECURITY_TIMED_CB_KIND_DELETE +} dds_security_timed_cb_kind; + + + +/** + * Template for the timed callback functions. + * It is NOT allowed to call any t_timed_cb API functions from within this + * callback context. + * + * This will be called when the trigger time of the added callback is reached, + * or if the related dispatcher is deleted. The latter can be used to clean up + * possible callback resources. + * + * @param d Related dispatcher. + * @param kind Triggered by cb timeout or dispatcher deletion. + * @param listener Listener that was provided when enabling the related + * dispatcher (NULL with a deletion trigger). + * @param arg User data, provided when adding a callback to the + * related dispatcher. + */ +typedef void +(*dds_security_timed_cb_t) ( + struct dds_security_timed_dispatcher_t *d, + dds_security_timed_cb_kind kind, + void *listener, + void *arg); + +DDS_EXPORT struct dds_security_timed_cb_data* +dds_security_timed_cb_new(void); + +DDS_EXPORT void +dds_security_timed_cb_free( + struct dds_security_timed_cb_data *dl); + +/** + * Create a new dispatcher for timed callbacks. + * The dispatcher is not enabled (see dds_security_timed_dispatcher_enable). + * + * @return New (disabled) timed callbacks dispatcher. + */ +DDS_EXPORT struct dds_security_timed_dispatcher_t* +dds_security_timed_dispatcher_new( + struct dds_security_timed_cb_data *tcb); + +/** + * Frees the given dispatcher. + * If the dispatcher contains timed callbacks, then these will be + * triggered with DDS_SECURITY_TIMED_CB_KIND_DELETE and then removed. This + * is done whether the dispatcher is enabled or not. + * + * @param d The dispatcher to free. + * + */ +DDS_EXPORT void +dds_security_timed_dispatcher_free( + struct dds_security_timed_cb_data *tcb, + struct dds_security_timed_dispatcher_t *d); + + + +/** + * Enables a dispatcher for timed callbacks. + * + * Until a dispatcher is enabled, no DDS_SECURITY_TIMED_CB_KIND_TIMEOUT callbacks will + * be triggered. + * As soon as it is enabled, possible stored timed callbacks that are in the + * past will be triggered at that moment. + * Also, from this point on, possible future callbacks will also be triggered + * when the appropriate time has been reached. + * + * A listener argument can be supplied that is returned when the callback + * is triggered. The dispatcher doesn't do anything more with it, so it may + * be NULL. + * + * DDS_SECURITY_TIMED_CB_KIND_DELETE callbacks will always be triggered despite the + * dispatcher being possibly disabled. + * + * @param d The dispatcher to enable. + * @param listener An object that is returned with the callback. + * + */ +DDS_EXPORT void +dds_security_timed_dispatcher_enable( + struct dds_security_timed_cb_data *tcb, + struct dds_security_timed_dispatcher_t *d, + void *listener); + + + +/** + * Disables a dispatcher for timed callbacks. + * + * When a dispatcher is disabled (default after creation), it will not + * trigger any related callbacks. It will still store them, however, so + * that they can be triggered after a (re)enabling. + * + * This is when the callback is actually triggered by a timeout and thus + * its kind is DDS_SECURITY_TIMED_CB_KIND_TIMEOUT. DDS_SECURITY_TIMED_CB_KIND_DELETE callbacks + * will always be triggered despite the dispatcher being possibly disabled. + * + * @param d The dispatcher to disable. + * + */ +DDS_EXPORT void +dds_security_timed_dispatcher_disable( + struct dds_security_timed_cb_data *tcb, + struct dds_security_timed_dispatcher_t *d); + + + +/** + * Adds a timed callback to a dispatcher. + * + * The given callback will be triggered with DDS_SECURITY_TIMED_CB_KIND_TIMEOUT when: + * 1. The dispatcher is enabled and + * 2. The trigger_time has been reached. + * + * If the trigger_time lays in the past, then the callback is still added. + * When the dispatcher is already enabled, it will trigger this 'past' + * callback immediately. Otherwise, the 'past' callback will be triggered + * at the moment that the dispatcher is enabled. + * + * The given callback will be triggered with DDS_SECURITY_TIMED_CB_KIND_DELETE when: + * 1. The related dispatcher is deleted (ignoring enable/disable). + * + * This is done so that possible related callback resources can be freed. + * + * @param d The dispatcher to add the callback to. + * @param cb The actual callback function. + * @param trigger_time A wall-clock time of when to trigger the callback. + * @param arg User data that is provided with the callback. + * + */ +DDS_EXPORT void +dds_security_timed_dispatcher_add( + struct dds_security_timed_cb_data *tcb, + struct dds_security_timed_dispatcher_t *d, + dds_security_timed_cb_t cb, + dds_time_t trigger_time, + void *arg); + +#if defined (__cplusplus) +} +#endif + +#endif /* DDS_SECURITY_TIMED_CALLBACK_H */ diff --git a/src/security/core/src/dds_security_timed_cb.c b/src/security/core/src/dds_security_timed_cb.c new file mode 100644 index 0000000..a8bfb0e --- /dev/null +++ b/src/security/core/src/dds_security_timed_cb.c @@ -0,0 +1,329 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "dds/ddsrt/atomics.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/log.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/threads.h" +#include "dds/ddsrt/time.h" +#include "dds/ddsrt/fibheap.h" + + +#include "dds/security/core/dds_security_timed_cb.h" + + +struct dds_security_timed_dispatcher_t +{ + bool active; + void *listener; + ddsrt_fibheap_t events; +}; + +struct list_dispatcher_t +{ + struct list_dispatcher_t *next; + struct dds_security_timed_dispatcher_t *dispatcher; +}; + +struct event_t +{ + ddsrt_fibheap_node_t heapnode; + dds_security_timed_cb_t callback; + dds_time_t trigger_time; + void *arg; +}; + +static int compare_timed_cb_trigger_time(const void *va, const void *vb); +static const ddsrt_fibheap_def_t timed_cb_queue_fhdef = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof(struct event_t, heapnode), compare_timed_cb_trigger_time); + +static int compare_timed_cb_trigger_time(const void *va, const void *vb) +{ + const struct event_t *a = va; + const struct event_t *b = vb; + return (a->trigger_time == b->trigger_time) ? 0 : (a->trigger_time < b->trigger_time) ? -1 : 1; +} + +struct dds_security_timed_cb_data { + ddsrt_mutex_t lock; + ddsrt_cond_t cond; + struct list_dispatcher_t *first_dispatcher_node; + ddsrt_thread_t thread; + bool terminate; +}; + + +static uint32_t timed_dispatcher_thread( + void *tcbv) +{ + struct list_dispatcher_t *dispatcher_node; + struct event_t *event; + dds_duration_t timeout; + dds_duration_t remain_time; + struct dds_security_timed_cb_data *tcb = (struct dds_security_timed_cb_data *)tcbv; + + ddsrt_mutex_lock(&tcb->lock); + do + { + remain_time = DDS_INFINITY; + for (dispatcher_node = tcb->first_dispatcher_node; dispatcher_node != NULL; dispatcher_node = dispatcher_node->next) + { + /* Just some sanity checks. */ + assert(dispatcher_node->dispatcher); + if (dispatcher_node->dispatcher->active) + { + do + { + timeout = DDS_INFINITY; + event = ddsrt_fibheap_min(&timed_cb_queue_fhdef, &dispatcher_node->dispatcher->events); + if (event) + { + /* Just some sanity checks. */ + assert(event->callback); + /* Determine the trigger timeout of this callback. */ + timeout = event->trigger_time - dds_time(); + if (timeout <= 0) + { + /* Trigger callback when related dispatcher is active. */ + event->callback(dispatcher_node->dispatcher, + DDS_SECURITY_TIMED_CB_KIND_TIMEOUT, + dispatcher_node->dispatcher->listener, + event->arg); + + /* Remove handled event from queue, continue with next. */ + ddsrt_fibheap_delete(&timed_cb_queue_fhdef, &dispatcher_node->dispatcher->events, event); + ddsrt_free(event); + } + else if (timeout < remain_time) + { + remain_time = timeout; + } + } + } + while (timeout < 0); + } + } + // tcb->cond condition may be triggered before this thread runs and causes + // this waitfor to wait infinity, hence the check of the tcb->terminate + if (((remain_time > 0) || (remain_time == DDS_INFINITY)) && !tcb->terminate) + { + /* Wait for new event, timeout or the end. */ + (void)ddsrt_cond_waitfor(&tcb->cond, &tcb->lock, remain_time); + } + + } while (!tcb->terminate); + + ddsrt_mutex_unlock(&tcb->lock); + + return 0; +} + +struct dds_security_timed_cb_data* +dds_security_timed_cb_new() +{ + struct dds_security_timed_cb_data *tcb = ddsrt_malloc(sizeof(*tcb)); + dds_return_t osres; + ddsrt_threadattr_t attr; + + ddsrt_mutex_init(&tcb->lock); + ddsrt_cond_init(&tcb->cond); + tcb->first_dispatcher_node = NULL; + tcb->terminate = false; + + ddsrt_threadattr_init(&attr); + osres = ddsrt_thread_create(&tcb->thread, "security_dispatcher", &attr, timed_dispatcher_thread, (void*)tcb); + if (osres != DDS_RETCODE_OK) + { + DDS_FATAL("Cannot create thread security_dispatcher"); + } + + return tcb; +} + +void +dds_security_timed_cb_free( + struct dds_security_timed_cb_data *tcb) +{ + ddsrt_mutex_lock(&tcb->lock); + tcb->terminate = true; + ddsrt_mutex_unlock(&tcb->lock); + ddsrt_cond_signal(&tcb->cond); + ddsrt_thread_join(tcb->thread, NULL); + + ddsrt_cond_destroy(&tcb->cond); + ddsrt_mutex_destroy(&tcb->lock); + ddsrt_free(tcb); +} + + +struct dds_security_timed_dispatcher_t* +dds_security_timed_dispatcher_new( + struct dds_security_timed_cb_data *tcb) +{ + struct dds_security_timed_dispatcher_t *d; + struct list_dispatcher_t *dispatcher_node_new; + struct list_dispatcher_t *dispatcher_node_wrk; + + /* New dispatcher. */ + d = ddsrt_malloc(sizeof(struct dds_security_timed_dispatcher_t)); + memset(d, 0, sizeof(struct dds_security_timed_dispatcher_t)); + + ddsrt_fibheap_init(&timed_cb_queue_fhdef, &d->events); + + dispatcher_node_new = ddsrt_malloc(sizeof(struct list_dispatcher_t)); + memset(dispatcher_node_new, 0, sizeof(struct list_dispatcher_t)); + dispatcher_node_new->dispatcher = d; + + ddsrt_mutex_lock(&tcb->lock); + + /* Append to list */ + if (tcb->first_dispatcher_node) { + struct list_dispatcher_t *last = NULL; + for (dispatcher_node_wrk = tcb->first_dispatcher_node; dispatcher_node_wrk != NULL; dispatcher_node_wrk = dispatcher_node_wrk->next) { + last = dispatcher_node_wrk; + } + last->next = dispatcher_node_new; + } else { + /* This new event is the first one. */ + tcb->first_dispatcher_node = dispatcher_node_new; + } + + ddsrt_mutex_unlock(&tcb->lock); + + + return d; +} + +void +dds_security_timed_dispatcher_free( + struct dds_security_timed_cb_data *tcb, + struct dds_security_timed_dispatcher_t *d) +{ + struct event_t *event; + struct list_dispatcher_t *dispatcher_node; + struct list_dispatcher_t *dispatcher_node_prev; + + assert(d); + + /* Remove related events from queue. */ + ddsrt_mutex_lock(&tcb->lock); + + while((event = ddsrt_fibheap_extract_min(&timed_cb_queue_fhdef, &d->events)) != NULL) + { + event->callback(d, DDS_SECURITY_TIMED_CB_KIND_DELETE, NULL, event->arg); + ddsrt_free(event); + } + + /* Remove dispatcher from list */ + dispatcher_node_prev = NULL; + for (dispatcher_node = tcb->first_dispatcher_node; dispatcher_node != NULL; dispatcher_node = dispatcher_node->next) + { + if (dispatcher_node->dispatcher == d) + { + /* remove element */ + if (dispatcher_node_prev != NULL) + { + dispatcher_node_prev->next = dispatcher_node->next; + } + else + { + tcb->first_dispatcher_node = dispatcher_node->next; + } + + ddsrt_free(dispatcher_node); + break; + } + dispatcher_node_prev = dispatcher_node; + } + /* Free this dispatcher. */ + ddsrt_free(d); + + ddsrt_mutex_unlock(&tcb->lock); + +} + + +void +dds_security_timed_dispatcher_enable( + struct dds_security_timed_cb_data *tcb, + struct dds_security_timed_dispatcher_t *d, + void *listener) +{ + assert(d); + assert(!(d->active)); + + ddsrt_mutex_lock(&tcb->lock); + + /* Remember possible listener and activate. */ + d->listener = listener; + d->active = true; + + /* Start thread when not running, otherwise wake it up to + * trigger callbacks that were (possibly) previously added. */ + ddsrt_cond_signal(&tcb->cond); + + ddsrt_mutex_unlock(&tcb->lock); +} + + +void +dds_security_timed_dispatcher_disable( + struct dds_security_timed_cb_data *tcb, + struct dds_security_timed_dispatcher_t *d) +{ + assert(d); + assert(d->active); + + ddsrt_mutex_lock(&tcb->lock); + + /* Forget listener and deactivate. */ + d->listener = NULL; + d->active = false; + + ddsrt_mutex_unlock(&tcb->lock); +} + + +void +dds_security_timed_dispatcher_add( + struct dds_security_timed_cb_data *tcb, + struct dds_security_timed_dispatcher_t *d, + dds_security_timed_cb_t cb, + dds_time_t trigger_time, + void *arg) +{ + struct event_t *event_new; + + assert(d); + assert(cb); + + /* Create event. */ + event_new = ddsrt_malloc(sizeof(struct event_t)); + memset(event_new, 0, sizeof(struct event_t)); + event_new->trigger_time = trigger_time; + event_new->callback = cb; + event_new->arg = arg; + + /* Insert event based on trigger_time. */ + ddsrt_mutex_lock(&tcb->lock); + ddsrt_fibheap_insert(&timed_cb_queue_fhdef, &d->events, event_new); + ddsrt_mutex_unlock(&tcb->lock); + + /* Wake up thread (if it's running). */ + ddsrt_cond_signal(&tcb->cond); +} + diff --git a/src/security/core/tests/CMakeLists.txt b/src/security/core/tests/CMakeLists.txt index 40a6650..9cd0e27 100644 --- a/src/security/core/tests/CMakeLists.txt +++ b/src/security/core/tests/CMakeLists.txt @@ -14,6 +14,7 @@ include (CUnit) set(security_core_test_sources "tc_fsm.c" + "dds_security_core.c" ) add_definitions(-DDDSI_INCLUDE_SECURITY) diff --git a/src/security/core/tests/dds_security_core.c b/src/security/core/tests/dds_security_core.c new file mode 100644 index 0000000..ac494c2 --- /dev/null +++ b/src/security/core/tests/dds_security_core.c @@ -0,0 +1,546 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#include +#include "CUnit/Test.h" + +#include "dds/security/core/dds_security_timed_cb.h" +#include "dds/ddsrt/misc.h" + +#define SEQ_SIZE (16) + +typedef struct { + struct dds_security_timed_dispatcher_t *d; + dds_security_timed_cb_kind kind; + void *listener; + void *arg; + dds_time_t time; +} tc__sequence_data; + +static int g_sequence_idx = 0; +static tc__sequence_data g_sequence_array[SEQ_SIZE]; + +static void simple_callback(struct dds_security_timed_dispatcher_t *d, + dds_security_timed_cb_kind kind, + void *listener, + void *arg) +{ + DDSRT_UNUSED_ARG(d); + DDSRT_UNUSED_ARG(kind); + DDSRT_UNUSED_ARG(listener); + + if (*((bool *)arg) == false) + { + *((bool *)arg) = true; + } + else + { + *((bool *)arg) = false; + } +} + +static int g_order_callback_idx = 0; +static void* g_order_callback[2] = {(void*)NULL, (void*)NULL}; +static void order_callback(struct dds_security_timed_dispatcher_t *d, + dds_security_timed_cb_kind kind, + void *listener, + void *arg) +{ + DDSRT_UNUSED_ARG(d); + DDSRT_UNUSED_ARG(kind); + DDSRT_UNUSED_ARG(listener); + + g_order_callback[g_order_callback_idx] = arg; + g_order_callback_idx++; +} + +static void +tc__callback( + struct dds_security_timed_dispatcher_t *d, + dds_security_timed_cb_kind kind, + void *listener, + void *arg) +{ + if (g_sequence_idx < SEQ_SIZE) { + g_sequence_array[g_sequence_idx].d = d; + g_sequence_array[g_sequence_idx].arg = arg; + g_sequence_array[g_sequence_idx].kind = kind; + g_sequence_array[g_sequence_idx].listener = listener; + g_sequence_array[g_sequence_idx].time = dds_time(); + } + g_sequence_idx++; +} + +CU_Test(dds_security_timed_cb, simple_test) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + struct dds_security_timed_dispatcher_t *d1 = NULL; + static bool test_var = false; + + dds_time_t now = dds_time(); + dds_time_t future = now + DDS_SECS(2); + + d1 = dds_security_timed_dispatcher_new(tcb); + + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void*)&test_var); + + dds_security_timed_dispatcher_enable(tcb, d1, (void*)NULL); + + CU_ASSERT_FALSE_FATAL(test_var); + + dds_sleepfor(DDS_MSECS(500)); + + CU_ASSERT_FALSE_FATAL(test_var); + + dds_sleepfor(DDS_SECS(2)); + + CU_ASSERT_TRUE_FATAL(test_var); + + dds_security_timed_dispatcher_free(tcb, d1); + + dds_security_timed_cb_free(tcb); +} + +CU_Test(dds_security_timed_cb, simple_order) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + struct dds_security_timed_dispatcher_t *d1 = NULL; + dds_time_t future; + dds_time_t future2; + + d1 = dds_security_timed_dispatcher_new(tcb); + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + future = dds_time() + DDS_MSECS(20); + future2 = future; + dds_security_timed_dispatcher_add(tcb, d1, order_callback, future, (void*)1); + dds_security_timed_dispatcher_add(tcb, d1, order_callback, future2, (void*)2); + dds_security_timed_dispatcher_enable(tcb, d1, (void*)&g_order_callback); + dds_sleepfor(DDS_MSECS(10)); + + dds_security_timed_dispatcher_free(tcb, d1); + + CU_ASSERT_EQUAL_FATAL(g_order_callback[0], (void*)1); + CU_ASSERT_EQUAL_FATAL(g_order_callback[1], (void*)2); + + dds_security_timed_cb_free(tcb); +} + +CU_Test(dds_security_timed_cb, test_enabled_and_disabled) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + struct dds_security_timed_dispatcher_t *d1 = NULL; + static bool test_var = false; + + dds_time_t now = dds_time(); + dds_time_t future = now + DDS_SECS(2); + + d1 = dds_security_timed_dispatcher_new(tcb); + + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void*)&test_var); + + dds_security_timed_dispatcher_enable(tcb, d1, (void*)NULL); + + CU_ASSERT_FALSE(test_var); + + dds_security_timed_dispatcher_disable(tcb, d1); + + dds_sleepfor(DDS_MSECS(500)); + + CU_ASSERT_FALSE(test_var); + + dds_sleepfor(DDS_SECS(2)); + + CU_ASSERT_FALSE(test_var); + + dds_security_timed_dispatcher_free(tcb, d1); + + dds_security_timed_cb_free(tcb); +} + +CU_Test(dds_security_timed_cb, simple_test_with_future) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + struct dds_security_timed_dispatcher_t *d1 = NULL; + static bool test_var = false; + + dds_time_t now = dds_time(); + dds_time_t future = now + DDS_SECS(2); + dds_time_t far_future = now + DDS_SECS(10); + + d1 = dds_security_timed_dispatcher_new(tcb); + + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + + dds_security_timed_dispatcher_enable(tcb, d1, (void*)NULL); + + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void*)&test_var); + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, far_future, (void*)&test_var); + + CU_ASSERT_FALSE_FATAL(test_var); + + dds_sleepfor(DDS_MSECS(500)); + + CU_ASSERT_FALSE_FATAL(test_var); + + dds_sleepfor(DDS_SECS(2)); + + CU_ASSERT_TRUE_FATAL(test_var); + + dds_security_timed_dispatcher_free(tcb, d1); + + dds_security_timed_cb_free(tcb); +} + +CU_Test(dds_security_timed_cb, test_multiple_dispatchers) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + struct dds_security_timed_dispatcher_t *d1 = NULL; + struct dds_security_timed_dispatcher_t *d2 = NULL; + static bool test_var = false; + + dds_time_t now = dds_time(); + dds_time_t future = now + DDS_SECS(2); + dds_time_t far_future = now + DDS_SECS(10); + + d1 = dds_security_timed_dispatcher_new(tcb); + d2 = dds_security_timed_dispatcher_new(tcb); + + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + + dds_security_timed_dispatcher_enable(tcb, d1, (void*)NULL); + dds_security_timed_dispatcher_enable(tcb, d2, (void*)NULL); + + dds_security_timed_dispatcher_free(tcb, d2); + + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void*)&test_var); + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, far_future, (void*)&test_var); + + CU_ASSERT_FALSE_FATAL(test_var); + + dds_sleepfor(DDS_MSECS(500)); + + CU_ASSERT_FALSE_FATAL(test_var); + + dds_sleepfor(DDS_SECS(2)); + + CU_ASSERT_TRUE_FATAL(test_var); + + dds_security_timed_dispatcher_free(tcb, d1); + + dds_security_timed_cb_free(tcb); +} + +CU_Test(dds_security_timed_cb, test_not_enabled_multiple_dispatchers) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + struct dds_security_timed_dispatcher_t *d1 = NULL; + struct dds_security_timed_dispatcher_t *d2 = NULL; + + d1 = dds_security_timed_dispatcher_new(tcb); + d2 = dds_security_timed_dispatcher_new(tcb); + + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + CU_ASSERT_PTR_NOT_NULL_FATAL(d2); + + dds_security_timed_dispatcher_free(tcb, d2); + + dds_security_timed_dispatcher_free(tcb, d1); + + dds_security_timed_cb_free(tcb); + + CU_PASS("Timed callbacks enabled and disabled without add"); +} + +CU_Test(dds_security_timed_cb, test_create_dispatcher) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + struct dds_security_timed_dispatcher_t *d1 = NULL; + struct dds_security_timed_dispatcher_t *d2 = NULL; + struct dds_security_timed_dispatcher_t *d3 = NULL; + struct dds_security_timed_dispatcher_t *d4 = NULL; + struct dds_security_timed_dispatcher_t *d5 = NULL; + bool ok = false; + + dds_time_t now = dds_time(); + dds_time_t past = now - DDS_SECS(1); + dds_time_t present = now + DDS_SECS(1); + dds_time_t future = present + DDS_SECS(1); + dds_time_t future2 = future + DDS_SECS(10); + + /************************************************************************* + * Check if dispatchers can be created + *************************************************************************/ + d1 = dds_security_timed_dispatcher_new(tcb); + d2 = dds_security_timed_dispatcher_new(tcb); + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + CU_ASSERT_PTR_NOT_NULL_FATAL(d2); + + /************************************************************************* + * Check if adding callbacks succeeds + *************************************************************************/ + + /* The last argument is a sequence number in which + * the callbacks are expected to be called. */ + /* We can only really check if it crashes or not... */ + dds_security_timed_dispatcher_add(tcb, d1, tc__callback, present, (void*)1); + dds_security_timed_dispatcher_add(tcb, d2, tc__callback, past, (void*)0); + dds_security_timed_dispatcher_add(tcb, d2, tc__callback, present, (void*)2); + dds_security_timed_dispatcher_add(tcb, d1, tc__callback, future, (void*)7); + + CU_PASS("Added callbacks") + + /************************************************************************* + * Check if dispatchers can be created + *************************************************************************/ + d3 = dds_security_timed_dispatcher_new(tcb); + d4 = dds_security_timed_dispatcher_new(tcb); + d5 = dds_security_timed_dispatcher_new(tcb); + + CU_ASSERT_PTR_NOT_NULL_FATAL(d3); + CU_ASSERT_PTR_NOT_NULL_FATAL(d4); + CU_ASSERT_PTR_NOT_NULL_FATAL(d5); + + + /************************************************************************* + * Check if enabling dispatchers succeeds + *************************************************************************/ + + /* The sleeps are added to get the timing between + * 'present' and 'past' callbacks right. */ + /* We can only really check if it crashes or not... */ + dds_sleepfor(DDS_MSECS(600)); + dds_security_timed_dispatcher_enable(tcb, d1, (void*)NULL); + dds_security_timed_dispatcher_enable(tcb, d2, (void*) d2); + dds_security_timed_dispatcher_enable(tcb, d3, (void*)NULL); + /* Specifically not enabling d4 and d5. */ + dds_sleepfor(DDS_MSECS(600)); + CU_PASS("Enabled dds_security_timed_dispatchers."); + + /************************************************************************* + * Check if adding callbacks succeeds + *************************************************************************/ + + /* The last argument is a sequence number in which + * the callbacks are expected to be called. */ + /* We can only really check if it crashes or not... */ + dds_security_timed_dispatcher_add(tcb, d4, tc__callback, past, (void*)99); + dds_security_timed_dispatcher_add(tcb, d2, tc__callback, future, (void*) 8); + dds_security_timed_dispatcher_add(tcb, d3, tc__callback, future2, (void*) 9); + dds_security_timed_dispatcher_add(tcb, d1, tc__callback, past, (void*) 3); + dds_security_timed_dispatcher_add(tcb, d1, tc__callback, future2, (void*)10); + dds_security_timed_dispatcher_add(tcb, d1, tc__callback, present, (void*) 4); + dds_security_timed_dispatcher_add(tcb, d2, tc__callback, present, (void*) 5); + dds_security_timed_dispatcher_add(tcb, d1, tc__callback, future, (void*) 6); + dds_security_timed_dispatcher_add(tcb, d3, tc__callback, future2, (void*)11); + CU_PASS("Added callbacks."); + + + /************************************************************************* + * Check if timeout callbacks are triggered in the right sequence + *************************************************************************/ + + int idx; + int timeout = 200; /* 2 seconds */ + + /* Wait for the callbacks to have been triggered. + * Ignore the ones in the far future. */ + while ((g_sequence_idx < 8) && (timeout > 0)) { + dds_sleepfor(DDS_MSECS(10)); + timeout--; + } + + /* Print and check sequence of triggered callbacks. */ + for (idx = 0; (idx < g_sequence_idx) && (idx < SEQ_SIZE); idx++) { + int seq = (int)(long long)(g_sequence_array[idx].arg); + struct dds_security_timed_dispatcher_t *expected_d; + void *expected_l; + + /* + * Sequence checks. + */ + if ((seq == 1) || (seq == 6) || (seq == 3) || (seq == 10) || (seq == 4) || (seq == 7)) { + expected_d = d1; + expected_l = NULL; + } else if ((seq == 0) || (seq == 2) || (seq == 8) || (seq == 5)) { + expected_d = d2; + expected_l = d2; + } else if (seq == 9) { + expected_d = d3; + expected_l = NULL; + } else if (seq == 99) { + expected_d = d4; + expected_l = NULL; + CU_FAIL("Unexpected callback on a disabled dispatcher"); + ok = false; + } else { + expected_d = NULL; + expected_l = NULL; + CU_FAIL(sprintf("Unknown sequence idx received %d", seq)); + ok = false; + } + + if (seq != idx) { + /* 6 and 7 order may be mixed since the order is not defined for same time stamp */ + if (!((seq == 6 && idx == 7) || (seq == 7 && idx == 6))) + { + printf("Unexpected sequence ordering %d vs %d\n", seq, idx); + CU_FAIL("Unexpected sequence ordering"); + ok = false; + } + } + if (seq > 8) { + CU_FAIL(sprintf("Unexpected sequence idx %d of the far future", seq)); + ok = false; + } + if (idx > 8) { + CU_FAIL(sprintf("Too many callbacks %d", idx)); + ok = false; + } + + /* + * Callback contents checks. + */ + if (expected_d != NULL) { + if (g_sequence_array[idx].d != expected_d) { + printf("Unexpected dispatcher %p vs %p\n", g_sequence_array[idx].d, expected_d); + CU_FAIL("Unexpected dispatcher"); + ok = false; + } + if (g_sequence_array[idx].listener != expected_l) { + CU_FAIL(sprintf("Unexpected listener %p vs %p", g_sequence_array[idx].listener, expected_l)); + ok = false; + } + } + + /* + * Callback kind check. + */ + if (g_sequence_array[idx].kind != DDS_SECURITY_TIMED_CB_KIND_TIMEOUT) { + CU_FAIL(sprintf("Unexpected kind %d vs %d", (int)g_sequence_array[idx].kind, (int)DDS_SECURITY_TIMED_CB_KIND_TIMEOUT)); + ok = false; + } + } + if (g_sequence_idx < 8) { + CU_FAIL(sprintf("Received %d callbacks, while 9 are expected", + g_sequence_idx + 1)); + ok = false; + } + if (ok) { + CU_FAIL(sprintf("Received timeout callbacks.")); + } + + /* Reset callback index to catch the deletion ones. */ + g_sequence_idx = 0; + + + /************************************************************************* + * Check if deleting succeeds with dispatchers in different states + *************************************************************************/ + /* We can only really check if it crashes or not... */ + if (d1) { + dds_security_timed_dispatcher_free(tcb, d1); + } + if (d2) { + dds_security_timed_dispatcher_free(tcb, d2); + } + if (d3) { + dds_security_timed_dispatcher_free(tcb, d3); + } + if (d4) { + dds_security_timed_dispatcher_free(tcb, d4); + } + if (d5) { + dds_security_timed_dispatcher_free(tcb, d5); + } + CU_PASS("Deleted dispatchers."); + + + /************************************************************************* + * Check if deletion callbacks are triggered + *************************************************************************/ + if (ok) { + timeout = 200; /* 2 seconds */ + + /* Wait for the callbacks to have been triggered. + * Ignore the ones in the far future. */ + while ((g_sequence_idx < 4) && (timeout > 0)) { + dds_sleepfor(DDS_MSECS(10)); + timeout--; + } + + /* Print and check sequence of triggered callbacks. */ + for (idx = 0; (idx < g_sequence_idx) && (idx < SEQ_SIZE); idx++) { + int seq = (int)(long long)(g_sequence_array[idx].arg); + struct dds_security_timed_dispatcher_t *expected_d; + + /* + * Human (somewhat) readable format. + */ + // tc__sequence_data_print(&(g_sequence_array[idx])); + + /* + * Sequence checks. + */ + if (seq == 99) { + expected_d = d4; + } else if ((seq == 9) || (seq == 11)) { + expected_d = d3; + } else if (seq == 10) { + expected_d = d1; + } else { + expected_d = NULL; + CU_FAIL(sprintf("Unexpected sequence idx received %d", seq)); + ok = false; + } + if (idx > 4) { + CU_FAIL(sprintf("Too many callbacks %d", idx)); + ok = false; + } + + /* + * Callback contents checks. + */ + if (expected_d != NULL) { + if (g_sequence_array[idx].d != expected_d) { + CU_FAIL(sprintf("Unexpected dispatcher %p vs %p", g_sequence_array[idx].d, expected_d)); + ok = false; + } + if (g_sequence_array[idx].listener != NULL) { + CU_FAIL(sprintf("Unexpected listener %p vs NULL", g_sequence_array[idx].listener)); + ok = false; + } + } + + /* + * Callback kind check. + */ + if (g_sequence_array[idx].kind != DDS_SECURITY_TIMED_CB_KIND_DELETE) { + CU_FAIL(sprintf("Unexpected kind %d vs %d", (int)g_sequence_array[idx].kind, (int)DDS_SECURITY_TIMED_CB_KIND_TIMEOUT)); + ok = false; + } + } + if (g_sequence_idx < 4) { + CU_FAIL(sprintf("Received %d callbacks, while 3 are expected", + g_sequence_idx + 1)); + ok = false; + } + if (ok) { + CU_PASS("Received deletion callbacks."); + } + } + + dds_security_timed_cb_free(tcb); +} From 68f789d77b11a86618b1620ef1d56b2cc8d264f1 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sun, 19 Jan 2020 17:00:18 +0100 Subject: [PATCH 093/238] Address some spurious Clang static analyzer warnings Signed-off-by: Erik Boasson Fix typo in dlopen_unknown test Signed-off-by: Dennis Potman Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_qos.c | 2 ++ src/core/ddsc/tests/qos.c | 6 ++++++ src/core/ddsi/src/q_xevent.c | 10 +--------- src/core/ddsi/tests/security_msg.c | 2 ++ src/ddsrt/tests/dynlib.c | 8 +++++++- src/ddsrt/tests/string.c | 2 ++ 6 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/core/ddsc/src/dds_qos.c b/src/core/ddsc/src/dds_qos.c index 1cebe53..d13eeeb 100644 --- a/src/core/ddsc/src/dds_qos.c +++ b/src/core/ddsc/src/dds_qos.c @@ -403,6 +403,7 @@ void dds_qset_prop (dds_qos_t * __restrict qos, const char * name, const char * dds_qprop_init (qos); if (dds_qprop_get_index (qos, name, &i)) { + assert (&qos->property.value.props[i] != NULL); /* for Clang static analyzer */ dds_free (qos->property.value.props[i].value); qos->property.value.props[i].value = dds_string_dup (value); } @@ -426,6 +427,7 @@ void dds_qset_bprop (dds_qos_t * __restrict qos, const char * name, const void * dds_qprop_init (qos); if (dds_qbprop_get_index (qos, name, &i)) { + assert (&qos->property.binary_value.props[i].value != NULL); /* for Clang static analyzer */ dds_qos_data_copy_in (&qos->property.binary_value.props[i].value, value, sz, true); } else diff --git a/src/core/ddsc/tests/qos.c b/src/core/ddsc/tests/qos.c index 3e6e644..24be7d3 100644 --- a/src/core/ddsc/tests/qos.c +++ b/src/core/ddsc/tests/qos.c @@ -11,6 +11,7 @@ */ #include "CUnit/Test.h" #include "dds/dds.h" +#include /**************************************************************************** * Convenience global policies @@ -746,6 +747,7 @@ CU_Test(ddsc_qos, bproperty, .init=qos_init, .fini=qos_fini) CU_ASSERT_FATAL(dds_qget_bprop (g_qos, c_bproperty_names[0], &bvalue, &size)); CU_ASSERT_FATAL (bvalue != NULL); CU_ASSERT_EQUAL_FATAL (size, 3); + assert (c_bproperty_values[0] != NULL); /* for Clang static analyzer */ CU_ASSERT_EQUAL_FATAL (memcmp (bvalue, c_bproperty_values[0], size), 0); dds_free (bvalue); @@ -754,6 +756,7 @@ CU_Test(ddsc_qos, bproperty, .init=qos_init, .fini=qos_fini) CU_ASSERT_FATAL (dds_qget_bprop (g_qos, c_bproperty_names[0], &bvalue, &size)); CU_ASSERT_FATAL (bvalue != NULL); CU_ASSERT_EQUAL_FATAL (size, 3); + assert (c_bproperty_values[1] != NULL); /* for Clang static analyzer */ CU_ASSERT_EQUAL_FATAL (memcmp (bvalue, c_bproperty_values[1], size), 0); dds_free (bvalue); dds_qset_bprop (g_qos, c_bproperty_names[0], &c_bproperty_values[0], 3); @@ -782,11 +785,13 @@ CU_Test(ddsc_qos, bproperty, .init=qos_init, .fini=qos_fini) CU_ASSERT_FATAL (dds_qget_bprop (g_qos, c_bproperty_names[0], &bvalue, &size)); CU_ASSERT_FATAL (bvalue != NULL); CU_ASSERT_EQUAL_FATAL (size, 3); + assert (c_bproperty_values[0] != NULL); /* for Clang static analyzer */ CU_ASSERT_EQUAL_FATAL (memcmp (bvalue, c_bproperty_values[0], size), 0); dds_free (bvalue); CU_ASSERT_FATAL (dds_qget_bprop (g_qos, c_bproperty_names[2], &bvalue, &size)); CU_ASSERT_FATAL (bvalue != NULL); CU_ASSERT_EQUAL_FATAL (size, 3); + assert (c_bproperty_values[2] != NULL); /* for Clang static analyzer */ CU_ASSERT_EQUAL_FATAL (memcmp (bvalue, c_bproperty_values[2], size), 0); dds_free (bvalue); dds_qunset_bprop (g_qos, c_bproperty_names[0]); @@ -809,6 +814,7 @@ CU_Test(ddsc_qos, property_mixed, .init=qos_init, .fini=qos_fini) CU_ASSERT_FATAL (dds_qget_bprop (g_qos, c_property_names[0], &bvalue, &size)); CU_ASSERT_FATAL (bvalue != NULL); CU_ASSERT_EQUAL_FATAL (size, 3); + assert (c_bproperty_values[0] != NULL); /* for Clang static analyzer */ CU_ASSERT_EQUAL_FATAL (memcmp (bvalue, c_bproperty_values[0], size), 0); dds_free (bvalue); CU_ASSERT_FATAL (dds_qget_prop (g_qos, c_property_names[0], &value)); diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index 4ff5608..3c852d5 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -584,7 +584,6 @@ static void send_heartbeat_to_all_readers(struct nn_xpack *xp, struct xevent *ev { struct whc_state whcst; nn_mtime_t t_next; - int hbansreq = 0; unsigned count = 0; ddsrt_mutex_lock (&wr->e.lock); @@ -592,21 +591,14 @@ static void send_heartbeat_to_all_readers(struct nn_xpack *xp, struct xevent *ev whc_get_state(wr->whc, &whcst); if (!writer_must_have_hb_scheduled (wr, &whcst)) - { - hbansreq = 1; /* just for trace */ t_next.v = T_NEVER; - } else if (!writer_hbcontrol_must_send (wr, &whcst, tnow)) - { - hbansreq = 1; /* just for trace */ t_next.v = tnow.v + writer_hbcontrol_intv (wr, &whcst, tnow); - } else { struct wr_prd_match *m; struct ddsi_guid last_guid = { .prefix = {.u = {0,0,0}}, .entityid = {0} }; - - hbansreq = writer_hbcontrol_ack_required (wr, &whcst, tnow); + const int hbansreq = writer_hbcontrol_ack_required (wr, &whcst, tnow); t_next.v = tnow.v + writer_hbcontrol_intv (wr, &whcst, tnow); while ((m = ddsrt_avl_lookup_succ (&wr_readers_treedef, &wr->readers, &last_guid)) != NULL) diff --git a/src/core/ddsi/tests/security_msg.c b/src/core/ddsi/tests/security_msg.c index 87bd734..c052a89 100644 --- a/src/core/ddsi/tests/security_msg.c +++ b/src/core/ddsi/tests/security_msg.c @@ -15,6 +15,7 @@ #include "dds/ddsrt/string.h" #include "dds/ddsi/ddsi_security_msg.h" #include "mem_ser.h" +#include static nn_participant_generic_message_t test_msg_in = { @@ -302,6 +303,7 @@ CU_Test (ddsi_security_msg, serializer) /* Check serialization result. */ size_t cmpsize = (len < sizeof(test_msg_ser)) ? len : sizeof(test_msg_ser); + assert(data != NULL); /* for Clang static analyzer */ if (memcmp (data, test_msg_ser, cmpsize) != 0) { printf ("memcmp(%d)\n", (int)cmpsize); diff --git a/src/ddsrt/tests/dynlib.c b/src/ddsrt/tests/dynlib.c index 76d5871..9b8d5df 100644 --- a/src/ddsrt/tests/dynlib.c +++ b/src/ddsrt/tests/dynlib.c @@ -87,7 +87,7 @@ CU_Test(ddsrt_library, dlopen_unknown) ddsrt_dynlib_t l; r = ddsrt_dlopen("UnknownLib", false, &l); - + CU_ASSERT_NOT_EQUAL(r, DDS_RETCODE_OK); CU_ASSERT_PTR_NULL_FATAL(l); r = ddsrt_dlerror(buffer, sizeof(buffer)); @@ -123,6 +123,7 @@ CU_Test(ddsrt_library, dlsym_unknown) void* f; r = ddsrt_dlopen(TEST_LIB_NAME, true, &l); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); CU_ASSERT_PTR_NOT_NULL(l); TEST_ABORT_IF_NULL(l,"ddsrt_dlopen() failed. Is the proper library path set?"); @@ -150,17 +151,21 @@ CU_Test(ddsrt_library, call) ddsrt_dynlib_t l; r = ddsrt_dlopen(TEST_LIB_NAME, true, &l); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); CU_ASSERT_PTR_NOT_NULL(l); TEST_ABORT_IF_NULL(l, "ddsrt_dlopen() failed. Is the proper library path set?"); r = ddsrt_dlsym(l, "get_int", (void **)&f_get); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); CU_ASSERT_PTR_NOT_NULL(f_get); TEST_ABORT_IF_NULL(f_get, "ddsrt_dlsym(l, \"get_int\") failed."); r = ddsrt_dlsym(l, "set_int", (void **)&f_set); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); CU_ASSERT_PTR_NOT_NULL(f_set); TEST_ABORT_IF_NULL(f_set, "ddsrt_dlsym(l, \"set_int\") failed."); + assert(f_set != 0 && f_get != 0); /* for Clang static analyzer */ f_set(set_int); get_int = f_get(); CU_ASSERT_EQUAL(set_int, get_int); @@ -175,6 +180,7 @@ CU_Test(ddsrt_library, dlclose_error) ddsrt_dynlib_t l; r = ddsrt_dlopen(TEST_LIB_NAME, true, &l); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); CU_ASSERT_PTR_NOT_NULL(l); TEST_ABORT_IF_NULL(l, "ddsrt_dlopen() failed. Is the proper library path set?"); diff --git a/src/ddsrt/tests/string.c b/src/ddsrt/tests/string.c index babe9af..2d809ea 100644 --- a/src/ddsrt/tests/string.c +++ b/src/ddsrt/tests/string.c @@ -10,6 +10,7 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include +#include #include "CUnit/Theory.h" #include "dds/ddsrt/heap.h" @@ -82,6 +83,7 @@ CU_Theory((const char *str, const char *srch, const char *subst, size_t max, con if (exp != NULL) { CU_ASSERT_FATAL(r != NULL); + assert(r != NULL); /* for Clang static analyzer */ CU_ASSERT(strcmp(r, exp) == 0); ddsrt_free(r); } From 3b4facbd454308247e7be3a423e1f1f44cf944d7 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Thu, 21 Nov 2019 12:01:34 +0100 Subject: [PATCH 094/238] DDS Security built-in Access Control plugin This commit adds the build-in Access Control plugin that is part of the DDS Security implementation for Cyclone. The Access Control Plugin API defines the types and operations necessary to support an access control mechanism for DDS Domain Participants. Similar to other builtin plugins, the DDS Security access control plugin is built as a shared library to allow dynamic library loading on runtime. This enables DDS participants to use specific plugin implementations with different configurations. This commit includes some basic tests for the access control functions. This initial version of the plugin does not support permissions expiry (not-valid-after date in permissions configuration). Signed-off-by: Dennis Potman Process review comments for access control plugin Signed-off-by: Dennis Potman Part 2 of processing review changes for access control Signed-off-by: Dennis Potman Add test for topicname dcps, add comment for xml date parser Signed-off-by: Dennis Potman Fixed an bug in leap year count for year 2200, changed the rounding for sub-ns fraction and added an additional overflow test in DDS_Security_parse_xml_date Signed-off-by: Dennis Potman --- src/core/ddsc/src/dds__topic.h | 2 + src/core/ddsc/src/dds_builtin.c | 2 +- src/core/ddsc/src/dds_topic.c | 11 +- src/core/ddsc/tests/topic.c | 2 +- .../dds/security/dds_security_api_err.h | 10 +- src/security/builtin_plugins/CMakeLists.txt | 1 + .../access_control/CMakeLists.txt | 55 + .../access_control/src/access_control.c | 2486 +++++++++++++++++ .../access_control/src/access_control.h | 21 + .../src/access_control_objects.c | 283 ++ .../src/access_control_objects.h | 106 + .../src/access_control_parser.c | 1212 ++++++++ .../src/access_control_parser.h | 301 ++ .../access_control/src/access_control_utils.c | 406 +++ .../access_control/src/access_control_utils.h | 30 + .../builtin_plugins/tests/CMakeLists.txt | 27 +- .../src/access_control_fnmatch_utests.c | 67 + .../etc/Test_Governance_ok.p7s | 114 + .../etc/Test_Permissions_ok.p7s | 85 + .../get_permissions_credential_token_utests.c | 497 ++++ .../etc/Test_Governance_ok.p7s | 114 + .../etc/Test_Permissions_ok.p7s | 85 + .../src/get_permissions_token_utests.c | 439 +++ .../etc/Test_Governance_full.p7s | 267 ++ ..._Governance_liveliness_discovery_clear.p7s | 114 + ..._Governance_liveliness_discovery_clear.xml | 62 + ...ernance_liveliness_discovery_different.p7s | 114 + ...ernance_liveliness_discovery_different.xml | 62 + ...ernance_liveliness_discovery_encrypted.p7s | 114 + ...ernance_liveliness_discovery_encrypted.xml | 62 + ..._discovery_encrypted_and_authenticated.p7s | 114 + ..._discovery_encrypted_and_authenticated.xml | 62 + ...Governance_liveliness_discovery_signed.p7s | 114 + ...Governance_liveliness_discovery_signed.xml | 62 + ...ess_discovery_signed_and_authenticated.p7s | 114 + ...ess_discovery_signed_and_authenticated.xml | 62 + .../etc/Test_Permissions_ok.p7s | 85 + .../src/get_xxx_sec_attributes_utests.c | 1649 +++++++++++ .../etc/Test_Governance_ok.p7s | 114 + .../etc/Test_Permissions_ca.pem | 22 + .../etc/Test_Permissions_ca_key.pem | 27 + .../etc/Test_Permissions_listener.p7s | 51 + .../src/listeners_access_control_utests.c | 671 +++++ .../etc/Test_File_empty.txt | 0 .../etc/Test_File_text.txt | 3 + ...st_Governance_check_create_participant.p7s | 199 ++ ...st_Governance_check_create_participant.xml | 147 + .../etc/Test_Governance_full.p7s | 267 ++ .../etc/Test_Governance_full.xml | 215 ++ .../etc/Test_Governance_invalid_data.p7s | 175 ++ .../etc/Test_Governance_invalid_data.xml | 123 + .../etc/Test_Governance_invalid_element.p7s | 178 ++ .../etc/Test_Governance_invalid_element.xml | 126 + .../etc/Test_Governance_not_signed.p7s | 62 + .../etc/Test_Governance_ok.p7s | 114 + .../etc/Test_Governance_unknown_ca.p7s | 117 + .../etc/Test_Permissions_ca.pem | 22 + .../etc/Test_Permissions_ca_key.pem | 27 + .../etc/Test_Permissions_expired.p7s | 243 ++ .../etc/Test_Permissions_expired.xml | 191 ++ .../etc/Test_Permissions_full.p7s | 243 ++ .../etc/Test_Permissions_full.xml | 191 ++ .../etc/Test_Permissions_invalid_data.p7s | 219 ++ .../etc/Test_Permissions_invalid_data.xml | 167 ++ .../etc/Test_Permissions_invalid_element.p7s | 219 ++ .../etc/Test_Permissions_invalid_element.xml | 167 ++ .../Test_Permissions_lack_of_not_after.p7s | 95 + .../Test_Permissions_lack_of_not_after.xml | 43 + .../Test_Permissions_lack_of_not_before.p7s | 95 + .../Test_Permissions_lack_of_not_before.xml | 43 + .../etc/Test_Permissions_not_signed.p7s | 33 + .../etc/Test_Permissions_notyet.p7s | 243 ++ .../etc/Test_Permissions_notyet.xml | 191 ++ .../etc/Test_Permissions_ok.p7s | 85 + .../etc/Test_Permissions_ok.xml | 33 + .../etc/Test_Permissions_unknown_ca.p7s | 87 + .../etc/Test_Permissions_unknown_subject.p7s | 85 + .../etc/Test_Permissions_unknown_subject.xml | 33 + .../src/validate_local_permissions_utests.c | 1020 +++++++ .../etc/Test_Governance_ok.p7s | 114 + ...sions_different_subject_representation.p7s | 96 + ...sions_different_subject_representation.xml | 44 + .../etc/Test_Permissions_expired.p7s | 243 ++ .../etc/Test_Permissions_expired.xml | 191 ++ .../etc/Test_Permissions_invalid_data.p7s | 219 ++ .../etc/Test_Permissions_invalid_data.xml | 167 ++ ..._Permissions_missing_subject_component.p7s | 96 + ..._Permissions_missing_subject_component.xml | 44 + .../etc/Test_Permissions_not_signed.p7s | 33 + .../etc/Test_Permissions_notyet.p7s | 243 ++ .../etc/Test_Permissions_notyet.xml | 191 ++ .../etc/Test_Permissions_ok.p7s | 85 + .../etc/Test_Permissions_ok.xml | 33 + .../etc/Test_Permissions_unknown_ca.p7s | 87 + .../etc/Test_Permissions_unknown_subject.p7s | 85 + .../etc/Test_Permissions_unknown_subject.xml | 33 + .../src/validate_remote_permissions_utests.c | 1068 +++++++ .../dds/security/core/dds_security_utils.h | 8 +- src/security/core/src/dds_security_utils.c | 264 +- src/security/core/tests/CMakeLists.txt | 1 + src/security/core/tests/security_utils.c | 62 + 101 files changed, 19154 insertions(+), 52 deletions(-) create mode 100644 src/security/builtin_plugins/access_control/CMakeLists.txt create mode 100644 src/security/builtin_plugins/access_control/src/access_control.c create mode 100644 src/security/builtin_plugins/access_control/src/access_control.h create mode 100644 src/security/builtin_plugins/access_control/src/access_control_objects.c create mode 100644 src/security/builtin_plugins/access_control/src/access_control_objects.h create mode 100644 src/security/builtin_plugins/access_control/src/access_control_parser.c create mode 100644 src/security/builtin_plugins/access_control/src/access_control_parser.h create mode 100644 src/security/builtin_plugins/access_control/src/access_control_utils.c create mode 100644 src/security/builtin_plugins/access_control/src/access_control_utils.h create mode 100644 src/security/builtin_plugins/tests/access_control_fnmatch/src/access_control_fnmatch_utests.c create mode 100644 src/security/builtin_plugins/tests/get_permissions_credential_token/etc/Test_Governance_ok.p7s create mode 100644 src/security/builtin_plugins/tests/get_permissions_credential_token/etc/Test_Permissions_ok.p7s create mode 100644 src/security/builtin_plugins/tests/get_permissions_credential_token/src/get_permissions_credential_token_utests.c create mode 100644 src/security/builtin_plugins/tests/get_permissions_token/etc/Test_Governance_ok.p7s create mode 100644 src/security/builtin_plugins/tests/get_permissions_token/etc/Test_Permissions_ok.p7s create mode 100644 src/security/builtin_plugins/tests/get_permissions_token/src/get_permissions_token_utests.c create mode 100644 src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_full.p7s create mode 100644 src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_clear.p7s create mode 100644 src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_clear.xml create mode 100644 src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_different.p7s create mode 100644 src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_different.xml create mode 100644 src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_encrypted.p7s create mode 100644 src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_encrypted.xml create mode 100644 src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_encrypted_and_authenticated.p7s create mode 100644 src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_encrypted_and_authenticated.xml create mode 100644 src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_signed.p7s create mode 100644 src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_signed.xml create mode 100644 src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_signed_and_authenticated.p7s create mode 100644 src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_signed_and_authenticated.xml create mode 100644 src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Permissions_ok.p7s create mode 100644 src/security/builtin_plugins/tests/get_xxx_sec_attributes/src/get_xxx_sec_attributes_utests.c create mode 100644 src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Governance_ok.p7s create mode 100644 src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Permissions_ca.pem create mode 100644 src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Permissions_ca_key.pem create mode 100644 src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Permissions_listener.p7s create mode 100644 src/security/builtin_plugins/tests/listeners_access_control/src/listeners_access_control_utests.c create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_File_empty.txt create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_File_text.txt create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_check_create_participant.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_check_create_participant.xml create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_full.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_full.xml create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_invalid_data.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_invalid_data.xml create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_invalid_element.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_invalid_element.xml create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_not_signed.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_ok.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_unknown_ca.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_ca.pem create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_ca_key.pem create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_expired.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_expired.xml create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_full.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_full.xml create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_invalid_data.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_invalid_data.xml create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_invalid_element.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_invalid_element.xml create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_lack_of_not_after.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_lack_of_not_after.xml create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_lack_of_not_before.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_lack_of_not_before.xml create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_not_signed.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_notyet.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_notyet.xml create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_ok.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_ok.xml create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_unknown_ca.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_unknown_subject.p7s create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_unknown_subject.xml create mode 100644 src/security/builtin_plugins/tests/validate_local_permissions/src/validate_local_permissions_utests.c create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Governance_ok.p7s create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_different_subject_representation.p7s create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_different_subject_representation.xml create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_expired.p7s create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_expired.xml create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_invalid_data.p7s create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_invalid_data.xml create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_missing_subject_component.p7s create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_missing_subject_component.xml create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_not_signed.p7s create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_notyet.p7s create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_notyet.xml create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_ok.p7s create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_ok.xml create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_unknown_ca.p7s create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_unknown_subject.p7s create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_unknown_subject.xml create mode 100644 src/security/builtin_plugins/tests/validate_remote_permissions/src/validate_remote_permissions_utests.c create mode 100644 src/security/core/tests/security_utils.c diff --git a/src/core/ddsc/src/dds__topic.h b/src/core/ddsc/src/dds__topic.h index d59dc1f..f6de42a 100644 --- a/src/core/ddsc/src/dds__topic.h +++ b/src/core/ddsc/src/dds__topic.h @@ -35,6 +35,8 @@ DDS_EXPORT void dds_topic_set_filter_with_ctx DDS_EXPORT dds_topic_intern_filter_fn dds_topic_get_filter_with_ctx (dds_entity_t topic); +DDS_EXPORT dds_entity_t dds_create_topic_impl (dds_entity_t participant, struct ddsi_sertopic *sertopic, const dds_qos_t *qos, const dds_listener_t *listener, const nn_plist_t *sedp_plist); + #if defined (__cplusplus) } #endif diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index 8dd026f..ca45561 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -76,7 +76,7 @@ dds_entity_t dds__get_builtin_topic (dds_entity_t entity, dds_entity_t topic) } dds_qos_t *qos = dds__create_builtin_qos (); - tp = dds_create_topic_arbitrary (par->m_entity.m_hdllink.hdl, sertopic, qos, NULL, NULL); + tp = dds_create_topic_impl (par->m_entity.m_hdllink.hdl, sertopic, qos, NULL, NULL); dds_delete_qos (qos); dds_entity_unpin (e); return tp; diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 7d9df7d..4796703 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -280,7 +280,7 @@ const struct dds_entity_deriver dds_entity_deriver_topic = { .validate_status = dds_topic_status_validate }; -dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_sertopic *sertopic, const dds_qos_t *qos, const dds_listener_t *listener, const nn_plist_t *sedp_plist) +dds_entity_t dds_create_topic_impl (dds_entity_t participant, struct ddsi_sertopic *sertopic, const dds_qos_t *qos, const dds_listener_t *listener, const nn_plist_t *sedp_plist) { dds_return_t rc; dds_participant *par; @@ -465,6 +465,15 @@ err_invalid_qos: return rc; } +dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_sertopic *sertopic, const dds_qos_t *qos, const dds_listener_t *listener, const nn_plist_t *sedp_plist) +{ + assert(sertopic); + assert(sertopic->name); + if (!strncmp(sertopic->name, "DCPS", 4)) + return DDS_RETCODE_BAD_PARAMETER; + return dds_create_topic_impl (participant, sertopic, qos, listener, sedp_plist); +} + dds_entity_t dds_create_topic (dds_entity_t participant, const dds_topic_descriptor_t *desc, const char *name, const dds_qos_t *qos, const dds_listener_t *listener) { struct ddsi_sertopic_default *st; diff --git a/src/core/ddsc/tests/topic.c b/src/core/ddsc/tests/topic.c index d71c8d5..3707715 100644 --- a/src/core/ddsc/tests/topic.c +++ b/src/core/ddsc/tests/topic.c @@ -177,7 +177,7 @@ CU_Test(ddsc_topic_create, desc_null, .init=ddsc_topic_init, .fini=ddsc_topic_fi CU_TheoryDataPoints(ddsc_topic_create, invalid_names) = { - CU_DataPoints(char *, NULL, "", "mi-dle", "-start", "end-", "1st", "Thus$", "pl+s", "t(4)"), + CU_DataPoints(char *, NULL, "", "mi-dle", "-start", "end-", "1st", "Thus$", "pl+s", "t(4)", "DCPSmytopic"), }; CU_Theory((char *name), ddsc_topic_create, invalid_names, .init=ddsc_topic_init, .fini=ddsc_topic_fini) { diff --git a/src/security/api/include/dds/security/dds_security_api_err.h b/src/security/api/include/dds/security/dds_security_api_err.h index 20ee24b..9246ba5 100644 --- a/src/security/api/include/dds/security/dds_security_api_err.h +++ b/src/security/api/include/dds/security/dds_security_api_err.h @@ -97,16 +97,14 @@ extern "C" { #define DDS_SECURITY_ERR_INVALID_SUBJECT_NAME_CODE 146 #define DDS_SECURITY_ERR_INVALID_SUBJECT_NAME_MESSAGE "Subject name is invalid" #define DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_CODE 147 -#define DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_MESSAGE "Permissions validity period expired for %s" +#define DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_MESSAGE "Permissions validity period expired for %s (expired: %s)" #define DDS_SECURITY_ERR_VALIDITY_PERIOD_NOT_STARTED_CODE 148 -#define DDS_SECURITY_ERR_VALIDITY_PERIOD_NOT_STARTED_MESSAGE "Permissions validity period has not started yet for %s" +#define DDS_SECURITY_ERR_VALIDITY_PERIOD_NOT_STARTED_MESSAGE "Permissions validity period has not started yet for %s (start: %s)" #define DDS_SECURITY_ERR_CAN_NOT_FIND_PERMISSIONS_GRANT_CODE 149 #define DDS_SECURITY_ERR_CAN_NOT_FIND_PERMISSIONS_GRANT_MESSAGE "Could not find valid grant in permissions" -#define DDS_SECURITY_ERR_PERMISSIONS_OUT_OF_VALIDITY_DATE_CODE 150 -#define DDS_SECURITY_ERR_PERMISSIONS_OUT_OF_VALIDITY_DATE_MESSAGE "Permissions of subject (%s) outside validity date: %s - %s" -#define DDS_SECURITY_ERR_URI_TYPE_NOT_SUPPORTED_CODE 151 +#define DDS_SECURITY_ERR_URI_TYPE_NOT_SUPPORTED_CODE 150 #define DDS_SECURITY_ERR_URI_TYPE_NOT_SUPPORTED_MESSAGE "Unsupported URI type: %s" -#define DDS_SECURITY_ERR_INVALID_CRYPTO_DATA_NOT_ALIGNED_CODE 152 +#define DDS_SECURITY_ERR_INVALID_CRYPTO_DATA_NOT_ALIGNED_CODE 151 #define DDS_SECURITY_ERR_INVALID_CRYPTO_DATA_NOT_ALIGNED_MESSAGE "The payload is not aligned at 4 bytes" #define DDS_SECURITY_ERR_UNDEFINED_CODE 200 diff --git a/src/security/builtin_plugins/CMakeLists.txt b/src/security/builtin_plugins/CMakeLists.txt index 113d0b4..93feffb 100644 --- a/src/security/builtin_plugins/CMakeLists.txt +++ b/src/security/builtin_plugins/CMakeLists.txt @@ -11,6 +11,7 @@ # cmake_minimum_required(VERSION 3.7) +add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/access_control") add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/authentication") add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/cryptographic") diff --git a/src/security/builtin_plugins/access_control/CMakeLists.txt b/src/security/builtin_plugins/access_control/CMakeLists.txt new file mode 100644 index 0000000..c0cee0a --- /dev/null +++ b/src/security/builtin_plugins/access_control/CMakeLists.txt @@ -0,0 +1,55 @@ +# +# Copyright(c) 2006 to 2019 ADLINK Technology Limited and others +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +# v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# +include (GenerateExportHeader) + +find_package(OpenSSL) + +PREPEND(srcs_accesscontrol "${CMAKE_CURRENT_LIST_DIR}/src" + access_control_objects.c + access_control_parser.c + access_control_utils.c + access_control.c +) + +add_library(dds_security_ac SHARED "") + +generate_export_header( + dds_security_ac + BASE_NAME SECURITY + EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/dds/security/export.h" +) + +add_definitions(-DDDSI_INCLUDE_SSL) + +target_link_libraries(dds_security_ac PUBLIC ddsc) +target_link_libraries(dds_security_ac PUBLIC OpenSSL::SSL) + +target_sources(dds_security_ac + PRIVATE + ${srcs_accesscontrol} +) + +target_include_directories(dds_security_ac + PUBLIC + "$>" + "$>" + "$>" + "$" +) + +install( + TARGETS + EXPORT "${PROJECT_NAME}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT lib + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib +) diff --git a/src/security/builtin_plugins/access_control/src/access_control.c b/src/security/builtin_plugins/access_control/src/access_control.c new file mode 100644 index 0000000..f356445 --- /dev/null +++ b/src/security/builtin_plugins/access_control/src/access_control.c @@ -0,0 +1,2486 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#define ACCESS_CONTROL_USE_ONE_PERMISSION + +#include +#include +#include +#include +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/misc.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/types.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/core/dds_security_utils.h" +#include "access_control.h" +#include "access_control_utils.h" +#include "access_control_objects.h" +#include "access_control_parser.h" + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10100000L +#define REMOVE_THREAD_STATE() ERR_remove_thread_state(NULL); +#elif OPENSSL_VERSION_NUMBER < 0x10000000L +#define REMOVE_THREAD_STATE() ERR_remove_state(0); +#else +#define REMOVE_THREAD_STATE() +#endif + +static const char *ACCESS_CONTROL_PROTOCOL_CLASS = "DDS:Access"; +static const unsigned ACCESS_CONTROL_PROTOCOL_VERSION_MAJOR = 1; +static const unsigned ACCESS_CONTROL_PROTOCOL_VERSION_MINOR = 0; + +static const char *ACCESS_CONTROL_PERMISSIONS_CLASS_ID = "Permissions"; + +static const char *QOS_PROPERTY_PERMISSIONS_DOCUMENT = "dds.sec.access.permissions"; +static const char *QOS_PROPERTY_GOVERNANCE_DOCUMENT = "dds.sec.access.governance"; +static const char *QOS_PROPERTY_PERMISSIONS_CA = "dds.sec.access.permissions_ca"; +static const char *QOS_PROPERTY_IDENTITY_CERT = "dds.sec.auth.identity_certificate"; + +static const char *ACCESS_PERMISSIONS_CREDENTIAL_TOKEN_ID = "DDS:Access:PermissionsCredential"; +static const char *ACCESS_PROPERTY_PERMISSION_DOCUMENT = "dds.perm.cert"; + +typedef enum TOPIC_TYPE +{ + TOPIC_TYPE_USER = 0, + TOPIC_TYPE_NON_SECURE_BUILTIN, + TOPIC_TYPE_SECURE_ParticipantsSecure, + TOPIC_TYPE_SECURE_PublicationsSecure, + TOPIC_TYPE_SECURE_SubscriptionsSecure, + TOPIC_TYPE_SECURE_ParticipantMessageSecure, + TOPIC_TYPE_SECURE_ParticipantStatelessMessage, + TOPIC_TYPE_SECURE_ParticipantVolatileMessageSecure +} TOPIC_TYPE; + +/** + * Implementation structure for storing encapsulated members of the instance + * while giving only the interface definition to user + */ + +typedef struct dds_security_access_control_impl +{ + dds_security_access_control base; + ddsrt_mutex_t lock; + +#ifdef ACCESS_CONTROL_USE_ONE_PERMISSION + local_participant_access_rights *local_access_rights; +#else + /* TODO: implement access rights per participant */ + struct AccessControlTable *local_permissions; +#endif + struct AccessControlTable *remote_permissions; +#if TIMED_CALLBACK_IMPLEMENTED + struct ut_timed_dispatcher_t *timed_callbacks; +#endif +} dds_security_access_control_impl; + +static bool get_sec_attributes(dds_security_access_control_impl *ac, const DDS_Security_PermissionsHandle permissions_handle, const char *topic_name, + DDS_Security_EndpointSecurityAttributes *attributes, DDS_Security_SecurityException *ex); +static char *get_access_control_class_id(const char *classid); +static local_participant_access_rights *check_and_create_local_participant_rights(DDS_Security_IdentityHandle identity_handle, int domain_id, const DDS_Security_Qos *participant_qos, DDS_Security_SecurityException *ex); +static remote_participant_access_rights *check_and_create_remote_participant_rights(DDS_Security_IdentityHandle remote_identity_handle, local_participant_access_rights *local_rights, + const DDS_Security_PermissionsToken *remote_permissions_token, const DDS_Security_AuthenticatedPeerCredentialToken *remote_credential_token, DDS_Security_SecurityException *ex); +static local_participant_access_rights *find_local_access_rights(dds_security_access_control_impl *ac, DDS_Security_PermissionsHandle handle); +static local_participant_access_rights *find_local_rights_by_identity(dds_security_access_control_impl *ac, DDS_Security_IdentityHandle identity_handle); +static remote_participant_access_rights *find_remote_rights_by_identity(dds_security_access_control_impl *ac, DDS_Security_IdentityHandle identity_handle); +static DDS_Security_boolean domainid_within_sets(struct domain_id_set *domain, int domain_id); +static DDS_Security_boolean is_topic_in_criteria(const struct criteria *criteria, const char *topic_name); +static DDS_Security_boolean is_partition_qos_in_criteria(const struct criteria *criteria, const DDS_Security_PartitionQosPolicy *partitions); +static DDS_Security_boolean is_partition_in_criteria(const struct criteria *criteria, const char *partition_name); +static struct domain_rule *find_domain_rule_in_governance(struct domain_rule *rule, int domain_id); +static DDS_Security_boolean get_participant_sec_attributes(dds_security_access_control *instance, const DDS_Security_PermissionsHandle permissions_handle, + DDS_Security_ParticipantSecurityAttributes *attributes, DDS_Security_SecurityException *ex); +static DDS_Security_boolean get_permissions_token(dds_security_access_control *instance, DDS_Security_PermissionsToken *permissions_token, const DDS_Security_PermissionsHandle handle, DDS_Security_SecurityException *ex); +static remote_participant_access_rights *find_remote_permissions_by_permissions_handle(dds_security_access_control_impl *ac, DDS_Security_PermissionsHandle permissions_handle); +static struct topic_rule *find_topic_from_domain_rule(struct domain_rule *domain_rule, const char *topic_name); +static DDS_Security_boolean domainid_within_sets(struct domain_id_set *domain, int domain_id); +static DDS_Security_boolean compare_class_id_plugin_classname(DDS_Security_string class_id_1, DDS_Security_string class_id_2); +static DDS_Security_boolean compare_class_id_major_ver(DDS_Security_string class_id_1, DDS_Security_string class_id_2); +#if TIMED_CALLBACK_IMPLEMENTED + static void add_validity_end_trigger(dds_security_access_control_impl *ac, const DDS_Security_PermissionsHandle permissions_handle, dds_time_t end); +#endif +static DDS_Security_boolean is_allowed_by_permissions(struct permissions_parser *permissions, int domain_id, const char *topic_name, const DDS_Security_PartitionQosPolicy *partitions, + const char *identity_subject_name, permission_criteria_type criteria_type, DDS_Security_SecurityException *ex); +static void sanity_check_local_access_rights(local_participant_access_rights *rights); +static void sanity_check_remote_access_rights(remote_participant_access_rights *rights); +static TOPIC_TYPE get_topic_type(const char *topic_name); + + +static DDS_Security_PermissionsHandle +validate_local_permissions( + dds_security_access_control *instance, + const dds_security_authentication *auth_plugin, + const DDS_Security_IdentityHandle identity_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_Qos *participant_qos, + DDS_Security_SecurityException *ex) +{ + dds_security_access_control_impl *ac = (dds_security_access_control_impl *)instance; + local_participant_access_rights *rights; + DDS_Security_PermissionsHandle permissions_handle = DDS_SECURITY_HANDLE_NIL; + + if (!instance || !auth_plugin || identity_handle == DDS_SECURITY_HANDLE_NIL || !participant_qos) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return DDS_SECURITY_HANDLE_NIL; + } + +#ifdef ACCESS_CONTROL_USE_ONE_PERMISSION + ddsrt_mutex_lock(&ac->lock); + if (ac->local_access_rights == NULL) + { + rights = check_and_create_local_participant_rights(identity_handle, domain_id, participant_qos, ex); + ac->local_access_rights = rights; + } + else + { + ACCESS_CONTROL_OBJECT_KEEP(ac->local_access_rights); + rights = ac->local_access_rights; + } + ddsrt_mutex_unlock(&ac->lock); +#else + { + local_participant_access_rights *existing = find_local_rights_by_identity(ac, identity_handle); + if (existing) + { + ACCESS_CONTROL_OBJECT_RELEASE(existing); + return ACCESS_CONTROL_OBJECT_HANDLE(existing); + } + + rights = check_and_create_local_participant_rights(identity_handle, domain_id, participant_qos, ex); + if (rights) + access_control_table_insert(ac->local_permissions, (AccessControlObject *)rights); + } +#endif + + permissions_handle = ACCESS_CONTROL_OBJECT_HANDLE(rights); + + if (permissions_handle != DDS_SECURITY_HANDLE_NIL) + { + assert (rights->permissions_expiry != DDS_TIME_INVALID); + +#if TIMED_CALLBACK_IMPLEMENTED + if (rights->permissions_expiry != 0) + add_validity_end_trigger(ac, permissions_handle, rights->permissions_expiry); +#endif + } + + return permissions_handle; +} + +static DDS_Security_PermissionsHandle +validate_remote_permissions( + dds_security_access_control *instance, + const dds_security_authentication *auth_plugin, + const DDS_Security_IdentityHandle local_identity_handle, + const DDS_Security_IdentityHandle remote_identity_handle, + const DDS_Security_PermissionsToken *remote_permissions_token, + const DDS_Security_AuthenticatedPeerCredentialToken *remote_credential_token, + DDS_Security_SecurityException *ex) +{ + dds_security_access_control_impl *ac = (dds_security_access_control_impl *)instance; + local_participant_access_rights *local_rights; + remote_participant_access_rights *remote_rights, *existing; + DDS_Security_PermissionsHandle permissions_handle = DDS_SECURITY_HANDLE_NIL; + + if (!instance || !auth_plugin || local_identity_handle == DDS_SECURITY_HANDLE_NIL || remote_identity_handle == DDS_SECURITY_HANDLE_NIL || + !remote_permissions_token || !remote_permissions_token->class_id || !remote_credential_token) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return DDS_SECURITY_HANDLE_NIL; + } + + if (!(local_rights = find_local_rights_by_identity(ac, local_identity_handle))) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return DDS_SECURITY_HANDLE_NIL; + } + + if ((existing = find_remote_rights_by_identity(ac, remote_identity_handle))) + { + if (existing->local_rights->local_identity == local_identity_handle) + { + ACCESS_CONTROL_OBJECT_RELEASE(existing); + return ACCESS_CONTROL_OBJECT_HANDLE(existing); + } + } + +#ifdef ACCESS_CONTROL_USE_ONE_PERMISSION + if (existing) + { + /* No check because it has already been checked */ + remote_rights = ac_remote_participant_access_rights_new(remote_identity_handle, local_rights, existing->permissions, existing->permissions_expiry, remote_permissions_token, existing->identity_subject_name); + sanity_check_remote_access_rights(remote_rights); + /* TODO: copy or relate security attributes of existing with new remote permissions object */ + } + else + { + remote_rights = check_and_create_remote_participant_rights(remote_identity_handle, local_rights, remote_permissions_token, remote_credential_token, ex); + } +#else + remote_rights = check_and_create_remote_participant_rights(remote_identity_handle, local_rights, remote_permissions_token, remote_credential_token, ex); +#endif + + permissions_handle = ACCESS_CONTROL_OBJECT_HANDLE(remote_rights); + +#if TIMED_CALLBACK_IMPLEMENTED + if (permissions_handle != DDS_SECURITY_HANDLE_NIL) + add_validity_end_trigger(ac, permissions_handle, remote_rights->permissions_expiry); +#endif + + if (remote_rights) + access_control_table_insert(ac->remote_permissions, (AccessControlObject *)remote_rights); + + ACCESS_CONTROL_OBJECT_RELEASE(existing); + ACCESS_CONTROL_OBJECT_RELEASE(remote_rights); + ACCESS_CONTROL_OBJECT_RELEASE(local_rights); + + return permissions_handle; +} + +static DDS_Security_boolean +check_create_participant(dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_Qos *participant_qos, + DDS_Security_SecurityException *ex) +{ + dds_security_access_control_impl *ac = (dds_security_access_control_impl *)instance; + local_participant_access_rights *rights; + struct domain_rule *domainRule = NULL; + struct topic_rule *topicRule = NULL; + DDS_Security_ParticipantSecurityAttributes participantSecurityAttributes; + DDS_Security_boolean result = false; + + if (instance == NULL || permissions_handle == DDS_SECURITY_HANDLE_NIL || participant_qos == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + + /* Retrieve rights */ + if ((rights = find_local_access_rights(ac, permissions_handle)) == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, "Could not find local rights for the participant."); + return false; + } + + /* Retrieve domain rules */ + domainRule = find_domain_rule_in_governance(rights->governance_tree->dds->domain_access_rules->domain_rule, domain_id); + if (domainRule == NULL || domainRule->topic_access_rules == NULL || domainRule->topic_access_rules->topic_rule == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_FIND_DOMAIN_IN_GOVERNANCE_CODE, 0, DDS_SECURITY_ERR_CAN_NOT_FIND_DOMAIN_IN_GOVERNANCE_MESSAGE, domain_id); + goto exit; + } + + /* Iterate over topics rules*/ + topicRule = domainRule->topic_access_rules->topic_rule; + while (topicRule != NULL) + { + if (!topicRule->enable_read_access_control->value || !topicRule->enable_write_access_control->value) + { + /* Governance specifies any topics on the DomainParticipant + domain_id with enable_read_access_control set to false or with enable_write_access_control set to false */ + result = true; + goto exit; + } + topicRule = (struct topic_rule *)topicRule->node.next; + } + + if (!get_participant_sec_attributes(instance, permissions_handle, &participantSecurityAttributes, ex)) + goto exit; + + if (!participantSecurityAttributes.is_access_protected) + { + result = true; + goto exit; + } + + /* Is this participant permitted? */ + result = is_allowed_by_permissions(rights->permissions_tree, domain_id, NULL /* topic_name */, NULL /* partitions */, rights->identity_subject_name, UNKNOWN_CRITERIA, ex); + +exit: + ACCESS_CONTROL_OBJECT_RELEASE(rights); + return result; +} + +static DDS_Security_boolean +check_create_datawriter(dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, const char *topic_name, + const DDS_Security_Qos *writer_qos, + const DDS_Security_PartitionQosPolicy *partition, + const DDS_Security_DataTags *data_tag, + DDS_Security_SecurityException *ex) +{ + DDS_Security_TopicSecurityAttributes topic_sec_attr; + local_participant_access_rights *local_rights; + DDS_Security_boolean result = false; + DDSRT_UNUSED_ARG(data_tag); + + if (instance == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, "Plugin instance not provided"); + return false; + } + if (permissions_handle == DDS_SECURITY_HANDLE_NIL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, "Permissions handle not provided"); + return false; + } + if (topic_name == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, "Topic name not provided"); + return false; + } + if (writer_qos == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, "QoS not provided"); + return false; + } + if (partition == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, "Partition not provided"); + return false; + } + if ((local_rights = find_local_access_rights((dds_security_access_control_impl *)instance, permissions_handle)) == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, "Could not find rights material"); + return false; + } + if (local_rights->domain_id != domain_id) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, + "Given domain_id (%d) does not match the related participant domain_id (%d)\n", domain_id, local_rights->domain_id); + goto exit; + } + + /* Find a topic with the specified topic name in the Governance */ + if (!(result = instance->get_topic_sec_attributes(instance, permissions_handle, topic_name, &topic_sec_attr, ex))) + goto exit; + + if (!topic_sec_attr.is_write_protected) + { + result = true; + goto exit; + } + + /* Find a topic with the specified topic name in the Governance */ + result = is_allowed_by_permissions(local_rights->permissions_tree, domain_id, topic_name, partition, local_rights->identity_subject_name, PUBLISH_CRITERIA, ex); + +exit: + ACCESS_CONTROL_OBJECT_RELEASE(local_rights); + return result; +} + +static DDS_Security_boolean +check_create_datareader(dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const char *topic_name, + const DDS_Security_Qos *reader_qos, + const DDS_Security_PartitionQosPolicy *partition, + const DDS_Security_DataTags *data_tag, + DDS_Security_SecurityException *ex) +{ + DDS_Security_TopicSecurityAttributes topic_sec_attr; + local_participant_access_rights *local_rights; + DDS_Security_boolean result = false; + + DDSRT_UNUSED_ARG(data_tag); + + if (instance == NULL || permissions_handle == DDS_SECURITY_HANDLE_NIL || topic_name == NULL || reader_qos == NULL || partition == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + if ((local_rights = find_local_access_rights((dds_security_access_control_impl *)instance, permissions_handle)) == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + if (local_rights->domain_id != domain_id) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, + "Given domain_id (%d) does not match the related participant domain_id (%d)\n", domain_id, local_rights->domain_id); + goto exit; + } + + /* Find a topic with the specified topic name in the Governance */ + if ((result = instance->get_topic_sec_attributes(instance, permissions_handle, topic_name, &topic_sec_attr, ex)) == false) + goto exit; + + if (topic_sec_attr.is_read_protected == false) + { + result = true; + goto exit; + } + + /* Find a topic with the specified topic name in the Governance */ + result = is_allowed_by_permissions(local_rights->permissions_tree, domain_id, topic_name, partition, local_rights->identity_subject_name, SUBSCRIBE_CRITERIA, ex); + +exit: + ACCESS_CONTROL_OBJECT_RELEASE(local_rights); + return result; +} + +static DDS_Security_boolean +check_create_topic(dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, const char *topic_name, + const DDS_Security_Qos *qos, DDS_Security_SecurityException *ex) +{ + DDS_Security_TopicSecurityAttributes topic_sec_attr; + local_participant_access_rights *local_rights; + DDS_Security_boolean result = false; + + if (instance == NULL || permissions_handle == DDS_SECURITY_HANDLE_NIL || qos == NULL || topic_name == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + if ((local_rights = find_local_access_rights((dds_security_access_control_impl *)instance, permissions_handle)) == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + if (local_rights->domain_id != domain_id) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, + "Given domain_id (%d) does not match the related participant domain_id (%d)\n", domain_id, local_rights->domain_id); + goto exit; + } + + /* Find a topic with the specified topic name in the Governance */ + if ((result = instance->get_topic_sec_attributes(instance, permissions_handle, topic_name, &topic_sec_attr, ex)) == false) + goto exit; + + if (topic_sec_attr.is_read_protected == false || topic_sec_attr.is_write_protected == false) + { + result = true; + goto exit; + } + + /* Find a topic with the specified topic name in the Governance */ + result = is_allowed_by_permissions(local_rights->permissions_tree, domain_id, topic_name, NULL, local_rights->identity_subject_name, UNKNOWN_CRITERIA /* both publish and subscribe rules */, ex); + +exit: + ACCESS_CONTROL_OBJECT_RELEASE(local_rights); + return result; +} + +static DDS_Security_boolean +check_local_datawriter_register_instance( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_Entity *writer, const DDS_Security_DynamicData *key, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(writer); + DDSRT_UNUSED_ARG(key); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + + /* Not implemented */ + return true; +} + +static DDS_Security_boolean +check_local_datawriter_dispose_instance( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_Entity *writer, const DDS_Security_DynamicData key, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(writer); + DDSRT_UNUSED_ARG(key); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + + /* Not implemented */ + return true; +} + +static DDS_Security_boolean +check_remote_participant(dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_ParticipantBuiltinTopicDataSecure *participant_data, + DDS_Security_SecurityException *ex) +{ + dds_security_access_control_impl *ac = (dds_security_access_control_impl *)instance; + remote_participant_access_rights *remote_rights = NULL; + DDS_Security_boolean isValid = false; + DDS_Security_ParticipantSecurityAttributes participantSecurityAttributes; + DDS_Security_PermissionsHandle local_permissions_handle; + DDS_Security_string class_id_remote_str; + DDS_Security_string class_id_local_str; + DDS_Security_boolean result = false; + + if (instance == NULL || permissions_handle == DDS_SECURITY_HANDLE_NIL || participant_data == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + + /* retrieve the cached remote DomainParticipant Governance; the permissions_handle is associated with the remote participant */ + if ((remote_rights = find_remote_permissions_by_permissions_handle(ac, permissions_handle)) == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + + /* The local rights pointer is actually the local permissions handle. */ + local_permissions_handle = ACCESS_CONTROL_OBJECT_HANDLE(remote_rights->local_rights); + if ((isValid = get_participant_sec_attributes(instance, local_permissions_handle, &participantSecurityAttributes, ex)) == false) + goto exit; + if (participantSecurityAttributes.is_access_protected == false) + { + result = true; + goto exit; + } + + /* 2) If the PluginClassName or the MajorVersion of the local permissions_token differ from those in the remote_permissions_token, + the operation shall return false. */ + class_id_remote_str = remote_rights->permissions->remote_permissions_token_class_id; + class_id_local_str = get_access_control_class_id(ACCESS_CONTROL_PERMISSIONS_CLASS_ID); + if (compare_class_id_plugin_classname(class_id_remote_str, class_id_local_str) == false) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INCOMPATIBLE_REMOTE_PLUGIN_CLASSNAME_CODE, 0, DDS_SECURITY_ERR_INCOMPATIBLE_REMOTE_PLUGIN_CLASSNAME_MESSAGE); + goto exit_free_classid; + } + if (compare_class_id_major_ver(class_id_remote_str, class_id_local_str) == false) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INCOMPATIBLE_REMOTE_PLUGIN_MAJORVERSION_CODE, 0, DDS_SECURITY_ERR_INCOMPATIBLE_REMOTE_PLUGIN_MAJORVERSION_MESSAGE); + goto exit_free_classid; + } + + /* 3) If the Permissions document contains a Grant for the remote DomainParticipant and the Grant contains an allow rule on + the DomainParticipant domain_id, then the operation shall succeed and return true. */ + /* Iterate over the grants and rules of the remote participant */ + result = is_allowed_by_permissions(remote_rights->permissions->permissions_tree, domain_id, NULL, NULL, remote_rights->identity_subject_name, UNKNOWN_CRITERIA, ex); + +exit_free_classid: + ddsrt_free(class_id_local_str); +exit: + ACCESS_CONTROL_OBJECT_RELEASE(remote_rights); + return result; +} + +static DDS_Security_boolean +check_remote_datawriter(dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, + DDS_Security_SecurityException *ex) +{ + dds_security_access_control_impl *ac = (dds_security_access_control_impl *)instance; + DDS_Security_TopicSecurityAttributes topic_sec_attr; + remote_participant_access_rights *remote_rights; + DDS_Security_string class_id_remote_str; + DDS_Security_string class_id_local_str; + DDS_Security_boolean result = false; + + if (instance == NULL || permissions_handle == DDS_SECURITY_HANDLE_NIL || publication_data == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + if ((remote_rights = find_remote_permissions_by_permissions_handle(ac, permissions_handle)) == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + if ((result = instance->get_topic_sec_attributes(instance, ACCESS_CONTROL_OBJECT_HANDLE(remote_rights->local_rights), publication_data->topic_name, &topic_sec_attr, ex)) == false) + goto exit; + if (topic_sec_attr.is_write_protected == false) + { + result = true; + goto exit; + } + + /* Compare PluginClassName and MajorVersion parts */ + class_id_remote_str = remote_rights->permissions->remote_permissions_token_class_id; + class_id_local_str = get_access_control_class_id(ACCESS_CONTROL_PERMISSIONS_CLASS_ID); + if (compare_class_id_plugin_classname(class_id_remote_str, class_id_local_str) == false) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INCOMPATIBLE_REMOTE_PLUGIN_CLASSNAME_CODE, 0, + DDS_SECURITY_ERR_INCOMPATIBLE_REMOTE_PLUGIN_CLASSNAME_MESSAGE); + goto exit_free_classid; + } + if (compare_class_id_major_ver(class_id_remote_str, class_id_local_str) == false) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INCOMPATIBLE_REMOTE_PLUGIN_MAJORVERSION_CODE, 0, + DDS_SECURITY_ERR_INCOMPATIBLE_REMOTE_PLUGIN_MAJORVERSION_MESSAGE); + goto exit_free_classid; + } + + /* Find a topic with the specified topic name in the Governance */ + result = is_allowed_by_permissions(remote_rights->permissions->permissions_tree, domain_id, publication_data->topic_name, + &(publication_data->partition), remote_rights->identity_subject_name, PUBLISH_CRITERIA, ex); + +exit_free_classid: + ddsrt_free(class_id_local_str); +exit: + ACCESS_CONTROL_OBJECT_RELEASE(remote_rights); + return result; +} + +static DDS_Security_boolean +check_remote_datareader(dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, + DDS_Security_boolean *relay_only, + DDS_Security_SecurityException *ex) +{ + dds_security_access_control_impl *ac = (dds_security_access_control_impl *)instance; + DDS_Security_TopicSecurityAttributes topic_sec_attr; + remote_participant_access_rights *remote_rights; + DDS_Security_string class_id_remote_str; + DDS_Security_string class_id_local_str; + + DDS_Security_boolean result = false; + + if (instance == NULL || permissions_handle == DDS_SECURITY_HANDLE_NIL || subscription_data == NULL || relay_only == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + + *relay_only = false; + if ((remote_rights = find_remote_permissions_by_permissions_handle(ac, permissions_handle)) == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + if (!(instance->get_topic_sec_attributes(instance, ACCESS_CONTROL_OBJECT_HANDLE(remote_rights->local_rights), subscription_data->topic_name, &topic_sec_attr, ex))) + goto exit; + if (!topic_sec_attr.is_read_protected) + { + result = true; + goto exit; + } + + /* Compare PluginClassName and MajorVersion parts */ + class_id_remote_str = remote_rights->permissions->remote_permissions_token_class_id; + class_id_local_str = get_access_control_class_id(ACCESS_CONTROL_PERMISSIONS_CLASS_ID); + if (compare_class_id_plugin_classname(class_id_remote_str, class_id_local_str) == false) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INCOMPATIBLE_REMOTE_PLUGIN_CLASSNAME_CODE, 0, + DDS_SECURITY_ERR_INCOMPATIBLE_REMOTE_PLUGIN_CLASSNAME_MESSAGE); + goto exit_free_classid; + } + if (compare_class_id_major_ver(class_id_remote_str, class_id_local_str) == false) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INCOMPATIBLE_REMOTE_PLUGIN_MAJORVERSION_CODE, 0, + DDS_SECURITY_ERR_INCOMPATIBLE_REMOTE_PLUGIN_MAJORVERSION_MESSAGE); + ACCESS_CONTROL_OBJECT_RELEASE(remote_rights); + goto exit_free_classid; + } + + /* Find a topic with the specified topic name in the Governance */ + result = is_allowed_by_permissions(remote_rights->permissions->permissions_tree, domain_id, subscription_data->topic_name, + &(subscription_data->partition), remote_rights->identity_subject_name, SUBSCRIBE_CRITERIA, ex); + +exit_free_classid: + ddsrt_free(class_id_local_str); +exit: + ACCESS_CONTROL_OBJECT_RELEASE(remote_rights); + return result; +} + +static DDS_Security_boolean +check_remote_topic(dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_TopicBuiltinTopicData *topic_data, + DDS_Security_SecurityException *ex) +{ + dds_security_access_control_impl *ac = (dds_security_access_control_impl *)instance; + DDS_Security_TopicSecurityAttributes topic_sec_attr; + remote_participant_access_rights *remote_rights; + DDS_Security_string class_id_remote_str; + DDS_Security_string class_id_local_str; + DDS_Security_boolean result = false; + + if (instance == NULL || permissions_handle == DDS_SECURITY_HANDLE_NIL || topic_data == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + if ((remote_rights = find_remote_permissions_by_permissions_handle(ac, permissions_handle)) == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + if ((result = instance->get_topic_sec_attributes(instance, ACCESS_CONTROL_OBJECT_HANDLE(remote_rights->local_rights), topic_data->name, &topic_sec_attr, ex)) == false) + goto exit; + if (!topic_sec_attr.is_read_protected || !topic_sec_attr.is_write_protected) + { + result = true; + goto exit; + } + + /* Compare PluginClassName and MajorVersion parts */ + class_id_remote_str = remote_rights->permissions->remote_permissions_token_class_id; + class_id_local_str = get_access_control_class_id(ACCESS_CONTROL_PERMISSIONS_CLASS_ID); + if (!compare_class_id_plugin_classname(class_id_remote_str, class_id_local_str)) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INCOMPATIBLE_REMOTE_PLUGIN_CLASSNAME_CODE, 0, + DDS_SECURITY_ERR_INCOMPATIBLE_REMOTE_PLUGIN_CLASSNAME_MESSAGE); + goto exit_free_classid; + } + if (!compare_class_id_major_ver(class_id_remote_str, class_id_local_str)) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INCOMPATIBLE_REMOTE_PLUGIN_MAJORVERSION_CODE, 0, + DDS_SECURITY_ERR_INCOMPATIBLE_REMOTE_PLUGIN_MAJORVERSION_MESSAGE); + goto exit_free_classid; + } + + result = is_allowed_by_permissions(remote_rights->permissions->permissions_tree, domain_id, topic_data->name, NULL, remote_rights->identity_subject_name, UNKNOWN_CRITERIA, ex); + +exit_free_classid: + ddsrt_free(class_id_local_str); +exit: + ACCESS_CONTROL_OBJECT_RELEASE(remote_rights); + return result; +} + +static DDS_Security_boolean +check_local_datawriter_match( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle writer_permissions_handle, + const DDS_Security_PermissionsHandle reader_permissions_handle, + const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, + const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(writer_permissions_handle); + DDSRT_UNUSED_ARG(reader_permissions_handle); + DDSRT_UNUSED_ARG(publication_data); + DDSRT_UNUSED_ARG(subscription_data); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + + /* This function is not implemented because it relies on DataTagging, + an optional DDS Security feature that is not implemented */ + return true; +} + +static DDS_Security_boolean +check_local_datareader_match( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle reader_permissions_handle, + const DDS_Security_PermissionsHandle writer_permissions_handle, + const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, + const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(reader_permissions_handle); + DDSRT_UNUSED_ARG(writer_permissions_handle); + DDSRT_UNUSED_ARG(subscription_data); + DDSRT_UNUSED_ARG(publication_data); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + + /* Not implemented */ + return true; +} + +static DDS_Security_boolean +check_remote_datawriter_register_instance( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_Entity *reader, + const DDS_Security_InstanceHandle publication_handle, + const DDS_Security_DynamicData key, + const DDS_Security_InstanceHandle instance_handle, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(reader); + DDSRT_UNUSED_ARG(publication_handle); + DDSRT_UNUSED_ARG(key); + DDSRT_UNUSED_ARG(instance_handle); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + + /* Not implemented */ + return true; +} + +static DDS_Security_boolean +check_remote_datawriter_dispose_instance( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_Entity *reader, + const DDS_Security_InstanceHandle publication_handle, + const DDS_Security_DynamicData key, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(reader); + DDSRT_UNUSED_ARG(publication_handle); + DDSRT_UNUSED_ARG(key); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + + /* Not implemented */ + return true; +} + +static DDS_Security_boolean +get_permissions_token(dds_security_access_control *instance, + DDS_Security_PermissionsToken *permissions_token, + const DDS_Security_PermissionsHandle handle, + DDS_Security_SecurityException *ex) +{ + local_participant_access_rights *rights; + if (!ex) + return false; + if (!instance) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_permissions_token: No instance provided"); + return false; + } + if (!permissions_token) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_permissions_token: No permissions token provided"); + return false; + } + if (handle == DDS_SECURITY_HANDLE_NIL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_permissions_token: No permissions handle provided"); + return false; + } + if ((rights = find_local_access_rights((dds_security_access_control_impl *)instance, handle)) == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, "get_permissions_token: Unused permissions handle provided"); + return false; + } + + ACCESS_CONTROL_OBJECT_RELEASE(rights); + memset(permissions_token, 0, sizeof(*permissions_token)); + permissions_token->class_id = get_access_control_class_id(ACCESS_CONTROL_PERMISSIONS_CLASS_ID); + return true; +} + +static DDS_Security_boolean +get_permissions_credential_token( + dds_security_access_control *instance, + DDS_Security_PermissionsCredentialToken *permissions_credential_token, + const DDS_Security_PermissionsHandle handle, + DDS_Security_SecurityException *ex) +{ + dds_security_access_control_impl *ac = (dds_security_access_control_impl *)instance; + local_participant_access_rights *rights; + if (!ex) + return false; + if (!instance) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_permissions_credential_token: No instance provided"); + return false; + } + if (!permissions_credential_token) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_permissions_credential_token: No permissions credential token provided"); + return false; + } + if (handle == DDS_SECURITY_HANDLE_NIL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_permissions_credential_token: No permissions handle provided"); + return false; + } + if ((rights = find_local_access_rights(ac, handle)) == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, "get_permissions_credential_token: Unused permissions handle provided"); + return false; + } + + memset(permissions_credential_token, 0, sizeof(*permissions_credential_token)); + permissions_credential_token->class_id = ddsrt_strdup(ACCESS_PERMISSIONS_CREDENTIAL_TOKEN_ID); + permissions_credential_token->properties._length = permissions_credential_token->properties._maximum = 1; + permissions_credential_token->properties._buffer = DDS_Security_PropertySeq_allocbuf(1); + permissions_credential_token->properties._buffer[0].name = ddsrt_strdup(ACCESS_PROPERTY_PERMISSION_DOCUMENT); + permissions_credential_token->properties._buffer[0].value = ddsrt_strdup(rights->permissions_document); + ACCESS_CONTROL_OBJECT_RELEASE(rights); + return true; +} + + +static DDS_Security_boolean +set_listener(dds_security_access_control *instance, + const dds_security_access_control_listener *listener, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(ex); +#if TIMED_CALLBACK_IMPLEMENTED + dds_security_access_control_impl *ac = (dds_security_access_control_impl *)instance; + if (listener) + ut_timed_dispatcher_enable(ac->timed_callbacks, (void *)listener); + else + ut_timed_dispatcher_disable(ac->timed_callbacks); +#else + DDSRT_UNUSED_ARG(instance); + DDSRT_UNUSED_ARG(listener); +#endif + + return true; +} + +static DDS_Security_boolean +return_permissions_token( + dds_security_access_control *instance, + const DDS_Security_PermissionsToken *token, + DDS_Security_SecurityException *ex) +{ + if (!instance || !token) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)token); + return true; +} + +static DDS_Security_boolean +return_permissions_credential_token( + dds_security_access_control *instance, + const DDS_Security_PermissionsCredentialToken *permissions_credential_token, + DDS_Security_SecurityException *ex) +{ + if (!instance || !permissions_credential_token) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)permissions_credential_token); + return true; +} + +static void +protectionkind_to_participant_attribute( + DDS_Security_ProtectionKind kind, + DDS_Security_boolean *is_protected, + DDS_Security_ParticipantSecurityAttributesMask *mask, + DDS_Security_ParticipantSecurityAttributesMask encryption_bit, + DDS_Security_ParticipantSecurityAttributesMask authentication_bit) +{ + switch (kind) + { + case DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION: + (*mask) |= authentication_bit; + (*mask) |= encryption_bit; + (*is_protected) = true; + break; + case DDS_SECURITY_PROTECTION_KIND_ENCRYPT: + (*mask) |= encryption_bit; + (*is_protected) = true; + break; + case DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION: + (*mask) |= authentication_bit; + (*is_protected) = true; + break; + case DDS_SECURITY_PROTECTION_KIND_SIGN: + (*is_protected) = true; + break; + case DDS_SECURITY_PROTECTION_KIND_NONE: + default: + (*is_protected) = false; + break; + } +} + +static DDS_Security_PluginEndpointSecurityAttributesMask +get_plugin_endpoint_security_attributes_mask( + DDS_Security_boolean is_payload_encrypted, + DDS_Security_boolean is_submessage_encrypted, + DDS_Security_boolean is_submessage_origin_authenticated) +{ + DDS_Security_PluginEndpointSecurityAttributesMask mask = DDS_SECURITY_ENDPOINT_ATTRIBUTES_FLAG_IS_VALID; + if (is_submessage_encrypted) + mask |= DDS_SECURITY_PLUGIN_ENDPOINT_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ENCRYPTED; + if (is_payload_encrypted) + mask |= DDS_SECURITY_PLUGIN_ENDPOINT_ATTRIBUTES_FLAG_IS_PAYLOAD_ENCRYPTED; + if (is_submessage_origin_authenticated) + mask |= DDS_SECURITY_PLUGIN_ENDPOINT_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ORIGIN_AUTHENTICATED; + return mask; +} + +static void +domain_rule_to_participant_attributes( + const struct domain_rule *rule, + DDS_Security_ParticipantSecurityAttributes *attributes) +{ + /* Expect proper rule. */ + assert(rule); + assert(rule->allow_unauthenticated_participants); + assert(rule->enable_join_access_control); + assert(rule->liveliness_protection_kind); + assert(rule->discovery_protection_kind); + assert(rule->rtps_protection_kind); + assert(attributes); + + memset(attributes, 0, sizeof(DDS_Security_ParticipantSecurityAttributes)); + + attributes->allow_unauthenticated_participants = rule->allow_unauthenticated_participants->value; + attributes->is_access_protected = rule->enable_join_access_control->value; + + attributes->plugin_participant_attributes = DDS_SECURITY_PARTICIPANT_ATTRIBUTES_FLAG_IS_VALID; + + protectionkind_to_participant_attribute( + rule->discovery_protection_kind->value, + &(attributes->is_discovery_protected), + &(attributes->plugin_participant_attributes), + DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_DISCOVERY_ENCRYPTED, + DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_DISCOVERY_AUTHENTICATED); + + protectionkind_to_participant_attribute( + rule->liveliness_protection_kind->value, + &(attributes->is_liveliness_protected), + &(attributes->plugin_participant_attributes), + DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_LIVELINESS_ENCRYPTED, + DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_LIVELINESS_AUTHENTICATED); + + protectionkind_to_participant_attribute( + rule->rtps_protection_kind->value, + &(attributes->is_rtps_protected), + &(attributes->plugin_participant_attributes), + DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_RTPS_ENCRYPTED, + DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_RTPS_AUTHENTICATED); +} + +static DDS_Security_boolean +domainid_within_sets( + struct domain_id_set *domain, + int domain_id) +{ + DDS_Security_boolean found = false; + int32_t min; + int32_t max; + + while (domain != NULL && !found) + { + assert(domain->min); + min = domain->min->value; + max = domain->max ? domain->max->value : min; + if ((domain_id >= min) && (domain_id <= max)) + found = true; + domain = (struct domain_id_set *)domain->node.next; + } + return found; +} + +static struct domain_rule * +find_domain_rule_in_governance(struct domain_rule *rule, int domain_id) +{ + struct domain_rule *found = NULL; + while ((rule != NULL) && (found == NULL)) + { + assert(rule->domains); + if (domainid_within_sets(rule->domains->domain_id_set, domain_id)) + found = rule; + rule = (struct domain_rule *)rule->node.next; + } + return found; +} + +static DDS_Security_boolean +get_participant_sec_attributes( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + DDS_Security_ParticipantSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + dds_security_access_control_impl *ac = (dds_security_access_control_impl *)instance; + local_participant_access_rights *local_rights; + struct domain_rule *found = NULL; + DDS_Security_boolean result = false; + + if (instance == 0 || permissions_handle == DDS_SECURITY_HANDLE_NIL || attributes == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + + /* The local rights are actually the local permissions handle. Check that. */ + if ((local_rights = find_local_access_rights(ac, permissions_handle)) == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, "Invalid permissions handle"); + return false; + } + if ((found = find_domain_rule_in_governance(local_rights->governance_tree->dds->domain_access_rules->domain_rule, local_rights->domain_id))) + { + domain_rule_to_participant_attributes(found, attributes); + result = true; + } + else + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Could not domain id within governance file."); + } + ACCESS_CONTROL_OBJECT_RELEASE(local_rights); + return result; +} + +static DDS_Security_boolean +compare_class_id_plugin_classname(DDS_Security_string classid1, DDS_Security_string classid2) +{ + char *classname1 = strrchr(classid1, ':'); + char *classname2 = strrchr(classid2, ':'); + const ptrdiff_t len1 = classname1 - classid1; + const ptrdiff_t len2 = classname2 - classid2; + return len1 == len2 && classname1 && classname2 && + ddsrt_strncasecmp(classid1, classid2, (size_t) len1) == 0; +} + +static DDS_Security_boolean +compare_class_id_major_ver(DDS_Security_string classid1, DDS_Security_string classid2) +{ + char *version_1 = strrchr(classid1, ':'); + char *version_2 = strrchr(classid2, ':'); + if (version_1 && version_2) + { + const char *majorVersion_1 = strrchr(version_1, '.'); + const char *majorVersion_2 = strrchr(version_2, '.'); + const ptrdiff_t len1 = majorVersion_1 - version_1; + const ptrdiff_t len2 = majorVersion_2 - version_2; + return len1 == len2 && majorVersion_1 && majorVersion_2 && + ddsrt_strncasecmp(version_1, version_2, (size_t) len1) == 0; + } + return false; +} + +static DDS_Security_boolean +is_partition_qos_in_criteria( + const struct criteria *criteria, + const DDS_Security_PartitionQosPolicy *partitions) +{ + unsigned int partition_index = 0; + const char *partitionDefault[] = {""}; + const DDS_Security_PartitionQosPolicy *partitionsToCheck; + DDS_Security_PartitionQosPolicy defaultPartitions; + defaultPartitions.name._length = 1; + defaultPartitions.name._maximum = 1; + defaultPartitions.name._buffer = (char **)partitionDefault; + + if (criteria == NULL) + return false; + + if (!partitions || partitions->name._length == 0) + partitionsToCheck = &defaultPartitions; + else + partitionsToCheck = partitions; + + for (partition_index = 0; partition_index < partitionsToCheck->name._length; partition_index++) + { + if (is_partition_in_criteria(criteria, partitionsToCheck->name._buffer[partition_index]) == false) + return false; + } + + return true; +} + +static DDS_Security_boolean +is_partition_in_criteria( + const struct criteria *criteria, + const char *partition_name) +{ + struct partitions *current_partitions; + struct string_value *current_partition; + + if (criteria == NULL || partition_name == NULL) + return false; + + current_partitions = (struct partitions *)criteria->partitions; + while (current_partitions != NULL) + { + current_partition = current_partitions->partition; + while (current_partition != NULL) + { + if (ac_fnmatch(current_partition->value, partition_name)) + return true; + current_partition = (struct string_value *)current_partition->node.next; + } + current_partitions = (struct partitions *)current_partitions->node.next; + } + return false; +} + +static DDS_Security_boolean +is_topic_in_criteria( + const struct criteria *criteria, + const char *topic_name) +{ + struct topics *current_topics; + struct string_value *current_topic; + + if (criteria == NULL || topic_name == NULL) + return false; + + /* Start by checking for a matching topic */ + current_topics = criteria->topics; + while (current_topics != NULL) + { + current_topic = current_topics->topic; + while (current_topic != NULL) + { + if (ac_fnmatch(current_topic->value, topic_name)) + return true; + current_topic = (struct string_value *)current_topic->node.next; + } + current_topics = (struct topics *)current_topics->node.next; + } + return false; +} + +static struct topic_rule * +find_topic_from_domain_rule( + struct domain_rule *domain_rule, + const char *topic_name) +{ + struct topic_rule *topic_rule; + struct topic_rule *topic_found = NULL; + + if (domain_rule->topic_access_rules != NULL && + domain_rule->topic_access_rules->topic_rule != NULL) + { + topic_rule = domain_rule->topic_access_rules->topic_rule; + while (topic_rule != NULL && topic_found == NULL) + { + assert(topic_rule->topic_expression); + if (ac_fnmatch(topic_rule->topic_expression->value, topic_name)) + topic_found = topic_rule; + topic_rule = (struct topic_rule *)topic_rule->node.next; + } + } + return topic_found; +} + +static DDS_Security_boolean +get_topic_sec_attributes( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const char *topic_name, + DDS_Security_TopicSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + dds_security_access_control_impl *ac = (dds_security_access_control_impl *)instance; + local_participant_access_rights *rights; + struct domain_rule *found; + DDS_Security_boolean result = false; + + if (instance == 0) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, "No plugin instance provided"); + return false; + } + if (permissions_handle == DDS_SECURITY_HANDLE_NIL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, "No permissions handle provided"); + return false; + } + if (topic_name == NULL || strlen(topic_name) == 0) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, "No topic name provided"); + return false; + } + if (attributes == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, "No attributes provided"); + return false; + } + rights = find_local_access_rights(ac, permissions_handle); + if (rights == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, "Unused permissions handle provided"); + return false; + } + + memset(attributes, 0, sizeof(*attributes)); + + if (get_topic_type(topic_name) != TOPIC_TYPE_USER) + { + /* No attributes are set for builtin topics. */ + ACCESS_CONTROL_OBJECT_RELEASE(rights); + return true; + } + + if ((found = find_domain_rule_in_governance(rights->governance_tree->dds->domain_access_rules->domain_rule, rights->domain_id))) + { + struct topic_rule *topic_rule = find_topic_from_domain_rule(found, topic_name); + if (topic_rule) + { + attributes->is_discovery_protected = topic_rule->enable_discovery_protection->value; + attributes->is_liveliness_protected = topic_rule->enable_liveliness_protection->value; + attributes->is_read_protected = topic_rule->enable_read_access_control->value; + attributes->is_write_protected = topic_rule->enable_write_access_control->value; + result = true; + } + else + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_FIND_TOPIC_IN_DOMAIN_CODE, 0, DDS_SECURITY_ERR_CAN_NOT_FIND_TOPIC_IN_DOMAIN_MESSAGE, topic_name, rights->domain_id); + } + } + else + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_FIND_DOMAIN_IN_GOVERNANCE_CODE, 0, DDS_SECURITY_ERR_CAN_NOT_FIND_DOMAIN_IN_GOVERNANCE_MESSAGE, rights->domain_id); + } + + ACCESS_CONTROL_OBJECT_RELEASE(rights); + return result; +} + +static DDS_Security_boolean +get_datawriter_sec_attributes( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const char *topic_name, + const DDS_Security_PartitionQosPolicy *partition, + const DDS_Security_DataTagQosPolicy *data_tag, + DDS_Security_EndpointSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(partition); + DDSRT_UNUSED_ARG(data_tag); + dds_security_access_control_impl *ac = (dds_security_access_control_impl *)instance; + + if (instance == 0 || permissions_handle == DDS_SECURITY_HANDLE_NIL || topic_name == 0 || strlen(topic_name) == 0 || attributes == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + return get_sec_attributes(ac, permissions_handle, topic_name, attributes, ex); +} + +static DDS_Security_boolean +get_datareader_sec_attributes( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const char *topic_name, + const DDS_Security_PartitionQosPolicy *partition, + const DDS_Security_DataTagQosPolicy *data_tag, + DDS_Security_EndpointSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(partition); + DDSRT_UNUSED_ARG(data_tag); + dds_security_access_control_impl *ac = (dds_security_access_control_impl *)instance; + + if (instance == 0 || permissions_handle == DDS_SECURITY_HANDLE_NIL || topic_name == 0 || strlen(topic_name) == 0 || attributes == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + return get_sec_attributes(ac, permissions_handle, topic_name, attributes, ex); +} + +static DDS_Security_boolean +return_participant_sec_attributes( + dds_security_access_control *instance, + const DDS_Security_ParticipantSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(attributes); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + /* Nothing to do. */ + return true; +} + +static DDS_Security_boolean +return_topic_sec_attributes( + dds_security_access_control *instance, + const DDS_Security_TopicSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(attributes); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + /* Nothing to do. */ + return true; +} + +static DDS_Security_boolean +return_datawriter_sec_attributes( + dds_security_access_control *instance, + const DDS_Security_EndpointSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(attributes); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + /* Nothing to do. */ + return true; +} + +static DDS_Security_boolean +return_datareader_sec_attributes( + dds_security_access_control *instance, + const DDS_Security_EndpointSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(attributes); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + /* Nothing to do. */ + return true; +} + +static DDS_Security_boolean +return_permissions_handle( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + DDS_Security_SecurityException *ex) +{ + dds_security_access_control_impl *ac = (dds_security_access_control_impl *)instance; + AccessControlObject *object; + + if (!instance || !permissions_handle) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + +#ifdef ACCESS_CONTROL_USE_ONE_PERMISSION + ddsrt_mutex_lock(&ac->lock); + if (permissions_handle == ACCESS_CONTROL_OBJECT_HANDLE(ac->local_access_rights)) + { + ddsrt_mutex_unlock(&ac->lock); + return true; + } + ddsrt_mutex_unlock(&ac->lock); +#else + object = access_control_table_find(ac->local_permissions, permissions_handle); + if (object) + { + access_control_table_remove_object(ac->local_permissions, object); + access_control_object_release(object); + return true; + } +#endif + + object = access_control_table_find(ac->remote_permissions, permissions_handle); + if (!object) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + + access_control_table_remove_object(ac->remote_permissions, object); + access_control_object_release(object); + return true; +} + +int init_access_control(const char *argument, void **context) +{ + DDSRT_UNUSED_ARG(argument); + + dds_security_access_control_impl *access_control = ddsrt_malloc(sizeof(*access_control)); + memset(access_control, 0, sizeof(*access_control)); + +#if TIMED_CALLBACK_IMPLEMENTED + access_control->timed_callbacks = ut_timed_dispatcher_new(); +#endif + access_control->base.validate_local_permissions = &validate_local_permissions; + access_control->base.validate_remote_permissions = &validate_remote_permissions; + access_control->base.check_create_participant = &check_create_participant; + access_control->base.check_create_datawriter = &check_create_datawriter; + access_control->base.check_create_datareader = &check_create_datareader; + access_control->base.check_create_topic = &check_create_topic; + access_control->base.check_local_datawriter_register_instance = &check_local_datawriter_register_instance; + access_control->base.check_local_datawriter_dispose_instance = &check_local_datawriter_dispose_instance; + access_control->base.check_remote_participant = &check_remote_participant; + access_control->base.check_remote_datawriter = &check_remote_datawriter; + access_control->base.check_remote_datareader = &check_remote_datareader; + access_control->base.check_remote_topic = &check_remote_topic; + access_control->base.check_local_datawriter_match = &check_local_datawriter_match; + access_control->base.check_local_datareader_match = &check_local_datareader_match; + access_control->base.check_remote_datawriter_register_instance = &check_remote_datawriter_register_instance; + access_control->base.check_remote_datawriter_dispose_instance = &check_remote_datawriter_dispose_instance; + access_control->base.get_permissions_token = &get_permissions_token; + access_control->base.get_permissions_credential_token = &get_permissions_credential_token; + access_control->base.set_listener = &set_listener; + access_control->base.return_permissions_token = &return_permissions_token; + access_control->base.return_permissions_credential_token = &return_permissions_credential_token; + access_control->base.get_participant_sec_attributes = &get_participant_sec_attributes; + access_control->base.get_topic_sec_attributes = &get_topic_sec_attributes; + access_control->base.get_datawriter_sec_attributes = &get_datawriter_sec_attributes; + access_control->base.get_datareader_sec_attributes = &get_datareader_sec_attributes; + access_control->base.return_participant_sec_attributes = &return_participant_sec_attributes; + access_control->base.return_topic_sec_attributes = &return_topic_sec_attributes; + access_control->base.return_datawriter_sec_attributes = &return_datawriter_sec_attributes; + access_control->base.return_datareader_sec_attributes = &return_datareader_sec_attributes; + access_control->base.return_permissions_handle = &return_permissions_handle; + ddsrt_mutex_init(&access_control->lock); + +#ifdef ACCESS_CONTROL_USE_ONE_PERMISSION + access_control->local_access_rights = NULL; +#else + access_control->local_permissions = access_control_table_new(); +#endif + access_control->remote_permissions = access_control_table_new(); + + OpenSSL_add_all_algorithms(); + OpenSSL_add_all_ciphers(); + OpenSSL_add_all_digests(); + ERR_load_BIO_strings(); + ERR_load_crypto_strings(); + + *context = access_control; + return 0; +} + +static bool +get_sec_attributes( + dds_security_access_control_impl *ac, + const DDS_Security_PermissionsHandle permissions_handle, + const char *topic_name, + DDS_Security_EndpointSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + local_participant_access_rights *rights; + DDS_Security_boolean result = false; + TOPIC_TYPE topic_type; + assert(topic_name); + assert(attributes); + memset(attributes, 0, sizeof(DDS_Security_EndpointSecurityAttributes)); + if ((rights = find_local_access_rights(ac, permissions_handle)) == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, "Invalid permissions handle"); + return false; + } + + if ((topic_type = get_topic_type(topic_name)) != TOPIC_TYPE_USER) + { + /* Builtin topics are treated in a special manner. */ + result = true; + + if (topic_type == TOPIC_TYPE_SECURE_ParticipantsSecure || topic_type == TOPIC_TYPE_SECURE_PublicationsSecure || + topic_type == TOPIC_TYPE_SECURE_SubscriptionsSecure || topic_type == TOPIC_TYPE_SECURE_ParticipantMessageSecure) + { + struct domain_rule *found = find_domain_rule_in_governance(rights->governance_tree->dds->domain_access_rules->domain_rule, rights->domain_id); + if (found) + { /* Domain matched */ + /* is_submessage_protected should match is_liveliness_protected of + * ParticipantSecurityAttributes for DCPSParticipantMessageSecure. + * is_submessage_protected should match is_discovery_protected of + * ParticipantSecurityAttributes for OTHER 3.*/ + if (topic_type == TOPIC_TYPE_SECURE_ParticipantMessageSecure) + { + attributes->is_submessage_protected = !(found->liveliness_protection_kind->value == DDS_SECURITY_PROTECTION_KIND_NONE); + attributes->plugin_endpoint_attributes = get_plugin_endpoint_security_attributes_mask( + /* payload encrypted */ + false, + /* submsg encrypted */ + found->liveliness_protection_kind->value == DDS_SECURITY_PROTECTION_KIND_ENCRYPT || + found->liveliness_protection_kind->value == DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION, + /* submsg authenticated */ + found->liveliness_protection_kind->value == DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION || + found->liveliness_protection_kind->value == DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION); + } + else + { + attributes->is_submessage_protected = !(found->discovery_protection_kind->value == DDS_SECURITY_PROTECTION_KIND_NONE); + attributes->plugin_endpoint_attributes = get_plugin_endpoint_security_attributes_mask( + /* payload encrypted */ + false, + /* submsg encrypted */ + found->discovery_protection_kind->value == DDS_SECURITY_PROTECTION_KIND_ENCRYPT || + found->discovery_protection_kind->value == DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION, + /* submsg authenticated */ + found->discovery_protection_kind->value == DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION || + found->discovery_protection_kind->value == DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION); + } + } + else + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_FIND_DOMAIN_IN_GOVERNANCE_CODE, 0, DDS_SECURITY_ERR_CAN_NOT_FIND_DOMAIN_IN_GOVERNANCE_MESSAGE, rights->domain_id); + result = false; + } + attributes->is_read_protected = false; + attributes->is_write_protected = false; + attributes->is_payload_protected = false; + attributes->is_key_protected = false; + } + else if (topic_type == TOPIC_TYPE_SECURE_ParticipantStatelessMessage) + { + attributes->plugin_endpoint_attributes = DDS_SECURITY_ENDPOINT_ATTRIBUTES_FLAG_IS_VALID; + attributes->is_read_protected = false; + attributes->is_write_protected = false; + attributes->is_payload_protected = false; + attributes->is_key_protected = false; + attributes->is_submessage_protected = false; + } + else if (topic_type == TOPIC_TYPE_SECURE_ParticipantVolatileMessageSecure) + { + attributes->plugin_endpoint_attributes = DDS_SECURITY_ENDPOINT_ATTRIBUTES_FLAG_IS_VALID | + DDS_SECURITY_PLUGIN_ENDPOINT_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ENCRYPTED; + attributes->is_read_protected = false; + attributes->is_write_protected = false; + attributes->is_payload_protected = false; + attributes->is_key_protected = false; + attributes->is_submessage_protected = true; + } + else + { + /* Non secure builtin topics. */ + attributes->plugin_endpoint_attributes = DDS_SECURITY_ENDPOINT_ATTRIBUTES_FLAG_IS_VALID; + attributes->is_read_protected = false; + attributes->is_write_protected = false; + attributes->is_payload_protected = false; + attributes->is_key_protected = false; + attributes->is_submessage_protected = false; + } + } + else + { + /* Normal user topic attributes are acquired from governance and permission documents. */ + struct domain_rule *found = find_domain_rule_in_governance(rights->governance_tree->dds->domain_access_rules->domain_rule, rights->domain_id); + if (found) + { /* Domain matched */ + struct topic_rule *topic_rule = find_topic_from_domain_rule(found, topic_name); + if (topic_rule) + { /* Topic matched */ + attributes->is_discovery_protected = topic_rule->enable_discovery_protection->value; + attributes->is_liveliness_protected = topic_rule->enable_liveliness_protection->value; + attributes->is_read_protected = topic_rule->enable_read_access_control->value; + attributes->is_write_protected = topic_rule->enable_write_access_control->value; + attributes->is_payload_protected = topic_rule->data_protection_kind->value != DDS_SECURITY_BASICPROTECTION_KIND_NONE; + attributes->is_submessage_protected = topic_rule->metadata_protection_kind->value != DDS_SECURITY_PROTECTION_KIND_NONE; + attributes->is_key_protected = topic_rule->data_protection_kind->value == DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT; + + /*calculate and assign the mask */ + attributes->plugin_endpoint_attributes = get_plugin_endpoint_security_attributes_mask( + topic_rule->data_protection_kind->value == DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT, + topic_rule->metadata_protection_kind->value == DDS_SECURITY_PROTECTION_KIND_ENCRYPT || + topic_rule->metadata_protection_kind->value == DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION, + topic_rule->metadata_protection_kind->value == DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION || + topic_rule->metadata_protection_kind->value == DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION); + + memset(&attributes->ac_endpoint_properties, 0, sizeof(DDS_Security_PropertySeq)); + result = true; + } + else + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_FIND_TOPIC_IN_DOMAIN_CODE, 0, DDS_SECURITY_ERR_CAN_NOT_FIND_TOPIC_IN_DOMAIN_MESSAGE, topic_name, rights->domain_id); + } + } + else + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_FIND_DOMAIN_IN_GOVERNANCE_CODE, 0, DDS_SECURITY_ERR_CAN_NOT_FIND_DOMAIN_IN_GOVERNANCE_MESSAGE, rights->domain_id); + } + } + ACCESS_CONTROL_OBJECT_RELEASE(rights); + return result; +} + +static char * +get_access_control_class_id( + const char *classid) +{ + size_t sz = strlen(ACCESS_CONTROL_PROTOCOL_CLASS) + strlen(classid) + 6; + char *classId = ddsrt_malloc(sz); + snprintf(classId, sz, "%s:%s:%1u.%1u", ACCESS_CONTROL_PROTOCOL_CLASS, classid, ACCESS_CONTROL_PROTOCOL_VERSION_MAJOR, ACCESS_CONTROL_PROTOCOL_VERSION_MINOR); + return classId; +} + +static void +sanity_check_local_access_rights( + local_participant_access_rights *rights) +{ +#ifndef NDEBUG + if (rights) + { + assert(rights->permissions_document); + assert(rights->governance_tree); + assert(rights->governance_tree->dds); + assert(rights->governance_tree->dds->domain_access_rules); + assert(rights->governance_tree->dds->domain_access_rules->domain_rule); + assert(rights->permissions_tree); + assert(rights->permissions_tree->dds); + assert(rights->permissions_tree->dds->permissions); + assert(rights->permissions_tree->dds->permissions->grant); + } +#else + DDSRT_UNUSED_ARG(rights); +#endif +} + +static void +sanity_check_remote_access_rights( + remote_participant_access_rights *rights) +{ +#ifndef NDEBUG + /* Just some sanity checks. */ + if (rights) + { + assert(rights->permissions); + assert(rights->permissions->permissions_tree); + assert(rights->permissions->permissions_tree->dds); + assert(rights->permissions->permissions_tree->dds->permissions); + assert(rights->permissions->remote_permissions_token_class_id); + assert(rights->local_rights); + sanity_check_local_access_rights(rights->local_rights); + } +#else + DDSRT_UNUSED_ARG(rights); +#endif +} + +static local_participant_access_rights * +find_local_access_rights( + dds_security_access_control_impl *ac, + DDS_Security_PermissionsHandle handle) +{ + local_participant_access_rights *rights = NULL; + +#ifdef ACCESS_CONTROL_USE_ONE_PERMISSION + DDSRT_UNUSED_ARG(handle); + + ddsrt_mutex_lock(&ac->lock); + if (handle == ACCESS_CONTROL_OBJECT_HANDLE(ac->local_access_rights)) + rights = (local_participant_access_rights *)ACCESS_CONTROL_OBJECT_KEEP(ac->local_access_rights); + ddsrt_mutex_unlock(&ac->lock); +#else + rights = (local_participant_access_rights *)access_control_table_find(ac->local_permissions, handle); +#endif + + sanity_check_local_access_rights(rights); + return rights; +} + +struct find_by_identity_arg +{ + AccessControlObject *object; + DDS_Security_IdentityHandle handle; +}; + +#ifndef ACCESS_CONTROL_USE_ONE_PERMISSION +static int +local_identity_handle_match( + AccessControlObject *obj, + void *arg) +{ + local_participant_access_rights *rights = (local_participant_access_rights *)obj; + struct find_by_identity_arg *info = arg; + + if (rights->local_identity == info->handle) + { + info->object = obj; + return 0; + } + + return 1; +} +#endif + +static int +remote_identity_handle_match( + AccessControlObject *obj, + void *arg) +{ + remote_participant_access_rights *rights = (remote_participant_access_rights *)obj; + struct find_by_identity_arg *info = arg; + + if (rights->remote_identity == info->handle) + { + info->object = ACCESS_CONTROL_OBJECT_KEEP(obj); + return 0; + } + + return 1; +} + +static local_participant_access_rights * +find_local_rights_by_identity( + dds_security_access_control_impl *ac, + DDS_Security_IdentityHandle identity_handle) +{ + local_participant_access_rights *rights = NULL; + +#ifdef ACCESS_CONTROL_USE_ONE_PERMISSION + DDSRT_UNUSED_ARG(identity_handle); + + ddsrt_mutex_lock(&ac->lock); + rights = (local_participant_access_rights *)ACCESS_CONTROL_OBJECT_KEEP(ac->local_access_rights); + ddsrt_mutex_unlock(&ac->lock); +#else + { + struct find_by_identity_arg args; + args.object = NULL; + args.handle = identity_handle; + access_control_table_walk(ac->local_permissions, local_identity_handle_match, &args); + rights = (local_participant_access_rights *)args.object; + } +#endif + sanity_check_local_access_rights(rights); + return rights; +} + +static remote_participant_access_rights * +find_remote_rights_by_identity( + dds_security_access_control_impl *ac, + DDS_Security_IdentityHandle identity_handle) +{ + struct find_by_identity_arg args; + args.object = NULL; + args.handle = identity_handle; + access_control_table_walk(ac->remote_permissions, remote_identity_handle_match, &args); + sanity_check_remote_access_rights((remote_participant_access_rights *)args.object); + return (remote_participant_access_rights *)args.object; +} + +struct find_by_permissions_handle_arg +{ + AccessControlObject *object; + DDS_Security_PermissionsHandle handle; +}; + +static int +remote_permissions_handle_match( + AccessControlObject *obj, + void *arg) +{ + struct find_by_permissions_handle_arg *info = arg; + if (obj->handle == info->handle) + { + info->object = ACCESS_CONTROL_OBJECT_KEEP(obj); + return 0; + } + return 1; +} + +static remote_participant_access_rights * +find_remote_permissions_by_permissions_handle( + dds_security_access_control_impl *ac, + DDS_Security_PermissionsHandle permissions_handle) +{ + struct find_by_permissions_handle_arg args; + args.object = NULL; + args.handle = permissions_handle; + access_control_table_walk(ac->remote_permissions, remote_permissions_handle_match, &args); + sanity_check_remote_access_rights((remote_participant_access_rights *)args.object); + return (remote_participant_access_rights *)args.object; +} + +#if TIMED_CALLBACK_IMPLEMENTED + +typedef struct +{ + dds_security_access_control_impl *ac; + DDS_Security_PermissionsHandle hdl; +} validity_cb_info; + +static void +validity_callback(struct ut_timed_dispatcher_t *d, + ut_timed_cb_kind kind, + void *listener, + void *arg) +{ + validity_cb_info *info = arg; + assert(d); + assert(arg); + if (kind == UT_TIMED_CB_KIND_TIMEOUT) + { + assert(listener); + if (1 /* TODO: Check if hdl is still valid or if it has been already returned. */) + { + dds_security_access_control_listener *ac_listener = (dds_security_access_control_listener *)listener; + if (ac_listener->on_revoke_permissions) + ac_listener->on_revoke_permissions(ac_listener, (dds_security_access_control *)info->ac, info->hdl); + } + } + ddsrt_free(arg); +} + +static void +add_validity_end_trigger(dds_security_access_control_impl *ac, + const DDS_Security_PermissionsHandle permissions_handle, + dds_time_t end) +{ + validity_cb_info *arg = ddsrt_malloc(sizeof(validity_cb_info)); + arg->ac = ac; + arg->hdl = permissions_handle; + ut_timed_dispatcher_add(ac->timed_callbacks, validity_callback, end, (void *)arg); +} +#endif + +static DDS_Security_boolean +is_allowed_by_permissions(struct permissions_parser *permissions, + int domain_id, + const char *topic_name, + const DDS_Security_PartitionQosPolicy *partitions, + const char *identity_subject_name, + permission_criteria_type criteria_type, + DDS_Security_SecurityException *ex) +{ + struct grant *permissions_grant; + struct allow_deny_rule *current_rule; + struct criteria *current_criteria; + + assert(permissions); + assert(permissions->dds); + assert(permissions->dds->permissions); + + permissions_grant = permissions->dds->permissions->grant; + + /* Check for a matching grant */ + while (permissions_grant != NULL) + { + /* Verify that it is within the validity date and the subject name matches */ + if (permissions_grant->subject_name != NULL && + permissions_grant->subject_name->value != NULL && + strcmp(permissions_grant->subject_name->value, identity_subject_name) == 0) + { + dds_time_t tnow = dds_time(); + if (tnow <= DDS_Security_parse_xml_date(permissions_grant->validity->not_before->value)) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_VALIDITY_PERIOD_NOT_STARTED_CODE, 0, + DDS_SECURITY_ERR_VALIDITY_PERIOD_NOT_STARTED_MESSAGE, permissions_grant->subject_name->value, permissions_grant->validity->not_before->value); + return false; + } + if (tnow >= DDS_Security_parse_xml_date(permissions_grant->validity->not_after->value)) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_CODE, 0, + DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_MESSAGE, permissions_grant->subject_name->value, permissions_grant->validity->not_after->value); + return false; + } + + current_rule = permissions_grant->allow_deny_rule; + while (current_rule != NULL) + { + /* Check if the domain matches the given ID otherwise move on */ + if (domainid_within_sets(current_rule->domains->domain_id_set, domain_id)) + { + if (topic_name == NULL) + { + if (current_rule->rule_type == ALLOW_RULE) + return true; + } + + /* Check all subscribe criteria to find the topics, partition and tags */ + current_criteria = current_rule->criteria; + while (current_criteria != NULL) + { + if (current_criteria->criteria_type == criteria_type || (int)criteria_type == UNKNOWN_CRITERIA) + { + if (is_topic_in_criteria(current_criteria, topic_name) && is_partition_qos_in_criteria(current_criteria, partitions)) + { + if (current_rule->rule_type == ALLOW_RULE) + return true; + if (current_rule->rule_type == DENY_RULE) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_ACCESS_DENIED_CODE, 0, "%s found in deny_rule.", topic_name); + return false; + } + } + } + current_criteria = (struct criteria *)current_criteria->node.next; + } + } + current_rule = (struct allow_deny_rule *)current_rule->node.next; + } + + /* If nothing found but the grant matches, return the default value */ + if (permissions_grant->default_action == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_ACCESS_DENIED_CODE, 0, "No rule found for %s", topic_name ? topic_name : "participant"); + return false; + } + + if (strcmp(permissions_grant->default_action->value, "ALLOW") != 0) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_ACCESS_DENIED_CODE, 0, "%s denied by default rule", topic_name ? topic_name : "participant"); + return false; + } + + return true; + } + permissions_grant = (struct grant *)permissions_grant->node.next; + } + + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_FIND_PERMISSIONS_GRANT_CODE, 0, DDS_SECURITY_ERR_CAN_NOT_FIND_PERMISSIONS_GRANT_MESSAGE); + return false; +} + +static bool +read_document_from_file( + const char *filename, + char **doc, + DDS_Security_SecurityException *ex) +{ + DDSRT_WARNING_MSVC_OFF(4996); + FILE *fp; + char *document = NULL; + char *fname = NULL; + size_t sz, r; + + assert(doc); + *doc = NULL; + /* Get portable file name. */ + fname = DDS_Security_normalize_file(filename); + if (fname) + { + /* Get size if it is a accessible regular file (no dir or link). */ + sz = ac_regular_file_size(fname); + if (sz > 0) + { + /* Open the actual file. */ + fp = fopen(fname, "r"); + if (fp) + { + /* Read the content. */ + document = ddsrt_malloc(sz + 1); + r = fread(document, 1, sz, fp); + if (r == 0) + { + ddsrt_free(document); + } + else + { + document[r] = '\0'; + *doc = document; + } + (void)fclose(fp); + } + } + ddsrt_free(fname); + } + + if ((*doc) == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE, 0, DDS_SECURITY_ERR_INVALID_FILE_PATH_MESSAGE, (filename ? filename : "NULL")); + return false; + } + return true; + DDSRT_WARNING_MSVC_ON(4996); +} + +static bool +read_document( + const char *doc_uri, + char **doc, + DDS_Security_SecurityException *ex) +{ + bool result = true; + char *data = NULL; + + switch (DDS_Security_get_conf_item_type(doc_uri, &data)) + { + case DDS_SECURITY_CONFIG_ITEM_PREFIX_DATA: + *doc = data; + break; + case DDS_SECURITY_CONFIG_ITEM_PREFIX_FILE: + result = read_document_from_file(data, doc, ex); + ddsrt_free(data); + break; + default: + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_URI_TYPE_NOT_SUPPORTED_CODE, 0, DDS_SECURITY_ERR_URI_TYPE_NOT_SUPPORTED_MESSAGE, doc_uri); + return false; + } + return result; +} + +static bool +validate_subject_name_in_permissions(struct permissions_parser *permissions_tree, + const char *identity_subject_name, + char **permission_subject_name, + dds_time_t *permission_validity_not_after, + DDS_Security_SecurityException *ex) +{ + + struct grant *permissions_grant; + assert(permission_subject_name); + + *permission_subject_name = NULL; + if (permissions_tree == NULL || permissions_tree->dds == NULL || permissions_tree->dds->permissions == NULL || permissions_tree->dds->permissions->grant == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } + + permissions_grant = permissions_tree->dds->permissions->grant; + while (permissions_grant != NULL) + { + /* Verify that it is within the validity date and the subject name matches */ + if (identity_subject_name != NULL && ac_check_subjects_are_equal(permissions_grant->subject_name->value, identity_subject_name)) + { + dds_time_t tnow = dds_time (); + if (tnow <= DDS_Security_parse_xml_date(permissions_grant->validity->not_before->value)) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_VALIDITY_PERIOD_NOT_STARTED_CODE, 0, + DDS_SECURITY_ERR_VALIDITY_PERIOD_NOT_STARTED_MESSAGE, permissions_grant->subject_name->value, permissions_grant->validity->not_before->value); + return false; + } + if (tnow >= DDS_Security_parse_xml_date(permissions_grant->validity->not_after->value)) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_CODE, 0, + DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_MESSAGE, permissions_grant->subject_name->value, permissions_grant->validity->not_after->value); + return false; + } + + /* identity subject name and permission subject name may not be exactly same because of different string representations + * That's why we are returning the string in permissions file to be stored for further comparisons */ + *permission_subject_name = ddsrt_strdup(permissions_grant->subject_name->value); + *permission_validity_not_after = DDS_Security_parse_xml_date(permissions_grant->validity->not_after->value); + return true; + } + permissions_grant = (struct grant *)permissions_grant->node.next; + } + + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_SUBJECT_NAME_CODE, 0, + DDS_SECURITY_ERR_INVALID_SUBJECT_NAME_MESSAGE); + return false; +} + +static local_participant_access_rights * +check_and_create_local_participant_rights( + DDS_Security_IdentityHandle identity_handle, + int domain_id, + const DDS_Security_Qos *participant_qos, + DDS_Security_SecurityException *ex) +{ + local_participant_access_rights *rights = NULL; + X509 *identity_cert; + X509 *permission_ca = NULL; + size_t pdlen; + size_t gvlen; + char *identity_cert_data = NULL; + char *permission_ca_data = NULL; + char *permission_document = NULL; + char *governance_document = NULL; + char *permission_xml = NULL; + char *governance_xml = NULL; + char *identity_subject = NULL; + struct governance_parser *governance_tree = NULL; + struct permissions_parser *permissions_tree = NULL; + char *permission_subject = NULL; + char *permissions_uri = NULL; + char *governance_uri = NULL; + dds_time_t permission_expiry = DDS_TIME_INVALID; + + /* Retrieve the identity certificate from the participant QoS */ + identity_cert_data = DDS_Security_Property_get_value(&participant_qos->property.value, QOS_PROPERTY_IDENTITY_CERT); + if (!identity_cert_data) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_MISSING_PROPERTY_CODE, 0, + DDS_SECURITY_ERR_MISSING_PROPERTY_MESSAGE, QOS_PROPERTY_IDENTITY_CERT); + goto err_no_identity_cert; + } + + if (!ac_X509_certificate_read(identity_cert_data, &identity_cert, ex)) + goto err_inv_identity_cert; + + if (!(identity_subject = ac_get_certificate_subject_name(identity_cert, ex))) + goto err_inv_identity_cert; + + if (!(governance_uri = DDS_Security_Property_get_value(&participant_qos->property.value, QOS_PROPERTY_GOVERNANCE_DOCUMENT))) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_MISSING_PROPERTY_CODE, 0, + DDS_SECURITY_ERR_MISSING_PROPERTY_MESSAGE, QOS_PROPERTY_GOVERNANCE_DOCUMENT); + goto err_no_governance; + } + + if (!(permissions_uri = DDS_Security_Property_get_value(&participant_qos->property.value, QOS_PROPERTY_PERMISSIONS_DOCUMENT))) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_MISSING_PROPERTY_CODE, 0, + DDS_SECURITY_ERR_MISSING_PROPERTY_MESSAGE, QOS_PROPERTY_PERMISSIONS_DOCUMENT); + goto err_no_permissions; + } + + if (!(permission_ca_data = DDS_Security_Property_get_value(&participant_qos->property.value, QOS_PROPERTY_PERMISSIONS_CA))) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_MISSING_PROPERTY_CODE, 0, + DDS_SECURITY_ERR_MISSING_PROPERTY_MESSAGE, QOS_PROPERTY_PERMISSIONS_CA); + goto err_no_permission_ca; + } + + if (strlen(governance_uri) == 0 && strlen(permissions_uri) == 0 && strlen(permission_ca_data) == 0) + { + bool result; + + result = ac_parse_governance_xml(DDS_SECURITY_DEFAULT_GOVERNANCE, &governance_tree, ex); + assert(result); + DDSRT_UNUSED_ARG(result); + + result = ac_parse_permissions_xml(DDS_SECURITY_DEFAULT_PERMISSIONS, &permissions_tree, ex); + assert(result); + DDSRT_UNUSED_ARG(result); + + /*set subject name on default permissions */ + ddsrt_free(permissions_tree->dds->permissions->grant->subject_name->value); + permissions_tree->dds->permissions->grant->subject_name->value = ddsrt_strdup(identity_subject); + permission_document = ddsrt_strdup(""); + + rights = ac_local_participant_access_rights_new(identity_handle, domain_id, permission_document, NULL, identity_subject, governance_tree, permissions_tree); + sanity_check_local_access_rights(rights); + } + else if (strlen(governance_uri) > 0 && strlen(permissions_uri) > 0 && strlen(permission_ca_data) > 0) + { + /* Retrieve the permission ca certificate from the participant QoS */ + if (!ac_X509_certificate_read(permission_ca_data, &permission_ca, ex)) + goto err_inv_permission_ca; + + /* Retrieve the permissions document from the participant QoS */ + if (!read_document(permissions_uri, &permission_document, ex)) + goto err_read_perm_doc; + + if ((pdlen = strlen(permission_document)) == 0) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PERMISSION_DOCUMENT_PROPERTY_CODE, + DDS_SECURITY_VALIDATION_FAILED, DDS_SECURITY_ERR_INVALID_PERMISSION_DOCUMENT_PROPERTY_MESSAGE); + goto err_read_perm_doc; + } + + /* Retrieve the governance from the participant QoS */ + if (!read_document(governance_uri, &governance_document, ex)) + goto err_read_gov_doc; + + if ((gvlen = strlen(governance_document)) == 0) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_GOVERNANCE_DOCUMENT_PROPERTY_CODE, + DDS_SECURITY_VALIDATION_FAILED, DDS_SECURITY_ERR_INVALID_GOVERNANCE_DOCUMENT_PROPERTY_MESSAGE); + goto err_read_gov_doc; + } + + if (!ac_PKCS7_document_check(permission_document, pdlen, permission_ca, &permission_xml, ex)) + goto err_inv_perm_doc; + + if (!ac_PKCS7_document_check(governance_document, gvlen, permission_ca, &governance_xml, ex)) + goto err_inv_gov_doc; + + if (!ac_parse_governance_xml(governance_xml, &governance_tree, ex)) + goto err_inv_gov_xml; + + if (!ac_parse_permissions_xml(permission_xml, &permissions_tree, ex)) + { + ac_return_governance_tree(governance_tree); + goto err_inv_perm_xml; + } + + /* check if subject name of identity certificate matches the subject name in the permissions document */ + if (!validate_subject_name_in_permissions(permissions_tree, identity_subject, &permission_subject, &permission_expiry, ex)) + { + ac_return_governance_tree(governance_tree); + ac_return_permissions_tree(permissions_tree); + goto err_inv_subject; + } + + rights = ac_local_participant_access_rights_new(identity_handle, domain_id, permission_document, permission_ca, permission_subject, governance_tree, permissions_tree); + rights->permissions_expiry = permission_expiry; + sanity_check_local_access_rights(rights); + } + else + { /*one of them is not empty but the others */ + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, DDS_SECURITY_VALIDATION_FAILED, + "Governance, Permissions and Permissions CA properties do not exist properly. Either all must be empty or all must be valid"); + goto err_inv_properties; + } + +err_inv_subject: +err_inv_perm_xml: +err_inv_gov_xml: + ddsrt_free(governance_xml); +err_inv_gov_doc: + ddsrt_free(permission_xml); +err_inv_perm_doc: +err_read_gov_doc: + ddsrt_free(governance_document); +err_read_perm_doc: + if (!rights) + { + ddsrt_free(permission_document); + X509_free(permission_ca); + } +err_inv_properties: +err_inv_permission_ca: + ddsrt_free(permission_ca_data); +err_no_permission_ca: + ddsrt_free(permissions_uri); +err_no_permissions: + ddsrt_free(governance_uri); +err_no_governance: + X509_free(identity_cert); +err_inv_identity_cert: + ddsrt_free(identity_subject); + ddsrt_free(permission_subject); + ddsrt_free(identity_cert_data); +err_no_identity_cert: + return rights; +} + +static remote_participant_access_rights * +check_and_create_remote_participant_rights( + DDS_Security_IdentityHandle remote_identity_handle, + local_participant_access_rights *local_rights, + const DDS_Security_PermissionsToken *remote_permissions_token, + const DDS_Security_AuthenticatedPeerCredentialToken *remote_credential_token, + DDS_Security_SecurityException *ex) +{ + remote_participant_access_rights *rights = NULL; + X509 *identity_cert = NULL; + const DDS_Security_Property_t *identity_cert_property; + const DDS_Security_Property_t *permission_doc_property; + char *identity_subject = NULL; + char *permissions_xml = NULL; + remote_permissions *permissions = NULL; + char *permission_subject = NULL; + dds_time_t permission_expiry = DDS_TIME_INVALID; + size_t len; + + /* Retrieve the remote identity certificate from the remote_credential_token */ + identity_cert_property = DDS_Security_DataHolder_find_property(remote_credential_token, "c.id"); + if (!identity_cert_property || !identity_cert_property->value) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_MISSING_PROPERTY_CODE, 0, + DDS_SECURITY_ERR_MISSING_PROPERTY_MESSAGE, "c.id"); + goto err_no_identity_cert; + } + + len = strlen(identity_cert_property->value); + assert (len <= INT32_MAX); + if (!ac_X509_certificate_from_data(identity_cert_property->value, (int) len, &identity_cert, ex)) + goto err_inv_identity_cert; + + if (!(identity_subject = ac_get_certificate_subject_name(identity_cert, ex))) + goto err_inv_identity_cert; + + /* Retrieve the remote permissions document from the remote_credential_token */ + permission_doc_property = DDS_Security_DataHolder_find_property(remote_credential_token, "c.perm"); + if (!permission_doc_property || !permission_doc_property->value) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_MISSING_PROPERTY_CODE, 0, DDS_SECURITY_ERR_MISSING_PROPERTY_MESSAGE, "c.perm"); + goto err_inv_perm_doc; + } + + if (strlen(permission_doc_property->value) == 0) + { + /* use default permissions document (all deny) if there is no permissions file + *to communicate with access_control=false and comply with previous release */ + struct domain_rule *domainRule = find_domain_rule_in_governance(local_rights->governance_tree->dds->domain_access_rules->domain_rule, local_rights->domain_id); + if (!domainRule->enable_join_access_control->value) + { + permissions_xml = ddsrt_str_replace(DDS_SECURITY_DEFAULT_PERMISSIONS, "DEFAULT_SUBJECT", identity_subject, 1); + } + else + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PERMISSION_DOCUMENT_PROPERTY_CODE, 0, DDS_SECURITY_ERR_INVALID_PERMISSION_DOCUMENT_PROPERTY_MESSAGE); + goto err_inv_perm_doc; + } + } + else + { + if (!ac_PKCS7_document_check(permission_doc_property->value, strlen(permission_doc_property->value), local_rights->permissions_ca, &permissions_xml, ex)) + goto err_inv_perm_doc; + } + + permissions = ddsrt_malloc(sizeof(remote_permissions)); + permissions->ref_cnt = 0; + permissions->permissions_tree = NULL; + if (!ac_parse_permissions_xml(permissions_xml, &(permissions->permissions_tree), ex)) + { + ddsrt_free(permissions); + goto err_inv_perm_xml; + } + + /* check if subject name of identity certificate matches the subject name in the permissions document */ + if (!validate_subject_name_in_permissions(permissions->permissions_tree, identity_subject, &permission_subject, &permission_expiry, ex)) + { + ac_return_permissions_tree(permissions->permissions_tree); + ddsrt_free(permissions); + goto err_inv_subject; + } + rights = ac_remote_participant_access_rights_new(remote_identity_handle, local_rights, permissions, permission_expiry, remote_permissions_token, permission_subject); + sanity_check_remote_access_rights(rights); + ddsrt_free(permission_subject); + +err_inv_subject: +err_inv_perm_xml: + ddsrt_free(permissions_xml); +err_inv_perm_doc: + X509_free(identity_cert); +err_inv_identity_cert: + ddsrt_free(identity_subject); +err_no_identity_cert: + return rights; +} + +static TOPIC_TYPE +get_topic_type( + const char *topic_name) +{ + TOPIC_TYPE type = TOPIC_TYPE_USER; + assert(topic_name); + + /* All builtin topics start with "DCPS" */ + if (strncmp(topic_name, "DCPS", 4) == 0) + { + /* There are a number of builtin topics starting with "DCPSParticipant" */ + if (strncmp(&(topic_name[4]), "Participant", 11) == 0) + { + if (strcmp(&(topic_name[15]), "") == 0) + type = TOPIC_TYPE_NON_SECURE_BUILTIN; /* DCPSParticipant */ + else if (strcmp(&(topic_name[15]), "Message") == 0) + type = TOPIC_TYPE_NON_SECURE_BUILTIN; /* DCPSParticipantMessage */ + else if (strcmp(&(topic_name[15]), "MessageSecure") == 0) + type = TOPIC_TYPE_SECURE_ParticipantMessageSecure; /* DCPSParticipantMessageSecure */ + else if (strcmp(&(topic_name[15]), "VolatileMessageSecure") == 0) + type = TOPIC_TYPE_SECURE_ParticipantVolatileMessageSecure; /* DCPSParticipantVolatileMessageSecure */ + else if (strcmp(&(topic_name[15]), "StatelessMessage") == 0) + type = TOPIC_TYPE_SECURE_ParticipantStatelessMessage; /* DCPSParticipantStatelessMessage */ + else if (strcmp(&(topic_name[15]), "sSecure") == 0) + type = TOPIC_TYPE_SECURE_ParticipantsSecure; /* DCPSParticipantsSecure */ + } + else if (strcmp(&(topic_name[4]), "SubscriptionsSecure") == 0) + type = TOPIC_TYPE_SECURE_SubscriptionsSecure; /* DCPSSubscriptionsSecure */ + else if (strcmp(&(topic_name[4]), "PublicationsSecure") == 0) + type = TOPIC_TYPE_SECURE_PublicationsSecure; /* DCPSPublicationsSecure */ + else if ((strcmp(&(topic_name[4]), "Topic") == 0) || + (strcmp(&(topic_name[4]), "Publication") == 0) || + (strcmp(&(topic_name[4]), "Subscription") == 0)) + { + /* DCPSTopic */ + /* DCPSPublication */ + /* DCPSSubscription */ + type = TOPIC_TYPE_NON_SECURE_BUILTIN; + } + } + return type; +} + +int finalize_access_control(void *context) +{ + dds_security_access_control_impl *access_control = context; + if (access_control) + { +#if TIMED_CALLBACK_IMPLEMENTED + ut_timed_dispatcher_free(access_control->timed_callbacks); +#endif + access_control_table_free(access_control->remote_permissions); +#ifdef ACCESS_CONTROL_USE_ONE_PERMISSION + if (access_control->local_access_rights) + access_control_object_free((AccessControlObject *)access_control->local_access_rights); +#else + access_control_table_free(access_control->local_permissions); +#endif + ddsrt_mutex_destroy(&access_control->lock); + ddsrt_free(access_control); + } + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); + REMOVE_THREAD_STATE(); + ERR_free_strings(); + return 0; +} diff --git a/src/security/builtin_plugins/access_control/src/access_control.h b/src/security/builtin_plugins/access_control/src/access_control.h new file mode 100644 index 0000000..b98d2d7 --- /dev/null +++ b/src/security/builtin_plugins/access_control/src/access_control.h @@ -0,0 +1,21 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef ACCESS_CONTROL_H +#define ACCESS_CONTROL_H + +#include "dds/security/dds_security_api.h" +#include "dds/security/export.h" + +SECURITY_EXPORT int init_access_control(const char *argument, void **context); +SECURITY_EXPORT int finalize_access_control(void *context); + +#endif /* ACCESS_CONTROL_H */ diff --git a/src/security/builtin_plugins/access_control/src/access_control_objects.c b/src/security/builtin_plugins/access_control/src/access_control_objects.c new file mode 100644 index 0000000..cee88cb --- /dev/null +++ b/src/security/builtin_plugins/access_control/src/access_control_objects.c @@ -0,0 +1,283 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include "dds/ddsrt/atomics.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/hopscotch.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/types.h" +#include "access_control_objects.h" +#include "access_control_utils.h" +#include "access_control_parser.h" + +struct AccessControlTable +{ + struct ddsrt_hh *htab; + ddsrt_mutex_t lock; +}; + +bool access_control_object_valid(const AccessControlObject *obj, const AccessControlObjectKind_t kind) +{ + if (!obj) + return false; + if (obj->kind != kind) + return false; + if (obj->handle != (int64_t)(uintptr_t)obj) + return false; + + return true; +} + +static uint32_t access_control_object_hash(const void *obj) +{ + const AccessControlObject *object = obj; + const uint64_t c = 0xE21B371BEB9E6C05; + const uint32_t x = (uint32_t)object->handle; + return (unsigned)((x * c) >> 32); +} + +static int access_control_object_equal(const void *ha, const void *hb) +{ + const AccessControlObject *la = ha; + const AccessControlObject *lb = hb; + return la->handle == lb->handle; +} + +void access_control_object_init(AccessControlObject *obj, AccessControlObjectKind_t kind, AccessControlObjectDestructor destructor) +{ + assert(obj); + obj->kind = kind; + obj->handle = (int64_t)(uintptr_t)obj; + obj->destructor = destructor; + ddsrt_atomic_st32(&obj->refcount, 1); +} + +static void access_control_object_deinit(AccessControlObject *obj) +{ + assert(obj); + obj->handle = DDS_SECURITY_HANDLE_NIL; + obj->kind = ACCESS_CONTROL_OBJECT_KIND_UNKNOWN; + obj->destructor = NULL; +} + +void access_control_object_free(AccessControlObject *obj) +{ + if (obj && obj->destructor) + obj->destructor(obj); +} + +AccessControlObject *access_control_object_keep(AccessControlObject *obj) +{ + if (obj) + ddsrt_atomic_inc32(&obj->refcount); + return obj; +} + +void access_control_object_release(AccessControlObject *obj) +{ + if (obj) + { + if (ddsrt_atomic_dec32_nv(&obj->refcount) == 0) + access_control_object_free(obj); + } +} + +struct AccessControlTable *access_control_table_new(void) +{ + struct AccessControlTable *table; + + table = ddsrt_malloc(sizeof(*table)); + table->htab = ddsrt_hh_new(32, access_control_object_hash, access_control_object_equal); + ddsrt_mutex_init(&table->lock); + return table; +} + +void access_control_table_free(struct AccessControlTable *table) +{ + struct ddsrt_hh_iter it; + AccessControlObject *obj; + + if (!table) + return; + for (obj = ddsrt_hh_iter_first(table->htab, &it); obj; obj = ddsrt_hh_iter_next(&it)) + { + (void)ddsrt_hh_remove(table->htab, obj); + access_control_object_release(obj); + } + ddsrt_hh_free(table->htab); + ddsrt_mutex_destroy(&table->lock); + ddsrt_free(table); +} + +AccessControlObject *access_control_table_insert(struct AccessControlTable *table, AccessControlObject *object) +{ + AccessControlObject template; + AccessControlObject *cur; + assert(table); + assert(object); + template.handle = object->handle; + ddsrt_mutex_lock(&table->lock); + if (!(cur = access_control_object_keep(ddsrt_hh_lookup(table->htab, &template)))) + { + cur = access_control_object_keep(object); + (void)ddsrt_hh_add(table->htab, cur); + } + ddsrt_mutex_unlock(&table->lock); + return cur; +} + +void access_control_table_remove_object(struct AccessControlTable *table, AccessControlObject *object) +{ + assert(table); + assert(object); + ddsrt_mutex_lock(&table->lock); + (void)ddsrt_hh_remove(table->htab, object); + ddsrt_mutex_unlock(&table->lock); + access_control_object_release(object); +} + +AccessControlObject *access_control_table_remove(struct AccessControlTable *table, int64_t handle) +{ + AccessControlObject template; + AccessControlObject *object; + assert(table); + template.handle = handle; + ddsrt_mutex_lock(&table->lock); + if ((object = access_control_object_keep(ddsrt_hh_lookup(table->htab, &template)))) + { + (void)ddsrt_hh_remove(table->htab, object); + access_control_object_release(object); + } + ddsrt_mutex_unlock(&table->lock); + return object; +} + +AccessControlObject *access_control_table_find(struct AccessControlTable *table, int64_t handle) +{ + AccessControlObject template; + AccessControlObject *object; + assert(table); + template.handle = handle; + ddsrt_mutex_lock(&table->lock); + object = access_control_object_keep(ddsrt_hh_lookup(table->htab, &template)); + ddsrt_mutex_unlock(&table->lock); + return object; +} + +void access_control_table_walk(struct AccessControlTable *table, AccessControlTableCallback callback, void *arg) +{ + struct ddsrt_hh_iter it; + AccessControlObject *obj; + int r = 1; + assert(table); + assert(callback); + ddsrt_mutex_lock(&table->lock); + for (obj = ddsrt_hh_iter_first(table->htab, &it); r && obj; obj = ddsrt_hh_iter_next(&it)) + r = callback(obj, arg); + ddsrt_mutex_unlock(&table->lock); +} + +static void local_participant_access_rights_free(AccessControlObject *obj) +{ + local_participant_access_rights *rights = (local_participant_access_rights *)obj; + if (rights) + { + ddsrt_free(rights->permissions_document); + if (rights->permissions_ca) + X509_free(rights->permissions_ca); + access_control_object_deinit((AccessControlObject *)rights); + if (rights->governance_tree) + ac_return_governance_tree(rights->governance_tree); + if (rights->permissions_tree) + ac_return_permissions_tree(rights->permissions_tree); + ddsrt_free(rights->identity_subject_name); + ddsrt_free(rights); + } +} + +local_participant_access_rights *ac_local_participant_access_rights_new( + DDS_Security_IdentityHandle local_identity, + int domain_id, + char *permissions_document, + X509 *permissions_ca, + const char *identity_subject_name, + struct governance_parser *governance_tree, + struct permissions_parser *permissions_tree) +{ + local_participant_access_rights *rights = ddsrt_malloc(sizeof(local_participant_access_rights)); + memset(rights, 0, sizeof(local_participant_access_rights)); + access_control_object_init((AccessControlObject *)rights, ACCESS_CONTROL_OBJECT_KIND_LOCAL_PARTICIPANT, local_participant_access_rights_free); + rights->local_identity = local_identity; + rights->domain_id = domain_id; + rights->permissions_document = permissions_document; + rights->permissions_ca = permissions_ca; + rights->identity_subject_name = ddsrt_strdup(identity_subject_name); + rights->governance_tree = governance_tree; + rights->permissions_tree = permissions_tree; + return rights; +} + + +static void remote_participant_access_rights_free(AccessControlObject *obj) +{ + remote_participant_access_rights *rights = (remote_participant_access_rights *)obj; + if (rights) + { + if (rights->permissions) + { + assert(rights->permissions->ref_cnt > 0); + rights->permissions->ref_cnt--; + if (rights->permissions->ref_cnt == 0) + { + ac_return_permissions_tree(rights->permissions->permissions_tree); + ddsrt_free(rights->permissions->remote_permissions_token_class_id); + ddsrt_free(rights->permissions); + } + } + ddsrt_free(rights->identity_subject_name); + ACCESS_CONTROL_OBJECT_RELEASE(rights->local_rights); + access_control_object_deinit((AccessControlObject *)rights); + ddsrt_free(rights); + } +} + +remote_participant_access_rights * +ac_remote_participant_access_rights_new( + DDS_Security_IdentityHandle remote_identity, + const local_participant_access_rights *local_rights, + remote_permissions *permissions, + dds_time_t permission_expiry, + const DDS_Security_PermissionsToken *remote_permissions_token, + const char *identity_subject) +{ + remote_participant_access_rights *rights = ddsrt_malloc(sizeof(remote_participant_access_rights)); + memset(rights, 0, sizeof(remote_participant_access_rights)); + access_control_object_init((AccessControlObject *)rights, ACCESS_CONTROL_OBJECT_KIND_REMOTE_PARTICIPANT, remote_participant_access_rights_free); + rights->remote_identity = remote_identity; + rights->permissions = permissions; + rights->permissions_expiry = permission_expiry; + rights->local_rights = (local_participant_access_rights *)ACCESS_CONTROL_OBJECT_KEEP(local_rights); + if (rights->permissions) + { + rights->permissions->remote_permissions_token_class_id = ddsrt_strdup(remote_permissions_token->class_id); + rights->permissions->ref_cnt++; + rights->identity_subject_name = ddsrt_strdup(identity_subject); + } + else + { + assert(identity_subject == NULL); + rights->identity_subject_name = NULL; + } + return rights; +} diff --git a/src/security/builtin_plugins/access_control/src/access_control_objects.h b/src/security/builtin_plugins/access_control/src/access_control_objects.h new file mode 100644 index 0000000..b1f033b --- /dev/null +++ b/src/security/builtin_plugins/access_control/src/access_control_objects.h @@ -0,0 +1,106 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef ACCESS_CONTROL_OBJECTS_H +#define ACCESS_CONTROL_OBJECTS_H + +#include +#include "dds/ddsrt/atomics.h" +#include "dds/ddsrt/types.h" +#include "dds/security/dds_security_api.h" + +#define ACCESS_CONTROL_OBJECT(o) ((AccessControlObject *)(o)) +#define ACCESS_CONTROL_OBJECT_HANDLE(o) ((o) ? ACCESS_CONTROL_OBJECT(o)->handle : DDS_SECURITY_HANDLE_NIL) + +#define ACCESS_CONTROL_OBJECT_KEEP(o) access_control_object_keep((AccessControlObject *)(o)) +#define ACCESS_CONTROL_OBJECT_RELEASE(o) access_control_object_release((AccessControlObject *)(o)) +#define ACCESS_CONTROL_OBJECT_VALID(o,k) access_control_object_valid((AccessControlObject *)(o), k) + +typedef enum { + ACCESS_CONTROL_OBJECT_KIND_UNKNOWN, + ACCESS_CONTROL_OBJECT_KIND_LOCAL_PARTICIPANT, + ACCESS_CONTROL_OBJECT_KIND_REMOTE_PARTICIPANT, +} AccessControlObjectKind_t; + +typedef struct AccessControlObject AccessControlObject; +typedef void (*AccessControlObjectDestructor)(AccessControlObject *obj); + +struct AccessControlObject { + int64_t handle; + ddsrt_atomic_uint32_t refcount; + AccessControlObjectKind_t kind; + AccessControlObjectDestructor destructor; +}; + +typedef struct local_participant_access_rights { + AccessControlObject _parent; + DDS_Security_ParticipantSecurityAttributes participant_attributes; + DDS_Security_IdentityHandle local_identity; + struct governance_parser *governance_tree; + struct permissions_parser *permissions_tree; + int domain_id; + char *identity_subject_name; + char *permissions_document; + X509 *permissions_ca; + dds_time_t permissions_expiry; +} local_participant_access_rights; + + +typedef struct remote_permissions { + int ref_cnt; + struct permissions_parser *permissions_tree; + DDS_Security_string remote_permissions_token_class_id; +} remote_permissions; + +typedef struct remote_participant_access_rights { + AccessControlObject _parent; + DDS_Security_IdentityHandle remote_identity; + local_participant_access_rights *local_rights; + remote_permissions *permissions; + char *identity_subject_name; + dds_time_t permissions_expiry; +} remote_participant_access_rights; + +void access_control_object_init(AccessControlObject *obj, AccessControlObjectKind_t kind, AccessControlObjectDestructor destructor); +AccessControlObject *access_control_object_keep(AccessControlObject *obj); +void access_control_object_release(AccessControlObject *obj); +bool access_control_object_valid(const AccessControlObject *obj, AccessControlObjectKind_t kind); +void access_control_object_free(AccessControlObject *obj); + +struct AccessControlTable; +typedef int (*AccessControlTableCallback)(AccessControlObject *obj, void *arg); +struct AccessControlTable *access_control_table_new(void); + +void access_control_table_free(struct AccessControlTable *table); +AccessControlObject *access_control_table_insert(struct AccessControlTable *table, AccessControlObject *object); +void access_control_table_remove_object(struct AccessControlTable *table, AccessControlObject *object); +AccessControlObject *access_control_table_remove(struct AccessControlTable *table, int64_t handle); +AccessControlObject *access_control_table_find(struct AccessControlTable *table, int64_t handle); +void access_control_table_walk(struct AccessControlTable *table, AccessControlTableCallback callback, void *arg); + +local_participant_access_rights *ac_local_participant_access_rights_new( + DDS_Security_IdentityHandle local_identity, + int domain_id, + char *permissions_document, + X509 *permissions_ca, + const char* identity_subject_name, + struct governance_parser *governance_tree, + struct permissions_parser *permissions_tree); + +remote_participant_access_rights *ac_remote_participant_access_rights_new( + DDS_Security_IdentityHandle remote_identity, + const local_participant_access_rights *local_rights, + remote_permissions *permissions, + dds_time_t permission_expiry, + const DDS_Security_PermissionsToken *remote_permissions_token, + const char *identity_subject); + +#endif /* ACCESS_CONTROL_OBJECTS_H */ diff --git a/src/security/builtin_plugins/access_control/src/access_control_parser.c b/src/security/builtin_plugins/access_control/src/access_control_parser.c new file mode 100644 index 0000000..5f1cf2d --- /dev/null +++ b/src/security/builtin_plugins/access_control/src/access_control_parser.c @@ -0,0 +1,1212 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include +#include +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/misc.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/strtol.h" +#include "dds/ddsrt/types.h" +#include "dds/ddsrt/xmlparser.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/core/dds_security_utils.h" +#include "access_control_parser.h" +#include "access_control_utils.h" + +#define DEBUG_PARSER 0 +#if (DEBUG_PARSER) + +static void print_tab(int spaces) +{ + while (spaces > 0) + { + printf(" "); + spaces--; + } +} + +static void print_string_value(struct string_value *val, const char *info, int spaces) +{ + print_tab(spaces); + printf("%s", info); + if (val) + printf(": %s", val->value ? val->value : ""); + printf("\n"); +} + +#define PRINT_VALUE_BASIC(name_, type_) \ + static void print_##name_##_value (type_ *val, const char *info, int spaces) \ + { \ + print_tab(spaces); \ + printf("%s", info); \ + if (val) \ + printf(": %d", val->value); \ + printf("\n"); \ + } +PRINT_VALUE_BASIC(bool, struct boolean_value) +PRINT_VALUE_BASIC(int, struct integer_value) +PRINT_VALUE_BASIC(protection, struct protection_kind_value) +PRINT_VALUE_BASIC(basic_protection, struct basicprotection_kind_value) +#undef PRINT_VALUE_BASIC + +static void print_domains(struct domains *domains, int spaces) +{ + print_tab(spaces); + printf("domains {\n"); + if (domains) + { + struct domain_id_set *current = domains->domain_id_set; + while (current != NULL) + { + if (current->max == NULL) + { + print_int_value(current->min, "id", spaces + 3); + } + else + { + print_int_value(current->min, "min", spaces + 3); + print_int_value(current->max, "max", spaces + 3); + } + current = (struct domain_id_set *)current->node.next; + } + } + else + { + printf(" {\n"); + } + print_tab(spaces); + printf("}\n"); +} + +static void print_topic_rule(struct topic_rule *rule, int spaces) +{ + print_tab(spaces); + printf("topic_rule {\n"); + if (rule) + { + print_string_value(rule->topic_expression, "topic_expression", spaces + 3); + print_bool_value(rule->enable_discovery_protection, "enable_discovery_protection", spaces + 3); + print_bool_value(rule->enable_liveliness_protection, "enable_liveliness_protection", spaces + 3); + print_bool_value(rule->enable_read_access_control, "enable_read_access_control", spaces + 3); + print_bool_value(rule->enable_write_access_control, "enable_write_access_control", spaces + 3); + print_protection_value(rule->metadata_protection_kind, "metadata_protection_kind", spaces + 3); + print_basic_protection_value(rule->data_protection_kind, "data_protection_kind", spaces + 3); + } + else + { + printf(" {\n"); + } + print_tab(spaces); + printf("}\n"); +} + +static void print_topic_access_rules(struct topic_access_rules *tar, int spaces) +{ + print_tab(spaces); + printf("topic_access_rules {\n"); + if (tar) + { + struct topic_rule *current = tar->topic_rule; + while (current != NULL) + { + print_topic_rule(current, spaces + 3); + current = (struct topic_rule *)current->node.next; + } + } + else + { + printf(" {\n"); + } + print_tab(spaces); + printf("}\n"); +} + +static void print_domain_rule(struct domain_rule *rule, int spaces) +{ + print_tab(spaces); + printf("domain_rule {\n"); + if (rule) + { + print_domains(rule->domains, spaces + 3); + print_bool_value(rule->allow_unauthenticated_participants, "allow_unauthenticated_participants", spaces + 3); + print_bool_value(rule->enable_join_access_control, "enable_join_access_control", spaces + 3); + print_protection_value(rule->rtps_protection_kind, "rtps_protection_kind", spaces + 3); + print_protection_value(rule->discovery_protection_kind, "discovery_protection_kind", spaces + 3); + print_protection_value(rule->liveliness_protection_kind, "liveliness_protection_kind", spaces + 3); + print_topic_access_rules(rule->topic_access_rules, spaces + 3); + } + else + { + printf(" {\n"); + } + print_tab(spaces); + printf("}\n"); +} + +static void print_domain_access_rules(struct domain_access_rules *dar, int spaces) +{ + print_tab(spaces); + printf("domain_access_rules {\n"); + if (dar) + { + struct domain_rule *current = dar->domain_rule; + while (current != NULL) + { + print_domain_rule(current, spaces + 3); + current = (struct domain_rule *)current->node.next; + } + } + else + { + printf(" {\n"); + } + print_tab(spaces); + printf("}\n"); +} + +static void print_governance_parser_result(struct governance_parser *parser) +{ + assert(parser); + assert(parser->dds); + assert(parser->dds->domain_access_rules); + printf("-----------------------------------------------\n"); + print_domain_access_rules(parser->dds->domain_access_rules, 0); + printf("-----------------------------------------------\n"); +} + +static void print_topic(struct string_value *topic, int spaces) +{ + if (topic) + { + print_string_value(topic, "topic", spaces); + print_topic((struct string_value *)topic->node.next, spaces); + } +} + +static void print_topics(struct topics *topics, int spaces) +{ + if (topics) + { + print_tab(spaces); + printf("topics {\n"); + print_topic(topics->topic, spaces + 3); + print_tab(spaces); + printf("}\n"); + } +} + +static void print_partition(struct string_value *partition, int spaces) +{ + if (partition) + { + print_string_value(partition, "partition", spaces); + print_partition((struct string_value *)partition->node.next, spaces); + } +} + +static void print_partitions(struct partitions *partitions, int spaces) +{ + if (partitions) + { + print_tab(spaces); + printf("partitions {\n"); + print_partition(partitions->partition, spaces + 3); + print_tab(spaces); + printf("}\n"); + } +} + +static void print_criteria(struct criteria *criteria, int spaces) +{ + if (criteria) + { + struct criteria *current = criteria; + while (current != NULL) + { + print_tab(spaces); + if (current->criteria_type == SUBSCRIBE_CRITERIA) + printf("subscribe {\n"); + else if (current->criteria_type == PUBLISH_CRITERIA) + printf("publish {\n"); + else + assert(0); + print_topics(current->topics, spaces + 3); + print_partitions(current->partitions, spaces + 3); + print_tab(spaces); + printf("}\n"); + current = (struct criteria *)current->node.next; + } + } +} + +static void print_allow_deny_rule(struct allow_deny_rule *allow_deny_rule, int spaces) +{ + if (allow_deny_rule) + { + struct allow_deny_rule *current = allow_deny_rule; + while (current != NULL) + { + print_tab(spaces); + if (current->rule_type == ALLOW_RULE) + printf("allow_rule {\n"); + else if (current->rule_type == DENY_RULE) + printf("deny_rule {\n"); + else + assert(0); + print_domains(current->domains, spaces + 3); + print_criteria(current->criteria, spaces + 3); + print_tab(spaces); + printf("}\n"); + current = (struct allow_deny_rule *)current->node.next; + } + } +} + +static void print_permissions(struct permissions *permissions, int spaces) +{ + struct grant *current = permissions->grant; + print_tab(spaces); + printf("permissions {\n"); + while (current != NULL) + { + print_tab(spaces + 3); + printf("grant {\n"); + print_tab(spaces + 6); + printf("name: %s\n", current->name); + print_string_value(current->subject_name, "subject_name", spaces + 6); + print_string_value(current->validity->not_before, "validity_not_before", spaces + 6); + print_string_value(current->validity->not_after, "validity_not_after", spaces + 6); + print_allow_deny_rule(current->allow_deny_rule, spaces + 6); + print_string_value(current->default_action, "default", spaces + 6); + current = (struct grant *)current->node.next; + print_tab(spaces + 3); + printf("}\n"); + } + print_tab(spaces); + printf("}\n"); +} + +static void print_permissions_parser_result(struct permissions_parser *parser) +{ + assert(parser); + assert(parser->dds); + assert(parser->dds->permissions); + printf("-----------------------------------------------\n"); + print_permissions(parser->dds->permissions, 0); + printf("-----------------------------------------------\n"); +} + +#endif /* DEBUG_PARSER */ + +static struct element *new_element(element_kind kind, struct element *parent, size_t size) +{ + struct element *e = ddsrt_malloc(size); + memset(e, 0, size); + e->parent = parent; + e->kind = kind; + e->next = NULL; + return e; +} + +#define PREPARE_NODE(element_type, element_kind, element_name, parent_type, parent_kind, current) \ + { \ + xml_##parent_type *P = (xml_##parent_type *)current; \ + if (!current || current->kind != ELEMENT_KIND_##parent_kind) \ + { \ + return -1; \ + } \ + current = new_element(ELEMENT_KIND_##element_kind, current, sizeof(xml_##element_type)); \ + P->element_name = (xml_##element_type *)current; \ + } + +#define PREPARE_NODE_WITH_LIST(element_type, element_kind, element_name, parent_type, parent_kind, current) \ + { \ + xml_##parent_type *P = (xml_##parent_type *)current; \ + xml_element *tail; \ + if (!current || current->kind != ELEMENT_KIND_##parent_kind) \ + { \ + return -1; \ + } \ + tail = (xml_element *)P->element_name; \ + current = new_element(ELEMENT_KIND_##element_kind, current, sizeof(xml_##element_type)); \ + if (!P->element_name) \ + { \ + P->element_name = (xml_##element_type *)current; \ + } \ + else \ + { \ + while (tail->next != NULL) \ + { \ + tail = tail->next; \ + } \ + tail->next = current; \ + tail->next->next = NULL; \ + } \ + } + +static void validate_domains(const struct domain_id_set *domains_set, DDS_Security_SecurityException *ex) +{ + const struct domain_id_set *domain = domains_set; + if (!domains_set) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found domain set in Governance file without domain ids."); + return; + } + while (domain != NULL && ex->code == 0) + { + if (!domain->min) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found domain range in Governance file without minimum value."); + else if (!domain->max) + ; /* The max isn't set with only an id (no range), so no error. */ + else if (domain->max->value < domain->min->value) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found domain range in Governance file with invalid range min(%d) max(%d).", domain->min->value, domain->max->value); + domain = (struct domain_id_set *)domain->node.next; + } +} + +static void validate_topic_rules(const struct topic_rule *topic_rule, DDS_Security_SecurityException *ex) +{ + while (topic_rule && ex->code == 0) + { + if (!topic_rule->data_protection_kind) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found topic rule in Governance file without data_protection_kind"); + else if (!topic_rule->enable_discovery_protection) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found topic rule in Governance file without enable_discovery_protection"); + else if (!topic_rule->enable_liveliness_protection) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found topic rule in Governance file without enable_liveliness_protection"); + else if (!topic_rule->enable_read_access_control) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found topic rule in Governance file without enable_read_access_control"); + else if (!topic_rule->enable_write_access_control) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found topic rule in Governance file without enable_write_access_control"); + else if (!topic_rule->metadata_protection_kind) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found topic rule in Governance file without metadata_protection_kind"); + else + topic_rule = (struct topic_rule *)topic_rule->node.next; + } +} + +static DDS_Security_boolean validate_rules(const struct domain_rule *rule, DDS_Security_SecurityException *ex) +{ + while (rule && ex->code == 0) + { + if (!rule->domains) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found rule in Governance file without domain ids."); + else if (!rule->allow_unauthenticated_participants) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found rule in Governance file without allow_unauthenticated_participants."); + else if (!rule->enable_join_access_control) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found rule in Governance file without enable_join_access_control."); + else if (!rule->rtps_protection_kind) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found rule in Governance file without rtps_protection_kind."); + else if (!rule->discovery_protection_kind) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found rule in Governance file without discovery_protection_kind."); + else if (!rule->liveliness_protection_kind) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found rule in Governance file without liveliness_protection_kind."); + else + { + /* Last but not least, check the domain ids (ex is set when there's a failure) */ + validate_domains(rule->domains->domain_id_set, ex); + if (!rule->topic_access_rules && rule->topic_access_rules->topic_rule) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found rule in Governance file without topic_access_rules"); + else + { + validate_topic_rules(rule->topic_access_rules->topic_rule, ex); + rule = (struct domain_rule *)rule->node.next; + } + } + } + return (ex->code == 0); +} + +static int validate_permissions_tree(const struct grant *grant, DDS_Security_SecurityException *ex) +{ + while (grant && (ex->code == 0)) + { + xml_allow_deny_rule *allow_deny_rule; + if (!grant->subject_name || !grant->subject_name->value) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_PARSE_PERMISSIONS_CODE, 0, "Found tree in Permissions file without subject name."); + else if (!grant->validity) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_PARSE_PERMISSIONS_CODE, 0, "Found tree in Permissions file without Validity."); + else if (!grant->validity->not_after || !grant->validity->not_after->value) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_PARSE_PERMISSIONS_CODE, 0, "Found tree in Permissions file without Validity/not_after."); + else if (!grant->validity->not_before || !grant->validity->not_before->value) + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_PARSE_PERMISSIONS_CODE, 0, "Found tree in Permissions file without Validity/not_before."); + else + { + /*validate partitions*/ + allow_deny_rule = grant->allow_deny_rule; + while (allow_deny_rule) + { + xml_criteria *criteria = allow_deny_rule->criteria; + while (criteria) + { + /* set to default partition, if there is no partition specifien in the XML. (DDS Security SPEC 9.4.1.3.2.3.1.4)*/ + if (criteria->partitions == NULL) + { + xml_element *criteria_element = &(criteria->node); + xml_element *partitions_element; + PREPARE_NODE(partitions, PARTITIONS, partitions, criteria, CRITERIA, criteria_element) + assert(criteria->partitions); + partitions_element = &(criteria->partitions->node); + PREPARE_NODE_WITH_LIST(string_value, STRING_VALUE, partition, partitions, PARTITIONS, partitions_element) + assert(criteria->partitions->partition); + criteria->partitions->partition->value = ddsrt_strdup(""); + } + criteria = (xml_criteria *)criteria->node.next; + } + allow_deny_rule = (xml_allow_deny_rule *)allow_deny_rule->node.next; + } + } + grant = (struct grant *)grant->node.next; + } + return (ex->code == 0); +} + +static int to_protection_kind(const char *kindStr, DDS_Security_ProtectionKind *kindEnum) +{ + if (strcmp(kindStr, "ENCRYPT_WITH_ORIGIN_AUTHENTICATION") == 0) + *kindEnum = DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION; + else if (strcmp(kindStr, "SIGN_WITH_ORIGIN_AUTHENTICATION") == 0) + *kindEnum = DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION; + else if (strcmp(kindStr, "ENCRYPT") == 0) + *kindEnum = DDS_SECURITY_PROTECTION_KIND_ENCRYPT; + else if (strcmp(kindStr, "SIGN") == 0) + *kindEnum = DDS_SECURITY_PROTECTION_KIND_SIGN; + else if (strcmp(kindStr, "NONE") == 0) + *kindEnum = DDS_SECURITY_PROTECTION_KIND_NONE; + else + return -1; + return 0; +} + +static int to_basic_protection_kind(const char *kindStr, DDS_Security_BasicProtectionKind *kindEnum) +{ + if (strcmp(kindStr, "ENCRYPT") == 0) + *kindEnum = DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT; + else if (strcmp(kindStr, "SIGN") == 0) + *kindEnum = DDS_SECURITY_BASICPROTECTION_KIND_SIGN; + else if (strcmp(kindStr, "NONE") == 0) + *kindEnum = DDS_SECURITY_BASICPROTECTION_KIND_NONE; + else + return -1; + return 0; +} + +static int governance_element_open_cb(void *varg, uintptr_t parentinfo, uintptr_t *eleminfo, const char *name, int line) +{ + governance_parser *parser = (governance_parser *)varg; + DDS_Security_SecurityException ex; + memset(&ex, 0, sizeof(DDS_Security_SecurityException)); + DDSRT_UNUSED_ARG(parentinfo); + DDSRT_UNUSED_ARG(eleminfo); + DDSRT_UNUSED_ARG(line); + if (ddsrt_strcasecmp(name, "dds") == 0) + { + /* This should be the first element. */ + if (parser->current || parser->dds) + return -1; + parser->current = new_element(ELEMENT_KIND_DDS, NULL, sizeof(struct governance_dds)); + parser->dds = (struct governance_dds *)parser->current; + } + else if (ddsrt_strcasecmp(name, "domain_access_rules") == 0) + PREPARE_NODE(domain_access_rules, DOMAIN_ACCESS_RULES, domain_access_rules, governance_dds, DDS, parser->current) + else if (ddsrt_strcasecmp(name, "domain_rule") == 0) + PREPARE_NODE_WITH_LIST(domain_rule, DOMAIN_RULE, domain_rule, domain_access_rules, DOMAIN_ACCESS_RULES, parser->current) + else if (ddsrt_strcasecmp(name, "domains") == 0) + PREPARE_NODE(domains, DOMAINS, domains, domain_rule, DOMAIN_RULE, parser->current) + else if (ddsrt_strcasecmp(name, "id") == 0) + { + xml_domains *domains = (xml_domains *)parser->current; + xml_domain_id_set *tail; + if (!parser->current || parser->current->kind != ELEMENT_KIND_DOMAINS) + return -1; + tail = domains->domain_id_set; + parser->current = new_element(ELEMENT_KIND_DOMAIN_VALUE, parser->current, sizeof(xml_integer_value)); + if (!tail) + { + domains->domain_id_set = (xml_domain_id_set *)new_element(ELEMENT_KIND_DOMAIN_ID_SET, parser->current, sizeof(xml_domain_id_set)); + tail = domains->domain_id_set; + } + else + { + while (tail->node.next != NULL) + tail = (xml_domain_id_set *)tail->node.next; + tail->node.next = new_element(ELEMENT_KIND_DOMAIN_ID_SET, parser->current, sizeof(xml_domain_id_set)); + tail = (xml_domain_id_set *)tail->node.next; + } + tail->min = (xml_integer_value *)parser->current; + tail->max = NULL; + } + else if (ddsrt_strcasecmp(name, "id_range") == 0) + PREPARE_NODE_WITH_LIST(domain_id_set, DOMAIN_ID_SET, domain_id_set, domains, DOMAINS, parser->current) + else if (ddsrt_strcasecmp(name, "min") == 0) + PREPARE_NODE(integer_value, DOMAIN_VALUE, min, domain_id_set, DOMAIN_ID_SET, parser->current) + else if (ddsrt_strcasecmp(name, "max") == 0) + PREPARE_NODE(integer_value, DOMAIN_VALUE, max, domain_id_set, DOMAIN_ID_SET, parser->current) + else if (ddsrt_strcasecmp(name, "allow_unauthenticated_participants") == 0) + PREPARE_NODE(boolean_value, BOOLEAN_VALUE, allow_unauthenticated_participants, domain_rule, DOMAIN_RULE, parser->current) + else if (ddsrt_strcasecmp(name, "enable_join_access_control") == 0) + PREPARE_NODE(boolean_value, BOOLEAN_VALUE, enable_join_access_control, domain_rule, DOMAIN_RULE, parser->current) + else if (ddsrt_strcasecmp(name, "rtps_protection_kind") == 0) + PREPARE_NODE(protection_kind_value, PROTECTION_KIND_VALUE, rtps_protection_kind, domain_rule, DOMAIN_RULE, parser->current) + else if (ddsrt_strcasecmp(name, "discovery_protection_kind") == 0) + PREPARE_NODE(protection_kind_value, PROTECTION_KIND_VALUE, discovery_protection_kind, domain_rule, DOMAIN_RULE, parser->current) + else if (ddsrt_strcasecmp(name, "liveliness_protection_kind") == 0) + PREPARE_NODE(protection_kind_value, PROTECTION_KIND_VALUE, liveliness_protection_kind, domain_rule, DOMAIN_RULE, parser->current) + else if (ddsrt_strcasecmp(name, "topic_access_rules") == 0) + PREPARE_NODE(topic_access_rules, TOPIC_ACCESS_RULES, topic_access_rules, domain_rule, DOMAIN_RULE, parser->current) + else if (ddsrt_strcasecmp(name, "topic_rule") == 0) + PREPARE_NODE_WITH_LIST(topic_rule, TOPIC_RULE, topic_rule, topic_access_rules, TOPIC_ACCESS_RULES, parser->current) + else if (ddsrt_strcasecmp(name, "enable_read_access_control") == 0) + PREPARE_NODE(boolean_value, BOOLEAN_VALUE, enable_read_access_control, topic_rule, TOPIC_RULE, parser->current) + else if (ddsrt_strcasecmp(name, "enable_write_access_control") == 0) + PREPARE_NODE(boolean_value, BOOLEAN_VALUE, enable_write_access_control, topic_rule, TOPIC_RULE, parser->current) + else if (ddsrt_strcasecmp(name, "metadata_protection_kind") == 0) + PREPARE_NODE(protection_kind_value, PROTECTION_KIND_VALUE, metadata_protection_kind, topic_rule, TOPIC_RULE, parser->current) + else if (ddsrt_strcasecmp(name, "data_protection_kind") == 0) + PREPARE_NODE(basicprotection_kind_value, BASICPROTECTION_KIND_VALUE, data_protection_kind, topic_rule, TOPIC_RULE, parser->current) + else if (ddsrt_strcasecmp(name, "enable_liveliness_protection") == 0) + PREPARE_NODE(boolean_value, BOOLEAN_VALUE, enable_liveliness_protection, topic_rule, TOPIC_RULE, parser->current) + else if (ddsrt_strcasecmp(name, "enable_discovery_protection") == 0) + PREPARE_NODE(boolean_value, BOOLEAN_VALUE, enable_discovery_protection, topic_rule, TOPIC_RULE, parser->current) + else if (ddsrt_strcasecmp(name, "topic_expression") == 0) + { + /* Current should be topic_rule. */ + struct topic_rule *topicRule = (struct topic_rule *)parser->current; + if (!parser->current || parser->current->kind != ELEMENT_KIND_TOPIC_RULE) + return -1; + parser->current = new_element(ELEMENT_KIND_STRING_VALUE, parser->current, sizeof(struct string_value)); + topicRule->topic_expression = (struct string_value *)parser->current; + } + else + { + printf("Unknown XML element: %s\n", name); + return -1; + } + + return 0; +} + +/* The function that is called on each attribute captured in XML. + * Only the following attributes will be handled: + * - name : the name of an element or attribute + */ +static int governance_element_attr_cb(void *varg, uintptr_t eleminfo, const char *name, const char *value, int line) +{ + /* There is no attribute in that XML */ + DDSRT_UNUSED_ARG(eleminfo); + DDSRT_UNUSED_ARG(varg); + DDSRT_UNUSED_ARG(value); + DDSRT_UNUSED_ARG(line); + + if (ddsrt_strcasecmp(name, "xmlns:xsi") == 0 || ddsrt_strcasecmp(name, "xsi:noNamespaceSchemaLocation") == 0) + return 0; + return -1; +} + +static bool str_to_intvalue(const char *image, int32_t *value) +{ + char *endptr; + long long l; + if (ddsrt_strtoll(image, &endptr, 0, &l) != DDS_RETCODE_OK) + return false; + *value = (int32_t)l; + if (*endptr != '\0') + return false; + return true; +} + +/* The function that is called on each data item captured in XML. + * - data: the string value between the element tags + */ +static int governance_element_data_cb(void *varg, uintptr_t eleminfo, const char *data, int line) +{ + struct governance_parser *parser = (struct governance_parser *)varg; + DDSRT_UNUSED_ARG(eleminfo); + DDSRT_UNUSED_ARG(line); + if (!parser || !parser->current) + return -1; + if (parser->current->kind == ELEMENT_KIND_STRING_VALUE) + { + struct string_value *value = (struct string_value *)parser->current; + value->value = ddsrt_strdup(data); + } + else if (parser->current->kind == ELEMENT_KIND_DOMAIN_VALUE) + { + struct integer_value *value = (struct integer_value *)parser->current; + if (str_to_intvalue(data, &value->value)) + { + if (value->value < 0 || value->value > 230) + return -1; + } + else + { + return -1; + } + } + else if (parser->current->kind == ELEMENT_KIND_BOOLEAN_VALUE) + { + struct boolean_value *value = (struct boolean_value *)parser->current; + if (ddsrt_strcasecmp("true", data) == 0 || strcmp("1", data) == 0) + value->value = true; + else if (ddsrt_strcasecmp("false", data) == 0 || strcmp("0", data) == 0) + value->value = false; + else + return -1; + } + else if (parser->current->kind == ELEMENT_KIND_PROTECTION_KIND_VALUE) + { + struct protection_kind_value *value = (struct protection_kind_value *)parser->current; + if (to_protection_kind(data, &(value->value)) != 0) + return -1; + } + else if (parser->current->kind == ELEMENT_KIND_BASICPROTECTION_KIND_VALUE) + { + struct basicprotection_kind_value *value = (struct basicprotection_kind_value *)parser->current; + if (to_basic_protection_kind(data, &(value->value)) != 0) + return -1; + } + else + { + return -1; + } + + return 0; +} + +static int governance_element_close_cb(void *varg, uintptr_t eleminfo, int line) +{ + struct governance_parser *parser = (struct governance_parser *)varg; + DDSRT_UNUSED_ARG(eleminfo); + DDSRT_UNUSED_ARG(line); + if (!parser->current) + return -1; + parser->current = parser->current->parent; + return 0; +} + +static void governance_error_cb(void *varg, const char *msg, int line) +{ + DDSRT_UNUSED_ARG(varg); + printf("Failed to parse configuration file: error %d - %s\n", line, msg); +} + +static void free_stringvalue(struct string_value *str) +{ + if (str) + { + ddsrt_free(str->value); + ddsrt_free(str); + } +} + +static void free_domainid_set(struct domain_id_set *dis) +{ + if (dis) + { + if (dis->node.next) + { + free_domainid_set((struct domain_id_set *)dis->node.next); + } + ddsrt_free(dis->min); + ddsrt_free(dis->max); + ddsrt_free(dis); + } +} + +static void free_domains(struct domains *domains) +{ + if (domains) + { + free_domainid_set(domains->domain_id_set); + ddsrt_free(domains); + } +} + +static void free_topic_rule(struct topic_rule *rule) +{ + if (rule) + { + if (rule->node.next) + free_topic_rule((struct topic_rule *)rule->node.next); + free_stringvalue(rule->topic_expression); + ddsrt_free(rule->enable_discovery_protection); + ddsrt_free(rule->enable_liveliness_protection); + ddsrt_free(rule->enable_read_access_control); + ddsrt_free(rule->enable_write_access_control); + ddsrt_free(rule->metadata_protection_kind); + ddsrt_free(rule->data_protection_kind); + ddsrt_free(rule); + } +} + +static void free_topic_access_rules(struct topic_access_rules *tar) +{ + if (tar) + { + struct topic_rule *current = tar->topic_rule; + free_topic_rule(current); + } + ddsrt_free(tar); +} + +static void free_domain_rule(struct domain_rule *rule) +{ + if (rule) + { + if (rule->node.next) + free_domain_rule((struct domain_rule *)rule->node.next); + free_domains(rule->domains); + ddsrt_free(rule->allow_unauthenticated_participants); + ddsrt_free(rule->enable_join_access_control); + ddsrt_free(rule->rtps_protection_kind); + ddsrt_free(rule->discovery_protection_kind); + ddsrt_free(rule->liveliness_protection_kind); + free_topic_access_rules(rule->topic_access_rules); + ddsrt_free(rule); + } +} + +static void free_domain_access_rules(struct domain_access_rules *dar) +{ + if (dar) + { + free_domain_rule(dar->domain_rule); + ddsrt_free(dar); + } +} + +bool ac_parse_governance_xml(const char *xml, struct governance_parser **governance_tree, DDS_Security_SecurityException *ex) +{ + struct governance_parser *parser = NULL; + struct ddsrt_xmlp_state *st = NULL; + if (xml) + { + struct ddsrt_xmlp_callbacks cb; + cb.elem_open = governance_element_open_cb; + cb.elem_data = governance_element_data_cb; + cb.elem_close = governance_element_close_cb; + cb.attr = governance_element_attr_cb; + cb.error = governance_error_cb; + parser = ddsrt_malloc(sizeof(struct governance_parser)); + parser->current = NULL; + parser->dds = NULL; + st = ddsrt_xmlp_new_string(xml, parser, &cb); + if (ddsrt_xmlp_parse(st) != 0) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_PARSE_GOVERNANCE_CODE, 0, DDS_SECURITY_ERR_CAN_NOT_PARSE_GOVERNANCE_MESSAGE); + goto err_xml_parsing; + } +#if DEBUG_PARSER + print_governance_parser_result(parser); +#endif + if ((parser->dds != NULL) && (parser->dds->domain_access_rules != NULL) && (parser->dds->domain_access_rules->domain_rule != NULL)) + { + if (!validate_rules(parser->dds->domain_access_rules->domain_rule, ex)) + goto err_rules_validation; + } + else + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_PARSE_GOVERNANCE_CODE, 0, DDS_SECURITY_ERR_CAN_NOT_PARSE_GOVERNANCE_MESSAGE); + goto err_parser_content; + } + *governance_tree = parser; + } + else + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_PARSE_GOVERNANCE_CODE, 0, DDS_SECURITY_ERR_CAN_NOT_PARSE_GOVERNANCE_MESSAGE); + goto err_xml; + } + ddsrt_xmlp_free(st); + return true; + +err_parser_content: +err_rules_validation: +err_xml_parsing: + ddsrt_xmlp_free(st); + ac_return_governance_tree(parser); +err_xml: + return false; +} + +void ac_return_governance_tree(struct governance_parser *parser) +{ + if (parser) + { + if (parser->dds) + { + free_domain_access_rules(parser->dds->domain_access_rules); + ddsrt_free(parser->dds); + } + ddsrt_free(parser); + } +} + +/* Permissions Callback functions */ + +static int permissions_element_open_cb(void *varg, uintptr_t parentinfo, uintptr_t *eleminfo, const char *name, int line) +{ + permissions_parser *parser = (permissions_parser *)varg; + DDS_Security_SecurityException ex; + memset(&ex, 0, sizeof(DDS_Security_SecurityException)); + DDSRT_UNUSED_ARG(parentinfo); + DDSRT_UNUSED_ARG(eleminfo); + DDSRT_UNUSED_ARG(line); + + /*it may be a valid element under an ignored element */ + if (parser->current && parser->current->kind == ELEMENT_KIND_IGNORED) + parser->current = new_element(ELEMENT_KIND_IGNORED, parser->current, sizeof(struct element)); + else if (ddsrt_strcasecmp(name, "dds") == 0) + { + /* This should be the first element. */ + if (parser->current || parser->dds) + return -1; + parser->current = new_element(ELEMENT_KIND_DDS, NULL, sizeof(struct permissions_dds)); + parser->dds = (struct permissions_dds *)parser->current; + } + else if (ddsrt_strcasecmp(name, "permissions") == 0) + PREPARE_NODE(permissions, PERMISSIONS, permissions, permissions_dds, DDS, parser->current) + else if (ddsrt_strcasecmp(name, "grant") == 0) + PREPARE_NODE_WITH_LIST(grant, GRANT, grant, permissions, PERMISSIONS, parser->current) + else if (ddsrt_strcasecmp(name, "domains") == 0) + PREPARE_NODE(domains, DOMAINS, domains, allow_deny_rule, ALLOW_DENY_RULE, parser->current) + else if (ddsrt_strcasecmp(name, "id") == 0) + { + xml_domains *domains = (xml_domains *)parser->current; + xml_domain_id_set *tail; + if (!parser->current || parser->current->kind != ELEMENT_KIND_DOMAINS) + return -1; + tail = domains->domain_id_set; + parser->current = new_element(ELEMENT_KIND_DOMAIN_VALUE, parser->current, sizeof(xml_integer_value)); + if (!tail) + { + domains->domain_id_set = (xml_domain_id_set *)new_element(ELEMENT_KIND_DOMAIN_ID_SET, parser->current, sizeof(xml_domain_id_set)); + tail = domains->domain_id_set; + } + else + { + while (tail->node.next != NULL) + tail = (xml_domain_id_set *)tail->node.next; + tail->node.next = new_element(ELEMENT_KIND_DOMAIN_ID_SET, parser->current, sizeof(xml_domain_id_set)); + tail = (xml_domain_id_set *)tail->node.next; + } + tail->min = (xml_integer_value *)parser->current; + tail->max = NULL; + } + else if (ddsrt_strcasecmp(name, "id_range") == 0) + PREPARE_NODE_WITH_LIST(domain_id_set, DOMAIN_ID_SET, domain_id_set, domains, DOMAINS, parser->current) + else if (ddsrt_strcasecmp(name, "min") == 0) + PREPARE_NODE(integer_value, DOMAIN_VALUE, min, domain_id_set, DOMAIN_ID_SET, parser->current) + else if (ddsrt_strcasecmp(name, "max") == 0) + PREPARE_NODE(integer_value, DOMAIN_VALUE, max, domain_id_set, DOMAIN_ID_SET, parser->current) + else if (ddsrt_strcasecmp(name, "subject_name") == 0) + PREPARE_NODE(string_value, STRING_VALUE, subject_name, grant, GRANT, parser->current) + else if (ddsrt_strcasecmp(name, "validity") == 0) + PREPARE_NODE(validity, VALIDITY, validity, grant, GRANT, parser->current) + else if (ddsrt_strcasecmp(name, "not_before") == 0) + PREPARE_NODE(string_value, STRING_VALUE, not_before, validity, VALIDITY, parser->current) + else if (ddsrt_strcasecmp(name, "not_after") == 0) + PREPARE_NODE(string_value, STRING_VALUE, not_after, validity, VALIDITY, parser->current) + else if (ddsrt_strcasecmp(name, "allow_rule") == 0) + { + PREPARE_NODE_WITH_LIST(allow_deny_rule, ALLOW_DENY_RULE, allow_deny_rule, grant, GRANT, parser->current) + ((xml_allow_deny_rule *)parser->current)->rule_type = ALLOW_RULE; + } + else if (ddsrt_strcasecmp(name, "deny_rule") == 0) + { + PREPARE_NODE_WITH_LIST(allow_deny_rule, ALLOW_DENY_RULE, allow_deny_rule, grant, GRANT, parser->current) + ((xml_allow_deny_rule *)parser->current)->rule_type = DENY_RULE; + } + else if (ddsrt_strcasecmp(name, "subscribe") == 0) + { + PREPARE_NODE_WITH_LIST(criteria, CRITERIA, criteria, allow_deny_rule, ALLOW_DENY_RULE, parser->current) + ((xml_criteria *)parser->current)->criteria_type = SUBSCRIBE_CRITERIA; + } + else if (ddsrt_strcasecmp(name, "publish") == 0) + { + PREPARE_NODE_WITH_LIST(criteria, CRITERIA, criteria, allow_deny_rule, ALLOW_DENY_RULE, parser->current) + ((xml_criteria *)parser->current)->criteria_type = PUBLISH_CRITERIA; + } + else if (ddsrt_strcasecmp(name, "topics") == 0) + PREPARE_NODE(topics, TOPICS, topics, criteria, CRITERIA, parser->current) + else if (ddsrt_strcasecmp(name, "topic") == 0) + PREPARE_NODE_WITH_LIST(string_value, STRING_VALUE, topic, topics, TOPICS, parser->current) + else if (ddsrt_strcasecmp(name, "partitions") == 0) + PREPARE_NODE(partitions, PARTITIONS, partitions, criteria, CRITERIA, parser->current) + else if (ddsrt_strcasecmp(name, "partition") == 0) + PREPARE_NODE_WITH_LIST(string_value, STRING_VALUE, partition, partitions, PARTITIONS, parser->current) + else if (ddsrt_strcasecmp(name, "default") == 0) + PREPARE_NODE(string_value, STRING_VALUE, default_action, grant, GRANT, parser->current) + else if (ddsrt_strcasecmp(name, "relay") == 0 || + ddsrt_strcasecmp(name, "value") == 0 || + ddsrt_strcasecmp(name, "name") == 0 || + ddsrt_strcasecmp(name, "tag") == 0 || + ddsrt_strcasecmp(name, "data_tags") == 0) + { + parser->current = new_element(ELEMENT_KIND_IGNORED, parser->current, sizeof(struct element)); + /*if this is the first element in the IGNORED branch, then give warning for the user*/ + if (parser->current->parent->kind != ELEMENT_KIND_IGNORED) + printf("Warning: Unsupported element \"%s\" has been ignored in permissions file.\n", name); + } + else + { + printf("Unknown XML element: %s\n", name); + return -1; + } + + return 0; +} + +/* The function that is called on each attribute captured in XML. + * Only the following attributes will be handled: + * - name : the name of an element or attribute + */ +static int permissions_element_attr_cb(void *varg, uintptr_t eleminfo, const char *name, const char *value, int line) +{ + struct permissions_parser *parser = (struct permissions_parser *)varg; + DDSRT_UNUSED_ARG(eleminfo); + DDSRT_UNUSED_ARG(line); + if (ddsrt_strcasecmp(name, "xmlns:xsi") == 0 || ddsrt_strcasecmp(name, "xsi:noNamespaceSchemaLocation") == 0) + return 0; + if (strcmp(name, "name") == 0) + { + /* Parent should be grants. */ + struct grant *grant = (struct grant *)parser->current; + if (!parser->current || parser->current->kind != ELEMENT_KIND_GRANT) + return -1; + grant->name = ddsrt_strdup(value); + return 0; + } + return -1; +} + +/* The function that is called on each data item captured in XML. + * - data: the string value between the element tags */ +static int permissions_element_data_cb(void *varg, uintptr_t eleminfo, const char *data, int line) +{ + struct permissions_parser *parser = (struct permissions_parser *)varg; + DDS_Security_SecurityException ex; + memset(&ex, 0, sizeof(DDS_Security_SecurityException)); + DDSRT_UNUSED_ARG(eleminfo); + DDSRT_UNUSED_ARG(line); + if (!parser || !parser->current) + return -1; + if (parser->current->kind == ELEMENT_KIND_STRING_VALUE) + { + struct string_value *value = (struct string_value *)parser->current; + value->value = ddsrt_strdup(data); + } + else if (parser->current->kind == ELEMENT_KIND_DOMAIN_VALUE) + { + struct integer_value *value = (struct integer_value *)parser->current; + if (str_to_intvalue(data, &value->value)) + { + if (value->value < 0 || value->value > 230) + return -1; + } + else + return -1; + } + else + { + if (parser->current->kind != ELEMENT_KIND_IGNORED) + return -1; + } + return 0; +} + +static int permissions_element_close_cb(void *varg, uintptr_t eleminfo, int line) +{ + struct permissions_parser *parser = (struct permissions_parser *)varg; + struct element *parent; + DDSRT_UNUSED_ARG(eleminfo); + DDSRT_UNUSED_ARG(line); + + if (!parser->current) + return -1; + parent = parser->current->parent; + if (parser->current->kind == ELEMENT_KIND_IGNORED) + ddsrt_free(parser->current); + parser->current = parent; + return 0; +} + +static void permissions_error_cb(void *varg, const char *msg, int line) +{ + DDSRT_UNUSED_ARG(varg); + printf("Failed to parse configuration file: error %d - %s\n", line, msg); +} + +bool ac_parse_permissions_xml(const char *xml, struct permissions_parser **permissions_tree, DDS_Security_SecurityException *ex) +{ + struct permissions_parser *parser = NULL; + struct ddsrt_xmlp_state *st = NULL; + + if (xml) + { + struct ddsrt_xmlp_callbacks cb; + cb.elem_open = permissions_element_open_cb; + cb.elem_data = permissions_element_data_cb; + cb.elem_close = permissions_element_close_cb; + cb.attr = permissions_element_attr_cb; + cb.error = permissions_error_cb; + parser = ddsrt_malloc(sizeof(struct permissions_parser)); + parser->current = NULL; + parser->dds = NULL; + st = ddsrt_xmlp_new_string(xml, parser, &cb); + if (ddsrt_xmlp_parse(st) != 0) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_PARSE_PERMISSIONS_CODE, 0, DDS_SECURITY_ERR_CAN_NOT_PARSE_PERMISSIONS_MESSAGE); + goto err_xml_parsing; + } +#if DEBUG_PARSER + print_permissions_parser_result(parser); +#endif + if ((parser->dds != NULL) && (parser->dds->permissions != NULL) && (parser->dds->permissions->grant != NULL)) + { + if (!validate_permissions_tree(parser->dds->permissions->grant, ex)) + goto err_parser_content; + } + else + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_PARSE_PERMISSIONS_CODE, 0, DDS_SECURITY_ERR_CAN_NOT_PARSE_PERMISSIONS_MESSAGE); + goto err_parser_content; + } + *permissions_tree = parser; + } + else + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CAN_NOT_PARSE_PERMISSIONS_CODE, 0, DDS_SECURITY_ERR_CAN_NOT_PARSE_PERMISSIONS_MESSAGE); + goto err_xml; + } + ddsrt_xmlp_free(st); + return true; + +err_parser_content: +err_xml_parsing: + ddsrt_xmlp_free(st); + ac_return_permissions_tree(parser); +err_xml: + return false; +} + +static void free_topic(struct string_value *topic) +{ + if (topic) + { + if (topic->node.next != NULL) + free_topic((struct string_value *)topic->node.next); + free_stringvalue(topic); + } +} + +static void free_topics(struct topics *topics) +{ + if (topics) + { + free_topic(topics->topic); + ddsrt_free(topics); + } +} + +static void free_partition(struct string_value *partition) +{ + if (partition) + { + if (partition->node.next != NULL) + free_partition((struct string_value *)partition->node.next); + free_stringvalue(partition); + } +} + +static void free_partitions(struct partitions *partitions) +{ + if (partitions) + { + free_partition(partitions->partition); + ddsrt_free(partitions); + } +} + +static void free_validity(struct validity *validity) +{ + if (validity) + { + free_stringvalue(validity->not_after); + free_stringvalue(validity->not_before); + ddsrt_free(validity); + } +} + +static void free_criteria(struct criteria *criteria) +{ + if (criteria) + { + if (criteria->node.next) + free_criteria((struct criteria *)criteria->node.next); + free_partitions(criteria->partitions); + free_topics(criteria->topics); + ddsrt_free(criteria); + } +} + +static void free_allow_deny_rule(struct allow_deny_rule *rule) +{ + if (rule) + { + free_allow_deny_rule((struct allow_deny_rule *)rule->node.next); + free_domains(rule->domains); + free_criteria(rule->criteria); + ddsrt_free(rule); + } +} + +static void free_grant(struct grant *grant) +{ + if (grant) + { + if (grant->node.next) + free_grant((struct grant *)grant->node.next); + ddsrt_free(grant->name); + free_stringvalue(grant->subject_name); + free_stringvalue(grant->default_action); + free_validity(grant->validity); + free_allow_deny_rule(grant->allow_deny_rule); + ddsrt_free(grant); + } +} + +static void free_permissions(struct permissions *permissions) +{ + if (permissions) + { + free_grant(permissions->grant); + ddsrt_free(permissions); + } +} + +void ac_return_permissions_tree(struct permissions_parser *parser) +{ + if (parser) + { + if (parser->dds) + { + free_permissions(parser->dds->permissions); + ddsrt_free(parser->dds); + } + ddsrt_free(parser); + } +} diff --git a/src/security/builtin_plugins/access_control/src/access_control_parser.h b/src/security/builtin_plugins/access_control/src/access_control_parser.h new file mode 100644 index 0000000..b4ed491 --- /dev/null +++ b/src/security/builtin_plugins/access_control/src/access_control_parser.h @@ -0,0 +1,301 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef ACCESS_CONTROL_PARSER_H +#define ACCESS_CONTROL_PARSER_H + +#include "dds/ddsrt/types.h" +#include "dds/security/dds_security_api.h" + +typedef enum +{ + ELEMENT_KIND_UNDEFINED, + ELEMENT_KIND_DDS, + ELEMENT_KIND_DOMAIN_ACCESS_RULES, + ELEMENT_KIND_DOMAIN_RULE, + ELEMENT_KIND_DOMAINS, + ELEMENT_KIND_DOMAIN_ID_SET, + ELEMENT_KIND_RANGE, + ELEMENT_KIND_ALLOW_UNAUTHENTICATED_PARTICIPANTS, + ELEMENT_KIND_ENABLE_JOIN_ACCESS_CONTROL, + ELEMENT_KIND_RTPS_PROTECTION, + ELEMENT_KIND_DISCOVERY_PROTECTION, + ELEMENT_KIND_LIVELINESS_PROTECTION, + ELEMENT_KIND_TOPIC_ACCESS_RULES, + ELEMENT_KIND_TOPIC_RULE, + ELEMENT_KIND_STRING_VALUE, + ELEMENT_KIND_BOOLEAN_VALUE, + ELEMENT_KIND_DOMAIN_VALUE, + ELEMENT_KIND_PROTECTION_KIND_VALUE, + ELEMENT_KIND_BASICPROTECTION_KIND_VALUE, + ELEMENT_KIND_PERMISSIONS, + ELEMENT_KIND_GRANT, + ELEMENT_KIND_ALLOW_DENY_RULE, + ELEMENT_KIND_CRITERIA, + ELEMENT_KIND_VALIDITY, + ELEMENT_KIND_TOPICS, + ELEMENT_KIND_PARTITIONS, + ELEMENT_KIND_DEFAULT, + ELEMENT_KIND_IGNORED +} element_kind; + +typedef enum +{ + UNKNOWN_CRITERIA, + SUBSCRIBE_CRITERIA, + PUBLISH_CRITERIA +} permission_criteria_type; + +typedef enum +{ + ALLOW_RULE, + DENY_RULE +} permission_rule_type; + +typedef struct element +{ + struct element *parent; + element_kind kind; + struct element *next; /*used in case of string list usage */ +} xml_element; + +/* TODO: Change the value nodes for specific nodes for + * proper value parsing and validating. */ + +typedef struct string_value +{ + struct element node; + char *value; +} xml_string_value; + +typedef struct boolean_value +{ + struct element node; + bool value; +} xml_boolean_value; + +typedef struct integer_value +{ + struct element node; + int32_t value; +} xml_integer_value; + +typedef struct protection_kind_value +{ + struct element node; + DDS_Security_ProtectionKind value; +} xml_protection_kind_value; + +typedef struct basicprotection_kind_value +{ + struct element node; + DDS_Security_BasicProtectionKind value; +} xml_basicprotection_kind_value; + +typedef struct domain_id_set +{ + struct element node; + struct integer_value *min; + struct integer_value *max; +} xml_domain_id_set; + +typedef struct domains +{ + struct element node; + struct domain_id_set *domain_id_set; /*linked list*/ +} xml_domains; + +typedef struct topic_rule +{ + struct element node; + struct string_value *topic_expression; + struct boolean_value *enable_discovery_protection; + struct boolean_value *enable_liveliness_protection; + struct boolean_value *enable_read_access_control; + struct boolean_value *enable_write_access_control; + struct protection_kind_value *metadata_protection_kind; + struct basicprotection_kind_value *data_protection_kind; +} xml_topic_rule; + +typedef struct topic_access_rules +{ + struct element node; + struct topic_rule *topic_rule; /*linked_list*/ +} xml_topic_access_rules; + +typedef struct domain_rule +{ + struct element node; + struct domains *domains; + struct boolean_value *allow_unauthenticated_participants; + struct boolean_value *enable_join_access_control; + struct protection_kind_value *discovery_protection_kind; + struct protection_kind_value *liveliness_protection_kind; + struct protection_kind_value *rtps_protection_kind; + struct topic_access_rules *topic_access_rules; +} xml_domain_rule; + +typedef struct domain_access_rules +{ + struct element node; + struct domain_rule *domain_rule; +} xml_domain_access_rules; + +typedef struct governance_dds +{ + struct element node; + struct domain_access_rules *domain_access_rules; +} xml_governance_dds; + +typedef struct governance_parser +{ + struct governance_dds *dds; + struct element *current; +} governance_parser; + +/* permissions file specific types */ +typedef struct validity +{ + struct element node; + struct string_value *not_before; + struct string_value *not_after; +} xml_validity; + +typedef struct topics +{ + struct element node; + struct string_value *topic; +} xml_topics; + +typedef struct partitions +{ + struct element node; + struct string_value *partition; +} xml_partitions; + +typedef struct criteria +{ + struct element node; + permission_criteria_type criteria_type; + struct topics *topics; + struct partitions *partitions; +} xml_criteria; + +typedef struct allow_deny_rule +{ + struct element node; + permission_rule_type rule_type; + struct domains *domains; + struct criteria *criteria; +} xml_allow_deny_rule; + +typedef struct grant +{ + struct element node; + char *name; + struct string_value *subject_name; + struct validity *validity; + struct allow_deny_rule *allow_deny_rule; + struct string_value *default_action; +} xml_grant; + +typedef struct permissions +{ + struct element node; + struct grant *grant; +} xml_permissions; + +typedef struct permissions_dds +{ + struct element node; + struct permissions *permissions; +} xml_permissions_dds; + +typedef struct permissions_parser +{ + struct permissions_dds *dds; + struct element *current; +} permissions_parser; + +bool ac_parse_governance_xml(const char *xml, struct governance_parser **governance_tree, DDS_Security_SecurityException *ex); +bool ac_parse_permissions_xml(const char *xml, struct permissions_parser **permissions_tree, DDS_Security_SecurityException *ex); +void ac_return_governance_tree(struct governance_parser *parser); +void ac_return_permissions_tree(struct permissions_parser *parser); + +#define DDS_SECURITY_DEFAULT_GOVERNANCE " \ + \ + \ + \ + \ + \ + \ + 0 \ + 230 \ + \ + \ + \ + false \ + false \ + ENCRYPT \ + ENCRYPT \ + NONE \ + \ + \ + * \ + true \ + true \ + false \ + false \ + ENCRYPT \ + ENCRYPT \ + \ + \ + \ + \ + " + +#define DDS_SECURITY_DEFAULT_PERMISSIONS " \ + \ + \ + \ + DEFAULT_SUBJECT \ + \ + 2015-09-15T01:00:00 \ + 2115-09-15T01:00:00 \ + \ + \ + \ + \ + 0 \ + 230 \ + \ + \ + \ + \ + * \ + \ + \ + \ + \ + \ + * \ + \ + \ + \ + \ + DENY \ + \ + \ + " + +#endif /* ACCESS_CONTROL_UTILS_H */ diff --git a/src/security/builtin_plugins/access_control/src/access_control_utils.c b/src/security/builtin_plugins/access_control/src/access_control_utils.c new file mode 100644 index 0000000..6c56d9e --- /dev/null +++ b/src/security/builtin_plugins/access_control/src/access_control_utils.c @@ -0,0 +1,406 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/misc.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/time.h" +#include "dds/ddsrt/types.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/core/dds_security_utils.h" +#include "access_control_utils.h" + +#define SEQ_ERR -1 +#define SEQ_NOMATCH 0 +#define SEQ_MATCH 1 + +bool ac_X509_certificate_from_data(const char *data, int len, X509 **x509Cert, DDS_Security_SecurityException *ex) +{ + BIO *bio; + assert(data); + assert(len >= 0); + assert(x509Cert); + + /* load certificate in buffer */ + if ((bio = BIO_new_mem_buf((void *)data, len)) == NULL) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_ALLOCATION_FAILED_CODE, 0, DDS_SECURITY_ERR_ALLOCATION_FAILED_MESSAGE ": "); + return false; + } + if ((*x509Cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CERTIFICATE_CODE, 0, DDS_SECURITY_ERR_INVALID_CERTICICATE_MESSAGE ": "); + BIO_free(bio); + return false; + } + BIO_free(bio); + return true; +} + +static bool X509_certificate_from_file(const char *filename, X509 **x509Cert, DDS_Security_SecurityException *ex) +{ + DDSRT_WARNING_MSVC_OFF(4996); + FILE *fp; + assert(filename); + assert(x509Cert); + + /* Check if this is a valid file by getting its size. */ + if (ac_regular_file_size(filename) == 0) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE, 0, DDS_SECURITY_ERR_INVALID_FILE_PATH_MESSAGE, filename); + return false; + } + if ((fp = fopen(filename, "r")) == NULL) + { + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE, 0, DDS_SECURITY_ERR_INVALID_FILE_PATH_MESSAGE, filename); + return false; + } + if ((*x509Cert = PEM_read_X509(fp, NULL, NULL, NULL)) == NULL) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CERTIFICATE_CODE, 0, DDS_SECURITY_ERR_INVALID_CERTICICATE_MESSAGE ": "); + fclose(fp); + return false; + } + fclose(fp); + return true; + DDSRT_WARNING_MSVC_ON(4996); +} + +bool ac_X509_certificate_read(const char *data, X509 **x509Cert, DDS_Security_SecurityException *ex) +{ + bool result = false; + char *contents = NULL; + assert(data); + assert(x509Cert); + + switch (DDS_Security_get_conf_item_type(data, &contents)) + { + case DDS_SECURITY_CONFIG_ITEM_PREFIX_FILE: + result = X509_certificate_from_file(contents, x509Cert, ex); + break; + case DDS_SECURITY_CONFIG_ITEM_PREFIX_DATA: + result = ac_X509_certificate_from_data(contents, (int)strlen(contents), x509Cert, ex); + break; + case DDS_SECURITY_CONFIG_ITEM_PREFIX_PKCS11: + DDS_Security_Exception_set( + ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CERTIFICATE_TYPE_NOT_SUPPORTED_CODE, 0, + DDS_SECURITY_ERR_CERTIFICATE_TYPE_NOT_SUPPORTED_MESSAGE " (pkcs11)"); + break; + default: + DDS_Security_Exception_set( + ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CERTIFICATE_TYPE_NOT_SUPPORTED_CODE, 0, + DDS_SECURITY_ERR_CERTIFICATE_TYPE_NOT_SUPPORTED_MESSAGE); + break; + } + ddsrt_free(contents); + return result; +} + +char *ac_get_certificate_subject_name(X509 *cert, DDS_Security_SecurityException *ex) +{ + X509_NAME *name; + BIO *bio; + char *subject = NULL; + char *pmem; + size_t sz; + assert(cert); + if (!(bio = BIO_new(BIO_s_mem()))) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_ALLOCATION_FAILED_CODE, 0, DDS_SECURITY_ERR_ALLOCATION_FAILED_MESSAGE ": "); + goto err_bio_alloc; + } + if (!(name = X509_get_subject_name(cert))) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_SUBJECT_NAME_CODE, 0, DDS_SECURITY_ERR_INVALID_SUBJECT_NAME_MESSAGE ": "); + goto err_get_subject; + } + + /* TODO: check if this is the correct format of the subject name: check spec */ + X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253); + + sz = (size_t) BIO_get_mem_data(bio, &pmem); + subject = ddsrt_malloc(sz + 1); + + if (BIO_gets(bio, subject, (int)sz + 1) < 0) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_SUBJECT_NAME_CODE, 0, DDS_SECURITY_ERR_INVALID_SUBJECT_NAME_MESSAGE ": "); + ddsrt_free(subject); + subject = NULL; + } + BIO_free(bio); + return subject; + +err_get_subject: + BIO_free(bio); +err_bio_alloc: + return NULL; +} + +static bool PKCS7_document_from_data(const char *data, size_t len, PKCS7 **p7, BIO **bcont, DDS_Security_SecurityException *ex) +{ + BIO *bio; + assert(data); + assert(p7); + assert(bcont); + + *bcont = NULL; + assert (len < INT32_MAX); + if ((bio = BIO_new_mem_buf((void *)data, (int)len)) == NULL) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_ALLOCATION_FAILED_CODE, 0, DDS_SECURITY_ERR_ALLOCATION_FAILED_MESSAGE ": "); + return false; + } + if ((*p7 = SMIME_read_PKCS7(bio, bcont)) == NULL) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_SMIME_DOCUMENT_CODE, 0, DDS_SECURITY_ERR_INVALID_SMIME_DOCUMENT_MESSAGE ": "); + BIO_free(bio); + return false; + } + BIO_free(bio); + return true; +} + +static bool PKCS7_document_verify(PKCS7 *p7, X509 *cert, BIO *inbio, BIO **outbio, DDS_Security_SecurityException *ex) +{ + bool result = false; + X509_STORE *store = NULL; + + assert(p7); + assert(cert); + assert(inbio); + assert(outbio); + + if ((*outbio = BIO_new(BIO_s_mem())) == NULL) + DDS_Security_Exception_set_with_openssl_error(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_ALLOCATION_FAILED_CODE, 0, DDS_SECURITY_ERR_ALLOCATION_FAILED_MESSAGE ": "); + else if ((store = X509_STORE_new()) == NULL) + DDS_Security_Exception_set_with_openssl_error(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_ALLOCATION_FAILED_CODE, 0, DDS_SECURITY_ERR_ALLOCATION_FAILED_MESSAGE ": "); + else + { + X509_STORE_add_cert(store, cert); + if (PKCS7_verify(p7, NULL, store, inbio, *outbio, PKCS7_TEXT) != 1) + DDS_Security_Exception_set_with_openssl_error(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_SMIME_DOCUMENT_CODE, 0, DDS_SECURITY_ERR_INVALID_SMIME_DOCUMENT_MESSAGE ": "); + else + result = true; + } + if (store) + X509_STORE_free(store); + if (!result && *outbio) + { + BIO_free(*outbio); + *outbio = NULL; + } + return result; +} + +bool ac_PKCS7_document_check(const char *data, size_t len, X509 *cert, char **document, DDS_Security_SecurityException *ex) +{ + bool result = false; + PKCS7 *p7; + BIO *bcont, *bdoc; + char *pmem; + size_t sz; + + assert(data); + assert(cert); + assert(document); + + if (!PKCS7_document_from_data(data, len, &p7, &bcont, ex)) + goto err_read_data; + + if (!PKCS7_document_verify(p7, cert, bcont, &bdoc, ex)) + goto err_verify; + + sz = (size_t) BIO_get_mem_data(bdoc, &pmem); + *document = ddsrt_malloc(sz + 1); + memcpy(*document, pmem, sz); + (*document)[sz] = '\0'; + result = true; + BIO_free(bdoc); + +err_verify: + PKCS7_free(p7); + BIO_free(bcont); +err_read_data: + return result; +} + +static bool string_to_properties(const char *str, DDS_Security_PropertySeq *properties) +{ + char *copy = ddsrt_strdup (str), *cursor = copy, *tok; + while ((tok = ddsrt_strsep (&cursor, ",/|")) != NULL) + { + if (strlen(tok) == 0) + continue; + char *name = ddsrt_strsep (&tok, "="); + if (name == NULL || tok == NULL || properties->_length >= properties->_maximum) + { + ddsrt_free (copy); + return false; + } + properties->_buffer[properties->_length].name = ddsrt_strdup(name); + properties->_buffer[properties->_length].value = ddsrt_strdup(tok); + properties->_length++; + } + ddsrt_free (copy); + return true; +} + +bool ac_check_subjects_are_equal(const char *permissions_sn, const char *identity_sn) +{ + bool result = false; + char *copy_idsn = ddsrt_strdup (identity_sn), *cursor_idsn = copy_idsn, *tok_idsn; + DDS_Security_PropertySeq prop_pmsn; + prop_pmsn._length = 0; + prop_pmsn._maximum = 20; + prop_pmsn._buffer = ddsrt_malloc(prop_pmsn._maximum * sizeof(DDS_Security_Property_t)); + + if (!string_to_properties(permissions_sn, &prop_pmsn)) + goto check_subj_equal_failed; + + while ((tok_idsn = ddsrt_strsep (&cursor_idsn, ",/|")) != NULL) + { + char *value_pmsn; + char *name_idsn = ddsrt_strsep (&tok_idsn, "="); + if (name_idsn == NULL || tok_idsn == NULL) + goto check_subj_equal_failed; + value_pmsn = DDS_Security_Property_get_value(&prop_pmsn, name_idsn); + if (value_pmsn == NULL || strcmp(value_pmsn, value_pmsn) != 0) + { + ddsrt_free(value_pmsn); + goto check_subj_equal_failed; + } + ddsrt_free(value_pmsn); + } + result = true; + +check_subj_equal_failed: + ddsrt_free(copy_idsn); + DDS_Security_PropertySeq_deinit(&prop_pmsn); + return result; +} + +size_t ac_regular_file_size(const char *filename) +{ + if (filename) + { +#if _WIN32 + struct _stat stat_info; + if (_stat (filename, &stat_info) == 0) + if (stat_info.st_mode & _S_IFREG) + return (size_t) stat_info.st_size; +#else + struct stat stat_info; + if (stat (filename, &stat_info) == 0) + if (S_ISREG(stat_info.st_mode)) + return (size_t) stat_info.st_size; +#endif + } + return 0; +} + +static int sequencematch(const char *pat, char c, char **new_pat) +{ + char patc = *pat; + char rpatc; + const bool neg = (patc == '!'); + bool m = false; + + if (neg) + ++pat; + for (patc = *pat; patc != ']'; pat++) + { + patc = *pat; + if (patc == '\0') + return SEQ_ERR; + if (*(pat + 1) == '-') + { + rpatc = *(pat + 2); + if (rpatc == '\0' || rpatc == ']') + return SEQ_ERR; + if ((uint8_t)patc <= (uint8_t)c && (uint8_t)c <= (uint8_t)rpatc) + m = true; + pat += 2; + } + else if (patc == c) + m = true; + } + *new_pat = (char *) pat; + return (m != neg) ? SEQ_MATCH : SEQ_NOMATCH; +} + +bool ac_fnmatch(const char* pat, const char* str) +{ + char patc; + bool ret; + char *new_pat; + + assert(pat != NULL); + assert(str != NULL); + + for (;;) + { + switch (patc = *pat++) + { + case '\0': + return (*str == '\0'); + case '?': + if (*str == '\0') + return false; + ++str; + break; + case '*': + patc = *pat; + while (patc == '*') + patc = *++pat; + if (patc == '\0') + return true; + while (*str != '\0') + { + ret = ac_fnmatch(pat, str); + if (ret) + return true; + ++str; + } + return false; + break; + case '[': + if (*str == '\0') + return false; + switch (sequencematch(pat, *str, &new_pat)) + { + case SEQ_MATCH: + pat = new_pat; + ++str; + break; + case SEQ_NOMATCH: + case SEQ_ERR: + return false; + } + break; + default: /* Regular character */ + if (*str != patc) + return false; + str++; + break; + } + } +} + diff --git a/src/security/builtin_plugins/access_control/src/access_control_utils.h b/src/security/builtin_plugins/access_control/src/access_control_utils.h new file mode 100644 index 0000000..008ab21 --- /dev/null +++ b/src/security/builtin_plugins/access_control/src/access_control_utils.h @@ -0,0 +1,30 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef ACCESS_CONTROL_UTILS_H +#define ACCESS_CONTROL_UTILS_H + +#include +#include "dds/ddsrt/types.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/export.h" + +#define DDS_ACCESS_CONTROL_PLUGIN_CONTEXT "Access Control" + +bool ac_X509_certificate_read(const char *data, X509 **x509Cert, DDS_Security_SecurityException *ex); +bool ac_X509_certificate_from_data(const char *data, int len, X509 **x509Cert, DDS_Security_SecurityException *ex); +char *ac_get_certificate_subject_name(X509 *cert, DDS_Security_SecurityException *ex); +bool ac_PKCS7_document_check(const char *data, size_t len, X509 *cert, char **document, DDS_Security_SecurityException *ex); +bool ac_check_subjects_are_equal(const char *permissions_sn, const char *identity_sn); +size_t ac_regular_file_size(const char *filename); +SECURITY_EXPORT bool ac_fnmatch(const char* pattern, const char* string); + +#endif /* ACCESS_CONTROL_UTILS_H */ diff --git a/src/security/builtin_plugins/tests/CMakeLists.txt b/src/security/builtin_plugins/tests/CMakeLists.txt index d3250d0..d822524 100644 --- a/src/security/builtin_plugins/tests/CMakeLists.txt +++ b/src/security/builtin_plugins/tests/CMakeLists.txt @@ -23,6 +23,16 @@ set(security_auth_test_sources "validate_remote_identity/src/validate_remote_identity_utests.c" ) +set(security_ac_test_sources + "access_control_fnmatch/src/access_control_fnmatch_utests.c" + "get_permissions_credential_token/src/get_permissions_credential_token_utests.c" + "get_permissions_token/src/get_permissions_token_utests.c" + "get_xxx_sec_attributes/src/get_xxx_sec_attributes_utests.c" + # "listeners_access_control/src/listeners_access_control_utests.c" + "validate_local_permissions/src/validate_local_permissions_utests.c" + "validate_remote_permissions/src/validate_remote_permissions_utests.c" +) + set(security_crypto_test_sources "common/src/crypto_helper.c" "create_local_datareader_crypto_tokens/src/create_local_datareader_crypto_tokens_utests.c" @@ -48,9 +58,21 @@ set(security_crypto_test_sources "set_remote_participant_crypto_tokens/src/set_remote_participant_crypto_tokens_utests.c" ) -add_cunit_executable(cunit_security_plugins ${security_auth_test_sources} ${security_crypto_test_sources}) +add_cunit_executable(cunit_security_plugins ${security_auth_test_sources} ${security_ac_test_sources} ${security_crypto_test_sources}) +target_include_directories( + cunit_security_plugins PRIVATE + "$" + "$>" + "$>" + "$>" + "$" + "$" +) +target_link_libraries(cunit_security_plugins PRIVATE ddsc security_api) + if(OPENSSL_FOUND) - target_link_libraries(cunit_security_plugins PRIVATE ddsc dds_security_crypto) +target_link_libraries(cunit_security_plugins PRIVATE ddsc dds_security_ac) +target_link_libraries(cunit_security_plugins PRIVATE ddsc dds_security_crypto) target_link_libraries(cunit_security_plugins PRIVATE OpenSSL::SSL) else() message(FATAL_ERROR "To build with openssl support, set ENABLE_OPENSSL to ON") @@ -58,6 +80,7 @@ endif() target_include_directories( cunit_security_plugins PRIVATE + "$" "$" "$>" "$>" diff --git a/src/security/builtin_plugins/tests/access_control_fnmatch/src/access_control_fnmatch_utests.c b/src/security/builtin_plugins/tests/access_control_fnmatch/src/access_control_fnmatch_utests.c new file mode 100644 index 0000000..08568a3 --- /dev/null +++ b/src/security/builtin_plugins/tests/access_control_fnmatch/src/access_control_fnmatch_utests.c @@ -0,0 +1,67 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#include +#include +#include "CUnit/CUnit.h" +#include "CUnit/Test.h" +#include "assert.h" +#include "access_control_utils.h" + + +CU_Test(ddssec_builtin_access_control_fnmatch, basic) +{ + CU_ASSERT(ac_fnmatch("", "")); + CU_ASSERT(ac_fnmatch("abc", "abc")); + CU_ASSERT(!ac_fnmatch("abc", "ab")); + CU_ASSERT(!ac_fnmatch("", "a")); + CU_ASSERT(!ac_fnmatch("a", "")); + + CU_ASSERT(ac_fnmatch("a?", "ab")); + CU_ASSERT(ac_fnmatch("?b", "ab")); + CU_ASSERT(ac_fnmatch("a?c", "abc")); + CU_ASSERT(!ac_fnmatch("a?", "abc")); + CU_ASSERT(!ac_fnmatch("?c", "abc")); + + CU_ASSERT(ac_fnmatch("a*", "a")); + CU_ASSERT(ac_fnmatch("a*", "abc")); + CU_ASSERT(ac_fnmatch("a*c", "abc")); + CU_ASSERT(ac_fnmatch("a*c", "abbc")); + CU_ASSERT(ac_fnmatch("*c", "abc")); + CU_ASSERT(ac_fnmatch("*c", "c")); + CU_ASSERT(!ac_fnmatch("a*", "")); + CU_ASSERT(!ac_fnmatch("a*c", "bc")); + + CU_ASSERT(ac_fnmatch("[ab]", "a")); + CU_ASSERT(ac_fnmatch("[ab]", "b")); + CU_ASSERT(ac_fnmatch("a[bc]", "ab")); + CU_ASSERT(ac_fnmatch("a[bc]", "ac")); + CU_ASSERT(ac_fnmatch("a[bc]d", "abd")); + CU_ASSERT(ac_fnmatch("a[b-d]", "ab")); + CU_ASSERT(ac_fnmatch("a[b-d]", "ac")); + CU_ASSERT(ac_fnmatch("a[b-d]", "ad")); + CU_ASSERT(ac_fnmatch("a[-b]", "ab")); + CU_ASSERT(ac_fnmatch("a[!b]", "ac")); + CU_ASSERT(ac_fnmatch("a[!bc]d", "aad")); + CU_ASSERT(ac_fnmatch("a]", "a]")); + CU_ASSERT(!ac_fnmatch("[ab]", "c")); + CU_ASSERT(!ac_fnmatch("a[bc]", "ad")); + CU_ASSERT(!ac_fnmatch("a[bc]", "abc")); + CU_ASSERT(!ac_fnmatch("a[b-]", "ab")); + CU_ASSERT(!ac_fnmatch("a[-", "a")); + CU_ASSERT(!ac_fnmatch("a[", "a[")); + CU_ASSERT(!ac_fnmatch("a[-", "a[-")); + CU_ASSERT(!ac_fnmatch("a[!b]", "ab")); + CU_ASSERT(!ac_fnmatch("a[!bc]d", "abd")); + CU_ASSERT(!ac_fnmatch("a[!b-d]", "ac")); + CU_ASSERT(!ac_fnmatch("a[!-b]", "ab")); +} diff --git a/src/security/builtin_plugins/tests/get_permissions_credential_token/etc/Test_Governance_ok.p7s b/src/security/builtin_plugins/tests/get_permissions_credential_token/etc/Test_Governance_ok.p7s new file mode 100644 index 0000000..c39903f --- /dev/null +++ b/src/security/builtin_plugins/tests/get_permissions_credential_token/etc/Test_Governance_ok.p7s @@ -0,0 +1,114 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----DB94A190D9780A24156FB0E8F1E76B5F" + +This is an S/MIME signed message + +------DB94A190D9780A24156FB0E8F1E76B5F +Content-Type: text/plain + + + + + + + + + 0 + 230 + + + + + false + + + true + + + ENCRYPT + + + ENCRYPT + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + ENCRYPT + + + ENCRYPT + + + + + + +------DB94A190D9780A24156FB0E8F1E76B5F +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGSAYJKoZIhvcNAQcCoIIGOTCCBjUCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCAnswggJ3AgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggeQwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTgwOTEzMDczOTUwWjAvBgkqhkiG9w0BCQQxIgQgXv8DkvlwebXMwHDbNc0/Pc30 +gyG3xWCnwet49TRMWFsweQYJKoZIhvcNAQkPMWwwajALBglghkgBZQMEASowCwYJ +YIZIAWUDBAEWMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAOBggqhkiG9w0DAgIC +AIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwDQYJKoZI +hvcNAQEBBQAEggEANy8t0EFmv5j1n0+mMn2ut3Chu8PSJceC8gd34IiKq79uC1O3 +PbL9xgiJ2vz7QiTEEeNL2q+CG77cXOcHGUWa4nvbggr/9CqLfHEKGQxDfyXlJZfM +8l550xIXRRBOQ7ilOGLD4QJFfbf9XA4rMuRe8WEYN3FleAaYBJag1tMPg1SS6tgA +BBDM9b1kXHU319zYOk6kZFjlbwHv6XO22SEVRUpXrKudAI8hrGvwksF/+W0S/jS5 +NmYtj/1oMGlCGIaA5rs27H9CkgwrzoMQ3MsR98JlwEUSa4PEe8CClsIziOulQxsp +MicBlMWL0rzpBPVfPTE4gZ/kP7hGBDEQlRzVTA== + +------DB94A190D9780A24156FB0E8F1E76B5F-- + diff --git a/src/security/builtin_plugins/tests/get_permissions_credential_token/etc/Test_Permissions_ok.p7s b/src/security/builtin_plugins/tests/get_permissions_credential_token/etc/Test_Permissions_ok.p7s new file mode 100644 index 0000000..052075b --- /dev/null +++ b/src/security/builtin_plugins/tests/get_permissions_credential_token/etc/Test_Permissions_ok.p7s @@ -0,0 +1,85 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----6B91005B007BBA8EDE10CD1CE487DB27" + +This is an S/MIME signed message + +------6B91005B007BBA8EDE10CD1CE487DB27 +Content-Type: text/plain + + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + + + * + + + + DENY + + + + +------6B91005B007BBA8EDE10CD1CE487DB27 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgl3LfUhn9L0vG/3QRPVYptcYw +/NH5HMN99aMe9JAT+LAwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAHe9vakfXPvbpgMeqlhG +SW6Z3uVA3Yri9bgQDpJ9daIUsM0/TLBSQVs85twTMXvqUSntKbfSGehxDQ9F+yje +mOEPMIwxOqcVyc2jpqoYsUWqpwiiZyk49DHUFrOfWJUx+rKdBftZWkxD05Wkovhk +2d4hGS/65Haoho4Z0AZwcyH+F52FZMiqw7I9FKrPlhxvJfQXmhIjOKtnvWnQ+Ar7 +YYiSrBEHMCy82LF1aKzz0nkL1SYWQHuQX475qoU4LMYY1J8WsD3rSBeq4GYZrl2K +X/JcOquMYqjfJLMYZY4fsc3FgEBkKNqJz1tDZ3ir24VMl+WsbEjVK8oXe/wt4V0U +aNQ= + +------6B91005B007BBA8EDE10CD1CE487DB27-- + diff --git a/src/security/builtin_plugins/tests/get_permissions_credential_token/src/get_permissions_credential_token_utests.c b/src/security/builtin_plugins/tests/get_permissions_credential_token/src/get_permissions_credential_token_utests.c new file mode 100644 index 0000000..bed337f --- /dev/null +++ b/src/security/builtin_plugins/tests/get_permissions_credential_token/src/get_permissions_credential_token_utests.c @@ -0,0 +1,497 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include + +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/io.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/types.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/core/dds_security_utils.h" +#include "CUnit/CUnit.h" +#include "CUnit/Test.h" +#include "common/src/loader.h" +#include "config_env.h" + +static const char *PERMISSIONS_FILE_NAME = "Test_Permissions_ok.p7s"; +static const char *GOVERNANCE_FILE_NAME = "Test_Governance_ok.p7s"; + +static const char *PROPERTY_IDENTITY_CA = "dds.sec.auth.identity_ca"; +static const char *PROPERTY_PRIVATE_KEY = "dds.sec.auth.private_key"; +static const char *PROPERTY_IDENTITY_CERT = "dds.sec.auth.identity_certificate"; +static const char *PROPERTY_PERMISSIONS_CA = "dds.sec.access.permissions_ca"; +static const char *PROPERTY_PERMISSIONS = "dds.sec.access.permissions"; +static const char *PROPERTY_GOVERNANCE = "dds.sec.access.governance"; + +static const char *RELATIVE_PATH_TO_ETC_DIR = "/get_permissions_credential_token/etc/"; + +static const char *IDENTITY_CERTIFICATE = + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIEQTCCAymgAwIBAgIINpuaAAnrQZIwDQYJKoZIhvcNAQELBQAwXzELMAkGA1UE\n" + "BhMCTkwxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp\n" + "ZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAxMPQ0hBTTUwMCByb290IGNhMCAXDTE3MDIy\n" + "MjIyMjIwMFoYDzIyMjIwMjIyMjIyMjAwWjBcMQswCQYDVQQGEwJOTDETMBEGA1UE\n" + "CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk\n" + "MRUwEwYDVQQDEwxDSEFNNTAwIGNlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\n" + "ggEKAoIBAQDCpVhivH/wBIyu74rvQncnSZqKyspN6CvD1pmV9wft5PHhVt9jV79v\n" + "gSub5LADoRHAgFdv9duYgBr17Ob6uRrIY4B18CcrCjhQcC4gjx8y2jl9PeYm+qYD\n" + "3o44FYBrBq0QCnrQgKsb/qX9Z+Mw/VUiw65x68W876LEHQQoEgT4kxSuagwBoVRk\n" + "ePD6fYAKmT4XS3x+O0v+rHESTcsKF6yMadgp7h3eH1b8kJTzSx8JV9Zzq++mxjox\n" + "qhbBVP5nDze2hhSIeCkCvSrx7efkgKS4AQXa5/Z44GiAu1TfXXUqdic9rxwD0edn\n" + "ajNElnZe7sjok/0yuqvH+2hSqpNva/zpAgMBAAGjggEAMIH9MAwGA1UdDwQFAwMH\n" + "/4AwgewGA1UdJQSB5DCB4QYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDAwYI\n" + "KwYBBQUHAwQGCCsGAQUFBwMIBgorBgEEAYI3AgEVBgorBgEEAYI3AgEWBgorBgEE\n" + "AYI3CgMBBgorBgEEAYI3CgMDBgorBgEEAYI3CgMEBglghkgBhvhCBAEGCysGAQQB\n" + "gjcKAwQBBggrBgEFBQcDBQYIKwYBBQUHAwYGCCsGAQUFBwMHBggrBgEFBQgCAgYK\n" + "KwYBBAGCNxQCAgYIKwYBBQUHAwkGCCsGAQUFBwMNBggrBgEFBQcDDgYHKwYBBQID\n" + "BTANBgkqhkiG9w0BAQsFAAOCAQEAawdHy0Xw7nTK2ltp91Ion6fJ7hqYuj///zr7\n" + "Adt6uonpDh/xl3esuwcFimIJrJrHujnGkL0nLddRCikmnzuBMNDWS6yq0/Ckl/YG\n" + "yjNr44dlX24wo+MVAgkj3/8CyWDZ3a8kBg9QT3bs2SqbjmhTrXN1DRyf9S5vJysE\n" + "I7V1gTN66BeKL64hOrAlRVrEu8Ds6TWL6Q/YH+61ViZkoLTeSaPjH4nknaFr4C35\n" + "iji0JhkyfRHRRVPHFnaj25AkxOrSV64qVKoTMjDl5fji5iMGtjm6iJ7q05ml/qDl\n" + "nLotHXemZNvYhbwUmRzbt4Dls9EMH4VRbP85I94nM5TAvtHVNA==\n" + "-----END CERTIFICATE-----\n"; + +static const char *IDENTITY_CA = + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIEmTCCA4GgAwIBAgIIZ5gEIUFhO5wwDQYJKoZIhvcNAQELBQAwXzELMAkGA1UE\n" + "BhMCTkwxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp\n" + "ZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAxMPQ0hBTTUwMCByb290IGNhMCAXDTE4MDIx\n" + "MjE1MDUwMFoYDzIyMjIwMjIyMjIyMjAwWjBfMQswCQYDVQQGEwJOTDETMBEGA1UE\n" + "CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk\n" + "MRgwFgYDVQQDEw9DSEFNNTAwIHJvb3QgY2EwggEiMA0GCSqGSIb3DQEBAQUAA4IB\n" + "DwAwggEKAoIBAQC6Fa3TheL+UrdZCp9GhU/2WbneP2t/avUa3muwDttPxeI2XU9k\n" + "ZjBR95mAXme4SPXHk5+YDN319AqIje3oKhzky/ngvKH2GkoJKYxWnuDBfMEHdViz\n" + "2Q9/xso2ZvH50ukwWa0pfx2/EVV1wRxeQcRd/UVfq3KTJizG0M88mOYvGEAw3LFf\n" + "zef7k1aCuOofQmBvLukUudcYpMzfyHFp7lQqU4CcrrR5RtmfiUfrWfdGLea2iPDB\n" + "pJgN8ESOMwEHtOTEBDclYnH9L4t7CHQz+fXXS5IWFsDK9fCMQjnxDsDVeNrNzTYL\n" + "FaZrMg9S6IUQCEsQWsnq5weS8omOpVLUm9klAgMBAAGjggFVMIIBUTAMBgNVHRME\n" + "BTADAQH/MB0GA1UdDgQWBBQg2FZB/j8uWDVnJhjwXkX278znSTAfBgNVHSMEGDAW\n" + "gBQg2FZB/j8uWDVnJhjwXkX278znSTAPBgNVHQ8BAf8EBQMDB/+AMIHvBgNVHSUB\n" + "Af8EgeQwgeEGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwME\n" + "BggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYK\n" + "KwYBBAGCNwoDAwYKKwYBBAGCNwoDBAYJYIZIAYb4QgQBBgsrBgEEAYI3CgMEAQYI\n" + "KwYBBQUHAwUGCCsGAQUFBwMGBggrBgEFBQcDBwYIKwYBBQUIAgIGCisGAQQBgjcU\n" + "AgIGCCsGAQUFBwMJBggrBgEFBQcDDQYIKwYBBQUHAw4GBysGAQUCAwUwDQYJKoZI\n" + "hvcNAQELBQADggEBAKHmwejWRwGE1wf1k2rG8SNRV/neGsZ6Qfqf6co3TpR/Wi1s\n" + "iZDvSeT/rbqNBS7z34xnG88NIUwu00y78e8Mfon31ZZbK4Uo7fla9/D3ukdJqPQC\n" + "LKdbKJjR2kH+KCukY/1rghjJ8/X+t2egBit0LCOdsFCl07Sfksb9kpGUIZSFcYYm\n" + "geqhjhoNwxazzHiw+QWHC5HG9248JIizBmy1aymNWuMnPudhjHAnPcsIlqMVNq3t\n" + "Rv9ap7S8JeCxHVRPJvJeCwXWvW3dW/v3xH52Yn/fqRblN1w9Fxz5NhopKx0gj/Jd\n" + "sw2N4Fk4gaOWEolFpa0bwNw8nAx7moehZpowzfw=\n" + "-----END CERTIFICATE-----\n"; + +static const char *PRIVATE_KEY = + "data:,-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEogIBAAKCAQEAwqVYYrx/8ASMru+K70J3J0maisrKTegrw9aZlfcH7eTx4Vbf\n" + "Y1e/b4Erm+SwA6ERwIBXb/XbmIAa9ezm+rkayGOAdfAnKwo4UHAuII8fMto5fT3m\n" + "JvqmA96OOBWAawatEAp60ICrG/6l/WfjMP1VIsOucevFvO+ixB0EKBIE+JMUrmoM\n" + "AaFUZHjw+n2ACpk+F0t8fjtL/qxxEk3LChesjGnYKe4d3h9W/JCU80sfCVfWc6vv\n" + "psY6MaoWwVT+Zw83toYUiHgpAr0q8e3n5ICkuAEF2uf2eOBogLtU3111KnYnPa8c\n" + "A9HnZ2ozRJZ2Xu7I6JP9Mrqrx/toUqqTb2v86QIDAQABAoIBAC1q32DKkx+yMBFx\n" + "m32QiLUGG6VfBC2BixS7MkMnzRXZYgcuehl4FBc0kLRjfB6cqsO8LqrVN1QyMBhK\n" + "GutN3c38SbE7RChqzhEW2+yE+Mao3Nk4ZEecHLiyaYT0n25ZtHAVwep823BAzwJ+\n" + "BykbM45VEpNKbG1VjSktjBa9faNyZiZAEJEjVyla+6R8N4kHV52LbZcLjvJv3IQ2\n" + "iPYRrmMyI5C23qTni0vy7yJbAXBo3CqgSlwie9FARBWT7Puu7F4mF1O1c/SnTysw\n" + "Tm3e5FzgfHipQbnRVn0w4rDprPMKmPxMnvf/Wkw0zVgNadp1Tc1I6Yj525DEQ07i\n" + "2gIn/gECgYEA4jNnY1u2Eu7x3pAQF3dRO0x35boVtuq9iwQk7q+uaZaK4RJRr+0Y\n" + "T68S3bPnfer6SHvcxtST89Bvs/j/Ky4SOaX037UYjFh6T7OIzPl+MzO1yb+VOBT6\n" + "D6FVGEJGp8ZAITU1OfJPeTYViUeEC8tHFGoKUCk50FbB6jOf1oKtv/ECgYEA3EnB\n" + "Y7kSbJJaUuj9ciFUL/pAno86Cim3VjegK1wKgEiyDb610bhoMErovPwfVJbtcttG\n" + "eKJNuwizkRcVbj+vpjDvqqaP5eMxLl6/Nd4haPMJYzGo88Z8NJpwFRNF2KEWjOpQ\n" + "2NEvoCeRtVulCJyka2Tpljzw8cOXkxhPOe2UhHkCgYBo3entj0QO7QXm56T+LAvV\n" + "0PK45xdQEO3EuCwjGAFk5C0IgUSrqeCeeIzniZMltj1IQ1wsNbtNynEu3530t8wt\n" + "O7oVyFBUKGSz9IjUdkpClJOPr6kPMfJoMqRPtdIpz+hFPPSrI6IikKdVWHloOlp+\n" + "pVaYqTQrWT1XRY2xli3VEQKBgGySmZN6Cx+h/oywswIGdUT0VdcQhq2to+QFpJba\n" + "VX6m1cM6hMip2Ag9U3qZ1SNPBBdBBfm9HQybHE3dj713/C2wHuAAGhpXIM1W+20k\n" + "X1knuC/AsSH9aQhQOf/ZMOq1crTfZBuI9q0782/sjGmzMsKPySU4QhUWruVb7OiD\n" + "NVkZAoGAEvihW7G+8/iOE40vGHyBqUeopAAWLciTAUIEwM/Oi3BYfNWNTWF/FWNc\n" + "nMvCZPYigY8C1vO+1iT2Frtd3CIU+f01Q3fJNJoRLlEiKLNZUJRF48OKUqjKSmsi\n" + "w6pucFO40z05YW7utApj4L82rZnOS0pd1tUI1yexqvj0i4ThJfk=\n" + "-----END RSA PRIVATE KEY-----\n"; + +static const char *PERMISSIONS_CA = + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV\n" + "BAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQKDBZBRExJTksgVGVj\n" + "aG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNvbTAgFw0xODA3MzAx\n" + "MjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMCTkwxEzARBgNVBAgM\n" + "ClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4xFzAV\n" + "BgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" + "CgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blIDehV6XCxrnGXusTCD\n" + "uFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9wicp3BGSpZZax/TcO\n" + "NjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLsDFFC+a0qn2RFh37r\n" + "cWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074BRDXVivx+wVD951L\n" + "FNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiySogRWAmKhysLQudu\n" + "kHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNVHQ4EFgQURWMbWvBK\n" + "ZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJvRV1/tyc1R82k0+gw\n" + "DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ysVtvHnk2hpu9yND\n" + "LCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9XVh0rGoR/6nHzo3TI\n" + "eiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9yghhKHHqNDvSsAL0\n" + "KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbtlLX3QnwVOmaRyzyl\n" + "PiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42+OyLqcH1rKT6Xhcs\n" + "hjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb6SDB340BFmtgDHbF\n" + "HQ==\n" + "-----END CERTIFICATE-----\n"; + +static char *permissions = NULL; +static char *g_path_to_etc_dir = NULL; +static struct plugins_hdl *plugins = NULL; +static dds_security_authentication *auth = NULL; +static dds_security_access_control *access_control = NULL; + +static DDS_Security_IdentityHandle local_identity_handle = DDS_SECURITY_HANDLE_NIL; +static DDS_Security_PermissionsHandle local_permissions_handle = DDS_SECURITY_HANDLE_NIL; + +static void reset_exception(DDS_Security_SecurityException *ex) +{ + ex->code = 0; + ex->minor_code = 0; + ddsrt_free(ex->message); + ex->message = NULL; +} + +static DDS_Security_Property_t *find_property(DDS_Security_DataHolder *token, const char *name) +{ + DDS_Security_Property_t *result = NULL; + uint32_t i; + + for (i = 0; i < token->properties._length && !result; i++) + if (token->properties._buffer[i].name && (strcmp(token->properties._buffer[i].name, name) == 0)) + result = &token->properties._buffer[i]; + return result; +} + +static void dds_security_property_init(DDS_Security_PropertySeq *seq, DDS_Security_unsigned_long size) +{ + seq->_length = size; + seq->_maximum = size; + seq->_buffer = ddsrt_malloc(size * sizeof(DDS_Security_Property_t)); + memset(seq->_buffer, 0, size * sizeof(DDS_Security_Property_t)); +} + +static void dds_security_property_deinit(DDS_Security_PropertySeq *seq) +{ + uint32_t i; + for (i = 0; i < seq->_length; i++) + { + ddsrt_free(seq->_buffer[i].name); + ddsrt_free(seq->_buffer[i].value); + } + ddsrt_free(seq->_buffer); +} + +static char *read_document_from_file(const char *filename) +{ + char *document; + char *normalized; + char *name; + + /* Get proper file name. */ + ddsrt_asprintf(&name, "%s%s", g_path_to_etc_dir, filename); + normalized = DDS_Security_normalize_file(name); + ddsrt_free(name); + document = load_file_contents(normalized); + + ddsrt_free(normalized); + + return document; +} + +static void fill_participant_qos(DDS_Security_Qos *qos, const char *permission_filename, const char *governance_filename) +{ + char *permission_uri; + char *governance_uri; + + ddsrt_asprintf(&permission_uri, "file:%s%s", g_path_to_etc_dir, permission_filename); + ddsrt_asprintf(&governance_uri, "file:%s%s", g_path_to_etc_dir, governance_filename); + + memset(qos, 0, sizeof(*qos)); + dds_security_property_init(&qos->property.value, 6); + qos->property.value._buffer[0].name = ddsrt_strdup(PROPERTY_IDENTITY_CERT); + qos->property.value._buffer[0].value = ddsrt_strdup(IDENTITY_CERTIFICATE); + qos->property.value._buffer[1].name = ddsrt_strdup(PROPERTY_IDENTITY_CA); + qos->property.value._buffer[1].value = ddsrt_strdup(IDENTITY_CA); + qos->property.value._buffer[2].name = ddsrt_strdup(PROPERTY_PRIVATE_KEY); + qos->property.value._buffer[2].value = ddsrt_strdup(PRIVATE_KEY); + qos->property.value._buffer[3].name = ddsrt_strdup(PROPERTY_PERMISSIONS_CA); + qos->property.value._buffer[3].value = ddsrt_strdup(PERMISSIONS_CA); + qos->property.value._buffer[4].name = ddsrt_strdup(PROPERTY_PERMISSIONS); + qos->property.value._buffer[4].value = ddsrt_strdup(permission_uri); + qos->property.value._buffer[5].name = ddsrt_strdup(PROPERTY_GOVERNANCE); + qos->property.value._buffer[5].value = ddsrt_strdup(governance_uri); + + ddsrt_free(permission_uri); + ddsrt_free(governance_uri); +} + +static int local_permissions_init(DDS_Security_DomainId domain_id) +{ + int res = 0; + DDS_Security_ValidationResult_t result; + DDS_Security_Qos participant_qos; + DDS_Security_GUID_t local_participant_guid; + DDS_Security_GUID_t candidate_participant_guid; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_GuidPrefix_t prefix = {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb}; + DDS_Security_EntityId_t entityId = {{0xb0, 0xb1, 0xb2}, 0x1}; + + memset(&local_participant_guid, 0, sizeof(local_participant_guid)); + memcpy(&candidate_participant_guid.prefix, &prefix, sizeof(prefix)); + memcpy(&candidate_participant_guid.entityId, &entityId, sizeof(entityId)); + + fill_participant_qos(&participant_qos, PERMISSIONS_FILE_NAME, GOVERNANCE_FILE_NAME); + + result = auth->validate_local_identity( + auth, + &local_identity_handle, + &local_participant_guid, + domain_id, + &participant_qos, + &candidate_participant_guid, + &exception); + + if (result != DDS_SECURITY_VALIDATION_OK) + { + res = -1; + printf("validate_local_identity_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + + reset_exception(&exception); + + if (res == 0) + { + local_permissions_handle = access_control->validate_local_permissions( + access_control, + auth, + local_identity_handle, + domain_id, + &participant_qos, + &exception); + + if (local_permissions_handle == DDS_SECURITY_HANDLE_NIL) + { + res = -1; + printf("validate_local_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + } + + reset_exception(&exception); + + dds_security_property_deinit(&participant_qos.property.value); + + return res; +} + +static void local_permissions_clean(void) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_boolean success; + + if (local_permissions_handle != DDS_SECURITY_HANDLE_NIL) + { + success = access_control->return_permissions_handle(access_control, local_permissions_handle, &exception); + if (!success) + { + printf("return_permission_handle failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + reset_exception(&exception); + } + + if (local_identity_handle != DDS_SECURITY_HANDLE_NIL) + { + success = auth->return_identity_handle(auth, local_identity_handle, &exception); + if (!success) + { + printf("return_identity_handle failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + reset_exception(&exception); + } +} + +static void set_path_to_etc_dir(void) +{ + ddsrt_asprintf(&g_path_to_etc_dir, "%s%s", CONFIG_ENV_TESTS_DIR, RELATIVE_PATH_TO_ETC_DIR); +} + +static void suite_get_permissions_credential_token_init(void) +{ + plugins = load_plugins(&access_control, &auth, NULL /* Cryptograpy */); + CU_ASSERT_FATAL (plugins != NULL); + set_path_to_etc_dir(); + local_permissions_init(0); + permissions = read_document_from_file(PERMISSIONS_FILE_NAME); + CU_ASSERT_FATAL (permissions != NULL); +} + +static void suite_get_permissions_credential_token_fini(void) +{ + local_permissions_clean(); + unload_plugins(plugins); + ddsrt_free(g_path_to_etc_dir); + ddsrt_free(permissions); +} + +static bool validate_permissions_token(DDS_Security_PermissionsCredentialToken *token) +{ + DDS_Security_Property_t *property; + + if (!token->class_id || strcmp(token->class_id, "DDS:Access:PermissionsCredential") != 0) + { + CU_FAIL("PermissionsCredentialToken incorrect class_id"); + return false; + } + + property = find_property(token, "dds.perm.cert"); + if (property == NULL) + { + CU_FAIL("PermissionsCredentialToken property 'dds.perm.cert' not found"); + return false; + } + if (property->value == NULL) + { + CU_FAIL("PermissionsCredentialToken property 'dds.perm.cert' does not have a value"); + return false; + } + if (strcmp(property->value, permissions) != 0) + { + CU_FAIL("PermissionsCredentialToken property 'dds.perm.cert' content does not match the permissions file"); + return false; + } + + return true; +} + +CU_Test(ddssec_builtin_get_permissions_credential_token, happy_day, .init = suite_get_permissions_credential_token_init, .fini = suite_get_permissions_credential_token_fini) +{ + DDS_Security_PermissionsCredentialToken token; + DDS_Security_SecurityException exception; + DDS_Security_boolean result; + + /* Pre-requisites. */ + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(access_control->get_permissions_credential_token != NULL); + memset(&exception, 0, sizeof(DDS_Security_SecurityException)); + memset(&token, 0, sizeof(token)); + + /* Test function call. */ + result = access_control->get_permissions_credential_token( + access_control, + &token, + local_permissions_handle, + &exception); + if (!result) + { + printf("get_permissions_credential_token: %s\n", exception.message ? exception.message : "Error message missing"); + } + CU_ASSERT_FATAL(result); + CU_ASSERT(exception.code == 0); + CU_ASSERT(exception.message == NULL); + + /* Test token contents. */ + CU_ASSERT(validate_permissions_token(&token)); + + /* Post-requisites. */ + DDS_Security_DataHolder_deinit(&token); + reset_exception(&exception); +} + +CU_Test(ddssec_builtin_get_permissions_credential_token, invalid_args, .init = suite_get_permissions_credential_token_init, .fini = suite_get_permissions_credential_token_fini) +{ + DDS_Security_PermissionsCredentialToken token; + DDS_Security_SecurityException exception; + DDS_Security_boolean result; + + /* Pre-requisites. */ + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(access_control->get_permissions_token != NULL); + memset(&exception, 0, sizeof(DDS_Security_SecurityException)); + memset(&token, 0, sizeof(token)); + + /* Test function calls with different invalid args. */ + result = access_control->get_permissions_credential_token( + NULL, + &token, + local_permissions_handle, + &exception); + if (!result) + { + printf("get_permissions_token: %s\n", exception.message ? exception.message : "Error message missing"); + } + CU_ASSERT(!result); + CU_ASSERT(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + CU_ASSERT(exception.message != NULL); + reset_exception(&exception); + + result = access_control->get_permissions_credential_token( + access_control, + NULL, + local_permissions_handle, + &exception); + if (!result) + { + printf("get_permissions_credential_token: %s\n", exception.message ? exception.message : "Error message missing"); + } + CU_ASSERT(!result); + CU_ASSERT(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + CU_ASSERT(exception.message != NULL); + reset_exception(&exception); + + result = access_control->get_permissions_credential_token( + access_control, + &token, + 0, + &exception); + if (!result) + { + printf("get_permissions_credential_token: %s\n", exception.message ? exception.message : "Error message missing"); + } + CU_ASSERT(!result); + CU_ASSERT(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + CU_ASSERT(exception.message != NULL); + reset_exception(&exception); + + result = access_control->get_permissions_credential_token( + access_control, + &token, + local_permissions_handle, + NULL); + if (!result) + { + printf("get_permissions_credential_token: %s\n", exception.message ? exception.message : "Error message missing"); + } + CU_ASSERT(!result); + CU_ASSERT(exception.code == 0); + CU_ASSERT(exception.message == NULL); + reset_exception(&exception); + + result = access_control->get_permissions_credential_token( + access_control, + &token, + local_permissions_handle + 12345 /* invalid handle */, + &exception); + if (!result) + { + printf("get_permissions_credential_token: %s\n", exception.message ? exception.message : "Error message missing"); + } + CU_ASSERT(!result); + CU_ASSERT(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + CU_ASSERT(exception.message != NULL); + reset_exception(&exception); +} + diff --git a/src/security/builtin_plugins/tests/get_permissions_token/etc/Test_Governance_ok.p7s b/src/security/builtin_plugins/tests/get_permissions_token/etc/Test_Governance_ok.p7s new file mode 100644 index 0000000..c39903f --- /dev/null +++ b/src/security/builtin_plugins/tests/get_permissions_token/etc/Test_Governance_ok.p7s @@ -0,0 +1,114 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----DB94A190D9780A24156FB0E8F1E76B5F" + +This is an S/MIME signed message + +------DB94A190D9780A24156FB0E8F1E76B5F +Content-Type: text/plain + + + + + + + + + 0 + 230 + + + + + false + + + true + + + ENCRYPT + + + ENCRYPT + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + ENCRYPT + + + ENCRYPT + + + + + + +------DB94A190D9780A24156FB0E8F1E76B5F +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGSAYJKoZIhvcNAQcCoIIGOTCCBjUCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCAnswggJ3AgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggeQwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTgwOTEzMDczOTUwWjAvBgkqhkiG9w0BCQQxIgQgXv8DkvlwebXMwHDbNc0/Pc30 +gyG3xWCnwet49TRMWFsweQYJKoZIhvcNAQkPMWwwajALBglghkgBZQMEASowCwYJ +YIZIAWUDBAEWMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAOBggqhkiG9w0DAgIC +AIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwDQYJKoZI +hvcNAQEBBQAEggEANy8t0EFmv5j1n0+mMn2ut3Chu8PSJceC8gd34IiKq79uC1O3 +PbL9xgiJ2vz7QiTEEeNL2q+CG77cXOcHGUWa4nvbggr/9CqLfHEKGQxDfyXlJZfM +8l550xIXRRBOQ7ilOGLD4QJFfbf9XA4rMuRe8WEYN3FleAaYBJag1tMPg1SS6tgA +BBDM9b1kXHU319zYOk6kZFjlbwHv6XO22SEVRUpXrKudAI8hrGvwksF/+W0S/jS5 +NmYtj/1oMGlCGIaA5rs27H9CkgwrzoMQ3MsR98JlwEUSa4PEe8CClsIziOulQxsp +MicBlMWL0rzpBPVfPTE4gZ/kP7hGBDEQlRzVTA== + +------DB94A190D9780A24156FB0E8F1E76B5F-- + diff --git a/src/security/builtin_plugins/tests/get_permissions_token/etc/Test_Permissions_ok.p7s b/src/security/builtin_plugins/tests/get_permissions_token/etc/Test_Permissions_ok.p7s new file mode 100644 index 0000000..052075b --- /dev/null +++ b/src/security/builtin_plugins/tests/get_permissions_token/etc/Test_Permissions_ok.p7s @@ -0,0 +1,85 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----6B91005B007BBA8EDE10CD1CE487DB27" + +This is an S/MIME signed message + +------6B91005B007BBA8EDE10CD1CE487DB27 +Content-Type: text/plain + + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + + + * + + + + DENY + + + + +------6B91005B007BBA8EDE10CD1CE487DB27 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgl3LfUhn9L0vG/3QRPVYptcYw +/NH5HMN99aMe9JAT+LAwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAHe9vakfXPvbpgMeqlhG +SW6Z3uVA3Yri9bgQDpJ9daIUsM0/TLBSQVs85twTMXvqUSntKbfSGehxDQ9F+yje +mOEPMIwxOqcVyc2jpqoYsUWqpwiiZyk49DHUFrOfWJUx+rKdBftZWkxD05Wkovhk +2d4hGS/65Haoho4Z0AZwcyH+F52FZMiqw7I9FKrPlhxvJfQXmhIjOKtnvWnQ+Ar7 +YYiSrBEHMCy82LF1aKzz0nkL1SYWQHuQX475qoU4LMYY1J8WsD3rSBeq4GYZrl2K +X/JcOquMYqjfJLMYZY4fsc3FgEBkKNqJz1tDZ3ir24VMl+WsbEjVK8oXe/wt4V0U +aNQ= + +------6B91005B007BBA8EDE10CD1CE487DB27-- + diff --git a/src/security/builtin_plugins/tests/get_permissions_token/src/get_permissions_token_utests.c b/src/security/builtin_plugins/tests/get_permissions_token/src/get_permissions_token_utests.c new file mode 100644 index 0000000..ca4f708 --- /dev/null +++ b/src/security/builtin_plugins/tests/get_permissions_token/src/get_permissions_token_utests.c @@ -0,0 +1,439 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include +#include + +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/io.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/types.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/core/dds_security_utils.h" +#include "CUnit/CUnit.h" +#include "CUnit/Test.h" +#include "common/src/loader.h" +#include "config_env.h" + +static const char *PROPERTY_IDENTITY_CA = "dds.sec.auth.identity_ca"; +static const char *PROPERTY_PRIVATE_KEY = "dds.sec.auth.private_key"; +static const char *PROPERTY_IDENTITY_CERT = "dds.sec.auth.identity_certificate"; +static const char *PROPERTY_PERMISSIONS_CA = "dds.sec.access.permissions_ca"; +static const char *PROPERTY_PERMISSIONS = "dds.sec.access.permissions"; +static const char *PROPERTY_GOVERNANCE = "dds.sec.access.governance"; + +static const char *RELATIVE_PATH_TO_ETC_DIR = "/get_permissions_token/etc/"; + +static const char *IDENTITY_CERTIFICATE = + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIEQTCCAymgAwIBAgIINpuaAAnrQZIwDQYJKoZIhvcNAQELBQAwXzELMAkGA1UE\n" + "BhMCTkwxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp\n" + "ZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAxMPQ0hBTTUwMCByb290IGNhMCAXDTE3MDIy\n" + "MjIyMjIwMFoYDzIyMjIwMjIyMjIyMjAwWjBcMQswCQYDVQQGEwJOTDETMBEGA1UE\n" + "CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk\n" + "MRUwEwYDVQQDEwxDSEFNNTAwIGNlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\n" + "ggEKAoIBAQDCpVhivH/wBIyu74rvQncnSZqKyspN6CvD1pmV9wft5PHhVt9jV79v\n" + "gSub5LADoRHAgFdv9duYgBr17Ob6uRrIY4B18CcrCjhQcC4gjx8y2jl9PeYm+qYD\n" + "3o44FYBrBq0QCnrQgKsb/qX9Z+Mw/VUiw65x68W876LEHQQoEgT4kxSuagwBoVRk\n" + "ePD6fYAKmT4XS3x+O0v+rHESTcsKF6yMadgp7h3eH1b8kJTzSx8JV9Zzq++mxjox\n" + "qhbBVP5nDze2hhSIeCkCvSrx7efkgKS4AQXa5/Z44GiAu1TfXXUqdic9rxwD0edn\n" + "ajNElnZe7sjok/0yuqvH+2hSqpNva/zpAgMBAAGjggEAMIH9MAwGA1UdDwQFAwMH\n" + "/4AwgewGA1UdJQSB5DCB4QYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDAwYI\n" + "KwYBBQUHAwQGCCsGAQUFBwMIBgorBgEEAYI3AgEVBgorBgEEAYI3AgEWBgorBgEE\n" + "AYI3CgMBBgorBgEEAYI3CgMDBgorBgEEAYI3CgMEBglghkgBhvhCBAEGCysGAQQB\n" + "gjcKAwQBBggrBgEFBQcDBQYIKwYBBQUHAwYGCCsGAQUFBwMHBggrBgEFBQgCAgYK\n" + "KwYBBAGCNxQCAgYIKwYBBQUHAwkGCCsGAQUFBwMNBggrBgEFBQcDDgYHKwYBBQID\n" + "BTANBgkqhkiG9w0BAQsFAAOCAQEAawdHy0Xw7nTK2ltp91Ion6fJ7hqYuj///zr7\n" + "Adt6uonpDh/xl3esuwcFimIJrJrHujnGkL0nLddRCikmnzuBMNDWS6yq0/Ckl/YG\n" + "yjNr44dlX24wo+MVAgkj3/8CyWDZ3a8kBg9QT3bs2SqbjmhTrXN1DRyf9S5vJysE\n" + "I7V1gTN66BeKL64hOrAlRVrEu8Ds6TWL6Q/YH+61ViZkoLTeSaPjH4nknaFr4C35\n" + "iji0JhkyfRHRRVPHFnaj25AkxOrSV64qVKoTMjDl5fji5iMGtjm6iJ7q05ml/qDl\n" + "nLotHXemZNvYhbwUmRzbt4Dls9EMH4VRbP85I94nM5TAvtHVNA==\n" + "-----END CERTIFICATE-----\n"; + +static const char *IDENTITY_CA = + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIEmTCCA4GgAwIBAgIIZ5gEIUFhO5wwDQYJKoZIhvcNAQELBQAwXzELMAkGA1UE\n" + "BhMCTkwxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp\n" + "ZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAxMPQ0hBTTUwMCByb290IGNhMCAXDTE4MDIx\n" + "MjE1MDUwMFoYDzIyMjIwMjIyMjIyMjAwWjBfMQswCQYDVQQGEwJOTDETMBEGA1UE\n" + "CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk\n" + "MRgwFgYDVQQDEw9DSEFNNTAwIHJvb3QgY2EwggEiMA0GCSqGSIb3DQEBAQUAA4IB\n" + "DwAwggEKAoIBAQC6Fa3TheL+UrdZCp9GhU/2WbneP2t/avUa3muwDttPxeI2XU9k\n" + "ZjBR95mAXme4SPXHk5+YDN319AqIje3oKhzky/ngvKH2GkoJKYxWnuDBfMEHdViz\n" + "2Q9/xso2ZvH50ukwWa0pfx2/EVV1wRxeQcRd/UVfq3KTJizG0M88mOYvGEAw3LFf\n" + "zef7k1aCuOofQmBvLukUudcYpMzfyHFp7lQqU4CcrrR5RtmfiUfrWfdGLea2iPDB\n" + "pJgN8ESOMwEHtOTEBDclYnH9L4t7CHQz+fXXS5IWFsDK9fCMQjnxDsDVeNrNzTYL\n" + "FaZrMg9S6IUQCEsQWsnq5weS8omOpVLUm9klAgMBAAGjggFVMIIBUTAMBgNVHRME\n" + "BTADAQH/MB0GA1UdDgQWBBQg2FZB/j8uWDVnJhjwXkX278znSTAfBgNVHSMEGDAW\n" + "gBQg2FZB/j8uWDVnJhjwXkX278znSTAPBgNVHQ8BAf8EBQMDB/+AMIHvBgNVHSUB\n" + "Af8EgeQwgeEGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwME\n" + "BggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYK\n" + "KwYBBAGCNwoDAwYKKwYBBAGCNwoDBAYJYIZIAYb4QgQBBgsrBgEEAYI3CgMEAQYI\n" + "KwYBBQUHAwUGCCsGAQUFBwMGBggrBgEFBQcDBwYIKwYBBQUIAgIGCisGAQQBgjcU\n" + "AgIGCCsGAQUFBwMJBggrBgEFBQcDDQYIKwYBBQUHAw4GBysGAQUCAwUwDQYJKoZI\n" + "hvcNAQELBQADggEBAKHmwejWRwGE1wf1k2rG8SNRV/neGsZ6Qfqf6co3TpR/Wi1s\n" + "iZDvSeT/rbqNBS7z34xnG88NIUwu00y78e8Mfon31ZZbK4Uo7fla9/D3ukdJqPQC\n" + "LKdbKJjR2kH+KCukY/1rghjJ8/X+t2egBit0LCOdsFCl07Sfksb9kpGUIZSFcYYm\n" + "geqhjhoNwxazzHiw+QWHC5HG9248JIizBmy1aymNWuMnPudhjHAnPcsIlqMVNq3t\n" + "Rv9ap7S8JeCxHVRPJvJeCwXWvW3dW/v3xH52Yn/fqRblN1w9Fxz5NhopKx0gj/Jd\n" + "sw2N4Fk4gaOWEolFpa0bwNw8nAx7moehZpowzfw=\n" + "-----END CERTIFICATE-----\n"; + +static const char *PRIVATE_KEY = + "data:,-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEogIBAAKCAQEAwqVYYrx/8ASMru+K70J3J0maisrKTegrw9aZlfcH7eTx4Vbf\n" + "Y1e/b4Erm+SwA6ERwIBXb/XbmIAa9ezm+rkayGOAdfAnKwo4UHAuII8fMto5fT3m\n" + "JvqmA96OOBWAawatEAp60ICrG/6l/WfjMP1VIsOucevFvO+ixB0EKBIE+JMUrmoM\n" + "AaFUZHjw+n2ACpk+F0t8fjtL/qxxEk3LChesjGnYKe4d3h9W/JCU80sfCVfWc6vv\n" + "psY6MaoWwVT+Zw83toYUiHgpAr0q8e3n5ICkuAEF2uf2eOBogLtU3111KnYnPa8c\n" + "A9HnZ2ozRJZ2Xu7I6JP9Mrqrx/toUqqTb2v86QIDAQABAoIBAC1q32DKkx+yMBFx\n" + "m32QiLUGG6VfBC2BixS7MkMnzRXZYgcuehl4FBc0kLRjfB6cqsO8LqrVN1QyMBhK\n" + "GutN3c38SbE7RChqzhEW2+yE+Mao3Nk4ZEecHLiyaYT0n25ZtHAVwep823BAzwJ+\n" + "BykbM45VEpNKbG1VjSktjBa9faNyZiZAEJEjVyla+6R8N4kHV52LbZcLjvJv3IQ2\n" + "iPYRrmMyI5C23qTni0vy7yJbAXBo3CqgSlwie9FARBWT7Puu7F4mF1O1c/SnTysw\n" + "Tm3e5FzgfHipQbnRVn0w4rDprPMKmPxMnvf/Wkw0zVgNadp1Tc1I6Yj525DEQ07i\n" + "2gIn/gECgYEA4jNnY1u2Eu7x3pAQF3dRO0x35boVtuq9iwQk7q+uaZaK4RJRr+0Y\n" + "T68S3bPnfer6SHvcxtST89Bvs/j/Ky4SOaX037UYjFh6T7OIzPl+MzO1yb+VOBT6\n" + "D6FVGEJGp8ZAITU1OfJPeTYViUeEC8tHFGoKUCk50FbB6jOf1oKtv/ECgYEA3EnB\n" + "Y7kSbJJaUuj9ciFUL/pAno86Cim3VjegK1wKgEiyDb610bhoMErovPwfVJbtcttG\n" + "eKJNuwizkRcVbj+vpjDvqqaP5eMxLl6/Nd4haPMJYzGo88Z8NJpwFRNF2KEWjOpQ\n" + "2NEvoCeRtVulCJyka2Tpljzw8cOXkxhPOe2UhHkCgYBo3entj0QO7QXm56T+LAvV\n" + "0PK45xdQEO3EuCwjGAFk5C0IgUSrqeCeeIzniZMltj1IQ1wsNbtNynEu3530t8wt\n" + "O7oVyFBUKGSz9IjUdkpClJOPr6kPMfJoMqRPtdIpz+hFPPSrI6IikKdVWHloOlp+\n" + "pVaYqTQrWT1XRY2xli3VEQKBgGySmZN6Cx+h/oywswIGdUT0VdcQhq2to+QFpJba\n" + "VX6m1cM6hMip2Ag9U3qZ1SNPBBdBBfm9HQybHE3dj713/C2wHuAAGhpXIM1W+20k\n" + "X1knuC/AsSH9aQhQOf/ZMOq1crTfZBuI9q0782/sjGmzMsKPySU4QhUWruVb7OiD\n" + "NVkZAoGAEvihW7G+8/iOE40vGHyBqUeopAAWLciTAUIEwM/Oi3BYfNWNTWF/FWNc\n" + "nMvCZPYigY8C1vO+1iT2Frtd3CIU+f01Q3fJNJoRLlEiKLNZUJRF48OKUqjKSmsi\n" + "w6pucFO40z05YW7utApj4L82rZnOS0pd1tUI1yexqvj0i4ThJfk=\n" + "-----END RSA PRIVATE KEY-----\n"; + +static const char *PERMISSIONS_CA = + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV\n" + "BAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQKDBZBRExJTksgVGVj\n" + "aG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNvbTAgFw0xODA3MzAx\n" + "MjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMCTkwxEzARBgNVBAgM\n" + "ClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4xFzAV\n" + "BgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" + "CgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blIDehV6XCxrnGXusTCD\n" + "uFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9wicp3BGSpZZax/TcO\n" + "NjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLsDFFC+a0qn2RFh37r\n" + "cWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074BRDXVivx+wVD951L\n" + "FNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiySogRWAmKhysLQudu\n" + "kHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNVHQ4EFgQURWMbWvBK\n" + "ZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJvRV1/tyc1R82k0+gw\n" + "DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ysVtvHnk2hpu9yND\n" + "LCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9XVh0rGoR/6nHzo3TI\n" + "eiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9yghhKHHqNDvSsAL0\n" + "KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbtlLX3QnwVOmaRyzyl\n" + "PiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42+OyLqcH1rKT6Xhcs\n" + "hjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb6SDB340BFmtgDHbF\n" + "HQ==\n" + "-----END CERTIFICATE-----\n"; + +static char *g_path_to_etc_dir = NULL; +static struct plugins_hdl *plugins = NULL; +static dds_security_authentication *auth = NULL; +static dds_security_access_control *access_control = NULL; + +static DDS_Security_IdentityHandle local_identity_handle = DDS_SECURITY_HANDLE_NIL; +static DDS_Security_PermissionsHandle local_permissions_handle = DDS_SECURITY_HANDLE_NIL; + +static void reset_exception(DDS_Security_SecurityException *ex) +{ + ex->code = 0; + ex->minor_code = 0; + ddsrt_free(ex->message); + ex->message = NULL; +} + +static DDS_Security_Property_t *find_property(DDS_Security_DataHolder *token, const char *name) +{ + DDS_Security_Property_t *result = NULL; + uint32_t i; + for (i = 0; i < token->properties._length && !result; i++) + if (token->properties._buffer[i].name && (strcmp(token->properties._buffer[i].name, name) == 0)) + result = &token->properties._buffer[i]; + return result; +} + +static void dds_security_property_init(DDS_Security_PropertySeq *seq, DDS_Security_unsigned_long size) +{ + seq->_length = size; + seq->_maximum = size; + seq->_buffer = ddsrt_malloc(size * sizeof(DDS_Security_Property_t)); + memset(seq->_buffer, 0, size * sizeof(DDS_Security_Property_t)); +} + +static void dds_security_property_deinit(DDS_Security_PropertySeq *seq) +{ + uint32_t i; + for (i = 0; i < seq->_length; i++) + { + ddsrt_free(seq->_buffer[i].name); + ddsrt_free(seq->_buffer[i].value); + } + ddsrt_free(seq->_buffer); +} + +static void fill_participant_qos(DDS_Security_Qos *qos, const char *permission_filename, const char *governance_filename) +{ + char *permission_uri; + char *governance_uri; + + ddsrt_asprintf(&permission_uri, "file:%s%s", g_path_to_etc_dir, permission_filename); + ddsrt_asprintf(&governance_uri, "file:%s%s", g_path_to_etc_dir, governance_filename); + + memset(qos, 0, sizeof(*qos)); + dds_security_property_init(&qos->property.value, 6); + qos->property.value._buffer[0].name = ddsrt_strdup(PROPERTY_IDENTITY_CERT); + qos->property.value._buffer[0].value = ddsrt_strdup(IDENTITY_CERTIFICATE); + qos->property.value._buffer[1].name = ddsrt_strdup(PROPERTY_IDENTITY_CA); + qos->property.value._buffer[1].value = ddsrt_strdup(IDENTITY_CA); + qos->property.value._buffer[2].name = ddsrt_strdup(PROPERTY_PRIVATE_KEY); + qos->property.value._buffer[2].value = ddsrt_strdup(PRIVATE_KEY); + qos->property.value._buffer[3].name = ddsrt_strdup(PROPERTY_PERMISSIONS_CA); + qos->property.value._buffer[3].value = ddsrt_strdup(PERMISSIONS_CA); + qos->property.value._buffer[4].name = ddsrt_strdup(PROPERTY_PERMISSIONS); + qos->property.value._buffer[4].value = ddsrt_strdup(permission_uri); + qos->property.value._buffer[5].name = ddsrt_strdup(PROPERTY_GOVERNANCE); + qos->property.value._buffer[5].value = ddsrt_strdup(governance_uri); + + ddsrt_free(permission_uri); + ddsrt_free(governance_uri); +} + +static void local_permissions_init(DDS_Security_DomainId domain_id) +{ + DDS_Security_ValidationResult_t result; + DDS_Security_Qos participant_qos; + DDS_Security_GUID_t local_participant_guid; + DDS_Security_GUID_t candidate_participant_guid; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_GuidPrefix_t prefix = {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb}; + DDS_Security_EntityId_t entityId = {{0xb0, 0xb1, 0xb2}, 0x1}; + + memset(&local_participant_guid, 0, sizeof(local_participant_guid)); + memcpy(&candidate_participant_guid.prefix, &prefix, sizeof(prefix)); + memcpy(&candidate_participant_guid.entityId, &entityId, sizeof(entityId)); + + fill_participant_qos(&participant_qos, "Test_Permissions_ok.p7s", "Test_Governance_ok.p7s"); + + result = auth->validate_local_identity( + auth, + &local_identity_handle, + &local_participant_guid, + domain_id, + &participant_qos, + &candidate_participant_guid, + &exception); + + CU_ASSERT_EQUAL_FATAL (result, DDS_SECURITY_VALIDATION_OK); + reset_exception(&exception); + local_permissions_handle = access_control->validate_local_permissions( + access_control, + auth, + local_identity_handle, + domain_id, + &participant_qos, + &exception); + + CU_ASSERT_FATAL (local_permissions_handle != DDS_SECURITY_HANDLE_NIL); + reset_exception(&exception); + dds_security_property_deinit(&participant_qos.property.value); +} + +static void local_permissions_clean(void) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_boolean success; + + if (local_permissions_handle != DDS_SECURITY_HANDLE_NIL) + { + success = access_control->return_permissions_handle(access_control, local_permissions_handle, &exception); + if (!success) + { + printf("return_permission_handle failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + reset_exception(&exception); + } + + if (local_identity_handle != DDS_SECURITY_HANDLE_NIL) + { + success = auth->return_identity_handle(auth, local_identity_handle, &exception); + if (!success) + { + printf("return_identity_handle failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + reset_exception(&exception); + } +} + +static void set_path_to_etc_dir(void) +{ + ddsrt_asprintf(&g_path_to_etc_dir, "%s%s", CONFIG_ENV_TESTS_DIR, RELATIVE_PATH_TO_ETC_DIR); +} + +static void suite_get_permissions_token_init(void) +{ + plugins = load_plugins(&access_control, &auth, NULL /* Cryptograpy */); + CU_ASSERT_FATAL (plugins != NULL); + set_path_to_etc_dir(); + local_permissions_init(0); +} + +static void suite_get_permissions_token_fini(void) +{ + local_permissions_clean(); + unload_plugins(plugins); + ddsrt_free(g_path_to_etc_dir); +} + +static bool validate_permissions_token( + DDS_Security_PermissionsToken *token) +{ + if (!token->class_id || strcmp(token->class_id, "DDS:Access:Permissions:1.0") != 0) + { + CU_FAIL("PermissionsToken incorrect class_id"); + return false; + } + + /* Optional. */ + if (find_property(token, "dds.perm_ca.sn") == NULL) + printf("Optional PermissionsToken property 'dds.perm_ca.sn' not found\n"); + if (find_property(token, "dds.perm_ca.algo") == NULL) + printf("Optional PermissionsToken property 'dds.perm_ca.algo' not found\n"); + return true; +} + +CU_Test(ddssec_builtin_get_permissions_token, happy_day, .init = suite_get_permissions_token_init, .fini = suite_get_permissions_token_fini) +{ + DDS_Security_SecurityException exception; + DDS_Security_PermissionsToken token; + DDS_Security_boolean result; + + /* Pre-requisites. */ + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(access_control->get_permissions_token != NULL); + memset(&exception, 0, sizeof(DDS_Security_SecurityException)); + memset(&token, 0, sizeof(token)); + + /* Test function call. */ + result = access_control->get_permissions_token( + access_control, + &token, + local_permissions_handle, + &exception); + if (!result) + { + printf("get_permissions_token: %s\n", exception.message ? exception.message : "Error message missing"); + } + CU_ASSERT_FATAL(result); + CU_ASSERT(exception.code == 0); + CU_ASSERT(exception.message == NULL); + + /* Test token contents. */ + CU_ASSERT(validate_permissions_token(&token)); + + /* Post-requisites. */ + DDS_Security_DataHolder_deinit(&token); + reset_exception(&exception); +} + +CU_Test(ddssec_builtin_get_permissions_token, invalid_args, .init = suite_get_permissions_token_init, .fini = suite_get_permissions_token_fini) +{ + DDS_Security_SecurityException exception; + DDS_Security_PermissionsToken token; + DDS_Security_boolean result; + + /* Pre-requisites. */ + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(access_control->get_permissions_token != NULL); + memset(&exception, 0, sizeof(DDS_Security_SecurityException)); + memset(&token, 0, sizeof(token)); + + /* Test function calls with different invalid args. */ + result = access_control->get_permissions_token( + NULL, + &token, + local_permissions_handle, + &exception); + if (!result) + { + printf("get_permissions_token: %s\n", exception.message ? exception.message : "Error message missing"); + } + CU_ASSERT(!result); + CU_ASSERT(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + CU_ASSERT(exception.message != NULL); + reset_exception(&exception); + + result = access_control->get_permissions_token( + access_control, + NULL, + local_permissions_handle, + &exception); + if (!result) + { + printf("get_permissions_token: %s\n", exception.message ? exception.message : "Error message missing"); + } + CU_ASSERT(!result); + CU_ASSERT(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + CU_ASSERT(exception.message != NULL); + reset_exception(&exception); + + result = access_control->get_permissions_token( + access_control, + &token, + 0, + &exception); + if (!result) + { + printf("get_permissions_token: %s\n", exception.message ? exception.message : "Error message missing"); + } + CU_ASSERT(!result); + CU_ASSERT(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + CU_ASSERT(exception.message != NULL); + reset_exception(&exception); + + result = access_control->get_permissions_token( + access_control, + &token, + local_permissions_handle, + NULL); + if (!result) + { + printf("get_permissions_token: %s\n", exception.message ? exception.message : "Error message missing"); + } + CU_ASSERT(!result); + CU_ASSERT(exception.code == 0); + CU_ASSERT(exception.message == NULL); + reset_exception(&exception); + + result = access_control->get_permissions_token( + access_control, + &token, + local_permissions_handle + 12345 /* invalid handle */, + &exception); + if (!result) + { + printf("get_permissions_token: %s\n", exception.message ? exception.message : "Error message missing"); + } + CU_ASSERT(!result); + CU_ASSERT(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + CU_ASSERT(exception.message != NULL); + reset_exception(&exception); +} diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_full.p7s b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_full.p7s new file mode 100644 index 0000000..4ea8fe8 --- /dev/null +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_full.p7s @@ -0,0 +1,267 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----05DBD6F6E587875751A79EAC78048D60" + +This is an S/MIME signed message + +------05DBD6F6E587875751A79EAC78048D60 +Content-Type: text/plain + + + + + + + + 20 + + 0 + 23 + + + 100 + 120 + + 200 + + + + false + + + TRUE + + + SIGN_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + + + + OwnShip?ata + + + FALSE + + + false + + + false + + + true + + + SIGN + + + ENCRYPT + + + + + Kinematics + + + true + + + true + + + true + + + false + + + NONE + + + NONE + + + + + *other + + + true + + + true + + + true + + + true + + + NONE + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT + + + + + + + + 100 + 120 + + 20 + + 0 + 23 + + 200 + 30 + + + + 1 + + + 0 + + + SIGN + + + ENCRYPT + + + NONE + + + + + OwnShipData + + + true + + + true + + + false + + + false + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT + + + + + + + + +------05DBD6F6E587875751A79EAC78048D60 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQg0GyBZYdNlmQT2Nv1CHrUEB6+ +C0U0yXvpmj5+mlGojPAwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAJXrVHO7KdgYM20uGGNL +P4VRPmYVWoWIkl5/OEzZ8uirs+oGJR7tYLiFl1wzXUzPBB/03qsANmlshDpFgbmV +thTV7AGRg3SXUDa/cG4N9PupE5VRZaVdbcbdH1DfoIZCLLp4HK3HgqUXkH9vnC92 +tdtgzxZOCrQ4A6WbGiBkWr5LtMWg2lnwPp55vrfRoh6u0qVEumD+VQi+Lroo9M1E +659LB2dwEcNb1g1HyoodpKlUSsbGsY/JA7bbNrw/KIGVYcoXfmpgWmtzUjfpkPDj +zVPImqr6jdxP4quGmGWRmrLHPrEYJscJqCwjNTi6naXnAvaE4nxQ4HBgveEodTuP +8tM= + +------05DBD6F6E587875751A79EAC78048D60-- + diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_clear.p7s b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_clear.p7s new file mode 100644 index 0000000..3ef33a2 --- /dev/null +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_clear.p7s @@ -0,0 +1,114 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----D5AADCFDEEF9EC8B0B116AC356AF41CA" + +This is an S/MIME signed message + +------D5AADCFDEEF9EC8B0B116AC356AF41CA +Content-Type: text/plain + + + + + + + + + 0 + 230 + + + + + false + + + TRUE + + + NONE + + + NONE + + + NONE + + + + + * + + + FALSE + + + false + + + false + + + false + + + NONE + + + NONE + + + + + + +------D5AADCFDEEF9EC8B0B116AC356AF41CA +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQg1l4l1hEFvxsjc65MThWHhvCb +YoBySw0UQA61LL+lSsEwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAF88Gg525eeqmgAtBky5 +lMnQehnA0c37pSL5uTklEcb0xwkQcdWQVerkAwKQb8CJGz4ttwvVqIde2Jn8boJP +Tb8xYvk38HXFHOpzSEv0qAj0u6dVB+go3OnrdhcM1R7jrHfReBRgnict8pLOPb+Y +khdlqzOMVxoTpJSiXUWdt5ucKbNvuWROG6TsNs4S5+lJ3EEvDn3++g32VRX9V3h4 +5Hni4AMGmZrjBbmL/S02iR33ltwXYqfipUQjR5S5V/HS0LHX/mjYwuiWCtHNiSIi +s+8mqW8vNebYA9LeK7bvWXCygqnVr3qJT+ryeXUXtBl7dCTV+QVAlUzbW1wgHSuq +wtc= + +------D5AADCFDEEF9EC8B0B116AC356AF41CA-- + diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_clear.xml b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_clear.xml new file mode 100644 index 0000000..e829911 --- /dev/null +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_clear.xml @@ -0,0 +1,62 @@ + + + + + + + + 0 + 230 + + + + + false + + + TRUE + + + NONE + + + NONE + + + NONE + + + + + * + + + FALSE + + + false + + + false + + + false + + + NONE + + + NONE + + + + + diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_different.p7s b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_different.p7s new file mode 100644 index 0000000..38b2c26 --- /dev/null +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_different.p7s @@ -0,0 +1,114 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----37F7530AAA327BE7C00C18ECA28FFF95" + +This is an S/MIME signed message + +------37F7530AAA327BE7C00C18ECA28FFF95 +Content-Type: text/plain + + + + + + + + + 0 + 230 + + + + + false + + + TRUE + + + ENCRYPT + + + NONE + + + NONE + + + + + * + + + false + + + true + + + false + + + false + + + NONE + + + NONE + + + + + + +------37F7530AAA327BE7C00C18ECA28FFF95 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgqqTuijPzgi5UyYnaRmfKMSwt +M8Mbr6egpAxWLt7vkkAwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBACmMVANcUvNpeIpdG6is +IbAJWbvoIh68B4nMLMU8gij1ZcNavWg6dDU709AJcrCU2ZbVsHKPyBvRuSctkbKe +XHCRv5bAkcqkLsEVPc4Yu8w2hIC8nSTW1E2l1I+tChcXepcSsmrRFjZI8myDWmre +Slzcq0nSwKayhMSkv0CJeSzhQGCHBhRnVCb7ZDJXL94VKh1OBxlqTWGLRNQcIk0p +WXI0B2j5n8nM+neQd1gnKKuvqjSh2/IwUPariRfqpfVm1e8Mc0zNAubHOfuZ/hXj +tDAPBcJq8gz3sKSbwvN4Rk1J7YV0AnA8pPq3nfoZWvqcUzbdExn2zvzawRgteUyf +luw= + +------37F7530AAA327BE7C00C18ECA28FFF95-- + diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_different.xml b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_different.xml new file mode 100644 index 0000000..6f12d18 --- /dev/null +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_different.xml @@ -0,0 +1,62 @@ + + + + + + + + 0 + 230 + + + + + false + + + TRUE + + + ENCRYPT + + + NONE + + + NONE + + + + + * + + + false + + + true + + + false + + + false + + + NONE + + + NONE + + + + + diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_encrypted.p7s b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_encrypted.p7s new file mode 100644 index 0000000..cfc92ac --- /dev/null +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_encrypted.p7s @@ -0,0 +1,114 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----E6FE6351D381785F2D971BF5DB266909" + +This is an S/MIME signed message + +------E6FE6351D381785F2D971BF5DB266909 +Content-Type: text/plain + + + + + + + + + 0 + 230 + + + + + false + + + TRUE + + + ENCRYPT + + + ENCRYPT + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + NONE + + + NONE + + + + + + +------E6FE6351D381785F2D971BF5DB266909 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQg7ee1YxacZ9KtXJCLUCzhZB8p +Sv4SXMFrKtVchg886ZkwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAB3tqkFmfwnk2HXgn9H1 +Ap6Hk7I3TIYBMMQkDTZHbPj3EMOls02+QI++ztvwaBzG7bS6f7qfxhHnNgXF/52t +Qf20nOXjxAUL82UxVxNmJjqE+FHksSTqEjtKFMy8V+wz9doVSUgdfKKD8SUOOr1I +nakp0o/Vk/E5bbYOoWaDXJKAo7iiEssbsw33/8eZgPpVOyPS0pqk7w6d/fmo2OMm +niCl24qiXjdQbkuUT+zuhjKIfBjxqIPRKnOxK+HheR77m/EhkNsYYbsOgLaSXQVW +O3Kv0GmJGKg0N2KXW5VH+6FhS5KA6TL/6Xz6LzLZFsSyAmhWsBK0l1Ted+z4Tgw3 +fP8= + +------E6FE6351D381785F2D971BF5DB266909-- + diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_encrypted.xml b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_encrypted.xml new file mode 100644 index 0000000..01b2d20 --- /dev/null +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_encrypted.xml @@ -0,0 +1,62 @@ + + + + + + + + 0 + 230 + + + + + false + + + TRUE + + + ENCRYPT + + + ENCRYPT + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + NONE + + + NONE + + + + + diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_encrypted_and_authenticated.p7s b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_encrypted_and_authenticated.p7s new file mode 100644 index 0000000..c604b13 --- /dev/null +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_encrypted_and_authenticated.p7s @@ -0,0 +1,114 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----4375434DF6819FB7435B04810D502609" + +This is an S/MIME signed message + +------4375434DF6819FB7435B04810D502609 +Content-Type: text/plain + + + + + + + + + 0 + 230 + + + + + false + + + TRUE + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + NONE + + + NONE + + + + + + +------4375434DF6819FB7435B04810D502609 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQglibSNHDswKA0PDJrsz8tZiXT +1UrMUhYJJbXsLdvTGVowgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBACLqhHS8kapMUhLBjAfI +17FuvzGjgJ2CSy7/yJDz1+OsUdbCofV8jA1rxxPIGv9Koq/BaKHtJdtzpLaag/CD +SITepCjU+rRoGnZ5vOeSgaHJlDWcRBtAoFME3NrgdYT7ldUABuiPngR5HuwNAUTA +aY2rPaSds2eWluqH6WJqO+qvRvSZEsypy+OSpRAu954rDfkFGyZ00aQnTpzJTVJT +MLF8rXziOY9CAHXFN0w6jEBy7Y4pBjnp/bQQFmE41NH9KuATEGPLChInQOYEEeNK +2rr96Z/rgfhcBE1qyZdt4RNgGNFNCRzeGIX5Kti/jTeas1430sQ+DYJypObVhrhY +S/M= + +------4375434DF6819FB7435B04810D502609-- + diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_encrypted_and_authenticated.xml b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_encrypted_and_authenticated.xml new file mode 100644 index 0000000..d011e9c --- /dev/null +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_encrypted_and_authenticated.xml @@ -0,0 +1,62 @@ + + + + + + + + 0 + 230 + + + + + false + + + TRUE + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + NONE + + + NONE + + + + + diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_signed.p7s b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_signed.p7s new file mode 100644 index 0000000..55cf899 --- /dev/null +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_signed.p7s @@ -0,0 +1,114 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----CAAC97AAFA02CB29461AE6EEFCBDADE0" + +This is an S/MIME signed message + +------CAAC97AAFA02CB29461AE6EEFCBDADE0 +Content-Type: text/plain + + + + + + + + + 0 + 230 + + + + + false + + + TRUE + + + SIGN + + + SIGN + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + NONE + + + NONE + + + + + + +------CAAC97AAFA02CB29461AE6EEFCBDADE0 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgUQGGQlfgFH2GTdp8QcQHAf7c +ytQO0EMxvnsXNDiWmfcwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBABl+6OuVlW5UltPGg+9c +6DlnX12Ah1feD0c/cmOkWjKW9A/soc+5npXvLcbxlkO/+MEkHlH00QKQmX7uY+3Z +NybUU/2KbzEeqo8WwkqJPFBBPrjbHTAuIIPDHFcSq9oY6zUWMcHDFVjaXcNOfyiA +clECqfcXesxfwGNXv5x58y0rJdxGiyptryLvJnZozwjNJ08ggY6d2mnitxbtSowY +InQ02I95vWHYquonVAihvKX9NhaCSDEMyJb/ckL8tJuzQ3qUsEfc5DJVUSOEyCo8 +C7cZbfCpM9R+ZwyhRQOaleHs4kLvli7Q8OkpH8ecUBeg9gQmriju1G2/irvTg4t+ +Tlw= + +------CAAC97AAFA02CB29461AE6EEFCBDADE0-- + diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_signed.xml b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_signed.xml new file mode 100644 index 0000000..63ee9e4 --- /dev/null +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_signed.xml @@ -0,0 +1,62 @@ + + + + + + + + 0 + 230 + + + + + false + + + TRUE + + + SIGN + + + SIGN + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + NONE + + + NONE + + + + + diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_signed_and_authenticated.p7s b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_signed_and_authenticated.p7s new file mode 100644 index 0000000..6273245 --- /dev/null +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_signed_and_authenticated.p7s @@ -0,0 +1,114 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----7D08A7D2B4B01785900B9A7208F12A69" + +This is an S/MIME signed message + +------7D08A7D2B4B01785900B9A7208F12A69 +Content-Type: text/plain + + + + + + + + + 0 + 230 + + + + + false + + + TRUE + + + SIGN_WITH_ORIGIN_AUTHENTICATION + + + SIGN_WITH_ORIGIN_AUTHENTICATION + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + NONE + + + NONE + + + + + + +------7D08A7D2B4B01785900B9A7208F12A69 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgu4lTESCOlPw4ua2e8RFY0V80 +KDwe7OyvA7k5OJvb70MwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAE6icR4lmUwDahVEA4BA +QIl2Pp+WGo1wDLHRdR1YnKt9narfgi6YHlt37sppOuKYPZSrjkcE07nlj9IN3PNR +2RxeUogt5fLHPll2E+GIfXRkPq5MtCscko+7MyrPkaMOPCv0pQ8e+nEvDkLeKqvS +jinelekFzICvUd8vg9UozxyUQciPLvjmEVwe+czFiM0oFqN9O9d1y5n985HXc/T5 +RfhSXpXUk2KBPvU+tN9UtdInMylPs8PK8wbONTem7uG9nP/tKL7VCjLiTQm5zAuo +ecEvLybuALPVwylTppB2a8jMwb3Qt3ERY/do9s9RyFszvMOqBXsDOpSGtjBHT2uU +Bhs= + +------7D08A7D2B4B01785900B9A7208F12A69-- + diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_signed_and_authenticated.xml b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_signed_and_authenticated.xml new file mode 100644 index 0000000..3930f88 --- /dev/null +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Governance_liveliness_discovery_signed_and_authenticated.xml @@ -0,0 +1,62 @@ + + + + + + + + 0 + 230 + + + + + false + + + TRUE + + + SIGN_WITH_ORIGIN_AUTHENTICATION + + + SIGN_WITH_ORIGIN_AUTHENTICATION + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + NONE + + + NONE + + + + + diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Permissions_ok.p7s b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Permissions_ok.p7s new file mode 100644 index 0000000..052075b --- /dev/null +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/etc/Test_Permissions_ok.p7s @@ -0,0 +1,85 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----6B91005B007BBA8EDE10CD1CE487DB27" + +This is an S/MIME signed message + +------6B91005B007BBA8EDE10CD1CE487DB27 +Content-Type: text/plain + + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + + + * + + + + DENY + + + + +------6B91005B007BBA8EDE10CD1CE487DB27 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgl3LfUhn9L0vG/3QRPVYptcYw +/NH5HMN99aMe9JAT+LAwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAHe9vakfXPvbpgMeqlhG +SW6Z3uVA3Yri9bgQDpJ9daIUsM0/TLBSQVs85twTMXvqUSntKbfSGehxDQ9F+yje +mOEPMIwxOqcVyc2jpqoYsUWqpwiiZyk49DHUFrOfWJUx+rKdBftZWkxD05Wkovhk +2d4hGS/65Haoho4Z0AZwcyH+F52FZMiqw7I9FKrPlhxvJfQXmhIjOKtnvWnQ+Ar7 +YYiSrBEHMCy82LF1aKzz0nkL1SYWQHuQX475qoU4LMYY1J8WsD3rSBeq4GYZrl2K +X/JcOquMYqjfJLMYZY4fsc3FgEBkKNqJz1tDZ3ir24VMl+WsbEjVK8oXe/wt4V0U +aNQ= + +------6B91005B007BBA8EDE10CD1CE487DB27-- + diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/src/get_xxx_sec_attributes_utests.c b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/src/get_xxx_sec_attributes_utests.c new file mode 100644 index 0000000..91381aa --- /dev/null +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/src/get_xxx_sec_attributes_utests.c @@ -0,0 +1,1649 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include +#include + +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/io.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/types.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/core/dds_security_utils.h" +#include "CUnit/CUnit.h" +#include "CUnit/Test.h" +#include "common/src/loader.h" +#include "config_env.h" + +#if OPENSLL_VERSION_NUMBER >= 0x10002000L +#define AUTH_INCLUDE_EC +#endif + +static const char *RELATIVE_PATH_TO_ETC_DIR = "/get_xxx_sec_attributes/etc/"; + +static const char *PROPERTY_IDENTITY_CA = "dds.sec.auth.identity_ca"; +static const char *PROPERTY_PRIVATE_KEY = "dds.sec.auth.private_key"; +static const char *PROPERTY_IDENTITY_CERT = "dds.sec.auth.identity_certificate"; +static const char *PROPERTY_PERMISSIONS_CA = "dds.sec.access.permissions_ca"; +static const char *PROPERTY_PERMISSIONS = "dds.sec.access.permissions"; +static const char *PROPERTY_GOVERNANCE = "dds.sec.access.governance"; + +static const char *IDENTITY_CERTIFICATE = + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIEQTCCAymgAwIBAgIINpuaAAnrQZIwDQYJKoZIhvcNAQELBQAwXzELMAkGA1UE\n" + "BhMCTkwxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp\n" + "ZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAxMPQ0hBTTUwMCByb290IGNhMCAXDTE3MDIy\n" + "MjIyMjIwMFoYDzIyMjIwMjIyMjIyMjAwWjBcMQswCQYDVQQGEwJOTDETMBEGA1UE\n" + "CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk\n" + "MRUwEwYDVQQDEwxDSEFNNTAwIGNlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\n" + "ggEKAoIBAQDCpVhivH/wBIyu74rvQncnSZqKyspN6CvD1pmV9wft5PHhVt9jV79v\n" + "gSub5LADoRHAgFdv9duYgBr17Ob6uRrIY4B18CcrCjhQcC4gjx8y2jl9PeYm+qYD\n" + "3o44FYBrBq0QCnrQgKsb/qX9Z+Mw/VUiw65x68W876LEHQQoEgT4kxSuagwBoVRk\n" + "ePD6fYAKmT4XS3x+O0v+rHESTcsKF6yMadgp7h3eH1b8kJTzSx8JV9Zzq++mxjox\n" + "qhbBVP5nDze2hhSIeCkCvSrx7efkgKS4AQXa5/Z44GiAu1TfXXUqdic9rxwD0edn\n" + "ajNElnZe7sjok/0yuqvH+2hSqpNva/zpAgMBAAGjggEAMIH9MAwGA1UdDwQFAwMH\n" + "/4AwgewGA1UdJQSB5DCB4QYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDAwYI\n" + "KwYBBQUHAwQGCCsGAQUFBwMIBgorBgEEAYI3AgEVBgorBgEEAYI3AgEWBgorBgEE\n" + "AYI3CgMBBgorBgEEAYI3CgMDBgorBgEEAYI3CgMEBglghkgBhvhCBAEGCysGAQQB\n" + "gjcKAwQBBggrBgEFBQcDBQYIKwYBBQUHAwYGCCsGAQUFBwMHBggrBgEFBQgCAgYK\n" + "KwYBBAGCNxQCAgYIKwYBBQUHAwkGCCsGAQUFBwMNBggrBgEFBQcDDgYHKwYBBQID\n" + "BTANBgkqhkiG9w0BAQsFAAOCAQEAawdHy0Xw7nTK2ltp91Ion6fJ7hqYuj///zr7\n" + "Adt6uonpDh/xl3esuwcFimIJrJrHujnGkL0nLddRCikmnzuBMNDWS6yq0/Ckl/YG\n" + "yjNr44dlX24wo+MVAgkj3/8CyWDZ3a8kBg9QT3bs2SqbjmhTrXN1DRyf9S5vJysE\n" + "I7V1gTN66BeKL64hOrAlRVrEu8Ds6TWL6Q/YH+61ViZkoLTeSaPjH4nknaFr4C35\n" + "iji0JhkyfRHRRVPHFnaj25AkxOrSV64qVKoTMjDl5fji5iMGtjm6iJ7q05ml/qDl\n" + "nLotHXemZNvYhbwUmRzbt4Dls9EMH4VRbP85I94nM5TAvtHVNA==\n" + "-----END CERTIFICATE-----\n"; + +static const char *IDENTITY_CA = + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIEmTCCA4GgAwIBAgIIZ5gEIUFhO5wwDQYJKoZIhvcNAQELBQAwXzELMAkGA1UE\n" + "BhMCTkwxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp\n" + "ZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAxMPQ0hBTTUwMCByb290IGNhMCAXDTE4MDIx\n" + "MjE1MDUwMFoYDzIyMjIwMjIyMjIyMjAwWjBfMQswCQYDVQQGEwJOTDETMBEGA1UE\n" + "CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk\n" + "MRgwFgYDVQQDEw9DSEFNNTAwIHJvb3QgY2EwggEiMA0GCSqGSIb3DQEBAQUAA4IB\n" + "DwAwggEKAoIBAQC6Fa3TheL+UrdZCp9GhU/2WbneP2t/avUa3muwDttPxeI2XU9k\n" + "ZjBR95mAXme4SPXHk5+YDN319AqIje3oKhzky/ngvKH2GkoJKYxWnuDBfMEHdViz\n" + "2Q9/xso2ZvH50ukwWa0pfx2/EVV1wRxeQcRd/UVfq3KTJizG0M88mOYvGEAw3LFf\n" + "zef7k1aCuOofQmBvLukUudcYpMzfyHFp7lQqU4CcrrR5RtmfiUfrWfdGLea2iPDB\n" + "pJgN8ESOMwEHtOTEBDclYnH9L4t7CHQz+fXXS5IWFsDK9fCMQjnxDsDVeNrNzTYL\n" + "FaZrMg9S6IUQCEsQWsnq5weS8omOpVLUm9klAgMBAAGjggFVMIIBUTAMBgNVHRME\n" + "BTADAQH/MB0GA1UdDgQWBBQg2FZB/j8uWDVnJhjwXkX278znSTAfBgNVHSMEGDAW\n" + "gBQg2FZB/j8uWDVnJhjwXkX278znSTAPBgNVHQ8BAf8EBQMDB/+AMIHvBgNVHSUB\n" + "Af8EgeQwgeEGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwME\n" + "BggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYK\n" + "KwYBBAGCNwoDAwYKKwYBBAGCNwoDBAYJYIZIAYb4QgQBBgsrBgEEAYI3CgMEAQYI\n" + "KwYBBQUHAwUGCCsGAQUFBwMGBggrBgEFBQcDBwYIKwYBBQUIAgIGCisGAQQBgjcU\n" + "AgIGCCsGAQUFBwMJBggrBgEFBQcDDQYIKwYBBQUHAw4GBysGAQUCAwUwDQYJKoZI\n" + "hvcNAQELBQADggEBAKHmwejWRwGE1wf1k2rG8SNRV/neGsZ6Qfqf6co3TpR/Wi1s\n" + "iZDvSeT/rbqNBS7z34xnG88NIUwu00y78e8Mfon31ZZbK4Uo7fla9/D3ukdJqPQC\n" + "LKdbKJjR2kH+KCukY/1rghjJ8/X+t2egBit0LCOdsFCl07Sfksb9kpGUIZSFcYYm\n" + "geqhjhoNwxazzHiw+QWHC5HG9248JIizBmy1aymNWuMnPudhjHAnPcsIlqMVNq3t\n" + "Rv9ap7S8JeCxHVRPJvJeCwXWvW3dW/v3xH52Yn/fqRblN1w9Fxz5NhopKx0gj/Jd\n" + "sw2N4Fk4gaOWEolFpa0bwNw8nAx7moehZpowzfw=\n" + "-----END CERTIFICATE-----\n"; + +static const char *PRIVATE_KEY = + "data:,-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEogIBAAKCAQEAwqVYYrx/8ASMru+K70J3J0maisrKTegrw9aZlfcH7eTx4Vbf\n" + "Y1e/b4Erm+SwA6ERwIBXb/XbmIAa9ezm+rkayGOAdfAnKwo4UHAuII8fMto5fT3m\n" + "JvqmA96OOBWAawatEAp60ICrG/6l/WfjMP1VIsOucevFvO+ixB0EKBIE+JMUrmoM\n" + "AaFUZHjw+n2ACpk+F0t8fjtL/qxxEk3LChesjGnYKe4d3h9W/JCU80sfCVfWc6vv\n" + "psY6MaoWwVT+Zw83toYUiHgpAr0q8e3n5ICkuAEF2uf2eOBogLtU3111KnYnPa8c\n" + "A9HnZ2ozRJZ2Xu7I6JP9Mrqrx/toUqqTb2v86QIDAQABAoIBAC1q32DKkx+yMBFx\n" + "m32QiLUGG6VfBC2BixS7MkMnzRXZYgcuehl4FBc0kLRjfB6cqsO8LqrVN1QyMBhK\n" + "GutN3c38SbE7RChqzhEW2+yE+Mao3Nk4ZEecHLiyaYT0n25ZtHAVwep823BAzwJ+\n" + "BykbM45VEpNKbG1VjSktjBa9faNyZiZAEJEjVyla+6R8N4kHV52LbZcLjvJv3IQ2\n" + "iPYRrmMyI5C23qTni0vy7yJbAXBo3CqgSlwie9FARBWT7Puu7F4mF1O1c/SnTysw\n" + "Tm3e5FzgfHipQbnRVn0w4rDprPMKmPxMnvf/Wkw0zVgNadp1Tc1I6Yj525DEQ07i\n" + "2gIn/gECgYEA4jNnY1u2Eu7x3pAQF3dRO0x35boVtuq9iwQk7q+uaZaK4RJRr+0Y\n" + "T68S3bPnfer6SHvcxtST89Bvs/j/Ky4SOaX037UYjFh6T7OIzPl+MzO1yb+VOBT6\n" + "D6FVGEJGp8ZAITU1OfJPeTYViUeEC8tHFGoKUCk50FbB6jOf1oKtv/ECgYEA3EnB\n" + "Y7kSbJJaUuj9ciFUL/pAno86Cim3VjegK1wKgEiyDb610bhoMErovPwfVJbtcttG\n" + "eKJNuwizkRcVbj+vpjDvqqaP5eMxLl6/Nd4haPMJYzGo88Z8NJpwFRNF2KEWjOpQ\n" + "2NEvoCeRtVulCJyka2Tpljzw8cOXkxhPOe2UhHkCgYBo3entj0QO7QXm56T+LAvV\n" + "0PK45xdQEO3EuCwjGAFk5C0IgUSrqeCeeIzniZMltj1IQ1wsNbtNynEu3530t8wt\n" + "O7oVyFBUKGSz9IjUdkpClJOPr6kPMfJoMqRPtdIpz+hFPPSrI6IikKdVWHloOlp+\n" + "pVaYqTQrWT1XRY2xli3VEQKBgGySmZN6Cx+h/oywswIGdUT0VdcQhq2to+QFpJba\n" + "VX6m1cM6hMip2Ag9U3qZ1SNPBBdBBfm9HQybHE3dj713/C2wHuAAGhpXIM1W+20k\n" + "X1knuC/AsSH9aQhQOf/ZMOq1crTfZBuI9q0782/sjGmzMsKPySU4QhUWruVb7OiD\n" + "NVkZAoGAEvihW7G+8/iOE40vGHyBqUeopAAWLciTAUIEwM/Oi3BYfNWNTWF/FWNc\n" + "nMvCZPYigY8C1vO+1iT2Frtd3CIU+f01Q3fJNJoRLlEiKLNZUJRF48OKUqjKSmsi\n" + "w6pucFO40z05YW7utApj4L82rZnOS0pd1tUI1yexqvj0i4ThJfk=\n" + "-----END RSA PRIVATE KEY-----\n"; + +static const char *PERMISSIONS_CA = + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV\n" + "BAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQKDBZBRExJTksgVGVj\n" + "aG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNvbTAgFw0xODA3MzAx\n" + "MjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMCTkwxEzARBgNVBAgM\n" + "ClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4xFzAV\n" + "BgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" + "CgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blIDehV6XCxrnGXusTCD\n" + "uFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9wicp3BGSpZZax/TcO\n" + "NjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLsDFFC+a0qn2RFh37r\n" + "cWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074BRDXVivx+wVD951L\n" + "FNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiySogRWAmKhysLQudu\n" + "kHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNVHQ4EFgQURWMbWvBK\n" + "ZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJvRV1/tyc1R82k0+gw\n" + "DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ysVtvHnk2hpu9yND\n" + "LCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9XVh0rGoR/6nHzo3TI\n" + "eiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9yghhKHHqNDvSsAL0\n" + "KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbtlLX3QnwVOmaRyzyl\n" + "PiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42+OyLqcH1rKT6Xhcs\n" + "hjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb6SDB340BFmtgDHbF\n" + "HQ==\n" + "-----END CERTIFICATE-----\n"; + +static struct plugins_hdl *plugins = NULL; +static dds_security_access_control *access_control = NULL; +static dds_security_authentication *auth = NULL; +static DDS_Security_IdentityHandle local_identity_handle = DDS_SECURITY_HANDLE_NIL; +static DDS_Security_PermissionsHandle local_permissions_handle = DDS_SECURITY_HANDLE_NIL; +static DDS_Security_GUID_t local_participant_guid; +static char *g_path_to_etc_dir = NULL; + +typedef enum SEC_TOPIC_NAME +{ + SEC_TOPIC_DCPSPARTICIPANTSECURE, + SEC_TOPIC_DCPSPUBLICATIONSSECURE, + SEC_TOPIC_DCPSSUBSCRIPTIONSSECURE, + SEC_TOPIC_DCPSPARTICIPANTMESSAGESECURE, + SEC_TOPIC_DCPSPARTICIPANTSTATELESSMESSAGE, + SEC_TOPIC_DCPSPARTICIPANTVOLATILEMESSAGESECURE, + SEC_TOPIC_DCPS_KINEMATICS, + SEC_TOPIC_DCPS_OWNSHIPDATA, + SEC_TOPIC_DCPS_SHAPE +} SEC_TOPIC_TYPE; + +const char *TOPIC_NAMES[] = {"DCPSParticipantsSecure", + "DCPSPublicationsSecure", + "DCPSSubscriptionsSecure", + "DCPSParticipantMessageSecure", + "DCPSParticipantStatelessMessage", + "DCPSParticipantVolatileMessageSecure", + "Kinematics", + "OwnShipData", + "Shape" + +}; + +static DDS_Security_EndpointSecurityAttributes ATTRIBUTE_CHECKLIST[9]; + +static void reset_exception(DDS_Security_SecurityException *ex) +{ + ex->code = 0; + ex->minor_code = 0; + ddsrt_free(ex->message); + ex->message = NULL; +} + +static void dds_security_property_init(DDS_Security_PropertySeq *seq, DDS_Security_unsigned_long size) +{ + seq->_length = size; + seq->_maximum = size; + seq->_buffer = ddsrt_malloc(size * sizeof(DDS_Security_Property_t)); + memset(seq->_buffer, 0, size * sizeof(DDS_Security_Property_t)); +} + +static void dds_security_property_deinit(DDS_Security_PropertySeq *seq) +{ + uint32_t i; + for (i = 0; i < seq->_length; i++) + { + ddsrt_free(seq->_buffer[i].name); + ddsrt_free(seq->_buffer[i].value); + } + ddsrt_free(seq->_buffer); +} + +static void fill_participant_qos(DDS_Security_Qos *qos, const char *permission_filename, + const char *governance_filename) +{ + char *permission_uri; + char *governance_uri; + + ddsrt_asprintf(&permission_uri, "file:%s%s", g_path_to_etc_dir, permission_filename); + ddsrt_asprintf(&governance_uri, "file:%s%s", g_path_to_etc_dir, governance_filename); + + memset(qos, 0, sizeof(*qos)); + dds_security_property_init(&qos->property.value, 6); + qos->property.value._buffer[0].name = ddsrt_strdup(PROPERTY_IDENTITY_CERT); + qos->property.value._buffer[0].value = ddsrt_strdup(IDENTITY_CERTIFICATE); + qos->property.value._buffer[1].name = ddsrt_strdup(PROPERTY_IDENTITY_CA); + qos->property.value._buffer[1].value = ddsrt_strdup(IDENTITY_CA); + qos->property.value._buffer[2].name = ddsrt_strdup(PROPERTY_PRIVATE_KEY); + qos->property.value._buffer[2].value = ddsrt_strdup(PRIVATE_KEY); + qos->property.value._buffer[3].name = ddsrt_strdup(PROPERTY_PERMISSIONS_CA); + qos->property.value._buffer[3].value = ddsrt_strdup(PERMISSIONS_CA); + qos->property.value._buffer[4].name = ddsrt_strdup(PROPERTY_PERMISSIONS); + qos->property.value._buffer[4].value = ddsrt_strdup(permission_uri); + qos->property.value._buffer[5].name = ddsrt_strdup(PROPERTY_GOVERNANCE); + qos->property.value._buffer[5].value = ddsrt_strdup(governance_uri); + + ddsrt_free(permission_uri); + ddsrt_free(governance_uri); +} + +static bool create_local_identity(DDS_Security_DomainId domain_id, const char *governance_file) +{ + DDS_Security_ValidationResult_t result; + DDS_Security_Qos participant_qos; + DDS_Security_GUID_t candidate_participant_guid; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_GuidPrefix_t prefix = {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb}; + DDS_Security_EntityId_t entityId = {{0xb0, 0xb1, 0xb2}, 0x1}; + + memset(&local_participant_guid, 0, sizeof(local_participant_guid)); + memcpy(&candidate_participant_guid.prefix, &prefix, sizeof(prefix)); + memcpy(&candidate_participant_guid.entityId, &entityId, sizeof(entityId)); + + fill_participant_qos(&participant_qos, "Test_Permissions_ok.p7s", governance_file); + + /* Now call the function. */ + result = auth->validate_local_identity( + auth, + &local_identity_handle, + &local_participant_guid, + domain_id, + &participant_qos, + &candidate_participant_guid, + &exception); + + if (result != DDS_SECURITY_VALIDATION_OK) + { + printf("[ERROR] validate_local_identity_failed: %s\n", exception.message ? exception.message : "Error message missing"); + return false; + } + + local_permissions_handle = access_control->validate_local_permissions( + access_control, + auth, + local_identity_handle, + domain_id, + &participant_qos, + &exception); + + if (local_permissions_handle == DDS_SECURITY_HANDLE_NIL) + { + printf("[ERROR] validate_local_identity_failed: %s\n", exception.message ? exception.message : "Error message missing"); + return false; + } + + dds_security_property_deinit(&participant_qos.property.value); + + return true; +} + +static void clear_local_identity(void) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_boolean success; + + if (local_identity_handle != DDS_SECURITY_HANDLE_NIL) + { + success = auth->return_identity_handle(auth, local_identity_handle, &exception); + if (!success) + { + printf("return_identity_handle failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + reset_exception(&exception); + } + + if (local_permissions_handle != DDS_SECURITY_HANDLE_NIL) + { + success = access_control->return_permissions_handle(access_control, local_permissions_handle, &exception); + if (!success) + { + printf("return_permissions_handle failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + reset_exception(&exception); + } + + local_identity_handle = DDS_SECURITY_HANDLE_NIL; + local_permissions_handle = DDS_SECURITY_HANDLE_NIL; +} + +static void set_path_to_etc_dir(void) +{ + ddsrt_asprintf(&g_path_to_etc_dir, "%s%s", CONFIG_ENV_TESTS_DIR, RELATIVE_PATH_TO_ETC_DIR); +} + +static DDS_Security_PluginEndpointSecurityAttributesMask get_plugin_endpoint_security_attributes_mask(DDS_Security_boolean is_payload_encrypted, DDS_Security_boolean is_submessage_encrypted, DDS_Security_boolean is_submessage_origin_authenticated) +{ + DDS_Security_PluginEndpointSecurityAttributesMask mask = DDS_SECURITY_ENDPOINT_ATTRIBUTES_FLAG_IS_VALID; + if (is_submessage_encrypted) + mask |= DDS_SECURITY_PLUGIN_ENDPOINT_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ENCRYPTED; + if (is_payload_encrypted) + mask |= DDS_SECURITY_PLUGIN_ENDPOINT_ATTRIBUTES_FLAG_IS_PAYLOAD_ENCRYPTED; + if (is_submessage_origin_authenticated) + mask |= DDS_SECURITY_PLUGIN_ENDPOINT_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ORIGIN_AUTHENTICATED; + return mask; +} + +static void suite_get_xxx_sec_attributes_init(void) +{ + set_path_to_etc_dir(); + + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTSECURE].is_read_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPUBLICATIONSSECURE].is_read_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSSUBSCRIPTIONSSECURE].is_read_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTMESSAGESECURE].is_read_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTSTATELESSMESSAGE].is_read_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTVOLATILEMESSAGESECURE].is_read_protected = false; + + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTSECURE].is_write_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPUBLICATIONSSECURE].is_write_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSSUBSCRIPTIONSSECURE].is_write_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTMESSAGESECURE].is_write_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTSTATELESSMESSAGE].is_write_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTVOLATILEMESSAGESECURE].is_write_protected = false; + + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTSECURE].is_payload_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPUBLICATIONSSECURE].is_payload_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSSUBSCRIPTIONSSECURE].is_payload_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTMESSAGESECURE].is_payload_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTSTATELESSMESSAGE].is_payload_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTVOLATILEMESSAGESECURE].is_payload_protected = false; + + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTSECURE].is_key_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPUBLICATIONSSECURE].is_key_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSSUBSCRIPTIONSSECURE].is_key_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTMESSAGESECURE].is_key_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTSTATELESSMESSAGE].is_key_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTVOLATILEMESSAGESECURE].is_key_protected = false; + + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTSECURE].is_submessage_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPUBLICATIONSSECURE].is_submessage_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSSUBSCRIPTIONSSECURE].is_submessage_protected = + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTMESSAGESECURE].is_submessage_protected = true; + + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTSTATELESSMESSAGE].is_submessage_protected = false; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPSPARTICIPANTVOLATILEMESSAGESECURE].is_submessage_protected = true; + + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_KINEMATICS].is_read_protected = true; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_KINEMATICS].is_write_protected = false; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_KINEMATICS].is_discovery_protected = true; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_KINEMATICS].is_liveliness_protected = true; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_KINEMATICS].is_submessage_protected = false; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_KINEMATICS].is_payload_protected = false; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_KINEMATICS].is_key_protected = false; + + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_KINEMATICS].plugin_endpoint_attributes = + get_plugin_endpoint_security_attributes_mask(false, false, false); + + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_OWNSHIPDATA].is_read_protected = false; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_OWNSHIPDATA].is_write_protected = true; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_OWNSHIPDATA].is_discovery_protected = false; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_OWNSHIPDATA].is_liveliness_protected = false; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_OWNSHIPDATA].is_submessage_protected = true; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_OWNSHIPDATA].is_payload_protected = true; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_OWNSHIPDATA].is_key_protected = true; + + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_OWNSHIPDATA].plugin_endpoint_attributes = + get_plugin_endpoint_security_attributes_mask(true, false, false); + + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_SHAPE].is_read_protected = false; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_SHAPE].is_write_protected = false; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_SHAPE].is_discovery_protected = true; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_SHAPE].is_liveliness_protected = true; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_SHAPE].is_submessage_protected = true; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_SHAPE].is_payload_protected = true; + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_SHAPE].is_key_protected = true; + + ATTRIBUTE_CHECKLIST[SEC_TOPIC_DCPS_SHAPE].plugin_endpoint_attributes = + get_plugin_endpoint_security_attributes_mask(true, true, true); +} + +static void suite_get_xxx_sec_attributes_fini(void) +{ + ddsrt_free(g_path_to_etc_dir); +} + +static bool plugins_init(void) +{ + /* Checking AccessControl, but needing Authentication to setup local identity. */ + plugins = load_plugins(&access_control, &auth, NULL /* Cryptograpy */); + return plugins ? true : false; +} + +static void plugins_fini(void) +{ + unload_plugins(plugins); +} + +static bool +verify_endpoint_attributes(SEC_TOPIC_TYPE topic_type, DDS_Security_EndpointSecurityAttributes *attributes) +{ + bool result = true; + if (attributes->is_read_protected != ATTRIBUTE_CHECKLIST[topic_type].is_read_protected || + attributes->is_write_protected != ATTRIBUTE_CHECKLIST[topic_type].is_write_protected || + attributes->is_submessage_protected != ATTRIBUTE_CHECKLIST[topic_type].is_submessage_protected || + attributes->is_payload_protected != ATTRIBUTE_CHECKLIST[topic_type].is_payload_protected || + attributes->is_key_protected != ATTRIBUTE_CHECKLIST[topic_type].is_key_protected) + { + + result = false; + } + if (topic_type == SEC_TOPIC_DCPS_KINEMATICS || topic_type == SEC_TOPIC_DCPS_SHAPE) + { + if (attributes->is_discovery_protected != ATTRIBUTE_CHECKLIST[topic_type].is_discovery_protected || + attributes->is_liveliness_protected != ATTRIBUTE_CHECKLIST[topic_type].is_liveliness_protected || + attributes->plugin_endpoint_attributes != ATTRIBUTE_CHECKLIST[topic_type].plugin_endpoint_attributes) + { + result = false; + } + } + + if (!result) + { + printf("Invalid attribute for Topic: %s\n", TOPIC_NAMES[topic_type]); + printf("is_read_protected: EXPECTED: %d ACTUAL: %d\n" + "is_write_protected: EXPECTED: %d ACTUAL: %d\n" + "is_discovery_protected: EXPECTED: %d ACTUAL: %d\n" + "is_liveliness_protected: EXPECTED: %d ACTUAL: %d\n" + "is_submessage_protected: EXPECTED: %d ACTUAL: %d\n" + "is_payload_protected: EXPECTED: %d ACTUAL: %d\n" + "is_key_protected: EXPECTED: %d ACTUAL: %d\n", + ATTRIBUTE_CHECKLIST[topic_type].is_read_protected, attributes->is_read_protected, + ATTRIBUTE_CHECKLIST[topic_type].is_write_protected, attributes->is_write_protected, + ATTRIBUTE_CHECKLIST[topic_type].is_discovery_protected, attributes->is_discovery_protected, + ATTRIBUTE_CHECKLIST[topic_type].is_liveliness_protected, attributes->is_liveliness_protected, + ATTRIBUTE_CHECKLIST[topic_type].is_submessage_protected, attributes->is_submessage_protected, + ATTRIBUTE_CHECKLIST[topic_type].is_payload_protected, attributes->is_payload_protected, + ATTRIBUTE_CHECKLIST[topic_type].is_key_protected, attributes->is_key_protected); + } + + return result; +} + +static bool verify_topic_attributes(SEC_TOPIC_TYPE topic_type, DDS_Security_TopicSecurityAttributes *attributes) +{ + bool result = true; + if (attributes->is_read_protected != ATTRIBUTE_CHECKLIST[topic_type].is_read_protected || + attributes->is_write_protected != ATTRIBUTE_CHECKLIST[topic_type].is_write_protected || + attributes->is_discovery_protected != ATTRIBUTE_CHECKLIST[topic_type].is_discovery_protected || + attributes->is_liveliness_protected != ATTRIBUTE_CHECKLIST[topic_type].is_liveliness_protected) + { + result = false; + } + + if (!result) + { + printf("Invalid attribute for Topic: %s\n", TOPIC_NAMES[topic_type]); + printf("is_read_protected: EXPECTED: %d ACTUAL: %d\n" + "is_write_protected: EXPECTED: %d ACTUAL: %d\n" + "is_discovery_protected: EXPECTED: %d ACTUAL: %d\n" + "is_liveliness_protected: EXPECTED: %d ACTUAL: %d\n", + ATTRIBUTE_CHECKLIST[topic_type].is_read_protected, attributes->is_read_protected, + ATTRIBUTE_CHECKLIST[topic_type].is_write_protected, attributes->is_write_protected, + ATTRIBUTE_CHECKLIST[topic_type].is_discovery_protected, attributes->is_discovery_protected, + ATTRIBUTE_CHECKLIST[topic_type].is_liveliness_protected, attributes->is_liveliness_protected); + } + + return result; +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, participant_happy_day, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_ParticipantSecurityAttributes attributes; + bool result; + + result = plugins_init(); + CU_ASSERT_FATAL(result); + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(access_control->get_participant_sec_attributes != NULL); + + result = create_local_identity(0, "Test_Governance_full.p7s"); + CU_ASSERT_FATAL(result); + + memset(&attributes, 0, sizeof(attributes)); + + result = access_control->get_participant_sec_attributes( + access_control, + local_permissions_handle, + &attributes, + &exception); + CU_ASSERT(result); + + /* + * Expect these values based on these options, which is the 1st domain rule + * in the Test_Governance_full.p7s (selected because of domain id 0): + * + * false + * true + * SIGN_WITH_ORIGIN_AUTHENTICATION + * ENCRYPT + * ENCRYPT_WITH_ORIGIN_AUTHENTICATION + */ + CU_ASSERT(attributes.allow_unauthenticated_participants == false); + CU_ASSERT(attributes.is_access_protected == true); + CU_ASSERT(attributes.is_discovery_protected == true); + CU_ASSERT(attributes.is_liveliness_protected == true); + CU_ASSERT(attributes.is_rtps_protected == true); + CU_ASSERT((attributes.plugin_participant_attributes & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_RTPS_ENCRYPTED) == DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_RTPS_ENCRYPTED); + CU_ASSERT((attributes.plugin_participant_attributes & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_DISCOVERY_ENCRYPTED) == 0); + CU_ASSERT((attributes.plugin_participant_attributes & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_LIVELINESS_ENCRYPTED) == DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_LIVELINESS_ENCRYPTED); + CU_ASSERT((attributes.plugin_participant_attributes & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_RTPS_AUTHENTICATED) == DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_RTPS_AUTHENTICATED); + CU_ASSERT((attributes.plugin_participant_attributes & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_DISCOVERY_AUTHENTICATED) == DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_DISCOVERY_AUTHENTICATED); + CU_ASSERT((attributes.plugin_participant_attributes & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_LIVELINESS_AUTHENTICATED) == 0); + CU_ASSERT((attributes.plugin_participant_attributes & DDS_SECURITY_PARTICIPANT_ATTRIBUTES_FLAG_IS_VALID) != 0); + + result = access_control->return_participant_sec_attributes( + access_control, + &attributes, + &exception); + CU_ASSERT(result); + + clear_local_identity(); + plugins_fini(); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, datawriter_happy_day, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_PartitionQosPolicy *partition = NULL; + DDS_Security_DataTagQosPolicy data_tag; + DDS_Security_EndpointSecurityAttributes attributes; + bool result; + unsigned i; + + result = plugins_init(); + CU_ASSERT_FATAL(result); + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(access_control->get_datawriter_sec_attributes != NULL); + + result = create_local_identity(0, "Test_Governance_full.p7s"); + CU_ASSERT_FATAL(result); + + memset(&attributes, 0, sizeof(attributes)); + + /*Test for each builtin topics: + "DCPSParticipantsSecure", "DCPSPublicationsSecure", "DCPSSubscriptionsSecure" + "DCPSParticipantMessageSecure", "DCPSParticipantStatelessMessage", "DCPSParticipantVolatileMessageSecure" + and a sample DCPS topic*/ + + /* Now call the function. */ + for (i = SEC_TOPIC_DCPSPARTICIPANTSECURE; i <= SEC_TOPIC_DCPS_SHAPE; ++i) + { + + result = access_control->get_datawriter_sec_attributes( + access_control, + local_permissions_handle, + TOPIC_NAMES[i], + partition, + &data_tag, + &attributes, + &exception); + + CU_ASSERT_FATAL(result); + + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_OK_CODE); + CU_ASSERT_FATAL(verify_endpoint_attributes(i, &attributes)); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + } + + plugins_fini(); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, datawriter_non_existing_topic, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_PartitionQosPolicy *partition = NULL; + DDS_Security_DataTagQosPolicy data_tag; + DDS_Security_EndpointSecurityAttributes attributes; + bool result; + + result = plugins_init(); + CU_ASSERT_FATAL(result); + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(access_control->get_datawriter_sec_attributes != NULL); + + /* use a different domain(30) to get non matching topic result */ + result = create_local_identity(30, "Test_Governance_full.p7s"); + CU_ASSERT_FATAL(result); + + memset(&attributes, 0, sizeof(attributes)); + + /* Now call the function. */ + result = access_control->get_datawriter_sec_attributes( + access_control, + local_permissions_handle, + TOPIC_NAMES[SEC_TOPIC_DCPS_SHAPE], + partition, + &data_tag, + &attributes, + &exception); + + CU_ASSERT_FATAL(!result); + + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_CAN_NOT_FIND_TOPIC_IN_DOMAIN_CODE); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + plugins_fini(); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, datareader_happy_day, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_PartitionQosPolicy *partition = NULL; + DDS_Security_DataTagQosPolicy data_tag; + DDS_Security_EndpointSecurityAttributes attributes; + bool result; + unsigned i; + + result = plugins_init(); + CU_ASSERT_FATAL(result); + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(access_control->get_datareader_sec_attributes != NULL); + + result = create_local_identity(0, "Test_Governance_full.p7s"); + CU_ASSERT_FATAL(result); + + memset(&attributes, 0, sizeof(attributes)); + + /*Test for each builtin topics: + "DCPSParticipantSecure", "DCPSPublicationsSecure", "DCPSSubscriptionsSecure" + "DCPSParticipantMessageSecure", "DCPSParticipantStatelessMessage", "DCPSParticipantVolatileMessageSecure" + and a sample DCPS topic*/ + + /* Now call the function. */ + for (i = SEC_TOPIC_DCPSPARTICIPANTSECURE; i <= SEC_TOPIC_DCPS_SHAPE; ++i) + { + + result = access_control->get_datareader_sec_attributes( + access_control, + local_permissions_handle, + TOPIC_NAMES[i], + partition, + &data_tag, + &attributes, + &exception); + + CU_ASSERT_FATAL(result); + + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_OK_CODE); + CU_ASSERT_FATAL(verify_endpoint_attributes(i, &attributes) == true); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + } + + plugins_fini(); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, datareader_non_existing_topic, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_PartitionQosPolicy *partition = NULL; + DDS_Security_DataTagQosPolicy data_tag; + DDS_Security_EndpointSecurityAttributes attributes; + bool result; + + result = plugins_init(); + CU_ASSERT_FATAL(result); + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(access_control->get_datawriter_sec_attributes != NULL); + + /* use a different domain (30) to get non matching topic result */ + result = create_local_identity(30, "Test_Governance_full.p7s"); + CU_ASSERT_FATAL(result); + + memset(&attributes, 0, sizeof(attributes)); + + result = access_control->get_datareader_sec_attributes( + access_control, + local_permissions_handle, + TOPIC_NAMES[SEC_TOPIC_DCPS_SHAPE], + partition, + &data_tag, + &attributes, + &exception); + + CU_ASSERT_FATAL(!result); + + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_CAN_NOT_FIND_TOPIC_IN_DOMAIN_CODE); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + plugins_fini(); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, participant_invalid_param, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_ParticipantSecurityAttributes attributes; + bool result; + + memset(&attributes, 0, sizeof(attributes)); + + result = plugins_init(); + CU_ASSERT_FATAL(result); + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(access_control->get_participant_sec_attributes != NULL); + + result = access_control->get_participant_sec_attributes( + NULL, + local_permissions_handle, + &attributes, + &exception); + CU_ASSERT(!result); + CU_ASSERT(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + result = access_control->get_participant_sec_attributes( + access_control, + 0, + &attributes, + &exception); + CU_ASSERT(!result); + CU_ASSERT(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + result = access_control->get_participant_sec_attributes( + access_control, + local_permissions_handle, + NULL, + &exception); + CU_ASSERT(!result); + CU_ASSERT(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + result = access_control->get_participant_sec_attributes( + access_control, + local_permissions_handle + 12345, + &attributes, + &exception); + CU_ASSERT(!result); + CU_ASSERT(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + plugins_fini(); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, datareader_invalid_param, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_PartitionQosPolicy *partition = NULL; + DDS_Security_DataTagQosPolicy data_tag; + DDS_Security_EndpointSecurityAttributes attributes; + bool result; + + result = plugins_init(); + CU_ASSERT_FATAL(result); + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(access_control->get_datareader_sec_attributes != NULL); + + memset(&attributes, 0, sizeof(attributes)); + + /* Now call the function. */ + + result = access_control->get_datareader_sec_attributes( + access_control, + local_permissions_handle, + NULL, + partition, + &data_tag, + &attributes, + &exception); + + CU_ASSERT_FATAL(!result); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + result = access_control->get_datareader_sec_attributes( + access_control, + local_permissions_handle, + "", + partition, + &data_tag, + &attributes, + &exception); + + CU_ASSERT_FATAL(!result); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + result = access_control->get_datareader_sec_attributes( + access_control, + local_permissions_handle, + "Shape", + partition, + &data_tag, + NULL, + &exception); + + CU_ASSERT_FATAL(!result); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + result = access_control->get_datareader_sec_attributes( + access_control, + local_permissions_handle + 12345, + "Shape", + partition, + &data_tag, + &attributes, + &exception); + + CU_ASSERT_FATAL(!result); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + plugins_fini(); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, datawriter_invalid_param, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_PartitionQosPolicy *partition = NULL; + DDS_Security_DataTagQosPolicy data_tag; + DDS_Security_EndpointSecurityAttributes attributes; + bool result; + + result = plugins_init(); + CU_ASSERT_FATAL(result); + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(access_control->get_datawriter_sec_attributes != NULL); + + memset(&attributes, 0, sizeof(attributes)); + + /* Now call the function. */ + + result = access_control->get_datawriter_sec_attributes( + access_control, + local_permissions_handle, + NULL, + partition, + &data_tag, + &attributes, + &exception); + + CU_ASSERT_FATAL(!result); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + result = access_control->get_datawriter_sec_attributes( + access_control, + local_permissions_handle, + "", + partition, + &data_tag, + &attributes, + &exception); + + CU_ASSERT_FATAL(!result); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + result = access_control->get_datawriter_sec_attributes( + access_control, + local_permissions_handle, + "Shape", + partition, + &data_tag, + NULL, + &exception); + + CU_ASSERT_FATAL(!result); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + result = access_control->get_datawriter_sec_attributes( + access_control, + local_permissions_handle + 12345, + "Shape", + partition, + &data_tag, + &attributes, + &exception); + + CU_ASSERT_FATAL(!result); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + plugins_fini(); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, topic_happy_day, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_TopicSecurityAttributes attributes; + bool result; + unsigned i; + + result = plugins_init(); + CU_ASSERT_FATAL(result); + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(access_control->get_topic_sec_attributes != NULL); + + result = create_local_identity(0, "Test_Governance_full.p7s"); + CU_ASSERT_FATAL(result); + + memset(&attributes, 0, sizeof(attributes)); + + /*Test for each builtin topics: + "DCPSParticipantsSecure", "DCPSPublicationsSecure", "DCPSSubscriptionsSecure" + "DCPSParticipantMessageSecure", "DCPSParticipantStatelessMessage", "DCPSParticipantVolatileMessageSecure" + and a sample DCPS topic*/ + + /* Now call the function. */ + for (i = SEC_TOPIC_DCPS_KINEMATICS; i <= SEC_TOPIC_DCPS_SHAPE; ++i) + { + + result = access_control->get_topic_sec_attributes( + access_control, + local_permissions_handle, + TOPIC_NAMES[i], + &attributes, + &exception); + + CU_ASSERT_FATAL(result); + + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_OK_CODE); + CU_ASSERT_FATAL(verify_topic_attributes(i, &attributes)); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + } + + plugins_fini(); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, topic_non_existing_topic, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_TopicSecurityAttributes attributes; + bool result; + + result = plugins_init(); + CU_ASSERT_FATAL(result); + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(access_control->get_topic_sec_attributes != NULL); + + result = create_local_identity(30, "Test_Governance_full.p7s"); + CU_ASSERT_FATAL(result); + + memset(&attributes, 0, sizeof(attributes)); + + /*Test for each builtin topics: + "DCPSParticipantsSecure", "DCPSPublicationsSecure", "DCPSSubscriptionsSecure" + "DCPSParticipantMessageSecure", "DCPSParticipantStatelessMessage", "DCPSParticipantVolatileMessageSecure" + and a sample DCPS topic*/ + + /* Now call the function. */ + result = access_control->get_topic_sec_attributes( + access_control, + local_permissions_handle, + TOPIC_NAMES[SEC_TOPIC_DCPS_SHAPE], + &attributes, + &exception); + + CU_ASSERT_FATAL(!result); + + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_CAN_NOT_FIND_TOPIC_IN_DOMAIN_CODE); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + plugins_fini(); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, topic_invalid_param, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_TopicSecurityAttributes attributes; + bool result; + + result = plugins_init(); + CU_ASSERT_FATAL(result); + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(access_control->get_topic_sec_attributes != NULL); + + result = create_local_identity(0, "Test_Governance_full.p7s"); + CU_ASSERT_FATAL(result); + + memset(&attributes, 0, sizeof(attributes)); + + /* Now call the function. */ + + result = access_control->get_topic_sec_attributes( + access_control, + local_permissions_handle, + NULL, + &attributes, + &exception); + + CU_ASSERT_FATAL(!result); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + result = access_control->get_topic_sec_attributes( + access_control, + local_permissions_handle, + "", + &attributes, + &exception); + + CU_ASSERT_FATAL(!result); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + result = access_control->get_topic_sec_attributes( + access_control, + local_permissions_handle, + "Shape", + NULL, + &exception); + + CU_ASSERT_FATAL(!result); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + result = access_control->get_topic_sec_attributes( + access_control, + local_permissions_handle + 12345, + "Shape", + &attributes, + &exception); + + CU_ASSERT_FATAL(!result); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_INVALID_PARAMETER_CODE); + + //reset control values + memset(&attributes, 0, sizeof(attributes)); + reset_exception(&exception); + + plugins_fini(); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, participant_2nd_rule, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_ParticipantSecurityAttributes attributes; + bool result; + + result = plugins_init(); + CU_ASSERT_FATAL(result); + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(access_control->get_participant_sec_attributes != NULL); + + result = create_local_identity(30, "Test_Governance_full.p7s"); + CU_ASSERT_FATAL(result); + + memset(&attributes, 0, sizeof(attributes)); + + result = access_control->get_participant_sec_attributes( + access_control, + local_permissions_handle, + &attributes, + &exception); + CU_ASSERT(result); + + /* + * Expect these values based on these options, which is the 2nd domain rule + * in the Test_Governance_full.p7s (selected because of domain id 30): + * + * 1 + * 0 + * SIGN + * ENCRYPT + * NONE + */ + CU_ASSERT(attributes.allow_unauthenticated_participants == true); + CU_ASSERT(attributes.is_access_protected == false); + CU_ASSERT(attributes.is_discovery_protected == true); + CU_ASSERT(attributes.is_liveliness_protected == true); + CU_ASSERT(attributes.is_rtps_protected == false); + CU_ASSERT((attributes.plugin_participant_attributes & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_RTPS_ENCRYPTED) == + 0); + CU_ASSERT((attributes.plugin_participant_attributes & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_DISCOVERY_ENCRYPTED) == + 0); + CU_ASSERT((attributes.plugin_participant_attributes & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_LIVELINESS_ENCRYPTED) == + DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_LIVELINESS_ENCRYPTED); + CU_ASSERT((attributes.plugin_participant_attributes & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_RTPS_AUTHENTICATED) == + 0); + CU_ASSERT((attributes.plugin_participant_attributes & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_DISCOVERY_AUTHENTICATED) == + 0); + CU_ASSERT((attributes.plugin_participant_attributes & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_LIVELINESS_AUTHENTICATED) == + 0); + + result = access_control->return_participant_sec_attributes( + access_control, + &attributes, + &exception); + CU_ASSERT(result); + + clear_local_identity(); + plugins_fini(); +} + +static void test_liveliness_discovery_participant_attr( + DDS_Security_PermissionsHandle hdl, + bool liveliness_protected, + DDS_Security_unsigned_long liveliness_mask, + bool discovery_protected, + DDS_Security_unsigned_long discovery_mask) +{ + DDS_Security_unsigned_long mask = DDS_SECURITY_PARTICIPANT_ATTRIBUTES_FLAG_IS_VALID | + liveliness_mask | + discovery_mask; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_ParticipantSecurityAttributes attr; + bool result; + + CU_ASSERT_FATAL(access_control->get_participant_sec_attributes != NULL); + + memset(&attr, 0, sizeof(attr)); + + result = access_control->get_participant_sec_attributes( + access_control, + hdl, + &attr, + &exception); + CU_ASSERT(result); + + CU_ASSERT(attr.allow_unauthenticated_participants == false); + CU_ASSERT(attr.is_access_protected == true); + CU_ASSERT(attr.is_discovery_protected == discovery_protected); + CU_ASSERT(attr.is_liveliness_protected == liveliness_protected); + CU_ASSERT(attr.is_rtps_protected == false); + CU_ASSERT(attr.plugin_participant_attributes == mask); + + result = access_control->return_participant_sec_attributes( + access_control, + &attr, + &exception); + CU_ASSERT(result); +} + +static void test_liveliness_discovery_writer_attr( + const char *topic_name, + DDS_Security_PermissionsHandle hdl, + bool liveliness_protected, + bool discovery_protected, + bool submsg_protected, + DDS_Security_unsigned_long submsg_mask) +{ + DDS_Security_unsigned_long mask = DDS_SECURITY_PARTICIPANT_ATTRIBUTES_FLAG_IS_VALID | submsg_mask; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_EndpointSecurityAttributes attr; + DDS_Security_DataTagQosPolicy data_tag; + DDS_Security_PartitionQosPolicy *partition = NULL; + bool result; + + CU_ASSERT_FATAL(access_control->get_datawriter_sec_attributes != NULL); + + memset(&attr, 0, sizeof(attr)); + + result = access_control->get_datawriter_sec_attributes( + access_control, + hdl, + topic_name, + partition, + &data_tag, + &attr, + &exception); + CU_ASSERT_FATAL(result); + + CU_ASSERT(attr.is_read_protected == false); + CU_ASSERT(attr.is_write_protected == false); + CU_ASSERT(attr.is_submessage_protected == submsg_protected); + CU_ASSERT(attr.is_payload_protected == false); + CU_ASSERT(attr.is_key_protected == false); + CU_ASSERT(attr.is_discovery_protected == discovery_protected); + CU_ASSERT(attr.is_liveliness_protected == liveliness_protected); + CU_ASSERT(attr.plugin_endpoint_attributes == mask); + + result = access_control->return_datawriter_sec_attributes( + access_control, + &attr, + &exception); + CU_ASSERT(result); +} + +static void test_liveliness_discovery_reader_attr( + const char *topic_name, + DDS_Security_PermissionsHandle hdl, + bool liveliness_protected, + bool discovery_protected, + bool submsg_protected, + DDS_Security_unsigned_long submsg_mask) +{ + DDS_Security_unsigned_long mask = DDS_SECURITY_PARTICIPANT_ATTRIBUTES_FLAG_IS_VALID | submsg_mask; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_EndpointSecurityAttributes attr; + DDS_Security_DataTagQosPolicy data_tag; + DDS_Security_PartitionQosPolicy *partition = NULL; + bool result; + return; + CU_ASSERT_FATAL(access_control->get_datareader_sec_attributes != NULL); + + memset(&attr, 0, sizeof(attr)); + + result = access_control->get_datareader_sec_attributes( + access_control, + hdl, + topic_name, + partition, + &data_tag, + &attr, + &exception); + CU_ASSERT_FATAL(result); + + CU_ASSERT(attr.is_read_protected == false); + CU_ASSERT(attr.is_write_protected == false); + CU_ASSERT(attr.is_submessage_protected == submsg_protected); + CU_ASSERT(attr.is_payload_protected == false); + CU_ASSERT(attr.is_key_protected == false); + CU_ASSERT(attr.is_discovery_protected == discovery_protected); + CU_ASSERT(attr.is_liveliness_protected == liveliness_protected); + CU_ASSERT(attr.plugin_endpoint_attributes == mask); + + result = access_control->return_datareader_sec_attributes( + access_control, + &attr, + &exception); + CU_ASSERT(result); +} + +static void test_liveliness_discovery_attr( + const char *governance, + bool liveliness_protected, + DDS_Security_unsigned_long liveliness_mask, + bool discovery_protected, + DDS_Security_unsigned_long discovery_mask) +{ + DDS_Security_unsigned_long submsg_liveliness_mask = 0; + DDS_Security_unsigned_long submsg_discovery_mask = 0; + bool result; + + result = plugins_init(); + CU_ASSERT_FATAL(result); + CU_ASSERT_FATAL(access_control != NULL); + + result = create_local_identity(0, governance); + CU_ASSERT_FATAL(result); + + /* For some endpoints, the submsg encryption mask depends on either the + * discovery or liveliness mask. */ + if (liveliness_mask & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_LIVELINESS_ENCRYPTED) + { + submsg_liveliness_mask |= DDS_SECURITY_PLUGIN_ENDPOINT_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ENCRYPTED; + } + if (liveliness_mask & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_LIVELINESS_AUTHENTICATED) + { + submsg_liveliness_mask |= DDS_SECURITY_PLUGIN_ENDPOINT_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ORIGIN_AUTHENTICATED; + } + if (discovery_mask & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_DISCOVERY_ENCRYPTED) + { + submsg_discovery_mask |= DDS_SECURITY_PLUGIN_ENDPOINT_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ENCRYPTED; + } + if (discovery_mask & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_DISCOVERY_AUTHENTICATED) + { + submsg_discovery_mask |= DDS_SECURITY_PLUGIN_ENDPOINT_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ORIGIN_AUTHENTICATED; + } + + /* Participant attributes */ + + test_liveliness_discovery_participant_attr( + local_permissions_handle, + liveliness_protected, + liveliness_mask, + discovery_protected, + discovery_mask); + + /* Writer attributes */ + + /* User topic. */ + test_liveliness_discovery_writer_attr( + "Kinematics", + local_permissions_handle, + liveliness_protected, + discovery_protected, + false /* submsg_protected */, + 0 /* submsg_mask */); + + /* Builtin topic. */ + test_liveliness_discovery_writer_attr( + "DCPSPublication", + local_permissions_handle, + false /* liveliness_protected */, + false /* discovery_protected */, + false /* submsg_protected */, + 0 /* submsg_mask */); + + /* Security (normal) builtin topic. */ + test_liveliness_discovery_writer_attr( + "DCPSPublicationsSecure", + local_permissions_handle, + false /* liveliness_protected */, + false /* discovery_protected */, + discovery_protected /* submsg_protected */, + submsg_discovery_mask /* submsg_mask */); + + /* Security (liveliness affected) builtin topic. */ + test_liveliness_discovery_writer_attr( + "DCPSParticipantMessageSecure", + local_permissions_handle, + false /* liveliness_protected */, + false /* discovery_protected */, + liveliness_protected /* submsg_protected */, + submsg_liveliness_mask /* submsg_mask */); + + /* Reader attributes */ + + /* User topic. */ + test_liveliness_discovery_reader_attr( + "Kinematics", + local_permissions_handle, + liveliness_protected, + discovery_protected, + false /* submsg_protected */, + false /* submsg_mask */); + + /* Builtin topic. */ + test_liveliness_discovery_reader_attr( + "DCPSPublication", + local_permissions_handle, + false /* liveliness_protected */, + false /* discovery_protected */, + false /* submsg_protected */, + 0 /* submsg_mask */); + + /* Security (normal) builtin topic. */ + test_liveliness_discovery_reader_attr( + "DCPSPublicationsSecure", + local_permissions_handle, + false /* liveliness_protected */, + false /* discovery_protected */, + discovery_protected /* submsg_protected */, + submsg_discovery_mask /* submsg_mask */); + + /* Security (liveliness affected) builtin topic. */ + test_liveliness_discovery_reader_attr( + "DCPSParticipantMessageSecure", + local_permissions_handle, + false /* liveliness_protected */, + false /* discovery_protected */, + liveliness_protected /* submsg_protected */, + submsg_liveliness_mask /* submsg_mask */); + + clear_local_identity(); + plugins_fini(); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, liveliness_discovery_clear, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + /* + * Expect these values based on these options, which is the 1st domain rule + * in the Test_Governance_liveliness_discovery_clear.p7s (selected because of domain id 0): + * + * false + * true + * NONE + * NONE + * NONE + * + * + * * + * false + * false + * false + * false + * NONE + * NONE + * + * + */ + test_liveliness_discovery_attr( + "Test_Governance_liveliness_discovery_clear.p7s", + /* liveliness_protected */ + false, + /* liveliness_mask */ + 0, + /* discovery_protected */ + false, + /* discovery_mask */ + 0); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, liveliness_discovery_encrypted, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + /* + * Expect these values based on these options, which is the 1st domain rule + * in the Test_Governance_liveliness_discovery_clear.p7s (selected because of domain id 0): + * + * false + * true + * ENCRYPT + * ENCRYPT + * NONE + * + * + * * + * true + * true + * false + * false + * NONE + * NONE + * + * + */ + test_liveliness_discovery_attr( + "Test_Governance_liveliness_discovery_encrypted.p7s", + /* liveliness_protected */ + true, + /* liveliness_mask */ + DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_LIVELINESS_ENCRYPTED, + /* discovery_protected */ + true, + /* discovery_mask */ + DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_DISCOVERY_ENCRYPTED); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, liveliness_discovery_signed, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + /* + * Expect these values based on these options, which is the 1st domain rule + * in the Test_Governance_liveliness_discovery_clear.p7s (selected because of domain id 0): + * + * false + * true + * SIGN + * SIGN + * NONE + * + * + * * + * true + * true + * false + * false + * NONE + * NONE + * + * + */ + test_liveliness_discovery_attr( + "Test_Governance_liveliness_discovery_signed.p7s", + /* liveliness_protected */ + true, + /* liveliness_mask */ + 0, + /* discovery_protected */ + true, + /* discovery_mask */ + 0); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, liveliness_discovery_encrypted_and_authenticated, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + /* + * Expect these values based on these options, which is the 1st domain rule + * in the Test_Governance_liveliness_discovery_clear.p7s (selected because of domain id 0): + * + * false + * true + * ENCRYPT_WITH_ORIGIN_AUTHENTICATION + * ENCRYPT_WITH_ORIGIN_AUTHENTICATION + * NONE + * + * + * * + * true + * true + * false + * false + * NONE + * NONE + * + * + */ + test_liveliness_discovery_attr( + "Test_Governance_liveliness_discovery_encrypted_and_authenticated.p7s", + /* liveliness_protected */ + true, + /* liveliness_mask */ + DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_LIVELINESS_ENCRYPTED | + DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_LIVELINESS_AUTHENTICATED, + /* discovery_protected */ + true, + /* discovery_mask */ + DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_DISCOVERY_ENCRYPTED | + DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_DISCOVERY_AUTHENTICATED); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, liveliness_discovery_signed_and_authenticated, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + /* + * Expect these values based on these options, which is the 1st domain rule + * in the Test_Governance_liveliness_discovery_clear.p7s (selected because of domain id 0): + * + * false + * true + * SIGN_WITH_ORIGIN_AUTHENTICATION + * SIGN_WITH_ORIGIN_AUTHENTICATION + * NONE + * + * + * * + * true + * true + * false + * false + * NONE + * NONE + * + * + */ + test_liveliness_discovery_attr( + "Test_Governance_liveliness_discovery_signed_and_authenticated.p7s", + /* liveliness_protected */ + true, + /* liveliness_mask */ + DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_LIVELINESS_AUTHENTICATED, + /* discovery_protected */ + true, + /* discovery_mask */ + DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_DISCOVERY_AUTHENTICATED); +} + +CU_Test(ddssec_builtin_get_xxx_sec_attributes, liveliness_discovery_different, .init = suite_get_xxx_sec_attributes_init, .fini = suite_get_xxx_sec_attributes_fini) +{ + /* + * Expect these values based on these options, which is the 1st domain rule + * in the Test_Governance_liveliness_discovery_clear.p7s (selected because of domain id 0): + * + * false + * true + * ENCRYPT + * NONE + * NONE + * + * + * * + * false + * true + * false + * false + * NONE + * NONE + * + * + */ + test_liveliness_discovery_attr( + "Test_Governance_liveliness_discovery_different.p7s", + /* liveliness_protected */ + false, + /* liveliness_mask */ + 0, + /* discovery_protected */ + true, + /* discovery_mask */ + DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_DISCOVERY_ENCRYPTED); +} diff --git a/src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Governance_ok.p7s b/src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Governance_ok.p7s new file mode 100644 index 0000000..c39903f --- /dev/null +++ b/src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Governance_ok.p7s @@ -0,0 +1,114 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----DB94A190D9780A24156FB0E8F1E76B5F" + +This is an S/MIME signed message + +------DB94A190D9780A24156FB0E8F1E76B5F +Content-Type: text/plain + + + + + + + + + 0 + 230 + + + + + false + + + true + + + ENCRYPT + + + ENCRYPT + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + ENCRYPT + + + ENCRYPT + + + + + + +------DB94A190D9780A24156FB0E8F1E76B5F +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGSAYJKoZIhvcNAQcCoIIGOTCCBjUCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCAnswggJ3AgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggeQwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTgwOTEzMDczOTUwWjAvBgkqhkiG9w0BCQQxIgQgXv8DkvlwebXMwHDbNc0/Pc30 +gyG3xWCnwet49TRMWFsweQYJKoZIhvcNAQkPMWwwajALBglghkgBZQMEASowCwYJ +YIZIAWUDBAEWMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAOBggqhkiG9w0DAgIC +AIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwDQYJKoZI +hvcNAQEBBQAEggEANy8t0EFmv5j1n0+mMn2ut3Chu8PSJceC8gd34IiKq79uC1O3 +PbL9xgiJ2vz7QiTEEeNL2q+CG77cXOcHGUWa4nvbggr/9CqLfHEKGQxDfyXlJZfM +8l550xIXRRBOQ7ilOGLD4QJFfbf9XA4rMuRe8WEYN3FleAaYBJag1tMPg1SS6tgA +BBDM9b1kXHU319zYOk6kZFjlbwHv6XO22SEVRUpXrKudAI8hrGvwksF/+W0S/jS5 +NmYtj/1oMGlCGIaA5rs27H9CkgwrzoMQ3MsR98JlwEUSa4PEe8CClsIziOulQxsp +MicBlMWL0rzpBPVfPTE4gZ/kP7hGBDEQlRzVTA== + +------DB94A190D9780A24156FB0E8F1E76B5F-- + diff --git a/src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Permissions_ca.pem b/src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Permissions_ca.pem new file mode 100644 index 0000000..2372ae0 --- /dev/null +++ b/src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Permissions_ca.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV +BAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQKDBZBRExJTksgVGVj +aG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNvbTAgFw0xODA3MzAx +MjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMCTkwxEzARBgNVBAgM +ClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4xFzAV +BgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blIDehV6XCxrnGXusTCD +uFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9wicp3BGSpZZax/TcO +NjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLsDFFC+a0qn2RFh37r +cWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074BRDXVivx+wVD951L +FNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiySogRWAmKhysLQudu +kHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNVHQ4EFgQURWMbWvBK +ZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJvRV1/tyc1R82k0+gw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ysVtvHnk2hpu9yND +LCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9XVh0rGoR/6nHzo3TI +eiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9yghhKHHqNDvSsAL0 +KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbtlLX3QnwVOmaRyzyl +PiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42+OyLqcH1rKT6Xhcs +hjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb6SDB340BFmtgDHbF +HQ== +-----END CERTIFICATE----- diff --git a/src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Permissions_ca_key.pem b/src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Permissions_ca_key.pem new file mode 100644 index 0000000..22fac8b --- /dev/null +++ b/src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Permissions_ca_key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blIDehV6XCxr +nGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9wicp3BGSp +ZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLsDFFC+a0q +n2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074BRDXVivx ++wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiySogRWAmK +hysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABAoIBABWqhMSCr+7Mr3O3 +bIymOr+CT4xWI8S47hmKGFCLTrNsfy7cQZ9PdHkm7Ez+rCx+KwQaTrwz7EM/e8aH +q2zimMn4YXxeS7MFdM+Xvp/Y0BhXMd1j8Nk0x14+WHmQ88YfA4szdrHDekR+6oB6 +5Lc2fAfNbCGdpRksCQWDndrvIOda1swKW1RsGWHPGtSM1qOg09A4CeASqbsxZfdL +9MgI7aJKYnvJrUhqsNZU3fuOrLDNl7/JvdI08nYLnNkEvbDYbdfH0Q/4laKsSJcp +0jM6tPrxbHMDmBEwullVPrVqJX+n6Hvz3E8C9QiZq8NWbJUc5FntLx8ynbiJg6Lb +1w49WxECgYEA8yVky++3v0ZMKZeSeGj3MuKuEJ2q3UdmsKXA+Pyq0rL/hh7r2oUY +dQDs23BIuaHeIZxAGaMeMjoYQBi+G50XfwHZSMqivxX/yYkXxOJfPQvVLDbqCIWS +94qU4/xo50IkCNxpvRwfpKG2ce5YG7jrQkfb5I6TfKUWAaXpmaQnbYsCgYEAxaVn +Hzw3OdY7q6kURSY6a8KqtcuN0lNKeUb68vZemmZ0FNKmyh+xGVFXXlvmJpQgr5Zm +2W2a1C1oPq2DEdvSKt/aTHVIazG9TtFK1WAXpLxmlXlyqWRv+IvdVkph+p/3dIT0 +Ilaglgbndth4xk0c1zqy3g4VlAgWgKKi5owZ/j8CgYEAndsFGbHEJZZKFCannSzo +cEzinT7/kzGr5bt3ES9Y5/n2Euk4TmJignPbUowPaxU/1apPo1VXYVx+Kf7mTZ8r +hfV5T9ze1BhAPGOY3uXo1wU7nLz6LBYsWDHMgEd7A8jZBDe1HmWH1aZ3gHgxE652 +bk2g4T3/WskDBIbmpi0AvAkCgYBKAfFnRMj5IzscwCcS7YmaqD377MiiJQYR+34k +VBSAhDSbR3Wk4dESxd6NOqQndff3R74jVGNRZ99M+PPHUCSWYVQApToEyY81YDFB +TMYNrW5MMjm5LB6xVs3+bcPacOPcAZzY7s8a3mL1oYE339AY16X6eBOkZpLmf/+3 +jGZ/SQKBgQDkyxymL4xJGV8HCDontJZiBStD954GH1AgqEAOdQxU5vW4ySQ7yRoT +ajb8tH052yWW11Mxd0TRW9qbVI0/4/4lR86sODYLFbgrHAMBl7mxJ8Qwi4zdI9Am +FXGkj5SX2bYrf2f0YvCHNUbELTd4mF6kAH0Eg6kHRXLsSbhtWC7D3Q== +-----END RSA PRIVATE KEY----- diff --git a/src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Permissions_listener.p7s b/src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Permissions_listener.p7s new file mode 100644 index 0000000..08434a9 --- /dev/null +++ b/src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Permissions_listener.p7s @@ -0,0 +1,51 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----3900963D3572093F6AEC654A72CAEE5A" + +This is an S/MIME signed message + +------3900963D3572093F6AEC654A72CAEE5A +Content-Type: text/plain + + /C=NL/ST=Some-State/O=Internet Widgits Pty Ltd/CN=CHAM500 cert 2015-09-15T01:00:00 2019-11-18T11:48:49 0 230 * * DENY +------3900963D3572093F6AEC654A72CAEE5A +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGSAYJKoZIhvcNAQcCoIIGOTCCBjUCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCAnswggJ3AgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggeQwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkxMTE4MTE0ODQ4WjAvBgkqhkiG9w0BCQQxIgQgaLNNlFwfVR0PrziT9wCAy5bM +qCZJX9yO3xJgut3/o7EweQYJKoZIhvcNAQkPMWwwajALBglghkgBZQMEASowCwYJ +YIZIAWUDBAEWMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAOBggqhkiG9w0DAgIC +AIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwDQYJKoZI +hvcNAQEBBQAEggEAWCFrUIvdYKBeT0lmpkRdmYJuvdmQ/Ro7k9iyreVofpB1/70B +hVOEeRjrlmhv/TUjSgQyli56wmXFmexcNRzSzpPNycz0gjwP9kX5BMnhAkKd08fC +4rgoirScmNxvxEkj5+wyq7s7rBEJOgVQ9ofwiZXEBVDMVvW2ENZhVF3FyoNulDQe +6BjXkuLw/QrJLWjywPy5naSSda2T7V3+Ssdu5/2vEjXPIJMM+xPOCaqGHJsSb72s +KiP48jZ95Wruvj3QAlpGxDaazWPTgn7tfThYrY3Kgiz5zyZM7FhFyIqxRF/89Ngo +hbu2mWzcXFF7wBLy+CvK5Foajro9t/PzD8uNuA== + +------3900963D3572093F6AEC654A72CAEE5A-- + diff --git a/src/security/builtin_plugins/tests/listeners_access_control/src/listeners_access_control_utests.c b/src/security/builtin_plugins/tests/listeners_access_control/src/listeners_access_control_utests.c new file mode 100644 index 0000000..5f32d09 --- /dev/null +++ b/src/security/builtin_plugins/tests/listeners_access_control/src/listeners_access_control_utests.c @@ -0,0 +1,671 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include +#include + +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/io.h" +#include "dds/ddsrt/misc.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/types.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/core/dds_security_utils.h" +#include "CUnit/CUnit.h" +#include "CUnit/Test.h" +#include "common/src/loader.h" +#include "config_env.h" + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10100000L +#define REMOVE_THREAD_STATE() ERR_remove_thread_state(NULL); +#elif OPENSSL_VERSION_NUMBER < 0x10000000L +#define REMOVE_THREAD_STATE() ERR_remove_state(0); +#else +#define REMOVE_THREAD_STATE() +#endif + +static const char *ACCESS_PERMISSIONS_TOKEN_ID = "DDS:Access:Permissions:1.0"; +static const char *AUTH_PROTOCOL_CLASS_ID = "DDS:Auth:PKI-DH:1.0"; + +static const char *PROPERTY_IDENTITY_CA = "dds.sec.auth.identity_ca"; +static const char *PROPERTY_PRIVATE_KEY = "dds.sec.auth.private_key"; +static const char *PROPERTY_IDENTITY_CERT = "dds.sec.auth.identity_certificate"; +static const char *PROPERTY_PERMISSIONS_CA = "dds.sec.access.permissions_ca"; +static const char *PROPERTY_PERMISSIONS = "dds.sec.access.permissions"; +static const char *PROPERTY_GOVERNANCE = "dds.sec.access.governance"; + +static const char *PROPERTY_PERMISSIONS_CA_SN = "dds.perm_ca.sn"; +static const char *PROPERTY_PERMISSIONS_CA_ALGO = "dds.perm_ca.algo"; +static const char *PROPERTY_C_ID = "c.id"; +static const char *PROPERTY_C_PERM = "c.perm"; + +static const char *SUBJECT_NAME_PERMISSIONS_CA = "C=NL, ST=Some-State, O=ADLINK Technolocy Inc., CN=adlinktech.com"; +static const char *RSA_2048_ALGORITHM_NAME = "RSA-2048"; + +static const char *RELATIVE_PATH_TO_ETC_DIR = "/listeners_access_control/etc/"; +static const char *PERMISSIONS_CA_CERT_FILE = "Test_Permissions_ca.pem"; +static const char *PERMISSIONS_CA_KEY_FILE = "Test_Permissions_ca_key.pem"; +static const char *PERMISSIONS_FILE = "Test_Permissions_listener.p7s"; +static dds_security_access_control_listener ac_listener; + +static const char *identity_certificate = + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIEQTCCAymgAwIBAgIINpuaAAnrQZIwDQYJKoZIhvcNAQELBQAwXzELMAkGA1UE\n" + "BhMCTkwxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp\n" + "ZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAxMPQ0hBTTUwMCByb290IGNhMCAXDTE3MDIy\n" + "MjIyMjIwMFoYDzIyMjIwMjIyMjIyMjAwWjBcMQswCQYDVQQGEwJOTDETMBEGA1UE\n" + "CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk\n" + "MRUwEwYDVQQDEwxDSEFNNTAwIGNlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\n" + "ggEKAoIBAQDCpVhivH/wBIyu74rvQncnSZqKyspN6CvD1pmV9wft5PHhVt9jV79v\n" + "gSub5LADoRHAgFdv9duYgBr17Ob6uRrIY4B18CcrCjhQcC4gjx8y2jl9PeYm+qYD\n" + "3o44FYBrBq0QCnrQgKsb/qX9Z+Mw/VUiw65x68W876LEHQQoEgT4kxSuagwBoVRk\n" + "ePD6fYAKmT4XS3x+O0v+rHESTcsKF6yMadgp7h3eH1b8kJTzSx8JV9Zzq++mxjox\n" + "qhbBVP5nDze2hhSIeCkCvSrx7efkgKS4AQXa5/Z44GiAu1TfXXUqdic9rxwD0edn\n" + "ajNElnZe7sjok/0yuqvH+2hSqpNva/zpAgMBAAGjggEAMIH9MAwGA1UdDwQFAwMH\n" + "/4AwgewGA1UdJQSB5DCB4QYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDAwYI\n" + "KwYBBQUHAwQGCCsGAQUFBwMIBgorBgEEAYI3AgEVBgorBgEEAYI3AgEWBgorBgEE\n" + "AYI3CgMBBgorBgEEAYI3CgMDBgorBgEEAYI3CgMEBglghkgBhvhCBAEGCysGAQQB\n" + "gjcKAwQBBggrBgEFBQcDBQYIKwYBBQUHAwYGCCsGAQUFBwMHBggrBgEFBQgCAgYK\n" + "KwYBBAGCNxQCAgYIKwYBBQUHAwkGCCsGAQUFBwMNBggrBgEFBQcDDgYHKwYBBQID\n" + "BTANBgkqhkiG9w0BAQsFAAOCAQEAawdHy0Xw7nTK2ltp91Ion6fJ7hqYuj///zr7\n" + "Adt6uonpDh/xl3esuwcFimIJrJrHujnGkL0nLddRCikmnzuBMNDWS6yq0/Ckl/YG\n" + "yjNr44dlX24wo+MVAgkj3/8CyWDZ3a8kBg9QT3bs2SqbjmhTrXN1DRyf9S5vJysE\n" + "I7V1gTN66BeKL64hOrAlRVrEu8Ds6TWL6Q/YH+61ViZkoLTeSaPjH4nknaFr4C35\n" + "iji0JhkyfRHRRVPHFnaj25AkxOrSV64qVKoTMjDl5fji5iMGtjm6iJ7q05ml/qDl\n" + "nLotHXemZNvYhbwUmRzbt4Dls9EMH4VRbP85I94nM5TAvtHVNA==\n" + "-----END CERTIFICATE-----\n"; + +static const char *identity_ca = + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIEmTCCA4GgAwIBAgIIZ5gEIUFhO5wwDQYJKoZIhvcNAQELBQAwXzELMAkGA1UE\n" + "BhMCTkwxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp\n" + "ZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAxMPQ0hBTTUwMCByb290IGNhMCAXDTE4MDIx\n" + "MjE1MDUwMFoYDzIyMjIwMjIyMjIyMjAwWjBfMQswCQYDVQQGEwJOTDETMBEGA1UE\n" + "CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk\n" + "MRgwFgYDVQQDEw9DSEFNNTAwIHJvb3QgY2EwggEiMA0GCSqGSIb3DQEBAQUAA4IB\n" + "DwAwggEKAoIBAQC6Fa3TheL+UrdZCp9GhU/2WbneP2t/avUa3muwDttPxeI2XU9k\n" + "ZjBR95mAXme4SPXHk5+YDN319AqIje3oKhzky/ngvKH2GkoJKYxWnuDBfMEHdViz\n" + "2Q9/xso2ZvH50ukwWa0pfx2/EVV1wRxeQcRd/UVfq3KTJizG0M88mOYvGEAw3LFf\n" + "zef7k1aCuOofQmBvLukUudcYpMzfyHFp7lQqU4CcrrR5RtmfiUfrWfdGLea2iPDB\n" + "pJgN8ESOMwEHtOTEBDclYnH9L4t7CHQz+fXXS5IWFsDK9fCMQjnxDsDVeNrNzTYL\n" + "FaZrMg9S6IUQCEsQWsnq5weS8omOpVLUm9klAgMBAAGjggFVMIIBUTAMBgNVHRME\n" + "BTADAQH/MB0GA1UdDgQWBBQg2FZB/j8uWDVnJhjwXkX278znSTAfBgNVHSMEGDAW\n" + "gBQg2FZB/j8uWDVnJhjwXkX278znSTAPBgNVHQ8BAf8EBQMDB/+AMIHvBgNVHSUB\n" + "Af8EgeQwgeEGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwME\n" + "BggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYK\n" + "KwYBBAGCNwoDAwYKKwYBBAGCNwoDBAYJYIZIAYb4QgQBBgsrBgEEAYI3CgMEAQYI\n" + "KwYBBQUHAwUGCCsGAQUFBwMGBggrBgEFBQcDBwYIKwYBBQUIAgIGCisGAQQBgjcU\n" + "AgIGCCsGAQUFBwMJBggrBgEFBQcDDQYIKwYBBQUHAw4GBysGAQUCAwUwDQYJKoZI\n" + "hvcNAQELBQADggEBAKHmwejWRwGE1wf1k2rG8SNRV/neGsZ6Qfqf6co3TpR/Wi1s\n" + "iZDvSeT/rbqNBS7z34xnG88NIUwu00y78e8Mfon31ZZbK4Uo7fla9/D3ukdJqPQC\n" + "LKdbKJjR2kH+KCukY/1rghjJ8/X+t2egBit0LCOdsFCl07Sfksb9kpGUIZSFcYYm\n" + "geqhjhoNwxazzHiw+QWHC5HG9248JIizBmy1aymNWuMnPudhjHAnPcsIlqMVNq3t\n" + "Rv9ap7S8JeCxHVRPJvJeCwXWvW3dW/v3xH52Yn/fqRblN1w9Fxz5NhopKx0gj/Jd\n" + "sw2N4Fk4gaOWEolFpa0bwNw8nAx7moehZpowzfw=\n" + "-----END CERTIFICATE-----\n"; + +static const char *private_key = + "data:,-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEogIBAAKCAQEAwqVYYrx/8ASMru+K70J3J0maisrKTegrw9aZlfcH7eTx4Vbf\n" + "Y1e/b4Erm+SwA6ERwIBXb/XbmIAa9ezm+rkayGOAdfAnKwo4UHAuII8fMto5fT3m\n" + "JvqmA96OOBWAawatEAp60ICrG/6l/WfjMP1VIsOucevFvO+ixB0EKBIE+JMUrmoM\n" + "AaFUZHjw+n2ACpk+F0t8fjtL/qxxEk3LChesjGnYKe4d3h9W/JCU80sfCVfWc6vv\n" + "psY6MaoWwVT+Zw83toYUiHgpAr0q8e3n5ICkuAEF2uf2eOBogLtU3111KnYnPa8c\n" + "A9HnZ2ozRJZ2Xu7I6JP9Mrqrx/toUqqTb2v86QIDAQABAoIBAC1q32DKkx+yMBFx\n" + "m32QiLUGG6VfBC2BixS7MkMnzRXZYgcuehl4FBc0kLRjfB6cqsO8LqrVN1QyMBhK\n" + "GutN3c38SbE7RChqzhEW2+yE+Mao3Nk4ZEecHLiyaYT0n25ZtHAVwep823BAzwJ+\n" + "BykbM45VEpNKbG1VjSktjBa9faNyZiZAEJEjVyla+6R8N4kHV52LbZcLjvJv3IQ2\n" + "iPYRrmMyI5C23qTni0vy7yJbAXBo3CqgSlwie9FARBWT7Puu7F4mF1O1c/SnTysw\n" + "Tm3e5FzgfHipQbnRVn0w4rDprPMKmPxMnvf/Wkw0zVgNadp1Tc1I6Yj525DEQ07i\n" + "2gIn/gECgYEA4jNnY1u2Eu7x3pAQF3dRO0x35boVtuq9iwQk7q+uaZaK4RJRr+0Y\n" + "T68S3bPnfer6SHvcxtST89Bvs/j/Ky4SOaX037UYjFh6T7OIzPl+MzO1yb+VOBT6\n" + "D6FVGEJGp8ZAITU1OfJPeTYViUeEC8tHFGoKUCk50FbB6jOf1oKtv/ECgYEA3EnB\n" + "Y7kSbJJaUuj9ciFUL/pAno86Cim3VjegK1wKgEiyDb610bhoMErovPwfVJbtcttG\n" + "eKJNuwizkRcVbj+vpjDvqqaP5eMxLl6/Nd4haPMJYzGo88Z8NJpwFRNF2KEWjOpQ\n" + "2NEvoCeRtVulCJyka2Tpljzw8cOXkxhPOe2UhHkCgYBo3entj0QO7QXm56T+LAvV\n" + "0PK45xdQEO3EuCwjGAFk5C0IgUSrqeCeeIzniZMltj1IQ1wsNbtNynEu3530t8wt\n" + "O7oVyFBUKGSz9IjUdkpClJOPr6kPMfJoMqRPtdIpz+hFPPSrI6IikKdVWHloOlp+\n" + "pVaYqTQrWT1XRY2xli3VEQKBgGySmZN6Cx+h/oywswIGdUT0VdcQhq2to+QFpJba\n" + "VX6m1cM6hMip2Ag9U3qZ1SNPBBdBBfm9HQybHE3dj713/C2wHuAAGhpXIM1W+20k\n" + "X1knuC/AsSH9aQhQOf/ZMOq1crTfZBuI9q0782/sjGmzMsKPySU4QhUWruVb7OiD\n" + "NVkZAoGAEvihW7G+8/iOE40vGHyBqUeopAAWLciTAUIEwM/Oi3BYfNWNTWF/FWNc\n" + "nMvCZPYigY8C1vO+1iT2Frtd3CIU+f01Q3fJNJoRLlEiKLNZUJRF48OKUqjKSmsi\n" + "w6pucFO40z05YW7utApj4L82rZnOS0pd1tUI1yexqvj0i4ThJfk=\n" + "-----END RSA PRIVATE KEY-----\n"; + +static const char *permissions_ca = /*Test_Permissions_ca.pem */ + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV\n" + "BAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQKDBZBRExJTksgVGVj\n" + "aG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNvbTAgFw0xODA3MzAx\n" + "MjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMCTkwxEzARBgNVBAgM\n" + "ClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4xFzAV\n" + "BgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" + "CgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blIDehV6XCxrnGXusTCD\n" + "uFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9wicp3BGSpZZax/TcO\n" + "NjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLsDFFC+a0qn2RFh37r\n" + "cWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074BRDXVivx+wVD951L\n" + "FNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiySogRWAmKhysLQudu\n" + "kHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNVHQ4EFgQURWMbWvBK\n" + "ZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJvRV1/tyc1R82k0+gw\n" + "DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ysVtvHnk2hpu9yND\n" + "LCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9XVh0rGoR/6nHzo3TI\n" + "eiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9yghhKHHqNDvSsAL0\n" + "KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbtlLX3QnwVOmaRyzyl\n" + "PiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42+OyLqcH1rKT6Xhcs\n" + "hjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb6SDB340BFmtgDHbF\n" + "HQ==\n" + "-----END CERTIFICATE-----\n"; + +#define PERMISSIONS_DOCUMENT " \ + \ + \ + \ + /C=NL/ST=Some-State/O=Internet Widgits Pty Ltd/CN=CHAM500 cert \ + \ + 2015-09-15T01:00:00 \ + PERMISSION_EXPIRY_DATE \ + \ + \ + \ + \ + 0 \ + 230 \ + \ + \ + \ + \ + * \ + \ + \ + \ + \ + \ + * \ + \ + \ + \ + \ + DENY \ + \ + \ + " + +static struct plugins_hdl *plugins = NULL; +static dds_security_authentication *auth = NULL; +static dds_security_access_control *access_control = NULL; +static DDS_Security_IdentityHandle local_identity_handle = DDS_SECURITY_HANDLE_NIL; +static DDS_Security_IdentityHandle remote_identity_handle = DDS_SECURITY_HANDLE_NIL; +static DDS_Security_PermissionsHandle local_permissions_handle = DDS_SECURITY_HANDLE_NIL; +static DDS_Security_PermissionsHandle remote_permissions_handle = DDS_SECURITY_HANDLE_NIL; +static DDS_Security_GUID_t local_participant_guid; +static char *g_path_to_etc_dir = NULL; +static DDS_Security_PermissionsHandle permission_handle_for_callback1 = DDS_SECURITY_HANDLE_NIL; +static DDS_Security_PermissionsHandle permission_handle_for_callback2 = DDS_SECURITY_HANDLE_NIL; +static dds_time_t local_expiry_date; +static dds_time_t remote_expiry_date; + +static void dds_security_property_init(DDS_Security_PropertySeq *seq, DDS_Security_unsigned_long size) +{ + seq->_length = size; + seq->_maximum = size; + seq->_buffer = ddsrt_malloc(size * sizeof(DDS_Security_Property_t)); + memset(seq->_buffer, 0, size * sizeof(DDS_Security_Property_t)); +} + +static void dds_security_property_deinit(DDS_Security_PropertySeq *seq) +{ + uint32_t i; + + for (i = 0; i < seq->_length; i++) + { + ddsrt_free(seq->_buffer[i].name); + ddsrt_free(seq->_buffer[i].value); + } + ddsrt_free(seq->_buffer); +} + +static void reset_exception(DDS_Security_SecurityException *ex) +{ + ex->code = 0; + ex->minor_code = 0; + ddsrt_free(ex->message); + ex->message = NULL; +} + +static void get_future_xsdate(char *str, size_t len, int32_t delta) +{ + time_t rawtime; + struct tm *future; + + /* Get future time. */ + rawtime = time(NULL) + delta; + future = gmtime(&rawtime); + + /* Put the future time in a xsDate format. */ + strftime(str, len, "%Y-%m-%dT%H:%M:%S", future); +} + +static int smime_sign(const char *certificate_file, const char *key_file, const char *data, const char *out_file) +{ + BIO *in = NULL, *out = NULL, *tbio = NULL, *keybio = NULL; + X509 *scert = NULL; + EVP_PKEY *skey = NULL; + PKCS7 *p7 = NULL; + int ret = 1; + int flags = PKCS7_DETACHED | PKCS7_STREAM | PKCS7_TEXT; + + /* Read in signer certificate and private key */ + tbio = BIO_new_file(certificate_file, "r"); + if (!tbio) + goto err; + scert = PEM_read_bio_X509(tbio, NULL, 0, NULL); + + keybio = BIO_new_file(key_file, "r"); + if (!keybio) + goto err; + + skey = PEM_read_bio_PrivateKey(keybio, NULL, 0, NULL); + if (!scert || !skey) + goto err; + + /* Open content being signed */ + in = BIO_new_mem_buf(data, (int)strlen(data)); + if (!in) + goto err; + /* Sign content */ + p7 = PKCS7_sign(scert, skey, NULL, in, flags); + if (!p7) + goto err; + out = BIO_new_file(out_file, "w"); + if (!out) + goto err; + + //if (!(flags & PKCS7_STREAM)) + // BIO_reset(in); + + /* Write out S/MIME message */ + if (!SMIME_write_PKCS7(out, p7, in, flags)) + goto err; + ret = 0; +err: + if (ret) + { + fprintf(stderr, "Error Signing Data\n"); + ERR_print_errors_fp(stderr); + } + if (p7) + PKCS7_free(p7); + if (scert) + X509_free(scert); + if (skey) + EVP_PKEY_free(skey); + if (in) + BIO_free(in); + if (keybio) + BIO_free(keybio); + if (out) + BIO_free(out); + if (tbio) + BIO_free(tbio); + + return ret; +} + +static void fill_participant_qos(DDS_Security_Qos *qos, int32_t permission_expiry, const char *governance_filename) +{ + char *permission_uri; + char *governance_uri; + char *permissions_ca_cert_file; + char *permissions_ca_key_file; + char *permissions_file; + char *permissions_xml_with_expiry; + char permission_expiry_date_str[30]; + + /*get time in future */ + get_future_xsdate(permission_expiry_date_str, 30, permission_expiry); + local_expiry_date = DDS_Security_parse_xml_date(permission_expiry_date_str); + + permissions_xml_with_expiry = ddsrt_str_replace(PERMISSIONS_DOCUMENT, "PERMISSION_EXPIRY_DATE", permission_expiry_date_str, 1); + + ddsrt_asprintf(&permissions_ca_cert_file, "%s%s", g_path_to_etc_dir, PERMISSIONS_CA_CERT_FILE); + ddsrt_asprintf(&permissions_ca_key_file, "%s%s", g_path_to_etc_dir, PERMISSIONS_CA_KEY_FILE); + ddsrt_asprintf(&permissions_file, "%s%s", g_path_to_etc_dir, PERMISSIONS_FILE); + + smime_sign(permissions_ca_cert_file, permissions_ca_key_file, permissions_xml_with_expiry, permissions_file); + + //check sign result + ddsrt_asprintf(&permission_uri, "file:%s", permissions_file); + ddsrt_asprintf(&governance_uri, "file:%s%s", g_path_to_etc_dir, governance_filename); + + memset(qos, 0, sizeof(*qos)); + dds_security_property_init(&qos->property.value, 6); + qos->property.value._buffer[0].name = ddsrt_strdup(PROPERTY_IDENTITY_CERT); + qos->property.value._buffer[0].value = ddsrt_strdup(identity_certificate); + qos->property.value._buffer[1].name = ddsrt_strdup(PROPERTY_IDENTITY_CA); + qos->property.value._buffer[1].value = ddsrt_strdup(identity_ca); + qos->property.value._buffer[2].name = ddsrt_strdup(PROPERTY_PRIVATE_KEY); + qos->property.value._buffer[2].value = ddsrt_strdup(private_key); + qos->property.value._buffer[3].name = ddsrt_strdup(PROPERTY_PERMISSIONS_CA); + qos->property.value._buffer[3].value = ddsrt_strdup(permissions_ca); + qos->property.value._buffer[4].name = ddsrt_strdup(PROPERTY_PERMISSIONS); + qos->property.value._buffer[4].value = ddsrt_strdup(permission_uri); + qos->property.value._buffer[5].name = ddsrt_strdup(PROPERTY_GOVERNANCE); + qos->property.value._buffer[5].value = ddsrt_strdup(governance_uri); + + ddsrt_free(permission_uri); + ddsrt_free(governance_uri); + ddsrt_free(permissions_xml_with_expiry); + ddsrt_free(permissions_ca_key_file); + ddsrt_free(permissions_ca_cert_file); + ddsrt_free(permissions_file); +} + +static void fill_permissions_token(DDS_Security_PermissionsToken *token) +{ + memset(token, 0, sizeof(DDS_Security_PermissionsToken)); + + token->class_id = ddsrt_strdup(ACCESS_PERMISSIONS_TOKEN_ID); + token->properties._length = token->properties._maximum = 2; + token->properties._buffer = DDS_Security_PropertySeq_allocbuf(2); + + token->properties._buffer[0].name = ddsrt_strdup(PROPERTY_PERMISSIONS_CA_SN); + token->properties._buffer[0].value = ddsrt_strdup(SUBJECT_NAME_PERMISSIONS_CA); + + token->properties._buffer[1].name = ddsrt_strdup(PROPERTY_PERMISSIONS_CA_ALGO); + token->properties._buffer[1].value = ddsrt_strdup(RSA_2048_ALGORITHM_NAME); +} + +static int fill_peer_credential_token(DDS_Security_AuthenticatedPeerCredentialToken *token, int32_t permission_expiry) +{ + int result = 1; + char *permission_data; + + char *permissions_ca_cert_file; + char *permissions_ca_key_file; + char *permissions_file; + char *permissions_xml_with_expiry; + char permission_expiry_date_str[30]; + + /*get time in future */ + get_future_xsdate(permission_expiry_date_str, 30, permission_expiry); + remote_expiry_date = DDS_Security_parse_xml_date(permission_expiry_date_str); + permissions_xml_with_expiry = ddsrt_str_replace(PERMISSIONS_DOCUMENT, "PERMISSION_EXPIRY_DATE", permission_expiry_date_str, 1); + + ddsrt_asprintf(permissions_ca_cert_file, "%s%s", g_path_to_etc_dir, PERMISSIONS_CA_CERT_FILE); + ddsrt_asprintf(permissions_ca_key_file, "%s%s", g_path_to_etc_dir, PERMISSIONS_CA_KEY_FILE); + ddsrt_asprintf(permissions_file, "%s%s", g_path_to_etc_dir, PERMISSIONS_FILE); + + smime_sign(permissions_ca_cert_file, permissions_ca_key_file, permissions_xml_with_expiry, permissions_file); + + memset(token, 0, sizeof(DDS_Security_AuthenticatedPeerCredentialToken)); + + permission_data = load_file_contents(permissions_file); + + if (permission_data) + { + token->class_id = ddsrt_strdup(AUTH_PROTOCOL_CLASS_ID); + token->properties._length = token->properties._maximum = 2; + token->properties._buffer = DDS_Security_PropertySeq_allocbuf(2); + + token->properties._buffer[0].name = ddsrt_strdup(PROPERTY_C_ID); + token->properties._buffer[0].value = ddsrt_strdup(&identity_certificate[6]); + + token->properties._buffer[1].name = ddsrt_strdup(PROPERTY_C_PERM); + token->properties._buffer[1].value = permission_data; + } + else + { + ddsrt_free(permission_data); + result = 0; + } + + ddsrt_free(permissions_xml_with_expiry); + ddsrt_free(permissions_ca_key_file); + ddsrt_free(permissions_ca_cert_file); + ddsrt_free(permissions_file); + return result; +} + +static DDS_Security_long +validate_local_identity_and_permissions(int32_t permission_expiry) +{ + DDS_Security_long res = DDS_SECURITY_ERR_OK_CODE; + DDS_Security_ValidationResult_t result; + DDS_Security_DomainId domain_id = 0; + DDS_Security_Qos participant_qos; + DDS_Security_GUID_t candidate_participant_guid; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_GuidPrefix_t prefix = {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb}; + DDS_Security_EntityId_t entityId = {{0xb0, 0xb1, 0xb2}, 0x1}; + + memset(&local_participant_guid, 0, sizeof(local_participant_guid)); + memcpy(&candidate_participant_guid.prefix, &prefix, sizeof(prefix)); + memcpy(&candidate_participant_guid.entityId, &entityId, sizeof(entityId)); + + fill_participant_qos(&participant_qos, permission_expiry, "Test_Governance_ok.p7s"); + + /* Now call the function. */ + result = auth->validate_local_identity( + auth, + &local_identity_handle, + &local_participant_guid, + domain_id, + &participant_qos, + &candidate_participant_guid, + &exception); + + if (result != DDS_SECURITY_VALIDATION_OK) + { + res = DDS_SECURITY_ERR_UNDEFINED_CODE; + printf("validate_local_identity_failed: (%d) %s\n", (int)exception.code, exception.message ? exception.message : "Error message missing"); + } + + reset_exception(&exception); + + if (res == 0) + { + local_permissions_handle = access_control->validate_local_permissions( + access_control, + auth, + local_identity_handle, + 0, + &participant_qos, + &exception); + + if (local_permissions_handle == DDS_SECURITY_HANDLE_NIL) + { + printf("validate_local_permissions_failed: (%d) %s\n", (int)exception.code, exception.message ? exception.message : "Error message missing"); + if (exception.code == DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_CODE) + /* This can happen on very slow platforms or when doing a valgrind run. */ + res = DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_CODE; + else + res = DDS_SECURITY_ERR_UNDEFINED_CODE; + } + } + + dds_security_property_deinit(&participant_qos.property.value); + ddsrt_free(exception.message); + + return res; +} + +static void clear_local_identity_and_permissions(void) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_boolean success; + + if (local_permissions_handle != DDS_SECURITY_HANDLE_NIL) + { + success = access_control->return_permissions_handle(access_control, local_permissions_handle, &exception); + if (!success) + printf("return_permission_handle failed: %s\n", exception.message ? exception.message : "Error message missing"); + reset_exception(&exception); + } + + if (local_identity_handle != DDS_SECURITY_HANDLE_NIL) + { + success = auth->return_identity_handle(auth, local_identity_handle, &exception); + if (!success) + printf("return_identity_handle failed: %s\n", exception.message ? exception.message : "Error message missing"); + reset_exception(&exception); + } +} + +static void set_path_to_etc_dir(void) +{ + ddsrt_asprintf(&g_path_to_etc_dir, "%s%s", CONFIG_ENV_TESTS_DIR, RELATIVE_PATH_TO_ETC_DIR); +} + +static void suite_listeners_access_control_init(void) +{ + plugins = load_plugins(&access_control, &auth, NULL /* Cryptograpy */); + CU_ASSERT_FATAL(plugins != NULL); + set_path_to_etc_dir(); + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); +} + +static void suite_listeners_access_control_fini(void) +{ + unload_plugins(plugins); + ddsrt_free(g_path_to_etc_dir); + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); + REMOVE_THREAD_STATE(); + ERR_free_strings(); +} + +static DDS_Security_boolean on_revoke_permissions_cb(dds_security_access_control_listener *instance, const dds_security_access_control *plugin, const DDS_Security_PermissionsHandle handle) +{ + DDSRT_UNUSED_ARG(instance); + DDSRT_UNUSED_ARG(plugin); + if (permission_handle_for_callback1 == DDS_SECURITY_HANDLE_NIL) + permission_handle_for_callback1 = handle; + else if (permission_handle_for_callback2 == DDS_SECURITY_HANDLE_NIL) + permission_handle_for_callback2 = handle; + printf("Listener called for handle: %lld Local:%ld Remote:%ld\n", (long long)handle, local_permissions_handle, remote_permissions_handle); + return true; +} + +CU_Test(ddssec_builtin_listeners_access_control, local_2secs, .init = suite_listeners_access_control_init, .fini = suite_listeners_access_control_fini) +{ + DDS_Security_PermissionsHandle result; + DDS_Security_PermissionsToken permissions_token; + DDS_Security_AuthenticatedPeerCredentialToken credential_token; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_long valid; + int r; + dds_duration_t time_left = DDS_MSECS(10000); + bool local_expired = false; + bool remote_expired = false; + + local_expiry_date = 0; + remote_expiry_date = 0; + + ac_listener.on_revoke_permissions = &on_revoke_permissions_cb; + + valid = validate_local_identity_and_permissions(2); + if (valid == DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_CODE) + { + /* This can happen on very slow platforms or when doing a valgrind run. + * Just take our losses and quit, simulating a success. */ + return; + } + CU_ASSERT_FATAL(valid == DDS_SECURITY_ERR_OK_CODE); + + /* Check if we actually have validate_remote_permissions function. */ + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(local_identity_handle != DDS_SECURITY_HANDLE_NIL); + CU_ASSERT_FATAL(access_control->validate_remote_permissions != NULL); + CU_ASSERT_FATAL(access_control->return_permissions_handle != NULL); + + fill_permissions_token(&permissions_token); + r = fill_peer_credential_token(&credential_token, 1); + CU_ASSERT_FATAL(r); + + remote_identity_handle++; + + access_control->set_listener(access_control, &ac_listener, &exception); + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + if (result == 0) + { + printf("validate_remote_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + /* Expiry can happen on very slow platforms or when doing a valgrind run. + * Just take our losses and quit, simulating a success. */ + CU_ASSERT(exception.code == DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_CODE); + goto end; + } + + remote_permissions_handle = result; + + reset_exception(&exception); + + while (time_left > 0 && (!local_expired || !remote_expired)) + { + /* Normally, it is expected that the remote expiry is triggered before the + * local one. However, that can change on slow platforms. */ + if (remote_expiry_date < local_expiry_date) + { + if (permission_handle_for_callback1 == remote_permissions_handle) + { + remote_expired = true; + } + if (permission_handle_for_callback2 == local_permissions_handle) + { + local_expired = true; + } + } + else + { + if (permission_handle_for_callback2 == remote_permissions_handle) + { + remote_expired = true; + } + if (permission_handle_for_callback1 == local_permissions_handle) + { + local_expired = true; + } + } + + dds_sleepfor(DDS_MSECS(100)); + time_left -= DDS_MSECS(100); + } + + CU_ASSERT(local_expired); + CU_ASSERT(remote_expired); + + access_control->return_permissions_handle(access_control, result, &exception); + +end: + reset_exception(&exception); + + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&permissions_token); + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&credential_token); + + clear_local_identity_and_permissions(); +} diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_File_empty.txt b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_File_empty.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_File_text.txt b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_File_text.txt new file mode 100644 index 0000000..c1991b0 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_File_text.txt @@ -0,0 +1,3 @@ +This is just a file to see how the Security Plugin +reacts when it receives a file that doesn't contain +expected content, but just some text. diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_check_create_participant.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_check_create_participant.p7s new file mode 100644 index 0000000..8992b03 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_check_create_participant.p7s @@ -0,0 +1,199 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----988CFBB47A225358D7A5B33A4CA9AD64" + +This is an S/MIME signed message + +------988CFBB47A225358D7A5B33A4CA9AD64 +Content-Type: text/plain + + + + + + + + 1 + + 1 + NONE + SIGN + ENCRYPT + + TRUE + + + + FALSE + ENCRYPT + TRUE + SIGN + Topic1 + + true + + true + + + FALSE + ENCRYPT + TRUE + SIGN + Topic2 + + true + + true + + + + + + + 2 + + 1 + NONE + SIGN + ENCRYPT + + TRUE + + + + FALSE + ENCRYPT + TRUE + SIGN + Topic1 + + true + + false + + + FALSE + ENCRYPT + TRUE + SIGN + Topic2 + + true + + true + + + + + + + 3 + + 1 + NONE + SIGN + ENCRYPT + + TRUE + + + + FALSE + ENCRYPT + TRUE + SIGN + Topic1 + + false + + false + + + FALSE + ENCRYPT + TRUE + SIGN + Topic2 + + false + + false + + + + + + + 4 + + 1 + NONE + SIGN + ENCRYPT + + FALSE + + + + FALSE + ENCRYPT + TRUE + SIGN + Topic1 + + true + + true + + + + + + +------988CFBB47A225358D7A5B33A4CA9AD64 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAyWjAvBgkqhkiG9w0BCQQxIgQg9ZheySVcKVr9eNKQTeuBdR0z +Cbgnm4HbSvO8/V0a7CAwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBACn66JQOghwlIQUMDQ0s +vMCGMl7OcZtxDdNQ2BYajufv+JGaf46xP6TWk4+c+bDq+9XTDFoTr/KY2XP7vKVD +RSAm9nlqChzzsKF/7yYdzOP8hILF644PT837mP+E5ss4EYPoPByQLVPWr1B52xWB +N/kixmZcMxe4btXqE8LGlSsPNioniZsDBRlDOcdFjxTL/3Ksgv6fX2gSEJgYVBH/ +xZ+Cpf4TsdtVDrQwUynck1+BogRtcofnkBFuKozqzwvzDQoLfW2fMnct5Jd7KPwM +6kN/bRvOEMGYTKYRgfJVdM4rZqbfdRlVnCj+pza4dIHmf5BDSOlsbRqWyJPRmQ8S +JkM= + +------988CFBB47A225358D7A5B33A4CA9AD64-- + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_check_create_participant.xml b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_check_create_participant.xml new file mode 100644 index 0000000..37749a3 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_check_create_participant.xml @@ -0,0 +1,147 @@ + + + + + + + 1 + + 1 + NONE + SIGN + ENCRYPT + + TRUE + + + + FALSE + ENCRYPT + TRUE + SIGN + Topic1 + + true + + true + + + FALSE + ENCRYPT + TRUE + SIGN + Topic2 + + true + + true + + + + + + + 2 + + 1 + NONE + SIGN + ENCRYPT + + TRUE + + + + FALSE + ENCRYPT + TRUE + SIGN + Topic1 + + true + + false + + + FALSE + ENCRYPT + TRUE + SIGN + Topic2 + + true + + true + + + + + + + 3 + + 1 + NONE + SIGN + ENCRYPT + + TRUE + + + + FALSE + ENCRYPT + TRUE + SIGN + Topic1 + + false + + false + + + FALSE + ENCRYPT + TRUE + SIGN + Topic2 + + false + + false + + + + + + + 4 + + 1 + NONE + SIGN + ENCRYPT + + FALSE + + + + FALSE + ENCRYPT + TRUE + SIGN + Topic1 + + true + + true + + + + + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_full.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_full.p7s new file mode 100644 index 0000000..4ea8fe8 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_full.p7s @@ -0,0 +1,267 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----05DBD6F6E587875751A79EAC78048D60" + +This is an S/MIME signed message + +------05DBD6F6E587875751A79EAC78048D60 +Content-Type: text/plain + + + + + + + + 20 + + 0 + 23 + + + 100 + 120 + + 200 + + + + false + + + TRUE + + + SIGN_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + + + + OwnShip?ata + + + FALSE + + + false + + + false + + + true + + + SIGN + + + ENCRYPT + + + + + Kinematics + + + true + + + true + + + true + + + false + + + NONE + + + NONE + + + + + *other + + + true + + + true + + + true + + + true + + + NONE + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT + + + + + + + + 100 + 120 + + 20 + + 0 + 23 + + 200 + 30 + + + + 1 + + + 0 + + + SIGN + + + ENCRYPT + + + NONE + + + + + OwnShipData + + + true + + + true + + + false + + + false + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT + + + + + + + + +------05DBD6F6E587875751A79EAC78048D60 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQg0GyBZYdNlmQT2Nv1CHrUEB6+ +C0U0yXvpmj5+mlGojPAwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAJXrVHO7KdgYM20uGGNL +P4VRPmYVWoWIkl5/OEzZ8uirs+oGJR7tYLiFl1wzXUzPBB/03qsANmlshDpFgbmV +thTV7AGRg3SXUDa/cG4N9PupE5VRZaVdbcbdH1DfoIZCLLp4HK3HgqUXkH9vnC92 +tdtgzxZOCrQ4A6WbGiBkWr5LtMWg2lnwPp55vrfRoh6u0qVEumD+VQi+Lroo9M1E +659LB2dwEcNb1g1HyoodpKlUSsbGsY/JA7bbNrw/KIGVYcoXfmpgWmtzUjfpkPDj +zVPImqr6jdxP4quGmGWRmrLHPrEYJscJqCwjNTi6naXnAvaE4nxQ4HBgveEodTuP +8tM= + +------05DBD6F6E587875751A79EAC78048D60-- + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_full.xml b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_full.xml new file mode 100644 index 0000000..4ff15ab --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_full.xml @@ -0,0 +1,215 @@ + + + + + + + 20 + + 0 + 23 + + + 100 + 120 + + 200 + + + + false + + + TRUE + + + SIGN_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + + + + OwnShip?ata + + + FALSE + + + false + + + false + + + true + + + SIGN + + + ENCRYPT + + + + + Kinematics + + + true + + + true + + + true + + + false + + + NONE + + + NONE + + + + + *other + + + true + + + true + + + true + + + true + + + NONE + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT + + + + + + + + 100 + 120 + + 20 + + 0 + 23 + + 200 + 30 + + + + 1 + + + 0 + + + SIGN + + + ENCRYPT + + + NONE + + + + + OwnShipData + + + true + + + true + + + false + + + false + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT + + + + + + + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_invalid_data.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_invalid_data.p7s new file mode 100644 index 0000000..ba75bfe --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_invalid_data.p7s @@ -0,0 +1,175 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----1A6607CDB3CA97628720C3874B28523D" + +This is an S/MIME signed message + +------1A6607CDB3CA97628720C3874B28523D +Content-Type: text/plain + + + + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + false + + + TRUE + + + SIGN_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + + + * + + + true + + + true + + + false + + + false + + + ENCRYPT_WITH_ + + + ENCRYPT + + + + + OwnShip?ata + + + FALSE + + + false + + + false + + + true + + + SIGN + + + ENCRYPT + + + + + Kinematics + + + true + + + true + + + true + + + false + + + NONE + + + NONE + + + + + + +------1A6607CDB3CA97628720C3874B28523D +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQg16RVkhnhbWczLVFXDHVD6lPy +G5w7StRkpXgPtz/r+5MwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAJsBPV85r3vm0jr/YWKo +J1j054f+gdqnrfH9kv6dvhg/IAK67mfWDHYUUah6D/1HFJve5KMR8tBu2j770M42 +rDjUBVQADqwWc+9ymiGcIjav9r1+YVTzOCHZnASJyqWPakCwwrdMthb2bB//ASmL +rHOxsJZs68r0ci8ZC4bPbe0m8gAC8lkAvfhIr0/WLO4zhdhVaSrKNKptEjTVGRan +KcjoHAiNOhxWZfwZ+OVEp6Rnax4xcpGK3oyCcg9v8zGKj9rDX917K3VfW9Guo+Px +fZ1u+ukL2GgvzPMdJuU0Uw6mPbWMPeAKbIFwLR9P8iXtKuj2HHqteFVbcyIQXZSE +nRM= + +------1A6607CDB3CA97628720C3874B28523D-- + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_invalid_data.xml b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_invalid_data.xml new file mode 100644 index 0000000..d445705 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_invalid_data.xml @@ -0,0 +1,123 @@ + + + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + false + + + TRUE + + + SIGN_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + + + * + + + true + + + true + + + false + + + false + + + ENCRYPT_WITH_ + + + ENCRYPT + + + + + OwnShip?ata + + + FALSE + + + false + + + false + + + true + + + SIGN + + + ENCRYPT + + + + + Kinematics + + + true + + + true + + + true + + + false + + + NONE + + + NONE + + + + + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_invalid_element.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_invalid_element.p7s new file mode 100644 index 0000000..9a51a3f --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_invalid_element.p7s @@ -0,0 +1,178 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----4B1AFE4A648D807454B86C7DDD6F392C" + +This is an S/MIME signed message + +------4B1AFE4A648D807454B86C7DDD6F392C +Content-Type: text/plain + + + + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + false + + + TRUE + + + SIGN_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT + + Unidentified Flying Object + + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + + + * + + + true + + + true + + + false + + + false + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT + + + + + OwnShip?ata + + + FALSE + + + false + + + false + + + true + + + SIGN + + + ENCRYPT + + + + + Kinematics + + + true + + + true + + + true + + + false + + + NONE + + + NONE + + + + + + +------4B1AFE4A648D807454B86C7DDD6F392C +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgLhPNfJcKb6QszZuyFWmmLGOQ +ZDTY0NBpcqMym1+AijAwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBABwNsFseYbpH+mGslN/g +UY1RNq8f9pFOhTn89NAu94xJgZ2wu5izmSsaEK8K8nrPnxTouD7b5P5w5JQnEVU5 +m2yDD62ZdrlNm51u6VS1JoleHleTEyseagVYlLk+R2FYIH8xfjT0e6jc93qIlm+f +XehwwbCsVUUdy3ViV9APoFP6b5YB+bXe6AtMMTobhEzplqs7GzOFzzC4YuhHSvi2 +sVFXmlHFwOKKIS7he8467breo+SYunv5IttcyqypltydmEcOndCQ2uAWiPvsJIat +DyIkewjrWFL/0l/uTDmk3EUcTmmugVkhykmkfb9subqMHXKbDkcXgZgggR57/9+n +eOU= + +------4B1AFE4A648D807454B86C7DDD6F392C-- + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_invalid_element.xml b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_invalid_element.xml new file mode 100644 index 0000000..81f5ea6 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_invalid_element.xml @@ -0,0 +1,126 @@ + + + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + false + + + TRUE + + + SIGN_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT + + Unidentified Flying Object + + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + + + * + + + true + + + true + + + false + + + false + + + ENCRYPT_WITH_ORIGIN_AUTHENTICATION + + + ENCRYPT + + + + + OwnShip?ata + + + FALSE + + + false + + + false + + + true + + + SIGN + + + ENCRYPT + + + + + Kinematics + + + true + + + true + + + true + + + false + + + NONE + + + NONE + + + + + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_not_signed.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_not_signed.p7s new file mode 100644 index 0000000..30fa20a --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_not_signed.p7s @@ -0,0 +1,62 @@ + + + + + + + + 0 + 230 + + + + + false + + + true + + + ENCRYPT + + + ENCRYPT + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + ENCRYPT + + + ENCRYPT + + + + + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_ok.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_ok.p7s new file mode 100644 index 0000000..c39903f --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_ok.p7s @@ -0,0 +1,114 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----DB94A190D9780A24156FB0E8F1E76B5F" + +This is an S/MIME signed message + +------DB94A190D9780A24156FB0E8F1E76B5F +Content-Type: text/plain + + + + + + + + + 0 + 230 + + + + + false + + + true + + + ENCRYPT + + + ENCRYPT + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + ENCRYPT + + + ENCRYPT + + + + + + +------DB94A190D9780A24156FB0E8F1E76B5F +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGSAYJKoZIhvcNAQcCoIIGOTCCBjUCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCAnswggJ3AgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggeQwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTgwOTEzMDczOTUwWjAvBgkqhkiG9w0BCQQxIgQgXv8DkvlwebXMwHDbNc0/Pc30 +gyG3xWCnwet49TRMWFsweQYJKoZIhvcNAQkPMWwwajALBglghkgBZQMEASowCwYJ +YIZIAWUDBAEWMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAOBggqhkiG9w0DAgIC +AIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwDQYJKoZI +hvcNAQEBBQAEggEANy8t0EFmv5j1n0+mMn2ut3Chu8PSJceC8gd34IiKq79uC1O3 +PbL9xgiJ2vz7QiTEEeNL2q+CG77cXOcHGUWa4nvbggr/9CqLfHEKGQxDfyXlJZfM +8l550xIXRRBOQ7ilOGLD4QJFfbf9XA4rMuRe8WEYN3FleAaYBJag1tMPg1SS6tgA +BBDM9b1kXHU319zYOk6kZFjlbwHv6XO22SEVRUpXrKudAI8hrGvwksF/+W0S/jS5 +NmYtj/1oMGlCGIaA5rs27H9CkgwrzoMQ3MsR98JlwEUSa4PEe8CClsIziOulQxsp +MicBlMWL0rzpBPVfPTE4gZ/kP7hGBDEQlRzVTA== + +------DB94A190D9780A24156FB0E8F1E76B5F-- + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_unknown_ca.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_unknown_ca.p7s new file mode 100644 index 0000000..9f07e40 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Governance_unknown_ca.p7s @@ -0,0 +1,117 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----F38FD3F34A584E774726CA12090D0B48" + +This is an S/MIME signed message + +------F38FD3F34A584E774726CA12090D0B48 +Content-Type: text/plain + + + + + + + + + 0 + 230 + + + + + false + + + true + + + ENCRYPT + + + ENCRYPT + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + ENCRYPT + + + ENCRYPT + + + + + + +------F38FD3F34A584E774726CA12090D0B48 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGywYJKoZIhvcNAQcCoIIGvDCCBrgCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggPKMIIDxjCCAq4CCQCBuTktP0h8BDANBgkqhkiG9w0BAQsFADCB +pDEWMBQGA1UEBwwNTG9jYWxpdHkgTmFtZTEhMB8GA1UECwwYT3JnYW5pemF0aW9u +YWwgVW5pdCBOYW1lMRwwGgYJKoZIhvcNAQkBFg1FbWFpbCBBZGRyZXNzMQswCQYD +VQQGEwJVUzELMAkGA1UECAwCTkoxGjAYBgNVBAoMEUV4YW1wbGUgU2lnbmVyIENB +MRMwEQYDVQQDDApFeGFtcGxlIENBMB4XDTE4MDgxNTA4NTE0MVoXDTQzMDgwOTA4 +NTE0MVowgaQxFjAUBgNVBAcMDUxvY2FsaXR5IE5hbWUxITAfBgNVBAsMGE9yZ2Fu +aXphdGlvbmFsIFVuaXQgTmFtZTEcMBoGCSqGSIb3DQEJARYNRW1haWwgQWRkcmVz +czELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5KMRowGAYDVQQKDBFFeGFtcGxlIFNp +Z25lciBDQTETMBEGA1UEAwwKRXhhbXBsZSBDQTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBALStAQ0yjM2qAWwsOXdX3hiyoZ6DDHWOTNI5LoCZGaN9rUZe +MY0waSxWNQ0ruURgZISeOFkdQTAE81Em+UaZI+MZvfYcEcSlVtF6yve/WnIzRYWu +f917moMCAInktfch4E6mskr4h7n+9sEz+3GsQS8SQRtwUe+PiXzjZrqHSbLC4Kn3 +/b8Mt+Ww3a4FyjHDZQJZsGSvrScr0Gq3xeKfMwb+KYNEnmh0o4os0gEGA4KUR+/1 +YDl1NmxQnm/AIMqwJzeaezBoMn0Nsi+OlAms85imGURNj9BCEJZBWwuuNL5ECDAq +WLOM3AKUsApVgtGd8/OLWW1RwYkW8uqTtkIR87MCAwEAATANBgkqhkiG9w0BAQsF +AAOCAQEAokKC77/kvxlObLSwkT5+7+S+DeznLBRiGVEh8+9PQw1q91sjiOZWf0e3 +T3XPH7CR/NDYoQJkrsqzIwKYrj41z/1jAs+HkH45NpTFiGlUFXNs5iwNh4RUqgf4 +e78Mge4q7pHMFzWTEwEn4DJMGcDDjLW1kN8GobGwHR7O0MpAJKrqcBSo+SPomnQv +TgiEMQ+Vlz0EJx6JPsq8c7HrxlSdeDAAWIOww/wcGyzlpYEoyz6voSSfdhMt5iy5 +k5BvhBJnTiJTasCHy9KRuis/6qpTZKEj0d7J7LAqpGh8oRIphMwCbFYQT0QBgV6p +gM8Ufss/RZ6CshMNxz7KtIYpvmxPPTGCAsUwggLBAgEBMIGyMIGkMRYwFAYDVQQH +DA1Mb2NhbGl0eSBOYW1lMSEwHwYDVQQLDBhPcmdhbml6YXRpb25hbCBVbml0IE5h +bWUxHDAaBgkqhkiG9w0BCQEWDUVtYWlsIEFkZHJlc3MxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJOSjEaMBgGA1UECgwRRXhhbXBsZSBTaWduZXIgQ0ExEzARBgNVBAMM +CkV4YW1wbGUgQ0ECCQCBuTktP0h8BDANBglghkgBZQMEAgEFAKCB5DAYBgkqhkiG +9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xODA5MTMwOTIyMzha +MC8GCSqGSIb3DQEJBDEiBCBe/wOS+XB5tczAcNs1zT89zfSDIbfFYKfB63j1NExY +WzB5BgkqhkiG9w0BCQ8xbDBqMAsGCWCGSAFlAwQBKjALBglghkgBZQMEARYwCwYJ +YIZIAWUDBAECMAoGCCqGSIb3DQMHMA4GCCqGSIb3DQMCAgIAgDANBggqhkiG9w0D +AgIBQDAHBgUrDgMCBzANBggqhkiG9w0DAgIBKDANBgkqhkiG9w0BAQEFAASCAQAy +baJVxRJcZ3wYtb/TfQUDKNmaz7pYWNoKNxkPyKUerMOAZ9n0yvySNJUpzG+kJJNi +Ib792GXdmP4hdz4qC4Zx3S7H26OAYcOsTwd6+O/xcv8H7PQoPD+3fplhIvLtpIlS +//9ghpBXbUowdgzeDrYBpzRLqUth58IxsHd9cJQCCboKZIv8+6eP9fn1OD/CLGV3 +BNMvmeP88LU8UgtiivmmEJZ0fRtDVAGRIWykT1AvTfl69Pv9VKDuUW3qkuMwz7lW +Dv0c624BYPbQWdU7W5//iy4kSfwrtXtag7aovUbcwkmb2qb5v5c5ZqNoLPUvUpIG +KZUh0/aBuBovjwHZMcgl + +------F38FD3F34A584E774726CA12090D0B48-- + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_ca.pem b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_ca.pem new file mode 100644 index 0000000..2372ae0 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_ca.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV +BAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQKDBZBRExJTksgVGVj +aG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNvbTAgFw0xODA3MzAx +MjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMCTkwxEzARBgNVBAgM +ClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4xFzAV +BgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blIDehV6XCxrnGXusTCD +uFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9wicp3BGSpZZax/TcO +NjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLsDFFC+a0qn2RFh37r +cWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074BRDXVivx+wVD951L +FNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiySogRWAmKhysLQudu +kHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNVHQ4EFgQURWMbWvBK +ZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJvRV1/tyc1R82k0+gw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ysVtvHnk2hpu9yND +LCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9XVh0rGoR/6nHzo3TI +eiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9yghhKHHqNDvSsAL0 +KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbtlLX3QnwVOmaRyzyl +PiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42+OyLqcH1rKT6Xhcs +hjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb6SDB340BFmtgDHbF +HQ== +-----END CERTIFICATE----- diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_ca_key.pem b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_ca_key.pem new file mode 100644 index 0000000..22fac8b --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_ca_key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blIDehV6XCxr +nGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9wicp3BGSp +ZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLsDFFC+a0q +n2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074BRDXVivx ++wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiySogRWAmK +hysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABAoIBABWqhMSCr+7Mr3O3 +bIymOr+CT4xWI8S47hmKGFCLTrNsfy7cQZ9PdHkm7Ez+rCx+KwQaTrwz7EM/e8aH +q2zimMn4YXxeS7MFdM+Xvp/Y0BhXMd1j8Nk0x14+WHmQ88YfA4szdrHDekR+6oB6 +5Lc2fAfNbCGdpRksCQWDndrvIOda1swKW1RsGWHPGtSM1qOg09A4CeASqbsxZfdL +9MgI7aJKYnvJrUhqsNZU3fuOrLDNl7/JvdI08nYLnNkEvbDYbdfH0Q/4laKsSJcp +0jM6tPrxbHMDmBEwullVPrVqJX+n6Hvz3E8C9QiZq8NWbJUc5FntLx8ynbiJg6Lb +1w49WxECgYEA8yVky++3v0ZMKZeSeGj3MuKuEJ2q3UdmsKXA+Pyq0rL/hh7r2oUY +dQDs23BIuaHeIZxAGaMeMjoYQBi+G50XfwHZSMqivxX/yYkXxOJfPQvVLDbqCIWS +94qU4/xo50IkCNxpvRwfpKG2ce5YG7jrQkfb5I6TfKUWAaXpmaQnbYsCgYEAxaVn +Hzw3OdY7q6kURSY6a8KqtcuN0lNKeUb68vZemmZ0FNKmyh+xGVFXXlvmJpQgr5Zm +2W2a1C1oPq2DEdvSKt/aTHVIazG9TtFK1WAXpLxmlXlyqWRv+IvdVkph+p/3dIT0 +Ilaglgbndth4xk0c1zqy3g4VlAgWgKKi5owZ/j8CgYEAndsFGbHEJZZKFCannSzo +cEzinT7/kzGr5bt3ES9Y5/n2Euk4TmJignPbUowPaxU/1apPo1VXYVx+Kf7mTZ8r +hfV5T9ze1BhAPGOY3uXo1wU7nLz6LBYsWDHMgEd7A8jZBDe1HmWH1aZ3gHgxE652 +bk2g4T3/WskDBIbmpi0AvAkCgYBKAfFnRMj5IzscwCcS7YmaqD377MiiJQYR+34k +VBSAhDSbR3Wk4dESxd6NOqQndff3R74jVGNRZ99M+PPHUCSWYVQApToEyY81YDFB +TMYNrW5MMjm5LB6xVs3+bcPacOPcAZzY7s8a3mL1oYE339AY16X6eBOkZpLmf/+3 +jGZ/SQKBgQDkyxymL4xJGV8HCDontJZiBStD954GH1AgqEAOdQxU5vW4ySQ7yRoT +ajb8tH052yWW11Mxd0TRW9qbVI0/4/4lR86sODYLFbgrHAMBl7mxJ8Qwi4zdI9Am +FXGkj5SX2bYrf2f0YvCHNUbELTd4mF6kAH0Eg6kHRXLsSbhtWC7D3Q== +-----END RSA PRIVATE KEY----- diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_expired.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_expired.p7s new file mode 100644 index 0000000..bf35bf7 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_expired.p7s @@ -0,0 +1,243 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----11798C99B4C31493D0479BB8A2064C72" + +This is an S/MIME signed message + +------11798C99B4C31493D0479BB8A2064C72 +Content-Type: text/plain + + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2016-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 230 + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + CN=Spare cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 23 + + + 100 + 120 + + 200 + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + ALLOW + + + + +------11798C99B4C31493D0479BB8A2064C72 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgXPEkUvQgZwRMdZgxT8k/mrsJ +delB0E3RjpayHUkKYzowgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAA/TNULF62fO5mfjXm1L +Yk4Dg/5ZxAF/grDAjamo5v2fxGn6B1rrkj8YtyB1FEA0moM/cL31kNXNMqLvFdhY +lHCmX8x5PHkKzLihTIMx6diSCupBvvqUACeA7Ir1A3tMqW5tYYMg6sZ/YolgLLFG +8XmhttpEibtZm90MN3Xpsa4TiW5PlEWHC5ai3tyeyd/RCVoeQJVA0pAytmjdf2Mw +C3W/28tUxVCAjdlqXYap6jWZlNv/43P5HED837bF5iqoa1dTvDirca6WPanNjp28 +GQDi4bnD1kAk8wAKIm14qwS+fzxM3SKxJtdQuUCx+s/tPma4bLCqt843ok35SoWo +QKM= + +------11798C99B4C31493D0479BB8A2064C72-- + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_expired.xml b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_expired.xml new file mode 100644 index 0000000..f408942 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_expired.xml @@ -0,0 +1,191 @@ + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2016-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 230 + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + CN=Spare cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 23 + + + 100 + 120 + + 200 + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + ALLOW + + + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_full.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_full.p7s new file mode 100644 index 0000000..a8e71c1 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_full.p7s @@ -0,0 +1,243 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----D2957343698C311655D075C56A04A68D" + +This is an S/MIME signed message + +------D2957343698C311655D075C56A04A68D +Content-Type: text/plain + + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 230 + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + CN=Spare cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 23 + + + 100 + 120 + + 200 + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + ALLOW + + + + +------D2957343698C311655D075C56A04A68D +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgcYMSlCRiboSPUqMbBIKL7lBv +QJlEFiHrJ5t/aOJZbi0wgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAJsR4q4Eeorhd4sQaw+D +PErzkTuI1PEDzv2oYy3U/w4ZdGF2TJQqZ/OqiKEtmwqVAKfuPb9XQLPSENtn2uZC +wz9ZcvMJ4/GOOMWezN6J65pfuAeEWa0oGCcAASl7tuk+QpAK3MY8L5hxCPb6sfr9 +jslfMqJ+WYgrOVuqWMAYZoXwIgJ1GdREXOXoCnyEkwy6Prk6NhSDO6Jl91PxcZWG +ZITu7y/mklX8cSx09MNyOfefFhCIfNnXGJu0HUTYluTFd1LgRan6f0uyPR2zBLlE +qzuaetvpNlUclf8dywlazI8oRjfrusYo3tiKG+hHkjrXc7WHOh+I08Tqeyue+0tg +cjw= + +------D2957343698C311655D075C56A04A68D-- + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_full.xml b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_full.xml new file mode 100644 index 0000000..0be3fa2 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_full.xml @@ -0,0 +1,191 @@ + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 230 + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + CN=Spare cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 23 + + + 100 + 120 + + 200 + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + ALLOW + + + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_invalid_data.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_invalid_data.p7s new file mode 100644 index 0000000..b3b969e --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_invalid_data.p7s @@ -0,0 +1,219 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----62BE4CE8CF1FCB0420A2F2884B1618E6" + +This is an S/MIME signed message + +------62BE4CE8CF1FCB0420A2F2884B1618E6 +Content-Type: text/plain + + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 430 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 230 + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 23 + + + 100 + 120 + + 200 + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + + +------62BE4CE8CF1FCB0420A2F2884B1618E6 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQghoicue+FOmdIHF9rpsNCfmjP ++ZyN+t9kCdmR68JCJU0wgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAI0BX2tu2DbQjvuzKG35 +myNBcOC9ZzRDqJEtmQhcY/2hAJzurlnclJVTEXFyXdpV4ywtA+lQvbtToh11AvnY +IY1QWNVm19mfO1J6m6PFu18tizd30sG7p1TZKxGB3zDeVVqmedZ+o7QJHv9/ixzz +Pyo2B9tG5Su94+ADc0LQNyGICjeMr7L6dhFDsm7fXBi8pMBKy/zEAynTA3r1ibsn +5zlizPMlad2HCaYv44x7Xksg9FSbzJwJpTiprbQbZSUPYk4WlfVz0l4plzRKu4AP +lCOsdRE6C6GQFnK5bLyndu3Ycp10niwfkfobruCDyigu+gjZtmmF/T7A8Xkk1uvx +fAM= + +------62BE4CE8CF1FCB0420A2F2884B1618E6-- + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_invalid_data.xml b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_invalid_data.xml new file mode 100644 index 0000000..5ebb397 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_invalid_data.xml @@ -0,0 +1,167 @@ + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 430 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 230 + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 23 + + + 100 + 120 + + 200 + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_invalid_element.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_invalid_element.p7s new file mode 100644 index 0000000..521f4cf --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_invalid_element.p7s @@ -0,0 +1,219 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----3EE420429594FF1492D49B1EEBFBAF0E" + +This is an S/MIME signed message + +------3EE420429594FF1492D49B1EEBFBAF0E +Content-Type: text/plain + + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 230 + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 23 + + + 100 + 120 + + 200 + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + + +------3EE420429594FF1492D49B1EEBFBAF0E +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgk4Y6Rw4+DVfETNs8Ddv6rnhK +w7EwwZ9nE7SiujxSsDEwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAGkiiP+V49XZIwqbpqwN +RHv0tn06/BAuRGNybse1GkVzlNmuwbGObUUpKtKh4VxN8XuTfH5uuLEqftN2LvGG +zEiyosHX0gjsX6hihqoIcbfdsKpxd/OPCr/iNdOKWCSyV0aqaP3fc9Y2L1xVdXfn +avjfd8wief+ERfwKlsbHYsgh6/zwhVeMt2mzr8T0c+ICC99+XXmSvpnGJ89amYub +NnQwdxTp4PBQhudXixG3LrZ1CZafoLRz+x9vEIVF9oFyy7kMkeFtjd7aXc346Ama +djOu1LtzvWZKOMeGYVaSiQMl4HhpOh/embx+AClH/Hf1o7AA+ivF8vZgUDAAK2GD +rx8= + +------3EE420429594FF1492D49B1EEBFBAF0E-- + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_invalid_element.xml b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_invalid_element.xml new file mode 100644 index 0000000..6f38953 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_invalid_element.xml @@ -0,0 +1,167 @@ + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 230 + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 23 + + + 100 + 120 + + 200 + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_lack_of_not_after.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_lack_of_not_after.p7s new file mode 100644 index 0000000..804f556 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_lack_of_not_after.p7s @@ -0,0 +1,95 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----E9994989EF5BC12DCCE6563CF088037D" + +This is an S/MIME signed message + +------E9994989EF5BC12DCCE6563CF088037D +Content-Type: text/plain + + + + + + /O=Internet Widgits Pty Ltd/ST=Some-State/C=NL/CN=CHAM500 cert + + + 2015-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + + + ALLOW + + + + +------E9994989EF5BC12DCCE6563CF088037D +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgVn6yZWB0OOqW+6/ubhU1M4pT +tL+lh8qj9izsf/c3gKMwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAKhwx+Ew2m6lHQxL0I0K +Z0fdN8+19XGKYPWNuGwDR5MYpMX5jin/w/FgzeG5gSHqB51PRLJjH81incNVcRCf +bRKvwOv8b4J8D14ZG28SoNCsKejbXccFuA967ir+GHYrh0V9ikM/TwPuhosxclM5 +hZQuvRKig6Fum+PmGO7sLNyIPB1ODE8gbz0IiY9l6Zlp0xEe/+4YYpBL+GKamnlS +boRrfgGaTaWWi9EnjZWmJkFBO9vC08XZQ1akCubC0G8Kki0X3ZXJVXkX3AxjvZJY +XDdstpKWbfqlWzkYlJSI/I96BO2ZXY7nnsQU+8tvPV/6k6BaC80m0FhoTQJfDdLR +WnA= + +------E9994989EF5BC12DCCE6563CF088037D-- + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_lack_of_not_after.xml b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_lack_of_not_after.xml new file mode 100644 index 0000000..27e5fb9 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_lack_of_not_after.xml @@ -0,0 +1,43 @@ + + + + + /O=Internet Widgits Pty Ltd/ST=Some-State/C=NL/CN=CHAM500 cert + + + 2015-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + + + ALLOW + + + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_lack_of_not_before.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_lack_of_not_before.p7s new file mode 100644 index 0000000..a21bac6 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_lack_of_not_before.p7s @@ -0,0 +1,95 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----E0088C6C0B487BC746E35E87718DA89E" + +This is an S/MIME signed message + +------E0088C6C0B487BC746E35E87718DA89E +Content-Type: text/plain + + + + + + /O=Internet Widgits Pty Ltd/ST=Some-State/C=NL/CN=CHAM500 cert + + + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + + + ALLOW + + + + +------E0088C6C0B487BC746E35E87718DA89E +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgOCgkm0Mu6pRSDhlMd5/7OGhr +3TedLdpw5DQNC60vDgYwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBALYwxGivvBYfCdRADnYd +ysgBOITPhEY+TqqqEtiX4cIyeEdZGMFxcciMxbXVB1qy7js7PM+tbZ/+ICutyA7J +dkU9cNO9hLM/LYASv9B9zpgxMecYcA9rx7OEpM3Sr2eXOTbu2j3gUoCun7y8f+yv +iiYUORa0cX8oFnq++rQXHE/0rOVd17tboLvsy97Tro8o1e7WFA2gkJsCyo4QF+Lg +yz8IKdKMIRLpEl07bGIcIq4gvarQnN3qT1KuOMrDQD29CFZMwCO/TSGVeZYRHdW9 +s1hhmrTlkmlhPyXG9yxm9PH9UHZyfhkbrhIXZtN6M/7SO8VfTMfotyTbFtuatzzL +fz4= + +------E0088C6C0B487BC746E35E87718DA89E-- + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_lack_of_not_before.xml b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_lack_of_not_before.xml new file mode 100644 index 0000000..6c3f892 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_lack_of_not_before.xml @@ -0,0 +1,43 @@ + + + + + /O=Internet Widgits Pty Ltd/ST=Some-State/C=NL/CN=CHAM500 cert + + + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + + + ALLOW + + + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_not_signed.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_not_signed.p7s new file mode 100644 index 0000000..8759d91 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_not_signed.p7s @@ -0,0 +1,33 @@ + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + + + * + + + + DENY + + + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_notyet.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_notyet.p7s new file mode 100644 index 0000000..7fd4098 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_notyet.p7s @@ -0,0 +1,243 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----F87E07CA6CCEAB50B03A143AC2354EB4" + +This is an S/MIME signed message + +------F87E07CA6CCEAB50B03A143AC2354EB4 +Content-Type: text/plain + + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2035-09-15T01:00:00 + 2046-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 230 + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + CN=Spare cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 23 + + + 100 + 120 + + 200 + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + ALLOW + + + + +------F87E07CA6CCEAB50B03A143AC2354EB4 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQg0GGu1gWhHWhfWnmg55AIr4tv +zMK0kIxNfJYQbb7LpJ8wgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBALsPI2+b0w+iUPJGJeMd +VdrY7s/GZYm6M8qOA5fmh3144bY1rZRjdHjXtLdaNDNN1Z5buRCiQcklAilf6O14 +7u6a5HR12N4LTbg3OYQplwz4ed/wBsL726htmkAK3JogGk5OVLqmmdrz3UOD8IaZ +wAfx2tpj3VJOVuW0XsqOrzQpnOjGWcPeOw6NAxRH1gLsxBP9HDz5+wrsKXjV/zG8 +dFTaZ0bKnBXTp5ccc9jB4qbcllC9nlJkJszGqvwOP7zWBAOXeU+joUGM4Bt+8Pmt +pKsVAmEqMpc368RMayDBWtTqUWpUKvDh4HSkuOGD4Hj5ViAoLFjisROhIK2d98XI +cRQ= + +------F87E07CA6CCEAB50B03A143AC2354EB4-- + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_notyet.xml b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_notyet.xml new file mode 100644 index 0000000..99fec50 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_notyet.xml @@ -0,0 +1,191 @@ + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2035-09-15T01:00:00 + 2046-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 230 + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + CN=Spare cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 23 + + + 100 + 120 + + 200 + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + ALLOW + + + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_ok.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_ok.p7s new file mode 100644 index 0000000..052075b --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_ok.p7s @@ -0,0 +1,85 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----6B91005B007BBA8EDE10CD1CE487DB27" + +This is an S/MIME signed message + +------6B91005B007BBA8EDE10CD1CE487DB27 +Content-Type: text/plain + + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + + + * + + + + DENY + + + + +------6B91005B007BBA8EDE10CD1CE487DB27 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgl3LfUhn9L0vG/3QRPVYptcYw +/NH5HMN99aMe9JAT+LAwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAHe9vakfXPvbpgMeqlhG +SW6Z3uVA3Yri9bgQDpJ9daIUsM0/TLBSQVs85twTMXvqUSntKbfSGehxDQ9F+yje +mOEPMIwxOqcVyc2jpqoYsUWqpwiiZyk49DHUFrOfWJUx+rKdBftZWkxD05Wkovhk +2d4hGS/65Haoho4Z0AZwcyH+F52FZMiqw7I9FKrPlhxvJfQXmhIjOKtnvWnQ+Ar7 +YYiSrBEHMCy82LF1aKzz0nkL1SYWQHuQX475qoU4LMYY1J8WsD3rSBeq4GYZrl2K +X/JcOquMYqjfJLMYZY4fsc3FgEBkKNqJz1tDZ3ir24VMl+WsbEjVK8oXe/wt4V0U +aNQ= + +------6B91005B007BBA8EDE10CD1CE487DB27-- + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_ok.xml b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_ok.xml new file mode 100644 index 0000000..8759d91 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_ok.xml @@ -0,0 +1,33 @@ + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + + + * + + + + DENY + + + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_unknown_ca.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_unknown_ca.p7s new file mode 100644 index 0000000..6a2905a --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_unknown_ca.p7s @@ -0,0 +1,87 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----7FBACED8776E5A4CF7612C83F9C33E17" + +This is an S/MIME signed message + +------7FBACED8776E5A4CF7612C83F9C33E17 +Content-Type: text/plain + + + + + + /C=NL/ST=Some-State/O=ADLINK Technolocy Inc./CN=adlinktech.com + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + + + * + + + + DENY + + + + +------7FBACED8776E5A4CF7612C83F9C33E17 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGywYJKoZIhvcNAQcCoIIGvDCCBrgCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggPKMIIDxjCCAq4CCQCBuTktP0h8BDANBgkqhkiG9w0BAQsFADCB +pDEWMBQGA1UEBwwNTG9jYWxpdHkgTmFtZTEhMB8GA1UECwwYT3JnYW5pemF0aW9u +YWwgVW5pdCBOYW1lMRwwGgYJKoZIhvcNAQkBFg1FbWFpbCBBZGRyZXNzMQswCQYD +VQQGEwJVUzELMAkGA1UECAwCTkoxGjAYBgNVBAoMEUV4YW1wbGUgU2lnbmVyIENB +MRMwEQYDVQQDDApFeGFtcGxlIENBMB4XDTE4MDgxNTA4NTE0MVoXDTQzMDgwOTA4 +NTE0MVowgaQxFjAUBgNVBAcMDUxvY2FsaXR5IE5hbWUxITAfBgNVBAsMGE9yZ2Fu +aXphdGlvbmFsIFVuaXQgTmFtZTEcMBoGCSqGSIb3DQEJARYNRW1haWwgQWRkcmVz +czELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5KMRowGAYDVQQKDBFFeGFtcGxlIFNp +Z25lciBDQTETMBEGA1UEAwwKRXhhbXBsZSBDQTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBALStAQ0yjM2qAWwsOXdX3hiyoZ6DDHWOTNI5LoCZGaN9rUZe +MY0waSxWNQ0ruURgZISeOFkdQTAE81Em+UaZI+MZvfYcEcSlVtF6yve/WnIzRYWu +f917moMCAInktfch4E6mskr4h7n+9sEz+3GsQS8SQRtwUe+PiXzjZrqHSbLC4Kn3 +/b8Mt+Ww3a4FyjHDZQJZsGSvrScr0Gq3xeKfMwb+KYNEnmh0o4os0gEGA4KUR+/1 +YDl1NmxQnm/AIMqwJzeaezBoMn0Nsi+OlAms85imGURNj9BCEJZBWwuuNL5ECDAq +WLOM3AKUsApVgtGd8/OLWW1RwYkW8uqTtkIR87MCAwEAATANBgkqhkiG9w0BAQsF +AAOCAQEAokKC77/kvxlObLSwkT5+7+S+DeznLBRiGVEh8+9PQw1q91sjiOZWf0e3 +T3XPH7CR/NDYoQJkrsqzIwKYrj41z/1jAs+HkH45NpTFiGlUFXNs5iwNh4RUqgf4 +e78Mge4q7pHMFzWTEwEn4DJMGcDDjLW1kN8GobGwHR7O0MpAJKrqcBSo+SPomnQv +TgiEMQ+Vlz0EJx6JPsq8c7HrxlSdeDAAWIOww/wcGyzlpYEoyz6voSSfdhMt5iy5 +k5BvhBJnTiJTasCHy9KRuis/6qpTZKEj0d7J7LAqpGh8oRIphMwCbFYQT0QBgV6p +gM8Ufss/RZ6CshMNxz7KtIYpvmxPPTGCAsUwggLBAgEBMIGyMIGkMRYwFAYDVQQH +DA1Mb2NhbGl0eSBOYW1lMSEwHwYDVQQLDBhPcmdhbml6YXRpb25hbCBVbml0IE5h +bWUxHDAaBgkqhkiG9w0BCQEWDUVtYWlsIEFkZHJlc3MxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJOSjEaMBgGA1UECgwRRXhhbXBsZSBTaWduZXIgQ0ExEzARBgNVBAMM +CkV4YW1wbGUgQ0ECCQCBuTktP0h8BDANBglghkgBZQMEAgEFAKCB5DAYBgkqhkiG +9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xODA5MTMwOTIzMDNa +MC8GCSqGSIb3DQEJBDEiBCCvP08gFBO7651mPPDFQ2suhL+eprGCGuRLXmiBmdvx +ITB5BgkqhkiG9w0BCQ8xbDBqMAsGCWCGSAFlAwQBKjALBglghkgBZQMEARYwCwYJ +YIZIAWUDBAECMAoGCCqGSIb3DQMHMA4GCCqGSIb3DQMCAgIAgDANBggqhkiG9w0D +AgIBQDAHBgUrDgMCBzANBggqhkiG9w0DAgIBKDANBgkqhkiG9w0BAQEFAASCAQB/ +4EQel+0LsmiNFCUjWM68u4ZvPtFBpeDe456DJuG6QR0LIzW42U7N4P2ZTIqjpGZx +YekBCNdkiVy6ER5IA4WfcKd6zXZEuXVxkMrGpJlqGdd+IdZpTsrBygGZJS4vMUfD +/6ty6OycET88RmJIu4V/TM3yLVKzHuj6TxCXb4OIYx8g3mdXUwUrp6DGgqggRSPJ +tatbpnqGZGcvty8MusXVnjnEwUWnJ/jojypY3MyL4MTbjufjv0K6NKQ3RzoLssot +SLq0YDLwvX/s9sLXDCedAwFXBS/6Qv56v0M2x4o8e3Eul7gGTMuCd/dJ0BhF8CW+ +IGxR5I3xXssh/AuWRRtV + +------7FBACED8776E5A4CF7612C83F9C33E17-- + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_unknown_subject.p7s b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_unknown_subject.p7s new file mode 100644 index 0000000..fb488c7 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_unknown_subject.p7s @@ -0,0 +1,85 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----7B161F9203F175A7F82A389A3E044741" + +This is an S/MIME signed message + +------7B161F9203F175A7F82A389A3E044741 +Content-Type: text/plain + + + + + + gibberish + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + + + * + + + + DENY + + + + +------7B161F9203F175A7F82A389A3E044741 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQg44QSCYJrKGm9hdPbOKQjrnQ8 +LXMSbo0mve1cRKvrm3gwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAH/fJ90OwloC73faPAGC +VRZrhW/gSsy/1VnprvWdDAU1ZZK+srIISFZAy19LcApTis0Vy9yz2PG8pue49R+y +UF6mCDSuN/l9SRBdUN+CXQdQ8sGq5SHXNhGzSX/nbR20ol4cSUMpKlEGx66E0KUW +tkk8HzYw7aHMiwK2E2Y0sbm/M/rdmAbgEoywYfvc25V4FHP66TstfCLBjN9Hz3bH +WcrCZuPjZo6vBd/rIJQSlgH81aCWn5RfCIccbc3iogwzIhYxAr6d+4do3LNa6H80 +W6CMgl0AnWFfa4QwnXFUzb1/W2rFjHp453w1Cbqk4Ll4ZlVJr4fzIuyuJMQlMrmK +1P0= + +------7B161F9203F175A7F82A389A3E044741-- + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_unknown_subject.xml b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_unknown_subject.xml new file mode 100644 index 0000000..8a55faf --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/etc/Test_Permissions_unknown_subject.xml @@ -0,0 +1,33 @@ + + + + + gibberish + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + + + * + + + + DENY + + + diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/src/validate_local_permissions_utests.c b/src/security/builtin_plugins/tests/validate_local_permissions/src/validate_local_permissions_utests.c new file mode 100644 index 0000000..b690fdb --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_local_permissions/src/validate_local_permissions_utests.c @@ -0,0 +1,1020 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include +#include + +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/io.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/types.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/core/dds_security_utils.h" +#include "CUnit/CUnit.h" +#include "CUnit/Test.h" +#include "common/src/loader.h" +#include "config_env.h" + +static const char *PROPERTY_IDENTITY_CA = "dds.sec.auth.identity_ca"; +static const char *PROPERTY_PRIVATE_KEY = "dds.sec.auth.private_key"; +static const char *PROPERTY_IDENTITY_CERT = "dds.sec.auth.identity_certificate"; +static const char *PROPERTY_PERMISSIONS_CA = "dds.sec.access.permissions_ca"; +static const char *PROPERTY_PERMISSIONS = "dds.sec.access.permissions"; +static const char *PROPERTY_GOVERNANCE = "dds.sec.access.governance"; + +static const char *RELATIVE_PATH_TO_ETC_DIR = "/validate_local_permissions/etc/"; + +static const char *AUTH_IDENTITY_CERT = + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIEQTCCAymgAwIBAgIINpuaAAnrQZIwDQYJKoZIhvcNAQELBQAwXzELMAkGA1UE\n" + "BhMCTkwxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp\n" + "ZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAxMPQ0hBTTUwMCByb290IGNhMCAXDTE3MDIy\n" + "MjIyMjIwMFoYDzIyMjIwMjIyMjIyMjAwWjBcMQswCQYDVQQGEwJOTDETMBEGA1UE\n" + "CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk\n" + "MRUwEwYDVQQDEwxDSEFNNTAwIGNlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\n" + "ggEKAoIBAQDCpVhivH/wBIyu74rvQncnSZqKyspN6CvD1pmV9wft5PHhVt9jV79v\n" + "gSub5LADoRHAgFdv9duYgBr17Ob6uRrIY4B18CcrCjhQcC4gjx8y2jl9PeYm+qYD\n" + "3o44FYBrBq0QCnrQgKsb/qX9Z+Mw/VUiw65x68W876LEHQQoEgT4kxSuagwBoVRk\n" + "ePD6fYAKmT4XS3x+O0v+rHESTcsKF6yMadgp7h3eH1b8kJTzSx8JV9Zzq++mxjox\n" + "qhbBVP5nDze2hhSIeCkCvSrx7efkgKS4AQXa5/Z44GiAu1TfXXUqdic9rxwD0edn\n" + "ajNElnZe7sjok/0yuqvH+2hSqpNva/zpAgMBAAGjggEAMIH9MAwGA1UdDwQFAwMH\n" + "/4AwgewGA1UdJQSB5DCB4QYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDAwYI\n" + "KwYBBQUHAwQGCCsGAQUFBwMIBgorBgEEAYI3AgEVBgorBgEEAYI3AgEWBgorBgEE\n" + "AYI3CgMBBgorBgEEAYI3CgMDBgorBgEEAYI3CgMEBglghkgBhvhCBAEGCysGAQQB\n" + "gjcKAwQBBggrBgEFBQcDBQYIKwYBBQUHAwYGCCsGAQUFBwMHBggrBgEFBQgCAgYK\n" + "KwYBBAGCNxQCAgYIKwYBBQUHAwkGCCsGAQUFBwMNBggrBgEFBQcDDgYHKwYBBQID\n" + "BTANBgkqhkiG9w0BAQsFAAOCAQEAawdHy0Xw7nTK2ltp91Ion6fJ7hqYuj///zr7\n" + "Adt6uonpDh/xl3esuwcFimIJrJrHujnGkL0nLddRCikmnzuBMNDWS6yq0/Ckl/YG\n" + "yjNr44dlX24wo+MVAgkj3/8CyWDZ3a8kBg9QT3bs2SqbjmhTrXN1DRyf9S5vJysE\n" + "I7V1gTN66BeKL64hOrAlRVrEu8Ds6TWL6Q/YH+61ViZkoLTeSaPjH4nknaFr4C35\n" + "iji0JhkyfRHRRVPHFnaj25AkxOrSV64qVKoTMjDl5fji5iMGtjm6iJ7q05ml/qDl\n" + "nLotHXemZNvYhbwUmRzbt4Dls9EMH4VRbP85I94nM5TAvtHVNA==\n" + "-----END CERTIFICATE-----\n"; + +static const char *AUTH_IDENTITY_CA = + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIEmTCCA4GgAwIBAgIIZ5gEIUFhO5wwDQYJKoZIhvcNAQELBQAwXzELMAkGA1UE\n" + "BhMCTkwxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp\n" + "ZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAxMPQ0hBTTUwMCByb290IGNhMCAXDTE4MDIx\n" + "MjE1MDUwMFoYDzIyMjIwMjIyMjIyMjAwWjBfMQswCQYDVQQGEwJOTDETMBEGA1UE\n" + "CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk\n" + "MRgwFgYDVQQDEw9DSEFNNTAwIHJvb3QgY2EwggEiMA0GCSqGSIb3DQEBAQUAA4IB\n" + "DwAwggEKAoIBAQC6Fa3TheL+UrdZCp9GhU/2WbneP2t/avUa3muwDttPxeI2XU9k\n" + "ZjBR95mAXme4SPXHk5+YDN319AqIje3oKhzky/ngvKH2GkoJKYxWnuDBfMEHdViz\n" + "2Q9/xso2ZvH50ukwWa0pfx2/EVV1wRxeQcRd/UVfq3KTJizG0M88mOYvGEAw3LFf\n" + "zef7k1aCuOofQmBvLukUudcYpMzfyHFp7lQqU4CcrrR5RtmfiUfrWfdGLea2iPDB\n" + "pJgN8ESOMwEHtOTEBDclYnH9L4t7CHQz+fXXS5IWFsDK9fCMQjnxDsDVeNrNzTYL\n" + "FaZrMg9S6IUQCEsQWsnq5weS8omOpVLUm9klAgMBAAGjggFVMIIBUTAMBgNVHRME\n" + "BTADAQH/MB0GA1UdDgQWBBQg2FZB/j8uWDVnJhjwXkX278znSTAfBgNVHSMEGDAW\n" + "gBQg2FZB/j8uWDVnJhjwXkX278znSTAPBgNVHQ8BAf8EBQMDB/+AMIHvBgNVHSUB\n" + "Af8EgeQwgeEGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwME\n" + "BggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYK\n" + "KwYBBAGCNwoDAwYKKwYBBAGCNwoDBAYJYIZIAYb4QgQBBgsrBgEEAYI3CgMEAQYI\n" + "KwYBBQUHAwUGCCsGAQUFBwMGBggrBgEFBQcDBwYIKwYBBQUIAgIGCisGAQQBgjcU\n" + "AgIGCCsGAQUFBwMJBggrBgEFBQcDDQYIKwYBBQUHAw4GBysGAQUCAwUwDQYJKoZI\n" + "hvcNAQELBQADggEBAKHmwejWRwGE1wf1k2rG8SNRV/neGsZ6Qfqf6co3TpR/Wi1s\n" + "iZDvSeT/rbqNBS7z34xnG88NIUwu00y78e8Mfon31ZZbK4Uo7fla9/D3ukdJqPQC\n" + "LKdbKJjR2kH+KCukY/1rghjJ8/X+t2egBit0LCOdsFCl07Sfksb9kpGUIZSFcYYm\n" + "geqhjhoNwxazzHiw+QWHC5HG9248JIizBmy1aymNWuMnPudhjHAnPcsIlqMVNq3t\n" + "Rv9ap7S8JeCxHVRPJvJeCwXWvW3dW/v3xH52Yn/fqRblN1w9Fxz5NhopKx0gj/Jd\n" + "sw2N4Fk4gaOWEolFpa0bwNw8nAx7moehZpowzfw=\n" + "-----END CERTIFICATE-----\n"; + +static const char *AUTH_PRIVATE_KEY = + "data:,-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEogIBAAKCAQEAwqVYYrx/8ASMru+K70J3J0maisrKTegrw9aZlfcH7eTx4Vbf\n" + "Y1e/b4Erm+SwA6ERwIBXb/XbmIAa9ezm+rkayGOAdfAnKwo4UHAuII8fMto5fT3m\n" + "JvqmA96OOBWAawatEAp60ICrG/6l/WfjMP1VIsOucevFvO+ixB0EKBIE+JMUrmoM\n" + "AaFUZHjw+n2ACpk+F0t8fjtL/qxxEk3LChesjGnYKe4d3h9W/JCU80sfCVfWc6vv\n" + "psY6MaoWwVT+Zw83toYUiHgpAr0q8e3n5ICkuAEF2uf2eOBogLtU3111KnYnPa8c\n" + "A9HnZ2ozRJZ2Xu7I6JP9Mrqrx/toUqqTb2v86QIDAQABAoIBAC1q32DKkx+yMBFx\n" + "m32QiLUGG6VfBC2BixS7MkMnzRXZYgcuehl4FBc0kLRjfB6cqsO8LqrVN1QyMBhK\n" + "GutN3c38SbE7RChqzhEW2+yE+Mao3Nk4ZEecHLiyaYT0n25ZtHAVwep823BAzwJ+\n" + "BykbM45VEpNKbG1VjSktjBa9faNyZiZAEJEjVyla+6R8N4kHV52LbZcLjvJv3IQ2\n" + "iPYRrmMyI5C23qTni0vy7yJbAXBo3CqgSlwie9FARBWT7Puu7F4mF1O1c/SnTysw\n" + "Tm3e5FzgfHipQbnRVn0w4rDprPMKmPxMnvf/Wkw0zVgNadp1Tc1I6Yj525DEQ07i\n" + "2gIn/gECgYEA4jNnY1u2Eu7x3pAQF3dRO0x35boVtuq9iwQk7q+uaZaK4RJRr+0Y\n" + "T68S3bPnfer6SHvcxtST89Bvs/j/Ky4SOaX037UYjFh6T7OIzPl+MzO1yb+VOBT6\n" + "D6FVGEJGp8ZAITU1OfJPeTYViUeEC8tHFGoKUCk50FbB6jOf1oKtv/ECgYEA3EnB\n" + "Y7kSbJJaUuj9ciFUL/pAno86Cim3VjegK1wKgEiyDb610bhoMErovPwfVJbtcttG\n" + "eKJNuwizkRcVbj+vpjDvqqaP5eMxLl6/Nd4haPMJYzGo88Z8NJpwFRNF2KEWjOpQ\n" + "2NEvoCeRtVulCJyka2Tpljzw8cOXkxhPOe2UhHkCgYBo3entj0QO7QXm56T+LAvV\n" + "0PK45xdQEO3EuCwjGAFk5C0IgUSrqeCeeIzniZMltj1IQ1wsNbtNynEu3530t8wt\n" + "O7oVyFBUKGSz9IjUdkpClJOPr6kPMfJoMqRPtdIpz+hFPPSrI6IikKdVWHloOlp+\n" + "pVaYqTQrWT1XRY2xli3VEQKBgGySmZN6Cx+h/oywswIGdUT0VdcQhq2to+QFpJba\n" + "VX6m1cM6hMip2Ag9U3qZ1SNPBBdBBfm9HQybHE3dj713/C2wHuAAGhpXIM1W+20k\n" + "X1knuC/AsSH9aQhQOf/ZMOq1crTfZBuI9q0782/sjGmzMsKPySU4QhUWruVb7OiD\n" + "NVkZAoGAEvihW7G+8/iOE40vGHyBqUeopAAWLciTAUIEwM/Oi3BYfNWNTWF/FWNc\n" + "nMvCZPYigY8C1vO+1iT2Frtd3CIU+f01Q3fJNJoRLlEiKLNZUJRF48OKUqjKSmsi\n" + "w6pucFO40z05YW7utApj4L82rZnOS0pd1tUI1yexqvj0i4ThJfk=\n" + "-----END RSA PRIVATE KEY-----\n"; + +static struct plugins_hdl *g_plugins = NULL; +static dds_security_authentication *g_auth = NULL; +static dds_security_access_control *g_access_control = NULL; +static char *g_path_to_etc_dir = NULL; + +/* Prepare a property sequence. */ +static void dds_security_property_init(DDS_Security_PropertySeq *seq, DDS_Security_unsigned_long size) +{ + seq->_length = size; + seq->_maximum = size; + seq->_buffer = ddsrt_malloc(size * sizeof(DDS_Security_Property_t)); + memset(seq->_buffer, 0, size * sizeof(DDS_Security_Property_t)); +} + +/* Cleanup a property sequence.*/ +static void dds_security_property_deinit(DDS_Security_PropertySeq *seq) +{ + uint32_t i; + + for (i = 0; i < seq->_length; i++) + { + ddsrt_free(seq->_buffer[i].name); + ddsrt_free(seq->_buffer[i].value); + } + ddsrt_free(seq->_buffer); +} + +/* Find a property within a sequence.*/ +static DDS_Security_Property_t *dds_security_property_find(DDS_Security_PropertySeq *seq, const char *name) +{ + DDS_Security_Property_t *prop = NULL; + uint32_t i; + for (i = 0; (i < seq->_length) && (prop == NULL); i++) + { + if (strcmp(seq->_buffer[i].name, name) == 0) + { + prop = &(seq->_buffer[i]); + } + } + return prop; +} + +/* Cleanup exception contents.*/ +static void reset_exception(DDS_Security_SecurityException *ex) +{ + ex->code = 0; + ex->minor_code = 0; + ddsrt_free(ex->message); + ex->message = NULL; +} + +/* Glue two strings together */ +static char *combine_strings(const char *prefix, const char *postfix) +{ + char *str; + ddsrt_asprintf(&str, "%s%s", prefix, postfix); + return str; +} + +/* Use the given file to create a proper file uri (with directory).*/ +static char *create_uri_file(const char *file) +{ + char *uri; + char *dir; + if (file) + { + dir = combine_strings("file:", g_path_to_etc_dir); + uri = combine_strings(dir, file); + ddsrt_free(dir); + } + else + { + uri = ddsrt_strdup("file:"); + } + return uri; +} + +/* Read the given file contents and transform it into a data uri.*/ +static char *create_uri_data(const char *file) +{ + char *data = NULL; + char *location; + char *contents; + + if (file) + { + location = combine_strings(g_path_to_etc_dir, file); + if (location) + { + contents = load_file_contents(location); + if (contents) + { + data = combine_strings("data:,", contents); + ddsrt_free(contents); + } + ddsrt_free(location); + } + } + else + { + data = ddsrt_strdup("data:,"); + } + + return data; +} + +/* Fill the security properties of a participant QoS with the + * authorization and access_control values. */ +static void fill_property_policy(DDS_Security_PropertyQosPolicy *property, const char *permission_ca, const char *permission_uri, const char *governance_uri) +{ + dds_security_property_init(&property->value, 6); + /* Authentication properties. */ + property->value._buffer[0].name = ddsrt_strdup(PROPERTY_IDENTITY_CERT); + property->value._buffer[0].value = ddsrt_strdup(AUTH_IDENTITY_CERT); + property->value._buffer[1].name = ddsrt_strdup(PROPERTY_IDENTITY_CA); + property->value._buffer[1].value = ddsrt_strdup(AUTH_IDENTITY_CA); + property->value._buffer[2].name = ddsrt_strdup(PROPERTY_PRIVATE_KEY); + property->value._buffer[2].value = ddsrt_strdup(AUTH_PRIVATE_KEY); + /* AccessControl properties. */ + property->value._buffer[3].name = ddsrt_strdup(PROPERTY_PERMISSIONS_CA); + property->value._buffer[3].value = permission_ca ? ddsrt_strdup(permission_ca) : NULL; + property->value._buffer[4].name = ddsrt_strdup(PROPERTY_PERMISSIONS); + property->value._buffer[4].value = permission_uri ? ddsrt_strdup(permission_uri) : NULL; + property->value._buffer[5].name = ddsrt_strdup(PROPERTY_GOVERNANCE); + property->value._buffer[5].value = governance_uri ? ddsrt_strdup(governance_uri) : NULL; +} + +/* Open a local identity by calling the authorization plugin with + * properly created dummy values and the given participant QoS.*/ +static DDS_Security_IdentityHandle create_local_identity(DDS_Security_Qos *participant_qos) +{ + DDS_Security_IdentityHandle local_id_hdl = DDS_SECURITY_HANDLE_NIL; + DDS_Security_ValidationResult_t result; + DDS_Security_DomainId domain_id = 0; + DDS_Security_GUID_t local_participant_guid; + DDS_Security_GUID_t candidate_participant_guid; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_GuidPrefix_t prefix = {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb}; + DDS_Security_EntityId_t entityId = {{0xb0, 0xb1, 0xb2}, 0x1}; + + CU_ASSERT_FATAL(g_auth->validate_local_identity != NULL); + + memset(&local_participant_guid, 0, sizeof(local_participant_guid)); + memcpy(&candidate_participant_guid.prefix, &prefix, sizeof(prefix)); + memcpy(&candidate_participant_guid.entityId, &entityId, sizeof(entityId)); + + /* Now call the function. */ + result = g_auth->validate_local_identity( + g_auth, + &local_id_hdl, + &local_participant_guid, + domain_id, + participant_qos, + &candidate_participant_guid, + &exception); + + if (result != DDS_SECURITY_VALIDATION_OK) + { + printf("validate_local_identity_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + + reset_exception(&exception); + + return local_id_hdl; +} + +/* Close the given local identity by returning its handle to the + * authorization plugin.*/ +static void clear_local_identity(DDS_Security_IdentityHandle local_id_hdl) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_boolean success; + + if (local_id_hdl != DDS_SECURITY_HANDLE_NIL) + { + success = g_auth->return_identity_handle(g_auth, local_id_hdl, &exception); + if (!success) + { + printf("return_identity_handle failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + reset_exception(&exception); + } +} + +/* Prepare the global link to the test's "etc" directory.*/ +static void set_path_to_etc_dir(void) +{ + ddsrt_asprintf(&g_path_to_etc_dir, "%s%s", CONFIG_ENV_TESTS_DIR, RELATIVE_PATH_TO_ETC_DIR); +} + +/* Initialize the participant QoS with security related properties. + * It will transform the given files into proper uri's. + * A NULL will result in a file uri without actual link.*/ +static void qos_init_file(DDS_Security_Qos *participant_qos, const char *certificate_filename, const char *permission_filename, const char *governance_filename) +{ + char *permission_ca; + char *permission_uri; + char *governance_uri; + + permission_ca = create_uri_file(certificate_filename); + permission_uri = create_uri_file(permission_filename); + governance_uri = create_uri_file(governance_filename); + + memset(participant_qos, 0, sizeof(*participant_qos)); + fill_property_policy(&(participant_qos->property), + permission_ca, + permission_uri, + governance_uri); + + ddsrt_free(permission_ca); + ddsrt_free(permission_uri); + ddsrt_free(governance_uri); +} + +/* Initialize the participant QoS with security related properties. + * It will transform the given files into data uri's. + * A NULL will result in a data uri without actual data.*/ +static void qos_init_data(DDS_Security_Qos *participant_qos, const char *certificate_filename, const char *permission_filename, const char *governance_filename) +{ + char *permission_ca; + char *permission_uri; + char *governance_uri; + + permission_ca = create_uri_data(certificate_filename); + permission_uri = create_uri_data(permission_filename); + governance_uri = create_uri_data(governance_filename); + CU_ASSERT_FATAL(permission_ca != NULL); + CU_ASSERT_FATAL(permission_uri != NULL); + CU_ASSERT_FATAL(governance_uri != NULL); + + memset(participant_qos, 0, sizeof(*participant_qos)); + fill_property_policy(&(participant_qos->property), + permission_ca, + permission_uri, + governance_uri); + + ddsrt_free(permission_ca); + ddsrt_free(permission_uri); + ddsrt_free(governance_uri); +} + +/* Initialize the participant QoS with security related properties. + * A NULL will result in an uri with an unknown type.*/ +static void qos_init_type(DDS_Security_Qos *participant_qos, const char *certificate_filename, const char *permission_filename, const char *governance_filename) +{ + char *permission_ca; + char *permission_uri; + char *governance_uri; + + if (certificate_filename) + permission_ca = create_uri_file(certificate_filename); + else + permission_ca = ddsrt_strdup("unknown_type:,just some data"); + if (permission_filename) + permission_uri = create_uri_file(permission_filename); + else + permission_uri = ddsrt_strdup("unknown_type:,just some data"); + if (governance_filename) + governance_uri = create_uri_file(governance_filename); + else + governance_uri = ddsrt_strdup("unknown_type:,just some data"); + + memset(participant_qos, 0, sizeof(*participant_qos)); + fill_property_policy(&(participant_qos->property), + permission_ca, + permission_uri, + governance_uri); + + ddsrt_free(permission_ca); + ddsrt_free(permission_uri); + ddsrt_free(governance_uri); +} + +/* Initialize the participant QoS with security related properties. + * Allow NULL as property value.*/ +static void qos_init_null(DDS_Security_Qos *participant_qos, const char *certificate_filename, const char *permission_filename, const char *governance_filename) +{ + char *permission_ca = NULL; + char *permission_uri = NULL; + char *governance_uri = NULL; + + if (certificate_filename) + permission_ca = create_uri_file(certificate_filename); + if (permission_filename) + permission_uri = create_uri_file(permission_filename); + if (governance_filename) + governance_uri = create_uri_file(governance_filename); + + memset(participant_qos, 0, sizeof(*participant_qos)); + fill_property_policy(&(participant_qos->property), + permission_ca, + permission_uri, + governance_uri); + + ddsrt_free(permission_ca); + ddsrt_free(permission_uri); + ddsrt_free(governance_uri); +} + +/* Cleanup the participant QoS.*/ +static void qos_deinit(DDS_Security_Qos *participant_qos) +{ + dds_security_property_deinit(&(participant_qos->property.value)); +} + +/* Setup the testing environment by loading the plugins and + * creating a local identity.*/ +static DDS_Security_IdentityHandle test_setup(DDS_Security_Qos *participant_qos) +{ + DDS_Security_IdentityHandle local_id_hdl = DDS_SECURITY_HANDLE_NIL; + + g_plugins = load_plugins(&g_access_control /* Access Control */, + &g_auth /* Authentication */, + NULL /* Cryptograpy */); + if (g_plugins) + { + CU_ASSERT_FATAL(g_auth != NULL); + CU_ASSERT_FATAL(g_access_control != NULL); + CU_ASSERT_FATAL(g_access_control->validate_local_permissions != NULL); + CU_ASSERT_FATAL(g_access_control->return_permissions_handle != NULL); + + local_id_hdl = create_local_identity(participant_qos); + } + + return local_id_hdl; +} + +/* Teardown the testing environment by clearing the local identity + * and closing the plugins.*/ +static int test_teardown(DDS_Security_IdentityHandle local_id_hdl) +{ + clear_local_identity(local_id_hdl); + unload_plugins(g_plugins); + g_plugins = NULL; + g_access_control = NULL; + g_auth = NULL; + return 0; +} + +/* The AccessControl related properties in the participant_qos will + * have some kind of problem that should force a failure when + * checking the local permissions.*/ +static DDS_Security_long test_failure_scenario(DDS_Security_Qos *participant_qos) +{ + DDS_Security_long code = DDS_SECURITY_ERR_OK_CODE; + DDS_Security_IdentityHandle local_id_hdl = DDS_SECURITY_HANDLE_NIL; + DDS_Security_PermissionsHandle result; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + + /* Prepare testing environment. */ + local_id_hdl = test_setup(participant_qos); + CU_ASSERT_FATAL(local_id_hdl != DDS_SECURITY_HANDLE_NIL); + + /* Call the plugin with the invalid property. */ + result = g_access_control->validate_local_permissions( + g_access_control, + g_auth, + local_id_hdl, + 0, + participant_qos, + &exception); + + /* Be sure the plugin returned a failure. */ + CU_ASSERT(result == 0); + if (result == 0) + { + code = exception.code; + CU_ASSERT(exception.message != NULL); + printf("validate_local_permissions failed: (%d) %s\n", (int)exception.code, exception.message ? exception.message : "Error message missing"); + } + else + { + reset_exception(&exception); + g_access_control->return_permissions_handle(g_access_control, result, &exception); + } + reset_exception(&exception); + + /* Cleanup the testing environment. */ + test_teardown(local_id_hdl); + + return code; +} + +/* Use with invalid file link for certificate, permission or + * governance. The local permissions check should fail.*/ +static DDS_Security_long test_invalid_file_uri(const char *certificate_filename, const char *permission_filename, const char *governance_filename) +{ + DDS_Security_long code = DDS_SECURITY_ERR_OK_CODE; + DDS_Security_Qos participant_qos; + + qos_init_file(&participant_qos, + certificate_filename, + permission_filename, + governance_filename); + + code = test_failure_scenario(&participant_qos); + + qos_deinit(&participant_qos); + + return code; +} + +/* Use with invalid data for certificate, permission or governance. + * The local permissions check should fail.*/ +static DDS_Security_long test_invalid_data_uri(const char *certificate_filename, const char *permission_filename, const char *governance_filename) +{ + DDS_Security_long code = DDS_SECURITY_ERR_OK_CODE; + DDS_Security_Qos participant_qos; + + qos_init_data(&participant_qos, + certificate_filename, + permission_filename, + governance_filename); + + code = test_failure_scenario(&participant_qos); + + qos_deinit(&participant_qos); + + return code; +} + +/* Generate uri's with invalid types for certificate, permission + * or governance. The local permissions check should fail.*/ +static DDS_Security_long test_invalid_type_uri(const char *certificate_filename, const char *permission_filename, const char *governance_filename) +{ + DDS_Security_long code = DDS_SECURITY_ERR_OK_CODE; + DDS_Security_Qos participant_qos; + + qos_init_type(&participant_qos, + certificate_filename, + permission_filename, + governance_filename); + + code = test_failure_scenario(&participant_qos); + qos_deinit(&participant_qos); + return code; +} + +/* Create properties in the QoS without actual values (NULL). + * The local permissions check should fail.*/ +static DDS_Security_long test_null_uri(const char *certificate_filename, const char *permission_filename, const char *governance_filename) +{ + DDS_Security_long code = DDS_SECURITY_ERR_OK_CODE; + DDS_Security_Qos participant_qos; + + qos_init_null(&participant_qos, + certificate_filename, + permission_filename, + governance_filename); + + code = test_failure_scenario(&participant_qos); + + qos_deinit(&participant_qos); + + return code; +} + +/* Get valid documents, but corrupt the signatures. + * The local permissions check should fail.*/ +static DDS_Security_long test_corrupted_signature(bool corrupt_permissions, bool corrupt_governance) +{ + DDS_Security_long code = DDS_SECURITY_ERR_OK_CODE; + DDS_Security_Property_t *prop = NULL; + DDS_Security_Qos participant_qos; + size_t len; + + /* Get data with valid signatures. */ + qos_init_data(&participant_qos, + "Test_Permissions_ca.pem", + "Test_Permissions_full.p7s", + "Test_Governance_full.p7s"); + + /* Only allow one signature to be corrupted. */ + CU_ASSERT_FATAL(corrupt_permissions != corrupt_governance); + + /* Corrupt the signature. */ + if (corrupt_permissions) + prop = dds_security_property_find(&(participant_qos.property.value), PROPERTY_PERMISSIONS); + if (corrupt_governance) + prop = dds_security_property_find(&(participant_qos.property.value), PROPERTY_GOVERNANCE); + + /* Just some (hardcoded) sanity checks. */ + CU_ASSERT_FATAL(prop != NULL); + CU_ASSERT_FATAL(prop->value != NULL); + len = strlen(prop->value); + CU_ASSERT_FATAL(len > 2250); + + /* Corrupt a byte somewhere in the signature. */ + prop->value[len - 75]--; + + code = test_failure_scenario(&participant_qos); + qos_deinit(&participant_qos); + return code; +} + +static void suite_validate_local_permissions_init(void) +{ + set_path_to_etc_dir(); +} + +static void suite_validate_local_permissions_fini(void) +{ + ddsrt_free(g_path_to_etc_dir); +} + +/* Supplying proper files should pass the local permissions check */ +CU_Test(ddssec_builtin_validate_local_permissions, valid_file, .init = suite_validate_local_permissions_init, .fini = suite_validate_local_permissions_fini) +{ + DDS_Security_IdentityHandle local_id_hdl = DDS_SECURITY_HANDLE_NIL; + DDS_Security_PermissionsHandle result; + DDS_Security_Qos participant_qos; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + + qos_init_file(&participant_qos, + "Test_Permissions_ca.pem", + "Test_Permissions_full.p7s", + "Test_Governance_full.p7s"); + local_id_hdl = test_setup(&participant_qos); + CU_ASSERT_FATAL(local_id_hdl != DDS_SECURITY_HANDLE_NIL); + + result = g_access_control->validate_local_permissions( + g_access_control, + g_auth, + local_id_hdl, + 0, + &participant_qos, + &exception); + + CU_ASSERT(result != 0); + if (result == 0) + { + printf("validate_local_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + else + { + g_access_control->return_permissions_handle(g_access_control, result, &exception); + } + reset_exception(&exception); + + test_teardown(local_id_hdl); + qos_deinit(&participant_qos); +} + +/* Supplying proper data should pass the local permissions check */ +CU_Test(ddssec_builtin_validate_local_permissions, valid_data, .init = suite_validate_local_permissions_init, .fini = suite_validate_local_permissions_fini) +{ + DDS_Security_IdentityHandle local_id_hdl = DDS_SECURITY_HANDLE_NIL; + DDS_Security_PermissionsHandle result; + DDS_Security_Qos participant_qos; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + + qos_init_data(&participant_qos, + "Test_Permissions_ca.pem", + "Test_Permissions_full.p7s", + "Test_Governance_full.p7s"); + local_id_hdl = test_setup(&participant_qos); + CU_ASSERT(local_id_hdl != DDS_SECURITY_HANDLE_NIL); + + result = g_access_control->validate_local_permissions( + g_access_control, + g_auth, + local_id_hdl, + 0, + &participant_qos, + &exception); + + CU_ASSERT(result != 0); + if (result == 0) + { + printf("validate_local_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + else + { + g_access_control->return_permissions_handle(g_access_control, result, &exception); + } + reset_exception(&exception); + + test_teardown(local_id_hdl); + qos_deinit(&participant_qos); +} + +/* Supplying no files but directories should fail the local permissions check. */ +CU_Test(ddssec_builtin_validate_local_permissions, uri_directories, .init = suite_validate_local_permissions_init, .fini = suite_validate_local_permissions_fini) +{ + DDS_Security_long code; + + /* Certificate points to a valid directory.*/ + code = test_invalid_file_uri("", + "Test_Permissions_full.p7s", + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE); + + /* Permission points to a valid directory. */ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "", + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE); + + /* Governance points to a valid directory.*/ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_full.p7s", + ""); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE); +} + +/* Supplying empty files should fail the local permissions check. */ +CU_Test(ddssec_builtin_validate_local_permissions, uri_empty_files, .init = suite_validate_local_permissions_init, .fini = suite_validate_local_permissions_fini) +{ + DDS_Security_long code; + + /* Certificate points to an empty file. */ + code = test_invalid_file_uri("Test_File_empty.txt", + "Test_Permissions_full.p7s", + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE); + + /* Permission points to an empty file. */ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_File_empty.txt", + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE); + + /* Governance points to an empty file. */ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_full.p7s", + "Test_File_empty.txt"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE); +} + +/* Supplying text files should fail the local permissions check. */ +CU_Test(ddssec_builtin_validate_local_permissions, uri_text_files, .init = suite_validate_local_permissions_init, .fini = suite_validate_local_permissions_fini) +{ + DDS_Security_long code; + + /* Certificate points to a file with only text. */ + code = test_invalid_file_uri("Test_File_text.txt", + "Test_Permissions_full.p7s", + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_CERTIFICATE_CODE); + + /* Permission points to a file with only text. */ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_File_text.txt", + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_SMIME_DOCUMENT_CODE); + + /* Governance points to a file with only text. */ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_full.p7s", + "Test_File_text.txt"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_SMIME_DOCUMENT_CODE); +} + +/* Not supplying files should fail the local permissions check. */ +CU_Test(ddssec_builtin_validate_local_permissions, uri_absent_files, .init = suite_validate_local_permissions_init, .fini = suite_validate_local_permissions_fini) +{ + DDS_Security_long code; + + /* Certificate points to a non-existing file.*/ + code = test_invalid_file_uri("Test_File_absent.txt", + "Test_Permissions_full.p7s", + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE); + + /* Permission points to a non-existing file.*/ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_File_absent.txt", + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE); + + /* Governance points to a non-existing file.*/ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_full.p7s", + "Test_File_absent.txt"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE); +} + +/* Not supplying file uris should fail the local permissions check. */ +CU_Test(ddssec_builtin_validate_local_permissions, uri_no_files, .init = suite_validate_local_permissions_init, .fini = suite_validate_local_permissions_fini) +{ + DDS_Security_long code; + + /* Certificate file uri doesn't point to anything.*/ + code = test_invalid_file_uri(NULL, + "Test_Permissions_full.p7s", + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE); + + /* Permission file uri doesn't point to anything.*/ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + NULL, + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE); + + /* Governance file uri doesn't point to anything.*/ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_full.p7s", + NULL); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE); +} + +/* Supplying empty data should fail the local permissions check. */ +CU_Test(ddssec_builtin_validate_local_permissions, uri_empty_data, .init = suite_validate_local_permissions_init, .fini = suite_validate_local_permissions_fini) +{ + DDS_Security_long code; + + /* Certificate is empty data.*/ + code = test_invalid_data_uri(NULL, + "Test_Permissions_full.p7s", + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_CERTIFICATE_CODE); + + /* Permission is empty data.*/ + code = test_invalid_data_uri("Test_Permissions_ca.pem", + NULL, + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_PERMISSION_DOCUMENT_PROPERTY_CODE); + + /* Governance is empty data.*/ + code = test_invalid_data_uri("Test_Permissions_ca.pem", + "Test_Permissions_full.p7s", + NULL); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_GOVERNANCE_DOCUMENT_PROPERTY_CODE); +} + +/* Supplying uris with invalid types should fail the local permissions check. */ +CU_Test(ddssec_builtin_validate_local_permissions, uri_invalid_types, .init = suite_validate_local_permissions_init, .fini = suite_validate_local_permissions_fini) +{ + DDS_Security_long code; + + /* Certificate doesn't point to anything: results in invalid type.*/ + code = test_invalid_type_uri(NULL, + "Test_Permissions_full.p7s", + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_CERTIFICATE_TYPE_NOT_SUPPORTED_CODE); + + /* Permission doesn't point to anything: results in invalid type.*/ + code = test_invalid_type_uri("Test_Permissions_ca.pem", + NULL, + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_URI_TYPE_NOT_SUPPORTED_CODE); + + /* Governance doesn't point to anything: results in invalid type*/ + code = test_invalid_type_uri("Test_Permissions_ca.pem", + "Test_Permissions_full.p7s", + NULL); + CU_ASSERT(code == DDS_SECURITY_ERR_URI_TYPE_NOT_SUPPORTED_CODE); +} + +/* Not supplying actual uris should fail the local permissions check. */ +CU_Test(ddssec_builtin_validate_local_permissions, uri_null, .init = suite_validate_local_permissions_init, .fini = suite_validate_local_permissions_fini) +{ + DDS_Security_long code; + + /* Certificate doesn't point to anything.*/ + code = test_null_uri(NULL, + "Test_Permissions_full.p7s", + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_MISSING_PROPERTY_CODE); + + /* Permission doesn't point to anything.*/ + code = test_null_uri("Test_Permissions_ca.pem", + NULL, + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_MISSING_PROPERTY_CODE); + + /* Governance doesn't point to anything.*/ + code = test_null_uri("Test_Permissions_ca.pem", + "Test_Permissions_full.p7s", + NULL); + CU_ASSERT(code == DDS_SECURITY_ERR_MISSING_PROPERTY_CODE); +} + +/* Corrupted signatures should fail the local permissions check. */ +CU_Test(ddssec_builtin_validate_local_permissions, corrupted_signatures, .init = suite_validate_local_permissions_init, .fini = suite_validate_local_permissions_fini) +{ + DDS_Security_long code; + + /* Corrupt permission signature.*/ + code = test_corrupted_signature(true /* Corrupt permissions? Yes. */, + false /* Corrupt governance? No. */); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_SMIME_DOCUMENT_CODE); + + /* Corrupt governance signature.*/ + code = test_corrupted_signature(false /* Corrupt permissions? No. */, + true /* Corrupt governance? Yes. */); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_SMIME_DOCUMENT_CODE); +} + +/* Unknown signatures should fail the local permissions check. */ +CU_Test(ddssec_builtin_validate_local_permissions, unknown_ca, .init = suite_validate_local_permissions_init, .fini = suite_validate_local_permissions_fini) +{ + DDS_Security_long code; + + /* Permission with unknown CA.*/ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_unknown_ca.p7s", + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_SMIME_DOCUMENT_CODE); + + /* Governance with unknown CA.*/ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_full.p7s", + "Test_Governance_unknown_ca.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_SMIME_DOCUMENT_CODE); +} + +/* Un-available signatures should fail the local permissions check. */ +CU_Test(ddssec_builtin_validate_local_permissions, not_signed, .init = suite_validate_local_permissions_init, .fini = suite_validate_local_permissions_fini) +{ + DDS_Security_long code; + + /* Permission not signed.*/ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_not_signed.p7s", + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_SMIME_DOCUMENT_CODE); + + /* Governance not signed.*/ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_full.p7s", + "Test_Governance_not_signed.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_SMIME_DOCUMENT_CODE); +} + +/* Permissions outside the validity data should fail the local */ +CU_Test(ddssec_builtin_validate_local_permissions, validity, .init = suite_validate_local_permissions_init, .fini = suite_validate_local_permissions_fini) +{ + DDS_Security_long code; + + /* Permission already expired.*/ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_expired.p7s", + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_CODE); + + /* Permission not yet valid.*/ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_notyet.p7s", + "Test_Governance_full.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_VALIDITY_PERIOD_NOT_STARTED_CODE); +} + +/* Permissions document does not contain a proper subject_name, + * which should fail the local permissions check. */ +CU_Test(ddssec_builtin_validate_local_permissions, subject_name, .init = suite_validate_local_permissions_init, .fini = suite_validate_local_permissions_fini) +{ + DDS_Security_long code; + + /* Permission document with unknown subject. */ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_unknown_subject.p7s", + "Test_Governance_check_create_participant.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_INVALID_SUBJECT_NAME_CODE); +} + +/* Documents with invalid xml should fail the local permissions check. */ +CU_Test(ddssec_builtin_validate_local_permissions, xml_invalid, .init = suite_validate_local_permissions_init, .fini = suite_validate_local_permissions_fini) +{ + DDS_Security_long code; + + /* Permission XML contains invalid domain id. */ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_invalid_data.p7s", + "Test_Governance_ok.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_CAN_NOT_PARSE_PERMISSIONS_CODE); + + /* Permission XML contains invalid domain id. */ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_invalid_element.p7s", + "Test_Governance_ok.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_CAN_NOT_PARSE_PERMISSIONS_CODE); + + /* Permission XML is missing the 'not before' validity tag.*/ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_lack_of_not_before.p7s", + "Test_Governance_ok.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_CAN_NOT_PARSE_PERMISSIONS_CODE); + + /* Permission XML is missing the 'not after' validity tag.*/ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_lack_of_not_after.p7s", + "Test_Governance_ok.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_CAN_NOT_PARSE_PERMISSIONS_CODE); + + /* Governance XML contains invalid encryption kind.*/ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_ok.p7s", + "Test_Governance_invalid_data.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_CAN_NOT_PARSE_GOVERNANCE_CODE); + + /* Governance XML contains unknown element.*/ + code = test_invalid_file_uri("Test_Permissions_ca.pem", + "Test_Permissions_ok.p7s", + "Test_Governance_invalid_element.p7s"); + CU_ASSERT(code == DDS_SECURITY_ERR_CAN_NOT_PARSE_GOVERNANCE_CODE); +} diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Governance_ok.p7s b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Governance_ok.p7s new file mode 100644 index 0000000..c39903f --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Governance_ok.p7s @@ -0,0 +1,114 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----DB94A190D9780A24156FB0E8F1E76B5F" + +This is an S/MIME signed message + +------DB94A190D9780A24156FB0E8F1E76B5F +Content-Type: text/plain + + + + + + + + + 0 + 230 + + + + + false + + + true + + + ENCRYPT + + + ENCRYPT + + + NONE + + + + + * + + + true + + + true + + + false + + + false + + + ENCRYPT + + + ENCRYPT + + + + + + +------DB94A190D9780A24156FB0E8F1E76B5F +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGSAYJKoZIhvcNAQcCoIIGOTCCBjUCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCAnswggJ3AgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggeQwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTgwOTEzMDczOTUwWjAvBgkqhkiG9w0BCQQxIgQgXv8DkvlwebXMwHDbNc0/Pc30 +gyG3xWCnwet49TRMWFsweQYJKoZIhvcNAQkPMWwwajALBglghkgBZQMEASowCwYJ +YIZIAWUDBAEWMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAOBggqhkiG9w0DAgIC +AIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwDQYJKoZI +hvcNAQEBBQAEggEANy8t0EFmv5j1n0+mMn2ut3Chu8PSJceC8gd34IiKq79uC1O3 +PbL9xgiJ2vz7QiTEEeNL2q+CG77cXOcHGUWa4nvbggr/9CqLfHEKGQxDfyXlJZfM +8l550xIXRRBOQ7ilOGLD4QJFfbf9XA4rMuRe8WEYN3FleAaYBJag1tMPg1SS6tgA +BBDM9b1kXHU319zYOk6kZFjlbwHv6XO22SEVRUpXrKudAI8hrGvwksF/+W0S/jS5 +NmYtj/1oMGlCGIaA5rs27H9CkgwrzoMQ3MsR98JlwEUSa4PEe8CClsIziOulQxsp +MicBlMWL0rzpBPVfPTE4gZ/kP7hGBDEQlRzVTA== + +------DB94A190D9780A24156FB0E8F1E76B5F-- + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_different_subject_representation.p7s b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_different_subject_representation.p7s new file mode 100644 index 0000000..13273ba --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_different_subject_representation.p7s @@ -0,0 +1,96 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----57B71E0E17C33E9E1569D11B98DA1D03" + +This is an S/MIME signed message + +------57B71E0E17C33E9E1569D11B98DA1D03 +Content-Type: text/plain + + + + + + /O=Internet Widgits Pty Ltd/ST=Some-State/C=NL/CN=CHAM500 cert + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + + + ALLOW + + + + +------57B71E0E17C33E9E1569D11B98DA1D03 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgocQS4FLDqU6X3kzlYhW9GLLt +ItKIWQ9ghIL29OEyHPcwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBADPtNnKmzgMNaoeAiyxH +0oO3D9qsLWlon9eG+ri3e4O4IBGAwPtwN92ah3OmqXeB7xqBlZwnR4jQIxwVl8eL +Zs2y7lJ6LxPYHJj6qERlYbRjS55X7Wnjcwy81w+yQelSLFcKvdmrV5HIuLbeskWw +WiJxu3Sxtett3NnJxV5za6C27pxGXmv+xdspUe1Zeoz7WjAA0ljOazSUXAyCriQH +LXSGjTM8Lgn/P8xJTVzGgxmLmGm9fAhhYk+25G9Fspomigvnj+B6HobEf4xKA/Mm +WPaLsNkLtbi954g5+EM9AOjpCR/2Ii1NB4lWeKGZLtbEm71dEUe2VDePy2ju+oOB +9ec= + +------57B71E0E17C33E9E1569D11B98DA1D03-- + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_different_subject_representation.xml b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_different_subject_representation.xml new file mode 100644 index 0000000..585030e --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_different_subject_representation.xml @@ -0,0 +1,44 @@ + + + + + /O=Internet Widgits Pty Ltd/ST=Some-State/C=NL/CN=CHAM500 cert + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + + + ALLOW + + + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_expired.p7s b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_expired.p7s new file mode 100644 index 0000000..bf35bf7 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_expired.p7s @@ -0,0 +1,243 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----11798C99B4C31493D0479BB8A2064C72" + +This is an S/MIME signed message + +------11798C99B4C31493D0479BB8A2064C72 +Content-Type: text/plain + + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2016-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 230 + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + CN=Spare cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 23 + + + 100 + 120 + + 200 + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + ALLOW + + + + +------11798C99B4C31493D0479BB8A2064C72 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgXPEkUvQgZwRMdZgxT8k/mrsJ +delB0E3RjpayHUkKYzowgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAA/TNULF62fO5mfjXm1L +Yk4Dg/5ZxAF/grDAjamo5v2fxGn6B1rrkj8YtyB1FEA0moM/cL31kNXNMqLvFdhY +lHCmX8x5PHkKzLihTIMx6diSCupBvvqUACeA7Ir1A3tMqW5tYYMg6sZ/YolgLLFG +8XmhttpEibtZm90MN3Xpsa4TiW5PlEWHC5ai3tyeyd/RCVoeQJVA0pAytmjdf2Mw +C3W/28tUxVCAjdlqXYap6jWZlNv/43P5HED837bF5iqoa1dTvDirca6WPanNjp28 +GQDi4bnD1kAk8wAKIm14qwS+fzxM3SKxJtdQuUCx+s/tPma4bLCqt843ok35SoWo +QKM= + +------11798C99B4C31493D0479BB8A2064C72-- + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_expired.xml b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_expired.xml new file mode 100644 index 0000000..f408942 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_expired.xml @@ -0,0 +1,191 @@ + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2016-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 230 + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + CN=Spare cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 23 + + + 100 + 120 + + 200 + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + ALLOW + + + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_invalid_data.p7s b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_invalid_data.p7s new file mode 100644 index 0000000..b3b969e --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_invalid_data.p7s @@ -0,0 +1,219 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----62BE4CE8CF1FCB0420A2F2884B1618E6" + +This is an S/MIME signed message + +------62BE4CE8CF1FCB0420A2F2884B1618E6 +Content-Type: text/plain + + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 430 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 230 + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 23 + + + 100 + 120 + + 200 + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + + +------62BE4CE8CF1FCB0420A2F2884B1618E6 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQghoicue+FOmdIHF9rpsNCfmjP ++ZyN+t9kCdmR68JCJU0wgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAI0BX2tu2DbQjvuzKG35 +myNBcOC9ZzRDqJEtmQhcY/2hAJzurlnclJVTEXFyXdpV4ywtA+lQvbtToh11AvnY +IY1QWNVm19mfO1J6m6PFu18tizd30sG7p1TZKxGB3zDeVVqmedZ+o7QJHv9/ixzz +Pyo2B9tG5Su94+ADc0LQNyGICjeMr7L6dhFDsm7fXBi8pMBKy/zEAynTA3r1ibsn +5zlizPMlad2HCaYv44x7Xksg9FSbzJwJpTiprbQbZSUPYk4WlfVz0l4plzRKu4AP +lCOsdRE6C6GQFnK5bLyndu3Ycp10niwfkfobruCDyigu+gjZtmmF/T7A8Xkk1uvx +fAM= + +------62BE4CE8CF1FCB0420A2F2884B1618E6-- + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_invalid_data.xml b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_invalid_data.xml new file mode 100644 index 0000000..5ebb397 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_invalid_data.xml @@ -0,0 +1,167 @@ + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 430 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 230 + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 23 + + + 100 + 120 + + 200 + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_missing_subject_component.p7s b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_missing_subject_component.p7s new file mode 100644 index 0000000..1362a86 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_missing_subject_component.p7s @@ -0,0 +1,96 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----DE8A6693E9678989859C23D21F4587AD" + +This is an S/MIME signed message + +------DE8A6693E9678989859C23D21F4587AD +Content-Type: text/plain + + + + + + /O=Internet Widgits Pty Ltd/ST=Some-State/CN=CHAM500 cert + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + + + ALLOW + + + + +------DE8A6693E9678989859C23D21F4587AD +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgrFwsV4SyJfHq+dBhrRXj6PlS +nZYIo1hJ+L29+U2Xpk0wgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAAt1pbdIgmqHNrruevrr +TUptMNDw6YzlmXpWAq3KZBGaeaiHpYbkI+WhJJee9hG7bF9NGI/SfjPhiaiTjk2X +XCgmFZJUQhY8pOWkVPSAhBxd+r4kQtRxo2Na148Z2nrxeqcLbk+SE1hxTwT2OgLh +HWHBoQofZcRFp36Z9v51fZHAZLbQ8pD45+oAe/7ElyrO80MnJc+2RUxcnLScT1J0 +ykgTsgrQxcVVZX6EFHhQxnzpqCbjGvpdGSnyojAFI4PuQ3uNiOTPTYqad4jf/vIq +YHngEXSMN8wkd8bopl1EPVdxDqKkXuwAb29Q6UvDWLQ4IDZkdHTWc/ojiKjxWsKF +wuQ= + +------DE8A6693E9678989859C23D21F4587AD-- + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_missing_subject_component.xml b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_missing_subject_component.xml new file mode 100644 index 0000000..de70a1c --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_missing_subject_component.xml @@ -0,0 +1,44 @@ + + + + + /O=Internet Widgits Pty Ltd/ST=Some-State/CN=CHAM500 cert + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + + + ALLOW + + + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_not_signed.p7s b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_not_signed.p7s new file mode 100644 index 0000000..8759d91 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_not_signed.p7s @@ -0,0 +1,33 @@ + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + + + * + + + + DENY + + + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_notyet.p7s b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_notyet.p7s new file mode 100644 index 0000000..7fd4098 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_notyet.p7s @@ -0,0 +1,243 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----F87E07CA6CCEAB50B03A143AC2354EB4" + +This is an S/MIME signed message + +------F87E07CA6CCEAB50B03A143AC2354EB4 +Content-Type: text/plain + + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2035-09-15T01:00:00 + 2046-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 230 + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + CN=Spare cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 23 + + + 100 + 120 + + 200 + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + ALLOW + + + + +------F87E07CA6CCEAB50B03A143AC2354EB4 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQg0GGu1gWhHWhfWnmg55AIr4tv +zMK0kIxNfJYQbb7LpJ8wgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBALsPI2+b0w+iUPJGJeMd +VdrY7s/GZYm6M8qOA5fmh3144bY1rZRjdHjXtLdaNDNN1Z5buRCiQcklAilf6O14 +7u6a5HR12N4LTbg3OYQplwz4ed/wBsL726htmkAK3JogGk5OVLqmmdrz3UOD8IaZ +wAfx2tpj3VJOVuW0XsqOrzQpnOjGWcPeOw6NAxRH1gLsxBP9HDz5+wrsKXjV/zG8 +dFTaZ0bKnBXTp5ccc9jB4qbcllC9nlJkJszGqvwOP7zWBAOXeU+joUGM4Bt+8Pmt +pKsVAmEqMpc368RMayDBWtTqUWpUKvDh4HSkuOGD4Hj5ViAoLFjisROhIK2d98XI +cRQ= + +------F87E07CA6CCEAB50B03A143AC2354EB4-- + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_notyet.xml b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_notyet.xml new file mode 100644 index 0000000..99fec50 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_notyet.xml @@ -0,0 +1,191 @@ + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2035-09-15T01:00:00 + 2046-09-15T01:00:00 + + + + + 0 + 230 + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 230 + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + DENY + + + CN=Spare cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 20 + 30 + + 0 + 23 + + + 100 + 120 + + 200 + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + K* + *OldMessage + OldMessanger + NewMessage + + + Apart + Bpa?t* + + + + + + + 0 + 23 + + + 100 + 120 + + 200 + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + P* + *WrongMessage + FakeMessanger + ChangedMessage + + + Apart + Bpa?t* + + + + aTagName1 + aTagValue1 + + + + + + ALLOW + + + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_ok.p7s b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_ok.p7s new file mode 100644 index 0000000..052075b --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_ok.p7s @@ -0,0 +1,85 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----6B91005B007BBA8EDE10CD1CE487DB27" + +This is an S/MIME signed message + +------6B91005B007BBA8EDE10CD1CE487DB27 +Content-Type: text/plain + + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + + + * + + + + DENY + + + + +------6B91005B007BBA8EDE10CD1CE487DB27 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQgl3LfUhn9L0vG/3QRPVYptcYw +/NH5HMN99aMe9JAT+LAwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAHe9vakfXPvbpgMeqlhG +SW6Z3uVA3Yri9bgQDpJ9daIUsM0/TLBSQVs85twTMXvqUSntKbfSGehxDQ9F+yje +mOEPMIwxOqcVyc2jpqoYsUWqpwiiZyk49DHUFrOfWJUx+rKdBftZWkxD05Wkovhk +2d4hGS/65Haoho4Z0AZwcyH+F52FZMiqw7I9FKrPlhxvJfQXmhIjOKtnvWnQ+Ar7 +YYiSrBEHMCy82LF1aKzz0nkL1SYWQHuQX475qoU4LMYY1J8WsD3rSBeq4GYZrl2K +X/JcOquMYqjfJLMYZY4fsc3FgEBkKNqJz1tDZ3ir24VMl+WsbEjVK8oXe/wt4V0U +aNQ= + +------6B91005B007BBA8EDE10CD1CE487DB27-- + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_ok.xml b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_ok.xml new file mode 100644 index 0000000..8759d91 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_ok.xml @@ -0,0 +1,33 @@ + + + + + CN=CHAM500 cert,O=Internet Widgits Pty Ltd,ST=Some-State,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + + + * + + + + DENY + + + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_unknown_ca.p7s b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_unknown_ca.p7s new file mode 100644 index 0000000..6a2905a --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_unknown_ca.p7s @@ -0,0 +1,87 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----7FBACED8776E5A4CF7612C83F9C33E17" + +This is an S/MIME signed message + +------7FBACED8776E5A4CF7612C83F9C33E17 +Content-Type: text/plain + + + + + + /C=NL/ST=Some-State/O=ADLINK Technolocy Inc./CN=adlinktech.com + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + + + * + + + + DENY + + + + +------7FBACED8776E5A4CF7612C83F9C33E17 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGywYJKoZIhvcNAQcCoIIGvDCCBrgCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggPKMIIDxjCCAq4CCQCBuTktP0h8BDANBgkqhkiG9w0BAQsFADCB +pDEWMBQGA1UEBwwNTG9jYWxpdHkgTmFtZTEhMB8GA1UECwwYT3JnYW5pemF0aW9u +YWwgVW5pdCBOYW1lMRwwGgYJKoZIhvcNAQkBFg1FbWFpbCBBZGRyZXNzMQswCQYD +VQQGEwJVUzELMAkGA1UECAwCTkoxGjAYBgNVBAoMEUV4YW1wbGUgU2lnbmVyIENB +MRMwEQYDVQQDDApFeGFtcGxlIENBMB4XDTE4MDgxNTA4NTE0MVoXDTQzMDgwOTA4 +NTE0MVowgaQxFjAUBgNVBAcMDUxvY2FsaXR5IE5hbWUxITAfBgNVBAsMGE9yZ2Fu +aXphdGlvbmFsIFVuaXQgTmFtZTEcMBoGCSqGSIb3DQEJARYNRW1haWwgQWRkcmVz +czELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5KMRowGAYDVQQKDBFFeGFtcGxlIFNp +Z25lciBDQTETMBEGA1UEAwwKRXhhbXBsZSBDQTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBALStAQ0yjM2qAWwsOXdX3hiyoZ6DDHWOTNI5LoCZGaN9rUZe +MY0waSxWNQ0ruURgZISeOFkdQTAE81Em+UaZI+MZvfYcEcSlVtF6yve/WnIzRYWu +f917moMCAInktfch4E6mskr4h7n+9sEz+3GsQS8SQRtwUe+PiXzjZrqHSbLC4Kn3 +/b8Mt+Ww3a4FyjHDZQJZsGSvrScr0Gq3xeKfMwb+KYNEnmh0o4os0gEGA4KUR+/1 +YDl1NmxQnm/AIMqwJzeaezBoMn0Nsi+OlAms85imGURNj9BCEJZBWwuuNL5ECDAq +WLOM3AKUsApVgtGd8/OLWW1RwYkW8uqTtkIR87MCAwEAATANBgkqhkiG9w0BAQsF +AAOCAQEAokKC77/kvxlObLSwkT5+7+S+DeznLBRiGVEh8+9PQw1q91sjiOZWf0e3 +T3XPH7CR/NDYoQJkrsqzIwKYrj41z/1jAs+HkH45NpTFiGlUFXNs5iwNh4RUqgf4 +e78Mge4q7pHMFzWTEwEn4DJMGcDDjLW1kN8GobGwHR7O0MpAJKrqcBSo+SPomnQv +TgiEMQ+Vlz0EJx6JPsq8c7HrxlSdeDAAWIOww/wcGyzlpYEoyz6voSSfdhMt5iy5 +k5BvhBJnTiJTasCHy9KRuis/6qpTZKEj0d7J7LAqpGh8oRIphMwCbFYQT0QBgV6p +gM8Ufss/RZ6CshMNxz7KtIYpvmxPPTGCAsUwggLBAgEBMIGyMIGkMRYwFAYDVQQH +DA1Mb2NhbGl0eSBOYW1lMSEwHwYDVQQLDBhPcmdhbml6YXRpb25hbCBVbml0IE5h +bWUxHDAaBgkqhkiG9w0BCQEWDUVtYWlsIEFkZHJlc3MxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJOSjEaMBgGA1UECgwRRXhhbXBsZSBTaWduZXIgQ0ExEzARBgNVBAMM +CkV4YW1wbGUgQ0ECCQCBuTktP0h8BDANBglghkgBZQMEAgEFAKCB5DAYBgkqhkiG +9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xODA5MTMwOTIzMDNa +MC8GCSqGSIb3DQEJBDEiBCCvP08gFBO7651mPPDFQ2suhL+eprGCGuRLXmiBmdvx +ITB5BgkqhkiG9w0BCQ8xbDBqMAsGCWCGSAFlAwQBKjALBglghkgBZQMEARYwCwYJ +YIZIAWUDBAECMAoGCCqGSIb3DQMHMA4GCCqGSIb3DQMCAgIAgDANBggqhkiG9w0D +AgIBQDAHBgUrDgMCBzANBggqhkiG9w0DAgIBKDANBgkqhkiG9w0BAQEFAASCAQB/ +4EQel+0LsmiNFCUjWM68u4ZvPtFBpeDe456DJuG6QR0LIzW42U7N4P2ZTIqjpGZx +YekBCNdkiVy6ER5IA4WfcKd6zXZEuXVxkMrGpJlqGdd+IdZpTsrBygGZJS4vMUfD +/6ty6OycET88RmJIu4V/TM3yLVKzHuj6TxCXb4OIYx8g3mdXUwUrp6DGgqggRSPJ +tatbpnqGZGcvty8MusXVnjnEwUWnJ/jojypY3MyL4MTbjufjv0K6NKQ3RzoLssot +SLq0YDLwvX/s9sLXDCedAwFXBS/6Qv56v0M2x4o8e3Eul7gGTMuCd/dJ0BhF8CW+ +IGxR5I3xXssh/AuWRRtV + +------7FBACED8776E5A4CF7612C83F9C33E17-- + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_unknown_subject.p7s b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_unknown_subject.p7s new file mode 100644 index 0000000..fb488c7 --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_unknown_subject.p7s @@ -0,0 +1,85 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----7B161F9203F175A7F82A389A3E044741" + +This is an S/MIME signed message + +------7B161F9203F175A7F82A389A3E044741 +Content-Type: text/plain + + + + + + gibberish + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + + + * + + + + DENY + + + + +------7B161F9203F175A7F82A389A3E044741 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIGXgYJKoZIhvcNAQcCoIIGTzCCBksCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB +CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK +DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv +bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC +TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s +b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID +ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w +icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs +DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 +BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy +SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV +HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv +RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ +ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X +Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 +yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt +lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 ++OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb +6SDB340BFmtgDHbFHTGCApEwggKNAgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV +BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x +FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB +BQCggfowGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN +MTkwMzI5MTMwODAzWjAvBgkqhkiG9w0BCQQxIgQg44QSCYJrKGm9hdPbOKQjrnQ8 +LXMSbo0mve1cRKvrm3gwgY4GCSqGSIb3DQEJDzGBgDB+MAsGCWCGSAFlAwQBKjAI +BgYqhQMCAgkwCAYGKoUDAgIVMAsGCWCGSAFlAwQBFjALBglghkgBZQMEAQIwCgYI +KoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0GCCqGSIb3DQMCAgFAMAcGBSsOAwIH +MA0GCCqGSIb3DQMCAgEoMA0GCSqGSIb3DQEBAQUABIIBAH/fJ90OwloC73faPAGC +VRZrhW/gSsy/1VnprvWdDAU1ZZK+srIISFZAy19LcApTis0Vy9yz2PG8pue49R+y +UF6mCDSuN/l9SRBdUN+CXQdQ8sGq5SHXNhGzSX/nbR20ol4cSUMpKlEGx66E0KUW +tkk8HzYw7aHMiwK2E2Y0sbm/M/rdmAbgEoywYfvc25V4FHP66TstfCLBjN9Hz3bH +WcrCZuPjZo6vBd/rIJQSlgH81aCWn5RfCIccbc3iogwzIhYxAr6d+4do3LNa6H80 +W6CMgl0AnWFfa4QwnXFUzb1/W2rFjHp453w1Cbqk4Ll4ZlVJr4fzIuyuJMQlMrmK +1P0= + +------7B161F9203F175A7F82A389A3E044741-- + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_unknown_subject.xml b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_unknown_subject.xml new file mode 100644 index 0000000..8a55faf --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/etc/Test_Permissions_unknown_subject.xml @@ -0,0 +1,33 @@ + + + + + gibberish + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + + + * + + + + DENY + + + diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/src/validate_remote_permissions_utests.c b/src/security/builtin_plugins/tests/validate_remote_permissions/src/validate_remote_permissions_utests.c new file mode 100644 index 0000000..137137a --- /dev/null +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/src/validate_remote_permissions_utests.c @@ -0,0 +1,1068 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include +#include + +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/io.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/types.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/core/dds_security_utils.h" +#include "CUnit/CUnit.h" +#include "CUnit/Test.h" +#include "common/src/loader.h" +#include "config_env.h" + +static const char *ACCESS_PERMISSIONS_TOKEN_ID = "DDS:Access:Permissions:1.0"; +static const char *AUTH_PROTOCOL_CLASS_ID = "DDS:Auth:PKI-DH:1.0"; + +static const char *PROPERTY_IDENTITY_CA = "dds.sec.auth.identity_ca"; +static const char *PROPERTY_PRIVATE_KEY = "dds.sec.auth.private_key"; +static const char *PROPERTY_IDENTITY_CERT = "dds.sec.auth.identity_certificate"; +static const char *PROPERTY_PERMISSIONS_CA = "dds.sec.access.permissions_ca"; +static const char *PROPERTY_PERMISSIONS = "dds.sec.access.permissions"; +static const char *PROPERTY_GOVERNANCE = "dds.sec.access.governance"; + +static const char *PROPERTY_PERMISSIONS_CA_SN = "dds.perm_ca.sn"; +static const char *PROPERTY_PERMISSIONS_CA_ALGO = "dds.perm_ca.algo"; +static const char *PROPERTY_C_ID = "c.id"; +static const char *PROPERTY_C_PERM = "c.perm"; + +static const char *SUBJECT_NAME_PERMISSIONS_CA = "C=NL, ST=Some-State, O=ADLINK Technolocy Inc., CN=adlinktech.com"; +static const char *RSA_2048_ALGORITHM_NAME = "RSA-2048"; + +static const char *RELATIVE_PATH_TO_ETC_DIR = "/validate_remote_permissions/etc/"; + +static const char *identity_certificate = + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIEQTCCAymgAwIBAgIINpuaAAnrQZIwDQYJKoZIhvcNAQELBQAwXzELMAkGA1UE\n" + "BhMCTkwxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp\n" + "ZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAxMPQ0hBTTUwMCByb290IGNhMCAXDTE3MDIy\n" + "MjIyMjIwMFoYDzIyMjIwMjIyMjIyMjAwWjBcMQswCQYDVQQGEwJOTDETMBEGA1UE\n" + "CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk\n" + "MRUwEwYDVQQDEwxDSEFNNTAwIGNlcnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\n" + "ggEKAoIBAQDCpVhivH/wBIyu74rvQncnSZqKyspN6CvD1pmV9wft5PHhVt9jV79v\n" + "gSub5LADoRHAgFdv9duYgBr17Ob6uRrIY4B18CcrCjhQcC4gjx8y2jl9PeYm+qYD\n" + "3o44FYBrBq0QCnrQgKsb/qX9Z+Mw/VUiw65x68W876LEHQQoEgT4kxSuagwBoVRk\n" + "ePD6fYAKmT4XS3x+O0v+rHESTcsKF6yMadgp7h3eH1b8kJTzSx8JV9Zzq++mxjox\n" + "qhbBVP5nDze2hhSIeCkCvSrx7efkgKS4AQXa5/Z44GiAu1TfXXUqdic9rxwD0edn\n" + "ajNElnZe7sjok/0yuqvH+2hSqpNva/zpAgMBAAGjggEAMIH9MAwGA1UdDwQFAwMH\n" + "/4AwgewGA1UdJQSB5DCB4QYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDAwYI\n" + "KwYBBQUHAwQGCCsGAQUFBwMIBgorBgEEAYI3AgEVBgorBgEEAYI3AgEWBgorBgEE\n" + "AYI3CgMBBgorBgEEAYI3CgMDBgorBgEEAYI3CgMEBglghkgBhvhCBAEGCysGAQQB\n" + "gjcKAwQBBggrBgEFBQcDBQYIKwYBBQUHAwYGCCsGAQUFBwMHBggrBgEFBQgCAgYK\n" + "KwYBBAGCNxQCAgYIKwYBBQUHAwkGCCsGAQUFBwMNBggrBgEFBQcDDgYHKwYBBQID\n" + "BTANBgkqhkiG9w0BAQsFAAOCAQEAawdHy0Xw7nTK2ltp91Ion6fJ7hqYuj///zr7\n" + "Adt6uonpDh/xl3esuwcFimIJrJrHujnGkL0nLddRCikmnzuBMNDWS6yq0/Ckl/YG\n" + "yjNr44dlX24wo+MVAgkj3/8CyWDZ3a8kBg9QT3bs2SqbjmhTrXN1DRyf9S5vJysE\n" + "I7V1gTN66BeKL64hOrAlRVrEu8Ds6TWL6Q/YH+61ViZkoLTeSaPjH4nknaFr4C35\n" + "iji0JhkyfRHRRVPHFnaj25AkxOrSV64qVKoTMjDl5fji5iMGtjm6iJ7q05ml/qDl\n" + "nLotHXemZNvYhbwUmRzbt4Dls9EMH4VRbP85I94nM5TAvtHVNA==\n" + "-----END CERTIFICATE-----\n"; + +static const char *identity_ca = + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIEmTCCA4GgAwIBAgIIZ5gEIUFhO5wwDQYJKoZIhvcNAQELBQAwXzELMAkGA1UE\n" + "BhMCTkwxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp\n" + "ZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAxMPQ0hBTTUwMCByb290IGNhMCAXDTE4MDIx\n" + "MjE1MDUwMFoYDzIyMjIwMjIyMjIyMjAwWjBfMQswCQYDVQQGEwJOTDETMBEGA1UE\n" + "CBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk\n" + "MRgwFgYDVQQDEw9DSEFNNTAwIHJvb3QgY2EwggEiMA0GCSqGSIb3DQEBAQUAA4IB\n" + "DwAwggEKAoIBAQC6Fa3TheL+UrdZCp9GhU/2WbneP2t/avUa3muwDttPxeI2XU9k\n" + "ZjBR95mAXme4SPXHk5+YDN319AqIje3oKhzky/ngvKH2GkoJKYxWnuDBfMEHdViz\n" + "2Q9/xso2ZvH50ukwWa0pfx2/EVV1wRxeQcRd/UVfq3KTJizG0M88mOYvGEAw3LFf\n" + "zef7k1aCuOofQmBvLukUudcYpMzfyHFp7lQqU4CcrrR5RtmfiUfrWfdGLea2iPDB\n" + "pJgN8ESOMwEHtOTEBDclYnH9L4t7CHQz+fXXS5IWFsDK9fCMQjnxDsDVeNrNzTYL\n" + "FaZrMg9S6IUQCEsQWsnq5weS8omOpVLUm9klAgMBAAGjggFVMIIBUTAMBgNVHRME\n" + "BTADAQH/MB0GA1UdDgQWBBQg2FZB/j8uWDVnJhjwXkX278znSTAfBgNVHSMEGDAW\n" + "gBQg2FZB/j8uWDVnJhjwXkX278znSTAPBgNVHQ8BAf8EBQMDB/+AMIHvBgNVHSUB\n" + "Af8EgeQwgeEGCCsGAQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwMGCCsGAQUFBwME\n" + "BggrBgEFBQcDCAYKKwYBBAGCNwIBFQYKKwYBBAGCNwIBFgYKKwYBBAGCNwoDAQYK\n" + "KwYBBAGCNwoDAwYKKwYBBAGCNwoDBAYJYIZIAYb4QgQBBgsrBgEEAYI3CgMEAQYI\n" + "KwYBBQUHAwUGCCsGAQUFBwMGBggrBgEFBQcDBwYIKwYBBQUIAgIGCisGAQQBgjcU\n" + "AgIGCCsGAQUFBwMJBggrBgEFBQcDDQYIKwYBBQUHAw4GBysGAQUCAwUwDQYJKoZI\n" + "hvcNAQELBQADggEBAKHmwejWRwGE1wf1k2rG8SNRV/neGsZ6Qfqf6co3TpR/Wi1s\n" + "iZDvSeT/rbqNBS7z34xnG88NIUwu00y78e8Mfon31ZZbK4Uo7fla9/D3ukdJqPQC\n" + "LKdbKJjR2kH+KCukY/1rghjJ8/X+t2egBit0LCOdsFCl07Sfksb9kpGUIZSFcYYm\n" + "geqhjhoNwxazzHiw+QWHC5HG9248JIizBmy1aymNWuMnPudhjHAnPcsIlqMVNq3t\n" + "Rv9ap7S8JeCxHVRPJvJeCwXWvW3dW/v3xH52Yn/fqRblN1w9Fxz5NhopKx0gj/Jd\n" + "sw2N4Fk4gaOWEolFpa0bwNw8nAx7moehZpowzfw=\n" + "-----END CERTIFICATE-----\n"; + +static const char *private_key = + "data:,-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEogIBAAKCAQEAwqVYYrx/8ASMru+K70J3J0maisrKTegrw9aZlfcH7eTx4Vbf\n" + "Y1e/b4Erm+SwA6ERwIBXb/XbmIAa9ezm+rkayGOAdfAnKwo4UHAuII8fMto5fT3m\n" + "JvqmA96OOBWAawatEAp60ICrG/6l/WfjMP1VIsOucevFvO+ixB0EKBIE+JMUrmoM\n" + "AaFUZHjw+n2ACpk+F0t8fjtL/qxxEk3LChesjGnYKe4d3h9W/JCU80sfCVfWc6vv\n" + "psY6MaoWwVT+Zw83toYUiHgpAr0q8e3n5ICkuAEF2uf2eOBogLtU3111KnYnPa8c\n" + "A9HnZ2ozRJZ2Xu7I6JP9Mrqrx/toUqqTb2v86QIDAQABAoIBAC1q32DKkx+yMBFx\n" + "m32QiLUGG6VfBC2BixS7MkMnzRXZYgcuehl4FBc0kLRjfB6cqsO8LqrVN1QyMBhK\n" + "GutN3c38SbE7RChqzhEW2+yE+Mao3Nk4ZEecHLiyaYT0n25ZtHAVwep823BAzwJ+\n" + "BykbM45VEpNKbG1VjSktjBa9faNyZiZAEJEjVyla+6R8N4kHV52LbZcLjvJv3IQ2\n" + "iPYRrmMyI5C23qTni0vy7yJbAXBo3CqgSlwie9FARBWT7Puu7F4mF1O1c/SnTysw\n" + "Tm3e5FzgfHipQbnRVn0w4rDprPMKmPxMnvf/Wkw0zVgNadp1Tc1I6Yj525DEQ07i\n" + "2gIn/gECgYEA4jNnY1u2Eu7x3pAQF3dRO0x35boVtuq9iwQk7q+uaZaK4RJRr+0Y\n" + "T68S3bPnfer6SHvcxtST89Bvs/j/Ky4SOaX037UYjFh6T7OIzPl+MzO1yb+VOBT6\n" + "D6FVGEJGp8ZAITU1OfJPeTYViUeEC8tHFGoKUCk50FbB6jOf1oKtv/ECgYEA3EnB\n" + "Y7kSbJJaUuj9ciFUL/pAno86Cim3VjegK1wKgEiyDb610bhoMErovPwfVJbtcttG\n" + "eKJNuwizkRcVbj+vpjDvqqaP5eMxLl6/Nd4haPMJYzGo88Z8NJpwFRNF2KEWjOpQ\n" + "2NEvoCeRtVulCJyka2Tpljzw8cOXkxhPOe2UhHkCgYBo3entj0QO7QXm56T+LAvV\n" + "0PK45xdQEO3EuCwjGAFk5C0IgUSrqeCeeIzniZMltj1IQ1wsNbtNynEu3530t8wt\n" + "O7oVyFBUKGSz9IjUdkpClJOPr6kPMfJoMqRPtdIpz+hFPPSrI6IikKdVWHloOlp+\n" + "pVaYqTQrWT1XRY2xli3VEQKBgGySmZN6Cx+h/oywswIGdUT0VdcQhq2to+QFpJba\n" + "VX6m1cM6hMip2Ag9U3qZ1SNPBBdBBfm9HQybHE3dj713/C2wHuAAGhpXIM1W+20k\n" + "X1knuC/AsSH9aQhQOf/ZMOq1crTfZBuI9q0782/sjGmzMsKPySU4QhUWruVb7OiD\n" + "NVkZAoGAEvihW7G+8/iOE40vGHyBqUeopAAWLciTAUIEwM/Oi3BYfNWNTWF/FWNc\n" + "nMvCZPYigY8C1vO+1iT2Frtd3CIU+f01Q3fJNJoRLlEiKLNZUJRF48OKUqjKSmsi\n" + "w6pucFO40z05YW7utApj4L82rZnOS0pd1tUI1yexqvj0i4ThJfk=\n" + "-----END RSA PRIVATE KEY-----\n"; + +static const char *permissions_ca = + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEBCwUAMFwxCzAJBgNV\n" + "BAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQKDBZBRExJTksgVGVj\n" + "aG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNvbTAgFw0xODA3MzAx\n" + "MjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMCTkwxEzARBgNVBAgM\n" + "ClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4xFzAV\n" + "BgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" + "CgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blIDehV6XCxrnGXusTCD\n" + "uFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9wicp3BGSpZZax/TcO\n" + "NjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLsDFFC+a0qn2RFh37r\n" + "cWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074BRDXVivx+wVD951L\n" + "FNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiySogRWAmKhysLQudu\n" + "kHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNVHQ4EFgQURWMbWvBK\n" + "ZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJvRV1/tyc1R82k0+gw\n" + "DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ysVtvHnk2hpu9yND\n" + "LCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9XVh0rGoR/6nHzo3TI\n" + "eiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9yghhKHHqNDvSsAL0\n" + "KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbtlLX3QnwVOmaRyzyl\n" + "PiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42+OyLqcH1rKT6Xhcs\n" + "hjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb6SDB340BFmtgDHbF\n" + "HQ==\n" + "-----END CERTIFICATE-----\n"; + +static struct plugins_hdl *plugins = NULL; +static dds_security_authentication *auth = NULL; +static dds_security_access_control *access_control = NULL; +static DDS_Security_IdentityHandle local_identity_handle = DDS_SECURITY_HANDLE_NIL; +static DDS_Security_IdentityHandle remote_identity_handle = DDS_SECURITY_HANDLE_NIL; +static DDS_Security_PermissionsHandle local_permissions_handle = DDS_SECURITY_HANDLE_NIL; +static DDS_Security_GUID_t local_participant_guid; +static char *g_path_to_etc_dir = NULL; + +static void dds_security_property_init(DDS_Security_PropertySeq *seq, DDS_Security_unsigned_long size) +{ + seq->_length = size; + seq->_maximum = size; + seq->_buffer = ddsrt_malloc(size * sizeof(DDS_Security_Property_t)); + memset(seq->_buffer, 0, size * sizeof(DDS_Security_Property_t)); +} + +static void dds_security_property_deinit(DDS_Security_PropertySeq *seq) +{ + uint32_t i; + + for (i = 0; i < seq->_length; i++) + { + ddsrt_free(seq->_buffer[i].name); + ddsrt_free(seq->_buffer[i].value); + } + ddsrt_free(seq->_buffer); +} + +static void reset_exception(DDS_Security_SecurityException *ex) +{ + ex->code = 0; + ex->minor_code = 0; + ddsrt_free(ex->message); + ex->message = NULL; +} + +static void fill_participant_qos(DDS_Security_Qos *qos, const char *permission_filename, const char *governance_filename) +{ + char *permission_uri; + char *governance_uri; + + ddsrt_asprintf(&permission_uri, "file:%s%s", g_path_to_etc_dir, permission_filename); + ddsrt_asprintf(&governance_uri, "file:%s%s", g_path_to_etc_dir, governance_filename); + + memset(qos, 0, sizeof(*qos)); + dds_security_property_init(&qos->property.value, 6); + qos->property.value._buffer[0].name = ddsrt_strdup(PROPERTY_IDENTITY_CERT); + qos->property.value._buffer[0].value = ddsrt_strdup(identity_certificate); + qos->property.value._buffer[1].name = ddsrt_strdup(PROPERTY_IDENTITY_CA); + qos->property.value._buffer[1].value = ddsrt_strdup(identity_ca); + qos->property.value._buffer[2].name = ddsrt_strdup(PROPERTY_PRIVATE_KEY); + qos->property.value._buffer[2].value = ddsrt_strdup(private_key); + qos->property.value._buffer[3].name = ddsrt_strdup(PROPERTY_PERMISSIONS_CA); + qos->property.value._buffer[3].value = ddsrt_strdup(permissions_ca); + qos->property.value._buffer[4].name = ddsrt_strdup(PROPERTY_PERMISSIONS); + qos->property.value._buffer[4].value = ddsrt_strdup(permission_uri); + qos->property.value._buffer[5].name = ddsrt_strdup(PROPERTY_GOVERNANCE); + qos->property.value._buffer[5].value = ddsrt_strdup(governance_uri); + + ddsrt_free(permission_uri); + ddsrt_free(governance_uri); +} + +static void fill_permissions_token(DDS_Security_PermissionsToken *token) +{ + memset(token, 0, sizeof(DDS_Security_PermissionsToken)); + + token->class_id = ddsrt_strdup(ACCESS_PERMISSIONS_TOKEN_ID); + token->properties._length = token->properties._maximum = 2; + token->properties._buffer = DDS_Security_PropertySeq_allocbuf(2); + + token->properties._buffer[0].name = ddsrt_strdup(PROPERTY_PERMISSIONS_CA_SN); + token->properties._buffer[0].value = ddsrt_strdup(SUBJECT_NAME_PERMISSIONS_CA); + + token->properties._buffer[1].name = ddsrt_strdup(PROPERTY_PERMISSIONS_CA_ALGO); + token->properties._buffer[1].value = ddsrt_strdup(RSA_2048_ALGORITHM_NAME); +} + +static int fill_peer_credential_token(DDS_Security_AuthenticatedPeerCredentialToken *token, const char *permission_filename) +{ + int result = 1; + char *permission_uri; + char *permission_data; + + memset(token, 0, sizeof(DDS_Security_AuthenticatedPeerCredentialToken)); + + ddsrt_asprintf(&permission_uri, "%s%s", g_path_to_etc_dir, permission_filename); + + permission_data = load_file_contents(permission_uri); + + if (permission_data) + { + token->class_id = ddsrt_strdup(AUTH_PROTOCOL_CLASS_ID); + token->properties._length = token->properties._maximum = 2; + token->properties._buffer = DDS_Security_PropertySeq_allocbuf(2); + + token->properties._buffer[0].name = ddsrt_strdup(PROPERTY_C_ID); + token->properties._buffer[0].value = ddsrt_strdup(&identity_certificate[6]); + + token->properties._buffer[1].name = ddsrt_strdup(PROPERTY_C_PERM); + token->properties._buffer[1].value = permission_data; + } + else + { + ddsrt_free(permission_data); + result = 0; + } + ddsrt_free(permission_uri); + + return result; +} + +static void corrupt_permission_signature(DDS_Security_AuthenticatedPeerCredentialToken *token) +{ + DDS_Security_string permissions; + size_t len; + + /* It is expected that the permissions are available in a fixed location. */ + CU_ASSERT_FATAL(token != NULL); + CU_ASSERT_FATAL(token->properties._buffer != NULL); + CU_ASSERT_FATAL(token->properties._length == 2); + CU_ASSERT_FATAL(token->properties._buffer[1].name != NULL); + CU_ASSERT_FATAL(token->properties._buffer[1].value != NULL); + CU_ASSERT_FATAL(strcmp(token->properties._buffer[1].name, PROPERTY_C_PERM) == 0); + + /* Corrupt a byte somewhere in the signature. */ + permissions = token->properties._buffer[1].value; + CU_ASSERT_FATAL(permissions != NULL); + len = strlen(permissions); + CU_ASSERT_FATAL(len > 100); + permissions[len - 75]--; +} + +static int validate_local_identity_and_permissions(void) +{ + int res = 0; + DDS_Security_ValidationResult_t result; + DDS_Security_DomainId domain_id = 0; + DDS_Security_Qos participant_qos; + DDS_Security_GUID_t candidate_participant_guid; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_GuidPrefix_t prefix = {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb}; + DDS_Security_EntityId_t entityId = {{0xb0, 0xb1, 0xb2}, 0x1}; + + memset(&local_participant_guid, 0, sizeof(local_participant_guid)); + memcpy(&candidate_participant_guid.prefix, &prefix, sizeof(prefix)); + memcpy(&candidate_participant_guid.entityId, &entityId, sizeof(entityId)); + + fill_participant_qos(&participant_qos, "Test_Permissions_ok.p7s", "Test_Governance_ok.p7s"); + + /* Now call the function. */ + result = auth->validate_local_identity( + auth, + &local_identity_handle, + &local_participant_guid, + domain_id, + &participant_qos, + &candidate_participant_guid, + &exception); + + if (result != DDS_SECURITY_VALIDATION_OK) + { + res = -1; + printf("validate_local_identity_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + + reset_exception(&exception); + + if (res == 0) + { + local_permissions_handle = access_control->validate_local_permissions( + access_control, + auth, + local_identity_handle, + 0, + &participant_qos, + &exception); + + if (local_permissions_handle == DDS_SECURITY_HANDLE_NIL) + { + res = -1; + printf("validate_local_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + } + + dds_security_property_deinit(&participant_qos.property.value); + + return res; +} + +static void clear_local_identity_and_permissions(void) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_boolean success; + + if (local_permissions_handle != DDS_SECURITY_HANDLE_NIL) + { + success = access_control->return_permissions_handle(access_control, local_permissions_handle, &exception); + if (!success) + printf("return_permission_handle failed: %s\n", exception.message ? exception.message : "Error message missing"); + reset_exception(&exception); + } + + if (local_identity_handle != DDS_SECURITY_HANDLE_NIL) + { + success = auth->return_identity_handle(auth, local_identity_handle, &exception); + if (!success) + printf("return_identity_handle failed: %s\n", exception.message ? exception.message : "Error message missing"); + reset_exception(&exception); + } +} + +static void set_path_to_etc_dir(void) +{ + ddsrt_asprintf(&g_path_to_etc_dir, "%s%s", CONFIG_ENV_TESTS_DIR, RELATIVE_PATH_TO_ETC_DIR); +} + +static void suite_validate_remote_permissions_init(void) +{ + plugins = load_plugins(&access_control, &auth, NULL /* Cryptograpy */); + CU_ASSERT_FATAL(plugins != NULL); + set_path_to_etc_dir(); + validate_local_identity_and_permissions(); +} + +static void suite_validate_remote_permissions_fini(void) +{ + clear_local_identity_and_permissions(); + unload_plugins(plugins); + ddsrt_free(g_path_to_etc_dir); +} + +CU_Test(ddssec_builtin_validate_remote_permissions, valid_permissions, .init = suite_validate_remote_permissions_init, .fini = suite_validate_remote_permissions_fini) +{ + DDS_Security_PermissionsHandle result; + DDS_Security_PermissionsToken permissions_token; + DDS_Security_AuthenticatedPeerCredentialToken credential_token; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + int r; + + /* Check if we actually have validate_remote_permissions function. */ + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(local_identity_handle != DDS_SECURITY_HANDLE_NIL); + CU_ASSERT_FATAL(access_control->validate_remote_permissions != NULL); + CU_ASSERT_FATAL(access_control->return_permissions_handle != NULL); + + fill_permissions_token(&permissions_token); + r = fill_peer_credential_token(&credential_token, "Test_Permissions_ok.p7s"); + CU_ASSERT_FATAL(r); + + remote_identity_handle++; + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + if (result == 0) + printf("validate_remote_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + reset_exception(&exception); + CU_ASSERT_FATAL(result != 0); + access_control->return_permissions_handle(access_control, result, &exception); + reset_exception(&exception); + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&permissions_token); + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&credential_token); +} + +CU_Test(ddssec_builtin_validate_remote_permissions, permissions_unknown_ca, .init = suite_validate_remote_permissions_init, .fini = suite_validate_remote_permissions_fini) +{ + DDS_Security_PermissionsHandle result; + DDS_Security_PermissionsToken permissions_token; + DDS_Security_AuthenticatedPeerCredentialToken credential_token; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + int r; + + /* Check if we actually have validate_remote_permissions function. */ + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(local_identity_handle != DDS_SECURITY_HANDLE_NIL); + CU_ASSERT_FATAL(access_control->validate_remote_permissions != NULL); + CU_ASSERT_FATAL(access_control->return_permissions_handle != NULL); + + fill_permissions_token(&permissions_token); + r = fill_peer_credential_token(&credential_token, "Test_Permissions_unknown_ca.p7s"); + CU_ASSERT_FATAL(r); + + remote_identity_handle++; + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + if (result == 0) + { + printf("validate_remote_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + + CU_ASSERT(result == 0); + if (result == 0) + { + CU_ASSERT(exception.code != 0); + CU_ASSERT(exception.message != NULL); + } + else + { + reset_exception(&exception); + access_control->return_permissions_handle(access_control, result, &exception); + } + + reset_exception(&exception); + + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&permissions_token); + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&credential_token); +} + +CU_Test(ddssec_builtin_validate_remote_permissions, permissions_not_signed, .init = suite_validate_remote_permissions_init, .fini = suite_validate_remote_permissions_fini) +{ + DDS_Security_PermissionsHandle result; + DDS_Security_PermissionsToken permissions_token; + DDS_Security_AuthenticatedPeerCredentialToken credential_token; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + int r; + + /* Check if we actually have validate_remote_permissions function. */ + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(local_identity_handle != DDS_SECURITY_HANDLE_NIL); + CU_ASSERT_FATAL(access_control->validate_remote_permissions != NULL); + CU_ASSERT_FATAL(access_control->return_permissions_handle != NULL); + + fill_permissions_token(&permissions_token); + r = fill_peer_credential_token(&credential_token, "Test_Permissions_not_signed.p7s"); + CU_ASSERT_FATAL(r); + + remote_identity_handle++; + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + if (result == 0) + { + printf("validate_remote_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + + CU_ASSERT(result == 0); + if (result == 0) + { + CU_ASSERT(exception.code != 0); + CU_ASSERT(exception.message != NULL); + } + else + { + reset_exception(&exception); + access_control->return_permissions_handle(access_control, result, &exception); + } + + reset_exception(&exception); + + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&permissions_token); + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&credential_token); +} + +CU_Test(ddssec_builtin_validate_remote_permissions, invalid_credential_token, .init = suite_validate_remote_permissions_init, .fini = suite_validate_remote_permissions_fini) +{ + DDS_Security_PermissionsHandle result; + DDS_Security_PermissionsToken permissions_token; + DDS_Security_AuthenticatedPeerCredentialToken credential_token; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + + /* Check if we actually have validate_remote_permissions function. */ + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(local_identity_handle != DDS_SECURITY_HANDLE_NIL); + CU_ASSERT_FATAL(access_control->validate_remote_permissions != NULL); + CU_ASSERT_FATAL(access_control->return_permissions_handle != NULL); + + remote_identity_handle++; + + fill_permissions_token(&permissions_token); + + /* empty peer credential token */ + memset(&credential_token, 0, sizeof(credential_token)); + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + if (result == 0) + { + printf("validate_remote_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + + CU_ASSERT(result == 0); + if (result == 0) + { + CU_ASSERT(exception.code != 0); + CU_ASSERT(exception.message != NULL); + } + else + { + reset_exception(&exception); + access_control->return_permissions_handle(access_control, result, &exception); + } + + reset_exception(&exception); + + /* peer credential token with invalid class id */ + credential_token.class_id = "UNKNOWN"; + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + if (result == 0) + { + printf("validate_remote_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + + CU_ASSERT(result == 0); + if (result == 0) + { + CU_ASSERT(exception.code != 0); + CU_ASSERT(exception.message != NULL); + } + else + { + reset_exception(&exception); + access_control->return_permissions_handle(access_control, result, &exception); + } + + reset_exception(&exception); + + /* peer credential token with no properties */ + credential_token.class_id = ddsrt_strdup(AUTH_PROTOCOL_CLASS_ID); + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + if (result == 0) + { + printf("validate_remote_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + + CU_ASSERT(result == 0); + if (result == 0) + { + CU_ASSERT(exception.code != 0); + CU_ASSERT(exception.message != NULL); + } + else + { + reset_exception(&exception); + access_control->return_permissions_handle(access_control, result, &exception); + } + + reset_exception(&exception); + + /* peer credential token with empty properties */ + credential_token.properties._length = credential_token.properties._maximum = 2; + credential_token.properties._buffer = DDS_Security_PropertySeq_allocbuf(2); + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + if (result == 0) + { + printf("validate_remote_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + + CU_ASSERT(result == 0); + if (result == 0) + { + CU_ASSERT(exception.code != 0); + CU_ASSERT(exception.message != NULL); + } + else + { + reset_exception(&exception); + access_control->return_permissions_handle(access_control, result, &exception); + } + + reset_exception(&exception); + + /* peer credential token with no c.id value */ + credential_token.properties._buffer[0].name = ddsrt_strdup(PROPERTY_C_ID); + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + if (result == 0) + { + printf("validate_remote_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + + CU_ASSERT(result == 0); + if (result == 0) + { + CU_ASSERT(exception.code != 0); + CU_ASSERT(exception.message != NULL); + } + else + { + reset_exception(&exception); + access_control->return_permissions_handle(access_control, result, &exception); + } + + reset_exception(&exception); + + /* peer credential token with no c.perm */ + credential_token.properties._buffer[0].value = ddsrt_strdup(PROPERTY_IDENTITY_CERT); + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + if (result == 0) + { + printf("validate_remote_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + + CU_ASSERT(result == 0); + if (result == 0) + { + CU_ASSERT(exception.code != 0); + CU_ASSERT(exception.message != NULL); + } + else + { + reset_exception(&exception); + access_control->return_permissions_handle(access_control, result, &exception); + } + + reset_exception(&exception); + + /* peer credential token with no c.perm value*/ + credential_token.properties._buffer[1].name = ddsrt_strdup(PROPERTY_C_PERM); + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + if (result == 0) + { + printf("validate_remote_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + + CU_ASSERT(result == 0); + if (result == 0) + { + CU_ASSERT(exception.code != 0); + CU_ASSERT(exception.message != NULL); + } + else + { + reset_exception(&exception); + access_control->return_permissions_handle(access_control, result, &exception); + } + + reset_exception(&exception); + + /* peer credential token with invalid c.perm value */ + credential_token.properties._buffer[1].value = ddsrt_strdup("Invalid value"); + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + if (result == 0) + { + printf("validate_remote_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + + CU_ASSERT(result == 0); + if (result == 0) + { + CU_ASSERT(exception.code != 0); + CU_ASSERT(exception.message != NULL); + } + else + { + reset_exception(&exception); + access_control->return_permissions_handle(access_control, result, &exception); + } + + reset_exception(&exception); + + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&permissions_token); + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&credential_token); +} + +CU_Test(ddssec_builtin_validate_remote_permissions, invalid_xml, .init = suite_validate_remote_permissions_init, .fini = suite_validate_remote_permissions_fini) +{ + DDS_Security_PermissionsHandle result; + DDS_Security_PermissionsToken permissions_token; + DDS_Security_AuthenticatedPeerCredentialToken credential_token; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + int r; + + /* Check if we actually have validate_remote_permissions function. */ + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(local_identity_handle != DDS_SECURITY_HANDLE_NIL); + CU_ASSERT_FATAL(access_control->validate_remote_permissions != NULL); + CU_ASSERT_FATAL(access_control->return_permissions_handle != NULL); + + fill_permissions_token(&permissions_token); + //permissions_token. + r = fill_peer_credential_token(&credential_token, "Test_Permissions_invalid_data.p7s"); + CU_ASSERT_FATAL(r); + + remote_identity_handle++; + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + CU_ASSERT(result == 0); + CU_ASSERT(exception.code == DDS_SECURITY_ERR_CAN_NOT_PARSE_PERMISSIONS_CODE); + CU_ASSERT(exception.message != NULL); + if (exception.message) + { + printf("(%d) %s\n", (int)exception.code, exception.message); + } + reset_exception(&exception); + + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&permissions_token); + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&credential_token); +} + +CU_Test(ddssec_builtin_validate_remote_permissions, permissions_expired, .init = suite_validate_remote_permissions_init, .fini = suite_validate_remote_permissions_fini) +{ + DDS_Security_PermissionsHandle result; + DDS_Security_PermissionsToken permissions_token; + DDS_Security_AuthenticatedPeerCredentialToken credential_token; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + int r; + + /* Check if we actually have validate_remote_permissions function. */ + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(local_identity_handle != DDS_SECURITY_HANDLE_NIL); + CU_ASSERT_FATAL(access_control->validate_remote_permissions != NULL); + CU_ASSERT_FATAL(access_control->return_permissions_handle != NULL); + + fill_permissions_token(&permissions_token); + r = fill_peer_credential_token(&credential_token, "Test_Permissions_expired.p7s"); + CU_ASSERT_FATAL(r); + + remote_identity_handle++; + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + CU_ASSERT_FATAL(result == 0); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_CODE); + CU_ASSERT_NSTRING_EQUAL_FATAL(DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_MESSAGE, exception.message, strlen(DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_MESSAGE) - 16); + reset_exception(&exception); + + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&permissions_token); + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&credential_token); +} + +CU_Test(ddssec_builtin_validate_remote_permissions, permissions_not_yet, .init = suite_validate_remote_permissions_init, .fini = suite_validate_remote_permissions_fini) +{ + DDS_Security_PermissionsHandle result; + DDS_Security_PermissionsToken permissions_token; + DDS_Security_AuthenticatedPeerCredentialToken credential_token; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + int r; + + /* Check if we actually have validate_remote_permissions function. */ + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(local_identity_handle != DDS_SECURITY_HANDLE_NIL); + CU_ASSERT_FATAL(access_control->validate_remote_permissions != NULL); + CU_ASSERT_FATAL(access_control->return_permissions_handle != NULL); + + fill_permissions_token(&permissions_token); + r = fill_peer_credential_token(&credential_token, "Test_Permissions_notyet.p7s"); + CU_ASSERT_FATAL(r); + + remote_identity_handle++; + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + CU_ASSERT_FATAL(result == 0); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_VALIDITY_PERIOD_NOT_STARTED_CODE); + CU_ASSERT_NSTRING_EQUAL_FATAL(DDS_SECURITY_ERR_VALIDITY_PERIOD_NOT_STARTED_MESSAGE, exception.message, strlen(DDS_SECURITY_ERR_VALIDITY_PERIOD_NOT_STARTED_MESSAGE) - 14); + reset_exception(&exception); + + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&permissions_token); + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&credential_token); +} + +CU_Test(ddssec_builtin_validate_remote_permissions, permissions_unknown_subject_name, .init = suite_validate_remote_permissions_init, .fini = suite_validate_remote_permissions_fini) +{ + DDS_Security_PermissionsHandle result; + DDS_Security_PermissionsToken permissions_token; + DDS_Security_AuthenticatedPeerCredentialToken credential_token; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + int r; + + /* Check if we actually have validate_remote_permissions function. */ + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(local_identity_handle != DDS_SECURITY_HANDLE_NIL); + CU_ASSERT_FATAL(access_control->validate_remote_permissions != NULL); + CU_ASSERT_FATAL(access_control->return_permissions_handle != NULL); + + fill_permissions_token(&permissions_token); + r = fill_peer_credential_token(&credential_token, "Test_Permissions_unknown_subject.p7s"); + CU_ASSERT_FATAL(r); + + remote_identity_handle++; + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + CU_ASSERT_FATAL(result == 0); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_INVALID_SUBJECT_NAME_CODE); + CU_ASSERT_STRING_EQUAL_FATAL(DDS_SECURITY_ERR_INVALID_SUBJECT_NAME_MESSAGE, exception.message); + reset_exception(&exception); + + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&permissions_token); + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&credential_token); + + /* missing subject name component */ + + fill_permissions_token(&permissions_token); + r = fill_peer_credential_token(&credential_token, "Test_Permissions_missing_subject_component.p7s"); + CU_ASSERT_FATAL(r); + + remote_identity_handle++; + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + CU_ASSERT_FATAL(result == 0); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_INVALID_SUBJECT_NAME_CODE); + CU_ASSERT_STRING_EQUAL_FATAL(DDS_SECURITY_ERR_INVALID_SUBJECT_NAME_MESSAGE, exception.message); + reset_exception(&exception); + + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&permissions_token); + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&credential_token); +} + +CU_Test(ddssec_builtin_validate_remote_permissions, permissions_different_subject, .init = suite_validate_remote_permissions_init, .fini = suite_validate_remote_permissions_fini) +{ + DDS_Security_PermissionsHandle result; + DDS_Security_PermissionsToken permissions_token; + DDS_Security_AuthenticatedPeerCredentialToken credential_token; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + int r; + + /* Check if we actually have validate_remote_permissions function. */ + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(local_identity_handle != DDS_SECURITY_HANDLE_NIL); + CU_ASSERT_FATAL(access_control->validate_remote_permissions != NULL); + CU_ASSERT_FATAL(access_control->return_permissions_handle != NULL); + + fill_permissions_token(&permissions_token); + r = fill_peer_credential_token(&credential_token, "Test_Permissions_different_subject_representation.p7s"); + CU_ASSERT_FATAL(r); + + remote_identity_handle++; + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + CU_ASSERT_FATAL(result != 0); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_OK_CODE); + + reset_exception(&exception); + + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&permissions_token); + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&credential_token); +} + +CU_Test(ddssec_builtin_validate_remote_permissions, corrupted_signature, .init = suite_validate_remote_permissions_init, .fini = suite_validate_remote_permissions_fini) +{ + DDS_Security_PermissionsHandle result; + DDS_Security_PermissionsToken permissions_token; + DDS_Security_AuthenticatedPeerCredentialToken credential_token; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + int r; + + /* Check if we actually have validate_remote_permissions function. */ + CU_ASSERT_FATAL(access_control != NULL); + CU_ASSERT_FATAL(local_identity_handle != DDS_SECURITY_HANDLE_NIL); + CU_ASSERT_FATAL(access_control->validate_remote_permissions != NULL); + CU_ASSERT_FATAL(access_control->return_permissions_handle != NULL); + + fill_permissions_token(&permissions_token); + //permissions_token. + r = fill_peer_credential_token(&credential_token, "Test_Permissions_ok.p7s"); + CU_ASSERT_FATAL(r); + + corrupt_permission_signature(&credential_token); + + remote_identity_handle++; + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + CU_ASSERT(result == 0); + CU_ASSERT(exception.code == DDS_SECURITY_ERR_INVALID_SMIME_DOCUMENT_CODE); + CU_ASSERT(exception.message != NULL); + if (exception.message) + { + printf("(%d) %s\n", (int)exception.code, exception.message); + } + reset_exception(&exception); + + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&permissions_token); + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)&credential_token); +} diff --git a/src/security/core/include/dds/security/core/dds_security_utils.h b/src/security/core/include/dds/security/core/dds_security_utils.h index fe975d6..a66c4d3 100644 --- a/src/security/core/include/dds/security/core/dds_security_utils.h +++ b/src/security/core/include/dds/security/core/dds_security_utils.h @@ -13,10 +13,12 @@ #ifndef DSCMN_SECURITY_UTILS_H_ #define DSCMN_SECURITY_UTILS_H_ -#include "dds/export.h" #include #include #include +#include "dds/export.h" +#include "dds/ddsrt/strtol.h" +#include "dds/ddsrt/time.h" #include "dds/security/core/dds_security_types.h" #include "dds/security/dds_security_api.h" @@ -339,6 +341,10 @@ ddssec_strchrs ( const char *chrs, bool inc); +DDS_EXPORT dds_time_t +DDS_Security_parse_xml_date( + char *buf); + #define DDS_Security_ParticipantCryptoTokenSeq_alloc() \ DDS_Security_DataHolderSeq_alloc()) diff --git a/src/security/core/src/dds_security_utils.c b/src/security/core/src/dds_security_utils.c index 665e587..8a5cef7 100644 --- a/src/security/core/src/dds_security_utils.c +++ b/src/security/core/src/dds_security_utils.c @@ -807,47 +807,34 @@ DDS_Security_Exception_set( #if DDSI_INCLUDE_SSL DDS_EXPORT void DDS_Security_Exception_set_with_openssl_error( - DDS_Security_SecurityException *ex, - const char *context, - int code, - int minor_code, - const char *error_area - ) + DDS_Security_SecurityException *ex, + const char *context, + int code, + int minor_code, + const char *error_area) { + BIO *bio; + assert(context); + assert(error_area); + assert(ex); + DDSRT_UNUSED_ARG(context); - BIO *bio; - char *buf = NULL; - char *str; - size_t len; /*BIO_get_mem_data requires long int */ - assert(context); - assert(error_area); - assert(ex); - DDSRT_UNUSED_ARG( context ); - - bio = BIO_new(BIO_s_mem()); - - if (bio) { - size_t exception_msg_len; - ERR_print_errors(bio); - len = (size_t)BIO_get_mem_data (bio, &buf); - exception_msg_len = len + strlen(error_area) + 1; - str = ddsrt_malloc( exception_msg_len ); - - ddsrt_strlcpy(str, error_area, exception_msg_len); - memcpy(str + strlen(error_area), buf, len ); - str [ exception_msg_len -1 ] = '\0'; - //snprintf( str, exception_msg_len, "%s%s", error_area, buf ); - - ex->message = str; - ex->code = code; - ex->minor_code = minor_code; - - BIO_free(bio); - - } else { - DDS_Security_Exception_set(ex, context, code, minor_code, "BIO_new failed"); - } - + if ((bio = BIO_new(BIO_s_mem()))) { + ERR_print_errors(bio); + char *buf = NULL; + size_t len = (size_t)BIO_get_mem_data(bio, &buf); + size_t exception_msg_len = len + strlen(error_area) + 1; + char *str = ddsrt_malloc(exception_msg_len); + ddsrt_strlcpy(str, error_area, exception_msg_len); + memcpy(str + strlen(error_area), buf, len); + str[exception_msg_len - 1] = '\0'; + ex->message = str; + ex->code = code; + ex->minor_code = minor_code; + BIO_free(bio); + } else { + DDS_Security_Exception_set(ex, context, code, minor_code, "BIO_new failed"); + } } #endif @@ -1104,6 +1091,203 @@ DDS_Security_normalize_file( } #undef __FILESEPCHAR return norm; - } +/** + * Parses an XML date string and returns this as a dds_time_t value. As leap seconds are not permitted + * in the XML date format (as stated in the XML Schema specification), this parser function does not + * accept leap seconds in its input string. This complies with the dds_time_t representation on posix, + * which is a unix timestamp (that also ignores leap seconds). + * + * As a dds_time_t is expressed as nanoseconds, the fractional seconds part of the input string will + * be rounded in case the fractional part has more than 9 digits. + */ +dds_time_t +DDS_Security_parse_xml_date( + char *buf) +{ + int32_t year = -1; + int32_t month = -1; + int32_t day = -1; + int32_t hour = -1; + int32_t minute = -1; + int32_t second = -1; + int32_t hour_offset = -1; + int32_t minute_offset = -1; + + int64_t frac_ns = 0; + + size_t cnt = 0; + size_t cnt_frac_sec = 0; + + assert(buf != NULL); + + /* Make an integrity check of the string before the conversion*/ + while (buf[cnt] != '\0') + { + if (cnt == 4 || cnt == 7) + { + if (buf[cnt] != '-') + return DDS_TIME_INVALID; + } + else if (cnt == 10) + { + if (buf[cnt] != 'T') + return DDS_TIME_INVALID; + } + else if (cnt == 13 || cnt == 16) + { + if (buf[cnt] != ':') + return DDS_TIME_INVALID; + } + else if (cnt == 19) + { + if (buf[cnt] != 'Z' && buf[cnt] != '+' && buf[cnt] != '-' && buf[cnt] != '.') + return DDS_TIME_INVALID; + + /* If a dot is found then a variable number of fractional seconds is present. + A second integrity loop to account for the variability is used */ + if (buf[cnt] == '.' && !cnt_frac_sec) + { + cnt_frac_sec = 1; + while (buf[cnt + 1] != '\0' && buf[cnt + 1] >= '0' && buf[cnt + 1] <= '9') + { + cnt_frac_sec++; + cnt++; + } + } + } + else if (cnt == 19 + cnt_frac_sec) + { + if (buf[cnt] != 'Z' && buf[cnt] != '+' && buf[cnt] != '-') + return DDS_TIME_INVALID; + } + else if (cnt == 22 + cnt_frac_sec) + { + if (buf[cnt] != ':') + return DDS_TIME_INVALID; + } + else + { + if (buf[cnt] < '0' || buf[cnt] > '9') + return DDS_TIME_INVALID; + } + cnt++; + } + + /* Do not allow more than 12 (13 including the dot) and less than 1 fractional second digits if they are used */ + if (cnt_frac_sec && (cnt_frac_sec < 2 || cnt_frac_sec > 13)) + return DDS_TIME_INVALID; + + /* Valid string length value at this stage are 19, 20 and 25 plus the fractional seconds part */ + if (cnt != 19 + cnt_frac_sec && cnt != 20 + cnt_frac_sec && cnt != 25 + cnt_frac_sec) + return DDS_TIME_INVALID; + + year = ddsrt_todigit(buf[0]) * 1000 + ddsrt_todigit(buf[1]) * 100 + ddsrt_todigit(buf[2]) * 10 + ddsrt_todigit(buf[3]); + month = ddsrt_todigit(buf[5]) * 10 + ddsrt_todigit(buf[6]); + day = ddsrt_todigit(buf[8]) * 10 + ddsrt_todigit(buf[9]); + + hour = ddsrt_todigit(buf[11]) * 10 + ddsrt_todigit(buf[12]); + minute = ddsrt_todigit(buf[14]) * 10 + ddsrt_todigit(buf[15]); + second = ddsrt_todigit(buf[17]) * 10 + ddsrt_todigit(buf[18]); + + { + int64_t frac_ns_pow = DDS_NSECS_IN_SEC / 10; + size_t n = 0; + for (n = 0; cnt_frac_sec && n < cnt_frac_sec - 1; n++) + { + /* Maximum granularity is nanosecond so round to maximum 9 digits */ + if (n == 9) + { + if (ddsrt_todigit(buf[20 + n]) >= 5) + frac_ns++; + break; + } + frac_ns += ddsrt_todigit(buf[20 + n]) * frac_ns_pow; + frac_ns_pow = frac_ns_pow / 10; + } + } + + /* If the length is 20 the last character must be a Z representing UTC time zone */ + if (cnt == 19 + cnt_frac_sec || (cnt == 20 + cnt_frac_sec && buf[19 + cnt_frac_sec] == 'Z')) + { + hour_offset = 0; + minute_offset = 0; + } + else if (cnt == 25 + cnt_frac_sec) + { + hour_offset = ddsrt_todigit(buf[20 + cnt_frac_sec]) * 10 + ddsrt_todigit(buf[21 + cnt_frac_sec]); + minute_offset = ddsrt_todigit(buf[23 + cnt_frac_sec]) * 10 + ddsrt_todigit(buf[24 + cnt_frac_sec]); + } + else + return DDS_TIME_INVALID; + + /* Make a limit check to make sure that all the numbers are within absolute boundaries. + Note that leap seconds are not allowed in XML dates and therefore not supported. */ + if (year < 1970 || year > 2262 || month < 1 || month > 12 || day < 1 || day > 31 || + hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59 || + ((hour_offset < 0 || hour_offset > 11 || minute_offset < 0 || minute_offset > 59) && (hour_offset != 12 || minute_offset != 0))) + { + return DDS_TIME_INVALID; + } + + /* Boundary check including consideration for month and leap years */ + if (!(((month == 4 || month == 6 || month == 9 || month == 11) && (day >= 1 && day <= 30)) || + ((month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) && (day >= 1 && day <= 31)) || + (month == 2 && ((year % 100 != 0 && year % 4 == 0) || (year % 400 == 0)) && (day >= 1 && day <= 29)) || + (month == 2 && (day >= 1 && day <= 28)))) + { + return DDS_TIME_INVALID; + } + + /* Convert the year-month-day to total number of days */ + int32_t total_leap_years = (year - 1970 + 1) / 4; + /* Leap year count decreased by the number of xx00 years before current year because these are not leap years, + except for 2000. The year 2400 is not in the valid year range so we don't take that into account. */ + if (year > 2100) + total_leap_years -= year / 100 - 20; + if (year == 2200) + total_leap_years++; + + int32_t total_reg_years = year - 1970 - total_leap_years; + int32_t total_num_days = total_leap_years * 366 + total_reg_years * 365; + int32_t month_cnt; + + for (month_cnt = 1; month_cnt < month; month_cnt++) + { + if (month_cnt == 4 || month_cnt == 6 || month_cnt == 9 || month_cnt == 11) + total_num_days += 30; + else if (month_cnt == 2) + { + if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) + total_num_days += 29; + else + total_num_days += 28; + } + else + total_num_days += 31; + } + total_num_days += day - 1; + + /* Correct the offset sign if negative */ + if (buf[19 + cnt_frac_sec] == '-') + { + hour_offset = -hour_offset; + minute_offset = -minute_offset; + } + /* Convert the total number of days to seconds */ + int64_t ts_days = (int64_t)total_num_days * 24 * 60 * 60; + int64_t ts_hms = hour * 60 * 60 + minute * 60 + second; + if (ts_days + ts_hms > INT64_MAX / DDS_NSECS_IN_SEC) + return DDS_TIME_INVALID; + int64_t ts = DDS_SECS(ts_days + ts_hms); + + /* Apply the hour and minute offset */ + int64_t ts_offset = DDS_SECS((int64_t)hour_offset * 60 * 60 + minute_offset * 60); + + /* Prevent the offset from making the timestamp negative or overflow it */ + if ((ts_offset <= 0 || (ts_offset > 0 && ts_offset < ts)) && INT64_MAX - ts - frac_ns >= -ts_offset) + return ts - ts_offset + frac_ns; + + return DDS_TIME_INVALID; +} diff --git a/src/security/core/tests/CMakeLists.txt b/src/security/core/tests/CMakeLists.txt index 9cd0e27..d240583 100644 --- a/src/security/core/tests/CMakeLists.txt +++ b/src/security/core/tests/CMakeLists.txt @@ -15,6 +15,7 @@ include (CUnit) set(security_core_test_sources "tc_fsm.c" "dds_security_core.c" + "security_utils.c" ) add_definitions(-DDDSI_INCLUDE_SECURITY) diff --git a/src/security/core/tests/security_utils.c b/src/security/core/tests/security_utils.c new file mode 100644 index 0000000..ec4ab89 --- /dev/null +++ b/src/security/core/tests/security_utils.c @@ -0,0 +1,62 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#include +#include +#include "CUnit/CUnit.h" +#include "CUnit/Test.h" +#include "dds/ddsrt/time.h" +#include "dds/security/core/dds_security_utils.h" + +CU_Test(ddssec_security_utils, parse_xml_date) +{ + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date(""), DDS_TIME_INVALID); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("abc"), DDS_TIME_INVALID); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2020-01-01"), DDS_TIME_INVALID); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2020-01-01D01:01:01Z"), DDS_TIME_INVALID); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2019-02-29T01:01:01Z"), DDS_TIME_INVALID); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2100-02-29T01:01:01Z"), DDS_TIME_INVALID); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("1969-01-01T01:01:01Z"), DDS_TIME_INVALID); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2010-01-01T23:59:60Z"), DDS_TIME_INVALID); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("1969-01-01T01:01:01+01"), DDS_TIME_INVALID); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("1969-01-01T01:01:01+0100"), DDS_TIME_INVALID); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("1969-01-01T01:01:01+0:00"), DDS_TIME_INVALID); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("1970-01-01T00:00:00+01:00"), DDS_TIME_INVALID); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2020-01-01T01:01:01.0000000000001+01:00"), DDS_TIME_INVALID); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2020-01-01T01:01:01.0.1+01:00"), DDS_TIME_INVALID); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2020-01-01T01:01:01.+01:00"), DDS_TIME_INVALID); + + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("1970-01-01T00:00:00Z"), 0); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2000-02-29T00:00:00Z"), DDS_SECS(951782400)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2020-01-01T01:01:01Z"), DDS_SECS(1577840461)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2020-01-01T01:01:01+00:30"), DDS_SECS(1577840461 - 30 * 60)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2020-01-01T01:01:01+01:00"), DDS_SECS(1577840461 - 60 * 60)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2020-01-01T01:01:01+12:00"), DDS_SECS(1577840461 - 12 * 60 * 60)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2020-01-01T01:01:01-01:00"), DDS_SECS(1577840461 + 60 * 60)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2020-12-31T23:59:59Z"), DDS_SECS(1609459199)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2020-02-29T01:01:01Z"), DDS_SECS(1582938061)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2038-01-19T03:14:07Z"), DDS_SECS(INT32_MAX)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2038-01-19T03:14:08Z"), DDS_SECS(INT64_C(INT32_MAX + 1))); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2100-01-01T00:00:00Z"), DDS_SECS(4102444800)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2120-01-01T00:00:00Z"), DDS_SECS(4733510400)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2200-01-01T00:00:00Z"), DDS_SECS(7258118400)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2220-01-01T00:00:00Z"), DDS_SECS(7889184000)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2262-04-11T23:47:16.854775807Z"), INT64_MAX); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2262-04-11T23:47:16.854775808Z"), DDS_TIME_INVALID); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2262-04-11T23:47:16.854775807+00:01"), INT64_MAX - DDS_SECS(60)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2262-04-11T23:47:16.854775807-00:01"), DDS_TIME_INVALID); + + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2020-01-01T01:01:01.000000001+01:00"), INT64_C(1577836861000000001)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2020-01-01T01:01:01.0000000004+01:00"), INT64_C(1577836861000000000)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2020-01-01T01:01:01.0000000005+01:00"), INT64_C(1577836861000000001)); + CU_ASSERT_EQUAL(DDS_Security_parse_xml_date("2020-01-01T01:01:01.987654321+01:00"), INT64_C(1577836861987654321)); +} From aef4f0a12661c7149d990acad47dc00a5573b2b9 Mon Sep 17 00:00:00 2001 From: Stefan Kimmer Date: Fri, 24 Jan 2020 10:53:18 +0100 Subject: [PATCH 095/238] Certificate trigger and directory operations Implement trigger of certificate and permission expiries using the timed callbacks. Implement directory operations such that trusted CA can be read. This implements OS abstraction functions such as opendir and stat. Signed-off-by: Stefan Kimmer --- src/ddsrt/CMakeLists.txt | 2 +- src/ddsrt/include/dds/ddsrt/filesystem.h | 123 + .../include/dds/ddsrt/filesystem/posix.h | 34 + .../include/dds/ddsrt/filesystem/windows.h | 34 + src/ddsrt/src/filesystem/posix/filesystem.c | 116 + src/ddsrt/src/filesystem/windows/filesystem.c | 122 + .../access_control/src/access_control.c | 51 +- .../authentication/src/auth_utils.c | 50 +- .../authentication/src/authentication.c | 43 +- .../builtin_plugins/tests/CMakeLists.txt | 6 + .../builtin_plugins/tests/config_env.h.in | 1 + .../etc/Test_Permissions_listener.p7s | 51 - .../src/listeners_access_control_utests.c | 49 +- .../etc/Example_Governance.p7s | 120 + .../etc/Example_Permissions_Alice.p7s | 98 + .../etc/Example_Permissions_Bob.p7s | 98 + .../etc/Identity_CA_Cert.pem | 25 + .../etc/Identity_CA_Private_Key.pem | 27 + .../etc/Permissions_CA_Cert.pem | 26 + .../src/listeners_authentication_utests.c | 2105 +++++++++++++++++ .../src/process_handshake_utests.c | 2 +- .../validate_begin_handshake_reply_utests.c | 9 +- .../src/validate_local_identity_utests.c | 9 +- .../dds/security/core/dds_security_timed_cb.h | 6 +- src/security/core/src/dds_security_utils.c | 1 + 25 files changed, 3039 insertions(+), 169 deletions(-) create mode 100644 src/ddsrt/include/dds/ddsrt/filesystem.h create mode 100644 src/ddsrt/include/dds/ddsrt/filesystem/posix.h create mode 100644 src/ddsrt/include/dds/ddsrt/filesystem/windows.h create mode 100644 src/ddsrt/src/filesystem/posix/filesystem.c create mode 100644 src/ddsrt/src/filesystem/windows/filesystem.c delete mode 100644 src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Permissions_listener.p7s create mode 100644 src/security/builtin_plugins/tests/listeners_authentication/etc/Example_Governance.p7s create mode 100644 src/security/builtin_plugins/tests/listeners_authentication/etc/Example_Permissions_Alice.p7s create mode 100644 src/security/builtin_plugins/tests/listeners_authentication/etc/Example_Permissions_Bob.p7s create mode 100644 src/security/builtin_plugins/tests/listeners_authentication/etc/Identity_CA_Cert.pem create mode 100644 src/security/builtin_plugins/tests/listeners_authentication/etc/Identity_CA_Private_Key.pem create mode 100644 src/security/builtin_plugins/tests/listeners_authentication/etc/Permissions_CA_Cert.pem create mode 100644 src/security/builtin_plugins/tests/listeners_authentication/src/listeners_authentication_utests.c diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index c9c44a7..00d51e5 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -149,7 +149,7 @@ list(APPEND sources # network stack. In order to mix-and-match various compilers, architectures, # operating systems, etc input from the build system is required. foreach(feature atomics cdtors environ heap ifaddrs random rusage - sockets string sync threads time md5 process netstat dynlib) + sockets string sync threads time md5 process netstat dynlib filesystem) if(EXISTS "${include_path}/dds/ddsrt/${feature}.h") list(APPEND headers "${include_path}/dds/ddsrt/${feature}.h") file(GLOB_RECURSE diff --git a/src/ddsrt/include/dds/ddsrt/filesystem.h b/src/ddsrt/include/dds/ddsrt/filesystem.h new file mode 100644 index 0000000..60ade53 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/filesystem.h @@ -0,0 +1,123 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#ifndef FILESYSTEM_H +#define FILESYSTEM_H + +#include + +#include "dds/export.h" +#include "dds/ddsrt/retcode.h" +#include "dds/ddsrt/time.h" + +#if _WIN32 +#include "dds/ddsrt/filesystem/windows.h" +#else +#include "dds/ddsrt/filesystem/posix.h" +#endif + +#if defined (__cplusplus) +extern "C" { +#endif + +struct ddsrt_stat { + ddsrt_mode_t stat_mode; + size_t stat_size; + dds_time_t stat_mtime; +}; + + +struct ddsrt_dirent { + char d_name[DDSRT_PATH_MAX + 1]; +}; + +/** \brief opendir wrapper + * + * Open the directory conform opendir + * + * Precondition: + * none + * + * Possible results: + * - return DDS_RETCODE_OK if directory 'name' is opened + * - DDS_RETCODE_ERROR if 'name' could not + * be found or is not a directory. + */ +DDS_EXPORT dds_return_t ddsrt_opendir(const char *name, ddsrt_dir_handle_t *dir); + +/** \brief closedir wrapper + * + * Close the directory conform closdir + * + * Precondition: + * none + * + * Possible results: + * - return DDS_RETCODE_OK if directory identified by the handle + * is succesfully closed + * - return DDS_RETCODE_ERROR if the handle is invalid. + */ +DDS_EXPORT dds_return_t ddsrt_closedir(ddsrt_dir_handle_t d); + +/** \brief readdir wrapper + * + * Read the directory conform readdir. + * + * Precondition: + * none + * + * Possible results: + * - return DDS_RETCODE_OK if next directory is found + * - return DDS_RETCODE_ERROR if no more directories are found. + */ +DDS_EXPORT dds_return_t ddsrt_readdir(ddsrt_dir_handle_t d, struct ddsrt_dirent *direntp); + +/** \brief stat wrapper + * + * Gets directory status conform stat. + * + * Precondition: + * none + * + * Possible results: + * - return DDS_RETCODE_OK if stat is successful + * - return DDS_RETCODE_ERROR if stat fails. + */ +DDS_EXPORT dds_return_t ddsrt_stat(const char *path, struct ddsrt_stat *buf); + +/** \brief Transforms the given filepath into a platform specific filepath. + * + * This translation function will replace any platform file seperator into + * the fileseperator of the current platform. Doulbe quotes are removed + * as well. + * + * Precondition: + * none + * + * Possible results: + * - returns normalized filepath conform current platform + * - return NULL if out of memory. + */ +DDS_EXPORT char* ddsrt_file_normalize(const char *filepath); + +/** \brief Get file seperator + * + * Possible Results: + * - "" + */ +DDS_EXPORT const char* ddsrt_file_sep(void); + +#if defined (__cplusplus) +} +#endif + +#endif // FILESYSTEM_H diff --git a/src/ddsrt/include/dds/ddsrt/filesystem/posix.h b/src/ddsrt/include/dds/ddsrt/filesystem/posix.h new file mode 100644 index 0000000..7d8e7c2 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/filesystem/posix.h @@ -0,0 +1,34 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSRT_FILESYSTEM_POSIX_H +#define DDSRT_FILESYSTEM_POSIX_H + +#include +#include +#include +#include + +typedef DIR *ddsrt_dir_handle_t; +typedef mode_t ddsrt_mode_t; + +#define DDSRT_PATH_MAX PATH_MAX +#define DDSRT_FILESEPCHAR '/' + +#if defined(__cplusplus) +extern "C" { +#endif + +#if defined(__cplusplus) +} +#endif + +#endif /* DDSRT_FILESYSTEM_POSIX_H */ diff --git a/src/ddsrt/include/dds/ddsrt/filesystem/windows.h b/src/ddsrt/include/dds/ddsrt/filesystem/windows.h new file mode 100644 index 0000000..abde1d6 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/filesystem/windows.h @@ -0,0 +1,34 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSRT_FILESYSTEM_WINDOWS_H +#define DDSRT_FILESYSTEM_WINDOWS_H + +#include +#include + +#include "dds/ddsrt/types.h" + +typedef HANDLE ddsrt_dir_handle_t; +typedef unsigned short ddsrt_mode_t; + +#define DDSRT_PATH_MAX MAX_PATH +#define DDSRT_FILESEPCHAR '\\' + +#if defined(__cplusplus) +extern "C" { +#endif + +#if defined(__cplusplus) +} +#endif + +#endif /* DDSRT_FILESYSTEM_WINDOWS_H */ diff --git a/src/ddsrt/src/filesystem/posix/filesystem.c b/src/ddsrt/src/filesystem/posix/filesystem.c new file mode 100644 index 0000000..11b57ce --- /dev/null +++ b/src/ddsrt/src/filesystem/posix/filesystem.c @@ -0,0 +1,116 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#include + +#include "dds/ddsrt/filesystem.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/heap.h" + +dds_return_t ddsrt_opendir(const char *name, ddsrt_dir_handle_t *dir) +{ + dds_return_t result = DDS_RETCODE_ERROR; + DIR *d; + if (dir) { + d = opendir(name); + if (d) { + *dir = d; + result = DDS_RETCODE_OK; + } + } + return result; +} + +dds_return_t ddsrt_readdir(ddsrt_dir_handle_t d, struct ddsrt_dirent *direntp) +{ + dds_return_t result; + struct dirent *d_entry; + + result = DDS_RETCODE_ERROR; + if (d && direntp) { + d_entry = readdir(d); + if (d_entry) { + ddsrt_strlcpy(direntp->d_name, d_entry->d_name, sizeof(direntp->d_name)); + result = DDS_RETCODE_OK; + } + } + + return result; +} + +dds_return_t ddsrt_closedir(ddsrt_dir_handle_t d) +{ + dds_return_t result; + + result = DDS_RETCODE_ERROR; + if (d) { + if (closedir(d) == 0) { + result = DDS_RETCODE_OK; + } + } + + return result; +} + +dds_return_t ddsrt_stat(const char *path, struct ddsrt_stat *buf) +{ + dds_return_t result; + struct stat _buf; + int r; + + r = stat(path, &_buf); + if (r == 0) { + buf->stat_mode = _buf.st_mode; + buf->stat_size = (size_t) _buf.st_size; + buf->stat_mtime = DDS_SECS(_buf.st_mtime); + result = DDS_RETCODE_OK; + } else { + result = DDS_RETCODE_ERROR; + } + + return result; +} + +char * ddsrt_file_normalize(const char *filepath) +{ + char *norm; + const char *fpPtr; + char *normPtr; + + norm = NULL; + if ((filepath != NULL) && (*filepath != '\0')) { + norm = ddsrt_malloc(strlen(filepath) + 1); + /* replace any / or \ by DDSRT_FILESEPCHAR */ + fpPtr = (char *) filepath; + normPtr = norm; + while (*fpPtr != '\0') { + *normPtr = *fpPtr; + if ((*fpPtr == '/') || (*fpPtr == '\\')) { + *normPtr = DDSRT_FILESEPCHAR; + normPtr++; + } else { + if (*fpPtr != '\"') { + normPtr++; + } + } + fpPtr++; + } + *normPtr = '\0'; + } + + return norm; +} + +const char *ddsrt_file_sep(void) +{ + return "/"; +} diff --git a/src/ddsrt/src/filesystem/windows/filesystem.c b/src/ddsrt/src/filesystem/windows/filesystem.c new file mode 100644 index 0000000..068d76e --- /dev/null +++ b/src/ddsrt/src/filesystem/windows/filesystem.c @@ -0,0 +1,122 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#include + +#include "dds/ddsrt/filesystem.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/io.h" + +dds_return_t ddsrt_opendir(const char *name, ddsrt_dir_handle_t *dir) +{ + dds_return_t result; + + TCHAR szDir[DDSRT_PATH_MAX + 1]; + WIN32_FIND_DATA FileData; + HANDLE hList; + + result = DDS_RETCODE_ERROR; + if (dir) { + snprintf(szDir, DDSRT_PATH_MAX, "%s\\*", name); + hList = FindFirstFile(szDir, &FileData); + + if (hList != INVALID_HANDLE_VALUE) { + *dir = hList; + result = DDS_RETCODE_OK; + } + } + + return result; +} + +dds_return_t ddsrt_readdir(ddsrt_dir_handle_t d, struct ddsrt_dirent *direntp) +{ + dds_return_t result; + WIN32_FIND_DATA FileData; + BOOL r; + + if (direntp) { + r = FindNextFile(d, &FileData); + if (r) { + ddsrt_strlcpy(direntp->d_name, FileData.cFileName, sizeof(direntp->d_name)); + result = DDS_RETCODE_OK; + } else { + result = DDS_RETCODE_ERROR; + } + } else { + result = DDS_RETCODE_ERROR; + } + + return result; +} + +dds_return_t ddsrt_closedir(ddsrt_dir_handle_t d) +{ + FindClose(d); + + return DDS_RETCODE_OK; +} + +dds_return_t ddsrt_stat(const char *path, struct ddsrt_stat *buf) +{ + dds_return_t result; + struct _stat _buf; + int r; + + r = _stat(path, &_buf); + if (r == 0) { + buf->stat_mode = _buf.st_mode; + buf->stat_size = _buf.st_size; + buf->stat_mtime = DDS_SECS(_buf.st_mtime);; + result = DDS_RETCODE_OK; + } else { + result = DDS_RETCODE_ERROR; + } + + return result; +} + +char * ddsrt_file_normalize(const char *filepath) +{ + char *norm; + const char *fpPtr; + char *normPtr; + + norm = NULL; + if ((filepath != NULL) && (*filepath != '\0')) { + norm = ddsrt_malloc(strlen(filepath) + 1); + /* replace any / or \ by DDSRT_FILESEPCHAR */ + fpPtr = (char *) filepath; + normPtr = norm; + while (*fpPtr != '\0') { + *normPtr = *fpPtr; + if ((*fpPtr == '/') || (*fpPtr == '\\')) { + *normPtr = DDSRT_FILESEPCHAR; + normPtr++; + } else { + if (*fpPtr != '\"') { + normPtr++; + } + } + fpPtr++; + } + *normPtr = '\0'; + } + + return norm; +} + +const char *ddsrt_file_sep(void) +{ + return "\\"; +} diff --git a/src/security/builtin_plugins/access_control/src/access_control.c b/src/security/builtin_plugins/access_control/src/access_control.c index f356445..d26b761 100644 --- a/src/security/builtin_plugins/access_control/src/access_control.c +++ b/src/security/builtin_plugins/access_control/src/access_control.c @@ -26,6 +26,7 @@ #include "access_control_utils.h" #include "access_control_objects.h" #include "access_control_parser.h" +#include "dds/security/core/dds_security_timed_cb.h" #if OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10100000L #define REMOVE_THREAD_STATE() ERR_remove_thread_state(NULL); @@ -78,9 +79,10 @@ typedef struct dds_security_access_control_impl struct AccessControlTable *local_permissions; #endif struct AccessControlTable *remote_permissions; -#if TIMED_CALLBACK_IMPLEMENTED - struct ut_timed_dispatcher_t *timed_callbacks; -#endif + + struct dds_security_timed_cb_data *timed_callbacks; + struct dds_security_timed_dispatcher_t *dispatcher; + } dds_security_access_control_impl; static bool get_sec_attributes(dds_security_access_control_impl *ac, const DDS_Security_PermissionsHandle permissions_handle, const char *topic_name, @@ -105,9 +107,7 @@ static struct topic_rule *find_topic_from_domain_rule(struct domain_rule *domain static DDS_Security_boolean domainid_within_sets(struct domain_id_set *domain, int domain_id); static DDS_Security_boolean compare_class_id_plugin_classname(DDS_Security_string class_id_1, DDS_Security_string class_id_2); static DDS_Security_boolean compare_class_id_major_ver(DDS_Security_string class_id_1, DDS_Security_string class_id_2); -#if TIMED_CALLBACK_IMPLEMENTED - static void add_validity_end_trigger(dds_security_access_control_impl *ac, const DDS_Security_PermissionsHandle permissions_handle, dds_time_t end); -#endif +static void add_validity_end_trigger(dds_security_access_control_impl *ac, const DDS_Security_PermissionsHandle permissions_handle, dds_time_t end); static DDS_Security_boolean is_allowed_by_permissions(struct permissions_parser *permissions, int domain_id, const char *topic_name, const DDS_Security_PartitionQosPolicy *partitions, const char *identity_subject_name, permission_criteria_type criteria_type, DDS_Security_SecurityException *ex); static void sanity_check_local_access_rights(local_participant_access_rights *rights); @@ -168,10 +168,8 @@ validate_local_permissions( { assert (rights->permissions_expiry != DDS_TIME_INVALID); -#if TIMED_CALLBACK_IMPLEMENTED if (rights->permissions_expiry != 0) add_validity_end_trigger(ac, permissions_handle, rights->permissions_expiry); -#endif } return permissions_handle; @@ -232,10 +230,8 @@ validate_remote_permissions( permissions_handle = ACCESS_CONTROL_OBJECT_HANDLE(remote_rights); -#if TIMED_CALLBACK_IMPLEMENTED if (permissions_handle != DDS_SECURITY_HANDLE_NIL) add_validity_end_trigger(ac, permissions_handle, remote_rights->permissions_expiry); -#endif if (remote_rights) access_control_table_insert(ac->remote_permissions, (AccessControlObject *)remote_rights); @@ -926,16 +922,12 @@ set_listener(dds_security_access_control *instance, DDS_Security_SecurityException *ex) { DDSRT_UNUSED_ARG(ex); -#if TIMED_CALLBACK_IMPLEMENTED + dds_security_access_control_impl *ac = (dds_security_access_control_impl *)instance; if (listener) - ut_timed_dispatcher_enable(ac->timed_callbacks, (void *)listener); + dds_security_timed_dispatcher_enable(ac->timed_callbacks, ac->dispatcher, (void *)listener); else - ut_timed_dispatcher_disable(ac->timed_callbacks); -#else - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(listener); -#endif + dds_security_timed_dispatcher_disable(ac->timed_callbacks, ac->dispatcher); return true; } @@ -1490,9 +1482,9 @@ int init_access_control(const char *argument, void **context) dds_security_access_control_impl *access_control = ddsrt_malloc(sizeof(*access_control)); memset(access_control, 0, sizeof(*access_control)); -#if TIMED_CALLBACK_IMPLEMENTED - access_control->timed_callbacks = ut_timed_dispatcher_new(); -#endif + + access_control->timed_callbacks = dds_security_timed_cb_new(); + access_control->dispatcher = dds_security_timed_dispatcher_new(access_control->timed_callbacks); access_control->base.validate_local_permissions = &validate_local_permissions; access_control->base.validate_remote_permissions = &validate_remote_permissions; access_control->base.check_create_participant = &check_create_participant; @@ -1875,7 +1867,6 @@ find_remote_permissions_by_permissions_handle( return (remote_participant_access_rights *)args.object; } -#if TIMED_CALLBACK_IMPLEMENTED typedef struct { @@ -1884,15 +1875,17 @@ typedef struct } validity_cb_info; static void -validity_callback(struct ut_timed_dispatcher_t *d, - ut_timed_cb_kind kind, +validity_callback(struct dds_security_timed_dispatcher_t *d, + dds_security_timed_cb_kind kind, void *listener, void *arg) { validity_cb_info *info = arg; + + DDSRT_UNUSED_ARG(d); assert(d); assert(arg); - if (kind == UT_TIMED_CB_KIND_TIMEOUT) + if (kind == DDS_SECURITY_TIMED_CB_KIND_TIMEOUT) { assert(listener); if (1 /* TODO: Check if hdl is still valid or if it has been already returned. */) @@ -1913,9 +1906,8 @@ add_validity_end_trigger(dds_security_access_control_impl *ac, validity_cb_info *arg = ddsrt_malloc(sizeof(validity_cb_info)); arg->ac = ac; arg->hdl = permissions_handle; - ut_timed_dispatcher_add(ac->timed_callbacks, validity_callback, end, (void *)arg); + dds_security_timed_dispatcher_add(ac->timed_callbacks, ac->dispatcher, validity_callback, end, (void *)arg); } -#endif static DDS_Security_boolean is_allowed_by_permissions(struct permissions_parser *permissions, @@ -2465,9 +2457,10 @@ int finalize_access_control(void *context) dds_security_access_control_impl *access_control = context; if (access_control) { -#if TIMED_CALLBACK_IMPLEMENTED - ut_timed_dispatcher_free(access_control->timed_callbacks); -#endif + + dds_security_timed_dispatcher_free(access_control->timed_callbacks, access_control->dispatcher); + dds_security_timed_cb_free(access_control->timed_callbacks); + access_control_table_free(access_control->remote_permissions); #ifdef ACCESS_CONTROL_USE_ONE_PERMISSION if (access_control->local_access_rights) diff --git a/src/security/builtin_plugins/authentication/src/auth_utils.c b/src/security/builtin_plugins/authentication/src/auth_utils.c index 430dffd..54b2224 100644 --- a/src/security/builtin_plugins/authentication/src/auth_utils.c +++ b/src/security/builtin_plugins/authentication/src/auth_utils.c @@ -30,6 +30,8 @@ #include #include "dds/ddsrt/time.h" #include "dds/ddsrt/heap.h" +#include "dds/ddsrt/filesystem.h" +#include "dds/ddsrt/retcode.h" #include "dds/security/dds_security_api_defs.h" #include "dds/security/core/dds_security_utils.h" #include @@ -47,11 +49,11 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/string.h" +#include "dds/ddsrt/io.h" #include "dds/security/core/dds_security_utils.h" #include #include "auth_utils.h" - #define MAX_TRUSTED_CA 100 char * @@ -1190,40 +1192,29 @@ get_trusted_ca_list ( const char* trusted_ca_dir, DDS_Security_ValidationResult_t loading_result = DDS_RETCODE_OK; - DDSRT_UNUSED_ARG( ca_list ); - DDSRT_UNUSED_ARG( trusted_ca_dir ); - DDSRT_UNUSED_ARG( ex ); -/* TODO: Trusted CA directory tracing function should be ported */ -/* TODO: MAX_TRUSTED_CA limitation will be removed */ -#ifdef TRUSTED_CA_LIST_IMPLEMENTED - os_result r; - os_dirHandle d_descr; - struct os_dirent d_entry; - struct os_stat_s status; + dds_return_t r; + ddsrt_dir_handle_t d_descr; + struct ddsrt_dirent d_entry; + struct ddsrt_stat status; char *full_file_path; char *trusted_ca_dir_normalized; X509 *ca_buffer_array[MAX_TRUSTED_CA]; /*max trusted CA size */ unsigned ca_buffer_array_size=0; unsigned i; - trusted_ca_dir_normalized = os_fileNormalize(trusted_ca_dir); + trusted_ca_dir_normalized = ddsrt_file_normalize(trusted_ca_dir); - r = os_opendir(trusted_ca_dir_normalized, &d_descr); + r = ddsrt_opendir(trusted_ca_dir_normalized, &d_descr); ddsrt_free ( trusted_ca_dir_normalized ); - - if (r == os_resultSuccess && ca_buffer_array_size < MAX_TRUSTED_CA) { /* accessable */ - r = os_readdir(d_descr, &d_entry); - while (r == os_resultSuccess) { - full_file_path = (char*) ddsrt_malloc(strlen(trusted_ca_dir) + strlen(os_fileSep()) + strlen(d_entry.d_name) + strlen(os_fileSep()) + 1 ); - ddsrt_strcpy(full_file_path, trusted_ca_dir); - ddsrt_strcat(full_file_path, os_fileSep()); - ddsrt_strcat(full_file_path, d_entry.d_name); - - if (os_stat (full_file_path, &status) == os_resultSuccess) { /* accessable */ + if (r == DDS_RETCODE_OK && ca_buffer_array_size < MAX_TRUSTED_CA) { /* accessable */ + r = ddsrt_readdir(d_descr, &d_entry); + while (r == DDS_RETCODE_OK) { + ddsrt_asprintf(&full_file_path, "%s%s%s", trusted_ca_dir, ddsrt_file_sep(), d_entry.d_name); + if (ddsrt_stat (full_file_path, &status) == DDS_RETCODE_OK) { /* accessable */ if ((strcmp(d_entry.d_name, ".") != 0) && (strcmp(d_entry.d_name, "..") != 0)) { - char * filename = os_fileNormalize(full_file_path); + char * filename = ddsrt_file_normalize(full_file_path); if(filename){ X509 *identityCA; @@ -1239,26 +1230,26 @@ get_trusted_ca_list ( const char* trusted_ca_dir, } } } - r = os_readdir(d_descr, &d_entry); + r = ddsrt_readdir(d_descr, &d_entry); ddsrt_free(full_file_path); } - os_closedir (d_descr); + ddsrt_closedir (d_descr); /* deallocate given ca_list if it is not NULL */ free_ca_list_contents(ca_list); /*copy CAs to out parameter as HASH*/ if( ca_buffer_array_size > 0 ){ - ca_list->_buffer = ddsrt_malloc( ca_buffer_array_size * sizeof(X509 * ) ); + ca_list->buffer = ddsrt_malloc( ca_buffer_array_size * sizeof(X509 * ) ); for (i = 0; i < ca_buffer_array_size; ++i) { - ca_list->_buffer[i] = ca_buffer_array[i]; + ca_list->buffer[i] = ca_buffer_array[i]; } } - ca_list->_length = ca_buffer_array_size; + ca_list->length = ca_buffer_array_size; return DDS_SECURITY_VALIDATION_OK; @@ -1267,7 +1258,6 @@ get_trusted_ca_list ( const char* trusted_ca_dir, DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_TRUSTED_CA_DIR_CODE, 0, DDS_SECURITY_ERR_INVALID_TRUSTED_CA_DIR_MESSAGE); return DDS_SECURITY_VALIDATION_FAILED; } -#endif return loading_result; } diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index dada4db..a3d5ea7 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -22,6 +22,7 @@ #include "authentication.h" #include "dds/ddsrt/heap.h" #include "dds/security/dds_security_api.h" +#include "dds/security/core/dds_security_timed_cb.h" #if OPENSLL_VERSION_NUMBER >= 0x10002000L @@ -202,7 +203,8 @@ typedef struct dds_security_authentication_impl { ddsrt_mutex_t lock; struct ddsrt_hh *objectHash; struct ddsrt_hh *remoteGuidHash; - struct ut_timed_dispatcher_t *timed_callbacks; + struct dds_security_timed_cb_data *timed_callbacks; + struct dds_security_timed_dispatcher_t *dispatcher; X509Seq trustedCAList; @@ -844,22 +846,19 @@ hash_value_to_binary_property( return bp; } - -/* Will be enabled after timed callback feature implementation */ -#if TIMED_CALLBACK_IMPLEMENTED - static void -validity_callback(struct ut_timed_dispatcher_t *d, - ut_timed_cb_kind kind, +validity_callback(struct dds_security_timed_dispatcher_t *d, + dds_security_timed_cb_kind kind, void *listener, void *arg) { validity_cb_info *info = arg; + DDSRT_UNUSED_ARG(d); assert(d); assert(arg); - if (kind == UT_TIMED_CB_KIND_TIMEOUT) { + if (kind == DDS_SECURITY_TIMED_CB_KIND_TIMEOUT) { assert(listener); dds_security_authentication_listener *auth_listener = (dds_security_authentication_listener*)listener; if (auth_listener->on_revoke_identity) { @@ -872,26 +871,19 @@ validity_callback(struct ut_timed_dispatcher_t *d, ddsrt_free(arg); } -#endif static void add_validity_end_trigger(dds_security_authentication_impl *auth, const DDS_Security_IdentityHandle identity_handle, dds_time_t end) { - DDSRT_UNUSED_ARG( auth ); - DDSRT_UNUSED_ARG( identity_handle ); - DDSRT_UNUSED_ARG( end ); - /* Will be enabled after timed call back feature implementation */ - /* validity_cb_info *arg = ddsrt_malloc(sizeof(validity_cb_info)); arg->auth = auth; arg->hdl = identity_handle; - ut_timed_dispatcher_add(auth->timed_callbacks, + dds_security_timed_dispatcher_add(auth->timed_callbacks, auth->dispatcher, validity_callback, end, (void*)arg); - */ } @@ -3170,18 +3162,14 @@ DDS_Security_boolean set_listener(dds_security_authentication *instance, { dds_security_authentication_impl *auth = (dds_security_authentication_impl*)instance; - DDSRT_UNUSED_ARG(auth); - DDSRT_UNUSED_ARG(listener); DDSRT_UNUSED_ARG(ex); - /* Will be enabled after timed call back feature implementation */ -#if TIMED_CALLBACK_IMPLEMENTED if (listener) { - ut_timed_dispatcher_enable(auth->timed_callbacks, (void*)listener); + dds_security_timed_dispatcher_enable(auth->timed_callbacks, auth->dispatcher, (void*)listener); } else { - ut_timed_dispatcher_disable(auth->timed_callbacks); + dds_security_timed_dispatcher_disable(auth->timed_callbacks, auth->dispatcher); } -#endif + return true; } @@ -3398,8 +3386,8 @@ init_authentication( const char *argument, void **context) memset(authentication, 0, sizeof(dds_security_authentication_impl)); /* assign dispatcher to be notified when a validity date ends */ - /* Disable it until timed callback is ready */ - /*authentication->timed_callbacks = ut_timed_dispatcher_new(); */ + authentication->timed_callbacks = dds_security_timed_cb_new(); + authentication->dispatcher = dds_security_timed_dispatcher_new(authentication->timed_callbacks); /* assign the interface functions */ authentication->base.validate_local_identity = &validate_local_identity; @@ -3474,8 +3462,9 @@ int32_t finalize_authentication(void *instance) if( authentication ){ ddsrt_mutex_lock(&authentication->lock); - /* Will be enabled after timed call back feature implementation */ - /* ut_timed_dispatcher_free(authentication->timed_callbacks); */ + dds_security_timed_dispatcher_free(authentication->timed_callbacks, authentication->dispatcher); + dds_security_timed_cb_free(authentication->timed_callbacks); + if (authentication->remoteGuidHash) { ddsrt_hh_free(authentication->remoteGuidHash); } diff --git a/src/security/builtin_plugins/tests/CMakeLists.txt b/src/security/builtin_plugins/tests/CMakeLists.txt index d822524..ac56a7f 100644 --- a/src/security/builtin_plugins/tests/CMakeLists.txt +++ b/src/security/builtin_plugins/tests/CMakeLists.txt @@ -21,6 +21,8 @@ set(security_auth_test_sources "validate_begin_handshake_request/src/validate_begin_handshake_request_utests.c" "validate_local_identity/src/validate_local_identity_utests.c" "validate_remote_identity/src/validate_remote_identity_utests.c" + "listeners_authentication/src/listeners_authentication_utests.c" + "listeners_access_control/src/listeners_access_control_utests.c" ) set(security_ac_test_sources @@ -74,6 +76,7 @@ if(OPENSSL_FOUND) target_link_libraries(cunit_security_plugins PRIVATE ddsc dds_security_ac) target_link_libraries(cunit_security_plugins PRIVATE ddsc dds_security_crypto) target_link_libraries(cunit_security_plugins PRIVATE OpenSSL::SSL) + else() message(FATAL_ERROR "To build with openssl support, set ENABLE_OPENSSL to ON") endif() @@ -92,5 +95,8 @@ target_include_directories( set(CUnit_builtin_plugins_tests_dir "${CMAKE_CURRENT_LIST_DIR}") +set(CUnit_build_dir "${CMAKE_CURRENT_BINARY_DIR}") configure_file("config_env.h.in" "config_env.h") + + diff --git a/src/security/builtin_plugins/tests/config_env.h.in b/src/security/builtin_plugins/tests/config_env.h.in index 3f2b23a..c22d1f5 100644 --- a/src/security/builtin_plugins/tests/config_env.h.in +++ b/src/security/builtin_plugins/tests/config_env.h.in @@ -13,5 +13,6 @@ #define CONFIG_ENV_H #define CONFIG_ENV_TESTS_DIR "@CUnit_builtin_plugins_tests_dir@" +#define CONFIG_ENV_BUILD_DIR "@CUnit_build_dir@" #endif /* CONFIG_ENV_H */ diff --git a/src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Permissions_listener.p7s b/src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Permissions_listener.p7s deleted file mode 100644 index 08434a9..0000000 --- a/src/security/builtin_plugins/tests/listeners_access_control/etc/Test_Permissions_listener.p7s +++ /dev/null @@ -1,51 +0,0 @@ -MIME-Version: 1.0 -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----3900963D3572093F6AEC654A72CAEE5A" - -This is an S/MIME signed message - -------3900963D3572093F6AEC654A72CAEE5A -Content-Type: text/plain - - /C=NL/ST=Some-State/O=Internet Widgits Pty Ltd/CN=CHAM500 cert 2015-09-15T01:00:00 2019-11-18T11:48:49 0 230 * * DENY -------3900963D3572093F6AEC654A72CAEE5A -Content-Type: application/x-pkcs7-signature; name="smime.p7s" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; filename="smime.p7s" - -MIIGSAYJKoZIhvcNAQcCoIIGOTCCBjUCAQExDzANBglghkgBZQMEAgEFADALBgkq -hkiG9w0BBwGgggORMIIDjTCCAnWgAwIBAgIJANsr3sm0NrypMA0GCSqGSIb3DQEB -CwUAMFwxCzAJBgNVBAYTAk5MMRMwEQYDVQQIDApTb21lLVN0YXRlMR8wHQYDVQQK -DBZBRExJTksgVGVjaG5vbG9jeSBJbmMuMRcwFQYDVQQDDA5hZGxpbmt0ZWNoLmNv -bTAgFw0xODA3MzAxMjQ1NTVaGA8yMTE4MDcwNjEyNDU1NVowXDELMAkGA1UEBhMC -TkwxEzARBgNVBAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9s -b2N5IEluYy4xFzAVBgNVBAMMDmFkbGlua3RlY2guY29tMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEAu7jfnJ0wYVuXgG+PgNawdN38+dRpa8jceqi+blID -ehV6XCxrnGXusTCDuFmo7HMOBVMVNDXlcBWgoGd+u5EultnOEiIeGTgtHc1O6V9w -icp3BGSpZZax/TcONjMVORaqHCADbQ2J8wsz1FHxuKDwX6BJElYOlK77lb/x3yLs -DFFC+a0qn2RFh37rcWBRAHy8VEASXKZElT9ZmfKd+KUq34KojhNJ4DepKStTq074 -BRDXVivx+wVD951LFNPiQXq+mgHcLj1k37KlZflTFhdP5oEMtATNsXNJPHlEymiy -SogRWAmKhysLQudukHfNKN+r0FEQMk/hzpYcFeZSOvbfNQIDAQABo1AwTjAdBgNV -HQ4EFgQURWMbWvBKZwJvRV1/tyc1R82k0+gwHwYDVR0jBBgwFoAURWMbWvBKZwJv -RV1/tyc1R82k0+gwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkPF+ -ysVtvHnk2hpu9yNDLCJ96ZzIoKOyY7uRj4ovzlAHFdpNOJQdcJihTmN8i7Trht9X -Vh0rGoR/6nHzo3TIeiogRC80RlDtuA3PF2dDQBMVDStlZMTZPb693hfjdAjhyyw9 -yghhKHHqNDvSsAL0KfBqjG4yGfGpJylYXIT5fWuKlo/ln/yyPa5s54T5XDo+CMbt -lLX3QnwVOmaRyzylPiTcPCDIkdLBdXmlfyJcmW6fWa6kPx+35MOxPsXZbujCo+42 -+OyLqcH1rKT6XhcshjXBEf+kdgUfSClrM1pNRWsw2ChIYim0F+nry5JFy0Y+8Hbb -6SDB340BFmtgDHbFHTGCAnswggJ3AgEBMGkwXDELMAkGA1UEBhMCTkwxEzARBgNV -BAgMClNvbWUtU3RhdGUxHzAdBgNVBAoMFkFETElOSyBUZWNobm9sb2N5IEluYy4x -FzAVBgNVBAMMDmFkbGlua3RlY2guY29tAgkA2yveybQ2vKkwDQYJYIZIAWUDBAIB -BQCggeQwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcN -MTkxMTE4MTE0ODQ4WjAvBgkqhkiG9w0BCQQxIgQgaLNNlFwfVR0PrziT9wCAy5bM -qCZJX9yO3xJgut3/o7EweQYJKoZIhvcNAQkPMWwwajALBglghkgBZQMEASowCwYJ -YIZIAWUDBAEWMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAOBggqhkiG9w0DAgIC -AIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwDQYJKoZI -hvcNAQEBBQAEggEAWCFrUIvdYKBeT0lmpkRdmYJuvdmQ/Ro7k9iyreVofpB1/70B -hVOEeRjrlmhv/TUjSgQyli56wmXFmexcNRzSzpPNycz0gjwP9kX5BMnhAkKd08fC -4rgoirScmNxvxEkj5+wyq7s7rBEJOgVQ9ofwiZXEBVDMVvW2ENZhVF3FyoNulDQe -6BjXkuLw/QrJLWjywPy5naSSda2T7V3+Ssdu5/2vEjXPIJMM+xPOCaqGHJsSb72s -KiP48jZ95Wruvj3QAlpGxDaazWPTgn7tfThYrY3Kgiz5zyZM7FhFyIqxRF/89Ngo -hbu2mWzcXFF7wBLy+CvK5Foajro9t/PzD8uNuA== - -------3900963D3572093F6AEC654A72CAEE5A-- - diff --git a/src/security/builtin_plugins/tests/listeners_access_control/src/listeners_access_control_utests.c b/src/security/builtin_plugins/tests/listeners_access_control/src/listeners_access_control_utests.c index 5f32d09..f215738 100644 --- a/src/security/builtin_plugins/tests/listeners_access_control/src/listeners_access_control_utests.c +++ b/src/security/builtin_plugins/tests/listeners_access_control/src/listeners_access_control_utests.c @@ -215,6 +215,7 @@ static DDS_Security_PermissionsHandle local_permissions_handle = DDS_SECURITY_HA static DDS_Security_PermissionsHandle remote_permissions_handle = DDS_SECURITY_HANDLE_NIL; static DDS_Security_GUID_t local_participant_guid; static char *g_path_to_etc_dir = NULL; +static char *g_path_build_dir = NULL; static DDS_Security_PermissionsHandle permission_handle_for_callback1 = DDS_SECURITY_HANDLE_NIL; static DDS_Security_PermissionsHandle permission_handle_for_callback2 = DDS_SECURITY_HANDLE_NIL; static dds_time_t local_expiry_date; @@ -251,14 +252,16 @@ static void reset_exception(DDS_Security_SecurityException *ex) static void get_future_xsdate(char *str, size_t len, int32_t delta) { time_t rawtime; - struct tm *future; + struct tm *future = ddsrt_malloc(sizeof(struct tm)); /* Get future time. */ rawtime = time(NULL) + delta; - future = gmtime(&rawtime); + OPENSSL_gmtime(&rawtime, future); /* Put the future time in a xsDate format. */ strftime(str, len, "%Y-%m-%dT%H:%M:%S", future); + + ddsrt_free(future); } static int smime_sign(const char *certificate_file, const char *key_file, const char *data, const char *out_file) @@ -345,7 +348,7 @@ static void fill_participant_qos(DDS_Security_Qos *qos, int32_t permission_expir ddsrt_asprintf(&permissions_ca_cert_file, "%s%s", g_path_to_etc_dir, PERMISSIONS_CA_CERT_FILE); ddsrt_asprintf(&permissions_ca_key_file, "%s%s", g_path_to_etc_dir, PERMISSIONS_CA_KEY_FILE); - ddsrt_asprintf(&permissions_file, "%s%s", g_path_to_etc_dir, PERMISSIONS_FILE); + ddsrt_asprintf(&permissions_file, "%s%s", g_path_build_dir, PERMISSIONS_FILE); smime_sign(permissions_ca_cert_file, permissions_ca_key_file, permissions_xml_with_expiry, permissions_file); @@ -407,9 +410,9 @@ static int fill_peer_credential_token(DDS_Security_AuthenticatedPeerCredentialTo remote_expiry_date = DDS_Security_parse_xml_date(permission_expiry_date_str); permissions_xml_with_expiry = ddsrt_str_replace(PERMISSIONS_DOCUMENT, "PERMISSION_EXPIRY_DATE", permission_expiry_date_str, 1); - ddsrt_asprintf(permissions_ca_cert_file, "%s%s", g_path_to_etc_dir, PERMISSIONS_CA_CERT_FILE); - ddsrt_asprintf(permissions_ca_key_file, "%s%s", g_path_to_etc_dir, PERMISSIONS_CA_KEY_FILE); - ddsrt_asprintf(permissions_file, "%s%s", g_path_to_etc_dir, PERMISSIONS_FILE); + ddsrt_asprintf(&permissions_ca_cert_file, "%s%s", g_path_to_etc_dir, PERMISSIONS_CA_CERT_FILE); + ddsrt_asprintf(&permissions_ca_key_file, "%s%s", g_path_to_etc_dir, PERMISSIONS_CA_KEY_FILE); + ddsrt_asprintf(&permissions_file, "%s%s", g_path_build_dir, PERMISSIONS_FILE); smime_sign(permissions_ca_cert_file, permissions_ca_key_file, permissions_xml_with_expiry, permissions_file); @@ -531,17 +534,29 @@ static void set_path_to_etc_dir(void) { ddsrt_asprintf(&g_path_to_etc_dir, "%s%s", CONFIG_ENV_TESTS_DIR, RELATIVE_PATH_TO_ETC_DIR); } - -static void suite_listeners_access_control_init(void) +static void set_path_build_dir(void) { - plugins = load_plugins(&access_control, &auth, NULL /* Cryptograpy */); - CU_ASSERT_FATAL(plugins != NULL); - set_path_to_etc_dir(); - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); + ddsrt_asprintf(&g_path_build_dir, "%s/", CONFIG_ENV_BUILD_DIR); } -static void suite_listeners_access_control_fini(void) +CU_Init(ddssec_builtin_listeners_access_control) +{ + int res = 0; + + plugins = load_plugins(&access_control, &auth, NULL /* Cryptograpy */); + if (!plugins) { + res = -1; + } else { + set_path_to_etc_dir(); + set_path_build_dir(); + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + } + + return res; +} + +CU_Clean(ddssec_builtin_listeners_access_control) { unload_plugins(plugins); ddsrt_free(g_path_to_etc_dir); @@ -549,6 +564,8 @@ static void suite_listeners_access_control_fini(void) CRYPTO_cleanup_all_ex_data(); REMOVE_THREAD_STATE(); ERR_free_strings(); + + return 0; } static DDS_Security_boolean on_revoke_permissions_cb(dds_security_access_control_listener *instance, const dds_security_access_control *plugin, const DDS_Security_PermissionsHandle handle) @@ -559,11 +576,11 @@ static DDS_Security_boolean on_revoke_permissions_cb(dds_security_access_control permission_handle_for_callback1 = handle; else if (permission_handle_for_callback2 == DDS_SECURITY_HANDLE_NIL) permission_handle_for_callback2 = handle; - printf("Listener called for handle: %lld Local:%ld Remote:%ld\n", (long long)handle, local_permissions_handle, remote_permissions_handle); + printf("Listener called for handle: %lld Local:%lld Remote:%lld\n", (long long)handle, (long long)local_permissions_handle, (long long)remote_permissions_handle); return true; } -CU_Test(ddssec_builtin_listeners_access_control, local_2secs, .init = suite_listeners_access_control_init, .fini = suite_listeners_access_control_fini) +CU_Test(ddssec_builtin_listeners_access_control, local_2secs) { DDS_Security_PermissionsHandle result; DDS_Security_PermissionsToken permissions_token; diff --git a/src/security/builtin_plugins/tests/listeners_authentication/etc/Example_Governance.p7s b/src/security/builtin_plugins/tests/listeners_authentication/etc/Example_Governance.p7s new file mode 100644 index 0000000..8c6aae5 --- /dev/null +++ b/src/security/builtin_plugins/tests/listeners_authentication/etc/Example_Governance.p7s @@ -0,0 +1,120 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----8F2D5CA80FE8B4509AF031712E008F0E" + +This is an S/MIME signed message + +------8F2D5CA80FE8B4509AF031712E008F0E +Content-Type: text/plain + + + + + + + + + 0 + 230 + + + + + true + + + true + + + ENCRYPT + + + ENCRYPT + + + ENCRYPT + + + + + * + + + true + + + true + + + true + + + true + + + ENCRYPT + + + ENCRYPT + + + + + + +------8F2D5CA80FE8B4509AF031712E008F0E +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIHiwYJKoZIhvcNAQcCoIIHfDCCB3gCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggRnMIIEYzCCA0ugAwIBAgIJAM3yAtULcaEIMA0GCSqGSIb3DQEB +CwUAMIHHMQswCQYDVQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2Fs +aXR5IE5hbWUxITAfBgNVBAsMGE9yZ2FuaXphdGlvbmFsIFVuaXQgTmFtZTEgMB4G +A1UECgwXRXhhbXBsZSBDQSBPcmdhbml6YXRpb24xHzAdBgNVBAMMFkV4YW1wbGUg +UGVybWlzc2lvbnMgQ0ExLTArBgkqhkiG9w0BCQEWHmF1dGhvcml0eUBwZXJtaXNz +aW9uc2NhbHRkLm9yZzAeFw0xOTAyMTIxMzUyMzJaFw0yOTAyMDkxMzUyMzJaMIHH +MQswCQYDVQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2FsaXR5IE5h +bWUxITAfBgNVBAsMGE9yZ2FuaXphdGlvbmFsIFVuaXQgTmFtZTEgMB4GA1UECgwX +RXhhbXBsZSBDQSBPcmdhbml6YXRpb24xHzAdBgNVBAMMFkV4YW1wbGUgUGVybWlz +c2lvbnMgQ0ExLTArBgkqhkiG9w0BCQEWHmF1dGhvcml0eUBwZXJtaXNzaW9uc2Nh +bHRkLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKD6nYCszMha +h3xGfJy8f3lowPHIj6zcldVYs5Krg7zXxZn+20lAMHUfgQcWZAauKbCnokYfTvXV +v0j9HCpQ3mRynNTyjLjc7HxAe6kfaJ75PoIoOMMQMEGvPOqRUq0tomVVJvcgzZZk +pwE30E6xvZrlQcrkQY/aOQ0sbje+RN8RKQ9vf6O45Np/0m2K5ohZPlBqg4F539v2 +iXGZczCr9AqAszc/7rOPX1aqZmmRDou0T+Zhx3ZZSAwZYQtr7uvvlUeGmDhNh+8p +LC+1FQPtkKmcVXO8oZWm5N8piOvH3M+v3qhyPtLv30cpl0bDiFl+PN7nZ6InOOtd +ZJVMa2rYCk8CAwEAAaNQME4wHQYDVR0OBBYEFA/CtiP8Z5Fk4aWDIb2j3FPwh9pg +MB8GA1UdIwQYMBaAFA/CtiP8Z5Fk4aWDIb2j3FPwh9pgMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQELBQADggEBACBupRddIR9zYBFLGFTzeiW+H1tRRKz+B3SWnCJH +89ijEdMYlKKLYT0R18lCV0vHnl29bU1CPlkLn+GQkvdfIjKguWEQKTP+GLzoa9TV +zOKAJ8NttCyW3YqriUOUGKqra1Fdt8nvrAyZUF+v/k8pTInmCvwu3l5HrVhkKHER +IbCIohKi/2mk1JZS9reWvZhqLoUIw5IDFlqtBDYOfMaqm8XF01YjEDBM6OuyQzYN +gDFVUZx0At4zzRjGTvqpLTkDYL1A3v4QYXZcwZiKeEVbFuNkauXgD+8pEZMB8yL4 +h1feIH+aucsAKBz1Ne5fTiTCannlKvLl8xWz5IdzP7gF0LIxggLoMIIC5AIBATCB +1TCBxzELMAkGA1UEBhMCTkwxCzAJBgNVBAgMAk9WMRYwFAYDVQQHDA1Mb2NhbGl0 +eSBOYW1lMSEwHwYDVQQLDBhPcmdhbml6YXRpb25hbCBVbml0IE5hbWUxIDAeBgNV +BAoMF0V4YW1wbGUgQ0EgT3JnYW5pemF0aW9uMR8wHQYDVQQDDBZFeGFtcGxlIFBl +cm1pc3Npb25zIENBMS0wKwYJKoZIhvcNAQkBFh5hdXRob3JpdHlAcGVybWlzc2lv +bnNjYWx0ZC5vcmcCCQDN8gLVC3GhCDANBglghkgBZQMEAgEFAKCB5DAYBgkqhkiG +9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xOTEyMDcxNjAxMjZa +MC8GCSqGSIb3DQEJBDEiBCCAw/IHksMBWVnBQEtBoPLvJ1B+9IvOrQ4OkihJ6q0v +ijB5BgkqhkiG9w0BCQ8xbDBqMAsGCWCGSAFlAwQBKjALBglghkgBZQMEARYwCwYJ +YIZIAWUDBAECMAoGCCqGSIb3DQMHMA4GCCqGSIb3DQMCAgIAgDANBggqhkiG9w0D +AgIBQDAHBgUrDgMCBzANBggqhkiG9w0DAgIBKDANBgkqhkiG9w0BAQEFAASCAQAd +j3vO63v4bBbNhE0wZ8gWPHFfJsZO4JUu+ZzJ08hO1fku07Q13medyyp1+6jeZWoV +rCqQbG37xL1dx023wsRu+mYPSgEtIx2zBGW8ADk2qEIGAVPUPGUiVXl6+7esAmnP +AFDrt3Qp6nEZIr7iQ6i+4WW3kWM3o9C1ghSz4tVBjP9El5/yrux2mo5DTSeB8QMR +npMNgwgatwAxTwUrBpQj0FE5NUDm21OT1VwlUAGTHz6m5npw92p6qvQxFYufRzWj +XoADdJW0qgfbL00Gvoimi2K21cSUqiYcKU06eQeCkrLXyjif2JlFdKXvODwlydOy +dtwcKpPKVKgBI01+5Imf + +------8F2D5CA80FE8B4509AF031712E008F0E-- + diff --git a/src/security/builtin_plugins/tests/listeners_authentication/etc/Example_Permissions_Alice.p7s b/src/security/builtin_plugins/tests/listeners_authentication/etc/Example_Permissions_Alice.p7s new file mode 100644 index 0000000..1e19a63 --- /dev/null +++ b/src/security/builtin_plugins/tests/listeners_authentication/etc/Example_Permissions_Alice.p7s @@ -0,0 +1,98 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----51AB97062CF028E6EBDDAA31699954BC" + +This is an S/MIME signed message + +------51AB97062CF028E6EBDDAA31699954BC +Content-Type: text/plain + + + + + + /C=NL/ST=OV/L=Locality Name/OU=Organizational Unit Name/O=Example Organization/CN=Alice Example/emailAddress=alice@exampleltd.com + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + * + + + + + * + + + * + + + + + DENY + + + + +------51AB97062CF028E6EBDDAA31699954BC +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIHiwYJKoZIhvcNAQcCoIIHfDCCB3gCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggRnMIIEYzCCA0ugAwIBAgIJAM3yAtULcaEIMA0GCSqGSIb3DQEB +CwUAMIHHMQswCQYDVQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2Fs +aXR5IE5hbWUxITAfBgNVBAsMGE9yZ2FuaXphdGlvbmFsIFVuaXQgTmFtZTEgMB4G +A1UECgwXRXhhbXBsZSBDQSBPcmdhbml6YXRpb24xHzAdBgNVBAMMFkV4YW1wbGUg +UGVybWlzc2lvbnMgQ0ExLTArBgkqhkiG9w0BCQEWHmF1dGhvcml0eUBwZXJtaXNz +aW9uc2NhbHRkLm9yZzAeFw0xOTAyMTIxMzUyMzJaFw0yOTAyMDkxMzUyMzJaMIHH +MQswCQYDVQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2FsaXR5IE5h +bWUxITAfBgNVBAsMGE9yZ2FuaXphdGlvbmFsIFVuaXQgTmFtZTEgMB4GA1UECgwX +RXhhbXBsZSBDQSBPcmdhbml6YXRpb24xHzAdBgNVBAMMFkV4YW1wbGUgUGVybWlz +c2lvbnMgQ0ExLTArBgkqhkiG9w0BCQEWHmF1dGhvcml0eUBwZXJtaXNzaW9uc2Nh +bHRkLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKD6nYCszMha +h3xGfJy8f3lowPHIj6zcldVYs5Krg7zXxZn+20lAMHUfgQcWZAauKbCnokYfTvXV +v0j9HCpQ3mRynNTyjLjc7HxAe6kfaJ75PoIoOMMQMEGvPOqRUq0tomVVJvcgzZZk +pwE30E6xvZrlQcrkQY/aOQ0sbje+RN8RKQ9vf6O45Np/0m2K5ohZPlBqg4F539v2 +iXGZczCr9AqAszc/7rOPX1aqZmmRDou0T+Zhx3ZZSAwZYQtr7uvvlUeGmDhNh+8p +LC+1FQPtkKmcVXO8oZWm5N8piOvH3M+v3qhyPtLv30cpl0bDiFl+PN7nZ6InOOtd +ZJVMa2rYCk8CAwEAAaNQME4wHQYDVR0OBBYEFA/CtiP8Z5Fk4aWDIb2j3FPwh9pg +MB8GA1UdIwQYMBaAFA/CtiP8Z5Fk4aWDIb2j3FPwh9pgMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQELBQADggEBACBupRddIR9zYBFLGFTzeiW+H1tRRKz+B3SWnCJH +89ijEdMYlKKLYT0R18lCV0vHnl29bU1CPlkLn+GQkvdfIjKguWEQKTP+GLzoa9TV +zOKAJ8NttCyW3YqriUOUGKqra1Fdt8nvrAyZUF+v/k8pTInmCvwu3l5HrVhkKHER +IbCIohKi/2mk1JZS9reWvZhqLoUIw5IDFlqtBDYOfMaqm8XF01YjEDBM6OuyQzYN +gDFVUZx0At4zzRjGTvqpLTkDYL1A3v4QYXZcwZiKeEVbFuNkauXgD+8pEZMB8yL4 +h1feIH+aucsAKBz1Ne5fTiTCannlKvLl8xWz5IdzP7gF0LIxggLoMIIC5AIBATCB +1TCBxzELMAkGA1UEBhMCTkwxCzAJBgNVBAgMAk9WMRYwFAYDVQQHDA1Mb2NhbGl0 +eSBOYW1lMSEwHwYDVQQLDBhPcmdhbml6YXRpb25hbCBVbml0IE5hbWUxIDAeBgNV +BAoMF0V4YW1wbGUgQ0EgT3JnYW5pemF0aW9uMR8wHQYDVQQDDBZFeGFtcGxlIFBl +cm1pc3Npb25zIENBMS0wKwYJKoZIhvcNAQkBFh5hdXRob3JpdHlAcGVybWlzc2lv +bnNjYWx0ZC5vcmcCCQDN8gLVC3GhCDANBglghkgBZQMEAgEFAKCB5DAYBgkqhkiG +9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xOTEyMDcxNjAxMjZa +MC8GCSqGSIb3DQEJBDEiBCAX5wSM0Og83gWKRmru9iCOm8h85e9oZ7rBebmSbLVN +1TB5BgkqhkiG9w0BCQ8xbDBqMAsGCWCGSAFlAwQBKjALBglghkgBZQMEARYwCwYJ +YIZIAWUDBAECMAoGCCqGSIb3DQMHMA4GCCqGSIb3DQMCAgIAgDANBggqhkiG9w0D +AgIBQDAHBgUrDgMCBzANBggqhkiG9w0DAgIBKDANBgkqhkiG9w0BAQEFAASCAQAT +QZbljrtQs/FcBUJBYoenquAQ5++twy5LE6A06dASaHFDxSxPsAe0KBl9EWJzE59X +4k73u+4bJZiuLHUPztuXIUt3gEKM72DDT+ET/13dWdM2vtITW6HZ27nvkngE35cc +kdUqkLyeM5dzsSDpr3Ba8epulThlwl7bw9dUd2FUOBCc266da+q1lcChjwfC5GBu +GB7oWODhSAk6L9dici8w5q9ybygBkFJHXTZVtsXQWuNmDtXWB2ury++WQlvtNK0s +aF+dtQlyEx2vvi5tV195vncAt514uHJ9optdEbaIyMo51G53QD0Cq62QhuFusug0 +nz2pgcEZ35JCd4gESMkL + +------51AB97062CF028E6EBDDAA31699954BC-- + diff --git a/src/security/builtin_plugins/tests/listeners_authentication/etc/Example_Permissions_Bob.p7s b/src/security/builtin_plugins/tests/listeners_authentication/etc/Example_Permissions_Bob.p7s new file mode 100644 index 0000000..f5ab923 --- /dev/null +++ b/src/security/builtin_plugins/tests/listeners_authentication/etc/Example_Permissions_Bob.p7s @@ -0,0 +1,98 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----EDFB3CE1089204FED046E2D32968C669" + +This is an S/MIME signed message + +------EDFB3CE1089204FED046E2D32968C669 +Content-Type: text/plain + + + + + + /C=NL/ST=OV/L=Locality Name/OU=Organizational Unit Name/O=Example Organization/CN=Bob Example/emailAddress=bob@exampleltd.com + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + * + + + + + * + + + * + + + + + DENY + + + + +------EDFB3CE1089204FED046E2D32968C669 +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIHiwYJKoZIhvcNAQcCoIIHfDCCB3gCAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggRnMIIEYzCCA0ugAwIBAgIJAM3yAtULcaEIMA0GCSqGSIb3DQEB +CwUAMIHHMQswCQYDVQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2Fs +aXR5IE5hbWUxITAfBgNVBAsMGE9yZ2FuaXphdGlvbmFsIFVuaXQgTmFtZTEgMB4G +A1UECgwXRXhhbXBsZSBDQSBPcmdhbml6YXRpb24xHzAdBgNVBAMMFkV4YW1wbGUg +UGVybWlzc2lvbnMgQ0ExLTArBgkqhkiG9w0BCQEWHmF1dGhvcml0eUBwZXJtaXNz +aW9uc2NhbHRkLm9yZzAeFw0xOTAyMTIxMzUyMzJaFw0yOTAyMDkxMzUyMzJaMIHH +MQswCQYDVQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2FsaXR5IE5h +bWUxITAfBgNVBAsMGE9yZ2FuaXphdGlvbmFsIFVuaXQgTmFtZTEgMB4GA1UECgwX +RXhhbXBsZSBDQSBPcmdhbml6YXRpb24xHzAdBgNVBAMMFkV4YW1wbGUgUGVybWlz +c2lvbnMgQ0ExLTArBgkqhkiG9w0BCQEWHmF1dGhvcml0eUBwZXJtaXNzaW9uc2Nh +bHRkLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKD6nYCszMha +h3xGfJy8f3lowPHIj6zcldVYs5Krg7zXxZn+20lAMHUfgQcWZAauKbCnokYfTvXV +v0j9HCpQ3mRynNTyjLjc7HxAe6kfaJ75PoIoOMMQMEGvPOqRUq0tomVVJvcgzZZk +pwE30E6xvZrlQcrkQY/aOQ0sbje+RN8RKQ9vf6O45Np/0m2K5ohZPlBqg4F539v2 +iXGZczCr9AqAszc/7rOPX1aqZmmRDou0T+Zhx3ZZSAwZYQtr7uvvlUeGmDhNh+8p +LC+1FQPtkKmcVXO8oZWm5N8piOvH3M+v3qhyPtLv30cpl0bDiFl+PN7nZ6InOOtd +ZJVMa2rYCk8CAwEAAaNQME4wHQYDVR0OBBYEFA/CtiP8Z5Fk4aWDIb2j3FPwh9pg +MB8GA1UdIwQYMBaAFA/CtiP8Z5Fk4aWDIb2j3FPwh9pgMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQELBQADggEBACBupRddIR9zYBFLGFTzeiW+H1tRRKz+B3SWnCJH +89ijEdMYlKKLYT0R18lCV0vHnl29bU1CPlkLn+GQkvdfIjKguWEQKTP+GLzoa9TV +zOKAJ8NttCyW3YqriUOUGKqra1Fdt8nvrAyZUF+v/k8pTInmCvwu3l5HrVhkKHER +IbCIohKi/2mk1JZS9reWvZhqLoUIw5IDFlqtBDYOfMaqm8XF01YjEDBM6OuyQzYN +gDFVUZx0At4zzRjGTvqpLTkDYL1A3v4QYXZcwZiKeEVbFuNkauXgD+8pEZMB8yL4 +h1feIH+aucsAKBz1Ne5fTiTCannlKvLl8xWz5IdzP7gF0LIxggLoMIIC5AIBATCB +1TCBxzELMAkGA1UEBhMCTkwxCzAJBgNVBAgMAk9WMRYwFAYDVQQHDA1Mb2NhbGl0 +eSBOYW1lMSEwHwYDVQQLDBhPcmdhbml6YXRpb25hbCBVbml0IE5hbWUxIDAeBgNV +BAoMF0V4YW1wbGUgQ0EgT3JnYW5pemF0aW9uMR8wHQYDVQQDDBZFeGFtcGxlIFBl +cm1pc3Npb25zIENBMS0wKwYJKoZIhvcNAQkBFh5hdXRob3JpdHlAcGVybWlzc2lv +bnNjYWx0ZC5vcmcCCQDN8gLVC3GhCDANBglghkgBZQMEAgEFAKCB5DAYBgkqhkiG +9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xOTEyMDcxNjAxMjZa +MC8GCSqGSIb3DQEJBDEiBCCEqUh7CpMRXpSMDeuCmSMz+I6WXjXpO2HRkCdRSczj +1TB5BgkqhkiG9w0BCQ8xbDBqMAsGCWCGSAFlAwQBKjALBglghkgBZQMEARYwCwYJ +YIZIAWUDBAECMAoGCCqGSIb3DQMHMA4GCCqGSIb3DQMCAgIAgDANBggqhkiG9w0D +AgIBQDAHBgUrDgMCBzANBggqhkiG9w0DAgIBKDANBgkqhkiG9w0BAQEFAASCAQAL +ExoTydhBE/8GgnqGp39cRVQ0Z1YIc55uACZK1V37R2b8rY4upLA7iHyzCBXQOwCz +mhjHfaNdW8twWru34EvD17RTfk49Lvmge4ceipgmqKwGVyTO57P5xzDaC+2F2KEi ++s6/YWIslixMhlQyuxZsmQDbRWcmQ1FRy7LJ80cctlDA44IviaEfv/u2+sqJgPNL +Z5AHMEv/qceKjtm/Wh7sdFhjfM4ZnfUWFB6Ni/sdNSmO9O3j9OHfpkzMJHxM4B5r +G5pMNDn2xibxwlx41he7mfENIjuk4Z3VDaTCTs++8GyivvvsCZSVimd0iuI1kVmd +JL58DFeKqgEZ358rN9/5 + +------EDFB3CE1089204FED046E2D32968C669-- + diff --git a/src/security/builtin_plugins/tests/listeners_authentication/etc/Identity_CA_Cert.pem b/src/security/builtin_plugins/tests/listeners_authentication/etc/Identity_CA_Cert.pem new file mode 100644 index 0000000..cce5c91 --- /dev/null +++ b/src/security/builtin_plugins/tests/listeners_authentication/etc/Identity_CA_Cert.pem @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEOTCCAyGgAwIBAgIJAPq0b61+PT2WMA0GCSqGSIb3DQEBCwUAMIGyMQswCQYD +VQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2FsaXR5IE5hbWUxITAf +BgNVBAsMGE9yZ2FuaXphdGlvbmFsIFVuaXQgTmFtZTEaMBgGA1UECgwRRXhhbXBs +ZSBTaWduZXIgQ0ExEzARBgNVBAMMCkV4YW1wbGUgQ0ExKjAoBgkqhkiG9w0BCQEW +G2F1dGhvcml0eUBpZGVudGl0eWNhbHRkLm9yZzAeFw0xOTAyMTIxMDIxNTJaFw0y +OTAyMDkxMDIxNTJaMIGyMQswCQYDVQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNV +BAcMDUxvY2FsaXR5IE5hbWUxITAfBgNVBAsMGE9yZ2FuaXphdGlvbmFsIFVuaXQg +TmFtZTEaMBgGA1UECgwRRXhhbXBsZSBTaWduZXIgQ0ExEzARBgNVBAMMCkV4YW1w +bGUgQ0ExKjAoBgkqhkiG9w0BCQEWG2F1dGhvcml0eUBpZGVudGl0eWNhbHRkLm9y +ZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKCBJ1r/2AcSHorpA2G2 +WR0CvGHPhhY2x93twW91LCJVOVzO0LuOscZXSkWDtAhyhy1EZN6r+4aLbMku/wVJ +kdjHPD+WSVEZn70LxYSgxiUwXalpa5RQeTkEHll5cSgtE8kSD4/HIxBsbwizeDVV +g8SWpBVb044GM4O3TDbCug9F7GJFzqcbSHQZnHO+3nWu6f21BEU7PZjrFox1NREN +g3H7WmNISx4DOK9bJcWS/i4qJjTxjQPPFmzGvRgO2FfWP+xYb70x/iOeKsML2y+d +XZqL99yzfP1dnpDtBzCTqJJizfuNMD6gvIXyk2PUy3FpAYoI9BvUehdWCP/okikx +5jsCAwEAAaNQME4wHQYDVR0OBBYEFL7LTHLvMsEeUDjMYeW4+DcXn62PMB8GA1Ud +IwQYMBaAFL7LTHLvMsEeUDjMYeW4+DcXn62PMAwGA1UdEwQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggEBAIDJ4g6aVGIVXDSQ5R2yY9I82zsRf3k+yRF/BBkqBP1XXYRA +6lk7Wk4y6+DmL9qbVG/xrkTCC066J8kVblOyfFP1LHAzlNOQE7aU+tyrAufW4fpz +f/Gv8PBQUTQGr8vNqLUuEdoQjzARm8g7L3qeXhIKjiWsWi99ibnm/jTjol1GleIX +RudKSSGyMcB2VgRjCEEIYrkXdkIfrznKcJxzUw3dsGx277dB+4iFLcqf1YDpoRe2 +aSwbtgx+lLZ4KXWtikBSmLSRBq9j2aGtKO08kru0U3jQo6B4Bvzp1KuJCBiktueY +yNRfgh8ggNERYF/SpVr/ivm3RM+mnWd3QpmVolw= +-----END CERTIFICATE----- diff --git a/src/security/builtin_plugins/tests/listeners_authentication/etc/Identity_CA_Private_Key.pem b/src/security/builtin_plugins/tests/listeners_authentication/etc/Identity_CA_Private_Key.pem new file mode 100644 index 0000000..16bfbf7 --- /dev/null +++ b/src/security/builtin_plugins/tests/listeners_authentication/etc/Identity_CA_Private_Key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAoIEnWv/YBxIeiukDYbZZHQK8Yc+GFjbH3e3Bb3UsIlU5XM7Q +u46xxldKRYO0CHKHLURk3qv7hotsyS7/BUmR2Mc8P5ZJURmfvQvFhKDGJTBdqWlr +lFB5OQQeWXlxKC0TyRIPj8cjEGxvCLN4NVWDxJakFVvTjgYzg7dMNsK6D0XsYkXO +pxtIdBmcc77eda7p/bUERTs9mOsWjHU1EQ2DcftaY0hLHgM4r1slxZL+LiomNPGN +A88WbMa9GA7YV9Y/7FhvvTH+I54qwwvbL51dmov33LN8/V2ekO0HMJOokmLN+40w +PqC8hfKTY9TLcWkBigj0G9R6F1YI/+iSKTHmOwIDAQABAoIBAAc5iRH5jjnTQPiz +wGk3kg9SPjSQ6NI7KQf+WcSwm4n4GBrrXE31AF+TMk6qvQHcVeVdvMShLTNDN2Re +7y/Hvf7qCPY7x5UU+DHEQ+HSctjdsnmbuzHz5WEBpHQWmVdboBZe78BjEFr+5oiX +u4N7E/FXbo9fkMhF0y/MomucnE9vnhFsCj/Qz+gqKJDz7n+jY1G9loGJpoZoGllK +s2+HzbY5qVKrrpDzD5FO5i+M/Obk4uwZVDSnFL316SKe9MzdlrH9ochdtsGlver8 +YsYtetqHy4QgE/WZLSgwQoYY7nlKnkAKUnGvTJ8pnmO2FkO9SAQsBIl32rURMQFY +2C7ka5ECgYEAz13hOWwsefCkMTpXOXpeagCACN86Oqel+gV+UYDWnRdwDrUKBhjA +u40+NVaxuJSNKV3mC0N2PxwTuYzQ6BOQgmNzlxv0xyKwkGW/d6F8VunV2mqb3EAL +m9qzN1k08V30RikSMCt1OV5isuUiC4ox3ToboLTibXKnbEFWjT3juM8CgYEAxiW0 ++CvqJQjrjJ/valshCQDF4fYLa2uTJcdDifyU3HVTn06yy0z42tLBhHCv8RY/SBRK +IqR3RDhYJbBgLhG7oBDvoGWUEhdGJ+z6qcw9v1tDj9QD1bQF7RJvuh2JA7mhbFe5 +cIptcDJNRN7PCrjqGksQfy8Gg6ABOGFhz3xZPtUCgYBeFpKio1pq2a0mSPpashM0 +tZVicSbShk7g6q0t/e9ix8eoZKxvp7uLXcLkILnyrjR+mIRQiAOXDv5EKoh/RKFF +CCriXWTrFepXGlONzE/Gf8Lwn36oqMabqNe4PVmwSpkTXH9MK+u8Y/8UfLK92a5W +Wo8+k9RJJMSiceL7oyE4MQKBgQCkVg2bbkCJaraBMPxNxzrEzsFPwNKDyvqFcJhR +TwzfMuehzpF3D2WthvI8t4EUgJEHZNx/ksvf5qMkzv1V+BsWjDVRYC3IO0lSP7c9 +MEld9YE5PmvXx7DKiGnlgC1sy35X7wG7lvNhBDcVkX1BtU9jczJBaW0LqZ6Zdhq7 +DLSv6QKBgQDNZpHEwi2P2LdlTRgbc4IWYjZZJaj+RrG881lgi+v8SI4E8eizlxLw +9HlG1nydvRqtU3T5h8UuqLOlXbfvQ7GOxVO2uJjtjJHZ8KbsFUH5i3UwZ+llyrRW +Y1ydvvE9Hux6I7I3L42J11jphNYKw/YwARkp8/Bc/wzKsGlnh3Oh+w== +-----END RSA PRIVATE KEY----- diff --git a/src/security/builtin_plugins/tests/listeners_authentication/etc/Permissions_CA_Cert.pem b/src/security/builtin_plugins/tests/listeners_authentication/etc/Permissions_CA_Cert.pem new file mode 100644 index 0000000..7420bc4 --- /dev/null +++ b/src/security/builtin_plugins/tests/listeners_authentication/etc/Permissions_CA_Cert.pem @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEYzCCA0ugAwIBAgIJAM3yAtULcaEIMA0GCSqGSIb3DQEBCwUAMIHHMQswCQYD +VQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2FsaXR5IE5hbWUxITAf +BgNVBAsMGE9yZ2FuaXphdGlvbmFsIFVuaXQgTmFtZTEgMB4GA1UECgwXRXhhbXBs +ZSBDQSBPcmdhbml6YXRpb24xHzAdBgNVBAMMFkV4YW1wbGUgUGVybWlzc2lvbnMg +Q0ExLTArBgkqhkiG9w0BCQEWHmF1dGhvcml0eUBwZXJtaXNzaW9uc2NhbHRkLm9y +ZzAeFw0xOTAyMTIxMzUyMzJaFw0yOTAyMDkxMzUyMzJaMIHHMQswCQYDVQQGEwJO +TDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2FsaXR5IE5hbWUxITAfBgNVBAsM +GE9yZ2FuaXphdGlvbmFsIFVuaXQgTmFtZTEgMB4GA1UECgwXRXhhbXBsZSBDQSBP +cmdhbml6YXRpb24xHzAdBgNVBAMMFkV4YW1wbGUgUGVybWlzc2lvbnMgQ0ExLTAr +BgkqhkiG9w0BCQEWHmF1dGhvcml0eUBwZXJtaXNzaW9uc2NhbHRkLm9yZzCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKD6nYCszMhah3xGfJy8f3lowPHI +j6zcldVYs5Krg7zXxZn+20lAMHUfgQcWZAauKbCnokYfTvXVv0j9HCpQ3mRynNTy +jLjc7HxAe6kfaJ75PoIoOMMQMEGvPOqRUq0tomVVJvcgzZZkpwE30E6xvZrlQcrk +QY/aOQ0sbje+RN8RKQ9vf6O45Np/0m2K5ohZPlBqg4F539v2iXGZczCr9AqAszc/ +7rOPX1aqZmmRDou0T+Zhx3ZZSAwZYQtr7uvvlUeGmDhNh+8pLC+1FQPtkKmcVXO8 +oZWm5N8piOvH3M+v3qhyPtLv30cpl0bDiFl+PN7nZ6InOOtdZJVMa2rYCk8CAwEA +AaNQME4wHQYDVR0OBBYEFA/CtiP8Z5Fk4aWDIb2j3FPwh9pgMB8GA1UdIwQYMBaA +FA/CtiP8Z5Fk4aWDIb2j3FPwh9pgMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBACBupRddIR9zYBFLGFTzeiW+H1tRRKz+B3SWnCJH89ijEdMYlKKLYT0R +18lCV0vHnl29bU1CPlkLn+GQkvdfIjKguWEQKTP+GLzoa9TVzOKAJ8NttCyW3Yqr +iUOUGKqra1Fdt8nvrAyZUF+v/k8pTInmCvwu3l5HrVhkKHERIbCIohKi/2mk1JZS +9reWvZhqLoUIw5IDFlqtBDYOfMaqm8XF01YjEDBM6OuyQzYNgDFVUZx0At4zzRjG +TvqpLTkDYL1A3v4QYXZcwZiKeEVbFuNkauXgD+8pEZMB8yL4h1feIH+aucsAKBz1 +Ne5fTiTCannlKvLl8xWz5IdzP7gF0LI= +-----END CERTIFICATE----- diff --git a/src/security/builtin_plugins/tests/listeners_authentication/src/listeners_authentication_utests.c b/src/security/builtin_plugins/tests/listeners_authentication/src/listeners_authentication_utests.c new file mode 100644 index 0000000..a039d25 --- /dev/null +++ b/src/security/builtin_plugins/tests/listeners_authentication/src/listeners_authentication_utests.c @@ -0,0 +1,2105 @@ +/** @file qos_utests.c + * @brief Unit tests for qos APIs + * + */ +/* CUnit includes. */ +#include "CUnit/CUnit.h" +#include "CUnit/Test.h" + +#include + +/* Test helper includes. */ +#include "common/src/loader.h" + +#include "config_env.h" + +#include "dds/ddsrt/time.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/dds_security_api_authentication.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/misc.h" +#include "dds/ddsrt/endian.h" +#include "dds/ddsrt/io.h" +#include "dds/security/core/dds_security_serialize.h" +#include "dds/security/core/dds_security_utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if OPENSSL_VERSION_NUMBER >= 0x1000200fL +#define AUTH_INCLUDE_EC +#include +#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#define AUTH_INCLUDE_DH_ACCESSORS +#endif +#else +#error "version not found" +#endif + + +static const char * ACCESS_PERMISSIONS_TOKEN_ID = "DDS:Access:Permissions:1.0"; +static const char * AUTH_PROTOCOL_CLASS_ID = "DDS:Auth:PKI-DH:1.0"; + +static const char * PROPERTY_IDENTITY_CA = "dds.sec.auth.identity_ca"; +static const char * PROPERTY_PRIVATE_KEY = "dds.sec.auth.private_key"; +static const char * PROPERTY_IDENTITY_CERT = "dds.sec.auth.identity_certificate"; +static const char * PROPERTY_PERMISSIONS_CA = "dds.sec.access.permissions_ca"; +static const char * PROPERTY_PERMISSIONS = "dds.sec.access.permissions"; +static const char * PROPERTY_GOVERNANCE = "dds.sec.access.governance"; + +static const char * PROPERTY_PERMISSIONS_CA_SN = "dds.perm_ca.sn"; +static const char * PROPERTY_PERMISSIONS_CA_ALGO = "dds.perm_ca.algo"; +static const char * PROPERTY_C_ID = "c.id"; +static const char * PROPERTY_C_PERM = "c.perm"; + + +static const char * SUBJECT_NAME_PERMISSIONS_CA = "/C=NL/ST=OV/L=Locality Name/OU=Organizational Unit Name/O=Example Signer CA/CN=Example CA/emailAddress=authority@identitycaltd.org"; +static const char * RSA_2048_ALGORITHM_NAME = "RSA-2048"; + +static const char * PERMISSIONS_CA_CERT_FILE = "Permissions_CA_Cert.pem"; +static const char * ALICE_PERMISSIONS_FILE = "Example_Permissions_Alice.p7s"; +static const char * BOB_PERMISSIONS_FILE = "Example_Permissions_Bob.p7s"; +static const char * ALICE_IDENTITY_CERT_FILE = "Example_Alice_Cert.pem"; +static const char * BOB_IDENTITY_CERT_FILE = "Example_Bob_Cert.pem"; +static const char * AUTH_DSIGN_ALGO_RSA_NAME = "RSASSA-PSS-SHA256"; +static const char * AUTH_KAGREE_ALGO_ECDH_NAME = "ECDH+prime256v1-CEUM"; +static DDS_Security_PermissionsHandle remote_permissions_handle = DDS_SECURITY_HANDLE_NIL; +static dds_security_authentication_listener auth_listener; +static dds_security_access_control_listener access_control_listener; + +#define IDENTITY_CA_FILE "Identity_CA_Cert.pem" +#define IDENTITY_CA_KEY_FILE "Identity_CA_Private_Key.pem" + +static const char *identity_ca =/*Identity_CA_Cert.pem*/ + "data:,-----BEGIN CERTIFICATE-----\n" + "MIIEOTCCAyGgAwIBAgIJAPq0b61+PT2WMA0GCSqGSIb3DQEBCwUAMIGyMQswCQYD\n" + "VQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2FsaXR5IE5hbWUxITAf\n" + "BgNVBAsMGE9yZ2FuaXphdGlvbmFsIFVuaXQgTmFtZTEaMBgGA1UECgwRRXhhbXBs\n" + "ZSBTaWduZXIgQ0ExEzARBgNVBAMMCkV4YW1wbGUgQ0ExKjAoBgkqhkiG9w0BCQEW\n" + "G2F1dGhvcml0eUBpZGVudGl0eWNhbHRkLm9yZzAeFw0xOTAyMTIxMDIxNTJaFw0y\n" + "OTAyMDkxMDIxNTJaMIGyMQswCQYDVQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNV\n" + "BAcMDUxvY2FsaXR5IE5hbWUxITAfBgNVBAsMGE9yZ2FuaXphdGlvbmFsIFVuaXQg\n" + "TmFtZTEaMBgGA1UECgwRRXhhbXBsZSBTaWduZXIgQ0ExEzARBgNVBAMMCkV4YW1w\n" + "bGUgQ0ExKjAoBgkqhkiG9w0BCQEWG2F1dGhvcml0eUBpZGVudGl0eWNhbHRkLm9y\n" + "ZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKCBJ1r/2AcSHorpA2G2\n" + "WR0CvGHPhhY2x93twW91LCJVOVzO0LuOscZXSkWDtAhyhy1EZN6r+4aLbMku/wVJ\n" + "kdjHPD+WSVEZn70LxYSgxiUwXalpa5RQeTkEHll5cSgtE8kSD4/HIxBsbwizeDVV\n" + "g8SWpBVb044GM4O3TDbCug9F7GJFzqcbSHQZnHO+3nWu6f21BEU7PZjrFox1NREN\n" + "g3H7WmNISx4DOK9bJcWS/i4qJjTxjQPPFmzGvRgO2FfWP+xYb70x/iOeKsML2y+d\n" + "XZqL99yzfP1dnpDtBzCTqJJizfuNMD6gvIXyk2PUy3FpAYoI9BvUehdWCP/okikx\n" + "5jsCAwEAAaNQME4wHQYDVR0OBBYEFL7LTHLvMsEeUDjMYeW4+DcXn62PMB8GA1Ud\n" + "IwQYMBaAFL7LTHLvMsEeUDjMYeW4+DcXn62PMAwGA1UdEwQFMAMBAf8wDQYJKoZI\n" + "hvcNAQELBQADggEBAIDJ4g6aVGIVXDSQ5R2yY9I82zsRf3k+yRF/BBkqBP1XXYRA\n" + "6lk7Wk4y6+DmL9qbVG/xrkTCC066J8kVblOyfFP1LHAzlNOQE7aU+tyrAufW4fpz\n" + "f/Gv8PBQUTQGr8vNqLUuEdoQjzARm8g7L3qeXhIKjiWsWi99ibnm/jTjol1GleIX\n" + "RudKSSGyMcB2VgRjCEEIYrkXdkIfrznKcJxzUw3dsGx277dB+4iFLcqf1YDpoRe2\n" + "aSwbtgx+lLZ4KXWtikBSmLSRBq9j2aGtKO08kru0U3jQo6B4Bvzp1KuJCBiktueY\n" + "yNRfgh8ggNERYF/SpVr/ivm3RM+mnWd3QpmVolw=\n" + "-----END CERTIFICATE-----\n"; + +static const char *alice_private_key = + "data:,-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEpAIBAAKCAQEA0Vn9YYllmrC/VVkxWFq6TzsmWn/niMydsE0hhm4Eam00gw3v\n" + "M4xScvBexI0td6tbStnWKz8vBiSVtWY1GDX8ICCBDufJcNIypu9L3DsjBoVTpcjx\n" + "XmfSpcxsepNaS7IqFPoRd+J+tzrl5qUR0Q52ObI02csp6CwecL8CvfXfc02U+tpP\n" + "b7iSsT/AcCeAAc10vdSXtnfcOGVLwy+D527kNr5r2VhE2FYdWbrGSOj8hw5eUfRs\n" + "KpnWlermWy1wzYfmMqkIII1hhY1sRDmMDrLpFeiYkf9B/7HQF+R2tFFFok1dYVpg\n" + "ZiZUNkONQnDQueThypzu3XB/PwHExILZnBwEtwIDAQABAoIBAHEVxCoQtuKlgOUQ\n" + "hfgtIiC0WdZe6unZZYCbWXWtLhNzI/964nAc51iRAQ/5Fstis7CuFONNgRA3aOsQ\n" + "57NJTgToqe4sRIL9+EB2WKsBAr19/Z46+i69tGq9DwfzWr4y4kpsfk0c+sftN8yr\n" + "9ADSaAhoe+X9uYhhdJwAgfGsw+Qa1BLM5jEexjcLwy1kqXwWKNHrPWU7NW40bPhV\n" + "Ne/UguklSp43sKoB1esTgRZe+OlQDCsQoXpyjtPYcKzF3Ion6e5rT8xQ1IkAtLTf\n" + "QJJTGMJGCguXxuDo2VRaa5pwbdRAamp63wD0IAPAf+ClCz4JLwOnOYsgSCZoY3l3\n" + "3GxWDAkCgYEA/scs7Ft50QOicnJ/DoCjxmpjba0hiqxbz0qAdCyl1llogUKuyCS7\n" + "sxQQvVTt6jk3gP0UYa3FJREToIGZuqaEu6qdY4GI61woNN5hXbkJC6G3FXI/VB8v\n" + "Actkas0kp6J8YWsmTqnsihE5Yii0WCBn+AnIpoU3S2N9WT7U8eA6B7sCgYEA0lsJ\n" + "xqB6NCkKbr+E+V0CGp+S+7zH5dxZtAhDPSKwy2kCYWtDlSVhAzXabTIzF2SW9tJQ\n" + "JV3FhRfiCWTBrBm/I7AmNbNtXnrexYyXPVBhN6uqzYCB8fcLy+HPNZYF3KtQtU3c\n" + "WxAyO6ZxSLgtcP3UB6J8Ac6CYB25cRWNsnrvETUCgYA1HpHfNbNQQNG9yuFyxJ9g\n" + "3w2b8Fzt7MG3lnDxx91Ls5h2WtDWKdJ4o9ZZozt3ejZ4TkvRkclo0QamkF7c65sB\n" + "BbGK7Zb+e1hmrXbfc5TPOAhUEF3jzByg4ycsnVjnGpmUNiLmg8ctginUrWfsd9U1\n" + "gdSz41KEBVo9ITyEsZtnwQKBgQCOgIfd3CcNIORlZC8D8wMS4BllmlzdFepa8OIE\n" + "D3UvR2MKdezho+HVl+zx3nkIFufCK3WJ6r19TVGeRXiCSyrWVWV9KaEkyR4TPAvU\n" + "yJgja5MZBj6BmXePVdjWl1w/Qns5Z5aoxg8Ro87IkaSPEBVMWsGhQ7HExT40IoLM\n" + "b0V3JQKBgQCnZRrzaY9xOy72rtyacWjQB2QxnmkZgwDUq0iQwU/EdP72fPV/TtG8\n" + "PxQqKVPM57XO7qDbyKBt9L3vvmkiC0bABlcMN7UX9H5cHGhnJn6+6muitJlxmtvU\n" + "IiwlYmN2hcA52Ft9cRVC8+8W6Knx019vBnJozjhzhy7wxwqggmxsxg==\n" + "-----END RSA PRIVATE KEY-----\n"; + +static const char *bob_private_key = + "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEogIBAAKCAQEA5Piv5VnOqg9vAWXGrdxH2Ax1svypJNVmNUlM95qGQloeJQPk\n" + "jSzAEHIBVYAE0eU5gHL3l9EI2mw/bVLsT/REXipj9STPN9NYOVNH2yeD8+KHWNXX\n" + "miTYJ5YjHP9GHDdKiZ52dn7BYktqUlghlxuY0pjWrqhnNkcJep7YZq4QTbCQcyUV\n" + "l+9v+lE6/DuSG5K1KNRCQmmnRVjdWmGQogrW8eZ1xNFwHJuZYgKP/q7ieQSYI+YR\n" + "Mrt1pScjj6FjdL5OMYShrBO7OBYrwDjMnpmox9omF+1S1Gmi1y03b3m1COKX4lID\n" + "Qpc7gvpwq02ZozEX+kfIs0Ua8EKbVgi23V/2OQIDAQABAoIBACXLry1Kr8R+m7I9\n" + "XJhiXjGZjOworLr5xs9Q9DWC+lqFiahOhjGPi3yrdPDqGuGS1vUPBTO4O5/icm3X\n" + "XE6uYYKxuKJEmzf52PxNdPUGBtABOpo9YkN9hXizXcRxlt8deV5SG/ffYIibLke9\n" + "aH4K/iT1OarG/ZKGE1h8U/hPDz3jcVGpqhwn7K4RtRJO7brYKw1jDJwH64g5gDZ7\n" + "Y2zcj5zh1JsnOYPx/1HWxDDIbBN9RbOTyKZIMP9OwglbS5RhIblTgM8zT8ZEHQ1s\n" + "h5dF1jt5pKtcqQelYbfACsTmVCvtJR9Uz98mYE/xpwvJTXbzeycmEccdfuWWFkFB\n" + "xzQroKECgYEA/VeD9T3/zJ9uls0DBuj+LBu+7mL/RrPuoJrqBIuXvIvddYgmvEkf\n" + "IhB7OLgLeMv5KvHRn8XWoEcPGoglfbY4jqIML855gFolyXSNJlbSiOPit8Ea9dKi\n" + "60fHhaa1U+E2xdDOeUilQVCEgnnqSBls1kGqB+81os5GVgo7MzW1+Y0CgYEA51+2\n" + "PYKLC5KU8r/bWlwjF2DmVJq6tD3O8SonqKsPv9MwGz0AimLO+iNtvEkh2rLVidtK\n" + "oP0tvIgsu70xqgX4wRBpZB+rk5IS8y3dCVf6TGVFYK9La5/L5BHLAzbf5jybRzH7\n" + "lT3O94oE7w7gkUiexSM37Wp8FoQG4EPl7MXXBl0CgYBDLE5H232U4v0urQNNdL/Y\n" + "MC8rBELNm239VbYRKHY+PxOkU0p6CCViId6aRmp8SBE0KtQ7OfjTnKPLlCfksklC\n" + "wILctjGPL9fvF6FJdiHyvAHkWSZt4cDjA7BKps5ThFbCkr/8dp+itte7xNmy7lLm\n" + "aJjN68Zb+be6npHd3TL4DQKBgBxHXHTEIc52SfIpdNvkav2OgFhS2QLykvpy1ooM\n" + "7k3ZuAV8PTaswPNdpSngHl0mgmbpAIQQrahfVGhVxV4sgKzIHrl4DXZp4hsKvftI\n" + "X3U643Hfuu4ah8cGTbPE3zS6r5fSChfBiCxFGDlHrjbTk2Qw28MOwr/Vvyll4xI/\n" + "U/qZAoGARuIs5CqcL3NTLyXQGCa3OIeUoqlpMHyy9niJb/S4z6ew6BvI2/uuI//j\n" + "zyZyRdexTF7rOIFDMqsCz7EpJDO9jjwTeKGZ1n25kFJS2AXHhFIU9mdYF9rZ9yuE\n" + "yLB7ISyuiPNMhsOOHMHWWTKiqmQdGBc/HTCKRA1Pu34Bcem55PA=\n" + "-----END RSA PRIVATE KEY-----\n"; + +static const char *alice_csr = + "-----BEGIN CERTIFICATE REQUEST-----\n" + "MIIC9zCCAd8CAQAwgbExCzAJBgNVBAYTAk5MMQswCQYDVQQIDAJPVjEWMBQGA1UE\n" + "BwwNTG9jYWxpdHkgTmFtZTEhMB8GA1UECwwYT3JnYW5pemF0aW9uYWwgVW5pdCBO\n" + "YW1lMR0wGwYDVQQKDBRFeGFtcGxlIE9yZ2FuaXphdGlvbjEWMBQGA1UEAwwNQWxp\n" + "Y2UgRXhhbXBsZTEjMCEGCSqGSIb3DQEJARYUYWxpY2VAZXhhbXBsZWx0ZC5jb20w\n" + "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDRWf1hiWWasL9VWTFYWrpP\n" + "OyZaf+eIzJ2wTSGGbgRqbTSDDe8zjFJy8F7EjS13q1tK2dYrPy8GJJW1ZjUYNfwg\n" + "IIEO58lw0jKm70vcOyMGhVOlyPFeZ9KlzGx6k1pLsioU+hF34n63OuXmpRHRDnY5\n" + "sjTZyynoLB5wvwK99d9zTZT62k9vuJKxP8BwJ4ABzXS91Je2d9w4ZUvDL4PnbuQ2\n" + "vmvZWETYVh1ZusZI6PyHDl5R9GwqmdaV6uZbLXDNh+YyqQggjWGFjWxEOYwOsukV\n" + "6JiR/0H/sdAX5Ha0UUWiTV1hWmBmJlQ2Q41CcNC55OHKnO7dcH8/AcTEgtmcHAS3\n" + "AgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAOqzDicnVFXBhsfRI/Gcmk0kyKAjg\n" + "UAfADqDT7EyqX31O4C+Flj+G++p4/Yo0W8yP01nSMOF5yB76Eep+hXuLldfL1aKs\n" + "krnZgIrCXyUSb5pVYHrbhI76eet6TMD8P9gj0okPLOfzyTHrQz9wCAv9FfiNl2y+\n" + "cK/meQPAByyxSiyW41owlHaMkSgIL/xULJHjR07QRCiKIAY3/mwUQ5I3k4qKibzQ\n" + "eV4Cus2SEqqXhNsFwZPWQZQmZOXLcEX7g9OsC4iVyGOunUwZdv8BRVThQk+5rGWk\n" + "dHjeWYmS7pWc8EjLnaSairQiw9tmZ0SQcNc7DjnPdkBU78MHxMW54sKBrw==\n" + "-----END CERTIFICATE REQUEST-----\n"; + + +static const char *bob_csr = + "-----BEGIN CERTIFICATE REQUEST-----\n" + "MIIC8zCCAdsCAQAwga0xCzAJBgNVBAYTAk5MMQswCQYDVQQIDAJPVjEWMBQGA1UE\n" + "BwwNTG9jYWxpdHkgTmFtZTEhMB8GA1UECwwYT3JnYW5pemF0aW9uYWwgVW5pdCBO\n" + "YW1lMR0wGwYDVQQKDBRFeGFtcGxlIE9yZ2FuaXphdGlvbjEUMBIGA1UEAwwLQm9i\n" + "IEV4YW1wbGUxITAfBgkqhkiG9w0BCQEWEmJvYkBleGFtcGxlbHRkLmNvbTCCASIw\n" + "DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOT4r+VZzqoPbwFlxq3cR9gMdbL8\n" + "qSTVZjVJTPeahkJaHiUD5I0swBByAVWABNHlOYBy95fRCNpsP21S7E/0RF4qY/Uk\n" + "zzfTWDlTR9sng/Pih1jV15ok2CeWIxz/Rhw3SomednZ+wWJLalJYIZcbmNKY1q6o\n" + "ZzZHCXqe2GauEE2wkHMlFZfvb/pROvw7khuStSjUQkJpp0VY3VphkKIK1vHmdcTR\n" + "cBybmWICj/6u4nkEmCPmETK7daUnI4+hY3S+TjGEoawTuzgWK8A4zJ6ZqMfaJhft\n" + "UtRpotctN295tQjil+JSA0KXO4L6cKtNmaMxF/pHyLNFGvBCm1YItt1f9jkCAwEA\n" + "AaAAMA0GCSqGSIb3DQEBCwUAA4IBAQBr85eN2h2q1dLfSeaJHmyVqmwdj2igMOcK\n" + "4RllC2LZ1aorfCvMSb5VzAUbVDFwKJOCfM5vk4hXmt9Uxxmr5qHpnBWi5XGoevuf\n" + "iQ+hdZqS9HIn1/vzNyX6OlCJwVd4qo42RLJFnxyKYnFtZrhA/kdB33Rf+UyRxfoB\n" + "/Su7pUUR+iIMZeu/C3LT3cZy5phqaWzOsw83m3Hap/UzTt5WAhynRfaYRdXuwACU\n" + "QscNSTJsYUfSlynzxY2GHgOw3N34x5pLlVGdOBoG4BjjdZVTeyPc/KgpkUYFY3mD\n" + "jDnSobyp5xr4wcR4RHJCUxCd3/bAAmqKwXY+GnRvOrdKG35Eii0Z\n" + "-----END CERTIFICATE REQUEST-----\n"; + + +static char *bob_identity_cert = NULL; + +typedef enum { + HANDSHAKE_REQUEST, + HANDSHAKE_REPLY, + HANDSHAKE_FINAL +} HandshakeStep_t; + + +struct octet_seq { + unsigned char *data; + uint32_t length; +}; + +static struct plugins_hdl *plugins = NULL; +static dds_security_authentication *auth = NULL; +static dds_security_access_control *access_control = NULL; +static DDS_Security_IdentityHandle local_identity_handle = DDS_SECURITY_HANDLE_NIL; +static DDS_Security_IdentityHandle remote_identity_handle = DDS_SECURITY_HANDLE_NIL; +static DDS_Security_IdentityHandle remote_identity_handle2 = DDS_SECURITY_HANDLE_NIL; +static DDS_Security_PermissionsHandle local_permissions_handle = DDS_SECURITY_HANDLE_NIL; +static char *path_to_etc_dir = NULL; +static char *g_path_build_dir = NULL; +static DDS_Security_IdentityHandle identity_handle_for_callback1=DDS_SECURITY_HANDLE_NIL; +static DDS_Security_IdentityHandle identity_handle_for_callback2=DDS_SECURITY_HANDLE_NIL; +static dds_time_t local_expiry_date; +static dds_time_t remote_expiry_date; + +#define HANDSHAKE_SIGNATURE_SIZE 6 + +#if DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN +static unsigned bswap4u (unsigned x) +{ + return (x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x << 24); +} +#define toBE4u(x) bswap4u (x) +#define fromBE4u(x) bswap4u (x) +#else +#define toBE4u(x) (x) +#define fromBE4u(x) (x) +#endif + +static const char * PROPERTY_CERT_SUBJECT_NAME = "dds.cert.sn"; +static const char * PROPERTY_CERT_ALGORITHM = "dds.cert.algo"; +static const char * PROPERTY_CA_SUBJECT_NAME = "dds.ca.sn"; +static const char * PROPERTY_CA_ALGORITHM = "dds.ca.aglo"; + +static const char * AUTH_REQUEST_TOKEN_CLASS_ID = "DDS:Auth:PKI-DH:1.0+AuthReq"; +static const char * AUTH_REQUEST_TOKEN_FUTURE_PROP_NAME = "future_challenge"; + +static const char * AUTH_HANDSHAKE_REQUEST_TOKEN_CLASS_ID = "DDS:Auth:PKI-DH:1.0+Req"; +static const char * AUTH_HANDSHAKE_REPLY_TOKEN_CLASS_ID = "DDS:Auth:PKI-DH:1.0+Reply"; +static const char * AUTH_HANDSHAKE_FINAL_TOKEN_CLASS_ID = "DDS:Auth:PKI-DH:1.0+Final"; +static DDS_Security_AuthRequestMessageToken g_local_auth_request_token = DDS_SECURITY_TOKEN_INIT; +static DDS_Security_AuthRequestMessageToken g_remote_auth_request_token = DDS_SECURITY_TOKEN_INIT; +static const DDS_Security_BinaryProperty_t *challenge1_predefined_glb = NULL; +static const DDS_Security_BinaryProperty_t *challenge2_predefined_glb = NULL; +static DDS_Security_OctetSeq serialized_participant_data = DDS_SECURITY_SEQUENCE_INIT; +static DDS_Security_ParticipantBuiltinTopicData *remote_participant_data1 = NULL; +static DDS_Security_ParticipantBuiltinTopicData *remote_participant_data2 = NULL; +static DDS_Security_ParticipantBuiltinTopicData *remote_participant_data3 = NULL; +static DDS_Security_GUID_t candidate_participant_guid; +static DDS_Security_GUID_t remote_participant_guid1; +static DDS_Security_GUID_t remote_participant_guid2; + +static EVP_PKEY *dh_modp_key = NULL; +static EVP_PKEY *dh_ecdh_key = NULL; +static struct octet_seq dh_modp_pub_key = {NULL, 0}; +static struct octet_seq dh_ecdh_pub_key = {NULL, 0}; +static struct octet_seq invalid_dh_pub_key = {NULL, 0}; + + +static void +dds_security_property_init( + DDS_Security_PropertySeq *seq, + DDS_Security_unsigned_long size) +{ + seq->_length = size; + seq->_maximum = size; + seq->_buffer = ddsrt_malloc(size * sizeof(DDS_Security_Property_t)); + memset(seq->_buffer, 0, size * sizeof(DDS_Security_Property_t)); +} + +static void +dds_security_property_deinit( + DDS_Security_PropertySeq *seq) +{ + uint32_t i; + + for (i = 0; i < seq->_length; i++) { + ddsrt_free(seq->_buffer[i].name); + ddsrt_free(seq->_buffer[i].value); + } + ddsrt_free(seq->_buffer); +} + +static void +reset_exception( + DDS_Security_SecurityException *ex) +{ + ex->code = 0; + ex->minor_code = 0; + ddsrt_free(ex->message); + ex->message = NULL; +} + + +static dds_time_t +get_certificate_expiry( + /*_In_*/ X509 *cert) +{ + dds_time_t expiry = DDS_TIME_INVALID; + ASN1_TIME *ans1; + + assert(cert); + + ans1 = X509_get_notAfter(cert); + if (ans1 != NULL) { + int days; + int seconds; + if (ASN1_TIME_diff(&days, &seconds, NULL, ans1) != 0) { + static const dds_duration_t secs_per_day = 86400; + dds_duration_t delta = DDS_SECS(((dds_duration_t)seconds + ((dds_duration_t)days * secs_per_day))); + expiry = dds_time() + delta; + { + BIO *b; + b = BIO_new_fp(stdout, BIO_NOCLOSE); + BIO_printf(b, "[asn1time] "); + ASN1_TIME_print(b, ans1); + BIO_printf(b, "\n"); + BIO_free(b); + } + } + } + + return expiry; +} + + +/* Generate a CA-signed certificate from CSR (Certificate Signing Request) */ +static DDS_Security_boolean create_certificate_from_csr(const char* csr, long valid_secs, + const char* outfile, dds_time_t *expiry) +{ + + ASN1_INTEGER *aserial = NULL; + EVP_PKEY *ca_privkey, *req_pubkey; + EVP_MD const *digest = NULL; + X509 *newcert, *cacert; + X509_NAME *name; + X509V3_CTX ctx; + BIO *fp; + BIO *reqbio = NULL; + BIO *outbio = NULL; + X509_REQ *certreq = NULL; + char *identity_ca_cert_file; + char *identity_ca_key_file; + char* certificate_file; + + outbio = BIO_new(BIO_s_file()); + + /* ---------------------------------------------------------- * + * Load the request data in a BIO, then in a x509_REQ struct. * + * ---------------------------------------------------------- */ + reqbio = BIO_new_mem_buf(csr, -1); + + if (!(certreq = PEM_read_bio_X509_REQ(reqbio, NULL, NULL, NULL))) { + BIO_printf(outbio, "Error can't read X509 request data into memory\n"); + return false; + } + + /* -------------------------------------------------------- * + * Load the signing CA Certificate file * + * ---------------------------------------------------------*/ + + ddsrt_asprintf(&identity_ca_cert_file, "%s%s", path_to_etc_dir, IDENTITY_CA_FILE); + + if (!(fp = BIO_new_file(identity_ca_cert_file, "r"))) { + BIO_printf(outbio, "Error reading CA cert file\n"); + return false; + } + + if (!(cacert = PEM_read_bio_X509(fp, NULL, NULL, NULL))) { + BIO_printf(outbio, "Error loading CA cert into memory\n"); + return false; + } + + BIO_free(fp); + + /* -------------------------------------------------------- * + * Import CA private key file for signing * + * ---------------------------------------------------------*/ + + ddsrt_asprintf(&identity_ca_key_file, "%s%s", path_to_etc_dir, IDENTITY_CA_KEY_FILE); + + if (!(fp = BIO_new_file(identity_ca_key_file, "r"))) { + BIO_printf(outbio, "Error reading CA private key file\n"); + return false; + } + + if (!(ca_privkey = PEM_read_bio_PrivateKey(fp, NULL, NULL, NULL))) { + BIO_printf(outbio, "Error importing key content from file\n"); + return false; + } + + BIO_free(fp); + + /* --------------------------------------------------------- * + * Build Certificate with data from request * + * ----------------------------------------------------------*/ + if (!(newcert = X509_new())) { + BIO_printf(outbio, "Error creating new X509 object\n"); + return false; + } + + if (X509_set_version(newcert, 2) != 1) { + BIO_printf(outbio, "Error setting certificate version\n"); + return false; + } + + /* --------------------------------------------------------- * + * set the certificate serial number here * + * If there is a problem, the value defaults to '0' * + * ----------------------------------------------------------*/ + aserial = ASN1_INTEGER_new(); + ASN1_INTEGER_set(aserial, 0); + if (!X509_set_serialNumber(newcert, aserial)) { + BIO_printf(outbio, "Error setting serial number of the certificate\n"); + return false; + } + + /* --------------------------------------------------------- * + * Extract the subject name from the request * + * ----------------------------------------------------------*/ + if (!(name = X509_REQ_get_subject_name(certreq))) + BIO_printf(outbio, "Error getting subject from cert request\n"); + + /* --------------------------------------------------------- * + * Set the new certificate subject name * + * ----------------------------------------------------------*/ + if (X509_set_subject_name(newcert, name) != 1) { + BIO_printf(outbio, "Error setting subject name of certificate\n"); + return false; + } + + /* --------------------------------------------------------- * + * Extract the subject name from the signing CA cert * + * ----------------------------------------------------------*/ + if (!(name = X509_get_subject_name(cacert))) { + BIO_printf(outbio, "Error getting subject from CA certificate\n"); + return false; + } + + /* --------------------------------------------------------- * + * Set the new certificate issuer name * + * ----------------------------------------------------------*/ + if (X509_set_issuer_name(newcert, name) != 1) { + BIO_printf(outbio, "Error setting issuer name of certificate\n"); + return false; + } + + /* --------------------------------------------------------- * + * Extract the public key data from the request * + * ----------------------------------------------------------*/ + if (!(req_pubkey = X509_REQ_get_pubkey(certreq))) { + BIO_printf(outbio, "Error unpacking public key from request\n"); + return false; + } + + /* --------------------------------------------------------- * + * Optionally: Use the public key to verify the signature * + * ----------------------------------------------------------*/ + if (X509_REQ_verify(certreq, req_pubkey) != 1) { + BIO_printf(outbio, "Error verifying signature on request\n"); + return false; + } + + /* --------------------------------------------------------- * + * Set the new certificate public key * + * ----------------------------------------------------------*/ + if (X509_set_pubkey(newcert, req_pubkey) != 1) { + BIO_printf(outbio, "Error setting public key of certificate\n"); + return false; + } + + /* ---------------------------------------------------------- * + * Set X509V3 start date (now) and expiration date (+365 days)* + * -----------------------------------------------------------*/ + if (!(X509_gmtime_adj(X509_get_notBefore(newcert), -10))) { + BIO_printf(outbio, "Error setting start time\n"); + return false; + } + + if (!(X509_gmtime_adj(X509_get_notAfter(newcert), valid_secs))) { + BIO_printf(outbio, "Error setting expiration time\n"); + return false; + } + + /* ----------------------------------------------------------- * + * Add X509V3 extensions * + * ------------------------------------------------------------*/ + X509V3_set_ctx(&ctx, cacert, newcert, NULL, NULL, 0); + + /* ----------------------------------------------------------- * + * Set digest type, sign new certificate with CA's private key * + * ------------------------------------------------------------*/ + digest = EVP_sha256(); + + if (!X509_sign(newcert, ca_privkey, digest)) { + BIO_printf(outbio, "Error signing the new certificate\n"); + return false; + } + + /* ------------------------------------------------------------ * + * write the certificate to file * + * -------------------------------------------------------------*/ + ddsrt_asprintf(&certificate_file, "%s%s", g_path_build_dir, outfile); + + if (!(fp = BIO_new_file(certificate_file, "w"))) { + BIO_printf(outbio, "Error opening certificate file for write\n"); + return false; + } + if (!PEM_write_bio_X509( fp, newcert)) { + BIO_printf(outbio, "Error writing the signed certificate\n"); + return false; + } + BIO_free(fp); + + *expiry = get_certificate_expiry( newcert ); + + EVP_PKEY_free(req_pubkey); + EVP_PKEY_free(ca_privkey); + X509_REQ_free(certreq); + ASN1_INTEGER_free( aserial ); + X509_free(newcert); + X509_free(cacert); + BIO_free_all(reqbio); + BIO_free_all(outbio); + ddsrt_free(certificate_file); + ddsrt_free( identity_ca_cert_file ); + ddsrt_free( identity_ca_key_file ); + return true; +} + +/* fills the participant properties and return identity cert expiry */ +static void +fill_participant_qos( + DDS_Security_Qos *qos, + long validity_duration, + const char *governance_filename, + dds_time_t *identity_expiry) +{ + char *permission_uri; + char *governance_uri; + char *permissions_ca_cert_file; + char *permissions_ca_uri; + char *identity_file; + char *identity_uri; + char *permissions_file; + + create_certificate_from_csr( alice_csr, validity_duration , ALICE_IDENTITY_CERT_FILE, identity_expiry); + + /*permissions ca cert*/ + ddsrt_asprintf(&permissions_ca_cert_file, "%s%s", path_to_etc_dir, PERMISSIONS_CA_CERT_FILE); + + ddsrt_asprintf(&permissions_ca_uri, "file:%s", permissions_ca_cert_file); + + /*Alice Identity*/ + ddsrt_asprintf(&identity_file, "%s%s", g_path_build_dir, ALICE_IDENTITY_CERT_FILE); + + ddsrt_asprintf(&identity_uri, "file:%s", identity_file); + + /*Alice Permissions */ + ddsrt_asprintf(&permissions_file, "%s%s", path_to_etc_dir, ALICE_PERMISSIONS_FILE); + + ddsrt_asprintf(&permission_uri, "file:%s", permissions_file); + + ddsrt_asprintf(&governance_uri, "file:%s%s", path_to_etc_dir, governance_filename); + + memset(qos, 0, sizeof(*qos)); + dds_security_property_init(&qos->property.value, 6); + qos->property.value._buffer[0].name = ddsrt_strdup(PROPERTY_IDENTITY_CERT); + qos->property.value._buffer[0].value = ddsrt_strdup(identity_uri); + qos->property.value._buffer[1].name = ddsrt_strdup(PROPERTY_IDENTITY_CA); + qos->property.value._buffer[1].value = ddsrt_strdup(identity_ca); + qos->property.value._buffer[2].name = ddsrt_strdup(PROPERTY_PRIVATE_KEY); + qos->property.value._buffer[2].value = ddsrt_strdup(alice_private_key); + qos->property.value._buffer[3].name = ddsrt_strdup(PROPERTY_PERMISSIONS_CA); + qos->property.value._buffer[3].value = ddsrt_strdup(permissions_ca_uri); + qos->property.value._buffer[4].name = ddsrt_strdup(PROPERTY_PERMISSIONS); + qos->property.value._buffer[4].value = ddsrt_strdup(permission_uri); + qos->property.value._buffer[5].name = ddsrt_strdup(PROPERTY_GOVERNANCE); + qos->property.value._buffer[5].value = ddsrt_strdup(governance_uri); + + ddsrt_free(permission_uri); + ddsrt_free(governance_uri); + ddsrt_free( permissions_ca_cert_file ); + ddsrt_free( permissions_file ); + ddsrt_free ( identity_file ); + ddsrt_free( identity_uri ); + ddsrt_free( permissions_ca_uri ); + + +} + +static void +fill_permissions_token( + DDS_Security_PermissionsToken *token) +{ + memset(token, 0, sizeof(DDS_Security_PermissionsToken)); + + token->class_id = ddsrt_strdup(ACCESS_PERMISSIONS_TOKEN_ID); + token->properties._length = token->properties._maximum = 2; + token->properties._buffer = DDS_Security_PropertySeq_allocbuf(2); + + token->properties._buffer[0].name = ddsrt_strdup(PROPERTY_PERMISSIONS_CA_SN); + token->properties._buffer[0].value = ddsrt_strdup(SUBJECT_NAME_PERMISSIONS_CA); + + token->properties._buffer[1].name = ddsrt_strdup(PROPERTY_PERMISSIONS_CA_ALGO); + token->properties._buffer[1].value = ddsrt_strdup(RSA_2048_ALGORITHM_NAME); +} + + +static int +fill_peer_credential_token( + DDS_Security_AuthenticatedPeerCredentialToken *token) +{ + int result = 1; + char *permission_data; + char *permissions_ca_cert_file; + char *permissions_file; + + + /*permissions ca cert*/ + ddsrt_asprintf(&permissions_ca_cert_file, "%s%s", path_to_etc_dir, PERMISSIONS_CA_CERT_FILE); + + /*permissions ca key*/ + ddsrt_asprintf(&permissions_file, "%s%s", path_to_etc_dir, BOB_PERMISSIONS_FILE); + + + memset(token, 0, sizeof(DDS_Security_AuthenticatedPeerCredentialToken)); + + permission_data = load_file_contents(permissions_file); + + if (permission_data) { + token->class_id = ddsrt_strdup(AUTH_PROTOCOL_CLASS_ID); + token->properties._length = token->properties._maximum = 2; + token->properties._buffer = DDS_Security_PropertySeq_allocbuf(2); + + token->properties._buffer[0].name = ddsrt_strdup(PROPERTY_C_ID); + token->properties._buffer[0].value = ddsrt_strdup(&bob_identity_cert[0]); + + token->properties._buffer[1].name = ddsrt_strdup(PROPERTY_C_PERM); + token->properties._buffer[1].value = permission_data; + } else { + ddsrt_free(permission_data); + result = 0; + } + + ddsrt_free( permissions_ca_cert_file ); + ddsrt_free( permissions_file ); + return result; +} + + +static void +serializer_participant_data( + DDS_Security_ParticipantBuiltinTopicData *pdata, + unsigned char **buffer, + size_t *size) +{ + DDS_Security_Serializer serializer; + serializer = DDS_Security_Serializer_new(1024, 1024); + + DDS_Security_Serialize_ParticipantBuiltinTopicData(serializer, pdata); + DDS_Security_Serializer_buffer(serializer, buffer, size); + DDS_Security_Serializer_free(serializer); +} + +static void +initialize_identity_token( + DDS_Security_IdentityToken *token, + const char *certAlgo, + const char *caAlgo) +{ + memset(token, 0, sizeof(*token)); + + token->class_id = ddsrt_strdup(AUTH_PROTOCOL_CLASS_ID); + token->properties._maximum = 4; + token->properties._length = 4; + token->properties._buffer = DDS_Security_PropertySeq_allocbuf(4); + + token->properties._buffer[0].name = ddsrt_strdup(PROPERTY_CERT_SUBJECT_NAME); + token->properties._buffer[0].value = ddsrt_strdup("/C=NL/ST=OV/L=Locality Name/OU=Organizational Unit Name/O=Example Organization/CN=Bob Example/emailAddress=bob@exampleltd.com"); + token->properties._buffer[0].propagate = true; + + token->properties._buffer[1].name = ddsrt_strdup(PROPERTY_CERT_ALGORITHM); + token->properties._buffer[1].value = ddsrt_strdup(certAlgo); + token->properties._buffer[1].propagate = true; + + token->properties._buffer[2].name = ddsrt_strdup(PROPERTY_CA_SUBJECT_NAME); + token->properties._buffer[2].value = ddsrt_strdup("/C=NL/ST=OV/L=Locality Name/OU=Organizational Unit Name/O=Example Signer CA/CN=Example CA/emailAddress=authority@identitycaltd.org"); + token->properties._buffer[2].propagate = true; + + token->properties._buffer[3].name = ddsrt_strdup(PROPERTY_CA_ALGORITHM); + token->properties._buffer[3].value = ddsrt_strdup(caAlgo); + token->properties._buffer[3].propagate = true; +} + +static DDS_Security_long +validate_local_identity_and_permissions( uint32_t identity_expiry_duration, dds_time_t *identity_expiry ) +{ + DDS_Security_long res = DDS_SECURITY_ERR_OK_CODE; + DDS_Security_ValidationResult_t result; + DDS_Security_DomainId domain_id = 0; + DDS_Security_Qos participant_qos; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_GuidPrefix_t prefix = {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb}; + DDS_Security_EntityId_t entityId = {{0xb0,0xb1,0xb2},0x1}; + DDS_Security_GUID_t local_participant_guid; + DDS_Security_ParticipantBuiltinTopicData *local_participant_data; + unsigned char *sdata; + size_t sz; + + memset(&local_participant_guid, 0, sizeof(local_participant_guid)); + memcpy(&candidate_participant_guid.prefix, &prefix, sizeof(prefix)); + memcpy(&candidate_participant_guid.entityId, &entityId, sizeof(entityId)); + + fill_participant_qos(&participant_qos, identity_expiry_duration, "Example_Governance.p7s", identity_expiry ); + + /* Now call the function. */ + result = auth->validate_local_identity( + auth, + &local_identity_handle, + &local_participant_guid, + domain_id, + &participant_qos, + &candidate_participant_guid, + &exception); + + if (result != DDS_SECURITY_VALIDATION_OK) { + res = DDS_SECURITY_ERR_UNDEFINED_CODE; + printf("validate_local_identity_failed: (%d) %s\n", (int)exception.code, exception.message ? exception.message : "Error message missing"); + } + + reset_exception(&exception); + + if (res == 0) { + local_permissions_handle = access_control->validate_local_permissions( + access_control, + auth, + local_identity_handle, + 0, + &participant_qos, + &exception); + + if (local_permissions_handle == DDS_SECURITY_HANDLE_NIL) { + printf("validate_local_permissions_failed: (%d) %s\n", (int)exception.code, exception.message ? exception.message : "Error message missing"); + if (exception.code == DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_CODE) { + /* This can happen on very slow platforms or when doing a valgrind run. */ + res = DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_CODE; + } else { + res = DDS_SECURITY_ERR_UNDEFINED_CODE; + } + } + } + + dds_security_property_deinit(&participant_qos.property.value); + reset_exception(&exception); + + local_participant_data = DDS_Security_ParticipantBuiltinTopicData_alloc(); + memcpy(&local_participant_data->key[0], &local_participant_guid, 12); + /* convert from big-endian format to native format */ + local_participant_data->key[0] = fromBE4u(local_participant_data->key[0]); + local_participant_data->key[1] = fromBE4u(local_participant_data->key[1]); + local_participant_data->key[2] = fromBE4u(local_participant_data->key[2]); + + initialize_identity_token(&local_participant_data->identity_token, RSA_2048_ALGORITHM_NAME, RSA_2048_ALGORITHM_NAME); + fill_permissions_token(&local_participant_data->permissions_token ); + + local_participant_data->security_info.participant_security_attributes = 0x01; + local_participant_data->security_info.plugin_participant_security_attributes = 0x02; + + serializer_participant_data(local_participant_data, &sdata, &sz); + + serialized_participant_data._length = serialized_participant_data._maximum = (DDS_Security_unsigned_long) sz; + serialized_participant_data._buffer = sdata; + + DDS_Security_ParticipantBuiltinTopicData_free(local_participant_data); + + + + return res; +} + +static void +clear_local_identity_and_permissions(void) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_boolean success; + + if (local_permissions_handle != DDS_SECURITY_HANDLE_NIL) { + success = access_control->return_permissions_handle(access_control, local_permissions_handle, &exception); + if (!success) { + printf("return_permission_handle failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + reset_exception(&exception); + } + + if (local_identity_handle != DDS_SECURITY_HANDLE_NIL) { + success = auth->return_identity_handle(auth, local_identity_handle, &exception); + if (!success) { + printf("return_identity_handle failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + reset_exception(&exception); + } + + DDS_Security_OctetSeq_deinit(&serialized_participant_data); +} + +static int +set_path_to_etc_dir(void) +{ + int res = 0; + size_t len; + + len = 1024; + path_to_etc_dir = ddsrt_malloc(len); + snprintf(path_to_etc_dir, 1024, "%s/listeners_authentication/etc/", CONFIG_ENV_TESTS_DIR); + + return res; +} + +static void set_path_build_dir(void) +{ + ddsrt_asprintf(&g_path_build_dir, "%s/", CONFIG_ENV_BUILD_DIR); +} + +/* handshake helper functions */ + + +static DDS_Security_BinaryProperty_t * +find_binary_property( + DDS_Security_DataHolder *token, + const char *name) +{ + DDS_Security_BinaryProperty_t *result = NULL; + uint32_t i; + + for (i = 0; i < token->binary_properties._length && !result; i++) { + if (token->binary_properties._buffer[i].name && (strcmp(token->binary_properties._buffer[i].name, name) == 0)) { + result = &token->binary_properties._buffer[i]; + } + } + + return result; +} + + +static void +octet_seq_init( + struct octet_seq *seq, + unsigned char *data, + uint32_t size) +{ + seq->data = ddsrt_malloc(size); + memcpy(seq->data, data, size); + seq->length = size; +} + +static void +octet_seq_deinit( + struct octet_seq *seq) +{ + ddsrt_free(seq->data); +} +static char * +get_openssl_error_message_for_test( + void) +{ + BIO *bio = BIO_new(BIO_s_mem()); + char *msg; + char *buf = NULL; + size_t len; + + if (bio) { + ERR_print_errors(bio); + len = (uint32_t)BIO_get_mem_data (bio, &buf); + msg = ddsrt_malloc(len + 1); + memset(msg, 0, len+1); + memcpy(msg, buf, len); + BIO_free(bio); + } else { + msg = ddsrt_strdup("BIO_new failed"); + } + + return msg; +} + + +static const BIGNUM * +dh_get_public_key( + /*_In_ */DH *dhkey) +{ +#ifdef AUTH_INCLUDE_DH_ACCESSORS + const BIGNUM *pubkey, *privkey; + DH_get0_key(dhkey, &pubkey, &privkey); + return pubkey; +#else + return dhkey->pub_key; +#endif +} + + + +/* DH Helper Functions */ + +static int +create_dh_key_modp_2048( + EVP_PKEY **pkey) +{ + int r = 0; + EVP_PKEY *params = NULL; + EVP_PKEY_CTX *kctx = NULL; + DH *dh = NULL; + + *pkey = NULL; + + if ((params = EVP_PKEY_new()) == NULL) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to allocate EVP_PKEY: %s", msg); + ddsrt_free(msg); + r = -1; + } else if ((dh = DH_get_2048_256()) == NULL) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to allocate DH parameter: %s", msg); + ddsrt_free(msg); + r = -1; + } else if (EVP_PKEY_set1_DH(params, dh) <= 0) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to set DH parameter to MODP_2048_256: %s", msg); + ddsrt_free(msg); + r = -1; + } else if ((kctx = EVP_PKEY_CTX_new(params, NULL)) == NULL) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to allocate KEY context %s", msg); + ddsrt_free(msg); + r = -1; + } else if (EVP_PKEY_keygen_init(kctx) <= 0) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to initialize KEY context: %s", msg); + ddsrt_free(msg); + r = -1; + } else if (EVP_PKEY_keygen(kctx, pkey) <= 0) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to generate :MODP_2048_256 keys %s", msg); + ddsrt_free(msg); + r = -1; + } + + if (params) EVP_PKEY_free(params); + if (kctx) EVP_PKEY_CTX_free(kctx); + if (dh) DH_free(dh); + + return r; +} + +static int +get_dh_public_key_modp_2048( + EVP_PKEY *pkey, + struct octet_seq *pubkey) +{ + int r = 0; + DH *dhkey; + unsigned char *buffer = NULL; + uint32_t size; + ASN1_INTEGER *asn1int; + + dhkey = EVP_PKEY_get1_DH(pkey); + if (!dhkey) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to get DH key from PKEY: %s", msg); + ddsrt_free(msg); + r = -1; + goto fail_get_dhkey; + } + + asn1int = BN_to_ASN1_INTEGER( dh_get_public_key(dhkey) , NULL); + if (!asn1int) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to convert DH key to ASN1 integer: %s", msg); + ddsrt_free(msg); + r = -1; + goto fail_get_pubkey; + } + + size = (uint32_t)i2d_ASN1_INTEGER(asn1int, &buffer); + octet_seq_init(pubkey, buffer, size); + + ASN1_INTEGER_free(asn1int); + OPENSSL_free(buffer); + +fail_get_pubkey: + DH_free(dhkey); +fail_get_dhkey: + return r; +} + +static int +create_dh_key_ecdh( + EVP_PKEY **pkey) +{ + int r = 0; + EVP_PKEY *params = NULL; + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY_CTX *kctx = NULL; + + *pkey = NULL; + + if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to allocate DH parameter context: %s", msg); + ddsrt_free(msg); + r = -1; + } else if (EVP_PKEY_paramgen_init(pctx) <= 0) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to initialize DH generation context: %s", msg); + ddsrt_free(msg); + r = -1; + } else if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1) <= 0) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to set DH generation parameter generation method: %s", msg); + ddsrt_free(msg); + r = -1; + } else if (EVP_PKEY_paramgen(pctx, ¶ms) <= 0) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to generate DH parameters: %s", msg); + ddsrt_free(msg); + r = -1; + } else if ((kctx = EVP_PKEY_CTX_new(params, NULL)) == NULL) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to allocate KEY context %s", msg); + ddsrt_free(msg); + r = -1; + } else if (EVP_PKEY_keygen_init(kctx) <= 0) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to initialize KEY context: %s", msg); + ddsrt_free(msg); + r = -1; + } else if (EVP_PKEY_keygen(kctx, pkey) <= 0) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to generate :MODP_2048_256 keys %s", msg); + ddsrt_free(msg); + r = -1; + } + + if (kctx) EVP_PKEY_CTX_free(kctx); + if (params) EVP_PKEY_free(params); + if (pctx) EVP_PKEY_CTX_free(pctx); + + return r; +} + +static int +get_dh_public_key_ecdh( + EVP_PKEY *pkey, + struct octet_seq *pubkey) +{ + int r = 0; + EC_KEY *eckey = NULL; + const EC_GROUP *group = NULL; + const EC_POINT *point = NULL; + size_t sz; + + if (!(eckey = EVP_PKEY_get1_EC_KEY(pkey))) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to get EC key from PKEY: %s", msg); + ddsrt_free(msg); + r = -1; + } else if (!(point = EC_KEY_get0_public_key(eckey))) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to get public key from ECKEY: %s", msg); + ddsrt_free(msg); + r = -1; + } else if (!(group = EC_KEY_get0_group(eckey))) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to get group from ECKEY: %s", msg); + ddsrt_free(msg); + r = -1; + } else if ((sz = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, NULL, 0, NULL)) != 0) { + pubkey->data = ddsrt_malloc(sz); + pubkey->length = (uint32_t)EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, pubkey->data, sz, NULL); + if (pubkey->length == 0) { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to serialize public EC key: %s", msg); + ddsrt_free(msg); + octet_seq_deinit(pubkey); + r = -1; + } + } else { + char *msg = get_openssl_error_message_for_test(); + printf("Failed to serialize public EC key: %s", msg); + ddsrt_free(msg); + r = -1; + } + + if (eckey) EC_KEY_free(eckey); + + return r; +} + +CU_Init(ddssec_builtin_listeners_auth) +{ + int res = 0; + + plugins = load_plugins(&access_control /* Access Control */, + &auth /* Authentication */, + NULL /* Cryptograpy */); + if (plugins) { + set_path_build_dir(); + res = set_path_to_etc_dir(); + if (res >= 0) { + res = create_dh_key_modp_2048(&dh_modp_key); + } + if (res >= 0) { + res = get_dh_public_key_modp_2048(dh_modp_key, &dh_modp_pub_key); + } + if (res >= 0) { + res = create_dh_key_ecdh(&dh_ecdh_key); + } + if (res >= 0) { + res = get_dh_public_key_ecdh(dh_ecdh_key, &dh_ecdh_pub_key); + } + if (res >= 0) { + octet_seq_init(&invalid_dh_pub_key, dh_modp_pub_key.data, dh_modp_pub_key.length); + invalid_dh_pub_key.data[0] = 0x08; + } + } else { + res = -1; + } + + /* Openssl init */ + OpenSSL_add_all_algorithms(); + ERR_load_BIO_strings(); + ERR_load_crypto_strings(); + + return res; +} + +CU_Clean(ddssec_builtin_listeners_auth) +{ + octet_seq_deinit(&dh_modp_pub_key); + octet_seq_deinit(&dh_ecdh_pub_key); + octet_seq_deinit(&invalid_dh_pub_key); + if (dh_modp_key) { + EVP_PKEY_free(dh_modp_key); + } + if (dh_ecdh_key) { + EVP_PKEY_free(dh_ecdh_key); + } + unload_plugins(plugins); + + ddsrt_free(path_to_etc_dir); + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); + ERR_free_strings(); + return 0; +} + + + +static void +set_binary_property_value( + DDS_Security_BinaryProperty_t *bp, + const char *name, + const unsigned char *data, + uint32_t length) +{ + assert(bp); + assert(name); + assert(data); + + bp->name = ddsrt_strdup(name); + bp->value._maximum = bp->value._length = length; + if (length) { + bp->value._buffer = ddsrt_malloc(length); + memcpy(bp->value._buffer, data, length); + } else { + bp->value._buffer = NULL; + } +} + +static void +set_binary_property_string( + DDS_Security_BinaryProperty_t *bp, + const char *name, + const char *data) +{ + uint32_t length; + + assert(bp); + assert(name); + assert(data); + + length = (uint32_t)strlen(data) + 1; + set_binary_property_value(bp, name, (const unsigned char *)data, length); +} + + +static DDS_Security_ValidationResult_t +create_asymmetrical_signature_for_test( + EVP_PKEY *pkey, + void *data, + size_t dataLen, + unsigned char **signature, + size_t *signatureLen, + DDS_Security_SecurityException *ex) +{ + DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; + EVP_MD_CTX *mdctx = NULL; + EVP_PKEY_CTX *kctx = NULL; + + if (!(mdctx = EVP_MD_CTX_create())) { + char *msg = get_openssl_error_message_for_test(); + result = DDS_SECURITY_VALIDATION_FAILED; + DDS_Security_Exception_set(ex, "Authentication", DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to create signing context: %s", msg); + ddsrt_free(msg); + goto err_create_ctx; + } + + if (EVP_DigestSignInit(mdctx, &kctx, EVP_sha256(), NULL, pkey) != 1) { + char *msg = get_openssl_error_message_for_test(); + result = DDS_SECURITY_VALIDATION_FAILED; + DDS_Security_Exception_set(ex, "Authentication", DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to initialize signing context: %s", msg); + ddsrt_free(msg); + goto err_sign; + } + + if (EVP_PKEY_CTX_set_rsa_padding(kctx, RSA_PKCS1_PSS_PADDING) < 1) { + char *msg = get_openssl_error_message_for_test(); + result = DDS_SECURITY_VALIDATION_FAILED; + DDS_Security_Exception_set(ex, "Authentication", DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to initialize signing context: %s", msg); + ddsrt_free(msg); + goto err_sign; + } + + if (EVP_DigestSignUpdate(mdctx, data, dataLen) != 1) { + char *msg = get_openssl_error_message_for_test(); + result = DDS_SECURITY_VALIDATION_FAILED; + DDS_Security_Exception_set(ex, "Authentication", DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to update signing context: %s", msg); + ddsrt_free(msg); + goto err_sign; + } + + if (EVP_DigestSignFinal(mdctx, NULL, signatureLen) != 1) { + char *msg = get_openssl_error_message_for_test(); + result = DDS_SECURITY_VALIDATION_FAILED; + DDS_Security_Exception_set(ex, "Authentication", DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to finalize signing context: %s", msg); + ddsrt_free(msg); + goto err_sign; + } + + //*signature = ddsrt_malloc(sizeof(unsigned char) * (*signatureLen)); + *signature = OPENSSL_malloc(*signatureLen); + if (EVP_DigestSignFinal(mdctx, *signature, signatureLen) != 1) { + char *msg = get_openssl_error_message_for_test(); + result = DDS_SECURITY_VALIDATION_FAILED; + DDS_Security_Exception_set(ex, "Authentication", DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to finalize signing context: %s", msg); + ddsrt_free(msg); + ddsrt_free(signature); + } + +err_sign: + EVP_MD_CTX_destroy(mdctx); +err_create_ctx: + return result; +} + + +static X509 * +load_certificate( + const char *data) +{ + X509 *cert = NULL; + BIO *bio; + + bio = BIO_new_mem_buf((void *) data, -1); + if (!bio) { + return NULL; + } + + cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); + + BIO_free(bio); + + return cert; +} + +static int +get_adjusted_participant_guid( + X509 *cert, + const DDS_Security_GUID_t *candidate, + DDS_Security_GUID_t *adjusted) +{ + int result = 0; + unsigned char high[SHA256_DIGEST_LENGTH], low[SHA256_DIGEST_LENGTH]; + unsigned char *subject; + DDS_Security_octet hb = 0x80; + X509_NAME *name; + unsigned char *tmp = NULL; + int i; + int sz; + + name = X509_get_subject_name(cert); + sz = i2d_X509_NAME(name, &tmp); + if (sz > 0) { + subject = ddsrt_malloc((size_t)sz); + memcpy(subject, tmp, (size_t)sz); + OPENSSL_free(tmp); + + SHA256(subject, (size_t)sz, high); + SHA256(&candidate->prefix[0], sizeof(DDS_Security_GuidPrefix_t), low); + + adjusted->entityId = candidate->entityId; + for (i = 0; i < 6; i++) { + adjusted->prefix[i] = hb | high[i]>>1; + hb = (DDS_Security_octet)(high[i]<<7); + } + for (i = 0; i < 6; i++) { + adjusted->prefix[i+6] = low[i]; + } + ddsrt_free(subject); + result = 1; + } + + return result; +} + +static DDS_Security_ValidationResult_t +create_signature_for_test( + EVP_PKEY *pkey, + const DDS_Security_BinaryProperty_t **binary_properties, + const uint32_t binary_properties_length, + unsigned char **signature, + size_t *signatureLen, + DDS_Security_SecurityException *ex) +{ + DDS_Security_ValidationResult_t result; + DDS_Security_Serializer serializer; + unsigned char *buffer; + size_t size; + + serializer = DDS_Security_Serializer_new(4096, 4096); + + DDS_Security_Serialize_BinaryPropertyArray(serializer,binary_properties, binary_properties_length); + DDS_Security_Serializer_buffer(serializer, &buffer, &size); + + result = create_asymmetrical_signature_for_test(pkey, buffer, size, signature, signatureLen, ex); + + ddsrt_free(buffer); + DDS_Security_Serializer_free(serializer); + + return result; +} + + +static void +deinitialize_identity_token( + DDS_Security_IdentityToken *token) +{ + DDS_Security_DataHolder_deinit(token); +} + + + +static void +fill_auth_request_token( + DDS_Security_AuthRequestMessageToken *token) +{ + uint32_t i; + uint32_t len = 32; + unsigned char *challenge; + + challenge = ddsrt_malloc(len); + + for (i = 0; i < len; i++) { + challenge[i] = (unsigned char)(0xFF - i); + } + + memset(token, 0, sizeof(*token)); + + token->class_id = ddsrt_strdup(AUTH_REQUEST_TOKEN_CLASS_ID); + token->binary_properties._maximum = 1; + token->binary_properties._length = 1; + token->binary_properties._buffer = DDS_Security_BinaryPropertySeq_allocbuf(1); + token->binary_properties._buffer->name = ddsrt_strdup(AUTH_REQUEST_TOKEN_FUTURE_PROP_NAME); + + token->binary_properties._buffer->value._maximum = len; + token->binary_properties._buffer->value._length = len; + token->binary_properties._buffer->value._buffer = challenge; +} + +static int +validate_remote_identity (const char *remote_id_certificate) +{ + int res = 0; + DDS_Security_ValidationResult_t result; + DDS_Security_IdentityToken remote_identity_token; + static DDS_Security_AuthRequestMessageToken local_auth_request_token = DDS_SECURITY_TOKEN_INIT; + DDS_Security_GUID_t guid1; + DDS_Security_GUID_t guid2; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_GuidPrefix_t prefix1 = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab}; + DDS_Security_GuidPrefix_t prefix2 = {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb}; + DDS_Security_EntityId_t entityId = {{0xb0,0xb1,0xb2},0x1}; + X509 *cert; + + memcpy(&guid1.prefix, &prefix1, sizeof(prefix1)); + memcpy(&guid1.entityId, &entityId, sizeof(entityId)); + memcpy(&guid2.prefix, &prefix2, sizeof(prefix2)); + memcpy(&guid2.entityId, &entityId, sizeof(entityId)); + + if (local_identity_handle == DDS_SECURITY_HANDLE_NIL) { + return -1; + } + + cert = load_certificate(remote_id_certificate); + if (!cert) { + return -1; + } + + if (!get_adjusted_participant_guid(cert, &guid1, &remote_participant_guid1)) { + X509_free(cert); + return -1; + } + + if (!get_adjusted_participant_guid(cert, &guid2, &remote_participant_guid2)) { + X509_free(cert); + return -1; + } + + X509_free(cert); + + initialize_identity_token(&remote_identity_token, RSA_2048_ALGORITHM_NAME, RSA_2048_ALGORITHM_NAME); + + result = auth->validate_remote_identity( + auth, + &remote_identity_handle, + &g_local_auth_request_token, + NULL, + local_identity_handle, + &remote_identity_token, + &remote_participant_guid1, + &exception); + + if ((result != DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_REQUEST) && + (result != DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE)) { + printf("validate_remote_identity_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + + reset_exception(&exception); + fill_auth_request_token(&g_remote_auth_request_token); + + result = auth->validate_remote_identity( + auth, + &remote_identity_handle2, + &local_auth_request_token, + &g_remote_auth_request_token, + local_identity_handle, + &remote_identity_token, + &remote_participant_guid2, + &exception); + + if ((result != DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_REQUEST) && + (result != DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE)) { + printf("validate_remote_identity_failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + + reset_exception(&exception); + deinitialize_identity_token(&remote_identity_token); + DDS_Security_DataHolder_deinit(&local_auth_request_token); + + remote_participant_data1 = DDS_Security_ParticipantBuiltinTopicData_alloc(); + memcpy(&remote_participant_data1->key[0], &remote_participant_guid1, 12); + remote_participant_data1->key[0] = fromBE4u(remote_participant_data1->key[0]); + remote_participant_data1->key[1] = fromBE4u(remote_participant_data1->key[1]); + remote_participant_data1->key[2] = fromBE4u(remote_participant_data1->key[2]); + + initialize_identity_token(&remote_participant_data1->identity_token, RSA_2048_ALGORITHM_NAME, RSA_2048_ALGORITHM_NAME); + fill_permissions_token(&remote_participant_data1->permissions_token ); + + remote_participant_data1->security_info.participant_security_attributes = 0x01; + remote_participant_data1->security_info.plugin_participant_security_attributes = 0x02; + + remote_participant_data2 = DDS_Security_ParticipantBuiltinTopicData_alloc(); + memcpy(&remote_participant_data2->key[0], &remote_participant_guid2, 12); + remote_participant_data2->key[0] = fromBE4u(remote_participant_data2->key[0]); + remote_participant_data2->key[1] = fromBE4u(remote_participant_data2->key[1]); + remote_participant_data2->key[2] = fromBE4u(remote_participant_data2->key[2]); + + initialize_identity_token(&remote_participant_data2->identity_token, RSA_2048_ALGORITHM_NAME, RSA_2048_ALGORITHM_NAME); + fill_permissions_token(&remote_participant_data2->permissions_token ); + + remote_participant_data2->security_info.participant_security_attributes = 0x01; + remote_participant_data2->security_info.plugin_participant_security_attributes = 0x02; + + remote_participant_data3 = DDS_Security_ParticipantBuiltinTopicData_alloc(); + memcpy(&remote_participant_data3->key[0], &candidate_participant_guid, 12); + + initialize_identity_token(&remote_participant_data3->identity_token, RSA_2048_ALGORITHM_NAME, RSA_2048_ALGORITHM_NAME); + fill_permissions_token(&remote_participant_data3->permissions_token ); + + remote_participant_data2->security_info.participant_security_attributes = 0x01; + remote_participant_data2->security_info.plugin_participant_security_attributes = 0x02; + + challenge1_predefined_glb = find_binary_property(&g_remote_auth_request_token, AUTH_REQUEST_TOKEN_FUTURE_PROP_NAME); + challenge2_predefined_glb = challenge1_predefined_glb; + + return res; +} + +static void +release_remote_identities(void) +{ + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_boolean success; + + if (remote_identity_handle != DDS_SECURITY_HANDLE_NIL) { + success = auth->return_identity_handle(auth, remote_identity_handle, &exception); + if (!success) { + printf("return_identity_handle failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + reset_exception(&exception); + } + + if (remote_identity_handle2 != DDS_SECURITY_HANDLE_NIL) { + success = auth->return_identity_handle(auth, remote_identity_handle2, &exception); + if (!success) { + printf("return_identity_handle failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + reset_exception(&exception); + } + + DDS_Security_DataHolder_deinit(&g_local_auth_request_token); + DDS_Security_DataHolder_deinit(&g_remote_auth_request_token); + + DDS_Security_ParticipantBuiltinTopicData_free(remote_participant_data1); + DDS_Security_ParticipantBuiltinTopicData_free(remote_participant_data2); + DDS_Security_ParticipantBuiltinTopicData_free(remote_participant_data3); +} + + +static void +fill_handshake_message_token( + DDS_Security_HandshakeMessageToken *token, + DDS_Security_ParticipantBuiltinTopicData *pdata, + const char *certificate, + const char *dsign, + const char *kagree, + const struct octet_seq *diffie_hellman1, + const unsigned char *challengeData, + unsigned int challengeDataSize, + const struct octet_seq *diffie_hellman2, + const unsigned char *challengeData2, + unsigned int challengeDataSize2, + const DDS_Security_BinaryProperty_t *hash1_from_request, + const DDS_Security_BinaryProperty_t *hash2_from_reply, + HandshakeStep_t step) +{ + DDS_Security_BinaryProperty_t *tokens; + DDS_Security_BinaryProperty_t *c_id; + DDS_Security_BinaryProperty_t *c_perm; + DDS_Security_BinaryProperty_t *c_pdata; + DDS_Security_BinaryProperty_t *c_dsign_algo; + DDS_Security_BinaryProperty_t *c_kagree_algo; + DDS_Security_BinaryProperty_t *hash_c1; + DDS_Security_BinaryProperty_t *hash_c2; + DDS_Security_BinaryProperty_t *dh1; + DDS_Security_BinaryProperty_t *dh2; + DDS_Security_BinaryProperty_t *challenge1; + DDS_Security_BinaryProperty_t *challenge2; + DDS_Security_BinaryProperty_t *signature; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + unsigned idx; + unsigned char *serialized_local_participant_data; + size_t serialized_local_participant_data_size; + /*unsigned hash[32];*/ + + switch( step ) + { + + case HANDSHAKE_REQUEST: + tokens = DDS_Security_BinaryPropertySeq_allocbuf(8); + c_id = &tokens[0]; + c_perm = &tokens[1]; + c_pdata = &tokens[2]; + c_dsign_algo = &tokens[3]; + c_kagree_algo = &tokens[4]; + hash_c1 = &tokens[5]; + dh1 = &tokens[6]; + challenge1 = &tokens[7]; + + serializer_participant_data(pdata, &serialized_local_participant_data, &serialized_local_participant_data_size); + + /* Store the Identity Certificate associated with the local identify in c.id property */ + if (certificate) { + set_binary_property_string(c_id, "c.id", certificate); + } else { + set_binary_property_string(c_id, "c.idx", "rubbish"); + } + + /* Store the permission document in the c.perm property */ + set_binary_property_string(c_perm, "c.perm", "permissions_document"); + + /* Store the provided local_participant_data in the c.pdata property */ + set_binary_property_value(c_pdata, "c.pdata", serialized_local_participant_data, (uint32_t)serialized_local_participant_data_size); + ddsrt_free(serialized_local_participant_data); + + /* Set the used signing algorithm descriptor in c.dsign_algo */ + if (dsign) { + set_binary_property_string(c_dsign_algo, "c.dsign_algo", dsign); + } else { + set_binary_property_string(c_dsign_algo, "c.dsign_algox", "rubbish"); + } + + /* Set the used key algorithm descriptor in c.kagree_algo */ + if (kagree) { + set_binary_property_string(c_kagree_algo, "c.kagree_algo", kagree); + } else { + set_binary_property_string(c_kagree_algo, "c.kagree_algox", "rubbish"); + } + + /* Calculate the hash_c1 */ + { + DDS_Security_BinaryPropertySeq bseq; + DDS_Security_Serializer serializer; + unsigned char hash1_sent_in_request_arr[32]; + unsigned char *buffer; + size_t size; + + bseq._length = bseq._maximum = 5; + bseq._buffer = tokens; + + serializer = DDS_Security_Serializer_new(1024, 1024); + + DDS_Security_Serialize_BinaryPropertySeq(serializer, &bseq); + DDS_Security_Serializer_buffer(serializer, &buffer, &size); + SHA256(buffer, size, hash1_sent_in_request_arr); + ddsrt_free(buffer); + DDS_Security_Serializer_free(serializer); + + set_binary_property_value(hash_c1, "hash_c1", hash1_sent_in_request_arr, sizeof(hash1_sent_in_request_arr)); + } + + /* Set the DH public key associated with the local participant in dh1 property */ + if (diffie_hellman1) { + set_binary_property_value(dh1, "dh1", diffie_hellman1->data, diffie_hellman1->length); + } else { + set_binary_property_string(dh1, "dh1x", "rubbish"); + } + + /* Set the challenge in challenge1 property */ + if (challengeData) { + set_binary_property_value(challenge1, "challenge1", challengeData, challengeDataSize); + } else { + set_binary_property_value(challenge1, "challenge1x", challenge1_predefined_glb->value._buffer, challenge1_predefined_glb->value._length); + } + + token->class_id = ddsrt_strdup(AUTH_HANDSHAKE_REQUEST_TOKEN_CLASS_ID); + token->binary_properties._length = token->binary_properties._maximum = 8; + token->binary_properties._buffer = tokens; + break; + + case HANDSHAKE_REPLY: + tokens = DDS_Security_BinaryPropertySeq_allocbuf(12); + idx = 0; + c_id = &tokens[idx++]; + c_perm = &tokens[idx++]; + c_pdata = &tokens[idx++]; + c_dsign_algo = &tokens[idx++]; + c_kagree_algo = &tokens[idx++]; + hash_c2 = &tokens[idx++]; + challenge2 = &tokens[idx++]; + dh2 = &tokens[idx++]; + challenge1 = &tokens[idx++]; + dh1 = &tokens[idx++]; + hash_c1 = &tokens[idx++] ; + signature = &tokens[idx++]; + + serializer_participant_data(pdata, &serialized_local_participant_data, &serialized_local_participant_data_size); + + /* Store the Identity Certificate associated with the local identify in c.id property */ + if (certificate) { + set_binary_property_string(c_id, "c.id", certificate); + } else { + set_binary_property_string(c_id, "c.idx", "rubbish"); + } + + /* Store the permission document in the c.perm property */ + set_binary_property_string(c_perm, "c.perm", "permissions_document"); + + /* Store the provided local_participant_data in the c.pdata property */ + set_binary_property_value(c_pdata, "c.pdata", serialized_local_participant_data, (uint32_t)serialized_local_participant_data_size); + ddsrt_free(serialized_local_participant_data); + + /* Set the used signing algorithm descriptor in c.dsign_algo */ + if (dsign) { + set_binary_property_string(c_dsign_algo, "c.dsign_algo", dsign); + } else { + set_binary_property_string(c_dsign_algo, "c.dsign_algox", "rubbish"); + } + + /* Set the used key algorithm descriptor in c.kagree_algo */ + if (kagree) { + set_binary_property_string(c_kagree_algo, "c.kagree_algo", kagree); + } else { + set_binary_property_string(c_kagree_algo, "c.kagree_algox", "rubbish"); + } + + CU_ASSERT(hash1_from_request != NULL); + + set_binary_property_value(hash_c1, "hash_c1", hash1_from_request->value._buffer, hash1_from_request->value._length); + + /* Calculate the hash_c2 */ + { + DDS_Security_BinaryPropertySeq bseq; + DDS_Security_Serializer serializer; + unsigned char hash2_sent_in_reply_arr[32]; + unsigned char *buffer; + size_t size; + + bseq._length = bseq._maximum = 5; + bseq._buffer = tokens; + + serializer = DDS_Security_Serializer_new(1024, 1024); + + DDS_Security_Serialize_BinaryPropertySeq(serializer, &bseq); + DDS_Security_Serializer_buffer(serializer, &buffer, &size); + SHA256(buffer, size, hash2_sent_in_reply_arr); + + ddsrt_free(buffer); + DDS_Security_Serializer_free(serializer); + + set_binary_property_value(hash_c2, "hash_c2", hash2_sent_in_reply_arr, sizeof(hash2_sent_in_reply_arr)); + } + + /* Set the challenge in challenge1 property */ + if (challengeData) { + set_binary_property_value(challenge1, "challenge1", challengeData, challengeDataSize); + } else { + set_binary_property_value(challenge1, "challenge1x", challenge2->value._buffer, challenge2->value._length); + } + + /* Set the challenge in challenge2 property */ + if (challengeData2) { + set_binary_property_value(challenge2, "challenge2", challengeData2, challengeDataSize2); + } else { + set_binary_property_value(challenge2, "challenge2x", challenge2->value._buffer, challenge2->value._length); + } + + + /* Set the DH public key associated with the local participant in dh1 property */ + if (diffie_hellman1) { + set_binary_property_value(dh1, "dh1", diffie_hellman1->data, diffie_hellman1->length); + } else { + set_binary_property_string(dh1, "dh1x", "rubbish"); + } + + /* Set the DH public key associated with the local participant in dh2 property */ + if (diffie_hellman2) { + set_binary_property_value(dh2, "dh2", diffie_hellman2->data, diffie_hellman2->length); + } else { + set_binary_property_string(dh2, "dh2x", "rubbish"); + } + + /* Calculate the signature */ + { + BIO *bio; + EVP_PKEY *private_key_x509; + unsigned char *sign; + size_t signlen; + + const DDS_Security_BinaryProperty_t * binary_properties[ HANDSHAKE_SIGNATURE_SIZE ]; + + /* load certificate in buffer */ + bio = BIO_new_mem_buf((const char *) bob_private_key, -1); + assert( bio ); + private_key_x509 = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); + assert (private_key_x509 ); + + binary_properties[0] = hash_c2; + binary_properties[1] = challenge2; + binary_properties[2] = dh2; + binary_properties[3] = challenge1; + binary_properties[4] = dh1; + binary_properties[5] = hash_c1; + + if (create_signature_for_test(private_key_x509, binary_properties, HANDSHAKE_SIGNATURE_SIZE , &sign, &signlen, &exception) != DDS_SECURITY_VALIDATION_OK) + { + printf("Exception: %s\n", exception.message); + } + set_binary_property_value(signature, "signature", sign, (uint32_t)signlen); + + ddsrt_free(sign); + EVP_PKEY_free(private_key_x509); + BIO_free(bio); + } + + token->class_id = ddsrt_strdup(AUTH_HANDSHAKE_REPLY_TOKEN_CLASS_ID); + token->binary_properties._length = token->binary_properties._maximum = 12; + token->binary_properties._buffer = tokens; + break; + + case HANDSHAKE_FINAL: + tokens = DDS_Security_BinaryPropertySeq_allocbuf(7); + idx = 0; + signature = &tokens[idx++]; + hash_c1 = &tokens[idx++]; + challenge1 = &tokens[idx++]; + dh1 = &tokens[idx++]; + challenge2 = &tokens[idx++]; + dh2 = &tokens[idx++]; + hash_c2 = &tokens[idx++]; + + CU_ASSERT(hash1_from_request != NULL); + CU_ASSERT(hash2_from_reply != NULL); + + set_binary_property_value(hash_c1, "hash_c1", hash1_from_request->value._buffer, hash1_from_request->value._length); + set_binary_property_value(hash_c2, "hash_c2", hash2_from_reply->value._buffer, hash2_from_reply->value._length); + + printf("process: %s\n", hash_c1->name); + + /* Set the challenge in challenge1 property */ + if (challengeData) { + set_binary_property_value(challenge1, "challenge1", challengeData, challengeDataSize); + } else { + set_binary_property_value(challenge1, "challenge1x", challenge2->value._buffer, challenge2->value._length); + } + + /* Set the challenge in challenge2 property */ + if (challengeData2) { + set_binary_property_value(challenge2, "challenge2", challengeData2, challengeDataSize2); + } else { + set_binary_property_value(challenge2, "challenge2x", challenge2->value._buffer, challenge2->value._length); + } + + + /* Set the DH public key associated with the local participant in dh1 property */ + if (diffie_hellman1) { + set_binary_property_value(dh1, "dh1", diffie_hellman1->data, diffie_hellman1->length); + } else { + set_binary_property_string(dh1, "dh1x", "rubbish"); + } + + /* Set the DH public key associated with the local participant in dh2 property */ + if (diffie_hellman2) { + set_binary_property_value(dh2, "dh2", diffie_hellman2->data, diffie_hellman2->length); + } else { + set_binary_property_string(dh2, "dh2x", "rubbish"); + } + + /* Calculate the signature */ + { + BIO *bio; + EVP_PKEY *private_key_x509; + unsigned char *sign; + size_t signlen; + const DDS_Security_BinaryProperty_t * binary_properties[ HANDSHAKE_SIGNATURE_SIZE ]; + + /* load certificate in buffer */ + bio = BIO_new_mem_buf((const char *) bob_private_key, -1); + assert( bio ); + private_key_x509 = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); + assert (private_key_x509 ); + + binary_properties[0] = hash_c1; + binary_properties[1] = challenge1; + binary_properties[2] = dh1; + binary_properties[3] = challenge2; + binary_properties[4] = dh2; + binary_properties[5] = hash_c2; + + if (create_signature_for_test(private_key_x509, binary_properties, HANDSHAKE_SIGNATURE_SIZE, &sign, &signlen, &exception) != DDS_SECURITY_VALIDATION_OK) + { + printf("Exception: %s\n", exception.message); + } + set_binary_property_value(signature, "signature", sign, (uint32_t)signlen); + + ddsrt_free(sign); + EVP_PKEY_free(private_key_x509); + BIO_free(bio); + } + token->class_id = ddsrt_strdup(AUTH_HANDSHAKE_FINAL_TOKEN_CLASS_ID); + token->binary_properties._length = token->binary_properties._maximum = 7; + token->binary_properties._buffer = tokens; + break; + } +} + + +static DDS_Security_boolean +on_revoke_identity_cb( dds_security_authentication_listener *instance, + const dds_security_authentication *plugin, + const DDS_Security_IdentityHandle handle) +{ + DDSRT_UNUSED_ARG( instance ); + DDSRT_UNUSED_ARG( plugin ); + if (identity_handle_for_callback1 == DDS_SECURITY_HANDLE_NIL) { + identity_handle_for_callback1 = handle; + } else if (identity_handle_for_callback2 == DDS_SECURITY_HANDLE_NIL) { + identity_handle_for_callback2 = handle; + } + printf( "Listener called for handle: %lld Local:%lld Remote:%lld\n", (long long) handle, (long long) local_identity_handle, (long long) remote_identity_handle2); + + return true; +} + + +/* sets listener for authentication expiry and checks if the listener triggered after a while */ +CU_Test(ddssec_builtin_listeners_auth, local_remote_set_before_validation) +{ + DDS_Security_PermissionsHandle result; + DDS_Security_PermissionsToken permissions_token; + DDS_Security_AuthenticatedPeerCredentialToken credential_token; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + DDS_Security_long valid; + int r; + dds_duration_t time_left = DDS_MSECS(10000); + DDS_Security_boolean local_expired = false; + DDS_Security_boolean remote_expired = false; + DDS_Security_HandshakeHandle handshake_handle; + DDS_Security_HandshakeMessageToken handshake_reply_token_in = DDS_SECURITY_TOKEN_INIT; + DDS_Security_HandshakeMessageToken handshake_token_out = DDS_SECURITY_TOKEN_INIT; + DDS_Security_HandshakeMessageToken handshake_reply_token_out = DDS_SECURITY_TOKEN_INIT; + const DDS_Security_BinaryProperty_t *hash1_sent_in_request; + const DDS_Security_BinaryProperty_t *dh1; + const DDS_Security_BinaryProperty_t *challenge1_glb; + struct octet_seq dh1_pub_key; + char *remote_certificate_file; + + local_expiry_date = DDS_TIME_INVALID; + remote_expiry_date = DDS_TIME_INVALID; + + auth_listener.on_revoke_identity = &on_revoke_identity_cb; + + auth->set_listener( auth, &auth_listener, &exception); + access_control->set_listener( access_control, + &access_control_listener, + &exception); + + + valid = validate_local_identity_and_permissions( 3, &local_expiry_date); + if (valid == DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_CODE) { + /* This can happen on very slow platforms or when doing a valgrind run. + * Just take our losses and quit, simulating a success. */ + return; + } + CU_ASSERT_FATAL (valid == DDS_SECURITY_ERR_OK_CODE); + + /*Generate remote certificate*/ + create_certificate_from_csr( bob_csr, 4, BOB_IDENTITY_CERT_FILE, &remote_expiry_date ); + + ddsrt_asprintf(&remote_certificate_file, "%s%s", g_path_build_dir, BOB_IDENTITY_CERT_FILE); + bob_identity_cert = load_file_contents( remote_certificate_file ); + + validate_remote_identity( bob_identity_cert ); + + + /* Check if we actually have validate_remote_permissions function. */ + CU_ASSERT_FATAL (access_control != NULL); + CU_ASSERT_FATAL (local_identity_handle != DDS_SECURITY_HANDLE_NIL); + CU_ASSERT_FATAL (access_control->validate_remote_permissions != NULL); + CU_ASSERT_FATAL (access_control->return_permissions_handle != NULL); + + fill_permissions_token(&permissions_token); + r = fill_peer_credential_token(&credential_token); + CU_ASSERT_FATAL (r); + + + + /*handshake*/ + result = auth->begin_handshake_request( + auth, + &handshake_handle, + &handshake_token_out, + local_identity_handle, + remote_identity_handle2, + &serialized_participant_data, + &exception); + + if (result != DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE) { + printf("begin_handshake_request failed: %s\n", exception.message ? exception.message : "Error message missing"); + } + + /* get challenge 1 from the message */ + challenge1_glb = find_binary_property(&handshake_token_out, "challenge1"); + + /*Get DH1 value */ + dh1 = find_binary_property(&handshake_token_out, "dh1"); + + hash1_sent_in_request = find_binary_property(&handshake_token_out, "hash_c1"); + + CU_ASSERT_FATAL(dh1 != NULL); + CU_ASSERT_FATAL(dh1->value._length > 0); + CU_ASSERT_FATAL(dh1->value._buffer != NULL); + + dh1_pub_key.data = dh1->value._buffer; + dh1_pub_key.length = dh1->value._length; + + /* prepare reply */ + fill_handshake_message_token( + &handshake_reply_token_in, remote_participant_data2, bob_identity_cert, + AUTH_DSIGN_ALGO_RSA_NAME, AUTH_KAGREE_ALGO_ECDH_NAME, + &dh1_pub_key, challenge1_glb->value._buffer, challenge1_glb->value._length, + &dh_ecdh_pub_key, challenge2_predefined_glb->value._buffer, challenge2_predefined_glb->value._length, hash1_sent_in_request, NULL, HANDSHAKE_REPLY); + + reset_exception(&exception); + + result = auth->process_handshake( + auth, + &handshake_reply_token_out, + &handshake_reply_token_in, + handshake_handle, + &exception); + + CU_ASSERT_FATAL(result == DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE); + CU_ASSERT(handshake_handle != DDS_SECURITY_HANDLE_NIL); + + result = access_control->validate_remote_permissions( + access_control, + auth, + local_identity_handle, + remote_identity_handle, + &permissions_token, + &credential_token, + &exception); + + if (result == 0) { + printf("validate_remote_permissions_failed: %s\n", exception.message ? exception.message : "Error message missing"); + //TODO: Clean-up before failing + CU_ASSERT_FATAL (exception.code == DDS_SECURITY_ERR_VALIDITY_PERIOD_EXPIRED_CODE); +// goto end; + + } + + remote_permissions_handle = result; + + reset_exception(&exception); + + while( time_left > 0 && (!local_expired || !remote_expired) ){ + /* Normally, it is expected that the remote expiry is triggered before the + * local one. However, that can change on slow platforms. */ + // TODO: Check for time compare + if (remote_expiry_date < local_expiry_date) { + if (identity_handle_for_callback1 == remote_identity_handle2) { + remote_expired = true; + } + if (identity_handle_for_callback2 == local_identity_handle) { + local_expired = true; + } + } else { + if (identity_handle_for_callback2 == remote_identity_handle2) { + remote_expired = true; + } + if (identity_handle_for_callback1 == local_identity_handle) { + local_expired = true; + } + } + + dds_sleepfor(DDS_MSECS(100)); + time_left -= DDS_MSECS(100); + } + + CU_ASSERT (local_expired); + CU_ASSERT (remote_expired); + + + reset_exception(&exception); + + result = auth->return_handshake_handle(auth, handshake_handle, &exception); + release_remote_identities(); + + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *) &permissions_token); + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *) &credential_token); + + + CU_ASSERT_TRUE (result == 1); + + reset_exception(&exception); + + DDS_Security_DataHolder_deinit(&handshake_token_out); + DDS_Security_DataHolder_deinit(&handshake_reply_token_in); + DDS_Security_DataHolder_deinit(&handshake_reply_token_out); + + clear_local_identity_and_permissions(); + ddsrt_free( bob_identity_cert ); + ddsrt_free ( remote_certificate_file ); +} diff --git a/src/security/builtin_plugins/tests/process_handshake/src/process_handshake_utests.c b/src/security/builtin_plugins/tests/process_handshake/src/process_handshake_utests.c index 9eaf2d1..5b2f5d6 100644 --- a/src/security/builtin_plugins/tests/process_handshake/src/process_handshake_utests.c +++ b/src/security/builtin_plugins/tests/process_handshake/src/process_handshake_utests.c @@ -523,7 +523,7 @@ validate_local_identity(const char* trusted_ca_dir) char trusted_ca_dir_path[1024]; dds_security_property_init(&participant_qos.property.value, 4); #ifdef WIN32 - snprintf(trusted_ca_dir_path, 1024, "%s\\testsuite\\dbt\\security_plugin\\tests\\validate_begin_handshake_reply\\etc\\%s", CONFIG_ENV_TESTS_DIR,trusted_ca_dir); + snprintf(trusted_ca_dir_path, 1024, "%s\\validate_begin_handshake_reply\\etc\\%s", CONFIG_ENV_TESTS_DIR, trusted_ca_dir); #else snprintf(trusted_ca_dir_path, 1024, "%s/validate_begin_handshake_reply/etc/%s", CONFIG_ENV_TESTS_DIR, trusted_ca_dir); #endif diff --git a/src/security/builtin_plugins/tests/validate_begin_handshake_reply/src/validate_begin_handshake_reply_utests.c b/src/security/builtin_plugins/tests/validate_begin_handshake_reply/src/validate_begin_handshake_reply_utests.c index b3871db..90cb2a7 100644 --- a/src/security/builtin_plugins/tests/validate_begin_handshake_reply/src/validate_begin_handshake_reply_utests.c +++ b/src/security/builtin_plugins/tests/validate_begin_handshake_reply/src/validate_begin_handshake_reply_utests.c @@ -220,7 +220,7 @@ static const char *unrelated_identity = "B7DMeaVlLClGQaKZZ7aexEx9se+IyLn2\n" "-----END CERTIFICATE-----\n"; -#ifdef TRUSTED_CA_DIR_IMPLEMENTED + static const char *remote_identity_trusted = "-----BEGIN CERTIFICATE-----\n" "MIIDcDCCAligAwIBAgIBBTANBgkqhkiG9w0BAQsFADByMQswCQYDVQQGEwJOTDEL\n" @@ -297,7 +297,6 @@ static const char *remote_identity_trusted_expired = "O3gAjPUL0jzRztp5Yj3dYPV8YyJHLEKr75IXNedV9YKhT4f6kTS3UEjMTqYbYsix\n" "MtqgY283RjsExzjNvw==\n" "-----END CERTIFICATE-----\n"; -#endif static struct plugins_hdl *plugins = NULL; static dds_security_authentication *auth = NULL; @@ -1968,10 +1967,7 @@ CU_Test(ddssec_builtin_validate_begin_handshake_reply,return_handle, .init = in } -/*TODO: test is waiting for Trusted CA parsing function */ - -#if(0) -CU _ Test(validate_begin_handshake_reply,extended_certificate_check ) +CU_Test(validate_begin_handshake_reply,extended_certificate_check, .init = init_testcase, .fini = fini_testcase ) { DDS_Security_ValidationResult_t result; DDS_Security_HandshakeHandle handshake_handle; @@ -2107,4 +2103,3 @@ CU _ Test(validate_begin_handshake_reply,extended_certificate_check ) handshake_message_deinit(&handshake_token_out); reset_exception(&exception); } -#endif diff --git a/src/security/builtin_plugins/tests/validate_local_identity/src/validate_local_identity_utests.c b/src/security/builtin_plugins/tests/validate_local_identity/src/validate_local_identity_utests.c index 5d17ebd..59a5567 100644 --- a/src/security/builtin_plugins/tests/validate_local_identity/src/validate_local_identity_utests.c +++ b/src/security/builtin_plugins/tests/validate_local_identity/src/validate_local_identity_utests.c @@ -2017,10 +2017,8 @@ CU_Test(ddssec_builtin_validate_local_identity,no_file) } -/* TODO: Should be enabled after implementing trusted ca dir parsing*/ -#if(0) -CU _ Test(validate_local_identity,with_extended_certificate_check) -{ +CU_Test(ddssec_builtin_validate_local_identity,with_extended_certificate_check) +{ DDS_Security_ValidationResult_t result; DDS_Security_IdentityHandle local_identity_handle = DDS_SECURITY_HANDLE_NIL; DDS_Security_GUID_t adjusted_participant_guid; @@ -2042,7 +2040,7 @@ CU _ Test(validate_local_identity,with_extended_certificate_check) fill_participant_qos(&participant_qos, false, identity_certificate, false, identity_ca, - false, private_key, + false, private_key_pem, NULL, "trusted_ca_dir"); /* Now call the function. */ @@ -2106,4 +2104,3 @@ CU _ Test(validate_local_identity,with_extended_certificate_check) } -#endif diff --git a/src/security/core/include/dds/security/core/dds_security_timed_cb.h b/src/security/core/include/dds/security/core/dds_security_timed_cb.h index 6a883d6..93b2eb4 100644 --- a/src/security/core/include/dds/security/core/dds_security_timed_cb.h +++ b/src/security/core/include/dds/security/core/dds_security_timed_cb.h @@ -25,7 +25,11 @@ extern "C" { */ struct dds_security_timed_dispatcher_t; -struct dds_security_timed_cb_data_t; +/** + * The timed callback structure holds a list of dispatchers and manages + * the thread that calls the dispatchers callbacks. + */ +struct dds_security_timed_cb_data; /** * The callback is triggered by two causes: diff --git a/src/security/core/src/dds_security_utils.c b/src/security/core/src/dds_security_utils.c index 8a5cef7..42610af 100644 --- a/src/security/core/src/dds_security_utils.c +++ b/src/security/core/src/dds_security_utils.c @@ -1291,3 +1291,4 @@ DDS_Security_parse_xml_date( return DDS_TIME_INVALID; } + From d24bf4d27d1b29122140b259c0e31e2f41f6c2dd Mon Sep 17 00:00:00 2001 From: MarcelJordense <37329887+MarcelJordense@users.noreply.github.com> Date: Mon, 10 Feb 2020 13:24:51 +0100 Subject: [PATCH 096/238] Update authentication plugin with respect to the remote identity handle (#379) * Authentication plugin determine remote identity handle on participant match Signed-off-by: Marcel Jordense * Correct authentication plugin Signed-off-by: Marcel Jordense --- .../authentication/src/authentication.c | 587 ++++++++---------- 1 file changed, 243 insertions(+), 344 deletions(-) diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index a3d5ea7..257debc 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -21,6 +21,7 @@ #include #include "authentication.h" #include "dds/ddsrt/heap.h" +#include "dds/ddsrt/avl.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_timed_cb.h" @@ -119,9 +120,9 @@ typedef enum { typedef enum { CREATEDREQUEST, CREATEDREPLY - } CreatedHandshakeStep_t; + typedef struct SecurityObject SecurityObject; typedef void (*SecurityObjectDestructor)(SecurityObject *obj); @@ -129,7 +130,6 @@ typedef void (*SecurityObjectDestructor)(SecurityObject *obj); struct SecurityObject { int64_t handle; SecurityObjectKind_t kind; - SecurityObjectDestructor destructor; }; @@ -146,6 +146,35 @@ struct SecurityObject { #define SECURITY_OBJECT_VALID(o,k) security_object_valid((SecurityObject *)(o), k) +struct LocalIdentityInfo; +struct HandshakeInfo; + +typedef struct RemoteIdentityInfo { + SecurityObject _parent; + uint32_t refc; + DDS_Security_GUID_t guid; + X509 *identityCert; + AuthenticationAlgoKind_t dsignAlgoKind; + AuthenticationAlgoKind_t kagreeAlgoKind; + DDS_Security_IdentityToken *remoteIdentityToken; + DDS_Security_OctetSeq pdata; + char *permissionsDocument; +} RemoteIdentityInfo; + +/* This structure contains the relation between a local and a remote identity + * The handle for this object is the same as the handle of the associated + * local identity object. The IdentityRelation object will be stored with the + * remote identity. + */ +typedef struct IdentityRelation { + SecurityObject _parent; + ddsrt_avl_node_t avlnode; + struct LocalIdentityInfo *localIdentity; + struct RemoteIdentityInfo *remoteIdentity; + AuthenticationChallenge *lchallenge; + AuthenticationChallenge *rchallenge; + struct HandshakeInfo *handshake; +} IdentityRelation; typedef struct LocalIdentityInfo { SecurityObject _parent; @@ -159,36 +188,12 @@ typedef struct LocalIdentityInfo { AuthenticationAlgoKind_t dsignAlgoKind; AuthenticationAlgoKind_t kagreeAlgoKind; char *permissionsDocument; + ddsrt_avl_tree_t relations; /* contains the IdentityRelation objects */ } LocalIdentityInfo; -typedef struct RemoteIdentityInfo { - SecurityObject _parent; - DDS_Security_GUID_t guid; - X509 *identityCert; - AuthenticationAlgoKind_t dsignAlgoKind; - AuthenticationAlgoKind_t kagreeAlgoKind; - DDS_Security_IdentityToken *remoteIdentityToken; - DDS_Security_OctetSeq pdata; - char *permissionsDocument; - struct ddsrt_hh *linkHash; /* contains the IdentityRelation objects */ -} RemoteIdentityInfo; - - -/* This structure contains the relation between a local and a remote identity - * The handle for this object is the same as the handle of the associated - * local identity object. The IdentityRelation object will be stored with the - * remote identity. - */ -typedef struct IdentityRelation { - SecurityObject _parent; - LocalIdentityInfo *localIdentity; - RemoteIdentityInfo *remoteIdentity; - AuthenticationChallenge *lchallenge; - AuthenticationChallenge *rchallenge; -} IdentityRelation; - typedef struct HandshakeInfo { SecurityObject _parent; + ddsrt_avl_node_t avlnode; IdentityRelation *relation; HashValue_t hash_c1; HashValue_t hash_c2; @@ -203,12 +208,10 @@ typedef struct dds_security_authentication_impl { ddsrt_mutex_t lock; struct ddsrt_hh *objectHash; struct ddsrt_hh *remoteGuidHash; + struct ddsrt_hh *handshakes; struct dds_security_timed_cb_data *timed_callbacks; struct dds_security_timed_dispatcher_t *dispatcher; X509Seq trustedCAList; - - - } dds_security_authentication_impl; /* data type for timer dispatcher */ @@ -218,6 +221,11 @@ typedef struct { } validity_cb_info; +static int compare_relation (const void *va, const void *vb); + +const ddsrt_avl_treedef_t relations_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY (offsetof (struct IdentityRelation, avlnode), offsetof (struct IdentityRelation, remoteIdentity), compare_relation, 0); + static bool security_object_valid( SecurityObject *obj, @@ -225,14 +233,7 @@ security_object_valid( { if (!obj) return false; if (obj->kind != kind) return false; - if (kind == SECURITY_OBJECT_KIND_IDENTITY_RELATION) { - IdentityRelation *relation = (IdentityRelation *)obj; - if (!relation->localIdentity || !relation->remoteIdentity || (ddsrt_address)obj->handle != (ddsrt_address)relation->localIdentity) { - return false; - } - } else if ((ddsrt_address)obj->handle != (ddsrt_address)obj) { - return false; - } + if ((uintptr_t)obj->handle != (uintptr_t)obj) return false; return true; } @@ -268,20 +269,31 @@ security_object_find( template.handle = handle; - return (SecurityObject *) ddsrt_hh_lookup(hh, &template);; + return (SecurityObject *) ddsrt_hh_lookup(hh, &template); +} + +static int compare_relation (const void *va, const void *vb) +{ + const struct RemoteIdentityInfo * ha = va; + const struct RemoteIdentityInfo * hb = vb; + + if (IDENTITY_HANDLE(ha) < IDENTITY_HANDLE(hb)) { + return -1; + } else if (IDENTITY_HANDLE(ha) > IDENTITY_HANDLE(hb)) { + return 1; + } + return 0; } static void security_object_init( SecurityObject *obj, - SecurityObjectKind_t kind, - SecurityObjectDestructor destructor) + SecurityObjectKind_t kind) { assert(obj); obj->kind = kind; - obj->handle = (int64_t)(ddsrt_address)obj; - obj->destructor = destructor; + obj->handle = (int64_t)(uintptr_t)obj; } static void @@ -292,25 +304,8 @@ security_object_deinit( assert(obj); obj->handle = DDS_SECURITY_HANDLE_NIL; obj->kind = SECURITY_OBJECT_KIND_UNKNOWN; - obj->destructor = NULL; } -static void -security_object_free( - SecurityObject *obj) -{ - assert(obj); - if (obj && obj->destructor) { - obj->destructor(obj); - } -} - -static void -localIdentityInfoFree( - SecurityObject *obj); - - - static LocalIdentityInfo * localIdentityInfoNew( DDS_Security_DomainId domainId, @@ -332,10 +327,7 @@ localIdentityInfoNew( identity = ddsrt_malloc(sizeof(*identity)); memset(identity, 0, sizeof(*identity)); - security_object_init((SecurityObject *)identity, SECURITY_OBJECT_KIND_LOCAL_IDENTITY, localIdentityInfoFree); - - - + security_object_init((SecurityObject *)identity, SECURITY_OBJECT_KIND_LOCAL_IDENTITY); identity->domainId = domainId; identity->identityCert = identityCert; @@ -348,31 +340,33 @@ localIdentityInfoNew( memcpy(&identity->candidateGUID, candidate_participant_guid, sizeof(DDS_Security_GUID_t)); memcpy(&identity->adjustedGUID, adjusted_participant_guid, sizeof(DDS_Security_GUID_t)); + ddsrt_avl_init(&relations_treedef, &identity->relations); + return identity; } static void localIdentityInfoFree( - SecurityObject *obj) + LocalIdentityInfo *info) { - LocalIdentityInfo *identity = (LocalIdentityInfo *)obj; + CHECK_OBJECT_KIND(info, SECURITY_OBJECT_KIND_LOCAL_IDENTITY); - CHECK_OBJECT_KIND(obj, SECURITY_OBJECT_KIND_LOCAL_IDENTITY); - - if (identity) { - if (identity->identityCert) { - X509_free(identity->identityCert); + if (info) { + assert(ddsrt_avl_is_empty(&info->relations)); + ddsrt_avl_free(&relations_treedef, &info->relations, NULL); + if (info->identityCert) { + X509_free(info->identityCert); } - if (identity->identityCA) { - X509_free(identity->identityCA); + if (info->identityCA) { + X509_free(info->identityCA); } - if (identity->privateKey) { - EVP_PKEY_free(identity->privateKey); + if (info->privateKey) { + EVP_PKEY_free(info->privateKey); } - ddsrt_free(identity->pdata._buffer); - ddsrt_free(identity->permissionsDocument); - security_object_deinit((SecurityObject *)identity); - ddsrt_free(identity); + ddsrt_free(info->pdata._buffer); + ddsrt_free(info->permissionsDocument); + security_object_deinit((SecurityObject *)info); + ddsrt_free(info); } } @@ -411,10 +405,6 @@ find_remote_identity_by_guid( return (RemoteIdentityInfo *) ddsrt_hh_lookup(hh, &template); } -static void -remoteIdentityInfoFree( - SecurityObject *obj); - static RemoteIdentityInfo * remoteIdentityInfoNew( const DDS_Security_GUID_t *guid, @@ -428,47 +418,39 @@ remoteIdentityInfoNew( identity = ddsrt_malloc(sizeof(*identity)); memset(identity, 0, sizeof(*identity)); - security_object_init((SecurityObject *)identity, SECURITY_OBJECT_KIND_REMOTE_IDENTITY, remoteIdentityInfoFree); + security_object_init((SecurityObject *)identity, SECURITY_OBJECT_KIND_REMOTE_IDENTITY); memcpy(&identity->guid, guid, sizeof(DDS_Security_GUID_t)); + identity->refc = 0; identity->remoteIdentityToken = DDS_Security_DataHolder_alloc(); DDS_Security_DataHolder_copy(identity->remoteIdentityToken, remote_identity_token); identity->identityCert = NULL; identity->dsignAlgoKind = AUTH_ALGO_KIND_UNKNOWN; identity->kagreeAlgoKind = AUTH_ALGO_KIND_UNKNOWN; identity->permissionsDocument = ddsrt_strdup(""); - identity->linkHash = ddsrt_hh_new(32, security_object_hash, security_object_equal); return identity; } static void remoteIdentityInfoFree( - SecurityObject *obj) + RemoteIdentityInfo *info) { - RemoteIdentityInfo *identity = (RemoteIdentityInfo *)obj; + CHECK_OBJECT_KIND(info, SECURITY_OBJECT_KIND_REMOTE_IDENTITY); - CHECK_OBJECT_KIND(obj, SECURITY_OBJECT_KIND_REMOTE_IDENTITY); - - if (identity) { - if (identity->identityCert) { - X509_free(identity->identityCert); + if (info) { + assert(info->refc == 0); + if (info->identityCert) { + X509_free(info->identityCert); } - DDS_Security_DataHolder_free(identity->remoteIdentityToken); - - ddsrt_hh_free(identity->linkHash); - - ddsrt_free(identity->pdata._buffer); - ddsrt_free(identity->permissionsDocument); - security_object_deinit((SecurityObject *)identity); - ddsrt_free(identity); + DDS_Security_DataHolder_free(info->remoteIdentityToken); + ddsrt_free(info->pdata._buffer); + ddsrt_free(info->permissionsDocument); + security_object_deinit((SecurityObject *)info); + ddsrt_free(info); } } -static void -identityRelationFree( - SecurityObject *obj); - /* The IdentityRelation provides the association between a local and a remote * identity. This object manages the challenges which are created for * each association between a local and a remote identity. @@ -492,24 +474,23 @@ identityRelationNew( relation = ddsrt_malloc(sizeof(*relation)); memset(relation, 0, sizeof(*relation)); - security_object_init((SecurityObject *)relation, SECURITY_OBJECT_KIND_IDENTITY_RELATION, identityRelationFree); - relation->_parent.handle = SECURITY_OBJECT_HANDLE(localIdentity); + security_object_init((SecurityObject *)relation, SECURITY_OBJECT_KIND_IDENTITY_RELATION); relation->localIdentity = localIdentity; relation->remoteIdentity = remoteIdentity; + remoteIdentity->refc++; relation->lchallenge = lchallenge; relation->rchallenge = rchallenge; + relation->handshake = NULL; return relation; } static void identityRelationFree( - SecurityObject *obj) + IdentityRelation *relation) { - IdentityRelation *relation = (IdentityRelation *)obj; - - CHECK_OBJECT_KIND(obj, SECURITY_OBJECT_KIND_IDENTITY_RELATION); + CHECK_OBJECT_KIND(relation, SECURITY_OBJECT_KIND_IDENTITY_RELATION); if (relation) { ddsrt_free(relation->lchallenge); @@ -519,27 +500,16 @@ identityRelationFree( } } -static void -handshakeInfoFree( - SecurityObject *obj); - static HandshakeInfo * handshakeInfoNew( - LocalIdentityInfo *localIdentity, - RemoteIdentityInfo *remoteIdentity, IdentityRelation *relation) { HandshakeInfo *handshake; - assert(localIdentity); - assert(remoteIdentity); - - DDSRT_UNUSED_ARG(localIdentity); - DDSRT_UNUSED_ARG(remoteIdentity); handshake = ddsrt_malloc(sizeof(*handshake)); memset(handshake, 0, sizeof(*handshake)); - security_object_init((SecurityObject *)handshake, SECURITY_OBJECT_KIND_HANDSHAKE, handshakeInfoFree); + security_object_init((SecurityObject *)handshake, SECURITY_OBJECT_KIND_HANDSHAKE); handshake->relation = relation; handshake->shared_secret_handle_impl = NULL; @@ -549,13 +519,14 @@ handshakeInfoNew( static void handshakeInfoFree( - SecurityObject *obj) + HandshakeInfo *handshake) { - HandshakeInfo *handshake = (HandshakeInfo *)obj; - - CHECK_OBJECT_KIND(obj, SECURITY_OBJECT_KIND_HANDSHAKE); + CHECK_OBJECT_KIND(handshake, SECURITY_OBJECT_KIND_HANDSHAKE); if (handshake) { + assert(handshake->relation && handshake->relation->handshake == handshake); + handshake->relation->handshake = NULL; + if (handshake->ldh) { EVP_PKEY_free(handshake->ldh); } @@ -571,48 +542,6 @@ handshakeInfoFree( } } -static IdentityRelation * -find_identity_relation( - const RemoteIdentityInfo *remote, - int64_t lid) -{ - return (IdentityRelation *)security_object_find(remote->linkHash, lid); -} - -static void -remove_identity_relation( - RemoteIdentityInfo *remote, - IdentityRelation *relation) -{ - (void)ddsrt_hh_remove(remote->linkHash, relation); - security_object_free((SecurityObject *) relation); -} - -static HandshakeInfo * -find_handshake( - const dds_security_authentication_impl *auth, - int64_t localId, - int64_t remoteId) -{ - struct ddsrt_hh_iter it; - SecurityObject *obj; - IdentityRelation *relation; - HandshakeInfo *found = NULL; - - for (obj = ddsrt_hh_iter_first(auth->objectHash, &it); obj && !found; obj = ddsrt_hh_iter_next(&it)) { - if (obj->kind == SECURITY_OBJECT_KIND_HANDSHAKE) { - relation = ((HandshakeInfo *)obj)->relation; - assert(relation); - if ((SECURITY_OBJECT_HANDLE(relation->localIdentity) == localId) && - (SECURITY_OBJECT_HANDLE(relation->remoteIdentity) == remoteId)) { - found = (HandshakeInfo *)obj; - } - } - } - - return found; -} - static char * get_authentication_class_id( void) @@ -1374,11 +1303,10 @@ validate_remote_identity( DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; dds_security_authentication_impl *impl = (dds_security_authentication_impl *) instance; SecurityObject *obj; - LocalIdentityInfo *localIdent; - RemoteIdentityInfo *remoteIdent; - IdentityRelation *relation; + LocalIdentityInfo *linfo; + RemoteIdentityInfo *rinfo; + IdentityRelation *relation = NULL; AuthenticationChallenge *lchallenge = NULL, *rchallenge = NULL; - int r; /* validate provided arguments */ if (!instance || !remote_identity_handle || !local_auth_request_token || !remote_identity_token || !remote_participant_guid) { @@ -1393,10 +1321,10 @@ validate_remote_identity( DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "validate_remote_identity: Invalid handle provided"); goto err_inv_handle; } - localIdent = (LocalIdentityInfo *) obj; + linfo = (LocalIdentityInfo *) obj; /* Check if the provided remote_identity_token is compatible */ - result = validate_remote_identity_token(localIdent, remote_identity_token, ex); + result = validate_remote_identity_token(linfo, remote_identity_token, ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_remote_identity_token; } @@ -1421,30 +1349,29 @@ validate_remote_identity( */ /* Check if the remote identity has already been validated by a previous validation request. */ - remoteIdent = find_remote_identity_by_guid(impl->remoteGuidHash, remote_participant_guid); - if (!remoteIdent) { - remoteIdent = remoteIdentityInfoNew(remote_participant_guid, remote_identity_token); - (void)ddsrt_hh_add(impl->objectHash, remoteIdent); - (void)ddsrt_hh_add(impl->remoteGuidHash, remoteIdent); - relation = identityRelationNew(localIdent, remoteIdent, lchallenge, rchallenge); - (void)ddsrt_hh_add(remoteIdent->linkHash, relation); + rinfo = find_remote_identity_by_guid(impl->remoteGuidHash, remote_participant_guid); + if (!rinfo) { + rinfo = remoteIdentityInfoNew(remote_participant_guid, remote_identity_token); + (void)ddsrt_hh_add(impl->remoteGuidHash, rinfo); + relation = identityRelationNew(linfo, rinfo, lchallenge, rchallenge); + (void)ddsrt_hh_add(impl->objectHash, relation); + ddsrt_avl_insert(&relations_treedef, &linfo->relations, relation); } else { + ddsrt_avl_ipath_t path; /* When the remote identity has already been validated before, check if the remote identity token matches with the existing one */ - if (!DDS_Security_DataHolder_equal(remoteIdent->remoteIdentityToken, remote_identity_token)) { + if (!DDS_Security_DataHolder_equal(rinfo->remoteIdentityToken, remote_identity_token)) { result = DDS_SECURITY_VALIDATION_FAILED; DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "validate_remote_identity: remote_identity_token does not match with previously received one"); goto err_inv_duplicate; } - - relation = find_identity_relation(remoteIdent, SECURITY_OBJECT_HANDLE(localIdent)); + relation = ddsrt_avl_lookup_ipath(&relations_treedef, &linfo->relations, rinfo, &path); if (!relation) { - relation = identityRelationNew(localIdent, remoteIdent, lchallenge, rchallenge); - r = ddsrt_hh_add(remoteIdent->linkHash, relation); - assert(r); - (void)r; + relation = identityRelationNew(linfo, rinfo, lchallenge, rchallenge); + (void)ddsrt_hh_add(impl->objectHash, relation); + ddsrt_avl_insert_ipath(&relations_treedef, &linfo->relations, relation, &path); } else { if (remote_auth_request_token) { assert(rchallenge); @@ -1465,9 +1392,9 @@ validate_remote_identity( DDS_Security_set_token_nil(local_auth_request_token); } - *remote_identity_handle = IDENTITY_HANDLE(remoteIdent);; + *remote_identity_handle = IDENTITY_HANDLE(relation); - if (memcmp(&localIdent->adjustedGUID, &remoteIdent->guid, sizeof(DDS_Security_GUID_t)) < 0) { + if (memcmp(&linfo->adjustedGUID, &rinfo->guid, sizeof(DDS_Security_GUID_t)) < 0) { result = DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_REQUEST; } else { result = DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE; @@ -1502,8 +1429,7 @@ begin_handshake_request( HandshakeInfo *handshake = NULL; IdentityRelation *relation = NULL; SecurityObject *obj; - LocalIdentityInfo *localIdent; - RemoteIdentityInfo *remoteIdent; + LocalIdentityInfo *linfo; EVP_PKEY *dhkey; DDS_Security_BinaryProperty_t *tokens; DDS_Security_BinaryProperty_t *c_id; @@ -1534,50 +1460,47 @@ begin_handshake_request( "begin_handshake_request: Invalid initiator_identity_handle provided"); goto err_inv_handle; } - localIdent = (LocalIdentityInfo *) obj; + linfo = (LocalIdentityInfo *) obj; obj = security_object_find(impl->objectHash, replier_identity_handle); - if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_REMOTE_IDENTITY)) { + if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_IDENTITY_RELATION)) { DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_request: Invalid replier_identity_handle provided"); goto err_inv_handle; } - remoteIdent = (RemoteIdentityInfo *)obj; + relation = (IdentityRelation *)obj; + handshake = relation->handshake; - result = get_certificate_contents(localIdent->identityCert, &certData, &certDataSize, ex); + result = get_certificate_contents(linfo->identityCert, &certData, &certDataSize, ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_alloc_cid; } - handshake = find_handshake(impl, SECURITY_OBJECT_HANDLE(localIdent), SECURITY_OBJECT_HANDLE(remoteIdent)); if (!handshake) { - relation = find_identity_relation(remoteIdent, SECURITY_OBJECT_HANDLE(localIdent)); - assert(relation); - handshake = handshakeInfoNew(localIdent, remoteIdent, relation); + handshake = handshakeInfoNew(relation); handshake->created_in = CREATEDREQUEST; - (void)ddsrt_hh_add(impl->objectHash, handshake); + relation->handshake = handshake; + (void)ddsrt_hh_add(impl->handshakes, handshake); created = 1; - } else { - relation = handshake->relation; - assert(relation); } + assert(handshake->relation == relation); + if (!handshake->ldh) { - result = generate_dh_keys(&dhkey, localIdent->kagreeAlgoKind, ex); + result = generate_dh_keys(&dhkey, linfo->kagreeAlgoKind, ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_gen_dh_keys; } - handshake->ldh = dhkey; } - result = dh_public_key_to_oct(handshake->ldh, localIdent->kagreeAlgoKind, &dhPubKeyData, &dhPubKeyDataSize, ex); + result = dh_public_key_to_oct(handshake->ldh, linfo->kagreeAlgoKind, &dhPubKeyData, &dhPubKeyDataSize, ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_get_public_key; } - if (localIdent->pdata._length == 0) { - DDS_Security_OctetSeq_copy(&localIdent->pdata, serialized_local_participant_data); + if (linfo->pdata._length == 0) { + DDS_Security_OctetSeq_copy(&linfo->pdata, serialized_local_participant_data); } tokens = DDS_Security_BinaryPropertySeq_allocbuf(8); @@ -1594,8 +1517,8 @@ begin_handshake_request( DDS_Security_BinaryProperty_set_by_ref(c_id, "c.id", certData, certDataSize); /* Store the permission document in the c.perm property */ - if (localIdent->permissionsDocument) { - DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", localIdent->permissionsDocument); + if (linfo->permissionsDocument) { + DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", linfo->permissionsDocument); } else { DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", ""); } @@ -1604,10 +1527,10 @@ begin_handshake_request( DDS_Security_BinaryProperty_set_by_value(c_pdata, "c.pdata", serialized_local_participant_data->_buffer, serialized_local_participant_data->_length); /* Set the used signing algorithm descriptor in c.dsign_algo */ - DDS_Security_BinaryProperty_set_by_string(c_dsign_algo, "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); + DDS_Security_BinaryProperty_set_by_string(c_dsign_algo, "c.dsign_algo", get_dsign_algo(linfo->dsignAlgoKind)); /* Set the used key algorithm descriptor in c.kagree_algo */ - DDS_Security_BinaryProperty_set_by_string(c_kagree_algo, "c.kagree_algo", get_kagree_algo(localIdent->kagreeAlgoKind)); + DDS_Security_BinaryProperty_set_by_string(c_kagree_algo, "c.kagree_algo", get_kagree_algo(linfo->kagreeAlgoKind)); /* Calculate the hash_c1 */ { @@ -1628,8 +1551,6 @@ begin_handshake_request( /* Set the challenge in challenge1 property */ DDS_Security_BinaryProperty_set_by_value(challenge, "challenge1", relation->lchallenge->value, sizeof(AuthenticationChallenge)); - (void)ddsrt_hh_add(impl->objectHash, handshake); - ddsrt_mutex_unlock(&impl->lock); handshake_message->class_id = ddsrt_strdup(AUTH_HANDSHAKE_REQUEST_TOKEN_ID); @@ -1644,8 +1565,8 @@ begin_handshake_request( err_get_public_key: err_gen_dh_keys: if (created) { - (void)ddsrt_hh_remove(impl->objectHash, handshake); - security_object_free((SecurityObject *)handshake); + (void)ddsrt_hh_remove(impl->handshakes, handshake); + handshakeInfoFree(handshake); } err_alloc_cid: ddsrt_free(certData); @@ -2503,8 +2424,8 @@ begin_handshake_reply( HandshakeInfo *handshake = NULL; IdentityRelation *relation = NULL; SecurityObject *obj; - LocalIdentityInfo *localIdent; - RemoteIdentityInfo *remoteIdent; + LocalIdentityInfo *linfo; + RemoteIdentityInfo *rinfo; EVP_PKEY *dhkeyLocal = NULL; DDS_Security_BinaryProperty_t *tokens; DDS_Security_BinaryProperty_t *c_id; @@ -2548,41 +2469,40 @@ begin_handshake_reply( "begin_handshake_reply: Invalid replier_identity_handle provided"); goto err_inv_handle; } - localIdent = (LocalIdentityInfo *) obj; + linfo = (LocalIdentityInfo *) obj; obj = security_object_find(impl->objectHash, initiator_identity_handle); - if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_REMOTE_IDENTITY)) { + if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_IDENTITY_RELATION)) { DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: Invalid initiator_identity_handle provided"); goto err_inv_handle; } - remoteIdent = (RemoteIdentityInfo *)obj; + relation = (IdentityRelation *)obj; + rinfo = relation->remoteIdentity; + handshake = relation->handshake; - handshake = find_handshake(impl, SECURITY_OBJECT_HANDLE(localIdent), SECURITY_OBJECT_HANDLE(remoteIdent)); if (!handshake) { - relation = find_identity_relation(remoteIdent, SECURITY_OBJECT_HANDLE(localIdent)); - assert(relation); - handshake = handshakeInfoNew(localIdent, remoteIdent, relation); + handshake = handshakeInfoNew(relation); + relation->handshake = handshake; handshake->created_in = CREATEDREPLY; - (void)ddsrt_hh_add(impl->objectHash, handshake); + (void)ddsrt_hh_add(impl->handshakes, handshake); created = 1; - } else { - relation = handshake->relation; - assert(relation); } + assert(handshake->relation == relation); + result = validate_handshake_request_token(handshake_message_in, handshake, &(impl->trustedCAList), ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_inv_token; } - result = get_certificate_contents(localIdent->identityCert, &certData, &certDataSize, ex); + result = get_certificate_contents(linfo->identityCert, &certData, &certDataSize, ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_alloc_cid; } if (!handshake->ldh) { - result = generate_dh_keys(&dhkeyLocal, remoteIdent->kagreeAlgoKind, ex); + result = generate_dh_keys(&dhkeyLocal, rinfo->kagreeAlgoKind, ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_gen_dh_keys; } @@ -2591,13 +2511,13 @@ begin_handshake_reply( EVP_PKEY_copy_parameters(handshake->rdh, handshake->ldh); } - result = dh_public_key_to_oct(handshake->ldh, remoteIdent->kagreeAlgoKind, &dhPubKeyData, &dhPubKeyDataSize, ex); + result = dh_public_key_to_oct(handshake->ldh, rinfo->kagreeAlgoKind, &dhPubKeyData, &dhPubKeyDataSize, ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_get_public_key; } - if (localIdent->pdata._length == 0) { - DDS_Security_OctetSeq_copy(&localIdent->pdata, serialized_local_participant_data); + if (linfo->pdata._length == 0) { + DDS_Security_OctetSeq_copy(&linfo->pdata, serialized_local_participant_data); } hash_c1_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "hash_c1"); @@ -2623,8 +2543,8 @@ begin_handshake_reply( certData = NULL; /* Store the permission document in the c.perm property */ - if (localIdent->permissionsDocument) { - DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", localIdent->permissionsDocument); + if (linfo->permissionsDocument) { + DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", linfo->permissionsDocument); } else { DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", ""); } @@ -2633,10 +2553,10 @@ begin_handshake_reply( DDS_Security_BinaryProperty_set_by_value(c_pdata, "c.pdata", serialized_local_participant_data->_buffer, serialized_local_participant_data->_length); /* Set the used signing algorithm descriptor in c.dsign_algo */ - DDS_Security_BinaryProperty_set_by_string(c_dsign_algo, "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); + DDS_Security_BinaryProperty_set_by_string(c_dsign_algo, "c.dsign_algo", get_dsign_algo(linfo->dsignAlgoKind)); /* Set the used key algorithm descriptor in c.kagree_algo */ - DDS_Security_BinaryProperty_set_by_string(c_kagree_algo, "c.kagree_algo", get_kagree_algo(remoteIdent->kagreeAlgoKind)); + DDS_Security_BinaryProperty_set_by_string(c_kagree_algo, "c.kagree_algo", get_kagree_algo(rinfo->kagreeAlgoKind)); /* Calculate the hash_c2 */ { @@ -2689,7 +2609,7 @@ begin_handshake_reply( binary_properties[4] = dh1; binary_properties[5] = hash_c1_val; - result = create_signature(localIdent->privateKey, binary_properties, HANDSHAKE_SIGNATURE_CONTENT_SIZE , &sign, &signlen, ex); + result = create_signature(linfo->privateKey, binary_properties, HANDSHAKE_SIGNATURE_CONTENT_SIZE , &sign, &signlen, ex); DDS_Security_BinaryProperty_free(hash_c1_val); DDS_Security_BinaryProperty_free(hash_c2_val); @@ -2700,15 +2620,12 @@ begin_handshake_reply( DDS_Security_BinaryProperty_set_by_ref(signature, "signature", sign, (uint32_t)signlen); } - (void)ddsrt_hh_add(impl->objectHash, handshake); - handshake_message_out->class_id = ddsrt_strdup(AUTH_HANDSHAKE_REPLY_TOKEN_ID); handshake_message_out->binary_properties._length = tokenSize; handshake_message_out->binary_properties._buffer = tokens; ddsrt_mutex_unlock(&impl->lock); - *handshake_handle = HANDSHAKE_HANDLE(handshake); if (result == DDS_SECURITY_VALIDATION_OK) { @@ -2725,8 +2642,8 @@ err_gen_dh_keys: err_alloc_cid: err_inv_token: if (created) { - (void)ddsrt_hh_remove(impl->objectHash, handshake); - security_object_free((SecurityObject *)handshake); + (void)ddsrt_hh_remove(impl->handshakes, handshake); + handshakeInfoFree(handshake); } err_inv_handle: ddsrt_mutex_unlock(&impl->lock); @@ -2734,7 +2651,6 @@ err_bad_param: return DDS_SECURITY_VALIDATION_FAILED; } - static bool generate_shared_secret( const HandshakeInfo *handshake, @@ -2800,9 +2716,6 @@ fail_ctx_new: return result; } - - - DDS_Security_ValidationResult_t process_handshake( dds_security_authentication *instance, @@ -2846,7 +2759,7 @@ process_handshake( ddsrt_mutex_lock(&impl->lock); - obj = security_object_find(impl->objectHash, handshake_handle); + obj = security_object_find(impl->handshakes, handshake_handle); if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_HANDSHAKE)) { DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, @@ -2934,7 +2847,6 @@ process_handshake( challenge2_ref->value._length); } - /* Calculate the signature */ { const DDS_Security_BinaryProperty_t * binary_properties[ HANDSHAKE_SIGNATURE_CONTENT_SIZE ]; @@ -2983,12 +2895,10 @@ process_handshake( goto err_inv_token; } - challenge2_ref_for_shared_secret = (DDS_Security_octet*)(handshake->relation->lchallenge); challenge1_ref_for_shared_secret = (DDS_Security_octet*)(handshake->relation->rchallenge); result = DDS_SECURITY_VALIDATION_OK; - break; default: ddsrt_mutex_unlock(&impl->lock); @@ -3021,10 +2931,9 @@ process_handshake( goto err_invalid_expiry; } else if( certExpiry != DDS_NEVER ){ add_validity_end_trigger( impl, - IDENTITY_HANDLE( handshake->relation->remoteIdentity ), + IDENTITY_HANDLE( handshake->relation ), certExpiry); } - } ddsrt_mutex_unlock(&impl->lock); @@ -3062,14 +2971,14 @@ DDS_Security_SharedSecretHandle get_shared_secret( } ddsrt_mutex_lock(&impl->lock); - obj = security_object_find(impl->objectHash, handshake_handle); + obj = security_object_find(impl->handshakes, handshake_handle); if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_HANDSHAKE)) { DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_handshake_handle: Invalid handle provided"); goto err_invalid_handle; } ddsrt_mutex_unlock(&impl->lock); - return (DDS_Security_SharedSecretHandle)(ddsrt_address)((HandshakeInfo*)obj)->shared_secret_handle_impl; + return (DDS_Security_SharedSecretHandle)(uintptr_t)((HandshakeInfo*)obj)->shared_secret_handle_impl; err_invalid_handle: @@ -3102,7 +3011,7 @@ get_authenticated_peer_credential_token( ddsrt_mutex_lock(&impl->lock); - handshake = (HandshakeInfo *) security_object_find(impl->objectHash, handshake_handle); + handshake = (HandshakeInfo *) security_object_find(impl->handshakes, handshake_handle); if (!handshake || !SECURITY_OBJECT_VALID(handshake, SECURITY_OBJECT_KIND_HANDSHAKE)) { DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, @@ -3227,18 +3136,15 @@ return_handshake_handle(dds_security_authentication *instance, } ddsrt_mutex_lock(&impl->lock); - obj = security_object_find(impl->objectHash, handshake_handle); + obj = security_object_find(impl->handshakes, handshake_handle); if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_HANDSHAKE)) { DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_handshake_handle: Invalid handle provided"); goto err_invalid_handle; } handshake = (HandshakeInfo *)obj; - assert(handshake->relation); - - (void)ddsrt_hh_remove(impl->objectHash, obj); - security_object_free((SecurityObject *)handshake); - + (void)ddsrt_hh_remove(impl->handshakes, handshake); + handshakeInfoFree(handshake); ddsrt_mutex_unlock(&impl->lock); return true; @@ -3249,56 +3155,63 @@ err_bad_param: return false; } +static void +release_remote_info( + dds_security_authentication_impl *impl, + RemoteIdentityInfo *info) +{ + if (--info->refc == 0) { + (void)ddsrt_hh_remove(impl->remoteGuidHash, info); + remoteIdentityInfoFree(info); + } +} static void invalidate_local_related_objects( dds_security_authentication_impl *impl, - LocalIdentityInfo *localIdent) + LocalIdentityInfo *linfo) { - struct ddsrt_hh_iter it; - SecurityObject *obj; + IdentityRelation *relation; - for (obj = ddsrt_hh_iter_first(impl->objectHash, &it); obj != NULL; obj = ddsrt_hh_iter_next(&it)) { - if (obj->kind == SECURITY_OBJECT_KIND_REMOTE_IDENTITY) { - RemoteIdentityInfo *remoteIdent = (RemoteIdentityInfo *)obj; - IdentityRelation *relation; - HandshakeInfo *handshake; + relation = ddsrt_avl_find_min(&relations_treedef, &linfo->relations); + while (relation) { + IdentityRelation *next = ddsrt_avl_find_succ(&relations_treedef, &linfo->relations, relation); - handshake = find_handshake(impl, SECURITY_OBJECT_HANDLE(localIdent), SECURITY_OBJECT_HANDLE(remoteIdent)); - if (handshake) { - (void)ddsrt_hh_remove(impl->objectHash, handshake); - security_object_free((SecurityObject *) handshake); - } + assert(relation->remoteIdentity); - relation = find_identity_relation(remoteIdent, SECURITY_OBJECT_HANDLE(localIdent)); - if (relation) { - remove_identity_relation(remoteIdent, relation); - } + if (relation->handshake) { + (void)ddsrt_hh_remove(impl->handshakes, relation->handshake); + handshakeInfoFree(relation->handshake); } + release_remote_info(impl, relation->remoteIdentity); + ddsrt_avl_delete(&relations_treedef, &linfo->relations, relation); + (void)ddsrt_hh_remove(impl->objectHash, relation); + identityRelationFree(relation); + relation = next; } + (void)ddsrt_hh_remove(impl->objectHash, linfo); + localIdentityInfoFree(linfo); } static void invalidate_remote_related_objects( dds_security_authentication_impl *impl, - RemoteIdentityInfo *remoteIdentity) + IdentityRelation *relation) { - struct ddsrt_hh_iter it; - IdentityRelation *relation; - HandshakeInfo *handshake; + assert(relation->remoteIdentity); + assert(relation->localIdentity); - for (relation = ddsrt_hh_iter_first(remoteIdentity->linkHash, &it); relation != NULL; relation = ddsrt_hh_iter_next(&it)) { - handshake = find_handshake(impl, SECURITY_OBJECT_HANDLE(relation->localIdentity), SECURITY_OBJECT_HANDLE(remoteIdentity)); - if (handshake) { - (void)ddsrt_hh_remove(impl->objectHash, handshake); - security_object_free((SecurityObject *) handshake); - } - - (void)ddsrt_hh_remove(remoteIdentity->linkHash, relation); - security_object_free((SecurityObject *) relation); + if (relation->handshake) { + (void)ddsrt_hh_remove(impl->handshakes, relation->handshake); + handshakeInfoFree(relation->handshake); } + release_remote_info(impl, relation->remoteIdentity); + ddsrt_avl_delete(&relations_treedef, &relation->localIdentity->relations, relation); + (void)ddsrt_hh_remove(impl->objectHash, relation); + identityRelationFree(relation); } + DDS_Security_boolean return_identity_handle( dds_security_authentication *instance, @@ -3308,8 +3221,8 @@ return_identity_handle( DDS_Security_boolean result = true; dds_security_authentication_impl *impl = (dds_security_authentication_impl *) instance; SecurityObject *obj; - LocalIdentityInfo *localIdent; - RemoteIdentityInfo *remoteIdent; + LocalIdentityInfo *linfo; + IdentityRelation *relation; /* validate provided arguments */ if (!instance || !identity_handle) { @@ -3332,17 +3245,12 @@ return_identity_handle( switch (obj->kind) { case SECURITY_OBJECT_KIND_LOCAL_IDENTITY: - localIdent = (LocalIdentityInfo *) obj; - invalidate_local_related_objects(impl, localIdent); - (void)ddsrt_hh_remove(impl->objectHash, obj); - security_object_free(obj); + linfo = (LocalIdentityInfo *) obj; + invalidate_local_related_objects(impl, linfo); break; - case SECURITY_OBJECT_KIND_REMOTE_IDENTITY: - remoteIdent = (RemoteIdentityInfo *) obj; - invalidate_remote_related_objects(impl, remoteIdent); - (void)ddsrt_hh_remove(impl->remoteGuidHash, remoteIdent); - (void)ddsrt_hh_remove(impl->objectHash, obj); - security_object_free(obj); + case SECURITY_OBJECT_KIND_IDENTITY_RELATION: + relation = (IdentityRelation *) obj; + invalidate_remote_related_objects(impl, relation); break; default: DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_identity_handle: Invalid handle provided"); @@ -3351,7 +3259,6 @@ return_identity_handle( } ddsrt_mutex_unlock(&impl->lock); - return result; err_invalid_handle: @@ -3372,10 +3279,8 @@ DDS_Security_boolean return_sharedsecret_handle( return true; } -int32_t -init_authentication( const char *argument, void **context) +int32_t init_authentication( const char *argument, void **context) { - dds_security_authentication_impl *authentication; DDSRT_UNUSED_ARG(argument); @@ -3391,51 +3296,31 @@ init_authentication( const char *argument, void **context) /* assign the interface functions */ authentication->base.validate_local_identity = &validate_local_identity; - authentication->base.get_identity_token = &get_identity_token; - authentication->base.get_identity_status_token = &get_identity_status_token; - - authentication->base.set_permissions_credential_and_token = - &set_permissions_credential_and_token; - + authentication->base.set_permissions_credential_and_token = &set_permissions_credential_and_token; authentication->base.validate_remote_identity = &validate_remote_identity; - authentication->base.begin_handshake_request = &begin_handshake_request; - authentication->base.begin_handshake_reply = &begin_handshake_reply; - authentication->base.process_handshake = &process_handshake; - authentication->base.get_shared_secret = &get_shared_secret; - - authentication->base.get_authenticated_peer_credential_token = - &get_authenticated_peer_credential_token; - + authentication->base.get_authenticated_peer_credential_token = &get_authenticated_peer_credential_token; authentication->base.set_listener = &set_listener; - authentication->base.return_identity_token = &return_identity_token; - - authentication->base.return_identity_status_token = - &return_identity_status_token; - - authentication->base.return_authenticated_peer_credential_token = - &return_authenticated_peer_credential_token; - + authentication->base.return_identity_status_token = &return_identity_status_token; + authentication->base.return_authenticated_peer_credential_token = &return_authenticated_peer_credential_token; authentication->base.return_handshake_handle = &return_handshake_handle; - authentication->base.return_identity_handle = &return_identity_handle; - authentication->base.return_sharedsecret_handle = &return_sharedsecret_handle; ddsrt_mutex_init(&authentication->lock); authentication->objectHash = ddsrt_hh_new(32, security_object_hash, security_object_equal); authentication->remoteGuidHash = ddsrt_hh_new(32, remote_guid_hash, remote_guid_equal); + authentication->handshakes = ddsrt_hh_new(32, security_object_hash, security_object_equal); memset( &authentication->trustedCAList, 0, sizeof(X509Seq)); - /* Initialize openssl */ OpenSSL_add_all_algorithms(); OpenSSL_add_all_ciphers(); @@ -3458,6 +3343,8 @@ err_mutex_failed: int32_t finalize_authentication(void *instance) { dds_security_authentication_impl *authentication = instance; + LocalIdentityInfo *linfo; + IdentityRelation *relation; if( authentication ){ ddsrt_mutex_lock(&authentication->lock); @@ -3465,25 +3352,37 @@ int32_t finalize_authentication(void *instance) dds_security_timed_dispatcher_free(authentication->timed_callbacks, authentication->dispatcher); dds_security_timed_cb_free(authentication->timed_callbacks); - if (authentication->remoteGuidHash) { - ddsrt_hh_free(authentication->remoteGuidHash); - } - if (authentication->objectHash) { struct ddsrt_hh_iter it; SecurityObject *obj; for (obj = ddsrt_hh_iter_first(authentication->objectHash, &it); obj != NULL; obj = ddsrt_hh_iter_next(&it)) { - security_object_free(obj); + switch (obj->kind) { + case SECURITY_OBJECT_KIND_LOCAL_IDENTITY: + linfo = (LocalIdentityInfo *) obj; + invalidate_local_related_objects(authentication, linfo); + break; + case SECURITY_OBJECT_KIND_IDENTITY_RELATION: + relation = (IdentityRelation *) obj; + invalidate_remote_related_objects(authentication, relation); + break; + default: + break; + } } ddsrt_hh_free(authentication->objectHash); } + if (authentication->remoteGuidHash) { + ddsrt_hh_free(authentication->remoteGuidHash); + } + + if (authentication->handshakes) { + ddsrt_hh_free(authentication->handshakes); + } + free_ca_list_contents(&(authentication->trustedCAList)); - ddsrt_mutex_unlock(&authentication->lock); - ddsrt_mutex_destroy(&authentication->lock); - ddsrt_free((dds_security_authentication_impl*) instance); } From 0d3ca448ff486397224e01dcbdcacca1babbe3af Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 12 Feb 2020 20:15:49 +0100 Subject: [PATCH 097/238] Liveliness monitoring fixes for security FSM Signed-off-by: Erik Boasson --- src/security/core/src/dds_security_fsm.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/security/core/src/dds_security_fsm.c b/src/security/core/src/dds_security_fsm.c index 8413575..ce1a2bb 100644 --- a/src/security/core/src/dds_security_fsm.c +++ b/src/security/core/src/dds_security_fsm.c @@ -179,7 +179,7 @@ static void fsm_check_auto_state_change (struct dds_security_fsm *fsm) } } -static void fsm_state_change (struct dds_security_fsm_control *control, struct fsm_event *event) +static void fsm_state_change (struct thread_state1 *ts1, struct dds_security_fsm_control *control, struct fsm_event *event) { struct dds_security_fsm *fsm = event->fsm; int event_id = event->event_id; @@ -199,10 +199,14 @@ static void fsm_state_change (struct dds_security_fsm_control *control, struct f set_state_timer (fsm); ddsrt_mutex_unlock (&control->lock); + + thread_state_asleep (ts1); if (fsm->transitions[i].func) fsm->transitions[i].func (fsm, fsm->arg); if (fsm->current && fsm->current->func) fsm->current->func (fsm, fsm->arg); + + thread_state_awake (ts1, control->gv); ddsrt_mutex_lock (&control->lock); fsm_check_auto_state_change (fsm); break; @@ -241,9 +245,8 @@ static void fsm_handle_timeout (struct dds_security_fsm_control *control, struct static uint32_t handle_events (struct dds_security_fsm_control *control) { struct thread_state1 * const ts1 = lookup_thread_state (); - - ddsrt_mutex_lock (&control->lock); thread_state_awake (ts1, control->gv); + ddsrt_mutex_lock (&control->lock); while (control->running) { if (control->event_queue) @@ -253,7 +256,7 @@ static uint32_t handle_events (struct dds_security_fsm_control *control) control->event_queue = event->next; if (control->event_queue) control->event_queue->prev = NULL; - fsm_state_change (control, event); + fsm_state_change (ts1, control, event); ddsrt_free (event); } else @@ -263,7 +266,7 @@ static uint32_t handle_events (struct dds_security_fsm_control *control) if (timeout > dds_time ()) { thread_state_asleep (ts1); - (void)ddsrt_cond_waituntil( &control->cond, &control->lock, timeout); + (void)ddsrt_cond_waituntil (&control->cond, &control->lock, timeout); thread_state_awake (ts1, control->gv); } else @@ -273,9 +276,8 @@ static uint32_t handle_events (struct dds_security_fsm_control *control) } } } - thread_state_asleep (ts1); ddsrt_mutex_unlock (&control->lock); - + thread_state_asleep (ts1); return 0; } From 9b43303d82e3dc7f9534708b9414c517fd293f41 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 13 Feb 2020 11:48:10 +0100 Subject: [PATCH 098/238] Remove unused "kernel sequence numbers" notion The flag originates in OpenSplice but is meaningless in Cyclone. Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_entity.h | 9 +++------ src/core/ddsi/src/q_ddsi_discovery.c | 3 --- src/core/ddsi/src/q_entity.c | 15 ++------------- 3 files changed, 5 insertions(+), 22 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 3623888..306029b 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -358,7 +358,6 @@ struct proxy_participant struct proxy_endpoint_common *endpoints; /* all proxy endpoints can be reached from here */ ddsrt_avl_tree_t groups; /* table of all groups (publisher, subscriber), see struct proxy_group */ seqno_t seq; /* sequence number of most recent SPDP message */ - unsigned kernel_sequence_numbers : 1; /* whether this proxy participant generates OSPL kernel sequence numbers */ unsigned implicitly_created : 1; /* participants are implicitly created for Cloud/Fog discovered endpoints */ unsigned is_ddsi2_pp: 1; /* if this is the federation-leader on the remote node */ unsigned minimal_bes_mode: 1; @@ -665,19 +664,17 @@ int writer_set_notalive (struct writer *wr, bool notify); XX -- */ -/* Set this custom flag when using nn_prismtech_writer_info_t iso nn_prismtech_writer_info_old_t */ -#define CF_INC_KERNEL_SEQUENCE_NUMBERS (1 << 0) /* Set when this proxy participant is created implicitly and has to be deleted upon disappearance of its last endpoint. FIXME: Currently there is a potential race with adding a new endpoint in parallel to deleting the last remaining one. The endpoint will then be created, added to the proxy participant and then both are deleted. With the current single-threaded discovery this can only happen when it is all triggered by lease expiry. */ -#define CF_IMPLICITLY_CREATED_PROXYPP (1 << 1) +#define CF_IMPLICITLY_CREATED_PROXYPP (1 << 0) /* Set when this proxy participant is a DDSI2 participant, to help Cloud figure out whom to send discovery data when used in conjunction with the networking bridge */ -#define CF_PARTICIPANT_IS_DDSI2 (1 << 2) +#define CF_PARTICIPANT_IS_DDSI2 (1 << 1) /* Set when this proxy participant is not to be announced on the built-in topics yet */ -#define CF_PROXYPP_NO_SPDP (1 << 3) +#define CF_PROXYPP_NO_SPDP (1 << 2) void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct ddsi_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, nn_wctime_t timestamp, seqno_t seq); int delete_proxy_participant_by_guid (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, nn_wctime_t timestamp, int isimplicit); diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 8877242..fb3f671 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -657,9 +657,6 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_ } if (datap->present & PP_PRISMTECH_PARTICIPANT_VERSION_INFO) { - if (datap->prismtech_participant_version_info.flags & NN_PRISMTECH_FL_KERNEL_SEQUENCE_NUMBER) - custom_flags |= CF_INC_KERNEL_SEQUENCE_NUMBERS; - if ((datap->prismtech_participant_version_info.flags & NN_PRISMTECH_FL_DDSI2_PARTICIPANT_FLAG) && (datap->prismtech_participant_version_info.flags & NN_PRISMTECH_FL_PARTICIPANT_IS_DDSI2)) custom_flags |= CF_PARTICIPANT_IS_DDSI2; diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index cf49032..39cc797 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -4827,6 +4827,8 @@ void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *pp proxypp->minimal_bes_mode = 1; else proxypp->minimal_bes_mode = 0; + proxypp->implicitly_created = ((custom_flags & CF_IMPLICITLY_CREATED_PROXYPP) != 0); + proxypp->proxypp_have_spdp = ((custom_flags & CF_PROXYPP_NO_SPDP) == 0); { struct proxy_participant *privpp; @@ -4889,19 +4891,6 @@ void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *pp set_proxy_participant_security_info(proxypp, plist); #endif - if (custom_flags & CF_INC_KERNEL_SEQUENCE_NUMBERS) - proxypp->kernel_sequence_numbers = 1; - else - proxypp->kernel_sequence_numbers = 0; - if (custom_flags & CF_IMPLICITLY_CREATED_PROXYPP) - proxypp->implicitly_created = 1; - else - proxypp->implicitly_created = 0; - - if (custom_flags & CF_PROXYPP_NO_SPDP) - proxypp->proxypp_have_spdp = 0; - else - proxypp->proxypp_have_spdp = 1; #ifdef DDSI_INCLUDE_SECURITY if (secure) From 62a6004e8a9e1ab4aa4fe9a9e8249f14bd42d19d Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 13 Feb 2020 11:52:52 +0100 Subject: [PATCH 099/238] Remove "CM" topic related flags reintroduced by merge Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_protocol.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_protocol.h b/src/core/ddsi/include/dds/ddsi/q_protocol.h index 1ffb559..b03d0ea 100644 --- a/src/core/ddsi/include/dds/ddsi/q_protocol.h +++ b/src/core/ddsi/include/dds/ddsi/q_protocol.h @@ -103,13 +103,6 @@ typedef struct { #define NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_ANNOUNCER (1u << 26) #define NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_DETECTOR (1u << 27) -/* PrismTech extensions: */ -#define NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_WRITER (1u << 0) -#define NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_READER (1u << 1) -#define NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_WRITER (1u << 2) -#define NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_READER (1u << 3) -#define NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_WRITER (1u << 4) -#define NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_READER (1u << 5) #define NN_LOCATOR_KIND_INVALID -1 #define NN_LOCATOR_KIND_RESERVED 0 From 4ed01285789c4ae95badb4426ef221c1c16d17d7 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 13 Feb 2020 11:54:21 +0100 Subject: [PATCH 100/238] Rework security code in proxy participant creation Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_protocol.h | 1 + src/core/ddsi/src/q_ddsi_discovery.c | 11 ++- src/core/ddsi/src/q_entity.c | 97 +++++++-------------- 3 files changed, 43 insertions(+), 66 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_protocol.h b/src/core/ddsi/include/dds/ddsi/q_protocol.h index b03d0ea..bc86f7c 100644 --- a/src/core/ddsi/include/dds/ddsi/q_protocol.h +++ b/src/core/ddsi/include/dds/ddsi/q_protocol.h @@ -103,6 +103,7 @@ typedef struct { #define NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_ANNOUNCER (1u << 26) #define NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_DETECTOR (1u << 27) +#define NN_BES_MASK_NON_SECURITY 0xf000ffffu #define NN_LOCATOR_KIND_INVALID -1 #define NN_LOCATOR_KIND_RESERVED 0 diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index fb3f671..05cdea6 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -644,7 +644,16 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, nn_ } } - GVLOGDISC ("SPDP ST0 "PGUIDFMT" bes %x NEW", PGUID (datap->participant_guid), builtin_endpoint_set); + const bool is_secure = (datap->builtin_endpoint_set & NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_ANNOUNCER) != 0; + /* Make sure we don't create any security builtin endpoint when it's considered unsecure. */ + if (!is_secure) + builtin_endpoint_set &= NN_BES_MASK_NON_SECURITY; + GVLOGDISC ("SPDP ST0 "PGUIDFMT" bes %x%s NEW", PGUID (datap->participant_guid), builtin_endpoint_set, is_secure ? " (secure)" : ""); + if (is_secure && !(datap->present & PP_IDENTITY_TOKEN)) + { + GVLOGDISC (" identity token missing\n"); + return 0; + } if (datap->present & PP_PARTICIPANT_LEASE_DURATION) { diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 39cc797..72df23f 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -109,8 +109,6 @@ static void unref_participant (struct participant *pp, const struct ddsi_guid *g static struct entity_common *entity_common_from_proxy_endpoint_common (const struct proxy_endpoint_common *c); #ifdef DDSI_INCLUDE_SECURITY -static const unsigned BES_MASK_NON_SECURITY = 0xf000ffff; - static void handshake_end_cb(struct ddsi_domaingv const * const gv, struct ddsi_handshake *handshake, const struct ddsi_guid *lpguid, const struct ddsi_guid *ppguid, enum ddsi_handshake_state result); static void downgrade_to_nonsecure(struct proxy_participant *proxypp); #endif @@ -4572,17 +4570,6 @@ static void add_proxy_builtin_endpoints( &gv->builtin_stateless_xqos_rd); #endif - /* write DCPSParticipant topic before the lease can expire */ - builtintopic_write (gv->builtin_topic_interface, &proxypp->e, timestamp, true); - - /* Register lease for auto liveliness, but be careful not to accidentally re-register - DDSI2's lease, as we may have become dependent on DDSI2 any time after - entidx_insert_proxy_participant_guid even if privileged_pp_guid was NULL originally */ - ddsrt_mutex_lock (&proxypp->e.lock); - if (proxypp->owns_lease) - lease_register (ddsrt_atomic_ldvoidp (&proxypp->minl_auto)); - ddsrt_mutex_unlock (&proxypp->e.lock); - #undef PT_TE #undef TE #undef LTE @@ -4770,6 +4757,9 @@ static void free_proxy_participant(struct proxy_participant *proxypp) assert (ddsrt_fibheap_min (&lease_fhdef_pp, &proxypp->leaseheap_man) == NULL); assert (ddsrt_atomic_ldvoidp (&proxypp->minl_man) == NULL); assert (!compare_guid (&minl_auto->entity->guid, &proxypp->e.guid)); + /* if the lease hasn't been registered yet (which is the case when + new_proxy_participant calls this, it is marked as such and calling + lease_unregister is ok */ lease_unregister (minl_auto); lease_free (minl_auto); lease_free (proxypp->lease); @@ -4791,9 +4781,9 @@ void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *pp runs on a single thread, it can't go wrong. FIXME, maybe? The same holds for the other functions for creating entities. */ struct proxy_participant *proxypp; -#ifdef DDSI_INCLUDE_SECURITY - bool secure = false; -#endif + const bool is_secure = ((bes & NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_ANNOUNCER) != 0); + assert (!is_secure || (plist->present & PP_IDENTITY_TOKEN)); + assert (is_secure || (bes & ~NN_BES_MASK_NON_SECURITY) == 0); assert (ppguid->entityid.u == NN_ENTITYID_PARTICIPANT); assert (entidx_lookup_proxy_participant_guid (gv->entity_index, ppguid) == NULL); @@ -4882,61 +4872,38 @@ void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *pp #ifdef DDSI_INCLUDE_SECURITY proxypp->remote_identity_handle = 0; proxypp->sec_attr = NULL; - secure = ((bes & NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_ANNOUNCER) != 0); - if (!secure) + set_proxy_participant_security_info (proxypp, plist); + if (is_secure) { - /* Make sure we don't create any security builtin endpoint when it's considered unsecure. */ - proxypp->bes &= BES_MASK_NON_SECURITY; + q_omg_security_init_remote_participant (proxypp); + /* check if the proxy participant has a match with a local participant */ + if (!proxy_participant_check_security_info (gv, proxypp)) + { + GVWARNING ("Remote secure participant "PGUIDFMT" not allowed\n", PGUID (*ppguid)); + free_proxy_participant (proxypp); + return; + } } - set_proxy_participant_security_info(proxypp, plist); #endif - -#ifdef DDSI_INCLUDE_SECURITY - if (secure) - { - /* Secure participant detected: start handshake. */ - if ((plist->present & PP_IDENTITY_TOKEN)) - { - /* initialize the security attributes associated with the proxy participant */ - q_omg_security_init_remote_participant(proxypp); - - /* check if the proxy participant has a match with a local participant */ - if (proxy_participant_check_security_info(gv, proxypp)) - { - /* Proxy participant must be in the hash tables for new_proxy_{writer,reader} to work */ - entidx_insert_proxy_participant_guid (gv->entity_index, proxypp); - /* Create builtin endpoints, of which a few are used in the handshake. */ - add_proxy_builtin_endpoints(gv, ppguid, proxypp, timestamp); - /* create authentication handshakes for each local secure participant */ - proxy_participant_create_handshakes(gv, proxypp); - } - else - { - DDS_CWARNING(&gv->logconfig, "Remote secure participant "PGUIDFMT" not allowed\n", PGUID (*ppguid)); - free_proxy_participant(proxypp); - } - } - else - { - /* Do not communicate with un-secure participants. */ - DDS_CWARNING(&gv->logconfig, "Don't communicate with secure participant "PGUIDFMT" which does not provide an identity token\n", PGUID (*ppguid)); - free_proxy_participant(proxypp); - } - } - else - { - /* Remote is un-secure. Try the discovery anyway. Maybe there's a local secure - * participant that allowed communication with remote non-secure ones - */ - entidx_insert_proxy_participant_guid (gv->entity_index, proxypp); - add_proxy_builtin_endpoints(gv, ppguid, proxypp, timestamp); - ELOGDISC (proxypp, "Un-secure participant "PGUIDFMT" tries to connect.\n", PGUID (*ppguid)); - } -#else /* Proxy participant must be in the hash tables for new_proxy_{writer,reader} to work */ entidx_insert_proxy_participant_guid (gv->entity_index, proxypp); add_proxy_builtin_endpoints(gv, ppguid, proxypp, timestamp); + + /* write DCPSParticipant topic before the lease can expire */ + builtintopic_write (gv->builtin_topic_interface, &proxypp->e, timestamp, true); + + /* Register lease for auto liveliness, but be careful not to accidentally re-register + DDSI2's lease, as we may have become dependent on DDSI2 any time after + entidx_insert_proxy_participant_guid even if privileged_pp_guid was NULL originally */ + ddsrt_mutex_lock (&proxypp->e.lock); + if (proxypp->owns_lease) + lease_register (ddsrt_atomic_ldvoidp (&proxypp->minl_auto)); + ddsrt_mutex_unlock (&proxypp->e.lock); + +#ifdef DDSI_INCLUDE_SECURITY + if (is_secure) + proxy_participant_create_handshakes (gv, proxypp); #endif } @@ -5184,7 +5151,7 @@ static void downgrade_to_nonsecure(struct proxy_participant *proxypp) /* Cleanup all kinds of related security information. */ q_omg_security_deregister_remote_participant(proxypp); - proxypp->bes &= BES_MASK_NON_SECURITY; + proxypp->bes &= NN_BES_MASK_NON_SECURITY; } #endif From e0a9beb3cb73de55a87c404595a2c72498039537 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 24 Feb 2020 13:11:52 +0100 Subject: [PATCH 101/238] Fix condition for validating topic access rules Signed-off-by: Erik Boasson --- .../builtin_plugins/access_control/src/access_control_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/security/builtin_plugins/access_control/src/access_control_parser.c b/src/security/builtin_plugins/access_control/src/access_control_parser.c index 5f1cf2d..fbf106c 100644 --- a/src/security/builtin_plugins/access_control/src/access_control_parser.c +++ b/src/security/builtin_plugins/access_control/src/access_control_parser.c @@ -419,7 +419,7 @@ static DDS_Security_boolean validate_rules(const struct domain_rule *rule, DDS_S { /* Last but not least, check the domain ids (ex is set when there's a failure) */ validate_domains(rule->domains->domain_id_set, ex); - if (!rule->topic_access_rules && rule->topic_access_rules->topic_rule) + if (!(rule->topic_access_rules && rule->topic_access_rules->topic_rule)) DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE, 0, "Found rule in Governance file without topic_access_rules"); else { From 0d5a8bf4611326987816cc00346dc4fdf449e0ec Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 24 Feb 2020 13:12:39 +0100 Subject: [PATCH 102/238] Remove built-in crypto plugin unused variables Signed-off-by: Erik Boasson --- .../cryptographic/src/crypto_transform.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_transform.c b/src/security/builtin_plugins/cryptographic/src/crypto_transform.c index f27ea24..0088f94 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_transform.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_transform.c @@ -1082,7 +1082,6 @@ encode_datawriter_submessage_encrypt ( struct submsg_header *prefix; struct crypto_header *header; struct submsg_header *postfix; - struct submsg_header *body; struct crypto_footer *footer; uint32_t transform_kind, transform_id; DDS_Security_boolean result = false; @@ -1147,7 +1146,7 @@ encode_datawriter_submessage_encrypt ( goto enc_dw_submsg_fail; /* add SEC_BODY submessage */ - body = add_submessage(&data, SMID_SEC_BODY_KIND, flags, submsg_len); + struct submsg_header *body = add_submessage(&data, SMID_SEC_BODY_KIND, flags, submsg_len); encrypted = (struct encrypted_data *)(body + 1); contents = encrypted->data; @@ -1171,7 +1170,6 @@ encode_datawriter_submessage_encrypt ( goto enc_dw_submsg_fail; /* copy submessage */ - body = (struct submsg_header *)contents; memcpy(contents, plain_submsg->_buffer, plain_submsg->_length); payload_len = plain_submsg->_length; data._length += payload_len; @@ -1319,7 +1317,6 @@ encode_datareader_submessage( struct submsg_header *prefix; struct crypto_header *header; struct submsg_header *postfix; - struct submsg_header *body; struct crypto_footer *footer; session_key_material *session = NULL; DDS_Security_ProtectionKind protection_kind; @@ -1404,7 +1401,7 @@ encode_datareader_submessage( goto enc_dr_submsg_fail; /* add SEC_BODY submessage */ - body = add_submessage(&data, SMID_SEC_BODY_KIND, flags, submsg_len); + struct submsg_header *body = add_submessage(&data, SMID_SEC_BODY_KIND, flags, submsg_len); encrypted = (struct encrypted_data *)(body + 1); contents = encrypted->data; @@ -1428,7 +1425,6 @@ encode_datareader_submessage( goto enc_dr_submsg_fail; /* copy submessage */ - body = (struct submsg_header *)contents; memcpy(contents, plain_submsg->_buffer, plain_submsg->_length); payload_len = plain_submsg->_length; data._length += payload_len; @@ -1540,8 +1536,6 @@ static DDS_Security_boolean encode_rtps_message_sign ( DDS_Security_SecurityException *ex ) { - size_t length_to_postfix, remaining = encoded_rtps_message->_length; - unsigned char *ptr; DDS_Security_boolean result; struct submsg_header *prefix = (struct submsg_header *)(encoded_rtps_message->_buffer + RTPS_HEADER_SIZE); struct crypto_header *header = (struct crypto_header *)(prefix + 1); @@ -1551,13 +1545,13 @@ static DDS_Security_boolean encode_rtps_message_sign ( if (submessage_header->id == SMID_SRTPS_INFO_SRC_KIND) /* not encrypted */ { /* skip INFO_SRC_HDR to RTPS submessage header */ - ptr = ((unsigned char *)submessage_header + sizeof(struct submsg_header) + submessage_header->length); - remaining = (size_t) (encoded_rtps_message->_buffer + encoded_rtps_message->_length - ptr); + unsigned char *ptr = ((unsigned char *)submessage_header + sizeof(struct submsg_header) + submessage_header->length); + size_t remaining = (size_t) (encoded_rtps_message->_buffer + encoded_rtps_message->_length - ptr); /* There may be multiple RTPS submessages until postfix */ while (remaining - sizeof(struct submsg_header) > 0) { submessage_header = (struct submsg_header *)ptr; - length_to_postfix = submessage_header->length + sizeof(struct submsg_header); + size_t length_to_postfix = submessage_header->length + sizeof(struct submsg_header); postfix = (struct submsg_header *)(((unsigned char *)submessage_header) + length_to_postfix); if (postfix->id == SMID_SRTPS_POSTFIX_KIND) break; From 1c77aad39c1cad71195a932a68ac21ec72345266 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 24 Feb 2020 13:13:23 +0100 Subject: [PATCH 103/238] Fix Clang static analyzer warnings Signed-off-by: Erik Boasson --- .../authentication/src/authentication.c | 2 +- .../cryptographic/src/crypto_key_factory.c | 2 ++ .../src/decode_serialized_payload_utests.c | 6 +++++ .../src/encode_datareader_submessage_utests.c | 7 ++++++ .../src/encode_datawriter_submessage_utests.c | 9 +++++++ .../src/encode_rtps_message_utests.c | 25 +++++++++++-------- .../src/encode_serialized_payload_utests.c | 4 +++ ...thenticated_peer_credential_token_utests.c | 13 ++++++++++ .../src/get_xxx_sec_attributes_utests.c | 2 +- .../src/listeners_authentication_utests.c | 12 +++++++-- .../src/process_handshake_utests.c | 21 +++++++++++++++- .../src/register_local_datareader_utests.c | 9 +++++-- .../src/register_local_datawriter_utests.c | 13 +++++++--- .../src/register_local_participant_utests.c | 4 +++ ...egister_matched_remote_datareader_utests.c | 10 +++++--- ...egister_matched_remote_datawriter_utests.c | 12 ++++++--- .../validate_begin_handshake_reply_utests.c | 22 ++++++++-------- .../src/validate_local_identity_utests.c | 3 +++ .../src/validate_local_permissions_utests.c | 1 + .../src/validate_remote_permissions_utests.c | 2 ++ .../mock_authentication.c | 6 +++++ .../mock_authentication.c | 6 +++++ 22 files changed, 154 insertions(+), 37 deletions(-) diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index 257debc..09d3425 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -660,7 +660,7 @@ free_binary_properties( uint32_t length) { uint32_t i; - + assert (seq); for (i = 0; i < length; i++) { ddsrt_free(seq[i].name); ddsrt_free(seq[i].value._buffer); diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c index 833ca01..e77c99c 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c @@ -1150,6 +1150,8 @@ crypto_factory_set_datawriter_crypto_tokens( endpoint_relation *relation; uint32_t key_id, i; + assert (num_key_mat > 0); + remote_writer_crypto = (remote_datawriter_crypto *)crypto_object_table_find(impl->crypto_objects, remote_writer_handle); if (!remote_writer_crypto) { diff --git a/src/security/builtin_plugins/tests/decode_serialized_payload/src/decode_serialized_payload_utests.c b/src/security/builtin_plugins/tests/decode_serialized_payload/src/decode_serialized_payload_utests.c index 91d7e55..05fcf46 100644 --- a/src/security/builtin_plugins/tests/decode_serialized_payload/src/decode_serialized_payload_utests.c +++ b/src/security/builtin_plugins/tests/decode_serialized_payload/src/decode_serialized_payload_utests.c @@ -9,6 +9,8 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ +#include + #include #include #include @@ -218,6 +220,7 @@ static DDS_Security_DatawriterCryptoHandle register_local_datawriter(bool encryp printf("register_local_datawriter: %s\n", exception.message ? exception.message : "Error message missing"); } + assert (writer_crypto != 0); return writer_crypto; } @@ -239,6 +242,7 @@ static DDS_Security_DatawriterCryptoHandle register_remote_datawriter(DDS_Securi printf("register_matched_remote_datareader: %s\n", exception.message ? exception.message : "Error message missing"); } + assert (writer_crypto != 0); return writer_crypto; } @@ -839,6 +843,7 @@ CU_Test(ddssec_builtin_decode_serialized_payload, invalid_data, .init = suite_de } CU_ASSERT_FATAL(result); + assert(result); // for Clang's static analyzer CU_ASSERT(exception.code == 0); CU_ASSERT(exception.message == NULL); @@ -846,6 +851,7 @@ CU_Test(ddssec_builtin_decode_serialized_payload, invalid_data, .init = suite_de result = split_encoded_data(encoded_buffer._buffer, encoded_buffer._length, &header, &contents, (uint32_t *) &length, &footer); CU_ASSERT_FATAL(result); + assert(result); // for Clang's static analyzer /* use incorrect transformation kind */ { diff --git a/src/security/builtin_plugins/tests/encode_datareader_submessage/src/encode_datareader_submessage_utests.c b/src/security/builtin_plugins/tests/encode_datareader_submessage/src/encode_datareader_submessage_utests.c index 2513a39..7d97531 100644 --- a/src/security/builtin_plugins/tests/encode_datareader_submessage/src/encode_datareader_submessage_utests.c +++ b/src/security/builtin_plugins/tests/encode_datareader_submessage/src/encode_datareader_submessage_utests.c @@ -804,6 +804,7 @@ static void encode_datareader_submessage_not_signed(uint32_t transformation_kind reader_crypto = register_local_datareader(&datareader_security_attributes, &datareader_properties); CU_ASSERT_FATAL(reader_crypto != 0); + assert(reader_crypto != 0); // for Clang's static analyzer session_keys = get_datareader_session(reader_crypto); @@ -829,6 +830,7 @@ static void encode_datareader_submessage_not_signed(uint32_t transformation_kind } CU_ASSERT_FATAL(result); + assert(result); // for Clang's static analyzer CU_ASSERT(exception.code == 0); CU_ASSERT(exception.message == NULL); @@ -836,6 +838,7 @@ static void encode_datareader_submessage_not_signed(uint32_t transformation_kind result = check_encoded_data(&encoded_buffer, is_encrypted, &header, &footer, &data); CU_ASSERT_FATAL(result); + assert(result); // for Clang's static analyzer CU_ASSERT(header->transform_identifier.transformation_kind[3] == transformation_kind); @@ -951,6 +954,7 @@ static void encode_datareader_submessage_sign(uint32_t transformation_kind) reader_crypto = register_local_datareader(&datareader_security_attributes, &datareader_properties); CU_ASSERT_FATAL(reader_crypto != 0); + assert(reader_crypto != 0); // for Clang's static analyzer session_keys = get_datareader_session(reader_crypto); @@ -960,6 +964,7 @@ static void encode_datareader_submessage_sign(uint32_t transformation_kind) { writer_crypto = register_remote_datawriter(reader_crypto); CU_ASSERT_FATAL(writer_crypto != 0); + assert(writer_crypto != 0); // for Clang's static analyzer writer_list._buffer[i] = writer_crypto; } @@ -980,6 +985,7 @@ static void encode_datareader_submessage_sign(uint32_t transformation_kind) } CU_ASSERT_FATAL(result); + assert(result); // for Clang's static analyzer CU_ASSERT(exception.code == 0); CU_ASSERT(exception.message == NULL); @@ -988,6 +994,7 @@ static void encode_datareader_submessage_sign(uint32_t transformation_kind) result = check_encoded_data(&encoded_buffer, is_encrypted, &header, &footer, &data); CU_ASSERT_FATAL(result); + assert(result); // for Clang's static analyzer CU_ASSERT(header->transform_identifier.transformation_kind[3] == transformation_kind); diff --git a/src/security/builtin_plugins/tests/encode_datawriter_submessage/src/encode_datawriter_submessage_utests.c b/src/security/builtin_plugins/tests/encode_datawriter_submessage/src/encode_datawriter_submessage_utests.c index e4c7428..f7433ac 100644 --- a/src/security/builtin_plugins/tests/encode_datawriter_submessage/src/encode_datawriter_submessage_utests.c +++ b/src/security/builtin_plugins/tests/encode_datawriter_submessage/src/encode_datawriter_submessage_utests.c @@ -810,11 +810,13 @@ static void encode_datawriter_submessage_not_signed(DDS_Security_CryptoTransform writer_crypto = register_local_datawriter(&datawriter_security_attributes, &datawriter_properties); CU_ASSERT_FATAL(writer_crypto != 0); + assert(writer_crypto != 0); // for Clang's static analyzer session_keys = get_datawriter_session(writer_crypto); reader_crypto = register_remote_datareader(writer_crypto); CU_ASSERT_FATAL(reader_crypto != 0); + assert(reader_crypto != 0); // for Clang's static analyzer reader_list._length = reader_list._maximum = 1; reader_list._buffer = DDS_Security_DatareaderCryptoHandleSeq_allocbuf(1); @@ -837,6 +839,8 @@ static void encode_datawriter_submessage_not_signed(DDS_Security_CryptoTransform } CU_ASSERT_FATAL(result); + assert(result != 0); // for Clang's static analyzer + CU_ASSERT(exception.code == 0); CU_ASSERT(exception.message == NULL); @@ -844,6 +848,7 @@ static void encode_datawriter_submessage_not_signed(DDS_Security_CryptoTransform result = check_encoded_data(&encoded_buffer, is_encrypted, &header, &footer, &data); CU_ASSERT_FATAL(result); + assert(result); // for Clang's static analyzer CU_ASSERT(header->transform_identifier.transformation_kind[3] == transformation_kind); @@ -961,6 +966,7 @@ static void encode_datawriter_submessage_sign(DDS_Security_CryptoTransformKind_E writer_crypto = register_local_datawriter(&datawriter_security_attributes, &datawriter_properties); CU_ASSERT_FATAL(writer_crypto != 0); + assert(writer_crypto != 0); // for Clang's static analyzer session_keys = get_datawriter_session(writer_crypto); @@ -970,6 +976,7 @@ static void encode_datawriter_submessage_sign(DDS_Security_CryptoTransformKind_E { reader_crypto = register_remote_datareader(writer_crypto); CU_ASSERT_FATAL(reader_crypto != 0); + assert(reader_crypto != 0); // for Clang's static analyzer reader_list._buffer[i] = reader_crypto; } index = 0; @@ -994,6 +1001,7 @@ static void encode_datawriter_submessage_sign(DDS_Security_CryptoTransformKind_E } CU_ASSERT_FATAL(result); + assert(result); // for Clang's static analyzer CU_ASSERT(exception.code == 0); CU_ASSERT(exception.message == NULL); @@ -1003,6 +1011,7 @@ static void encode_datawriter_submessage_sign(DDS_Security_CryptoTransformKind_E result = check_encoded_data(&encoded_buffer, is_encrypted, &header, &footer, &data); CU_ASSERT_FATAL(result); + assert(result); // for Clang's static analyzer CU_ASSERT(header->transform_identifier.transformation_kind[3] == transformation_kind); diff --git a/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c b/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c index d65a0c7..bdcbb95 100644 --- a/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c +++ b/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c @@ -40,7 +40,7 @@ static DDS_Security_IdentityHandle local_participant_identity = 1; static DDS_Security_IdentityHandle remote_participant_identities[] = {2, 3, 4, 5}; static DDS_Security_ParticipantCryptoHandle local_particpant_crypto = 0; -static DDS_Security_ParticipantCryptoHandle remote_particpant_cryptos[4]; +static DDS_Security_ParticipantCryptoHandle remote_particpant_cryptos[sizeof(remote_participant_identities) / sizeof(remote_participant_identities[0])]; static DDS_Security_SharedSecretHandleImpl *shared_secret_handle_impl = NULL; static DDS_Security_SharedSecretHandle shared_secret_handle; @@ -63,7 +63,7 @@ struct submsg_header struct crypto_header { struct CryptoTransformIdentifier transform_identifier; - unsigned char session_id[4]; + unsigned char session_id[sizeof(remote_participant_identities) / sizeof(remote_participant_identities[0])]; unsigned char init_vector_suffix[8]; }; @@ -167,7 +167,7 @@ static int register_remote_participants(void) unsigned i; int result = 0; - for (i = 0; i < 4; ++i) + for (i = 0; i < sizeof(remote_particpant_cryptos) / sizeof(remote_particpant_cryptos[0]); ++i) { remote_particpant_cryptos[i] = crypto->crypto_key_factory->register_matched_remote_participant( @@ -194,7 +194,7 @@ unregister_remote_participants(void) { unsigned i; DDS_Security_SecurityException exception = {NULL, 0, 0}; - for (i = 0; i < 4; ++i) + for (i = 0; i < sizeof(remote_particpant_cryptos) / sizeof(remote_particpant_cryptos[0]); ++i) { if (remote_particpant_cryptos[i]) { @@ -825,6 +825,7 @@ static void encode_rtps_message_not_authenticated(DDS_Security_CryptoTransformKi } CU_ASSERT_FATAL(result); + assert(result); // for Clang's static analyzer CU_ASSERT(exception.code == 0); CU_ASSERT(exception.message == NULL); @@ -832,6 +833,7 @@ static void encode_rtps_message_not_authenticated(DDS_Security_CryptoTransformKi result = check_encoded_data(&encoded_buffer, encrypted, &header, &footer, &data); CU_ASSERT_FATAL(result); + assert(result); // for Clang's static analyzer CU_ASSERT(header->transform_identifier.transformation_kind[3] == transformation_kind); @@ -922,7 +924,7 @@ static void encode_rtps_message_sign(DDS_Security_CryptoTransformKind_Enum trans struct crypto_header *header = NULL; struct crypto_footer *footer = NULL; uint32_t session_id; - int i; + size_t i; CU_ASSERT_FATAL(crypto != NULL); CU_ASSERT_FATAL(crypto->crypto_transform != NULL); @@ -943,9 +945,9 @@ static void encode_rtps_message_sign(DDS_Security_CryptoTransformKind_Enum trans register_remote_participants(); - reader_list._length = reader_list._maximum = 4; - reader_list._buffer = DDS_Security_ParticipantCryptoHandleSeq_allocbuf(4); - for (i = 0; i < 4; i++) + reader_list._length = reader_list._maximum = (uint32_t) (sizeof(remote_particpant_cryptos) / sizeof(remote_particpant_cryptos[0])); + reader_list._buffer = DDS_Security_ParticipantCryptoHandleSeq_allocbuf(reader_list._maximum); + for (i = 0; i < sizeof(remote_particpant_cryptos) / sizeof(remote_particpant_cryptos[0]); i++) { set_remote_participant_protection_kind(remote_particpant_cryptos[i], protection_kind); reader_list._buffer[i] = remote_particpant_cryptos[i]; @@ -955,7 +957,7 @@ static void encode_rtps_message_sign(DDS_Security_CryptoTransformKind_Enum trans /* Now call the function. */ buffer = &plain_buffer; - while (index != 4) + while ((uint32_t) index != reader_list._length) { result = crypto->crypto_transform->encode_rtps_message( crypto->crypto_transform, @@ -1082,14 +1084,17 @@ CU_Test(ddssec_builtin_encode_rtps_message, invalid_args, .init = suite_encode_r memset(&empty_reader_list, 0, sizeof(empty_reader_list)); CU_ASSERT_FATAL(local_particpant_crypto != 0); + assert(local_particpant_crypto != 0); // for Clang's static analyzer register_remote_participants(); - for (i = 0; i < 4; i++) + for (i = 0; i < sizeof (remote_particpant_cryptos) / sizeof (remote_particpant_cryptos[0]); i++) { + assert (remote_particpant_cryptos[i]); // for Clang's static analyzer set_remote_participant_protection_kind(remote_particpant_cryptos[i], DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION); } CU_ASSERT_FATAL(remote_particpant_cryptos[0] != 0); + assert(remote_particpant_cryptos[0] != 0); // for Clang's static analyzer reader_list._length = reader_list._maximum = 1; reader_list._buffer = DDS_Security_ParticipantCryptoHandleSeq_allocbuf(1); diff --git a/src/security/builtin_plugins/tests/encode_serialized_payload/src/encode_serialized_payload_utests.c b/src/security/builtin_plugins/tests/encode_serialized_payload/src/encode_serialized_payload_utests.c index f477ea3..e4cd8ea 100644 --- a/src/security/builtin_plugins/tests/encode_serialized_payload/src/encode_serialized_payload_utests.c +++ b/src/security/builtin_plugins/tests/encode_serialized_payload/src/encode_serialized_payload_utests.c @@ -566,6 +566,8 @@ static void encode_serialized_payload_check(uint32_t key_size, bool encrypted) writer_crypto = register_local_datawriter(encrypted); CU_ASSERT_FATAL(writer_crypto != 0); + assert(writer_crypto != 0); // for Clang's static analyzer + CU_ASSERT(check_protection_kind(writer_crypto, encrypted ? DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT : DDS_SECURITY_BASICPROTECTION_KIND_SIGN)); session_keys = get_datawriter_session(writer_crypto); @@ -586,12 +588,14 @@ static void encode_serialized_payload_check(uint32_t key_size, bool encrypted) printf("[ERROR] encode_serialized_payload: %s\n", exception.message ? exception.message : "Error message missing"); } CU_ASSERT_FATAL(result); + assert(result); // for Clang's static analyzer CU_ASSERT(exception.code == 0); CU_ASSERT(exception.message == NULL); reset_exception(&exception); result = split_encoded_data(encoded_buffer._buffer, encoded_buffer._length, &header, &encoded_payload, &footer, encrypted); CU_ASSERT_FATAL(result == true); + assert(result); // for Clang's static analyzer CU_ASSERT(check_payload_encoded(&encoded_payload, &plain_buffer, encrypted)); session_id = ddsrt_fromBE4u(*(uint32_t *)header->session_id); diff --git a/src/security/builtin_plugins/tests/get_authenticated_peer_credential_token/src/get_authenticated_peer_credential_token_utests.c b/src/security/builtin_plugins/tests/get_authenticated_peer_credential_token/src/get_authenticated_peer_credential_token_utests.c index 160ae83..6ae66d7 100644 --- a/src/security/builtin_plugins/tests/get_authenticated_peer_credential_token/src/get_authenticated_peer_credential_token_utests.c +++ b/src/security/builtin_plugins/tests/get_authenticated_peer_credential_token/src/get_authenticated_peer_credential_token_utests.c @@ -1256,6 +1256,7 @@ fill_handshake_message_token( CU_ASSERT(hash1_from_request != NULL); CU_ASSERT(hash2_from_reply != NULL); + assert(hash1_from_request && hash2_from_reply); // for Clang's static analyzer set_binary_property_value(hash_c1, "hash_c1", hash1_from_request->value._buffer, hash1_from_request->value._length); set_binary_property_value(hash_c2, "hash_c2", hash2_from_reply->value._buffer, hash2_from_reply->value._length); @@ -1382,6 +1383,7 @@ CU_Test(ddssec_builtin_get_authenticated_peer_credential,token_after_request ) &exception); CU_ASSERT_FATAL(result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE); + assert(result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE); // for Clang's static analyzer /* mock reply */ dh1 = find_binary_property(&handshake_token_out, "dh1"); @@ -1414,6 +1416,7 @@ CU_Test(ddssec_builtin_get_authenticated_peer_credential,token_after_request ) handshake_handle, &exception); CU_ASSERT_FATAL(result == DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE); + assert(result == DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE); // for Clang's static analyzer /* * Actual test. @@ -1425,8 +1428,10 @@ CU_Test(ddssec_builtin_get_authenticated_peer_credential,token_after_request ) &exception); CU_ASSERT_TRUE (success); + assert(success); // for Clang's static analyzer CU_ASSERT_FATAL(credential_token.class_id != NULL); + assert(credential_token.class_id); // for Clang's static analyzer CU_ASSERT(strcmp(credential_token.class_id, AUTH_PROTOCOL_CLASS_ID) == 0); CU_ASSERT(credential_token.properties._length == 2); CU_ASSERT(credential_token.binary_properties._length == 0); @@ -1434,12 +1439,14 @@ CU_Test(ddssec_builtin_get_authenticated_peer_credential,token_after_request ) c_id = find_property(&credential_token, "c.id"); CU_ASSERT_FATAL(c_id != NULL); CU_ASSERT_FATAL(c_id->value != NULL); + assert(c_id && c_id->value); // for Clang's static analyzer //printf("c_id->value: %s\n", c_id->value); CU_ASSERT(strcmp(c_id->value, REMOTE_IDENTITY_CERTIFICATE) == 0); c_perm = find_property(&credential_token, "c.perm"); CU_ASSERT_FATAL(c_perm != NULL); CU_ASSERT_FATAL(c_perm->value != NULL); + assert(c_perm && c_perm->value); // for Clang's static analyzer //printf("c_perm->value: %s\n", c_perm->value); CU_ASSERT(strcmp(c_perm->value, PERMISSIONS_DOCUMENT) == 0); @@ -1506,6 +1513,7 @@ CU_Test(ddssec_builtin_get_authenticated_peer_credential,token_after_reply ) &exception); CU_ASSERT_FATAL(result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE); + assert(result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE); // for Clang's static analyzer /* mock final */ dh2 = find_binary_property(&handshake_token_out, "dh2"); @@ -1539,6 +1547,7 @@ CU_Test(ddssec_builtin_get_authenticated_peer_credential,token_after_reply ) &exception); CU_ASSERT_FATAL(result == DDS_SECURITY_VALIDATION_OK); + assert(result == DDS_SECURITY_VALIDATION_OK); // for Clang's static analyzer /* * Actual test. @@ -1550,6 +1559,7 @@ CU_Test(ddssec_builtin_get_authenticated_peer_credential,token_after_reply ) &exception); CU_ASSERT_TRUE (success); + assert(success); // for Clang's static analyzer CU_ASSERT_FATAL(credential_token.class_id != NULL); CU_ASSERT(strcmp(credential_token.class_id, AUTH_PROTOCOL_CLASS_ID) == 0); @@ -1559,12 +1569,14 @@ CU_Test(ddssec_builtin_get_authenticated_peer_credential,token_after_reply ) c_id = find_property(&credential_token, "c.id"); CU_ASSERT_FATAL(c_id != NULL); CU_ASSERT_FATAL(c_id->value != NULL); + assert(c_id && c_id->value); // for Clang's static analyzer //printf("c_id->value: %s\n", c_id->value); CU_ASSERT(strcmp(c_id->value, REMOTE_IDENTITY_CERTIFICATE) == 0); c_perm = find_property(&credential_token, "c.perm"); CU_ASSERT_FATAL(c_perm != NULL); CU_ASSERT_FATAL(c_perm->value != NULL); + assert(c_perm && c_perm->value); // for Clang's static analyzer //printf("c_perm->value: %s\n", c_perm->value); CU_ASSERT(strcmp(c_perm->value, PERMISSIONS_DOCUMENT) == 0); @@ -1581,6 +1593,7 @@ CU_Test(ddssec_builtin_get_authenticated_peer_credential,token_after_reply ) success = g_auth->return_handshake_handle(g_auth, handshake_handle, &exception); CU_ASSERT_TRUE (success); + assert(success); // for Clang's static analyzer reset_exception(&exception); diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/src/get_xxx_sec_attributes_utests.c b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/src/get_xxx_sec_attributes_utests.c index 91381aa..04df354 100644 --- a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/src/get_xxx_sec_attributes_utests.c +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/src/get_xxx_sec_attributes_utests.c @@ -1279,7 +1279,7 @@ static void test_liveliness_discovery_reader_attr( DDS_Security_DataTagQosPolicy data_tag; DDS_Security_PartitionQosPolicy *partition = NULL; bool result; - return; + CU_ASSERT_FATAL(access_control->get_datareader_sec_attributes != NULL); memset(&attr, 0, sizeof(attr)); diff --git a/src/security/builtin_plugins/tests/listeners_authentication/src/listeners_authentication_utests.c b/src/security/builtin_plugins/tests/listeners_authentication/src/listeners_authentication_utests.c index a039d25..779b254 100644 --- a/src/security/builtin_plugins/tests/listeners_authentication/src/listeners_authentication_utests.c +++ b/src/security/builtin_plugins/tests/listeners_authentication/src/listeners_authentication_utests.c @@ -1724,7 +1724,8 @@ fill_handshake_message_token( set_binary_property_string(c_kagree_algo, "c.kagree_algox", "rubbish"); } - CU_ASSERT(hash1_from_request != NULL); + CU_ASSERT_FATAL(hash1_from_request != NULL); + assert(hash1_from_request != NULL); // for Clang's static analyzer set_binary_property_value(hash_c1, "hash_c1", hash1_from_request->value._buffer, hash1_from_request->value._length); @@ -1786,6 +1787,7 @@ fill_handshake_message_token( EVP_PKEY *private_key_x509; unsigned char *sign; size_t signlen; + DDS_Security_ValidationResult_t rc; const DDS_Security_BinaryProperty_t * binary_properties[ HANDSHAKE_SIGNATURE_SIZE ]; @@ -1802,10 +1804,14 @@ fill_handshake_message_token( binary_properties[4] = dh1; binary_properties[5] = hash_c1; - if (create_signature_for_test(private_key_x509, binary_properties, HANDSHAKE_SIGNATURE_SIZE , &sign, &signlen, &exception) != DDS_SECURITY_VALIDATION_OK) + rc = create_signature_for_test(private_key_x509, binary_properties, HANDSHAKE_SIGNATURE_SIZE , &sign, &signlen, &exception); + if (rc != DDS_SECURITY_VALIDATION_OK) { printf("Exception: %s\n", exception.message); } + CU_ASSERT_FATAL (rc == DDS_SECURITY_VALIDATION_OK); + assert(rc == DDS_SECURITY_VALIDATION_OK); // for Clang's static analyzer + set_binary_property_value(signature, "signature", sign, (uint32_t)signlen); ddsrt_free(sign); @@ -2008,8 +2014,10 @@ CU_Test(ddssec_builtin_listeners_auth, local_remote_set_before_validation) hash1_sent_in_request = find_binary_property(&handshake_token_out, "hash_c1"); CU_ASSERT_FATAL(dh1 != NULL); + assert(dh1 != NULL); // for Clang's static analyzer CU_ASSERT_FATAL(dh1->value._length > 0); CU_ASSERT_FATAL(dh1->value._buffer != NULL); + assert(dh1->value._length > 0 && dh1->value._buffer != NULL); // for Clang's static analyzer dh1_pub_key.data = dh1->value._buffer; dh1_pub_key.length = dh1->value._length; diff --git a/src/security/builtin_plugins/tests/process_handshake/src/process_handshake_utests.c b/src/security/builtin_plugins/tests/process_handshake/src/process_handshake_utests.c index 5b2f5d6..dabd5a8 100644 --- a/src/security/builtin_plugins/tests/process_handshake/src/process_handshake_utests.c +++ b/src/security/builtin_plugins/tests/process_handshake/src/process_handshake_utests.c @@ -1292,7 +1292,8 @@ fill_handshake_message_token( set_binary_property_string(c_kagree_algo, "c.kagree_algox", "rubbish"); } - CU_ASSERT(hash1_from_request != NULL); + CU_ASSERT_FATAL(hash1_from_request != NULL); + assert(hash1_from_request != NULL); // for Clang's static analyzer set_binary_property_value(hash_c1, "hash_c1", hash1_from_request->value._buffer, hash1_from_request->value._length); @@ -1587,8 +1588,10 @@ CU_Test(ddssec_builtin_process_handshake,happy_day_after_request ) hash1_sentrequest = find_binary_property(&handshake_token_out, "hash_c1"); CU_ASSERT_FATAL(dh1 != NULL); + assert(dh1 != NULL); // for Clang's static analyzer CU_ASSERT_FATAL(dh1->value._length > 0); CU_ASSERT_FATAL(dh1->value._buffer != NULL); + assert(dh1->value._length > 0 && dh1->value._buffer != NULL); // for Clang's static analyzer dh1_pub_key.data = dh1->value._buffer; dh1_pub_key.length = dh1->value._length; @@ -1875,8 +1878,10 @@ CU_Test(ddssec_builtin_process_handshake,invalid_certificate ) hash1_sentrequest = find_binary_property(&handshake_token_out, "hash_c1"); CU_ASSERT_FATAL(dh1 != NULL); + assert(dh1 != NULL); // for Clang's static analyzer CU_ASSERT_FATAL(dh1->value._length > 0); CU_ASSERT_FATAL(dh1->value._buffer != NULL); + assert(dh1->value._length > 0 && dh1->value._buffer != NULL); // for Clang's static analyzer /* prepare reply */ dh1_pub_key.data = dh1->value._buffer; @@ -1959,8 +1964,10 @@ CU_Test(ddssec_builtin_process_handshake,invalid_dsign_algo ) hash1_sentrequest = find_binary_property(&handshake_token_out, "hash_c1"); CU_ASSERT_FATAL(dh1 != NULL); + assert(dh1 != NULL); // for Clang's static analyzer CU_ASSERT_FATAL(dh1->value._length > 0); CU_ASSERT_FATAL(dh1->value._buffer != NULL); + assert(dh1->value._length > 0 && dh1->value._buffer != NULL); // for Clang's static analyzer /* prepare reply */ dh1_pub_key.data = dh1->value._buffer; @@ -2037,8 +2044,10 @@ CU_Test(ddssec_builtin_process_handshake,invalid_kagree_algo ) hash1_sentrequest = find_binary_property(&handshake_token_out, "hash_c1"); CU_ASSERT_FATAL(dh1 != NULL); + assert (dh1 != NULL); // for Clang's static analyzer CU_ASSERT_FATAL(dh1->value._length > 0); CU_ASSERT_FATAL(dh1->value._buffer != NULL); + assert (dh1->value._length > 0 && dh1->value._buffer != NULL); // for Clang's static analyzer /* prepare reply */ dh1_pub_key.data = dh1->value._buffer; @@ -2114,8 +2123,10 @@ CU_Test(ddssec_builtin_process_handshake,invalid_diffie_hellman ) hash1_sentrequest = find_binary_property(&handshake_token_out, "hash_c1"); CU_ASSERT_FATAL(dh1 != NULL); + assert (dh1 != NULL); // for Clang's static analyzer CU_ASSERT_FATAL(dh1->value._length > 0); CU_ASSERT_FATAL(dh1->value._buffer != NULL); + assert (dh1->value._length > 0 && dh1->value._buffer != NULL); // for Clang's static analyzer /* prepare reply */ fill_handshake_message_token( @@ -2244,6 +2255,8 @@ CU_Test(ddssec_builtin_process_handshake,extended_certificate_check ) if (result != DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE) { printf("begin_handshake_request failed: %s\n", exception.message ? exception.message : "Error message missing"); } + CU_ASSERT_FATAL(result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE); + assert(result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE); // for Clang's static analyzer /* get challenge 1 from the message */ challenge1_glb = find_binary_property(&handshake_token_out, "challenge1"); @@ -2254,8 +2267,10 @@ CU_Test(ddssec_builtin_process_handshake,extended_certificate_check ) hash1_sentrequest = find_binary_property(&handshake_token_out, "hash_c1"); CU_ASSERT_FATAL(dh1 != NULL); + assert(dh1 != NULL); // for Clang's static analyzer CU_ASSERT_FATAL(dh1->value._length > 0); CU_ASSERT_FATAL(dh1->value._buffer != NULL); + assert(dh1->value._length > 0 && dh1->value._buffer != NULL); // for Clang's static analyzer dh1_pub_key.data = dh1->value._buffer; dh1_pub_key.length = dh1->value._length; @@ -2328,8 +2343,10 @@ CU_Test(ddssec_builtin_process_handshake,extended_certificate_check ) hash1_sentrequest = find_binary_property(&handshake_token_out, "hash_c1"); CU_ASSERT_FATAL(dh1 != NULL); + assert (dh1 != NULL); // for Clang's static analyzer CU_ASSERT_FATAL(dh1->value._length > 0); CU_ASSERT_FATAL(dh1->value._buffer != NULL); + assert (dh1->value._length > 0 && dh1->value._buffer != NULL); // for Clang's static analyzer dh1_pub_key.data = dh1->value._buffer; dh1_pub_key.length = dh1->value._length; @@ -2397,8 +2414,10 @@ CU_Test(ddssec_builtin_process_handshake,extended_certificate_check ) hash1_sentrequest = find_binary_property(&handshake_token_out, "hash_c1"); CU_ASSERT_FATAL(dh1 != NULL); + assert (dh1 != NULL); // for Clang's static analyzer CU_ASSERT_FATAL(dh1->value._length > 0); CU_ASSERT_FATAL(dh1->value._buffer != NULL); + assert (dh1->value._length > 0 && dh1->value._buffer != NULL); // for Clang's static analyzer dh1_pub_key.data = dh1->value._buffer; dh1_pub_key.length = dh1->value._length; diff --git a/src/security/builtin_plugins/tests/register_local_datareader/src/register_local_datareader_utests.c b/src/security/builtin_plugins/tests/register_local_datareader/src/register_local_datareader_utests.c index 327ddb7..5747ac3 100644 --- a/src/security/builtin_plugins/tests/register_local_datareader/src/register_local_datareader_utests.c +++ b/src/security/builtin_plugins/tests/register_local_datareader/src/register_local_datareader_utests.c @@ -9,6 +9,8 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ +#include + #include #include #include @@ -166,6 +168,7 @@ CU_Test(ddssec_builtin_register_local_datareader, happy_day, .init = suite_regis /* A valid handle to be returned */ CU_ASSERT(result != 0); + assert(result != 0); // for Clang's static analyzer CU_ASSERT(exception.code == DDS_SECURITY_ERR_OK_CODE); @@ -220,6 +223,7 @@ CU_Test(ddssec_builtin_register_local_datareader, builtin_endpoint, .init = suit /* A valid handle to be returned */ CU_ASSERT(result != 0); CU_ASSERT(exception.code == DDS_SECURITY_ERR_OK_CODE); + assert(result != 0); // for Clang's static analyzer /* NOTE: It would be better to check if the keys have been generated but there is no interface to get them from handle */ reader_crypto = (local_datareader_crypto *)result; @@ -268,8 +272,9 @@ CU_Test(ddssec_builtin_register_local_datareader, special_endpoint_name, .init = printf("register_local_datareader: %s\n", exception.message ? exception.message : "Error message missing"); /* A valid handle to be returned */ - CU_ASSERT(result != 0); - CU_ASSERT(exception.code == DDS_SECURITY_ERR_OK_CODE); + CU_ASSERT_FATAL(result != 0); + assert(result != 0); // for Clang's static analyzer + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_OK_CODE); CU_ASSERT_FATAL(((local_datareader_crypto *)result)->is_builtin_participant_volatile_message_secure_reader); reset_exception(&exception); DDS_Security_PropertySeq_deinit(&datareader_properties); diff --git a/src/security/builtin_plugins/tests/register_local_datawriter/src/register_local_datawriter_utests.c b/src/security/builtin_plugins/tests/register_local_datawriter/src/register_local_datawriter_utests.c index c6d1adc..16d13f3 100644 --- a/src/security/builtin_plugins/tests/register_local_datawriter/src/register_local_datawriter_utests.c +++ b/src/security/builtin_plugins/tests/register_local_datawriter/src/register_local_datawriter_utests.c @@ -9,6 +9,8 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ +#include + #include #include #include @@ -172,6 +174,7 @@ CU_Test(ddssec_builtin_register_local_datawriter, happy_day, .init = suite_regis /* A valid handle to be returned */ CU_ASSERT(result != 0); CU_ASSERT(exception.code == DDS_SECURITY_ERR_OK_CODE); + assert(result != 0); // for Clang's static analyzer /* NOTE: It would be better to check if the keys have been generated but there is no interface to get them from handle */ writer_crypto = (local_datawriter_crypto *)result; @@ -230,8 +233,9 @@ CU_Test(ddssec_builtin_register_local_datawriter, builtin_endpoint, .init = suit printf("register_local_datawriter: %s\n", exception.message ? exception.message : "Error message missing"); /* A valid handle to be returned */ - CU_ASSERT(result != 0); - CU_ASSERT(exception.code == DDS_SECURITY_ERR_OK_CODE); + CU_ASSERT_FATAL(result != 0); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_OK_CODE); + assert(result != 0); // for Clang's static analyzer /* NOTE: It would be better to check if the keys have been generated but there is no interface to get them from handle */ writer_crypto = (local_datawriter_crypto *)result; @@ -289,8 +293,9 @@ CU_Test(ddssec_builtin_register_local_datawriter, special_endpoint_name, .init = printf("register_local_datawriter: %s\n", exception.message ? exception.message : "Error message missing"); /* A valid handle to be returned */ - CU_ASSERT(result != 0); - CU_ASSERT(exception.code == DDS_SECURITY_ERR_OK_CODE); + CU_ASSERT_FATAL(result != 0); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_OK_CODE); + assert(result != 0); // for Clang's static analyzer CU_ASSERT_FATAL(((local_datawriter_crypto *)result)->is_builtin_participant_volatile_message_secure_writer); reset_exception(&exception); diff --git a/src/security/builtin_plugins/tests/register_local_participant/src/register_local_participant_utests.c b/src/security/builtin_plugins/tests/register_local_participant/src/register_local_participant_utests.c index 967cf67..1602d9a 100644 --- a/src/security/builtin_plugins/tests/register_local_participant/src/register_local_participant_utests.c +++ b/src/security/builtin_plugins/tests/register_local_participant/src/register_local_participant_utests.c @@ -9,6 +9,8 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ +#include + #include #include #include @@ -146,6 +148,8 @@ CU_Test(ddssec_builtin_register_local_participant, empty_identity, .init = suite printf("register_local_participant: %s\n", exception.message ? exception.message : "Error message missing"); CU_ASSERT(exception.code == DDS_SECURITY_ERR_IDENTITY_EMPTY_CODE); + CU_ASSERT_FATAL(exception.message != NULL); + assert(exception.message != NULL); // for Clang's static analyzer CU_ASSERT(!strcmp(exception.message, DDS_SECURITY_ERR_IDENTITY_EMPTY_MESSAGE)); CU_ASSERT(result == 0); diff --git a/src/security/builtin_plugins/tests/register_matched_remote_datareader/src/register_matched_remote_datareader_utests.c b/src/security/builtin_plugins/tests/register_matched_remote_datareader/src/register_matched_remote_datareader_utests.c index 6c6d6ff..2f0eadb 100644 --- a/src/security/builtin_plugins/tests/register_matched_remote_datareader/src/register_matched_remote_datareader_utests.c +++ b/src/security/builtin_plugins/tests/register_matched_remote_datareader/src/register_matched_remote_datareader_utests.c @@ -9,6 +9,8 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ +#include + #include #include #include @@ -200,8 +202,9 @@ CU_Test(ddssec_builtin_register_remote_datareader, happy_day, .init = suite_regi printf("register_remote_datareader: %s\n", exception.message ? exception.message : "Error message missing"); /* A valid handle to be returned */ - CU_ASSERT(result != 0); - CU_ASSERT(exception.code == DDS_SECURITY_ERR_OK_CODE); + CU_ASSERT_FATAL(result != 0); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_OK_CODE); + assert(result != 0); // for Clang's static analyzer /* NOTE: It would be better to check if the keys have been generated but there is no interface to get them from handle */ reader_crypto = (remote_datareader_crypto *)result; @@ -265,6 +268,7 @@ CU_Test(ddssec_builtin_register_remote_datareader, volatile_secure, .init = suit /* A valid handle to be returned */ CU_ASSERT_FATAL(result != 0); + assert(result != 0); // for Clang's static analyzer CU_ASSERT_FATAL(((remote_datareader_crypto *)result)->is_builtin_participant_volatile_message_secure_reader); CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_OK_CODE); reset_exception(&exception); @@ -293,7 +297,6 @@ CU_Test(ddssec_builtin_register_remote_datareader, with_origin_authentication, . /*set writer protection kind */ writer_crypto = (local_datawriter_crypto *)local_writer_handle; writer_crypto->metadata_protectionKind = DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION; - writer_crypto = (local_datawriter_crypto *)local_writer_handle; /* Now call the function. */ result = crypto->crypto_key_factory->register_matched_remote_datareader( @@ -310,6 +313,7 @@ CU_Test(ddssec_builtin_register_remote_datareader, with_origin_authentication, . /* A valid handle to be returned */ CU_ASSERT(result != 0); CU_ASSERT(exception.code == DDS_SECURITY_ERR_OK_CODE); + assert(result != 0); // for Clang's static analyzer /* NOTE: It would be better to check if the keys have been generated but there is no interface to get them from handle */ reader_crypto = (remote_datareader_crypto *)result; diff --git a/src/security/builtin_plugins/tests/register_matched_remote_datawriter/src/register_matched_remote_datawriter_utests.c b/src/security/builtin_plugins/tests/register_matched_remote_datawriter/src/register_matched_remote_datawriter_utests.c index 635c018..c9dc669 100644 --- a/src/security/builtin_plugins/tests/register_matched_remote_datawriter/src/register_matched_remote_datawriter_utests.c +++ b/src/security/builtin_plugins/tests/register_matched_remote_datawriter/src/register_matched_remote_datawriter_utests.c @@ -9,6 +9,8 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ +#include + #include #include #include @@ -199,10 +201,12 @@ CU_Test(ddssec_builtin_register_remote_datawriter, happy_day, .init = suite_regi /* A valid handle to be returned */ CU_ASSERT_FATAL(result != 0); CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_OK_CODE); + assert(result != 0); // for Clang's static analyzer /* NOTE: It would be better to check if the keys have been generated but there is no interface to get them from handle */ writer_crypto = (remote_datawriter_crypto *)result; CU_ASSERT_FATAL(writer_crypto->reader2writer_key_material != NULL); + assert(writer_crypto->reader2writer_key_material != NULL); // for Clang's static analyzer CU_ASSERT(master_salt_not_empty(writer_crypto->reader2writer_key_material)); CU_ASSERT(master_key_not_empty(writer_crypto->reader2writer_key_material)); CU_ASSERT_FATAL(writer_crypto->reader2writer_key_material->receiver_specific_key_id == 0); @@ -254,6 +258,7 @@ CU_Test(ddssec_builtin_register_remote_datawriter, volatile_secure, .init = suit /* A valid handle to be returned */ CU_ASSERT_FATAL(result != 0); + assert(result != 0); // for Clang's static analyzer CU_ASSERT_FATAL(((remote_datawriter_crypto *)result)->is_builtin_participant_volatile_message_secure_writer); CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_OK_CODE); reset_exception(&exception); @@ -282,7 +287,6 @@ CU_Test(ddssec_builtin_register_remote_datawriter, with_origin_authentication, . /*set reader protection kind */ reader_crypto = (local_datareader_crypto *)local_reader_handle; reader_crypto->metadata_protectionKind = DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION; - reader_crypto = (local_datareader_crypto *)local_reader_handle; /* Now call the function. */ result = crypto->crypto_key_factory->register_matched_remote_datawriter( @@ -296,12 +300,14 @@ CU_Test(ddssec_builtin_register_remote_datawriter, with_origin_authentication, . printf("register_remote_datawriter: %s\n", exception.message ? exception.message : "Error message missing"); /* A valid handle to be returned */ - CU_ASSERT(result != 0); - CU_ASSERT(exception.code == DDS_SECURITY_ERR_OK_CODE); + CU_ASSERT_FATAL(result != 0); + CU_ASSERT_FATAL(exception.code == DDS_SECURITY_ERR_OK_CODE); + assert(result != 0); // for Clang's static analyzer /* NOTE: It would be better to check if the keys have been generated but there is no interface to get them from handle */ writer_crypto = (remote_datawriter_crypto *)result; CU_ASSERT_FATAL(writer_crypto->reader2writer_key_material != NULL); + assert(writer_crypto->reader2writer_key_material != NULL); // for Clang's static analyzer CU_ASSERT(master_salt_not_empty(writer_crypto->reader2writer_key_material)); CU_ASSERT(master_key_not_empty(writer_crypto->reader2writer_key_material)); CU_ASSERT_FATAL(writer_crypto->reader2writer_key_material->receiver_specific_key_id != 0); diff --git a/src/security/builtin_plugins/tests/validate_begin_handshake_reply/src/validate_begin_handshake_reply_utests.c b/src/security/builtin_plugins/tests/validate_begin_handshake_reply/src/validate_begin_handshake_reply_utests.c index 90cb2a7..e8f5259 100644 --- a/src/security/builtin_plugins/tests/validate_begin_handshake_reply/src/validate_begin_handshake_reply_utests.c +++ b/src/security/builtin_plugins/tests/validate_begin_handshake_reply/src/validate_begin_handshake_reply_utests.c @@ -1586,6 +1586,7 @@ CU_Test(ddssec_builtin_validate_begin_handshake_reply,invalid_participant_data , property = find_binary_property(&handshake_token_in, "c.pdata"); CU_ASSERT_FATAL(property != NULL); + assert(property != NULL); // for Clang's static analyzer ddsrt_free(property->name); property->name = ddsrt_strdup("c.pdatax"); @@ -1835,17 +1836,18 @@ CU_Test(ddssec_builtin_validate_begin_handshake_reply,invalid_challenge , .init CU_ASSERT_FATAL (remote_identity_handle2 != DDS_SECURITY_HANDLE_NIL); CU_ASSERT_FATAL (auth->begin_handshake_reply != NULL); - fill_handshake_message_token_default(&handshake_token_in, remote_participant_data2, challenge2->value._buffer, challenge2->value._length); + fill_handshake_message_token_default(&handshake_token_in, remote_participant_data2, challenge2->value._buffer, challenge2->value._length); - result = auth->begin_handshake_reply( - auth, - &handshake_handle, - &handshake_token_out, - &handshake_token_in, - remote_identity_handle1, - local_identity_handle, - &serialized_participant_data, - &exception); + result = auth->begin_handshake_reply( + auth, + &handshake_handle, + &handshake_token_out, + &handshake_token_in, + remote_identity_handle1, + local_identity_handle, + &serialized_participant_data, + &exception); + CU_ASSERT_FATAL (result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE); handshake_message_deinit(&handshake_token_in); handshake_message_deinit(&handshake_token_out); diff --git a/src/security/builtin_plugins/tests/validate_local_identity/src/validate_local_identity_utests.c b/src/security/builtin_plugins/tests/validate_local_identity/src/validate_local_identity_utests.c index 59a5567..721e854 100644 --- a/src/security/builtin_plugins/tests/validate_local_identity/src/validate_local_identity_utests.c +++ b/src/security/builtin_plugins/tests/validate_local_identity/src/validate_local_identity_utests.c @@ -1133,6 +1133,7 @@ CU_Test(ddssec_builtin_validate_local_identity,missing_certificate_property) CU_ASSERT (result != DDS_SECURITY_VALIDATION_OK); CU_ASSERT (exception.minor_code != 0); CU_ASSERT_FATAL (exception.message != NULL); + assert(exception.message != NULL); // for Clang's static analyzer CU_ASSERT(strcmp(exception.message, "validate_local_identity: missing property 'dds.sec.auth.identity_certificate'") == 0); dds_security_property_deinit(&participant_qos.property.value); @@ -1189,6 +1190,7 @@ CU_Test(ddssec_builtin_validate_local_identity,missing_ca_property) CU_ASSERT (result != DDS_SECURITY_VALIDATION_OK); CU_ASSERT (exception.minor_code != 0); CU_ASSERT_FATAL (exception.message != NULL); + assert(exception.message != NULL); // for Clang's static analyzer CU_ASSERT(strcmp(exception.message, "validate_local_identity: missing property 'dds.sec.auth.identity_ca'") == 0); dds_security_property_deinit(&participant_qos.property.value); @@ -1240,6 +1242,7 @@ CU_Test(ddssec_builtin_validate_local_identity,missing_private_key_property) CU_ASSERT (result != DDS_SECURITY_VALIDATION_OK); CU_ASSERT (exception.minor_code != 0); CU_ASSERT_FATAL (exception.message != NULL); + assert(exception.message != NULL); // for Clang's static analyzer CU_ASSERT(strcmp(exception.message, "validate_local_identity: missing property 'dds.sec.auth.private_key'") == 0); dds_security_property_deinit(&participant_qos.property.value); diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/src/validate_local_permissions_utests.c b/src/security/builtin_plugins/tests/validate_local_permissions/src/validate_local_permissions_utests.c index b690fdb..f0a4cb5 100644 --- a/src/security/builtin_plugins/tests/validate_local_permissions/src/validate_local_permissions_utests.c +++ b/src/security/builtin_plugins/tests/validate_local_permissions/src/validate_local_permissions_utests.c @@ -605,6 +605,7 @@ static DDS_Security_long test_corrupted_signature(bool corrupt_permissions, bool /* Just some (hardcoded) sanity checks. */ CU_ASSERT_FATAL(prop != NULL); CU_ASSERT_FATAL(prop->value != NULL); + assert(prop && prop->value); // for Clang's static analyzer len = strlen(prop->value); CU_ASSERT_FATAL(len > 2250); diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/src/validate_remote_permissions_utests.c b/src/security/builtin_plugins/tests/validate_remote_permissions/src/validate_remote_permissions_utests.c index 137137a..84c413f 100644 --- a/src/security/builtin_plugins/tests/validate_remote_permissions/src/validate_remote_permissions_utests.c +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/src/validate_remote_permissions_utests.c @@ -277,6 +277,7 @@ static void corrupt_permission_signature(DDS_Security_AuthenticatedPeerCredentia /* It is expected that the permissions are available in a fixed location. */ CU_ASSERT_FATAL(token != NULL); CU_ASSERT_FATAL(token->properties._buffer != NULL); + assert(token->properties._buffer != NULL); // for Clang's static analyzer CU_ASSERT_FATAL(token->properties._length == 2); CU_ASSERT_FATAL(token->properties._buffer[1].name != NULL); CU_ASSERT_FATAL(token->properties._buffer[1].value != NULL); @@ -285,6 +286,7 @@ static void corrupt_permission_signature(DDS_Security_AuthenticatedPeerCredentia /* Corrupt a byte somewhere in the signature. */ permissions = token->properties._buffer[1].value; CU_ASSERT_FATAL(permissions != NULL); + assert(permissions != NULL); // for Clang's static analyzer len = strlen(permissions); CU_ASSERT_FATAL(len > 100); permissions[len - 75]--; diff --git a/src/security/core/tests/plugin_loading/plugin_mock/authentication_finalize_error/mock_authentication.c b/src/security/core/tests/plugin_loading/plugin_mock/authentication_finalize_error/mock_authentication.c index a072b00..68f53ad 100644 --- a/src/security/core/tests/plugin_loading/plugin_mock/authentication_finalize_error/mock_authentication.c +++ b/src/security/core/tests/plugin_loading/plugin_mock/authentication_finalize_error/mock_authentication.c @@ -15,6 +15,7 @@ #include "dds/ddsrt/misc.h" #include "mock_authentication.h" #include +#include #include #include @@ -72,6 +73,11 @@ DDS_Security_ValidationResult_t validate_local_identity( } } + /* for Clang's static analyzer */ + assert(identity_certificate != NULL); + assert(identity_ca != NULL); + assert(private_key != NULL); + if( strcmp(identity_certificate, test_identity_certificate) != 0){ result = DDS_SECURITY_VALIDATION_FAILED; diff --git a/src/security/core/tests/plugin_loading/plugin_mock/authentication_missing_function/mock_authentication.c b/src/security/core/tests/plugin_loading/plugin_mock/authentication_missing_function/mock_authentication.c index ee4efe2..c80c8d1 100644 --- a/src/security/core/tests/plugin_loading/plugin_mock/authentication_missing_function/mock_authentication.c +++ b/src/security/core/tests/plugin_loading/plugin_mock/authentication_missing_function/mock_authentication.c @@ -13,6 +13,7 @@ #include "dds/ddsrt/misc.h" #include "mock_authentication.h" #include +#include #include #include @@ -73,6 +74,11 @@ DDS_Security_ValidationResult_t validate_local_identity( } } + /* for Clang's static analyzer */ + assert(identity_certificate != NULL); + assert(identity_ca != NULL); + assert(private_key != NULL); + if( strcmp(identity_certificate, test_identity_certificate) != 0){ result = DDS_SECURITY_VALIDATION_FAILED; From 4960fbf94ce9857e7e323b6e300014674351431e Mon Sep 17 00:00:00 2001 From: Marcel Jordense Date: Fri, 22 Nov 2019 17:50:35 +0100 Subject: [PATCH 104/238] Add security authentication handshake and encoding and decoding Signed-off-by: Marcel Jordense --- src/core/ddsc/src/dds_topic.c | 19 +- src/core/ddsi/CMakeLists.txt | 8 +- .../ddsi/include/dds/ddsi/ddsi_domaingv.h | 5 + .../ddsi/include/dds/ddsi/ddsi_handshake.h | 53 +- src/core/ddsi/include/dds/ddsi/ddsi_plist.h | 1 + .../include/dds/ddsi/ddsi_security_exchange.h | 49 + .../ddsi/include/dds/ddsi/ddsi_security_msg.h | 18 +- .../ddsi/include/dds/ddsi/ddsi_security_omg.h | 1153 ++++-- .../include/dds/ddsi/ddsi_security_util.h | 91 + .../ddsi/include/dds/ddsi/q_ddsi_discovery.h | 2 + src/core/ddsi/include/dds/ddsi/q_entity.h | 43 +- src/core/ddsi/include/dds/ddsi/q_misc.h | 1 + src/core/ddsi/include/dds/ddsi/q_xevent.h | 2 + src/core/ddsi/include/dds/ddsi/q_xmsg.h | 2 + src/core/ddsi/src/ddsi_handshake.c | 1189 ++++++- src/core/ddsi/src/ddsi_plist.c | 82 +- src/core/ddsi/src/ddsi_security_exchange.c | 428 +++ src/core/ddsi/src/ddsi_security_msg.c | 81 +- src/core/ddsi/src/ddsi_security_omg.c | 3077 +++++++++++++++-- src/core/ddsi/src/ddsi_security_util.c | 708 ++++ src/core/ddsi/src/q_ddsi_discovery.c | 254 +- src/core/ddsi/src/q_entity.c | 253 +- src/core/ddsi/src/q_init.c | 7 +- src/core/ddsi/src/q_misc.c | 5 + src/core/ddsi/src/q_receive.c | 26 +- src/core/ddsi/src/q_transmit.c | 2 +- src/core/ddsi/src/q_xevent.c | 34 +- src/core/ddsi/src/q_xmsg.c | 21 +- .../src/access_control_parser.c | 2 + .../authentication/src/auth_utils.c | 3 +- .../authentication/src/authentication.c | 590 ++-- .../cryptographic/src/crypto_key_exchange.c | 73 +- .../cryptographic/src/crypto_key_factory.c | 105 +- .../cryptographic/src/crypto_key_factory.h | 5 + .../cryptographic/src/crypto_objects.c | 13 +- .../cryptographic/src/crypto_objects.h | 8 +- ...t_remote_datareader_crypto_tokens_utests.c | 1 + ...t_remote_datawriter_crypto_tokens_utests.c | 1 + src/security/core/CMakeLists.txt | 3 +- .../dds/security/core/dds_security_utils.h | 4 +- src/security/core/src/dds_security_fsm.c | 227 +- src/security/core/src/dds_security_utils.c | 8 +- .../tests/plugin_loading/plugin_loading.c | 17 +- .../mock_authentication.c | 12 +- .../mock_authentication.h | 78 +- .../tests/plugin_loading/plugin_mock_common.h | 98 + .../tests/plugin_loading/security_config.c | 81 +- src/security/core/tests/tc_fsm.c | 69 +- 48 files changed, 7473 insertions(+), 1539 deletions(-) create mode 100644 src/core/ddsi/include/dds/ddsi/ddsi_security_exchange.h create mode 100644 src/core/ddsi/include/dds/ddsi/ddsi_security_util.h create mode 100644 src/core/ddsi/src/ddsi_security_exchange.c create mode 100644 src/core/ddsi/src/ddsi_security_util.c create mode 100644 src/security/core/tests/plugin_loading/plugin_mock_common.h diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index d85eb91..743e9b9 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -32,6 +32,7 @@ #include "dds/ddsi/ddsi_plist.h" #include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/ddsi_cdrstream.h" +#include "dds/ddsi/ddsi_security_omg.h" #include "dds__serdata_builtintopic.h" DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_topic) @@ -317,10 +318,12 @@ dds_entity_t dds_create_topic_impl (dds_entity_t participant, struct ddsi_sertop * reliable ... (and keep behaviour unchanged) */ struct ddsi_domaingv * const gv = &pp->m_entity.m_domain->gv; if ((rc = ddsi_xqos_valid (&gv->logconfig, new_qos)) != DDS_RETCODE_OK) + goto error; + + if (!q_omg_security_check_create_topic (&pp->m_entity.m_domain->gv, &pp->m_entity.m_guid, sertopic->name, new_qos)) { - dds_delete_qos (new_qos); - dds_entity_unpin (&pp->m_entity); - return rc; + rc = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY; + goto error; } /* See if we're allowed to create the topic; ktp is returned pinned & locked @@ -333,9 +336,8 @@ dds_entity_t dds_create_topic_impl (dds_entity_t participant, struct ddsi_sertop if ((rc = lookup_and_check_ktopic (&ktp, pp, sertopic->name, sertopic->type_name, new_qos)) != DDS_RETCODE_OK) { GVTRACE ("dds_create_topic_arbitrary: failed after compatibility check: %s\n", dds_strretcode (rc)); - dds_participant_unlock (pp); - dds_delete_qos (new_qos); - return rc; + ddsrt_mutex_unlock (&pp->m_entity.m_mutex); + goto error; } /* Create a ktopic if it doesn't exist yet, else reference existing one and delete the @@ -378,6 +380,11 @@ dds_entity_t dds_create_topic_impl (dds_entity_t participant, struct ddsi_sertop dds_participant_unlock (pp); GVTRACE ("dds_create_topic_arbitrary: new topic %"PRId32"\n", hdl); return hdl; + + error: + dds_entity_unpin (&pp->m_entity); + dds_delete_qos (new_qos); + return rc; } dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_sertopic *sertopic, const dds_qos_t *qos, const dds_listener_t *listener, const ddsi_plist_t *sedp_plist) diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index ddd07fd..4c466bd 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -18,6 +18,7 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" ddsi_raweth.c ddsi_ipaddr.c ddsi_mcgroup.c + ddsi_security_util.c ddsi_security_omg.c ddsi_portmapping.c ddsi_handshake.c @@ -83,6 +84,7 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" ddsi_ipaddr.h ddsi_mcgroup.h ddsi_plist_generic.h + ddsi_security_util.h ddsi_security_omg.h ddsi_portmapping.h ddsi_handshake.h @@ -148,10 +150,12 @@ target_sources(ddsc if(ENABLE_SECURITY) PREPEND(security_srcs "${CMAKE_CURRENT_LIST_DIR}/src" - ddsi_security_msg.c) + ddsi_security_msg.c + ddsi_security_exchange.c) PREPEND(security_hdrs "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" - ddsi_security_msg.h) + ddsi_security_msg.h + ddsi_security_exchange.h) target_sources(ddsc PRIVATE ${security_srcs} ${security_hdrs}) diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h b/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h index 17fc797..f7227bd 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h @@ -47,6 +47,8 @@ struct ddsrt_thread_pool_s; struct debug_monitor; struct ddsi_tkmap; struct dds_security_context; +struct dds_security_match_index; +struct ddsi_hsadmin; typedef struct config_in_addr_node { nn_locator_t loc; @@ -299,7 +301,10 @@ 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 + }; #if defined (__cplusplus) diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_handshake.h b/src/core/ddsi/include/dds/ddsi/ddsi_handshake.h index 91300d4..f473d0f 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_handshake.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_handshake.h @@ -12,9 +12,7 @@ #ifndef DDSI_HANDSHAKE_H #define DDSI_HANDSHAKE_H -#include "q_unused.h" -#include "q_entity.h" -#include "ddsi_security_msg.h" +#include "dds/ddsi/q_entity.h" #if defined (__cplusplus) extern "C" { @@ -37,10 +35,9 @@ enum ddsi_handshake_state { /* The handshake will not use the related handshake object after this callback * was executed. This means that it can be deleted in this callback. */ typedef void (*ddsi_handshake_end_cb_t)( - struct ddsi_domaingv const * const gv, struct ddsi_handshake *handshake, - const ddsi_guid_t *lpguid, /* Local participant */ - const ddsi_guid_t *ppguid, /* Proxy participant */ + struct participant *pp, + struct proxy_participant *proxypp, enum ddsi_handshake_state result); #ifdef DDSI_INCLUDE_SECURITY @@ -123,7 +120,7 @@ int64_t ddsi_handshake_get_handle(const struct ddsi_handshake *handshake); * @param[in] callback The callback function. * */ -void ddsi_handshake_register(const struct participant *pp, const struct proxy_participant *proxypp, ddsi_handshake_end_cb_t callback); +void ddsi_handshake_register(struct participant *pp, struct proxy_participant *proxypp, ddsi_handshake_end_cb_t callback); /** * @brief Remove the handshake associated with the specified participants. @@ -137,7 +134,7 @@ void ddsi_handshake_register(const struct participant *pp, const struct proxy_pa * @param[in] handshake The handshake. * */ -void ddsi_handshake_remove(const struct participant *pp, const struct proxy_participant *proxypp, struct ddsi_handshake *handshake); +void ddsi_handshake_remove(struct participant *pp, struct proxy_participant *proxypp, struct ddsi_handshake *handshake); /** * @brief Searches for the handshake associated with the specified participants @@ -150,12 +147,42 @@ void ddsi_handshake_remove(const struct participant *pp, const struct proxy_part * * @returns The handshake */ -struct ddsi_handshake * ddsi_handshake_find(const struct participant *pp, const struct proxy_participant *proxypp); +struct ddsi_handshake * ddsi_handshake_find(struct participant *pp, struct proxy_participant *proxypp); + +/** + * @brief Searches for the handshake associated with the specified participants + * + * This function will search through the handshake administration to find the handshake + * corresponding the to specified local and remote participant. + * + * @param[in] pp The local participant. + * @param[in] proxypp The remote participant. + * + * @returns The handshake + */ +struct ddsi_handshake * ddsi_handshake_find(struct participant *pp, struct proxy_participant *proxypp); + +/** + * @brief Initialize the handshake administration + * + * @param[in] gv The global parameters + */ +void ddsi_handshake_admin_init(struct ddsi_domaingv *gv); + +/** + * @brief Deinitialze the handshake administration. + * + * @param[in] gv The global parameters + */ +void ddsi_handshake_admin_deinit(struct ddsi_domaingv *gv); #else /* DDSI_INCLUDE_SECURITY */ #include "dds/ddsi/q_unused.h" +inline void ddsi_handshake_register(UNUSED_ARG(struct participant *pp), UNUSED_ARG(struct proxy_participant *proxypp), UNUSED_ARG(ddsi_handshake_end_cb_t callback)) +{ +} inline void ddsi_handshake_release(UNUSED_ARG(struct ddsi_handshake *handshake)) { @@ -175,15 +202,11 @@ inline int64_t ddsi_handshake_get_handle(UNUSED_ARG(const struct ddsi_handshake return 0; } -inline void ddsi_handshake_register(UNUSED_ARG(const struct participant *pp), UNUSED_ARG(const struct proxy_participant *proxypp), UNUSED_ARG(ddsi_handshake_end_cb_t callback)) +inline void ddsi_handshake_remove(UNUSED_ARG(struct participant *pp), UNUSED_ARG(struct proxy_participant *proxypp), UNUSED_ARG(struct ddsi_handshake *handshake)) { } -inline void ddsi_handshake_remove(UNUSED_ARG(const struct participant *pp), UNUSED_ARG(const struct proxy_participant *proxypp), UNUSED_ARG(struct ddsi_handshake *handshake)) -{ -} - -inline struct ddsi_handshake * ddsi_handshake_find(UNUSED_ARG(const struct participant *pp), UNUSED_ARG(const struct proxy_participant *proxypp)) +inline struct ddsi_handshake * ddsi_handshake_find(UNUSED_ARG(struct participant *pp), UNUSED_ARG(struct proxy_participant *proxypp)) { return NULL; } diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_plist.h b/src/core/ddsi/include/dds/ddsi/ddsi_plist.h index c6f5a8d..4f8b07f 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_plist.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_plist.h @@ -309,6 +309,7 @@ DDS_EXPORT void ddsi_plist_fini (ddsi_plist_t *ps); DDS_EXPORT void ddsi_plist_fini_mask (ddsi_plist_t *plist, uint64_t pmask, uint64_t qmask); DDS_EXPORT void ddsi_plist_unalias (ddsi_plist_t *plist); DDS_EXPORT void ddsi_plist_addtomsg (struct nn_xmsg *m, const ddsi_plist_t *ps, uint64_t pwanted, uint64_t qwanted); +DDS_EXPORT void ddsi_plist_addtomsg_bo (struct nn_xmsg *m, const ddsi_plist_t *ps, uint64_t pwanted, uint64_t qwanted, bool be); DDS_EXPORT void ddsi_plist_init_default_participant (ddsi_plist_t *plist); DDS_EXPORT void ddsi_plist_delta (uint64_t *pdelta, uint64_t *qdelta, const ddsi_plist_t *x, const ddsi_plist_t *y, uint64_t pmask, uint64_t qmask); DDS_EXPORT void ddsi_plist_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const ddsi_plist_t *plist); diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_security_exchange.h b/src/core/ddsi/include/dds/ddsi/ddsi_security_exchange.h new file mode 100644 index 0000000..4495cdf --- /dev/null +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_exchange.h @@ -0,0 +1,49 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSI_SECURITY_EXCHANGE_H +#define DDSI_SECURITY_EXCHANGE_H + +#ifdef DDSI_INCLUDE_SECURITY + +#if defined (__cplusplus) +extern "C" { +#endif + +#include "dds/ddsi/q_rtps.h" +#include "dds/ddsi/q_radmin.h" +#include "dds/ddsi/q_entity.h" +#include "dds/ddsi/ddsi_security_msg.h" + + +#define GMCLASSID_SECURITY_PARTICIPANT_CRYPTO_TOKENS "dds.sec.participant_crypto_tokens" +#define GMCLASSID_SECURITY_DATAWRITER_CRYPTO_TOKENS "dds.sec.datawriter_crypto_tokens" +#define GMCLASSID_SECURITY_DATAREADER_CRYPTO_TOKENS "dds.sec.datareader_crypto_tokens" + +bool write_auth_handshake_message(const struct participant *pp, const struct proxy_participant *proxypp, nn_dataholderseq_t *mdata, bool request, const nn_message_identity_t *related_message_id); +void handle_auth_handshake_message(const struct receiver_state *rst, ddsi_entityid_t wr_entity_id, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, size_t len); +void handle_crypto_exchange_message(const struct receiver_state *rst, ddsi_entityid_t wr_entity_id, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len); +void auth_get_serialized_participant_data(struct participant *pp, ddsi_octetseq_t *seq); +bool write_crypto_participant_tokens(const struct participant *pp, const struct proxy_participant *proxypp, const nn_dataholderseq_t *tokens); +bool write_crypto_writer_tokens(const struct writer *wr, const struct proxy_reader *prd, const nn_dataholderseq_t *tokens); +bool write_crypto_reader_tokens(const struct reader *rd, const struct proxy_writer *pwr, const nn_dataholderseq_t *tokens); + +#if defined (__cplusplus) +} +#endif + +#else /* DDSI_INCLUDE_SECURITY */ + +#define volatile_secure_data_filter NULL + +#endif /* DDSI_INCLUDE_SECURITY */ + +#endif /* DDSI_SECURITY_EXCHANGE_H */ diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_security_msg.h b/src/core/ddsi/include/dds/ddsi/ddsi_security_msg.h index a35a43d..072a3eb 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_msg.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_msg.h @@ -28,8 +28,13 @@ struct writer; struct proxy_reader; struct ddsi_serdata; -#define GMCLASSID_SECURITY_AUTH_REQUEST "dds.sec.auth_request" -#define GMCLASSID_SECURITY_AUTH_HANDSHAKE "dds.sec.auth" +#define DDS_SECURITY_AUTH_REQUEST "dds.sec.auth_request" +#define DDS_SECURITY_AUTH_HANDSHAKE "dds.sec.auth" +#define DDS_SECURITY_AUTH_REQUEST_TOKEN_CLASS_ID "DDS:Auth:PKI-DH:1.0+AuthReq" +#define DDS_SECURITY_AUTH_HANDSHAKE_REQUEST_TOKEN_ID "DDS:Auth:PKI-DH:1.0+Req" +#define DDS_SECURITY_AUTH_HANDSHAKE_REPLY_TOKEN_ID "DDS:Auth:PKI-DH:1.0+Reply" +#define DDS_SECURITY_AUTH_HANDSHAKE_FINAL_TOKEN_ID "DDS:Auth:PKI-DH:1.0+Final" + typedef struct nn_message_identity { ddsi_guid_t source_guid; @@ -91,15 +96,6 @@ nn_participant_generic_message_serialize( DDS_EXPORT extern const enum pserop pserop_participant_generic_message[]; -DDS_EXPORT int -write_crypto_exchange_message( - const struct participant *pp, - const ddsi_guid_t *dst_pguid, - const ddsi_guid_t *src_eguid, - const ddsi_guid_t *dst_eguid, - const char *classid, - const nn_dataholderseq_t *tokens); - DDS_EXPORT int volatile_secure_data_filter( struct writer *wr, 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 d6a36ea..534a762 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h @@ -12,6 +12,9 @@ #ifndef DDSI_OMG_SECURITY_H #define DDSI_OMG_SECURITY_H +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/avl.h" + #include "dds/ddsi/ddsi_plist.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/ddsi_domaingv.h" @@ -20,7 +23,11 @@ #include "dds/ddsrt/retcode.h" #include "dds/ddsrt/types.h" #include "dds/ddsrt/sync.h" +#include "dds/ddsi/ddsi_xqos.h" +#ifdef DDSI_INCLUDE_SECURITY +#include "dds/security/dds_security_api.h" +#endif #if defined (__cplusplus) extern "C" { @@ -34,26 +41,123 @@ typedef enum { #ifdef DDSI_INCLUDE_SECURITY -#include "dds/security/dds_security_api.h" -#include "dds/security/core/dds_security_plugins.h" +struct ddsi_hsadmin; +struct participant_sec_attributes; +struct proxy_participant_sec_attributes; +struct writer_sec_attributes; +struct reader_sec_attributes; +struct dds_security_context; typedef struct nn_msg_sec_info { + unsigned encoded:1; + unsigned use_rtps_encoding:1; int64_t src_pp_handle; int64_t dst_pp_handle; - bool use_rtps_encoding; } 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; + 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; + ddsi_guid_t proxypp_guid; + DDS_Security_ParticipantCryptoHandle proxypp_crypto_handle; +}; + +struct proxypp_pp_match { + ddsrt_avl_node_t avlnode; + ddsi_guid_t pp_guid; + DDS_Security_ParticipantCryptoHandle pp_crypto_handle; + DDS_Security_PermissionsHandle permissions_handle; + DDS_Security_SharedSecretHandle shared_secret; +}; + +struct participant_sec_attributes { + ddsrt_avl_node_t avlnode; + ddsi_guid_t pp_guid; + DDS_Security_ParticipantSecurityAttributes attr; + DDS_Security_IdentityHandle local_identity_handle; + DDS_Security_PermissionsHandle permissions_handle; + DDS_Security_ParticipantCryptoHandle crypto_handle; + bool plugin_attr; + ddsrt_mutex_t lock; + ddsrt_avl_ctree_t proxy_participants; + bool initialized; +}; + +struct proxy_participant_sec_attributes { + struct dds_security_context *sc; + DDS_Security_IdentityHandle remote_identity_handle; + DDS_Security_ParticipantCryptoHandle crypto_handle; + ddsrt_mutex_t lock; + ddsrt_avl_tree_t participants; + bool initialized; +}; + +struct writer_sec_attributes { + DDS_Security_EndpointSecurityAttributes attr; + DDS_Security_DatawriterCryptoHandle crypto_handle; + bool plugin_attr; +}; + +struct reader_sec_attributes { + DDS_Security_EndpointSecurityAttributes attr; + DDS_Security_DatareaderCryptoHandle crypto_handle; + bool plugin_attr; +}; + +struct dds_security_authentication *q_omg_participant_get_authentication(const struct participant *pp); + +void q_omg_log_exception(const struct ddsrt_log_cfg *lc, uint32_t cat, DDS_Security_SecurityException *exception, const char *file, uint32_t line, const char *func, const char *fmt, ...); + +/** + * @brief Check if access control is enabled for the participant. + * + * @param[in] pp Participant to check. + * + * @returns bool True if access control is enabled for participant + */ +bool q_omg_participant_is_access_protected(const struct participant *pp); + +/** + * @brief Check if protection at RTPS level is enabled for the participant. + * + * @param[in] pp Participant to check. + * + * @returns bool True if RTPS protection enabled for participant + */ +bool q_omg_participant_is_rtps_protected(const struct participant *pp); + +/** + * @brief Check if liveliness is protected for the participant. + * + * @param[in] pp Participant to check. + * + * @returns bool True if liveliness data for participant is protected + */ +bool q_omg_participant_is_liveliness_protected(const struct participant *pp); /** * @brief Check if security is enabled for the participant. * * @param[in] pp Participant to check if it is secure. * - * @returns bool - * @retval true Participant is secure - * @retval false Participant is not secure + * @returns bool True if participant is secure */ bool q_omg_participant_is_secure(const struct participant *pp); @@ -62,31 +166,150 @@ bool q_omg_participant_is_secure(const struct participant *pp); * * @param[in] proxypp Proxy participant to check if it is secure. * - * @returns bool - * @retval true Proxy participant is secure - * @retval false Proxy participant is not secure + * @returns bool True if proxy participant is secure */ bool q_omg_proxy_participant_is_secure(const struct proxy_participant *proxypp); /** - * @brief Get the security handle of the given local participant. + * @brief Check security if it is allowed to create the participant. + * + * When security is enabled for this participant it is checked if the + * participant is authenticated by checking the provided security + * certificates. When that is ok the participant is registered with + * access control and with cryptography. When that is all successful + * this function return true; + * + * @param[in] pp The participant to check if alloweed by security. + * #param[in] domain_id The domain_id + * + * @returns bool + * @retval true Participant is allowed + * @retval false Participant is not allowed + */ +bool q_omg_security_check_create_participant(struct participant *pp, uint32_t domain_id); + +void q_omg_security_participant_set_initialized(struct participant *pp); + +bool q_omg_security_participant_is_initialized(struct participant *pp); + +/** + * @brief Remove the participant from the security plugins. + * + * When the participant was registered with the security + * plugins then this function will release the allocated + * security resources. + * + * @param[in] pp Participant to remove. + */ +void q_omg_security_deregister_participant(struct participant *pp); + +/** + * @brief Get the identity handle associate with this participant. + * + * This function returns the identity handle that was created + * when the participant was authenticated. This handle corresponds + * with the handle returned by calling validate_local_identity on + * the authentication plugin. * * @param[in] pp Participant to check if it is secure. * * @returns int64_t - * @retval Local participant security handle + * @retval !0 Identity handle associated with the participant. + * @retval 0 Invalid handle the participant was not registered */ -int64_t q_omg_security_get_local_participant_handle(struct participant *pp); +int64_t q_omg_security_get_local_participant_handle(const struct participant *pp); /** - * @brief Get the security handle of the given remote participant. + * @brief Get security info flags of the given participant. * - * @param[in] proxypp Participant to check if it is secure. + * @param[in] pp Participant to get the security info from. + * @param[out] info The security info. * - * @returns int64_t - * @retval Remote participant security handle + * @returns bool + * @retval true Security info set. + * @retval false Security info not set. */ -int64_t q_omg_security_get_remote_participant_handle(struct proxy_participant *proxypp); +bool q_omg_get_participant_security_info(const struct participant *pp, nn_security_info_t *info); + +/** + * @brief Get the is_rtps_protected flag of the given remote participant. + * + * @param[in] pp The participant. + * @param[in] entityid ID of the entity to check. + * + * @returns bool + * @retval true RTPS protected is set. + * @retval false RTPS protected is not set. + */ +bool q_omg_security_is_local_rtps_protected(const struct participant *pp, ddsi_entityid_t entityid); + +/** + * @brief Check if the participant and the proxy participant + * have compatible security info settings. + * + * Associated with a secure participant is the ParticipantSecurityInfo parameter. + * This parameter contains the setting of the security attributes and the associated + * plugin security attributes of the secure participant. + * This function will check if the received ParticipantSecurityInfo parameter is + * compatible with the local ParticipantSecurityInfo parameter. + * + * @param[in] pp The participant. + * @param[in] proxypp The proxy participant. + * + * @returns bool + * @retval true The participant and the proxy participant have compatible + * security info settings. + * @retval false Otherwise. + */ +bool q_omg_is_similar_participant_security_info(struct participant *pp, struct proxy_participant *proxypp); + +/** + * @brief Check if the parameter list key hash is protected + * + * @param[in] plist The parameter list + * + * @returns bool True if the parameter list key hash is protected + */ +bool q_omg_plist_keyhash_is_protected(const ddsi_plist_t *plist); + +/** + * @brief Check if the endpoint is protected + * + * Checks whether the provided parameter list has the flag + * ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID set. When this flag + * is set, this implies that the remote endpoint has protection + * enabled. + * + * @param[in] plist The parameter list + * + * @returns bool True if the endpoint is protected + */ +bool q_omg_is_endpoint_protected(const ddsi_plist_t *plist); + +/** + * @brief Writes the security attributes and security plugin attributes to log (category discovery) + * + * @param[in] gv Global variable + * @param[in] plist The parameter list + */ +void q_omg_log_endpoint_protection(struct ddsi_domaingv * const gv, const ddsi_plist_t *plist); + +/** + * @brief Check if security allows to create the topic. + * + * This function checks with access control if is allowed to create + * this topic for the specified domain. + * + * @param[in] gv The domain global information. + * @param[in] pp_guid The participant guid. + * @param[in] topic_name The name of the topic. + * @param[in] qos The topic QoS used. + * + * @returns bool + * @retval true Creation of the topic is allowed + * @retval false Otherwise. + */ +bool q_omg_security_check_create_topic(const struct ddsi_domaingv *gv, const ddsi_guid_t *pp_guid, const char *topic_name, const struct dds_qos *qos); /** * @brief Get security info flags of the given writer. @@ -100,6 +323,65 @@ int64_t q_omg_security_get_remote_participant_handle(struct proxy_participant *p */ bool q_omg_get_writer_security_info(const struct writer *wr, nn_security_info_t *info); +/** + * @brief Return the builtin writer id for this writers' discovery. + * + * Return builtin entity id of the writer to use for the publication + * discovery information. + * Depending on whether the discovery is protected or not (for the + * given writer), either the default writer or protected writer needs + * to be used. + * + * @param[in] wr Writer to determine the publication writer from. + * + * @returns unsigned + * @retval NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER + * @retval NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER + */ +unsigned determine_publication_writer(const struct writer *wr); + +/** + * @brief Check if security allows to create the writer. + * + * This function checks with access control if is allowed to create + * this writer for the specified domain. + * + * @param[in] pp Participant on which the topic is being created. + * @param[in] domain_id The corresponding domain_id. + * @param[in] topic_name The name of the topic. + * @param[in] writer_qos The writer QoS used. + * + * @returns bool + * @retval true Creation of the writer is allowed + * @retval false Otherwise. + */ +bool q_omg_security_check_create_writer(struct participant *pp, uint32_t domain_id, const char *topic_name, const struct dds_qos *writer_qos); + +/** + * @brief Register the writer with security. + * + * This function registers the writer with security + * when the associated participant has security enabled. + * The security settings associated with this writer are determined + * and the writer is registered with cryptography when needed by + * the security settings which indicate if payload protection and or + * submessage protection is enabled for this writer. + * + * @param[in] wr The writer to register. + */ +void q_omg_security_register_writer(struct writer *wr); + +/** + * @brief Remove the writer from security. + * + * When the writer was registered with security then this function + * will remove the writer from security which will free the allocated + * security resource created for this writer. + * + * @param[in] wr The writer to remove. + */ +void q_omg_security_deregister_writer(struct writer *wr); + /** * @brief Get security info flags of the given reader. * @@ -128,23 +410,47 @@ bool q_omg_get_reader_security_info(const struct reader *rd, nn_security_info_t * @retval NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER */ unsigned determine_subscription_writer(const struct reader *rd); +/** + * @brief Check if security allows to create the reader. + * + * This function checks with access control if is allowed to create + * this reader for the specified domain. + * + * @param[in] pp Participant on which the topic is being created. + * @param[in] domain_id The corresponding domain_id. + * @param[in] topic_name The name of the topic. + * @param[in] reader_qos The reader QoS used. + * + * @returns bool + * @retval true Creation of the writer is allowed + * @retval false Otherwise. + */ +bool q_omg_security_check_create_reader(struct participant *pp, uint32_t domain_id, const char *topic_name, const struct dds_qos *reader_qos); /** - * @brief Return the builtin writer id for this writers' discovery. + * @brief Register the reader with security. * - * Return builtin entity id of the writer to use for the publication - * discovery information. - * Depending on whether the discovery is protected or not (for the - * given writer), either the default writer or protected writer needs - * to be used. + * This function registers the reader with security + * when the associated participant has security enabled. + * The security settings associated with this reader are determined + * and the reader is registered with cryptography when needed by + * the security settings which indicate if submessage protection is + * enabled for this reader. * - * @param[in] wr Writer to determine the publication writer from. - * - * @returns unsigned - * @retval NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER - * @retval NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER + * @param[in] rd The reader to register. */ -unsigned determine_publication_writer(const struct writer *wr); +void q_omg_security_register_reader(struct reader *rd); + +/** + * @brief Remove the reader from security. + * + * When the reader was registered with security then this function + * will remove the reader from security which will free the allocated + * security resource created for this reader. + * + * @param[in] rd The reader to remove. + */ +void q_omg_security_deregister_reader(struct reader *rd); /** * @brief Determine if the proxy participant is allowed to be deleted @@ -162,11 +468,7 @@ unsigned determine_publication_writer(const struct writer *wr); * @retval true The proxy participant may be deleted. * @retval false The proxy participant may not be deleted by this writer. */ -bool -is_proxy_participant_deletion_allowed( - struct ddsi_domaingv * const gv, - const struct ddsi_guid *guid, - const ddsi_entityid_t pwr_entityid); +bool is_proxy_participant_deletion_allowed(struct ddsi_domaingv * const gv, const struct ddsi_guid *guid, const ddsi_entityid_t pwr_entityid); /** * @brief Determine if the messages, related to the given remote @@ -179,26 +481,7 @@ is_proxy_participant_deletion_allowed( * @retval true The entity messages are RTPS protected. * @retval false The entity messages are not RTPS protected. */ -bool -q_omg_security_is_remote_rtps_protected( - const struct proxy_participant *proxy_pp, - ddsi_entityid_t entityid); - -/** - * @brief Determine if the messages, related to the given local - * entity, are RTPS protected or not. - * - * @param[in] pp Related participant. - * @param[in] entityid ID of the entity to check. - * - * @returns bool - * @retval true The entity messages are RTPS protected. - * @retval false The entity messages are not RTPS protected. - */ -bool -q_omg_security_is_local_rtps_protected( - const struct participant *pp, - ddsi_entityid_t entityid); +bool q_omg_security_is_remote_rtps_protected(const struct proxy_participant *proxy_pp, ddsi_entityid_t entityid); /** * @brief Set security information, depending on plist, into the given @@ -207,22 +490,120 @@ q_omg_security_is_local_rtps_protected( * @param[in] proxypp Proxy participant to set security info on. * @param[in] plist Paramater list, possibly contains security info. */ -void -set_proxy_participant_security_info( - struct proxy_participant *proxypp, - const ddsi_plist_t *plist); +void set_proxy_participant_security_info(struct proxy_participant *proxypp, const ddsi_plist_t *plist); /** - * @brief Set security information, depending on plist and proxy participant, - * into the given proxy reader. + * @brief Check if the participant and the proxy participant + * have compatible security info settings. * - * @param[in] prd Proxy reader to set security info on. - * @param[in] plist Paramater list, possibly contains security info. + * Associated with a secure participant is the ParticipantSecurityInfo parameter. + * This parameter contains the setting of the security attributes and the associated + * plugin security attributes of the secure participant. + * This function will check if the received ParticipantSecurityInfo parameter is + * compatible with the local ParticipantSecurityInfo parameter. + * + * @param[in] pp The participant. + * @param[in] proxypp The proxy participant. + * + * @returns bool + * @retval true The participant and the proxy participant have compatible + * security info settings. + * @retval false Otherwise. */ -void -set_proxy_reader_security_info( - struct proxy_reader *prd, - const ddsi_plist_t *plist); +bool q_omg_security_is_local_rtps_protected(const struct participant *pp, ddsi_entityid_t entityid); + +/** + * @brief Check if the participant allows communication with unauthenticated + * participants + * + * @param[in] pp The participant. + * + * @returns bool + * @retval true The participant allows unauthenticated communication + * @retval false Otherwise. + */ +bool q_omg_participant_allow_unauthenticated(struct participant *pp); + +/** + * @brief Initialize the proxy participant security attributes + * + * @param[in] proxypp The proxy participant. + * + */ +void q_omg_security_init_remote_participant(struct proxy_participant *proxypp); + +void q_omg_security_remote_participant_set_initialized(struct proxy_participant *proxypp); + +bool q_omg_security_remote_participant_is_initialized(struct proxy_participant *proxypp); + +/** + * @brief Registers the matched proxy participant with the crypto plugin + * + * When the proxy participant is authenticated and allowed by access control then the match between the local and + * the remote participant must be registered with the cypto factory provided by the crypto plugin. The + * shared secret handle obtained from the authentication phase and the permission handle returned when validating + * the proxy participant with access control plugin have to be provided. + * + * + * @param[in] pp The participant. + * @param[in] proxypp The proxy participant. + * @param[in] shared_secret The shared_secret handle. + * + * @returns bool + * @retval true The proxy participant is allowed. + * @retval false The proxy participant is not allowed. + */ +bool q_omg_security_register_remote_participant(struct participant *pp, struct proxy_participant *proxypp, int64_t shared_secret); + +/** + * @brief Removes a registered proxy participant from administation of the authentication, + * access control and crypto plugins. + * + * @param[in] proxypp The proxy participant. + */ +void q_omg_security_deregister_remote_participant(struct proxy_participant *proxypp); + +/** + * @brief Generate and send the crypto tokens needed for encoding RTPS messages. + * + * When the security settings indicate that RTPS message encoding or signing is + * configured for the participant then this function will ask the cypto echange for + * the corresponding cypto tokens and send these to the proxy participant. + * + * @param[in] pp The participant. + * @param[in] proxypp The proxy participant. + */ +void q_omg_security_participant_send_tokens(struct participant *pp, struct proxy_participant *proxypp); + +/** + * @brief Get the cypto handle associated with the proxy participant. + * + * This function returns the handle which is the association between + * the proxy participant and the crypto plugin. This handle is created + * when the proxy participant is registered with the crypto plugin. + * + * @param[in] proxypp The proxy participant. + * + * @returns handle + * @retval !0 Valid crypto handle associated with the proxy participant. + * @retval 0 Otherwise. + */ +int64_t q_omg_security_get_remote_participant_handle(struct proxy_participant *proxypp); + +/** + * @brief Set the crypto tokens used for the encryption and decryption of RTPS messages. + * + * The remote participant will send the crypto tokens when the security settings determine that the + * communication between the participants must be secure. These tokens are used for the necryption and + * decryption of complete RTPS messages. When these tokens are received this function will register these tokens + * with the crypto plugin. The crypto plugin will return a crypto handle that will be used to associate the + * stored tokens with the remote participant. + * + * @param[in] pp The local participant. + * @param[in] proxypp The remote participant. + * @param[in] tokens The crypto token received from the remote participant for the local participant. + */ +void q_omg_security_set_participant_crypto_tokens(struct participant *pp, struct proxy_participant *proxypp, const nn_dataholderseq_t *tokens); /** * @brief Set security information, depending on plist and proxy participant, @@ -231,10 +612,220 @@ set_proxy_reader_security_info( * @param[in] pwr Proxy writer to set security info on. * @param[in] plist Paramater list, possibly contains security info. */ -void -set_proxy_writer_security_info( - struct proxy_writer *pwr, - const ddsi_plist_t *plist); +void set_proxy_writer_security_info(struct proxy_writer *pwr, const ddsi_plist_t *plist); + +/** + * @brief Determine the security settings associated with the remote writer. + * + * From the security information contained in the parameter list from the remote writer + * the corresponding security settings are determined and returned in the info parameter. + * + * @param[in] pwr The remote writer. + * @param[in] plist The parameter list from the remote writer. + * @param[out] info The security settings associated with the remote writer. + */ +void q_omg_get_proxy_writer_security_info(struct proxy_writer *pwr, const ddsi_plist_t *plist, nn_security_info_t *info); + +/** + * @brief Check if the writer has the is_discovery_protected flag set + * + * @param[in] wr The local writer. + * + * @returns bool True if the writer has the is_discovery_protected flag set + */ +bool q_omg_writer_is_discovery_protected(const struct writer *wr); + +/** + * @brief Check if the writer has the is_submessage_protected flag set + * + * @param[in] wr The local writer. + * + * @returns bool True if the writer has the is_submessage_protected flag set + */ +bool q_omg_writer_is_submessage_protected(const struct writer *wr); + +/** + * @brief Check if the writer has the is_payload_protected flag set + * + * @param[in] wr The local writer. + * + * @returns bool True if the writer has the is_payload_protected flag set + */ +bool q_omg_writer_is_payload_protected(const struct writer *wr); + +/** + * @brief Check if the remote writer is allowed to communicate with endpoints of the + * local participant. + * + * This function will check with the access control plugin if the remote writer + * is allowed to communicate with this participant. + * + * @param[in] pwr The remote writer. + * @param[in] domain_id The domain id. + * @param[in] pp The local participant. + * + * @returns bool + * @retval true The remote writer is allowed to communicate. + * @retval false Otherwise. + */ +bool q_omg_security_check_remote_writer_permissions(const struct proxy_writer *pwr, uint32_t domain_id, struct participant *pp); + +/** + * @brief Check it the remote writer is allowed to communicate with the local reader. + * + * When a remote writer is allowed by access control it has to be checked if the remote + * writer is allowed to communicate with a particular local reader. This function will + * check if the provided security end-point attributes are compatible, When the security + * attributes are compatible then the function will register the reader and remote writer + * match with the crypto factory and will also ask the crypto exchange to generate the + * crypto tokens associate with the local reader which will be sent to the remote entity. + * Note that the reader crypto tokens are used to encrypt the reader specific submessages + * when submessage encoding or signing is configured. + * + * @param[in] rd The local reader. + * @param[in] pwr The remote writer. + * @param[out] crypto_handle The crypto handle associated with the match. + * + * @returns bool + * @retval true The local reader and remote writer are allowed to communicate. + * @retval false Otherwise. + */ +bool q_omg_security_match_remote_writer_enabled(struct reader *rd, struct proxy_writer *pwr, int64_t *crypto_handle); + +/** + * @brief Release the security information associated with the match between a reader and + * a remote writer. + * + * This function releases the security resources that were allocated for this reader and remote + * writer match. For example it will release the security tokens that where associated with this + * reader and the remote writer. + * + * @param[in] gv The global parameters. + * @param[in] rd_guid The guid of the reader. + * @param[in] match The reader-proxy_writer match. + */ +void q_omg_security_deregister_remote_writer_match(const struct ddsi_domaingv *gv, const ddsi_guid_t *rd_guid, struct rd_pwr_match *match); + +/** + * @brief Set the crypto tokens used for the secure communication from the remote writer to the reader. + * + * The remote writer instance will send the crypto tokens when the security settings determine that the + * communication between the remote writer and the reader must be secure. When these tokens are received + * this function will register these tokens with the crypto plugin and set the corresponding crypto handle returned + * by the crypto plugin which is then used for decrypting messages received from that remote writer to the reader. + * + * @param[in] rd The local reader. + * @param[in] pwr_guid The guid of the remote writer. + * @param[in] tokens The crypto token received from the remote writer for the reader. + */ +void q_omg_security_set_remote_writer_crypto_tokens(struct reader *rd, const ddsi_guid_t *pwr_guid, const nn_dataholderseq_t *tokens); + +/** + * @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 + * + * @param[in] rd The local reader. + * + * @returns bool True if the reader has the is_discovery_protected flag set + */ +bool q_omg_reader_is_discovery_protected(const struct reader *rd); + +/** + * @brief Check if the reader has the is_submessage_protected flag set + * + * @param[in] rd The local reader. + * + * @returns bool True if the reader has the is_submessage_protected flag set + */ +bool q_omg_reader_is_submessage_protected(const struct reader *rd); + +/** + * @brief Check if the remote reader is allowed to communicate with endpoints of the + * local participant. + * + * This function will check with the access control plugin if the remote reader + * is allowed to communicate with this participant. + * + * @param[in] prd The remote reader. + * @param[in] domain_id The domain id. + * @param[in] pp The local participant. + * + * @returns bool + * @retval true The remote reader is allowed to communicate. + * @retval false Otherwise. + */ +bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *prd, uint32_t domain_id, struct participant *pp); + +/** + * @brief Check it the local writer is allowed to communicate with the remote reader. + * + * When a remote reader is allowed by accessstruct dds_security_garbage control it has to be checked if the local + * writer is allowed to communicate with a particular local writer. This function will + * check if the provided security end-point attributes are compatible, When the security + * attributes are compatible then the function will register the writer and remote reader + * match with the crypto factory and will also ask the crypto exchange to generate the + * crypto tokens associate with the local writer which will be sent to the remote entity. + * Note that the writer crypto tokens are used to encrypt the writer specific submessages + * when submessage encoding or signing is configured and also the crypto tokens used + * for encoding the payload of data or datafrag messages. + * + * @param[in] wr The local writer. + * @param[in] prd The remote reader. + * @param[out] crypto_handle The crypto handle associated with the match. + * + * @returns bool + * @retval true The local writer and remote reader are allowed to communicate. + * @retval false Otherwise. + */ +bool q_omg_security_match_remote_reader_enabled(struct writer *wr, struct proxy_reader *prd, int64_t *crypto_handle); + +/** + * @brief Release the security information associated with the match between a writer and + * a remote reader. + * + * This function releases the security resources that were allocated for this writer and remote + * reader match. For example it will release the security tokens that where associated with this + * writer and the remote reader. + * + * @param[in] gv The global parameters. + * @param[in] wr_guid The guid of the writer. + * @param[in] match The writer-proxy_reader match. + */ +void q_omg_security_deregister_remote_reader_match(const struct ddsi_domaingv *gv, const ddsi_guid_t *wr_guid, struct wr_prd_match *match); + +/** + * @brief Set the crypto tokens used for the secure communication from the remote reader to the writer. + * + * The remote reader instance will send the crypto tokens when the security settings determine that the + * communication between the remote reader and the writer must be secure. When these tokens are received + * this function will register these tokens with the crypto plugin and set the corresponding crypto handle returned + * by the crypto plugin which is then used for decrypting messages received from that remote reader to the writer. + * + * @param[in] wr The local writer. + * @param[in] prd_guid The guid of the remote reader. + * @param[in] tokens The crypto token received from the remote reader for the writer. + */ +void q_omg_security_set_remote_reader_crypto_tokens(struct writer *wr, const ddsi_guid_t *prd_guid, const nn_dataholderseq_t *tokens); /** * @brief Encode RTPS message. @@ -253,8 +844,9 @@ set_proxy_writer_security_info( */ bool q_omg_security_encode_rtps_message( + const struct ddsi_domaingv *gv, int64_t src_handle, - ddsi_guid_t *src_guid, + const ddsi_guid_t *src_guid, const unsigned char *src_buf, size_t src_len, unsigned char **dst_buf, @@ -283,11 +875,7 @@ q_omg_security_encode_rtps_message( * contains the payload that should be send. * @retval false Encoding was necessary, but failed. */ -bool -encode_payload( - struct writer *wr, - ddsrt_iovec_t *vec, - unsigned char **buf); +bool encode_payload(struct writer *wr, ddsrt_iovec_t *vec, unsigned char **buf); /** * @brief Decode the payload of a Data submessage. @@ -309,13 +897,7 @@ encode_payload( * contains the data that should be deserialized. * @retval false Decoding was necessary, but failed. */ -bool -decode_Data( - const struct ddsi_domaingv *gv, - struct nn_rsample_info *sampleinfo, - unsigned char *payloadp, - uint32_t payloadsz, - size_t *submsg_len); +bool decode_Data(const struct ddsi_domaingv *gv, struct nn_rsample_info *sampleinfo, unsigned char *payloadp, uint32_t payloadsz, size_t *submsg_len); /** * @brief Decode the payload of a DataFrag submessage. @@ -337,13 +919,7 @@ decode_Data( * contains the data that should be deserialized. * @retval false Decoding was necessary, but failed. */ -bool -decode_DataFrag( - const struct ddsi_domaingv *gv, - struct nn_rsample_info *sampleinfo, - unsigned char *payloadp, - uint32_t payloadsz, - size_t *submsg_len); +bool decode_DataFrag(const struct ddsi_domaingv *gv, struct nn_rsample_info *sampleinfo, unsigned char *payloadp, uint32_t payloadsz, size_t *submsg_len); /** * @brief Encode datareader submessage when necessary. @@ -359,12 +935,7 @@ decode_DataFrag( * @param[in] pwr Writer for which the message is intended. * @param[in] rd_guid Origin reader guid. */ -void -encode_datareader_submsg( - struct nn_xmsg *msg, - struct nn_xmsg_marker sm_marker, - struct proxy_writer *pwr, - const struct ddsi_guid *rd_guid); +void encode_datareader_submsg(struct nn_xmsg *msg, struct nn_xmsg_marker sm_marker, struct proxy_writer *pwr, const struct ddsi_guid *rd_guid); /** * @brief Encode datawriter submessage when necessary. @@ -379,11 +950,7 @@ encode_datareader_submsg( * @param[in,out] sm_marker Submessage location within message. * @param[in] wr Origin writer guid. */ -void -encode_datawriter_submsg( - struct nn_xmsg *msg, - struct nn_xmsg_marker sm_marker, - struct writer *wr); +void encode_datawriter_submsg(struct nn_xmsg *msg, struct nn_xmsg_marker sm_marker, struct writer *wr); /** * @brief Check if given submessage is properly decoded. @@ -461,16 +1028,7 @@ decode_SecPrefix( * @retval NN_RTPS_MSG_STATE_ENCODED Decoding succeeded. * @retval NN_RTPS_MSG_STATE_ERROR Decoding failed. */ -nn_rtps_msg_state_t -decode_rtps_message( - struct thread_state1 * const ts1, - struct ddsi_domaingv *gv, - struct nn_rmsg **rmsg, - Header_t **hdr, - unsigned char **buff, - ssize_t *sz, - struct nn_rbufpool *rbpool, - bool isstream); +nn_rtps_msg_state_t decode_rtps_message(struct thread_state1 * const ts1, struct ddsi_domaingv *gv, struct nn_rmsg **rmsg, Header_t **hdr, unsigned char **buff, ssize_t *sz, struct nn_rbufpool *rbpool, bool isstream); /** * @brief Send the RTPS message securely. @@ -491,6 +1049,7 @@ decode_rtps_message( */ ssize_t secure_conn_write( + const struct ddsi_domaingv *gv, ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, @@ -518,239 +1077,58 @@ secure_conn_write( dds_return_t q_omg_security_load( struct dds_security_context *security_context, const dds_qos_t *qos ); -void q_omg_security_init( struct dds_security_context **sc, const struct ddsrt_log_cfg *logcfg); +void q_omg_security_init( struct ddsi_domaingv *gv ); -void q_omg_security_deinit( struct dds_security_context **sc); +void q_omg_security_deinit( struct ddsi_domaingv *gv ); bool q_omg_is_security_loaded( struct dds_security_context *sc ); -/** - * @brief Check if the participant and the proxy participant - * have compatible security info settings. - * - * Associated with a secure participant is the ParticipantSecurityInfo parameter. - * This parameter contains the setting of the security attributes and the associated - * plugin security attributes of the secure participant. - * This function will check if the received ParticipantSecurityInfo parameter is - * compatible with the local ParticipantSecurityInfo parameter. - * - * @param[in] pp The participant. - * @param[in] proxypp The proxy participant. - * - * @returns bool - * @retval true The participant and the proxy participant have compatible - * security info settings. - * @retval false Otherwise. - */ -bool q_omg_is_similar_participant_security_info(struct participant *pp, struct proxy_participant *proxypp); - -/** - * @brief Check if the participant allows communication with unauthenticated - * participants - * - * @param[in] pp The participant. - * - * @returns bool - * @retval true The participant allows unauthenticated communication - * @retval false Otherwise. - */ -bool q_omg_participant_allow_unauthenticated(struct participant *pp); - -/** - * @brief Register participant with security plugin and check if the - * participant is allowed by security. - * - * This function will register the participant with the authentication - * plugin which will check if the provided security QoS parameters are - * correct, e.g. is the provided certificate valid, etc. - * When that is successful it is checked with access control if the - * participant has the correct permissions and is allowed to be created. - * - * @param[in] pp The participant. - * @param[in] domain_id The domain id. - * - * @returns bool - * @retval true The security check on the participant succeeded. - * @retval false The security check on the participant failed. - */ -bool q_omg_security_check_create_participant(struct participant *pp, uint32_t domain_id); - -/** - * @brief Initialize the proxy participant security attributes - * - * @param[in] proxypp The proxy participant. - * - */ -void q_omg_security_init_remote_participant(struct proxy_participant *proxypp); - -/** - * @brief Check the if the proxy participant is allowed by checking the security permissions. - * - * The access control plugin is ask to verify if the proxy participant is allowed to - * communicate with the local participant. When the proxy participant is allowed the - * function will return a valid permission handle which is provided by the access control plugin. - * - * @param[in] domain_id The domain id - * @param[in] pp The participant - * @param[in] proxypp The proxy participant - * - * @returns permission handle - * @retval !0 The proxy participant is allowed - * @retval 0 The proxy participant is not allowed. - */ -int64_t q_omg_security_check_remote_participant_permissions(uint32_t domain_id, struct participant *pp, struct proxy_participant *proxypp); - -/** - * @brief Registers the matched proxy participant with the crypto plugin - * - * When the proxy participant is authenticated and allowed by access control then the match between the local and - * the remote participant must be registered with the cypto factory provided by the crypto plugin. The - * shared secret handle obtained from the authentication phase and the permission handle returned when validating - * the proxy participant with access control plugin have to be provided. - * - * - * @param[in] pp The participant. - * @param[in] proxypp The proxy participant. - * @param[in] shared_secret The shared_secret handle. - * @param[in] proxy_permissions The permission handle associated with the proxy participant. - */ -void q_omg_security_register_remote_participant(struct participant *pp, struct proxy_participant *proxypp, int64_t shared_secret, int64_t proxy_permissions); - -/** - * @brief Removes a registered proxy participant from administation of the authentication, - * access control and crypto plugins. - * - * @param[in] proxypp The proxy participant. - */ -void q_omg_security_deregister_remote_participant(struct proxy_participant *proxypp); - -/** - * @brief Generate and send the crypto tokens needed for encoding RTPS messages. - * - * When the security settings indicate that RTPS message encoding or signing is - * configured for the participant then this function will ask the cypto echange for - * the corresponding cypto tokens and send these to the proxy participant. - * - * @param[in] pp The participant. - * @param[in] proxypp The proxy participant. - */ -void q_omg_security_participant_send_tokens(struct participant *pp, struct proxy_participant *proxypp); - -/** - * @brief Check if the remote writer is allowed to communicate with endpoints of the - * local participant. - * - * This function will check with the access control plugin if the remote writer - * is allowed to communicate with this participant. - * - * @param[in] pwr The remote writer. - * @param[in] domain_id The domain id. - * @param[in] pp The local participant. - * - * @returns bool - * @retval true The remote writer is allowed to communicate. - * @retval false Otherwise. - */ -bool q_omg_security_check_remote_writer_permissions(const struct proxy_writer *pwr, uint32_t domain_id, struct participant *pp); - -/** - * @brief Check if the remote reader is allowed to communicate with endpoints of the - * local participant. - * - * This function will check with the access control plugin if the remote reader - * is allowed to communicate with this participant. - * - * @param[in] prd The remote reader. - * @param[in] domain_id The domain id. - * @param[in] pp The local participant. - * - * @returns bool - * @retval true The remote reader is allowed to communicate. - * @retval false Otherwise. - */ -bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *prd, uint32_t domain_id, struct participant *pp); - -/** - * @brief Check it the remote writer is allowed to communicate with the local reader. - * - * When a remote writer is allowed by access control it has to be checked if the remote - * writer is allowed to communicate with a particular local reader. This function will - * check if the provided security end-point attributes are compatible, When the security - * attributes are compatible then the function will register the reader and remote writer - * match with the crypto factory and will also ask the crypto exchange to generate the - * crypto tokens associate with the local reader which will be sent to the remote entity. - * Note that the reader crypto tokens are used to encrypt the reader specific submessages - * when submessage encoding or signing is configured. - * - * @param[in] rd The local reader. - * @param[in] pwr The remote writer. - * - * @returns bool - * @retval true The local reader and remote writer are allowed to communicate. - * @retval false Otherwise. - */ -bool q_omg_security_match_remote_writer_enabled(struct reader *rd, struct proxy_writer *pwr); - -/** - * @brief Check it the local writer is allowed to communicate with the remote reader. - * - * When a remote reader is allowed by access control it has to be checked if the local - * writer is allowed to communicate with a particular local writer. This function will - * check if the provided security end-point attributes are compatible, When the security - * attributes are compatible then the function will register the writer and remote reader - * match with the crypto factory and will also ask the crypto exchange to generate the - * crypto tokens associate with the local writer which will be sent to the remote entity. - * Note that the writer crypto tokens are used to encrypt the writer specific submessages - * when submessage encoding or signing is configured and also the crypto tokens used - * for encoding the payload of data or datafrag messages. - * - * @param[in] wr The local writer. - * @param[in] prd The remote reader. - * - * @returns bool - * @retval true The local writer and remote reader are allowed to communicate. - * @retval false Otherwise. - */ -bool q_omg_security_match_remote_reader_enabled(struct writer *wr, struct proxy_reader *prd); - #else /* DDSI_INCLUDE_SECURITY */ #include "dds/ddsi/q_unused.h" -inline bool -q_omg_participant_is_secure( - UNUSED_ARG(const struct participant *pp)) +inline bool q_omg_security_enabled(void) { return false; } -inline bool -q_omg_proxy_participant_is_secure( - UNUSED_ARG(const struct proxy_participant *proxypp)) +inline bool q_omg_participant_is_access_protected(UNUSED_ARG(const struct participant *pp)) { return false; } -inline unsigned -determine_subscription_writer( - UNUSED_ARG(const struct reader *rd)) +inline bool q_omg_participant_is_rtps_protected(UNUSED_ARG(const struct participant *pp)) +{ + return false; +} + +inline bool q_omg_participant_is_liveliness_protected(UNUSED_ARG(const struct participant *pp)) +{ + return false; +} + +inline bool q_omg_participant_is_secure(UNUSED_ARG(const struct participant *pp)) +{ + return false; +} + +inline bool q_omg_proxy_participant_is_secure(UNUSED_ARG(const struct proxy_participant *proxypp)) +{ + return false; +} + +inline unsigned determine_subscription_writer(UNUSED_ARG(const struct reader *rd)) { return NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER; } -inline unsigned -determine_publication_writer( - UNUSED_ARG(const struct writer *wr)) +inline unsigned determine_publication_writer(UNUSED_ARG(const struct writer *wr)) { return NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER; } -inline bool -is_proxy_participant_deletion_allowed( - UNUSED_ARG(struct ddsi_domaingv * const gv), - UNUSED_ARG(const struct ddsi_guid *guid), - UNUSED_ARG(const ddsi_entityid_t pwr_entityid)) +inline bool is_proxy_participant_deletion_allowed(UNUSED_ARG(struct ddsi_domaingv * const gv), UNUSED_ARG(const struct ddsi_guid *guid), UNUSED_ARG(const ddsi_entityid_t pwr_entityid)) { return true; } @@ -765,12 +1143,56 @@ inline bool q_omg_participant_allow_unauthenticated(UNUSED_ARG(struct participan return true; } -inline bool -q_omg_security_check_create_participant(UNUSED_ARG(struct participant *pp), UNUSED_ARG(uint32_t domain_id)) +inline bool q_omg_security_check_create_participant(UNUSED_ARG(struct participant *pp), UNUSED_ARG(uint32_t domain_id)) { return true; } +inline void q_omg_security_deregister_participant(UNUSED_ARG(struct participant *pp)) +{ +} + +inline bool q_omg_security_check_create_topic(UNUSED_ARG(const struct ddsi_domaingv *gv), UNUSED_ARG(const ddsi_guid_t *pp_guid), UNUSED_ARG(const char *topic_name), UNUSED_ARG(const struct dds_qos *qos)) +{ + return true; +} + +inline int64_t q_omg_security_get_local_participant_handle(UNUSED_ARG(const struct participant *pp)) +{ + return 0; +} + +inline bool q_omg_security_check_create_writer(UNUSED_ARG(struct participant *pp), UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(const char *topic_name), UNUSED_ARG(const struct dds_qos *writer_qos)) +{ + return true; +} + +inline void q_omg_security_register_writer(UNUSED_ARG(struct writer *wr)) +{ +} + +inline void q_omg_security_deregister_writer(UNUSED_ARG(struct writer *wr)) +{ +} + +inline bool q_omg_security_check_create_reader(UNUSED_ARG(struct participant *pp), UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(const char *topic_name), UNUSED_ARG(const struct dds_qos *reader_qos)) +{ + return true; +} + +inline void q_omg_security_register_reader(UNUSED_ARG(struct reader *rd)) +{ +} + +inline void q_omg_security_deregister_reader(UNUSED_ARG(struct reader *rd)) +{ +} + +inline bool q_omg_security_is_remote_rtps_protected(UNUSED_ARG(const struct proxy_participant *proxypp), UNUSED_ARG(ddsi_entityid_t entityid)) +{ + return false; +} + inline void q_omg_security_init_remote_participant(UNUSED_ARG(struct proxy_participant *proxypp)) { } @@ -780,8 +1202,9 @@ inline int64_t q_omg_security_check_remote_participant_permissions(UNUSED_ARG(ui return 0LL; } -inline void q_omg_security_register_remote_participant(UNUSED_ARG(struct participant *pp), UNUSED_ARG(struct proxy_participant *proxypp), UNUSED_ARG(int64_t shared_secret), UNUSED_ARG(int64_t proxy_permissions)) +inline bool q_omg_security_register_remote_participant(UNUSED_ARG(struct participant *pp), UNUSED_ARG(struct proxy_participant *proxypp), UNUSED_ARG(int64_t identity_handle), UNUSED_ARG(int64_t shared_secret)) { + return true; } inline void q_omg_security_deregister_remote_participant(UNUSED_ARG(struct proxy_participant *proxypp)) @@ -792,46 +1215,78 @@ inline void q_omg_security_participant_send_tokens(UNUSED_ARG(struct participant { } -inline bool q_omg_security_match_remote_writer_enabled(UNUSED_ARG(struct reader *rd), UNUSED_ARG(struct proxy_writer *pwr)) +inline int64_t q_omg_security_get_remote_participant_handle(UNUSED_ARG(struct proxy_participant *proxypp)) +{ + return 0; +} + +inline bool q_omg_security_match_remote_writer_enabled(UNUSED_ARG(struct reader *rd), UNUSED_ARG(struct proxy_writer *pwr), UNUSED_ARG(int64_t *crypto_handle)) { return true; } -inline bool q_omg_security_match_remote_reader_enabled(UNUSED_ARG(struct writer *wr), UNUSED_ARG(struct proxy_reader *prd)) +inline bool q_omg_security_match_remote_reader_enabled(UNUSED_ARG(struct writer *wr), UNUSED_ARG(struct proxy_reader *prd), UNUSED_ARG(int64_t *crypto_handle)) { return true; } -inline bool -q_omg_security_check_remote_writer_permissions(UNUSED_ARG(const struct proxy_writer *pwr), UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(struct participant *pp)) +inline void q_omg_get_proxy_writer_security_info(UNUSED_ARG(struct proxy_writer *pwr), UNUSED_ARG(const ddsi_plist_t *plist), UNUSED_ARG(nn_security_info_t *info)) +{ +} + +inline bool q_omg_writer_is_discovery_protected(UNUSED_ARG(const struct writer *wr)) +{ + return false; +} + +inline bool q_omg_writer_is_submessage_protected(UNUSED_ARG(const struct writer *wr)) +{ + return false; +} + +inline bool q_omg_writer_is_payload_protected(UNUSED_ARG(const struct writer *wr)) +{ + return false; +} + +inline bool q_omg_security_check_remote_writer_permissions(UNUSED_ARG(const struct proxy_writer *pwr), UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(struct participant *pp)) { return true; } -inline bool -q_omg_security_check_remote_reader_permissions(UNUSED_ARG(const struct proxy_reader *prd), UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(struct participant *pp)) +inline void q_omg_security_deregister_remote_writer_match(UNUSED_ARG(const struct proxy_writer *pwr), UNUSED_ARG(const struct reader *rd), UNUSED_ARG(struct rd_pwr_match *match)) +{ +} + +inline void q_omg_get_proxy_reader_security_info(UNUSED_ARG(struct proxy_reader *prd), UNUSED_ARG(const ddsi_plist_t *plist), UNUSED_ARG(nn_security_info_t *info)) +{ +} + +inline bool q_omg_reader_is_discovery_protected(UNUSED_ARG(const struct reader *rd)) +{ + return false; +} + +inline bool q_omg_reader_is_submessage_protected(UNUSED_ARG(const struct reader *rd)) +{ + return false; +} + + +inline bool q_omg_security_check_remote_reader_permissions(UNUSED_ARG(const struct proxy_reader *prd), UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(struct participant *pp)) { return true; } -inline void -set_proxy_participant_security_info( - UNUSED_ARG(struct proxy_participant *prd), - UNUSED_ARG(const ddsi_plist_t *plist)) +inline void set_proxy_participant_security_info(UNUSED_ARG(struct proxy_participant *prd), UNUSED_ARG(const ddsi_plist_t *plist)) { } -inline void -set_proxy_reader_security_info( - UNUSED_ARG(struct proxy_reader *prd), - UNUSED_ARG(const ddsi_plist_t *plist)) +inline void set_proxy_reader_security_info(UNUSED_ARG(struct proxy_reader *prd), UNUSED_ARG(const ddsi_plist_t *plist)) { } -inline void -set_proxy_writer_security_info( - UNUSED_ARG(struct proxy_writer *pwr), - UNUSED_ARG(const ddsi_plist_t *plist)) +inline void set_proxy_writer_security_info(UNUSED_ARG(struct proxy_writer *pwr), UNUSED_ARG(const ddsi_plist_t *plist)) { } @@ -924,6 +1379,24 @@ inline void q_omg_security_deinit( UNUSED_ARG( struct dds_security_context *sc) inline bool q_omg_is_security_loaded( UNUSED_ARG( struct dds_security_context *sc )) { return false; } +inline void q_omg_security_deregister_remote_reader_match(UNUSED_ARG(const struct proxy_reader *prd), UNUSED_ARG(const struct writer *wr), UNUSED_ARG(struct wr_prd_match *match)) +{ +} + +inline bool q_omg_plist_keyhash_is_protected(UNUSED_ARG(const ddsi_plist_t *plist)) +{ + return false; +} + +inline bool q_omg_is_endpoint_protected(UNUSED_ARG(const ddsi_plist_t *plist)) +{ + return false; +} + +inline void q_omg_log_endpoint_protection(UNUSED_ARG(struct ddsi_domaingv * const gv), UNUSED_ARG(const ddsi_plist_t *plist)) +{ +} + #endif /* DDSI_INCLUDE_SECURITY */ #if defined (__cplusplus) diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_security_util.h b/src/core/ddsi/include/dds/ddsi/ddsi_security_util.h new file mode 100644 index 0000000..7c03496 --- /dev/null +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_util.h @@ -0,0 +1,91 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSI_SECURITY_UTIL_H +#define DDSI_SECURITY_UTIL_H + +#ifdef DDSI_INCLUDE_SECURITY + +#include "dds/ddsi/ddsi_plist.h" +#include "dds/security/core/dds_security_utils.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +void g_omg_shallow_copy_StringSeq(DDS_Security_StringSeq *dst, const ddsi_stringseq_t *src); + +void g_omg_shallow_free_StringSeq(DDS_Security_StringSeq *obj); + +void q_omg_copy_PropertySeq(DDS_Security_PropertySeq *dst, const dds_propertyseq_t *src); + +void q_omg_shallow_copyin_PropertySeq(DDS_Security_PropertySeq *dst, const dds_propertyseq_t *src); + +void q_omg_shallow_copyout_PropertySeq(dds_propertyseq_t *dst, const DDS_Security_PropertySeq *src); + +void q_omg_shallow_free_PropertySeq(DDS_Security_PropertySeq *obj); + +void q_omg_shallow_copyin_BinaryPropertySeq(DDS_Security_BinaryPropertySeq *dst, const dds_binarypropertyseq_t *src); + +void q_omg_shallow_copyout_BinaryPropertySeq(dds_binarypropertyseq_t *dst, const DDS_Security_BinaryPropertySeq *src); + +void q_omg_shallow_free_BinaryPropertySeq(DDS_Security_BinaryPropertySeq *obj); + +void q_omg_shallow_copy_PropertyQosPolicy(DDS_Security_PropertyQosPolicy *dst, const dds_property_qospolicy_t *src); + +void q_omg_shallow_copy_security_qos(DDS_Security_Qos *dst, const struct dds_qos *src); + +void q_omg_shallow_free_PropertyQosPolicy(DDS_Security_PropertyQosPolicy *obj); + +void q_omg_shallow_free_security_qos(DDS_Security_Qos *obj); + +void q_omg_security_dataholder_copyin(nn_dataholder_t *dh, const DDS_Security_DataHolder *holder); + +void q_omg_security_dataholder_copyout(DDS_Security_DataHolder *holder, const nn_dataholder_t *dh); + +void q_omg_shallow_copyin_DataHolder(DDS_Security_DataHolder *dst, const nn_dataholder_t *src); + +void q_omg_shallow_copyout_DataHolder(nn_dataholder_t *dst, const DDS_Security_DataHolder *src); + +void q_omg_shallow_free_DataHolder(DDS_Security_DataHolder *obj); + +void q_omg_shallow_free_nn_dataholder(nn_dataholder_t *holder); + +void q_omg_shallow_copyin_DataHolderSeq(DDS_Security_DataHolderSeq *dst, const nn_dataholderseq_t *src); + +void q_omg_copyin_DataHolderSeq(DDS_Security_DataHolderSeq *dst, const nn_dataholderseq_t *src); + +void q_omg_shallow_copyout_DataHolderSeq(nn_dataholderseq_t *dst, const DDS_Security_DataHolderSeq *src); + +void q_omg_shallow_free_DataHolderSeq(DDS_Security_DataHolderSeq *obj); + +void q_omg_shallow_free_nn_dataholderseq(nn_dataholderseq_t *obj); + +void q_omg_shallow_copy_ParticipantBuiltinTopicDataSecure(DDS_Security_ParticipantBuiltinTopicDataSecure *dst, const ddsi_guid_t *guid, const ddsi_plist_t *plist); + +void q_omg_shallow_free_ParticipantBuiltinTopicDataSecure(DDS_Security_ParticipantBuiltinTopicDataSecure *obj); + +void q_omg_shallow_copy_SubscriptionBuiltinTopicDataSecure(DDS_Security_SubscriptionBuiltinTopicDataSecure *dst, const ddsi_guid_t *guid, const struct dds_qos *qos, const nn_security_info_t *secinfo); + +void q_omg_shallow_free_SubscriptionBuiltinTopicDataSecure(DDS_Security_SubscriptionBuiltinTopicDataSecure *obj); + +void q_omg_shallow_copy_PublicationBuiltinTopicDataSecure(DDS_Security_PublicationBuiltinTopicDataSecure *dst, const ddsi_guid_t *guid, const struct dds_qos *qos, const nn_security_info_t *secinfo); + +void q_omg_shallow_free_PublicationBuiltinTopicDataSecure(DDS_Security_PublicationBuiltinTopicDataSecure *obj); + +#if defined (__cplusplus) +} +#endif + + +#endif /* DDSI_INCLUDE_SECURITY */ + +#endif /* DDSI_SECURITY_UTIL_H */ diff --git a/src/core/ddsi/include/dds/ddsi/q_ddsi_discovery.h b/src/core/ddsi/include/dds/ddsi/q_ddsi_discovery.h index c5c801e..e18dde9 100644 --- a/src/core/ddsi/include/dds/ddsi/q_ddsi_discovery.h +++ b/src/core/ddsi/include/dds/ddsi/q_ddsi_discovery.h @@ -25,6 +25,8 @@ struct nn_rsample_info; struct nn_rdata; struct ddsi_plist; +void get_participant_builtin_topic_data(const struct participant *pp, struct nn_xmsg *mpayload, bool be); + int spdp_write (struct participant *pp); int spdp_dispose_unregister (struct participant *pp); diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 306029b..37b4fff 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -45,6 +45,10 @@ struct whc; struct dds_qos; struct ddsi_plist; struct lease; +struct participant_sec_attributes; +struct proxy_participant_sec_attributes; +struct writer_sec_attributes; +struct reader_sec_attributes; struct proxy_group; struct proxy_endpoint_common; @@ -83,6 +87,9 @@ typedef void (*status_cb_t) (void *entity, const status_cb_data_t *data); struct prd_wr_match { ddsrt_avl_node_t avlnode; ddsi_guid_t wr_guid; +#ifdef DDSI_INCLUDE_SECURITY + int64_t crypto_handle; +#endif }; struct rd_pwr_match { @@ -94,6 +101,9 @@ struct rd_pwr_match { nn_locator_t ssm_mc_loc; nn_locator_t ssm_src_loc; #endif +#ifdef DDSI_INCLUDE_SECURITY + int64_t crypto_handle; +#endif }; struct wr_rd_match { @@ -128,6 +138,9 @@ struct wr_prd_match { nn_wctime_t hb_to_ack_latency_tlastlog; uint32_t non_responsive_count; uint32_t rexmit_requests; +#ifdef DDSI_INCLUDE_SECURITY + int64_t crypto_handle; +#endif }; enum pwr_rd_match_syncstate { @@ -156,6 +169,9 @@ struct pwr_rd_match { struct nn_reorder *reorder; /* can be done (mostly) per proxy writer, but that is harder; only when state=OUT_OF_SYNC */ } not_in_sync; } u; +#ifdef DDSI_INCLUDE_SECURITY + int64_t crypto_handle; +#endif }; struct nn_rsample_info; @@ -218,8 +234,6 @@ struct participant ddsrt_atomic_voidp_t minl_man; /* lease object for shortest manual-by-participant liveliness writer's lease */ ddsrt_fibheap_t leaseheap_man; /* keeps leases for this participant's writers (with liveliness manual-by-participant) */ #ifdef DDSI_INCLUDE_SECURITY - int64_t local_identity_handle; /* OMG DDS Security related member */ - int64_t permissions_handle; /* OMG DDS Security related member */ struct participant_sec_attributes *sec_attr; nn_security_info_t security_info; #endif @@ -286,6 +300,7 @@ struct writer uint32_t whc_low, whc_high; /* watermarks for WHC in bytes (counting only unack'd data) */ nn_etime_t t_rexmit_end; /* time of last 1->0 transition of "retransmitting" */ nn_etime_t t_whc_high_upd; /* time "whc_high" was last updated for controlled ramp-up of throughput */ + uint32_t num_readers; /* total number of matching PROXY readers */ int32_t num_reliable_readers; /* number of matching reliable PROXY readers */ ddsrt_avl_tree_t readers; /* all matching PROXY readers, see struct wr_prd_match */ ddsrt_avl_tree_t local_readers; /* all matching LOCAL readers, see struct wr_rd_match */ @@ -301,6 +316,9 @@ struct writer struct xeventq *evq; /* timed event queue to be used by this writer */ struct local_reader_ary rdary; /* LOCAL readers for fast-pathing; if not fast-pathed, fall back to scanning local_readers */ struct lease *lease; /* for liveliness administration (writer can only become inactive when using manual liveliness) */ +#ifdef DDSI_INCLUDE_SECURITY + struct writer_sec_attributes *sec_attr; +#endif }; inline seqno_t writer_read_seq_xmit (const struct writer *wr) { @@ -333,10 +351,14 @@ struct reader struct addrset *as; #endif const struct ddsi_sertopic * topic; /* topic is NULL for built-in readers */ + uint32_t num_writers; /* total number of matching PROXY writers */ ddsrt_avl_tree_t writers; /* all matching PROXY writers, see struct rd_pwr_match */ ddsrt_avl_tree_t local_writers; /* all matching LOCAL writers, see struct rd_wr_match */ ddsi2direct_directread_cb_t ddsi2direct_cb; void *ddsi2direct_cbarg; +#ifdef DDSI_INCLUDE_SECURITY + struct reader_sec_attributes *sec_attr; +#endif }; struct proxy_participant @@ -366,7 +388,6 @@ struct proxy_participant unsigned proxypp_have_spdp: 1; unsigned owns_lease: 1; #ifdef DDSI_INCLUDE_SECURITY - int64_t remote_identity_handle; /* OMG DDS Security related member */ nn_security_info_t security_info; struct proxy_participant_sec_attributes *sec_attr; #endif @@ -435,6 +456,9 @@ struct proxy_writer { ddsi2direct_directread_cb_t ddsi2direct_cb; void *ddsi2direct_cbarg; struct lease *lease; +#ifdef DDSI_INCLUDE_SECURITY + nn_security_info_t security_info; +#endif }; @@ -450,6 +474,9 @@ struct proxy_reader { #endif ddsrt_avl_tree_t writers; /* matching LOCAL writers */ filter_fn_t filter; +#ifdef DDSI_INCLUDE_SECURITY + nn_security_info_t security_info; +#endif }; DDS_EXPORT extern const ddsrt_avl_treedef_t wr_readers_treedef; @@ -533,8 +560,8 @@ nn_vendorid_t get_entity_vendorid (const struct entity_common *e); /** * @brief Create a new participant with a given GUID in the domain. * - * @param[in] ppguid - * The GUID of the new participant. + * @param[in,out] ppguid + * The GUID of the new participant, may be adjusted by security. * @param[in] flags * Zero or more of: * - RTPS_PF_NO_BUILTIN_READERS do not create discovery readers in new ppant @@ -555,7 +582,7 @@ nn_vendorid_t get_entity_vendorid (const struct entity_common *e); * @retval DDS_RETCODE_OUT_OF_RESOURCES * The configured maximum number of participants has been reached. */ -dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct ddsi_domaingv *gv, unsigned flags, const struct ddsi_plist *plist); +dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv, unsigned flags, const struct ddsi_plist *plist); /** * @brief Create a new participant in the domain. See also new_participant_guid. @@ -720,8 +747,8 @@ void rebuild_or_clear_writer_addrsets(struct ddsi_domaingv *gv, int rebuild); void local_reader_ary_setfastpath_ok (struct local_reader_ary *x, bool fastpath_ok); -void connect_writer_with_proxy_reader_secure(struct writer *wr, struct proxy_reader *prd, nn_mtime_t tnow); -void connect_reader_with_proxy_writer_secure(struct reader *rd, struct proxy_writer *pwr, nn_mtime_t tnow); +void connect_writer_with_proxy_reader_secure(struct writer *wr, struct proxy_reader *prd, nn_mtime_t tnow, int64_t crypto_handle); +void connect_reader_with_proxy_writer_secure(struct reader *rd, struct proxy_writer *pwr, nn_mtime_t tnow, int64_t crypto_handle); struct ddsi_writer_info; diff --git a/src/core/ddsi/include/dds/ddsi/q_misc.h b/src/core/ddsi/include/dds/ddsi/q_misc.h index 22bb720..98a7457 100644 --- a/src/core/ddsi/include/dds/ddsi/q_misc.h +++ b/src/core/ddsi/include/dds/ddsi/q_misc.h @@ -35,6 +35,7 @@ unsigned char normalize_data_datafrag_flags (const SubmessageHeader_t *smhdr); int WildcardOverlap(char * p1, char * p2); #endif +DDS_EXPORT bool guid_prefix_zero (const ddsi_guid_prefix_t *a); DDS_EXPORT int guid_prefix_eq (const ddsi_guid_prefix_t *a, const ddsi_guid_prefix_t *b); DDS_EXPORT int guid_eq (const struct ddsi_guid *a, const struct ddsi_guid *b); DDS_EXPORT int ddsi2_patmatch (const char *pat, const char *str); diff --git a/src/core/ddsi/include/dds/ddsi/q_xevent.h b/src/core/ddsi/include/dds/ddsi/q_xevent.h index a3ba7b5..6542633 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xevent.h +++ b/src/core/ddsi/include/dds/ddsi/q_xevent.h @@ -50,8 +50,10 @@ DDS_EXPORT dds_return_t xeventq_start (struct xeventq *evq, const char *name); / DDS_EXPORT void xeventq_stop (struct xeventq *evq); DDS_EXPORT void qxev_msg (struct xeventq *evq, struct nn_xmsg *msg); + DDS_EXPORT void qxev_pwr_entityid (struct proxy_writer * pwr, const ddsi_guid_t *guid); DDS_EXPORT void qxev_prd_entityid (struct proxy_reader * prd, const ddsi_guid_t *guid); +DDS_EXPORT void qxev_nt_callback (struct xeventq *evq, void (*cb) (void *arg), void *arg); /* Returns 1 if queued, 0 otherwise (no point in returning the event, you can't do anything with it anyway) */ diff --git a/src/core/ddsi/include/dds/ddsi/q_xmsg.h b/src/core/ddsi/include/dds/ddsi/q_xmsg.h index e82a81d..fcd6db1 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xmsg.h +++ b/src/core/ddsi/include/dds/ddsi/q_xmsg.h @@ -128,10 +128,12 @@ void nn_xmsg_submsg_setnext (struct nn_xmsg *msg, struct nn_xmsg_marker marker); void nn_xmsg_submsg_init (struct nn_xmsg *msg, struct nn_xmsg_marker marker, SubmessageKind_t smkind); void nn_xmsg_add_timestamp (struct nn_xmsg *m, nn_wctime_t t); void nn_xmsg_add_entityid (struct nn_xmsg * m); +void *nn_xmsg_addpar_bo (struct nn_xmsg *m, nn_parameterid_t pid, size_t len, bool be); void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len); void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serdata, bool force_md5); void nn_xmsg_addpar_statusinfo (struct nn_xmsg *m, unsigned statusinfo); void nn_xmsg_addpar_sentinel (struct nn_xmsg *m); +void nn_xmsg_addpar_sentinel_bo (struct nn_xmsg * m, bool be); int nn_xmsg_addpar_sentinel_ifparam (struct nn_xmsg *m); /* XPACK */ diff --git a/src/core/ddsi/src/ddsi_handshake.c b/src/core/ddsi/src/ddsi_handshake.c index 63de1a0..5d1b967 100644 --- a/src/core/ddsi/src/ddsi_handshake.c +++ b/src/core/ddsi/src/ddsi_handshake.c @@ -12,27 +12,76 @@ #include "dds/ddsi/ddsi_handshake.h" + #ifdef DDSI_INCLUDE_SECURITY +#include + +#include "dds/ddsi/q_bswap.h" +#include "dds/ddsi/ddsi_entity_index.h" +#include "dds/ddsi/ddsi_plist.h" +#include "dds/ddsi/q_entity.h" +#include "dds/security/dds_security_api_types.h" #include "dds/security/dds_security_api.h" -#include "dds/ddsrt/hopscotch.h" +#include "dds/ddsi/ddsi_security_omg.h" +#include "dds/security/core/dds_security_fsm.h" +#include "dds/ddsi/ddsi_security_util.h" +#include "dds/ddsi/ddsi_security_exchange.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/avl.h" + +#define HSTRACE(...) DDS_CTRACE (&handshake->gv->logconfig, __VA_ARGS__) +#define HSWARNING(...) DDS_CLOG (DDS_LC_WARNING, &handshake->gv->logconfig, __VA_ARGS__) +#define HSERROR(...) DDS_CLOG (DDS_LC_ERROR, &handshake->gv->logconfig, __VA_ARGS__) + +#define HSEXCEPTION(e, ...) \ + q_omg_log_exception(&handshake->gv->logconfig, DDS_LC_WARNING, e, __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) + + +#define VERBOSE_HANDSHAKE_DEBUG + +#if 1 +#define TRACE_FUNC(ptr) +#else +#undef TRACE +#define TRACE(args) nn_trace args +#define TRACE_FUNC(ptr) printf("[%p] %s\n", ptr, __FUNCTION__); +#endif + +typedef enum { + EVENT_AUTO = DDS_SECURITY_FSM_EVENT_AUTO, + EVENT_TIMEOUT = DDS_SECURITY_FSM_EVENT_TIMEOUT, + EVENT_VALIDATION_OK = DDS_SECURITY_VALIDATION_OK, + EVENT_VALIDATION_FAILED = DDS_SECURITY_VALIDATION_FAILED, + EVENT_VALIDATION_PENDING_RETRY = DDS_SECURITY_VALIDATION_PENDING_RETRY, + EVENT_VALIDATION_PENDING_HANDSHAKE_REQUEST = DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_REQUEST, + EVENT_VALIDATION_PENDING_HANDSHAKE_MESSAGE = DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE, + EVENT_VALIDATION_OK_FINAL_MESSAGE = DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE, + EVENT_RECEIVED_MESSAGE_REQUEST = 100, + EVENT_RECEIVED_MESSAGE_REPLY = 101, + EVENT_RECEIVED_MESSAGE_FINAL = 102, + EVENT_SEND_CRYPTO_TOKENS = 103, + EVENT_RECV_CRYPTO_TOKENS = 104 +} handshake_event_t; + +struct handshake_entities { + ddsi_guid_t lguid; + ddsi_guid_t rguid; +}; struct ddsi_handshake { + ddsrt_avl_node_t avlnode; enum ddsi_handshake_state state; - - ddsi_guid_t local_pguid; /* the guid of the local participant */ - ddsi_guid_t remote_pguid; /* the guid of the remote participant */ - ddsi_handshake_end_cb_t end_cb; - struct ddsi_domaingv *gv; - ddsrt_mutex_t lock; - ddsrt_cond_t cv; - - ddsrt_atomic_uint32_t refc; - - DDS_Security_IdentityHandle local_identity_handle; - DDS_Security_IdentityHandle remote_identity_handle; + struct handshake_entities participants; DDS_Security_HandshakeHandle handshake_handle; + ddsrt_atomic_uint32_t refc; + ddsrt_atomic_uint32_t deleting; + ddsi_handshake_end_cb_t end_cb; + ddsrt_mutex_t lock; + struct dds_security_fsm *fsm; + const struct ddsi_domaingv *gv; + dds_security_authentication *auth; DDS_Security_HandshakeMessageToken handshake_message_in_token; nn_message_identity_t handshake_message_in_id; @@ -40,58 +89,1121 @@ struct ddsi_handshake DDS_Security_AuthRequestMessageToken local_auth_request_token; DDS_Security_AuthRequestMessageToken *remote_auth_request_token; DDS_Security_OctetSeq pdata; - DDS_Security_SharedSecretHandle shared_secret; + int64_t shared_secret; int handled_handshake_message; }; +struct ddsi_hsadmin { + ddsrt_mutex_t lock; + ddsrt_avl_tree_t handshakes; + struct dds_security_fsm_control *fsm_control; +}; + +static int compare_handshake(const void *va, const void *vb); + +const ddsrt_avl_treedef_t handshake_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct ddsi_handshake, avlnode), offsetof (struct ddsi_handshake, participants), compare_handshake, 0); + +static int compare_handshake(const void *va, const void *vb) +{ + const struct handshake_entities *ha = va; + const struct handshake_entities *hb = vb; + int r; + + r = memcmp(&ha->rguid, &hb->rguid, sizeof(ha->rguid)); + if (r == 0) + r = memcmp(&ha->lguid, &hb->lguid, sizeof(ha->lguid)); + return r; +} + +static bool validate_handshake(struct ddsi_handshake *handshake, struct participant **pp, struct proxy_participant **proxypp) +{ + if (ddsrt_atomic_ld32(&handshake->deleting) > 0) + return false; + + if (pp) + { + if ((*pp = entidx_lookup_participant_guid(handshake->gv->entity_index, &handshake->participants.lguid)) == NULL) + return false; + } + + if (proxypp) + { + if ((*proxypp = entidx_lookup_proxy_participant_guid(handshake->gv->entity_index, &handshake->participants.rguid)) == NULL) + return false; + } + return true; +} + + +#define RETRY_TIMEOUT DDS_SECS(1) +#define RESEND_TIMEOUT DDS_SECS(1) +#define SEND_TOKENS_TIMEOUT DDS_MSECS(100) +#define AUTHENTICATION_TIMEOUT DDS_SECS(100) + +static void func_validate_remote_identity (struct dds_security_fsm *fsm, void *arg); +static void func_handshake_init_message_resend(struct dds_security_fsm *fsm, void *arg); +static void func_begin_handshake_reply (struct dds_security_fsm *fsm, void *arg); +static void func_begin_handshake_request (struct dds_security_fsm *fsm, void *arg); +static void func_process_handshake (struct dds_security_fsm *fsm, void *arg); +static void func_handshake_message_resend (struct dds_security_fsm *fsm, void *arg); +static void func_validation_ok (struct dds_security_fsm *fsm, void *arg); +static void func_validation_failed (struct dds_security_fsm *fsm, void *arg); +static void func_send_crypto_tokens_final (struct dds_security_fsm *fsm, void *arg); +static void func_send_crypto_tokens (struct dds_security_fsm *fsm, void *arg); + +static dds_security_fsm_state state_validate_remote_identity = { func_validate_remote_identity, 0 }; +static dds_security_fsm_state state_validate_remote_identity_retry_wait = { NULL, RETRY_TIMEOUT }; +static dds_security_fsm_state state_handshake_init_message_resend = { func_handshake_init_message_resend, 0 }; +static dds_security_fsm_state state_handshake_init_message_wait = { NULL, RESEND_TIMEOUT }; +static dds_security_fsm_state state_begin_handshake_reply = { func_begin_handshake_reply, 0 }; +static dds_security_fsm_state state_begin_handshake_reply_retry_wait = { NULL, RETRY_TIMEOUT }; +static dds_security_fsm_state state_begin_handshake_request = { func_begin_handshake_request, 0 }; +static dds_security_fsm_state state_begin_handshake_request_retry_wait = { NULL, RETRY_TIMEOUT }; +static dds_security_fsm_state state_process_handshake = { func_process_handshake, 0 }; +static dds_security_fsm_state state_process_handshake_retry_wait = { NULL, RETRY_TIMEOUT }; +static dds_security_fsm_state state_handshake_message_resend = { func_handshake_message_resend, 0 }; +static dds_security_fsm_state state_handshake_message_wait = { NULL, RESEND_TIMEOUT }; +static dds_security_fsm_state state_validation_ok = { func_validation_ok, 0 }; +static dds_security_fsm_state state_validation_failed = { func_validation_failed, 0 }; +static dds_security_fsm_state state_send_crypto_tokens_final_wait = { NULL, SEND_TOKENS_TIMEOUT }; +static dds_security_fsm_state state_send_crypto_tokens_wait = { NULL, SEND_TOKENS_TIMEOUT }; +static dds_security_fsm_state state_send_crypto_tokens_final = { func_send_crypto_tokens_final, 0 }; +static dds_security_fsm_state state_send_crypto_tokens = { func_send_crypto_tokens, 0 }; +static dds_security_fsm_state state_wait_crypto_tokens = { NULL, 0 }; +static dds_security_fsm_state state_handshake_final_resend = { func_handshake_message_resend, 0 }; + +#ifdef VERBOSE_HANDSHAKE_DEBUG +static void q_handshake_fsm_debug( + struct dds_security_fsm *fsm, + DDS_SECURITY_FSM_DEBUG_ACT act, + const dds_security_fsm_state *current, + int event_id, + void *arg) +{ + struct ddsi_handshake *handshake = arg; + char *dispatch; + char *state; + char *event; + + assert(handshake); + DDSRT_UNUSED_ARG(fsm); + + + if (current == NULL) state = "NULL"; + else if (current == &state_validate_remote_identity) state = "state_validate_remote_identity"; + else if (current == &state_validate_remote_identity_retry_wait) state = "state_validate_remote_identity_retry_wait"; + else if (current == &state_handshake_init_message_resend) state = "state_handshake_init_message_resend"; + else if (current == &state_handshake_init_message_wait) state = "state_handshake_init_message_wait"; + else if (current == &state_begin_handshake_reply) state = "state_begin_handshake_reply"; + else if (current == &state_begin_handshake_reply_retry_wait) state = "state_begin_handshake_reply_retry_wait"; + else if (current == &state_begin_handshake_request) state = "state_begin_handshake_request"; + else if (current == &state_begin_handshake_request_retry_wait) state = "state_begin_handshake_request_retry_wait"; + else if (current == &state_process_handshake) state = "state_process_handshake"; + else if (current == &state_process_handshake_retry_wait) state = "state_process_handshake_retry_wait"; + else if (current == &state_handshake_message_resend) state = "state_handshake_message_resend"; + else if (current == &state_handshake_message_wait) state = "state_handshake_message_wait"; + else if (current == &state_validation_ok) state = "state_validation_ok"; + else if (current == &state_validation_failed) state = "state_validation_failed"; + else if (current == &state_send_crypto_tokens_final_wait) state = "state_send_crypto_tokens_final_wait"; + else if (current == &state_send_crypto_tokens_wait) state = "state_send_crypto_tokens_wait"; + else if (current == &state_send_crypto_tokens_final) state = "state_send_crypto_tokens_final"; + else if (current == &state_send_crypto_tokens) state = "state_send_crypto_tokens"; + else if (current == &state_wait_crypto_tokens) state = "state_wait_crypto_tokens"; + else if (current == &state_handshake_final_resend) state = "state_handshake_final_resend"; + else state = "else????"; + + if (event_id == EVENT_AUTO) event = "EVENT_AUTO"; + else if (event_id == EVENT_TIMEOUT) event = "EVENT_TIMEOUT"; + else if (event_id == EVENT_VALIDATION_OK) event = "EVENT_VALIDATION_OK"; + else if (event_id == EVENT_VALIDATION_FAILED) event = "EVENT_VALIDATION_FAILED"; + else if (event_id == EVENT_VALIDATION_PENDING_RETRY) event = "EVENT_VALIDATION_PENDING_RETRY"; + else if (event_id == EVENT_VALIDATION_PENDING_HANDSHAKE_REQUEST) event = "EVENT_VALIDATION_PENDING_HANDSHAKE_REQUEST"; + else if (event_id == EVENT_VALIDATION_PENDING_HANDSHAKE_MESSAGE) event = "EVENT_VALIDATION_PENDING_HANDSHAKE_MESSAGE"; + else if (event_id == EVENT_VALIDATION_OK_FINAL_MESSAGE) event = "EVENT_VALIDATION_OK_FINAL_MESSAGE"; + else if (event_id == EVENT_RECEIVED_MESSAGE_REQUEST) event = "EVENT_RECEIVED_MESSAGE_REQUEST"; + else if (event_id == EVENT_RECEIVED_MESSAGE_REPLY) event = "EVENT_RECEIVED_MESSAGE_REPLY"; + else if (event_id == EVENT_RECEIVED_MESSAGE_FINAL) event = "EVENT_RECEIVED_MESSAGE_FINAL"; + else if (event_id == EVENT_SEND_CRYPTO_TOKENS) event = "EVENT_SEND_CRYPTO_TOKENS"; + else if (event_id == EVENT_RECV_CRYPTO_TOKENS) event = "EVENT_RECV_CRYPTO_TOKENS"; + else event = ""; + + if (act == DDS_SECURITY_FSM_DEBUG_ACT_DISPATCH) dispatch = "dispatching"; + else if (act == DDS_SECURITY_FSM_DEBUG_ACT_DISPATCH_DIRECT) dispatch = "direct_dispatching"; + else if (act == DDS_SECURITY_FSM_DEBUG_ACT_HANDLING) dispatch = "handling"; + else dispatch = ""; + + HSTRACE ("FSM: handshake_debug (lguid="PGUIDFMT" rguid="PGUIDFMT") act=%s, state=%s, event=%s\n", + PGUID (handshake->participants.lguid), + PGUID (handshake->participants.rguid), + dispatch, + state, + event); + +} +#endif + + +/************************************************************************************************************ + Inspiration from https://confluence.prismtech.com/display/VC/Authentication?preview=/30379826/34340895/PT_StateMachine_3g.gif + + [START] + | + v + .---------------------------------. + | state_validate_remote_identity | + .------------|---------------------------------|----------.--------------------. + | | func_validate_remote_identity() | | | + | '---------------------------------' | VALIDATION_PENDING_HANDSHAKE_MESSAGE +VALIDATION_FAILED ^ | VALIDATION_PENDING_RETRY | | +VALIDATION_OK | | | | + | TIMEOUT | v | v + | .-------------------------------------------. | .-----------------------------------. + | | state_validate_remote_identity_retry_wait | | | state_handshake_init_message_wait |<---------------. + | |-------------------------------------------| | |-----------------------------------| AUTO | + | | retry_timeout | | | resend_timeout |---------. | + | '-------------------------------------------' | '-----------------------------------' TIMEOUT | | + | | | | | + | .-----------------------------------' | | | + | | VALIDATION_PENDING_HANDSHAKE_REQUEST | v | + | | | .--------------------------------------. + | v RECEIVED_MESSAGE_REQUEST | state_handshake_init_message_resend | + | .--------------------------------. | |--------------------------------------| + | | state_begin_handshake_request | VALIDATION_PENDING_RETRY | | func_handshake_init_message_resend() | + | |--------------------------------|------------. | '--------------------------------------' + | | func_begin_handshake_request() | | | ^ + | '--------------------------------' | | | + | | | ^ | | | + | | | | TIMEOUT v | | + | VALIDATION_FAILED | .------------------------------------------. | | + | VALIDATION_OK | | state_begin_handshake_request_retry_wait | | | + | | | |------------------------------------------| | | + |--------' | | retry_timeout | | | + | | '------------------------------------------' | | + | | v VALIDATION_FAILED + | | .------------------------------. | + | VALIDATION_PENDING_HANDSHAKE_MESSAGE | state_begin_handshake_reply |------------' + | | .-------|------------------------------| + | | | | func_begin_handshake_reply() |------------. + | | | '------------------------------' | + | | | VALIDATION_OK | ^ VALIDATION_PENDING_RETRY + | | | | | | + | | VALIDATION_PENDING_HANDSHAKE_MESSAGE v | TIMEOUT | + | | | goto state_validation_ok | | + | | v | v + | | .------------------------------. .------------------------------------------. + | | | state_handshake_message_wait | | state_begin_handshake_reply_retry_wait | + | .--------------->|------------------------------|-------. |------------------------------------------| + | | | resend_timeout | | | retry_timeout | + | | '------------------------------' | '------------------------------------------' + | | AUTO | ^ | + | | TIMEOUT | | | + | .---------------------------------. | | | RECEIVED_MESSAGE_REPLY + | | state_handshake_message_resend | | VALIDATION_FAILED | RECEIVED_MESSAGE_FINAL + | |---------------------------------|<--------------' | | + | | func_handshake_message_resend() | | v + | '---------------------------------' .--------------------------. + | | state_process_handshake | + | .--------------------------------|--------------------------|--------------------------. + | | .------------------>| func_process_handshake() | | + | | | '--------------------------' | + | | | | | + | VALIDATION_PENDING_RETRY TIMEOUT VALIDATION_OK | | + | v | v | + | .------------------------------------. .-------------------------------. | + | | state_process_handshake_retry_wait | | state_send_crypto_tokens_wait | | + | |------------------------------------| |-------------------------------| | + | | retry_timeout | | send_tokens_timeout | | + | '------------------------------------' '-------------------------------' | + | | | VALIDATION_OK_FINAL_MESSAGE + | .-------------' '---------. | + | | RECV_CRYPTO_TOKENS TIMEOUT | | + | v v | + | .---------------------------------. .---------------------------. | + | | state_send_crypto_tokens_final | | state_send_crypto_tokens | | + | .--------------|---------------------------------| |---------------------------| | + | | | func_send_crypto_tokens_final() | | func_send_crypto_tokens() | | + | | '---------------------------------' '---------------------------' | + | | ^ | | + | VALIDATION_OK | .--------------------. VALIDATION_OK_FINAL_MESSAGE | + | | TIMEOUT | | RECV_CRYPTO_TOKENS | | | + | | | v | v | + | | .-------------------------------------. .--------------------------. | + | | | state_send_crypto_tokens_final_wait | | state_wait_crypto_tokens |<--------' + | | |-------------------------------------| |--------------------------| + | | | send_tokens_timeout | | |---------. + | | '-------------------------------------' '--------------------------' | + | | ^ | ^ | + | | | RECEIVED_MESSAGE_REPLY AUTO VALIDATION_OK + | | RECV_CRYPTO_TOKENS v | | + | | | .---------------------------------. | + | | | | state_handshake_final_resend | | + | | '---------------------|---------------------------------| | + | VALIDATION_OK | | func_handshake_message_resend() | | + |---------------------------------------------------------. '---------------------------------' | + | | | + '---------------. | | +VALIDATION_FAILED | | | + v v | + .--------------------------. .----------------------. | + | state_validation_failed | | state_validation_ok | | + |--------------------------| |----------------------|<----------------------------------------' + | func_validation_failed() | | func_validation_ok() | + '--------------------------' '----------------------' + | | + v v + [END] [END] + + + .----------------------------------------. + | state_begin_handshake_reply_retry_wait | + |----------------------------------------| + | retry_timeout | + '----------------------------------------' + + +*************************************************************************************************************/ +static const dds_security_fsm_transition handshake_transistions [] = +{ /* Start */ + { NULL, EVENT_AUTO, NULL, + &state_validate_remote_identity }, + /* validate remote identity */ + { &state_validate_remote_identity, EVENT_VALIDATION_PENDING_RETRY, NULL, + &state_validate_remote_identity_retry_wait }, + { &state_validate_remote_identity, EVENT_VALIDATION_FAILED, NULL, + &state_validation_failed }, + { &state_validate_remote_identity, EVENT_VALIDATION_PENDING_HANDSHAKE_REQUEST, NULL, + &state_begin_handshake_request }, + { &state_validate_remote_identity, EVENT_VALIDATION_OK, NULL, + &state_validation_ok }, + { &state_validate_remote_identity, EVENT_VALIDATION_PENDING_HANDSHAKE_MESSAGE, NULL, + &state_handshake_init_message_wait }, + /* ValRemIdentityRetryWait */ + { &state_validate_remote_identity_retry_wait, EVENT_TIMEOUT, NULL, + &state_validate_remote_identity }, + /* HandshakeInitMessageWait */ + { &state_handshake_init_message_wait, EVENT_TIMEOUT, NULL, + &state_handshake_init_message_resend }, + { &state_handshake_init_message_wait, EVENT_RECEIVED_MESSAGE_REQUEST, NULL, + &state_begin_handshake_reply }, + /* resend message */ + { &state_handshake_init_message_resend, EVENT_AUTO, NULL, + &state_handshake_init_message_wait }, + /* begin handshake reply */ + { &state_begin_handshake_reply, EVENT_VALIDATION_PENDING_RETRY, NULL, + &state_begin_handshake_reply_retry_wait }, + { &state_begin_handshake_reply, EVENT_VALIDATION_FAILED, NULL, + &state_handshake_init_message_resend }, + { &state_begin_handshake_reply, EVENT_VALIDATION_PENDING_HANDSHAKE_MESSAGE, NULL, + &state_handshake_message_wait }, + { &state_begin_handshake_reply, EVENT_VALIDATION_OK, NULL, + &state_validation_ok }, + /* BeginHsRepRetryWait */ + { &state_begin_handshake_reply_retry_wait, EVENT_TIMEOUT, NULL, + &state_begin_handshake_reply }, + /* begin handshake request */ + { &state_begin_handshake_request, EVENT_VALIDATION_PENDING_RETRY, NULL, + &state_begin_handshake_request_retry_wait }, + { &state_begin_handshake_request, EVENT_VALIDATION_FAILED, NULL, + &state_validation_failed }, + { &state_begin_handshake_request, EVENT_VALIDATION_PENDING_HANDSHAKE_MESSAGE, NULL, + &state_handshake_message_wait }, + { &state_begin_handshake_request, EVENT_VALIDATION_OK, NULL, + &state_validation_ok }, + /* BeginHsReqRetryWait */ + { &state_begin_handshake_request_retry_wait, EVENT_TIMEOUT, NULL, + &state_begin_handshake_request }, + /* HandshakeMessageWait */ + { &state_handshake_message_wait, EVENT_TIMEOUT, NULL, + &state_handshake_message_resend }, + { &state_handshake_message_wait, EVENT_RECEIVED_MESSAGE_REPLY, NULL, + &state_process_handshake }, + { &state_handshake_message_wait, EVENT_RECEIVED_MESSAGE_FINAL, NULL, + &state_process_handshake }, + /* resend message */ + { &state_handshake_message_resend, EVENT_AUTO, NULL, + &state_handshake_message_wait }, + /* process handshake */ + { &state_process_handshake, EVENT_VALIDATION_PENDING_RETRY, NULL, + &state_process_handshake_retry_wait }, + { &state_process_handshake, EVENT_VALIDATION_FAILED, NULL, + &state_handshake_message_wait }, + { &state_process_handshake, EVENT_VALIDATION_OK, NULL, + &state_send_crypto_tokens_wait }, + { &state_process_handshake, EVENT_VALIDATION_OK_FINAL_MESSAGE, NULL, + &state_wait_crypto_tokens }, + /* ProcessHsRetryWait */ + { &state_process_handshake_retry_wait, EVENT_TIMEOUT, NULL, + &state_process_handshake }, + + { &state_send_crypto_tokens_wait, EVENT_TIMEOUT, NULL, + &state_send_crypto_tokens }, + { &state_send_crypto_tokens_wait, EVENT_RECV_CRYPTO_TOKENS, NULL, + &state_send_crypto_tokens_final }, + + { &state_send_crypto_tokens_final_wait, EVENT_TIMEOUT, NULL, + &state_send_crypto_tokens_final }, + + /* Process_handshake returned VALIDATION_OK_FINAL_MESSAGE notify user and wait for tokens */ + { &state_send_crypto_tokens, EVENT_VALIDATION_OK_FINAL_MESSAGE, NULL, + &state_wait_crypto_tokens }, + /* Process_handshake returned VALIDATION_OK notify user and goto ready state */ + { &state_send_crypto_tokens_final, EVENT_VALIDATION_OK, NULL, + &state_validation_ok }, + + { &state_handshake_final_resend, EVENT_AUTO, NULL, + &state_wait_crypto_tokens }, + + { &state_handshake_final_resend, EVENT_RECV_CRYPTO_TOKENS, NULL, + &state_send_crypto_tokens_final_wait }, + + { &state_wait_crypto_tokens, EVENT_RECV_CRYPTO_TOKENS, NULL, + &state_send_crypto_tokens_final_wait }, + + { &state_wait_crypto_tokens, EVENT_VALIDATION_OK, NULL, + &state_validation_ok }, + + { &state_wait_crypto_tokens, EVENT_RECEIVED_MESSAGE_REPLY, NULL, + &state_handshake_final_resend }, + + /* End */ + { &state_validation_ok, EVENT_AUTO, NULL, + NULL }, + { &state_validation_failed, EVENT_AUTO, NULL, + NULL }, +}; + + + +static bool send_handshake_message(const struct ddsi_handshake *handshake, DDS_Security_DataHolder *token, struct participant *pp, struct proxy_participant *proxypp, int request) +{ + bool ret = false; + nn_dataholderseq_t mdata; + DDS_Security_DataHolderSeq tseq; + + tseq._length = tseq._maximum = 1; + tseq._buffer = token; + + q_omg_shallow_copyout_DataHolderSeq(&mdata, &tseq); + + if (!(ret = write_auth_handshake_message(pp, proxypp, &mdata, request, &handshake->handshake_message_in_id))) + { + HSWARNING("Send handshake: failed to send message (lguid="PGUIDFMT" rguid="PGUIDFMT")", PGUID (pp->e.guid), PGUID (proxypp->e.guid)); + } + + q_omg_shallow_free_nn_dataholderseq(&mdata); + + return ret; +} + +static void func_validate_remote_identity(struct dds_security_fsm *fsm, void *arg) +{ + DDS_Security_ValidationResult_t ret; + DDS_Security_SecurityException exception = {0}; + struct ddsi_handshake *handshake = (struct ddsi_handshake*)arg; + dds_security_authentication *auth = handshake->auth; + struct participant *pp; + struct proxy_participant *proxypp; + DDS_Security_IdentityToken remote_identity_token; + int64_t remote_identity_handle; + ddsi_guid_t remote_guid; + + if (!validate_handshake(handshake, &pp, &proxypp)) + return; + + TRACE_FUNC(fsm); + + if (!(proxypp->plist->present & PP_IDENTITY_TOKEN)) + { + HSERROR("validate remote identity failed: remote participant ("PGUIDFMT") identity token missing", PGUID (proxypp->e.guid)); + ret = DDS_SECURITY_VALIDATION_FAILED; + goto ident_token_missing; + } + + remote_guid = nn_hton_guid(proxypp->e.guid); + q_omg_security_dataholder_copyout(&remote_identity_token, &proxypp->plist->identity_token); + + ddsrt_mutex_lock(&handshake->lock); + ret = auth->validate_remote_identity( + auth, &remote_identity_handle, &handshake->local_auth_request_token, handshake->remote_auth_request_token, + pp->sec_attr->local_identity_handle, &remote_identity_token, (DDS_Security_GUID_t *)&remote_guid, &exception); + ddsrt_mutex_unlock(&handshake->lock); + + /* Trace a failed handshake. */ + if ((ret != DDS_SECURITY_VALIDATION_OK ) && + (ret != DDS_SECURITY_VALIDATION_PENDING_RETRY ) && + (ret != DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_REQUEST) && + (ret != DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE)) + { + HSEXCEPTION(&exception, "Validate remote identity failed"); + ret = DDS_SECURITY_VALIDATION_FAILED; + goto validation_failed; + } + + HSTRACE("FSM: validate_remote_identity (lguid="PGUIDFMT" rguid="PGUIDFMT") ret=%d\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid), ret); + + assert(proxypp->sec_attr->remote_identity_handle == 0 || proxypp->sec_attr->remote_identity_handle == remote_identity_handle); + proxypp->sec_attr->remote_identity_handle = remote_identity_handle; + + DDS_Security_DataHolder_deinit(&remote_identity_token); + + /* When validate_remote_identity returns a local_auth_request_token + * which does not equal TOKEN_NIL then an AUTH_REQUEST message has + * to be send. + */ + if (handshake->local_auth_request_token.class_id && strlen(handshake->local_auth_request_token.class_id) != 0) + (void)send_handshake_message(handshake, &handshake->local_auth_request_token, pp, proxypp, 1); + +validation_failed: +ident_token_missing: + /* Use return value as state machine event. */ + dds_security_fsm_dispatch(fsm, (int32_t)ret, true); +} + +static void func_handshake_init_message_resend(struct dds_security_fsm *fsm, void *arg) +{ + struct ddsi_handshake *handshake = arg; + struct participant *pp; + struct proxy_participant *proxypp; + + DDSRT_UNUSED_ARG(fsm); + + if (!validate_handshake(handshake, &pp, &proxypp)) + return; + + TRACE_FUNC(fsm); + + HSTRACE("FSM: handshake init_message_resend (lguid="PGUIDFMT" rguid="PGUIDFMT")\n", PGUID(pp->e.guid), PGUID(proxypp->e.guid)); + + if (strlen(handshake->local_auth_request_token.class_id) != 0) + (void)send_handshake_message(handshake, &handshake->local_auth_request_token, pp, proxypp, 1); +} + +static void func_begin_handshake_reply(struct dds_security_fsm *fsm, void *arg) +{ + DDS_Security_ValidationResult_t ret; + DDS_Security_SecurityException exception = {0}; + struct ddsi_handshake *handshake = arg; + dds_security_authentication *auth = handshake->auth; + struct participant *pp; + struct proxy_participant *proxypp; + + if (!validate_handshake(handshake, &pp, &proxypp)) + return; + + TRACE_FUNC(fsm); + + ddsrt_mutex_lock(&handshake->lock); + + if (handshake->handshake_message_out) + DDS_Security_DataHolder_free(handshake->handshake_message_out); + handshake->handshake_message_out = DDS_Security_DataHolder_alloc(); + + ret = auth->begin_handshake_reply( + auth, &(handshake->handshake_handle), handshake->handshake_message_out, &handshake->handshake_message_in_token, + proxypp->sec_attr->remote_identity_handle, pp->sec_attr->local_identity_handle, &handshake->pdata, &exception); + + ddsrt_mutex_unlock(&handshake->lock); + + HSTRACE("FSM: begin_handshake_reply (lguid="PGUIDFMT" rguid="PGUIDFMT") ret=%d\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid), ret); + + /* Trace a failed handshake. */ + if ((ret != DDS_SECURITY_VALIDATION_OK ) && + (ret != DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE ) && + (ret != DDS_SECURITY_VALIDATION_PENDING_RETRY ) && + (ret != DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE)) + { + HSEXCEPTION(&exception, "Begin handshake reply failed"); + ret = DDS_SECURITY_VALIDATION_FAILED; + goto handshake_failed; + } + + if (ret == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE) { + if (!send_handshake_message(handshake, handshake->handshake_message_out, pp, proxypp, 0)) { + ret = DDS_SECURITY_VALIDATION_FAILED; + goto handshake_failed; + } + } + else if (ret == DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE) + { + if (send_handshake_message(handshake, handshake->handshake_message_out, pp, proxypp, 0)) + ret = DDS_SECURITY_VALIDATION_OK; + else + { + ret = DDS_SECURITY_VALIDATION_FAILED; + goto handshake_failed; + } + } + + if (ret == DDS_SECURITY_VALIDATION_OK) + { + handshake->shared_secret = auth->get_shared_secret(auth, handshake->handshake_handle, &exception); + if (handshake->shared_secret == DDS_SECURITY_HANDLE_NIL) + { + HSEXCEPTION(&exception, "Getting shared secret failed"); + ret = DDS_SECURITY_VALIDATION_FAILED; + goto handshake_failed; + } + } + + dds_security_fsm_dispatch(fsm, (int32_t)ret, true); + return; + +handshake_failed: + DDS_Security_DataHolder_free(handshake->handshake_message_out); + handshake->handshake_message_out = NULL; + /* Use return value as state machine event. */ + dds_security_fsm_dispatch(fsm, (int32_t)ret, true); +} + +static void func_begin_handshake_request(struct dds_security_fsm *fsm, void *arg) +{ + DDS_Security_ValidationResult_t ret; + DDS_Security_SecurityException exception = {0}; + struct ddsi_handshake *handshake = arg; + dds_security_authentication *auth = handshake->auth; + struct participant *pp; + struct proxy_participant *proxypp; + + if (!validate_handshake(handshake, &pp, &proxypp)) + return; + + TRACE_FUNC(fsm); + + ddsrt_mutex_lock(&handshake->lock); + + if (handshake->handshake_message_out) + DDS_Security_DataHolder_free(handshake->handshake_message_out); + handshake->handshake_message_out = DDS_Security_DataHolder_alloc(); + + ret = auth->begin_handshake_request(auth, &(handshake->handshake_handle), handshake->handshake_message_out, pp->sec_attr->local_identity_handle, proxypp->sec_attr->remote_identity_handle, &handshake->pdata, &exception); + ddsrt_mutex_unlock(&handshake->lock); + + HSTRACE("FSM: begin_handshake_request (lguid="PGUIDFMT" rguid="PGUIDFMT") ret=%d\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid), ret); + + /* Trace a failed handshake. */ + if ((ret != DDS_SECURITY_VALIDATION_OK ) && + (ret != DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE ) && + (ret != DDS_SECURITY_VALIDATION_PENDING_RETRY ) && + (ret != DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE)) + { + HSEXCEPTION(&exception, "Begin handshake request failed"); + ret = DDS_SECURITY_VALIDATION_FAILED; + goto handshake_failed; + } + + if (ret == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE) + { + if (!send_handshake_message(handshake, handshake->handshake_message_out, pp, proxypp, 0)) + { + ret = DDS_SECURITY_VALIDATION_FAILED; + goto handshake_failed; + } + } + else if (ret == DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE) + { + if (send_handshake_message(handshake, handshake->handshake_message_out, pp, proxypp, 0)) + { + ret = DDS_SECURITY_VALIDATION_OK; + } else { + ret = DDS_SECURITY_VALIDATION_FAILED; + goto handshake_failed; + } + } + + if (ret == DDS_SECURITY_VALIDATION_OK) + { + handshake->shared_secret = auth->get_shared_secret(auth, handshake->handshake_handle, &exception); + if (handshake->shared_secret == DDS_SECURITY_HANDLE_NIL) + { + HSEXCEPTION(&exception, "Getting shared secret failed"); + ret = DDS_SECURITY_VALIDATION_FAILED; + goto handshake_failed; + } + } + + dds_security_fsm_dispatch(fsm, (int32_t)ret, true); + return; + +handshake_failed: + DDS_Security_DataHolder_free(handshake->handshake_message_out); + handshake->handshake_message_out = NULL; + /* Use return value as state machine event. */ + dds_security_fsm_dispatch(fsm, (int32_t)ret, true); +} + +static void func_process_handshake(struct dds_security_fsm *fsm, void *arg) +{ + DDS_Security_ValidationResult_t ret; + DDS_Security_SecurityException exception = {0}; + struct ddsi_handshake *handshake = arg; + dds_security_authentication *auth = handshake->auth; + struct participant *pp; + struct proxy_participant *proxypp; + + if (!validate_handshake(handshake, &pp, &proxypp)) + return; + + TRACE_FUNC(fsm); + + ddsrt_mutex_lock(&handshake->lock); + + if (handshake->handshake_message_out) + DDS_Security_DataHolder_free(handshake->handshake_message_out); + handshake->handshake_message_out = DDS_Security_DataHolder_alloc(); + + ret = auth->process_handshake(auth, handshake->handshake_message_out, &handshake->handshake_message_in_token, handshake->handshake_handle, &exception); + ddsrt_mutex_unlock(&handshake->lock); + + HSTRACE("FSM: process_handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") ret=%d\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid), ret); + + /* Trace a failed handshake. */ + if ((ret != DDS_SECURITY_VALIDATION_OK ) && + (ret != DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE ) && + (ret != DDS_SECURITY_VALIDATION_PENDING_RETRY )) + { + HSEXCEPTION(&exception, "Process handshake failed"); + ret = DDS_SECURITY_VALIDATION_FAILED; + goto handshake_failed; + } + + if ((ret == DDS_SECURITY_VALIDATION_OK) || (ret == DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE)) + { + handshake->shared_secret = auth->get_shared_secret(auth, handshake->handshake_handle, &exception); + if (handshake->shared_secret == DDS_SECURITY_HANDLE_NIL) + { + HSEXCEPTION(&exception, "Getting shared secret failed"); + ret = DDS_SECURITY_VALIDATION_FAILED; + goto handshake_failed; + } + handshake->end_cb(handshake, pp, proxypp, STATE_HANDSHAKE_PROCESSED); + } + + if (ret == DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE) + { + if (!send_handshake_message(handshake, handshake->handshake_message_out, pp, proxypp, 0)) + { + ret = DDS_SECURITY_VALIDATION_FAILED; + goto handshake_failed; + } + } + + dds_security_fsm_dispatch(fsm, (int32_t)ret, true); + return; + +handshake_failed: + DDS_Security_DataHolder_free(handshake->handshake_message_out); + handshake->handshake_message_out = NULL; + /* Use return value as state machine event. */ + dds_security_fsm_dispatch(fsm, (int32_t)ret, true); +} + +static void func_send_crypto_tokens(struct dds_security_fsm *fsm, void *arg) +{ + struct ddsi_handshake *handshake = arg; + struct participant *pp; + struct proxy_participant *proxypp; + + if (!validate_handshake(handshake, &pp, &proxypp)) + return; + + TRACE_FUNC(fsm); + + /* The final handshake message has been send to the remote + * participant. Call the callback function to signal that + * the corresponding crypto tokens can be send. Amd start + * waiting for the crypto tokens from the remote participant + */ + + HSTRACE("FSM: handshake send crypto tokens (lguid="PGUIDFMT" rguid="PGUIDFMT")\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid)); + handshake->end_cb(handshake, pp, proxypp, STATE_HANDSHAKE_SEND_TOKENS); + dds_security_fsm_dispatch(fsm, EVENT_VALIDATION_OK_FINAL_MESSAGE, true); +} + +static void func_send_crypto_tokens_final(struct dds_security_fsm *fsm, void *arg) +{ + struct ddsi_handshake *handshake = arg; + struct participant *pp; + struct proxy_participant *proxypp; + + if (!validate_handshake(handshake, &pp, &proxypp)) + return; + + TRACE_FUNC(fsm); + + /* The final handshake message has been send to the remote + * participant. Call the callback function to signal that + * the corresponding crypto tokens can be send. Amd start + * waiting for the crypto tokens from the remote participant + */ + + HSTRACE("FSM: handshake send crypto tokens final (lguid="PGUIDFMT" rguid="PGUIDFMT")\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid)); + handshake->end_cb(handshake, pp, proxypp, STATE_HANDSHAKE_SEND_TOKENS); + dds_security_fsm_dispatch(fsm, EVENT_VALIDATION_OK, true); +} + +static void func_handshake_message_resend(struct dds_security_fsm *fsm, void *arg) +{ + struct ddsi_handshake *handshake = arg; + struct participant *pp; + struct proxy_participant *proxypp; + + DDSRT_UNUSED_ARG(fsm); + DDSRT_UNUSED_ARG(arg); + + if (!validate_handshake(handshake, &pp, &proxypp)) + return; + + TRACE_FUNC(fsm); + + HSTRACE("handshake resend (lguid="PGUIDFMT" rguid="PGUIDFMT")\n", PGUID(pp->e.guid), PGUID(proxypp->e.guid)); + if (handshake->handshake_message_out) { + (void)send_handshake_message(handshake, handshake->handshake_message_out, pp, proxypp, 0); + } +} + +static void func_validation_ok(struct dds_security_fsm *fsm, void *arg) +{ + struct ddsi_handshake *handshake = arg; + struct participant *pp; + struct proxy_participant *proxypp; + + DDSRT_UNUSED_ARG(fsm); + + if (!validate_handshake(handshake, &pp, &proxypp)) + return; + + TRACE_FUNC(fsm); + + HSTRACE("FSM: handshake succeeded (lguid="PGUIDFMT" rguid="PGUIDFMT")\n", PGUID(pp->e.guid), PGUID(proxypp->e.guid)); + handshake->state = STATE_HANDSHAKE_OK; + handshake->end_cb(handshake, pp, proxypp, STATE_HANDSHAKE_OK); +} + +static void func_validation_failed(struct dds_security_fsm *fsm, void *arg) +{ + struct ddsi_handshake *handshake = arg; + struct participant *pp; + struct proxy_participant *proxypp; + + DDSRT_UNUSED_ARG(fsm); + + if (!validate_handshake(handshake, &pp, &proxypp)) + return; + + TRACE_FUNC(fsm); + + HSTRACE("FSM: handshake failed (lguid="PGUIDFMT" rguid="PGUIDFMT")\n", PGUID(pp->e.guid), PGUID(proxypp->e.guid)); + handshake->state = STATE_HANDSHAKE_FAILED; + handshake->end_cb(handshake, pp, proxypp, STATE_HANDSHAKE_FAILED); +} + +static void func_handshake_timeout(struct dds_security_fsm *fsm, void *arg) +{ + struct ddsi_handshake *handshake = arg; + struct participant *pp; + struct proxy_participant *proxypp; + + DDSRT_UNUSED_ARG(fsm); + + if (!validate_handshake(handshake, &pp, &proxypp)) + return; + + TRACE_FUNC(fsm); + + HSTRACE("FSM: handshake timeout (lguid="PGUIDFMT" rguid="PGUIDFMT")\n", PGUID(pp->e.guid), PGUID(proxypp->e.guid)); + handshake->state = STATE_HANDSHAKE_TIMED_OUT; + handshake->end_cb(handshake, pp, proxypp, STATE_HANDSHAKE_TIMED_OUT); +} + + +static struct ddsi_handshake * ddsi_handshake_create(struct participant *pp, struct proxy_participant *proxypp, ddsi_handshake_end_cb_t callback) +{ + const struct ddsi_domaingv * gv = pp->e.gv; + struct ddsi_hsadmin *hsadmin = pp->e.gv->hsadmin; + struct ddsi_handshake *handshake; + dds_return_t rc; + ddsi_octetseq_t pdata; + + TRACE_FUNC(NULL); + + handshake = ddsrt_malloc(sizeof(struct ddsi_handshake)); + memset(handshake, 0, sizeof(struct ddsi_handshake)); + + ddsrt_mutex_init(&handshake->lock); + handshake->auth = q_omg_participant_get_authentication(pp); + ddsrt_atomic_st32(&handshake->refc, 1); + ddsrt_atomic_st32(&handshake->deleting, 0); + handshake->participants.lguid = pp->e.guid; + handshake->participants.rguid = proxypp->e.guid; + handshake->gv = gv; + handshake->handshake_handle = 0; + handshake->shared_secret = 0; + auth_get_serialized_participant_data(pp, &pdata); + + handshake->pdata._length = handshake->pdata._maximum = pdata.length; + handshake->pdata._buffer = pdata.value; + + handshake->end_cb = callback; + + handshake->state = STATE_HANDSHAKE_IN_PROGRESS; + if (!hsadmin->fsm_control) + { + hsadmin->fsm_control = dds_security_fsm_control_create(pp->e.gv); + rc = dds_security_fsm_control_start(hsadmin->fsm_control, NULL); + if (rc < 0) + { + GVERROR("Failed to create FSM control"); + goto fsm_control_failed; + } + } + + handshake->fsm = dds_security_fsm_create(hsadmin->fsm_control, handshake_transistions, sizeof(handshake_transistions)/sizeof(handshake_transistions[0]), handshake); + if (!handshake->fsm) + { + GVERROR("Failed to create FSM"); + goto fsm_failed; + } + dds_security_fsm_set_timeout(handshake->fsm, func_handshake_timeout, AUTHENTICATION_TIMEOUT); + +#ifdef VERBOSE_HANDSHAKE_DEBUG + dds_security_fsm_set_debug(handshake->fsm, q_handshake_fsm_debug); +#endif + dds_security_fsm_start(handshake->fsm); + + return handshake; + +fsm_failed: +fsm_control_failed: + ddsrt_free(handshake); + return NULL; +} + +void ddsi_handshake_release(struct ddsi_handshake *handshake) +{ + if (!handshake) return; + + if (ddsrt_atomic_dec32_nv(&handshake->refc) == 0) + { + HSTRACE("handshake delete (lguid="PGUIDFMT" rguid="PGUIDFMT")\n", PGUID(handshake->participants.lguid), PGUID(handshake->participants.rguid)); + DDS_Security_DataHolder_deinit(&handshake->local_auth_request_token); + DDS_Security_DataHolder_deinit(&handshake->handshake_message_in_token); + DDS_Security_DataHolder_free(handshake->handshake_message_out); + DDS_Security_DataHolder_free(handshake->remote_auth_request_token); + DDS_Security_OctetSeq_deinit(&handshake->pdata); + ddsrt_mutex_destroy(&handshake->lock); + ddsrt_free(handshake); + } +} void ddsi_handshake_handle_message(struct ddsi_handshake *handshake, const struct participant *pp, const struct proxy_participant *proxypp, const struct nn_participant_generic_message *msg) { - DDSRT_UNUSED_ARG(handshake); + handshake_event_t event = EVENT_VALIDATION_FAILED; + DDSRT_UNUSED_ARG(pp); DDSRT_UNUSED_ARG(proxypp); - DDSRT_UNUSED_ARG(msg); + + assert(handshake); + assert(pp); + assert(proxypp); + assert(msg); + + TRACE_FUNC(handshake->fsm); + + if (!validate_handshake(handshake, NULL, NULL)) + return; + + HSTRACE ("FSM: handshake_handle_message (lguid="PGUIDFMT" rguid="PGUIDFMT") class_id=%s\n", + PGUID (pp->e.guid), PGUID (proxypp->e.guid), + msg->message_class_id ? msg->message_class_id: "NULL"); + + if (!msg->message_class_id || msg->message_data.n == 0 || !msg->message_data.tags[0].class_id) + { + HSERROR("received handshake message ("PGUIDFMT" --> "PGUIDFMT") does not contain a handshake message token\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid)); + goto invalid_message; + } + else if (strcmp(msg->message_class_id, DDS_SECURITY_AUTH_REQUEST) == 0) + { + if (strcmp(msg->message_data.tags[0].class_id, DDS_SECURITY_AUTH_REQUEST_TOKEN_CLASS_ID) == 0) + { + /* Note the state machine is started by discovery + * currently and not by the reception of an auth_request message which was send as the + * result of validate_remote_entity at the opposite participant + */ + ddsrt_mutex_lock(&handshake->lock); + if (handshake->remote_auth_request_token) + DDS_Security_DataHolder_free(handshake->remote_auth_request_token); + handshake->remote_auth_request_token = DDS_Security_DataHolder_alloc(); + q_omg_security_dataholder_copyout(handshake->remote_auth_request_token, &msg->message_data.tags[0]); + ddsrt_mutex_unlock(&handshake->lock); + } + else + { + HSERROR("received handshake message ("PGUIDFMT" --> "PGUIDFMT") does not contain a valid handshake message token\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid)); + } + } + else if (strcmp(msg->message_class_id, DDS_SECURITY_AUTH_HANDSHAKE) == 0) + { + if (msg->message_data.tags[0].class_id == NULL) + HSERROR("received handshake message ("PGUIDFMT" --> "PGUIDFMT") does not contain a valid handshake message token\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid)); + else if (strcmp(msg->message_data.tags[0].class_id, DDS_SECURITY_AUTH_HANDSHAKE_REQUEST_TOKEN_ID) == 0) + event = EVENT_RECEIVED_MESSAGE_REQUEST; + else if (strcmp(msg->message_data.tags[0].class_id, DDS_SECURITY_AUTH_HANDSHAKE_REPLY_TOKEN_ID) == 0) + event = EVENT_RECEIVED_MESSAGE_REPLY; + else if (strcmp(msg->message_data.tags[0].class_id, DDS_SECURITY_AUTH_HANDSHAKE_FINAL_TOKEN_ID) == 0) + event = EVENT_RECEIVED_MESSAGE_FINAL; + else + { + HSERROR("received handshake message ("PGUIDFMT" --> "PGUIDFMT") does not contain a valid handshake message token\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid)); + goto invalid_message; + } + + ddsrt_mutex_lock(&handshake->lock); + DDS_Security_DataHolder_deinit(&handshake->handshake_message_in_token); + q_omg_security_dataholder_copyout(&handshake->handshake_message_in_token, &msg->message_data.tags[0]); + memcpy(&handshake->handshake_message_in_id, &msg->message_identity, sizeof(handshake->handshake_message_in_id)); + handshake->handled_handshake_message = 0; + dds_security_fsm_dispatch(handshake->fsm, event, false); + ddsrt_mutex_unlock(&handshake->lock); + } + else + { + HSERROR("received handshake message ("PGUIDFMT" --> "PGUIDFMT") does not contain a valid message_class_id\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid)); + } + +invalid_message: + return; } void ddsi_handshake_crypto_tokens_received(struct ddsi_handshake *handshake) { - DDSRT_UNUSED_ARG(handshake); + struct participant *pp; + struct proxy_participant *proxypp; + + assert(handshake); + assert(handshake->fsm); + + if (!validate_handshake(handshake, &pp, &proxypp)) + return; + + HSTRACE("FSM: tokens received (lguid="PGUIDFMT" rguid="PGUIDFMT")\n", PGUID(pp->e.guid), PGUID(proxypp->e.guid)); + + dds_security_fsm_dispatch(handshake->fsm, EVENT_RECV_CRYPTO_TOKENS, false); } int64_t ddsi_handshake_get_shared_secret(const struct ddsi_handshake *handshake) { - DDSRT_UNUSED_ARG(handshake); - - return 0; + return handshake->shared_secret; } int64_t ddsi_handshake_get_handle(const struct ddsi_handshake *handshake) { - DDSRT_UNUSED_ARG(handshake); - - return 0; + return handshake->handshake_handle; } -void ddsi_handshake_register(const struct participant *pp, const struct proxy_participant *proxypp, ddsi_handshake_end_cb_t callback) +static struct ddsi_hsadmin * ddsi_handshake_admin_create(void) { - DDSRT_UNUSED_ARG(pp); - DDSRT_UNUSED_ARG(proxypp); - DDSRT_UNUSED_ARG(callback); + struct ddsi_hsadmin *admin; + + admin = ddsrt_malloc(sizeof(*admin)); + ddsrt_mutex_init(&admin->lock); + ddsrt_avl_init(&handshake_treedef, &admin->handshakes); + admin->fsm_control = NULL; + + return admin; } -void ddsi_handshake_remove(const struct participant *pp, const struct proxy_participant *proxypp, struct ddsi_handshake *handshake) +static void release_handshake(void *arg) { - DDSRT_UNUSED_ARG(pp); - DDSRT_UNUSED_ARG(proxypp); - DDSRT_UNUSED_ARG(handshake); + ddsi_handshake_release((struct ddsi_handshake *)arg); } -struct ddsi_handshake * ddsi_handshake_find(const struct participant *pp, const struct proxy_participant *proxypp) +static void ddsi_handshake_admin_delete(struct ddsi_hsadmin *hsadmin) { - DDSRT_UNUSED_ARG(pp); - DDSRT_UNUSED_ARG(proxypp); + if (hsadmin) + { + ddsrt_mutex_destroy(&hsadmin->lock); + ddsrt_avl_free(&handshake_treedef, &hsadmin->handshakes, release_handshake); + if (hsadmin->fsm_control) + { + dds_security_fsm_control_stop(hsadmin->fsm_control); + dds_security_fsm_control_free(hsadmin->fsm_control); + } + ddsrt_free(hsadmin); + } +} - return NULL; +static struct ddsi_handshake * ddsi_handshake_find_locked( + struct ddsi_hsadmin *hsadmin, + struct participant *pp, + struct proxy_participant *proxypp) +{ + struct handshake_entities handles; + + handles.lguid = pp->e.guid; + handles.rguid = proxypp->e.guid; + + return ddsrt_avl_lookup(&handshake_treedef, &hsadmin->handshakes, &handles); +} + +void ddsi_handshake_remove(struct participant *pp, struct proxy_participant *proxypp, struct ddsi_handshake *handshake) +{ + struct ddsi_hsadmin *hsadmin = pp->e.gv->hsadmin; + + ddsrt_mutex_lock(&hsadmin->lock); + if (!handshake) + handshake = ddsi_handshake_find_locked(hsadmin, pp, proxypp); + if (handshake) + { + ddsrt_avl_delete(&handshake_treedef, &hsadmin->handshakes, handshake); + ddsrt_atomic_st32(&handshake->deleting, 1); + } + ddsrt_mutex_unlock(&hsadmin->lock); + if (handshake && handshake->fsm) + dds_security_fsm_free(handshake->fsm); + ddsi_handshake_release(handshake); +} + +struct ddsi_handshake * ddsi_handshake_find(struct participant *pp, struct proxy_participant *proxypp) +{ + struct ddsi_hsadmin *hsadmin = pp->e.gv->hsadmin; + struct ddsi_handshake *handshake = NULL; + + ddsrt_mutex_lock(&hsadmin->lock); + handshake = ddsi_handshake_find_locked(hsadmin, pp, proxypp); + if (handshake) + ddsrt_atomic_inc32(&handshake->refc); + ddsrt_mutex_unlock(&hsadmin->lock); + + return handshake; +} + +void ddsi_handshake_register(struct participant *pp, struct proxy_participant *proxypp, ddsi_handshake_end_cb_t callback) +{ + struct ddsi_hsadmin *hsadmin = pp->e.gv->hsadmin; + struct ddsi_handshake *handshake = NULL; + + ddsrt_mutex_lock(&hsadmin->lock); + handshake = ddsi_handshake_find_locked(hsadmin, pp, proxypp); + if (!handshake) + { + handshake = ddsi_handshake_create(pp, proxypp, callback); + if (handshake) + ddsrt_avl_insert(&handshake_treedef, &hsadmin->handshakes, handshake); + } + ddsrt_mutex_unlock(&hsadmin->lock); +} + +void ddsi_handshake_admin_init(struct ddsi_domaingv *gv) +{ + assert(gv); + gv->hsadmin = ddsi_handshake_admin_create(); +} + +void ddsi_handshake_admin_deinit(struct ddsi_domaingv *gv) +{ + assert(gv); + ddsi_handshake_admin_delete(gv->hsadmin); } @@ -101,9 +1213,8 @@ extern inline void ddsi_handshake_release(UNUSED_ARG(struct ddsi_handshake *hand extern inline void ddsi_handshake_crypto_tokens_received(UNUSED_ARG(struct ddsi_handshake *handshake)); extern inline int64_t ddsi_handshake_get_shared_secret(UNUSED_ARG(const struct ddsi_handshake *handshake)); extern inline int64_t ddsi_handshake_get_handle(UNUSED_ARG(const struct ddsi_handshake *handshake)); -extern inline void ddsi_handshake_register(UNUSED_ARG(const struct participant *pp), UNUSED_ARG(const struct proxy_participant *proxypp), UNUSED_ARG(ddsi_handshake_end_cb_t callback)); -extern inline void ddsi_handshake_remove(UNUSED_ARG(const struct participant *pp), UNUSED_ARG(const struct proxy_participant *proxypp), UNUSED_ARG(struct ddsi_handshake *handshake)); -extern inline struct ddsi_handshake * ddsi_handshake_find(UNUSED_ARG(const struct participant *pp), UNUSED_ARG(const struct proxy_participant *proxypp)); - +extern inline void ddsi_handshake_register(UNUSED_ARG(struct participant *pp), UNUSED_ARG(struct proxy_participant *proxypp), UNUSED_ARG(ddsi_handshake_end_cb_t callback)); +extern inline void ddsi_handshake_remove(UNUSED_ARG(struct participant *pp), UNUSED_ARG(struct proxy_participant *proxypp), UNUSED_ARG(struct ddsi_handshake *handshake)); +extern inline struct ddsi_handshake * ddsi_handshake_find(UNUSED_ARG(struct participant *pp), UNUSED_ARG(struct proxy_participant *proxypp)); #endif /* DDSI_INCLUDE_DDS_SECURITY */ diff --git a/src/core/ddsi/src/ddsi_plist.c b/src/core/ddsi/src/ddsi_plist.c index d2243f6..9722e02 100644 --- a/src/core/ddsi/src/ddsi_plist.c +++ b/src/core/ddsi/src/ddsi_plist.c @@ -106,7 +106,7 @@ struct piddesc { const enum pserop desc[12]; struct { dds_return_t (*deser) (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag, const struct dd * __restrict dd, size_t * __restrict srcoff); - dds_return_t (*ser) (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff); + dds_return_t (*ser) (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff, bool be); dds_return_t (*unalias) (void * __restrict dst, size_t * __restrict dstoff); dds_return_t (*fini) (void * __restrict dst, size_t * __restrict dstoff, struct flagset *flagset, uint64_t flag); dds_return_t (*valid) (const void *src, size_t srcoff); @@ -289,17 +289,19 @@ static dds_return_t deser_reliability (void * __restrict dst, size_t * __restric return 0; } -static dds_return_t ser_reliability (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff) +static dds_return_t ser_reliability (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff, bool be) { +#define BO4U(x) ((be) ? ddsrt_toBE4u((x)) : (x)) DDSRT_STATIC_ASSERT (DDS_EXTERNAL_RELIABILITY_BEST_EFFORT == 1 && DDS_EXTERNAL_RELIABILITY_RELIABLE == 2 && DDS_RELIABILITY_BEST_EFFORT == 0 && DDS_RELIABILITY_RELIABLE == 1); dds_reliability_qospolicy_t const * const x = deser_generic_src (src, &srcoff, alignof (dds_reliability_qospolicy_t)); ddsi_duration_t mbt = nn_to_ddsi_duration (x->max_blocking_time); - uint32_t * const p = nn_xmsg_addpar (xmsg, pid, 3 * sizeof (uint32_t)); - p[0] = 1 + (uint32_t) x->kind; - p[1] = (uint32_t) mbt.seconds; - p[2] = mbt.fraction; + uint32_t * const p = nn_xmsg_addpar_bo (xmsg, pid, 3 * sizeof (uint32_t), be); + p[0] = BO4U(1 + (uint32_t) x->kind); + p[1] = BO4U((uint32_t) mbt.seconds); + p[2] = BO4U(mbt.fraction); return 0; +#undef BO4U } static dds_return_t valid_reliability (const void *src, size_t srcoff) @@ -340,10 +342,10 @@ static dds_return_t deser_statusinfo (void * __restrict dst, size_t * __restrict return 0; } -static dds_return_t ser_statusinfo (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff) +static dds_return_t ser_statusinfo (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff, bool be) { uint32_t const * const x = deser_generic_src (src, &srcoff, alignof (uint32_t)); - uint32_t * const p = nn_xmsg_addpar (xmsg, pid, sizeof (uint32_t)); + uint32_t * const p = nn_xmsg_addpar_bo (xmsg, pid, sizeof (uint32_t), be); *p = ddsrt_toBE4u (*x); return 0; } @@ -374,14 +376,16 @@ static dds_return_t deser_locator (void * __restrict dst, size_t * __restrict ds return 0; } -static dds_return_t ser_locator (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff) +static dds_return_t ser_locator (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff, bool be) { nn_locators_t const * const x = deser_generic_src (src, &srcoff, alignof (nn_locators_t)); for (const struct nn_locators_one *l = x->first; l != NULL; l = l->next) { - char * const p = nn_xmsg_addpar (xmsg, pid, 24); - memcpy (p, &l->loc.kind, 4); - memcpy (p + 4, &l->loc.port, 4); + char * const p = nn_xmsg_addpar_bo (xmsg, pid, 24, be); + const int32_t kind = be ? ddsrt_toBE4 (l->loc.kind) : l->loc.kind; + const uint32_t port = be ? ddsrt_toBE4u (l->loc.port) : l->loc.port; + memcpy (p, &kind, 4); + memcpy (p + 4, &port, 4); memcpy (p + 8, l->loc.address, 16); } return 0; @@ -854,8 +858,12 @@ static uint32_t ser_generic_count (const ddsi_octetseq_t *src, size_t elem_size, return count; } -static dds_return_t ser_generic_embeddable (char * const data, size_t *dstoff, const void *src, size_t srcoff, const enum pserop * __restrict desc) +static dds_return_t ser_generic_embeddable (char * const data, size_t *dstoff, const void *src, size_t srcoff, const enum pserop * __restrict desc, bool be) { +#define BO4(x) (be ? ddsrt_toBE4((x)) : (x)) +#define BO4U(x) (be ? ddsrt_toBE4u((x)) : (x)) +#define BO8(x) (be ? ddsrt_toBE8((x)) : (x)) + while (true) { switch (*desc) @@ -865,7 +873,7 @@ static dds_return_t ser_generic_embeddable (char * const data, size_t *dstoff, c case XO: { /* octet sequence */ ddsi_octetseq_t const * const x = deser_generic_src (src, &srcoff, alignof (ddsi_octetseq_t)); char * const p = ser_generic_align4 (data, dstoff); - *((uint32_t *) p) = x->length; + *((uint32_t *) p) = BO4U(x->length); if (x->length) memcpy (p + 4, x->value, x->length); *dstoff += 4 + x->length; srcoff += sizeof (*x); @@ -875,7 +883,7 @@ static dds_return_t ser_generic_embeddable (char * const data, size_t *dstoff, c char const * const * const x = deser_generic_src (src, &srcoff, alignof (char *)); const uint32_t size = (uint32_t) (strlen (*x) + 1); char * const p = ser_generic_align4 (data, dstoff); - *((uint32_t *) p) = size; + *((uint32_t *) p) = BO4U(size); memcpy (p + 4, *x, size); *dstoff += 4 + size; srcoff += sizeof (*x); @@ -884,7 +892,7 @@ static dds_return_t ser_generic_embeddable (char * const data, size_t *dstoff, c case XE1: case XE2: case XE3: { /* enum */ unsigned const * const x = deser_generic_src (src, &srcoff, alignof (unsigned)); uint32_t * const p = ser_generic_align4 (data, dstoff); - *p = (uint32_t) *x; + *p = BO4U((uint32_t) *x); *dstoff += 4; srcoff += sizeof (*x); break; @@ -894,7 +902,7 @@ static dds_return_t ser_generic_embeddable (char * const data, size_t *dstoff, c const uint32_t cnt = 1 + (uint32_t) (*desc - Xi); int32_t * const p = ser_generic_align4 (data, dstoff); for (uint32_t i = 0; i < cnt; i++) - p[i] = x[i]; + p[i] = BO4(x[i]); *dstoff += cnt * sizeof (*x); srcoff += cnt * sizeof (*x); break; @@ -904,7 +912,7 @@ static dds_return_t ser_generic_embeddable (char * const data, size_t *dstoff, c const uint32_t cnt = 1 + (uint32_t) (*desc - Xu); uint32_t * const p = ser_generic_align4 (data, dstoff); for (uint32_t i = 0; i < cnt; i++) - p[i] = x[i]; + p[i] = BO4U(x[i]); *dstoff += cnt * sizeof (*x); srcoff += cnt * sizeof (*x); break; @@ -912,7 +920,7 @@ static dds_return_t ser_generic_embeddable (char * const data, size_t *dstoff, c case Xl: { /* int64_t */ int64_t const * const x = deser_generic_src (src, &srcoff, alignof (int64_t)); int64_t * const p = ser_generic_align8 (data, dstoff); - *p = *x; + *p = BO8(*x); *dstoff += sizeof (*x); srcoff += sizeof (*x); break; @@ -924,8 +932,8 @@ static dds_return_t ser_generic_embeddable (char * const data, size_t *dstoff, c for (uint32_t i = 0; i < cnt; i++) { ddsi_duration_t tmp = nn_to_ddsi_duration (x[i]); - p[2 * i + 0] = (uint32_t) tmp.seconds; - p[2 * i + 1] = tmp.fraction; + p[2 * i + 0] = BO4U((uint32_t) tmp.seconds); + p[2 * i + 1] = BO4U(tmp.fraction); } *dstoff += 2 * cnt * sizeof (uint32_t); srcoff += cnt * sizeof (*x); @@ -981,9 +989,9 @@ static dds_return_t ser_generic_embeddable (char * const data, size_t *dstoff, c else { const size_t elem_size = ser_generic_srcsize (desc + 1); - *((uint32_t *) p) = ser_generic_count (x, elem_size, desc + 1); + *((uint32_t *) p) = BO4U(ser_generic_count (x, elem_size, desc + 1)); for (uint32_t i = 0; i < x->length; i++) - ser_generic_embeddable (data, dstoff, x->value, i * elem_size, desc + 1); + ser_generic_embeddable (data, dstoff, x->value, i * elem_size, desc + 1, be); } srcoff += sizeof (*x); break; @@ -993,13 +1001,18 @@ static dds_return_t ser_generic_embeddable (char * const data, size_t *dstoff, c } desc = pserop_advance(desc); } +#undef BO4 +#undef BO4U +#undef BO8 } -static dds_return_t ser_generic (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff, const enum pserop * __restrict desc) + + +static dds_return_t ser_generic (struct nn_xmsg *xmsg, nn_parameterid_t pid, const void *src, size_t srcoff, const enum pserop * __restrict desc, bool be) { - char * const data = nn_xmsg_addpar (xmsg, pid, ser_generic_size (src, srcoff, desc)); + char * const data = nn_xmsg_addpar_bo (xmsg, pid, ser_generic_size (src, srcoff, desc), be); size_t dstoff = 0; - return ser_generic_embeddable (data, &dstoff, src, srcoff, desc); + return ser_generic_embeddable (data, &dstoff, src, srcoff, desc, be); } dds_return_t plist_ser_generic (void **dst, size_t *dstsize, const void *src, const enum pserop * __restrict desc) @@ -1010,7 +1023,7 @@ dds_return_t plist_ser_generic (void **dst, size_t *dstsize, const void *src, co *dstsize = ser_generic_size (src, srcoff, desc); if ((*dst = ddsrt_malloc (*dstsize == 0 ? 1 : *dstsize)) == NULL) return DDS_RETCODE_OUT_OF_RESOURCES; - ret = ser_generic_embeddable (*dst, &dstoff, src, srcoff, desc); + ret = ser_generic_embeddable (*dst, &dstoff, src, srcoff, desc, false); assert (dstoff == *dstsize); return ret; } @@ -1987,7 +2000,7 @@ static void plist_or_xqos_mergein_missing (void * __restrict dst, const void * _ assert ((*qfs_dst.aliased & ~ aliased_dst_inq) == 0); } -static void plist_or_xqos_addtomsg (struct nn_xmsg *xmsg, const void * __restrict src, size_t shift, uint64_t pwanted, uint64_t qwanted) +static void plist_or_xqos_addtomsg (struct nn_xmsg *xmsg, const void * __restrict src, size_t shift, uint64_t pwanted, uint64_t qwanted, bool be) { /* shift == 0: plist, shift > 0: just qos */ uint64_t pw, qw; @@ -2017,9 +2030,9 @@ static void plist_or_xqos_addtomsg (struct nn_xmsg *xmsg, const void * __restric assert (shift == 0 || entry->plist_offset - shift < sizeof (dds_qos_t)); size_t srcoff = entry->plist_offset - shift; if (!(entry->flags & PDF_FUNCTION)) - ser_generic (xmsg, entry->pid, src, srcoff, entry->op.desc); + ser_generic (xmsg, entry->pid, src, srcoff, entry->op.desc, be); else - entry->op.f.ser (xmsg, entry->pid, src, srcoff); + entry->op.f.ser (xmsg, entry->pid, src, srcoff, be); } } } @@ -3333,12 +3346,17 @@ static int partitions_equal (const void *srca, const void *srcb, size_t off) void ddsi_xqos_addtomsg (struct nn_xmsg *m, const dds_qos_t *xqos, uint64_t wanted) { - plist_or_xqos_addtomsg (m, xqos, offsetof (struct ddsi_plist, qos), 0, wanted); + plist_or_xqos_addtomsg (m, xqos, offsetof (struct ddsi_plist, qos), 0, wanted, false); +} + +void ddsi_plist_addtomsg_bo (struct nn_xmsg *m, const ddsi_plist_t *ps, uint64_t pwanted, uint64_t qwanted, bool be) +{ + plist_or_xqos_addtomsg (m, ps, 0, pwanted, qwanted, be); } void ddsi_plist_addtomsg (struct nn_xmsg *m, const ddsi_plist_t *ps, uint64_t pwanted, uint64_t qwanted) { - plist_or_xqos_addtomsg (m, ps, 0, pwanted, qwanted); + plist_or_xqos_addtomsg (m, ps, 0, pwanted, qwanted, false); } /*************************/ diff --git a/src/core/ddsi/src/ddsi_security_exchange.c b/src/core/ddsi/src/ddsi_security_exchange.c new file mode 100644 index 0000000..c583f71 --- /dev/null +++ b/src/core/ddsi/src/ddsi_security_exchange.c @@ -0,0 +1,428 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifdef DDSI_INCLUDE_SECURITY + +#include + +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/md5.h" + +#include "dds/ddsi/ddsi_domaingv.h" +#include "dds/ddsi/ddsi_entity_index.h" +#include "dds/ddsi/ddsi_security_exchange.h" +#include "dds/ddsi/ddsi_serdata_default.h" +#include "dds/ddsi/ddsi_security_omg.h" +#include "dds/ddsi/ddsi_handshake.h" +#include "dds/ddsi/q_ddsi_discovery.h" +#include "dds/ddsi/ddsi_tkmap.h" +#include "dds/ddsi/q_xmsg.h" +#include "dds/ddsi/q_transmit.h" +#include "dds/ddsi/q_log.h" +#include "dds/ddsi/q_bswap.h" + +//#define SECURITY_LOG_MESSAGE_DATA + +#ifdef SECURITY_LOG_MESSAGE_DATA +static void nn_property_seq_log(struct ddsi_domaingv *gv, const dds_propertyseq_t *seq) +{ + uint32_t i; + + GVTRACE("{"); + for (i = 0; i < seq->n; i++) { + GVTRACE("n=%s,v=%s", seq->props[i].name, seq->props[i].value); + } + GVTRACE("}"); +} + +static void nn_binary_property_seq_log(struct ddsi_domaingv *gv, const dds_binarypropertyseq_t *seq) +{ + uint32_t i; + + GVTRACE("{"); + for (i = 0; i < seq->n; i++) { + uint32_t j; + GVTRACE("n=%s,v={", seq->props[i].name); + for (j = 0; j < seq->props[i].value.length; j++) { + GVTRACE("%02x", seq->props[i].value.value[j]); + } + GVTRACE("}"); + } + GVTRACE("}"); +} + +static void nn_dataholder_seq_log(struct ddsi_domaingv *gv, const char *prefix, const nn_dataholderseq_t *dhseq) +{ + uint32_t i; + + GVTRACE("%s={", prefix); + for (i = 0; i < dhseq->n; i++) { + GVTRACE("cid=%s,", dhseq->tags[i].class_id); + nn_property_seq_log(gv, &dhseq->tags[i].properties); + GVTRACE(","); + nn_binary_property_seq_log(gv, &dhseq->tags[i].binary_properties); + } + GVTRACE("}"); +} +#endif + +static void nn_participant_generic_message_log(struct ddsi_domaingv *gv, const struct nn_participant_generic_message *msg, int conv) +{ + ddsi_guid_t spguid = conv ? nn_ntoh_guid(msg->message_identity.source_guid ): msg->message_identity.source_guid; + ddsi_guid_t rmguid = conv ? nn_ntoh_guid(msg->related_message_identity.source_guid) : msg->related_message_identity.source_guid; + ddsi_guid_t dpguid = conv ? nn_ntoh_guid(msg->destination_participant_guid) : msg->destination_participant_guid; + ddsi_guid_t deguid = conv ? nn_ntoh_guid(msg->destination_endpoint_guid) : msg->destination_endpoint_guid; + ddsi_guid_t seguid = conv ? nn_ntoh_guid(msg->source_endpoint_guid) : msg->source_endpoint_guid; + + GVTRACE (" msg="); + GVTRACE("mi=" PGUIDFMT "#%" PRId64 ",", PGUID(spguid), msg->message_identity.sequence_number); + GVTRACE("rmi=" PGUIDFMT "#%" PRId64 ",", PGUID(rmguid), msg->related_message_identity.sequence_number); + GVTRACE("dpg=" PGUIDFMT ",", PGUID(dpguid)); + GVTRACE("deg=" PGUIDFMT ",", PGUID(deguid)); + GVTRACE("seg=" PGUIDFMT ",", PGUID(seguid)); + GVTRACE("cid=%s", msg->message_class_id); +#ifdef SECURITY_LOG_MESSAGE_DATA + nn_dataholder_seq_log(gv, ",mdata", &msg->message_data); +#endif + GVTRACE ("\n"); +} + +bool write_auth_handshake_message(const struct participant *pp, const struct proxy_participant *proxypp, nn_dataholderseq_t *mdata, bool request, const nn_message_identity_t *related_message_id) +{ + struct ddsi_domaingv *gv = pp->e.gv; + struct nn_participant_generic_message pmg; + struct ddsi_serdata *serdata; + unsigned char *blob; + size_t len; + struct writer *wr; + int64_t seq; + struct proxy_reader *prd; + ddsi_guid_t prd_guid; + bool result = false; + + if ((wr = get_builtin_writer (pp, NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER)) == NULL) { + GVTRACE ("write_handshake("PGUIDFMT") - builtin stateless message writer not found", PGUID (pp->e.guid)); + return false; + } + + prd_guid.prefix = proxypp->e.guid.prefix; + prd_guid.entityid.u = NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_READER; + if ((prd = entidx_lookup_proxy_reader_guid (gv->entity_index, &prd_guid)) == NULL) { + GVTRACE ("write_handshake("PGUIDFMT") - builtin stateless message proxy reader not found", PGUID (prd_guid)); + return false; + } + + ddsrt_mutex_lock (&wr->e.lock); + seq = ++wr->seq; + + if (request) { + nn_participant_generic_message_init(&pmg, &wr->e.guid, seq, &proxypp->e.guid, NULL, NULL, DDS_SECURITY_AUTH_REQUEST, mdata, NULL); + } else { + nn_participant_generic_message_init(&pmg, &wr->e.guid, seq, &proxypp->e.guid, NULL, NULL, DDS_SECURITY_AUTH_HANDSHAKE, mdata, related_message_id); + } + + if (nn_participant_generic_message_serialize(&pmg, &blob, &len) != DDS_RETCODE_OK) + return false; + + GVTRACE("write_handshake("PGUIDFMT" --> "PGUIDFMT")(lguid="PGUIDFMT" rguid="PGUIDFMT") ", + PGUID (wr->e.guid), PGUID (prd_guid), + PGUID (pp->e.guid), PGUID (proxypp->e.guid)); + nn_participant_generic_message_log(gv, &pmg, 1); + + struct ddsi_rawcdr_sample raw = { + .blob = blob, + .size = len, + .key = NULL, + .keysize = 0 + }; + serdata = ddsi_serdata_from_sample (gv->rawcdr_topic, SDK_DATA, &raw); + serdata->timestamp = now (); + + result = enqueue_sample_wrlock_held (wr, seq, NULL, serdata, prd, 1) == 0; + ddsi_serdata_unref (serdata); + dds_free(blob); + + ddsrt_mutex_unlock (&wr->e.lock); + nn_participant_generic_message_deinit(&pmg); + + return result; +} + +void auth_get_serialized_participant_data(struct participant *pp, ddsi_octetseq_t *seq) +{ + struct nn_xmsg *mpayload; + size_t sz; + char *payload; + + mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid, pp, 0, NN_XMSG_KIND_DATA); + + get_participant_builtin_topic_data(pp, mpayload, true); + payload = nn_xmsg_payload (&sz, mpayload); + + seq->length = (uint32_t)sz; + seq->value = ddsrt_malloc(sz); + memcpy(seq->value, payload, sz); + nn_xmsg_free (mpayload); +} + +void handle_auth_handshake_message(const struct receiver_state *rst, ddsi_entityid_t wr_entity_id, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, size_t len) +{ + const struct CDRHeader *hdr = vdata; /* built-ins not deserialized (yet) */ + const bool bswap = (hdr->identifier == CDR_LE) ^ DDSRT_LITTLE_ENDIAN; + const void *data = (void *) (hdr + 1); + size_t size = (len - sizeof(struct CDRHeader)); + struct nn_participant_generic_message msg; + struct participant *pp = NULL; + struct proxy_writer *pwr = NULL; + ddsi_guid_t guid; + ddsi_guid_t *pwr_guid; + struct ddsi_handshake *handshake; + + DDSRT_UNUSED_ARG(wr_entity_id); + DDSRT_UNUSED_ARG(timestamp); + + RSTTRACE ("recv_handshake ST%x", statusinfo); + if ((hdr->identifier != CDR_LE) && (hdr->identifier != PL_CDR_LE) && + (hdr->identifier != CDR_BE) && (hdr->identifier != PL_CDR_BE)) + { + RSTTRACE (" data->identifier %d !?\n", ntohs (hdr->identifier)); + return; + } + + if (nn_participant_generic_message_deseralize(&msg, data, size, bswap) < 0) + { + RSTTRACE ("deserialize failed\n"); + goto err_deser; + } + + nn_participant_generic_message_log(rst->gv, &msg, 0); + + if (msg.message_identity.source_guid.entityid.u == NN_ENTITYID_PARTICIPANT) + { + guid = msg.message_identity.source_guid; + guid.entityid.u = NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER; + pwr_guid= &guid; + } + else if (msg.message_identity.source_guid.entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER) + { + pwr_guid= &msg.message_identity.source_guid; + } + else + { + RSTTRACE ("invalid source entity id\n"); + goto invalid_source; + } + + if ((pp = entidx_lookup_participant_guid(rst->gv->entity_index, &msg.destination_participant_guid)) == NULL) + { + RSTTRACE ("destination participant ("PGUIDFMT") not found\n", PGUID(msg.destination_participant_guid)); + } + else if ((pwr = entidx_lookup_proxy_writer_guid(rst->gv->entity_index, pwr_guid)) == NULL) + { + RSTTRACE ("proxy writer ("PGUIDFMT") not found\n", PGUID(*pwr_guid)); + } + else if ((handshake = ddsi_handshake_find(pp, pwr->c.proxypp)) == NULL) + { + RSTTRACE ("handshake not found ("PGUIDFMT" --> "PGUIDFMT")\n", PGUID (pwr->c.proxypp->e.guid), PGUID(pp->e.guid)); + } + else + { +// RSTTRACE (" ("PGUIDFMT" --> "PGUIDFMT")\n", PGUID (pwr->c.proxypp->e.guid), PGUID (pp->e.guid)); + ddsi_handshake_handle_message(handshake, pp, pwr->c.proxypp, &msg); + ddsi_handshake_release(handshake); + } + +invalid_source: + nn_participant_generic_message_deinit(&msg); +err_deser: + return; +} + +static bool write_crypto_exchange_message(const struct participant *pp, const ddsi_guid_t *dst_pguid, const ddsi_guid_t *src_eguid, const ddsi_guid_t *dst_eguid, const char *classid, const nn_dataholderseq_t *tokens) +{ + struct ddsi_domaingv * const gv = pp->e.gv; + struct nn_participant_generic_message pmg; + struct ddsi_tkmap_instance *tk; + struct ddsi_serdata *serdata; + struct proxy_reader *prd; + ddsi_guid_t prd_guid; + unsigned char *data; + size_t len; + struct writer *wr; + seqno_t seq; + int r; + + if ((wr = get_builtin_writer (pp, NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER)) == NULL) + { + GVLOG (DDS_LC_DISCOVERY, "write_crypto_exchange_message("PGUIDFMT") - builtin volatile secure writer not found\n", PGUID (pp->e.guid)); + return false; + } + + prd_guid.prefix = dst_pguid->prefix; + prd_guid.entityid.u = NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER; + if ((prd = entidx_lookup_proxy_reader_guid (gv->entity_index, &prd_guid)) == NULL) + return false; + + GVLOG (DDS_LC_DISCOVERY, "send crypto tokens("PGUIDFMT" --> "PGUIDFMT")\n", PGUID (wr->e.guid), PGUID (prd_guid)); + + ddsrt_mutex_lock (&wr->e.lock); + seq = ++wr->seq; + + /* Get serialized message. */ + nn_participant_generic_message_init(&pmg, &wr->e.guid, seq, dst_pguid, dst_eguid, src_eguid, classid, tokens, NULL); + nn_participant_generic_message_serialize(&pmg, &data, &len); + + /* Get the key value. */ + ddsrt_md5_state_t md5st; + ddsrt_md5_byte_t digest[16]; + ddsrt_md5_init (&md5st); + ddsrt_md5_append (&md5st, (const ddsrt_md5_byte_t *)data, sizeof (nn_message_identity_t)); + ddsrt_md5_finish (&md5st, digest); + + /* Write the sample. */ + struct ddsi_rawcdr_sample raw = { + .blob = data, + .size = len, + .key = digest, + .keysize = 16 + }; + serdata = ddsi_serdata_from_sample (gv->rawcdr_topic, SDK_DATA, &raw); + tk = ddsi_tkmap_lookup_instance_ref (gv->m_tkmap, serdata); + ddsrt_mutex_unlock (&wr->e.lock); + ddsrt_free(data); + + r = write_sample_p2p_wrlock_held(wr, seq, NULL, serdata, tk, prd); + ddsi_tkmap_instance_unref (gv->m_tkmap, tk); + ddsi_serdata_unref (serdata); + + nn_participant_generic_message_deinit(&pmg); + + return (r < 0 ? false : true); +} + +bool write_crypto_participant_tokens(const struct participant *pp, const struct proxy_participant *proxypp, const nn_dataholderseq_t *tokens) +{ + return write_crypto_exchange_message(pp, &proxypp->e.guid, NULL, NULL, GMCLASSID_SECURITY_PARTICIPANT_CRYPTO_TOKENS, tokens); +} + +bool write_crypto_writer_tokens(const struct writer *wr, const struct proxy_reader *prd, const nn_dataholderseq_t *tokens) +{ + struct participant *pp = wr->c.pp; + struct proxy_participant *proxypp = prd->c.proxypp; + + return write_crypto_exchange_message(pp, &proxypp->e.guid, &wr->e.guid, &prd->e.guid, GMCLASSID_SECURITY_DATAWRITER_CRYPTO_TOKENS, tokens); +} + +bool write_crypto_reader_tokens(const struct reader *rd, const struct proxy_writer *pwr, const nn_dataholderseq_t *tokens) +{ + struct participant *pp = rd->c.pp; + struct proxy_participant *proxypp = pwr->c.proxypp; + + return write_crypto_exchange_message(pp, &proxypp->e.guid, &rd->e.guid, &pwr->e.guid, GMCLASSID_SECURITY_DATAREADER_CRYPTO_TOKENS, tokens); +} + +void handle_crypto_exchange_message(const struct receiver_state *rst, ddsi_entityid_t wr_entity_id, nn_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len) +{ + struct ddsi_domaingv *gv = rst->gv; + const struct CDRHeader *hdr = vdata; /* built-ins not deserialized (yet) */ + const int bswap = (hdr->identifier == CDR_LE) ^ DDSRT_LITTLE_ENDIAN; + const void *data = (void *) (hdr + 1); + unsigned size = (unsigned)(len - sizeof(struct CDRHeader)); + struct nn_participant_generic_message msg; + ddsi_guid_t rd_guid; + ddsi_guid_t pwr_guid; + ddsi_guid_t proxypp_guid; + struct participant *pp; + struct proxy_participant *proxypp; + + DDSRT_UNUSED_ARG(timestamp); + + rd_guid.prefix = rst->dst_guid_prefix; + rd_guid.entityid.u = NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER; + pwr_guid.prefix = rst->src_guid_prefix; + pwr_guid.entityid = wr_entity_id; + + GVTRACE ("recv crypto tokens ("PGUIDFMT" --> "PGUIDFMT") ST%x", PGUID (pwr_guid), PGUID (rd_guid), statusinfo); + + memset(&msg, 0, sizeof(msg)); + if (nn_participant_generic_message_deseralize(&msg, data, size, bswap) < 0) + goto deser_msg_failed; + + nn_participant_generic_message_log(gv, &msg, 0); + + if (!msg.message_class_id) + { + ddsi_guid_t guid; + guid.prefix = rst->dst_guid_prefix; + guid.entityid.u = NN_ENTITYID_PARTICIPANT; + GVWARNING("participant "PGUIDFMT" received a crypto exchange message with empty class_id", PGUID(guid)); + goto invalid_msg; + } + + proxypp_guid.prefix = msg.message_identity.source_guid.prefix; + proxypp_guid.entityid.u = NN_ENTITYID_PARTICIPANT; + + if (strcmp(GMCLASSID_SECURITY_PARTICIPANT_CRYPTO_TOKENS, msg.message_class_id) == 0) + { + pp = entidx_lookup_participant_guid(gv->entity_index, &msg.destination_participant_guid); + if (!pp) + { + GVWARNING("received a crypto exchange message from "PGUIDFMT" with participant unknown "PGUIDFMT, PGUID(proxypp_guid), PGUID(msg.destination_participant_guid)); + goto invalid_msg; + } + proxypp = entidx_lookup_proxy_participant_guid(gv->entity_index, &proxypp_guid); + if (!proxypp) + { + GVWARNING("received a crypto exchange message from "PGUIDFMT" with proxy participant unknown "PGUIDFMT, PGUID(proxypp_guid), PGUID(msg.destination_participant_guid)); + goto invalid_msg; + } + q_omg_security_set_participant_crypto_tokens(pp, proxypp, &msg.message_data); + } + else if (strcmp(GMCLASSID_SECURITY_DATAWRITER_CRYPTO_TOKENS, msg.message_class_id) == 0) + { + struct reader *rd; + + rd = entidx_lookup_reader_guid(gv->entity_index, &msg.destination_endpoint_guid); + if (!rd) + { + GVWARNING("received a crypto exchange message from "PGUIDFMT" with reader unknown "PGUIDFMT, PGUID(proxypp_guid), PGUID(msg.destination_participant_guid)); + goto invalid_msg; + } + q_omg_security_set_remote_writer_crypto_tokens(rd, &msg.source_endpoint_guid, &msg.message_data); + } + else if (strcmp(GMCLASSID_SECURITY_DATAREADER_CRYPTO_TOKENS, msg.message_class_id) == 0) + { + struct writer *wr; + + wr = entidx_lookup_writer_guid(gv->entity_index, &msg.destination_endpoint_guid); + if (!wr) + { + GVWARNING("received a crypto exchange message from "PGUIDFMT" with writer unknown "PGUIDFMT, PGUID(proxypp_guid), PGUID(msg.destination_participant_guid)); + goto invalid_msg; + } + q_omg_security_set_remote_reader_crypto_tokens(wr, &msg.source_endpoint_guid, &msg.message_data); + } + else + { + ddsi_guid_t guid; + guid.prefix = rst->dst_guid_prefix; + guid.entityid.u = NN_ENTITYID_PARTICIPANT; + GVWARNING("participant "PGUIDFMT" received a crypto exchange message with unknown class_id", PGUID(guid)); + } + +invalid_msg: + nn_participant_generic_message_deinit(&msg); +deser_msg_failed: + return; +} + + +#endif /* DDSI_INCLUDE_SECURITY */ diff --git a/src/core/ddsi/src/ddsi_security_msg.c b/src/core/ddsi/src/ddsi_security_msg.c index a0bbe77..8838327 100644 --- a/src/core/ddsi/src/ddsi_security_msg.c +++ b/src/core/ddsi/src/ddsi_security_msg.c @@ -14,7 +14,6 @@ #include "dds/ddsrt/md5.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" -#include "dds/ddsi/ddsi_plist.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_transmit.h" @@ -23,6 +22,9 @@ #include "dds/ddsi/ddsi_entity_index.h" #include "dds/ddsi/ddsi_security_msg.h" #include "dds/ddsi/ddsi_plist_generic.h" +#include "dds/ddsi/ddsi_plist.h" +#include "dds/security/core/dds_security_utils.h" + const enum pserop pserop_participant_generic_message[] = { @@ -56,6 +58,8 @@ alias_simple_sequence(ddsi_octetseq_t *dst, const ddsi_octetseq_t *src, size_t e /* Even when aliased, sequence buffers are not shared. */ dst->value = ddsrt_memdup(src->value, src->length * elem_size); } + else + dst->value = NULL; } static void @@ -83,6 +87,8 @@ alias_dataholderseq(nn_dataholderseq_t *dst, const nn_dataholderseq_t *src) alias_dataholder(&(dst->tags[i]), &(src->tags[i])); } } + else + dst->tags = NULL; } void @@ -155,76 +161,6 @@ nn_participant_generic_message_deseralize( return plist_deser_generic (msg, data, len, bswap, pserop_participant_generic_message); } -int -write_crypto_exchange_message( - const struct participant *pp, - const ddsi_guid_t *dst_pguid, - const ddsi_guid_t *src_eguid, - const ddsi_guid_t *dst_eguid, - const char *classid, - const nn_dataholderseq_t *tokens) -{ - struct ddsi_domaingv * const gv = pp->e.gv; - struct nn_participant_generic_message pmg; - struct ddsi_tkmap_instance *tk; - struct ddsi_serdata *serdata; - struct proxy_reader *prd; - ddsi_guid_t prd_guid; - unsigned char *data; - size_t len; - struct writer *wr; - seqno_t seq; - int r; - - if ((wr = get_builtin_writer (pp, NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER)) == NULL) - { - GVLOG (DDS_LC_DISCOVERY, "write_crypto_exchange_message("PGUIDFMT") - builtin volatile secure writer not found\n", PGUID (pp->e.guid)); - return -1; - } - - prd_guid.prefix = dst_pguid->prefix; - prd_guid.entityid.u = NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER; - if ((prd = entidx_lookup_proxy_reader_guid (gv->entity_index, &prd_guid)) == NULL) - { - return -1; - } - - GVLOG (DDS_LC_DISCOVERY, "send crypto tokens("PGUIDFMT" --> "PGUIDFMT")\n", PGUID (wr->e.guid), PGUID (prd_guid)); - - ddsrt_mutex_lock (&wr->e.lock); - seq = ++wr->seq; - - /* Get serialized message. */ - nn_participant_generic_message_init(&pmg, &wr->e.guid, seq, dst_pguid, dst_eguid, src_eguid, classid, tokens, NULL); - nn_participant_generic_message_serialize(&pmg, &data, &len); - - /* Get the key value. */ - ddsrt_md5_state_t md5st; - ddsrt_md5_byte_t digest[16]; - ddsrt_md5_init (&md5st); - ddsrt_md5_append (&md5st, (const ddsrt_md5_byte_t *)data, sizeof (nn_message_identity_t)); - ddsrt_md5_finish (&md5st, digest); - - /* Write the sample. */ - struct ddsi_rawcdr_sample raw = { - .blob = data, - .size = len, - .key = digest, - .keysize = 16 - }; - serdata = ddsi_serdata_from_sample (gv->rawcdr_topic, SDK_DATA, &raw); - tk = ddsi_tkmap_lookup_instance_ref (gv->m_tkmap, serdata); - r = write_sample_p2p_wrlock_held(wr, seq, NULL, serdata, tk, prd); - ddsi_tkmap_instance_unref (gv->m_tkmap, tk); - ddsi_serdata_unref (serdata); - - nn_participant_generic_message_deinit(&pmg); - - ddsrt_mutex_unlock (&wr->e.lock); - - return r; -} - int volatile_secure_data_filter(struct writer *wr, struct proxy_reader *prd, struct ddsi_serdata *serdata) { static const size_t guid_offset = offsetof(nn_participant_generic_message_t, destination_participant_guid); @@ -239,7 +175,8 @@ int volatile_secure_data_filter(struct writer *wr, struct proxy_reader *prd, str assert(prd); assert(serdata); - (void)ddsi_serdata_to_ser_ref(serdata, guid_offset, sizeof(ddsi_guid_t), &guid_ref); + /* guid_offset + 4 because 4 bytes header is at 0 */ + (void)ddsi_serdata_to_ser_ref(serdata, guid_offset + 4, sizeof(ddsi_guid_t), &guid_ref); assert(guid_ref.iov_len == sizeof(ddsi_guid_t)); assert(guid_ref.iov_base); msg_guid = (ddsi_guid_t*)guid_ref.iov_base; diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index f118f41..8e3808d 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -12,17 +12,24 @@ #ifdef DDSI_INCLUDE_SECURITY #include +#include -#include "dds/ddsrt/misc.h" #include "dds/ddsrt/heap.h" -#include "dds/ddsrt/bswap.h" #include "dds/ddsrt/string.h" -#include "dds/ddsrt/process.h" +#include "dds/ddsrt/misc.h" +#include "dds/ddsrt/avl.h" +#include "dds/ddsi/ddsi_domaingv.h" +#include "dds/ddsi/q_unused.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_radmin.h" +#include "dds/ddsi/q_misc.h" #include "dds/ddsi/ddsi_entity_index.h" +#include "dds/ddsi/ddsi_security_msg.h" #include "dds/ddsi/ddsi_security_omg.h" +#include "dds/ddsi/ddsi_security_util.h" +#include "dds/ddsi/ddsi_security_exchange.h" +#include "dds/ddsi/ddsi_handshake.h" #include "dds/ddsi/ddsi_sertopic.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/q_log.h" @@ -35,30 +42,79 @@ #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_xevent.h" #include "dds/ddsi/ddsi_plist.h" +#include "dds/ddsi/sysdeps.h" #define AUTH_NAME "Authentication" #define AC_NAME "Access Control" #define CRYPTO_NAME "Cryptographic" -#define SECURITY_EXCEPTION_INIT {NULL, 0, 0} +#define EXCEPTION_LOG(sc,e,cat, ...) \ + q_omg_log_exception(sc->logcfg, cat, e, __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) -struct dds_security_context { - dds_security_plugin auth_plugin; - dds_security_plugin ac_plugin; - dds_security_plugin crypto_plugin; +#define EXCEPTION_ERROR(s, e, ...) EXCEPTION_LOG(s, e, DDS_LC_ERROR, __VA_ARGS__) +#define EXCEPTION_WARNING(s, e, ...) EXCEPTION_LOG(s, e, DDS_LC_WARNING, __VA_ARGS__) - dds_security_authentication *authentication_context; - dds_security_cryptography *crypto_context; - dds_security_access_control *access_control_context; - ddsrt_mutex_t omg_security_lock; - uint32_t next_plugin_id; - const struct ddsrt_log_cfg *logcfg; -}; +#define SECURITY_ATTR_IS_VALID(attr) \ + ((attr) & NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID) -typedef struct dds_security_context dds_security_context; +/* Security attributes are compatible ... */ +#define SECURITY_ATTR_COMPATIBLE(attr_a, attr_b, is_valid_flag) \ +( \ + /* ... if masks are equal ... */ \ + (attr_a == attr_b) \ + || \ + /* ... or if either of the masks is not valid ... */ \ + (((attr_a & is_valid_flag) == 0) || ((attr_b & is_valid_flag) == 0)) \ +) -static bool q_omg_writer_is_payload_protected (const struct writer *wr); +/* Security information are compatible ... */ +#define SECURITY_INFO_COMPATIBLE(info_a, info_b, is_valid_flag) \ +( \ + /* ... if plugin attributes are compatible ... */ \ + SECURITY_ATTR_COMPATIBLE(info_a.plugin_security_attributes, \ + info_b.plugin_security_attributes, \ + is_valid_flag) \ + && \ + /* ... and spec attributes are compatible ... */ \ + SECURITY_ATTR_COMPATIBLE(info_a.security_attributes, \ + info_b.security_attributes, \ + is_valid_flag) \ +) + +/* Security information indicates clear data ... */ +#define SECURITY_INFO_CLEAR(info, is_valid_flag) \ +( \ + /* ... if no flag was set (ignoring the is_valid flag) ... */ \ + (info.security_attributes & (~is_valid_flag)) == 0 \ +) + +#define SECURITY_INFO_IS_RTPS_PROTECTED(info) \ +( \ + (info.security_attributes & NN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_VALID ) && \ + (info.security_attributes & NN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_RTPS_PROTECTED) \ +) + +#define SECURITY_INFO_IS_WRITE_PROTECTED(info) \ +( \ + (info.security_attributes & NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID ) && \ + (info.security_attributes & NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_WRITE_PROTECTED) \ +) + +#define SECURITY_INFO_IS_READ_PROTECTED(info) \ +( \ + (info.security_attributes & NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID ) && \ + (info.security_attributes & NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_READ_PROTECTED ) \ +) + +#define SECURITY_INFO_IS_RTPS_PROTECTED(info) \ +( \ + (info.security_attributes & NN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_VALID ) && \ + (info.security_attributes & NN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_RTPS_PROTECTED) \ +) + +#define SECURITY_INFO_USE_RTPS_AUTHENTICATION(info) \ + ((info).plugin_participant_attributes & DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_RTPS_AUTHENTICATED) static bool endpoint_is_DCPSParticipantSecure (const ddsi_guid_t *guid) { @@ -92,14 +148,415 @@ static bool endpoint_is_DCPSParticipantMessageSecure (const ddsi_guid_t *guid) static bool endpoint_is_DCPSParticipantVolatileMessageSecure (const ddsi_guid_t *guid) { -#if 1 - /* TODO: volatile endpoint. */ - DDSRT_UNUSED_ARG(guid); - return false; -#else return ((guid->entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER) || (guid->entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER)); -#endif +} + +struct participant_sec_index { + ddsrt_mutex_t lock; + ddsrt_avl_ctree_t participants; +}; + +struct dds_security_context { + dds_security_plugin auth_plugin; + dds_security_plugin ac_plugin; + dds_security_plugin crypto_plugin; + + dds_security_authentication *authentication_context; + dds_security_cryptography *crypto_context; + dds_security_access_control *access_control_context; + ddsrt_mutex_t omg_security_lock; + uint32_t next_plugin_id; + + struct participant_sec_index partiticpant_index; + + const struct ddsrt_log_cfg *logcfg; +}; + +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); + +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); + +static int compare_crypto_handle (const void *va, const void *vb) +{ + const DDS_Security_ParticipantCryptoHandle *ha = va; + const DDS_Security_ParticipantCryptoHandle *hb = vb; + + return ((*ha > *hb) ? 1 : (*ha < *hb) ? -1 : 0); +} + +static int guid_compare (const ddsi_guid_t *guid1, const ddsi_guid_t *guid2) +{ + return memcmp (guid1, guid2, sizeof (ddsi_guid_t)); +} + +static int compare_guid(const void *va, const void *vb) +{ + const ddsi_guid_t *ga = va; + const ddsi_guid_t *gb = vb; + + return guid_compare(ga, gb); +} + +static int compare_guid_pair(const void *va, const void *vb) +{ + const struct guid_pair *na = va; + const struct guid_pair *nb = vb; + int r; + + if ((r = guid_compare(&na->src, &nb->src)) == 0) + r = guid_compare(&na->dst, &nb->dst); + return r; +} + +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)) + return pp->e.gv->security_context; + return NULL; +} + +struct dds_security_authentication *q_omg_participant_get_authentication(const struct participant *pp) +{ + if (pp && pp->e.gv->security_context && q_omg_is_security_loaded(pp->e.gv->security_context)) + return pp->e.gv->security_context->authentication_context; + return NULL; +} + +static struct dds_security_context * q_omg_security_get_secure_context_from_proxypp(const struct proxy_participant *proxypp) +{ + if (proxypp && proxypp->e.gv->security_context && q_omg_is_security_loaded(proxypp->e.gv->security_context)) + return proxypp->e.gv->security_context; + return NULL; +} + +void q_omg_log_exception(const struct ddsrt_log_cfg *lc, uint32_t cat, DDS_Security_SecurityException *exception, const char *file, uint32_t line, const char *func, const char *fmt, ...) +{ + char logbuffer[512]; + va_list ap; + int l; + + va_start (ap, fmt); + l = vsnprintf(logbuffer, sizeof(logbuffer), fmt, ap); + va_end (ap); + if ((size_t) l >= sizeof(logbuffer)) + { + logbuffer[sizeof(logbuffer)-1] = '\0'; + } + dds_log_cfg(lc, cat, file, line, func, "%s: %s(code: %d)\n", logbuffer, exception->message ? exception->message : "", exception->code); + DDS_Security_Exception_reset(exception); +} + +static struct security_entity_match * entity_match_new(const ddsi_guid_t *src, const ddsi_guid_t *dst) +{ + 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); + 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) +{ + struct guid_pair guids; + + 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) + { + match = entity_match_new(src, dst); + ddsrt_avl_insert(&entity_match_treedef, &list->matches, match); + } + ddsrt_mutex_unlock(&list->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) +{ + struct security_entity_match *match; + struct guid_pair guids; + ddsrt_avl_dpath_t path; + + guids.src = *src; + guids.dst = *dst; + + ddsrt_mutex_lock(&list->lock); + match = ddsrt_avl_lookup_dpath(&entity_match_treedef, &list->matches, &guids, &path); + if (match) + ddsrt_avl_delete_dpath(&entity_match_treedef, &list->matches, match, &path); + ddsrt_mutex_unlock(&list->lock); + + return match; +} + +static struct dds_security_match_index * security_match_index_new(void) +{ + struct dds_security_match_index *list; + + 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_avl_free (&entity_match_treedef, &list->matches, entity_match_free_wrapper); + ddsrt_mutex_destroy(&list->lock); + ddsrt_free(list); + } +} + +static struct pp_proxypp_match * pp_proxypp_match_new(struct proxy_participant *proxypp, DDS_Security_ParticipantCryptoHandle proxypp_crypto_handle) +{ + struct pp_proxypp_match *pm; + + pm = ddsrt_malloc(sizeof(*pm)); + pm->proxypp_guid = proxypp->e.guid; + pm->proxypp_crypto_handle = proxypp_crypto_handle; + + return pm; +} + +static void pp_proxypp_match_free(struct dds_security_context *sc, struct pp_proxypp_match *pm) +{ + DDSRT_UNUSED_ARG(sc); + + ddsrt_free(pm); +} + +static struct proxypp_pp_match * proxypp_pp_match_new(struct participant *pp, DDS_Security_PermissionsHandle permissions_hdl, DDS_Security_SharedSecretHandle shared_secret) +{ + struct proxypp_pp_match *pm; + + pm = ddsrt_malloc(sizeof(*pm)); + pm->pp_guid = pp->e.guid; + pm->pp_crypto_handle = pp->sec_attr->crypto_handle; + pm->permissions_handle = permissions_hdl; + pm->shared_secret = shared_secret; + + return pm; +} + +static void proxypp_pp_match_free(struct dds_security_context *sc, struct proxypp_pp_match *pm) +{ + DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + + if (pm->permissions_handle != DDS_SECURITY_HANDLE_NIL) + { + if (!sc->access_control_context->return_permissions_handle(sc->access_control_context, pm->permissions_handle, &exception)) + EXCEPTION_ERROR(sc, &exception, "Failed to return remote permissions handle"); + } + ddsrt_free(pm); +} + +static void pp_proxypp_unrelate(struct dds_security_context *sc, struct participant *pp, const ddsi_guid_t *proxypp_guid) +{ + struct pp_proxypp_match *pm; + ddsrt_avl_dpath_t dpath; + + ddsrt_mutex_lock(&pp->sec_attr->lock); + if ((pm = ddsrt_avl_clookup_dpath(&pp_proxypp_treedef, &pp->sec_attr->proxy_participants, proxypp_guid, &dpath)) != NULL) + { + ddsrt_avl_cdelete_dpath(&pp_proxypp_treedef, &pp->sec_attr->proxy_participants, pm, &dpath); + pp_proxypp_match_free(sc, pm); + } + ddsrt_mutex_unlock(&pp->sec_attr->lock); +} + +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) +{ + 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) + { + ddsrt_avl_delete_dpath(&proxypp_pp_treedef, &proxypp->sec_attr->participants, pm, &dpath); + proxypp_pp_match_free(sc, pm); + } + ddsrt_mutex_unlock(&proxypp->sec_attr->lock); + } +} + +static struct participant_sec_attributes * participant_sec_attributes_new(ddsi_guid_t *guid) +{ + struct participant_sec_attributes *attr; + + attr = ddsrt_malloc(sizeof(*attr)); + ddsrt_mutex_init(&attr->lock); + ddsrt_avl_cinit(&pp_proxypp_treedef, &attr->proxy_participants); + attr->pp_guid = *guid; + attr->crypto_handle = DDS_SECURITY_HANDLE_NIL; + attr->plugin_attr = false; + attr->initialized = false; + return attr; +} + +static void participant_sec_attributes_free(struct participant_sec_attributes *attr) +{ + if (attr) + { + ddsrt_avl_cfree(&pp_proxypp_treedef, &attr->proxy_participants, 0); + ddsrt_mutex_destroy(&attr->lock); + ddsrt_free(attr); + } +} + +static struct writer_sec_attributes * writer_sec_attributes_new(void) +{ + struct writer_sec_attributes *attr; + + attr = ddsrt_malloc(sizeof(*attr)); + memset(attr, 0, sizeof(*attr)); + attr->crypto_handle = DDS_SECURITY_HANDLE_NIL; + attr->plugin_attr = false; + return attr; +} + +static void writer_sec_attributes_free(struct writer_sec_attributes *attr) +{ + ddsrt_free(attr); +} + +static struct reader_sec_attributes * reader_sec_attributes_new(void) +{ + struct reader_sec_attributes *attr; + + attr = ddsrt_malloc(sizeof(*attr)); + memset(attr, 0, sizeof(*attr)); + attr->crypto_handle = DDS_SECURITY_HANDLE_NIL; + attr->plugin_attr = false; + + return attr; +} + +static void reader_sec_attributes_free(struct reader_sec_attributes *attr) +{ + ddsrt_free(attr); +} + +static void +participant_index_add(dds_security_context *sc, struct participant_sec_attributes *attr) +{ + ddsrt_mutex_lock(&sc->partiticpant_index.lock); + ddsrt_avl_cinsert(&participant_index_treedef, &sc->partiticpant_index.participants, attr); + ddsrt_mutex_unlock(&sc->partiticpant_index.lock); +} + +static struct participant_sec_attributes * +participant_index_find(dds_security_context *sc, int64_t crypto_handle) +{ + struct participant_sec_attributes *attr; + + ddsrt_mutex_lock(&sc->partiticpant_index.lock); + attr = ddsrt_avl_clookup(&participant_index_treedef, &sc->partiticpant_index.participants, &crypto_handle); + ddsrt_mutex_unlock(&sc->partiticpant_index.lock); + + return attr; +} + +static struct participant_sec_attributes * +participant_index_remove(dds_security_context *sc, int64_t crypto_handle) +{ + struct participant_sec_attributes *attr; + ddsrt_avl_dpath_t dpath; + + ddsrt_mutex_lock(&sc->partiticpant_index.lock); + attr = ddsrt_avl_clookup_dpath(&participant_index_treedef, &sc->partiticpant_index.participants, &crypto_handle, &dpath); + if (attr) + ddsrt_avl_cdelete_dpath(&participant_index_treedef, &sc->partiticpant_index.participants, attr, &dpath); + ddsrt_mutex_unlock(&sc->partiticpant_index.lock); + + return attr; +} + +static uint32_t +get_matched_proxypp_crypto_handles(struct participant_sec_attributes *attr, DDS_Security_ParticipantCryptoHandleSeq *hdls) +{ + uint32_t i; + struct pp_proxypp_match *pm; + ddsrt_avl_citer_t it; + + ddsrt_mutex_lock(&attr->lock); + hdls->_length = hdls->_maximum = (uint32_t)ddsrt_avl_ccount(&attr->proxy_participants); + hdls->_buffer = NULL; + if (hdls->_length == 0) + { + ddsrt_mutex_unlock(&attr->lock); + return 0; + } + hdls->_buffer = ddsrt_malloc(hdls->_length * sizeof(int64_t)); + for (pm = ddsrt_avl_citer_first(&pp_proxypp_treedef, &attr->proxy_participants, &it), i = 0; pm; pm = ddsrt_avl_citer_next(&it), i++) + hdls->_buffer[i] = pm->proxypp_crypto_handle; + ddsrt_mutex_unlock(&attr->lock); + return hdls->_length; +} + +static int64_t +get_first_matched_proxypp_crypto_handle(struct participant_sec_attributes *attr) +{ + int64_t handle = 0; + struct pp_proxypp_match *pm; + + ddsrt_mutex_lock(&attr->lock); + pm = ddsrt_avl_croot(&pp_proxypp_treedef, &attr->proxy_participants); + if (pm) + handle = pm->proxypp_crypto_handle; + ddsrt_mutex_unlock(&attr->lock); + + return handle; } bool q_omg_is_security_loaded (dds_security_context *sc) @@ -107,22 +564,27 @@ bool q_omg_is_security_loaded (dds_security_context *sc) return (sc->crypto_context != NULL || sc->authentication_context != NULL || sc->access_control_context != NULL); } -void q_omg_security_init (dds_security_context **sc, const struct ddsrt_log_cfg *logcfg) +void q_omg_security_init (struct ddsi_domaingv *gv) { - *sc = ddsrt_malloc (sizeof (dds_security_context)); - memset (*sc, 0, sizeof (dds_security_context)); + dds_security_context *sc; - (*sc)->auth_plugin.name = AUTH_NAME; - (*sc)->ac_plugin.name = AC_NAME; - (*sc)->crypto_plugin.name = CRYPTO_NAME; + sc = ddsrt_malloc (sizeof (dds_security_context)); + memset (sc, 0, sizeof (dds_security_context)); - ddsrt_mutex_init (&(*sc)->omg_security_lock); - (*sc)->logcfg = logcfg; + sc->auth_plugin.name = AUTH_NAME; + sc->ac_plugin.name = AC_NAME; + sc->crypto_plugin.name = CRYPTO_NAME; - //DDS_CTRACE ((*sc)->logcfg, "DDS Security init\n"); -#if HANDSHAKE_IMPLEMENTED - //remote_participant_crypto_handle_list_init(); -#endif + ddsrt_mutex_init(&sc->partiticpant_index.lock); + ddsrt_avl_cinit(&participant_index_treedef, &sc->partiticpant_index.participants); + + 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); } /** @@ -130,42 +592,42 @@ void q_omg_security_init (dds_security_context **sc, const struct ddsrt_log_cfg */ static void release_plugins (dds_security_context *sc) { -#if HANDSHAKE_IMPLEMENTED - q_handshake_terminate (); -#endif - if (dds_security_plugin_release (&sc->auth_plugin, sc->authentication_context)) - DDS_CERROR (sc->logcfg, "Error occured releasing %s plugin", sc->auth_plugin.name); + DDS_CERROR (sc->logcfg, "Error occurred releasing %s plugin", sc->auth_plugin.name); if (dds_security_plugin_release (&sc->crypto_plugin, sc->crypto_context)) - DDS_CERROR (sc->logcfg, "Error occured releasing %s plugin", sc->crypto_plugin.name); + DDS_CERROR (sc->logcfg, "Error occurred releasing %s plugin", sc->crypto_plugin.name); if (dds_security_plugin_release (&sc->ac_plugin, sc->access_control_context)) - DDS_CERROR (sc->logcfg, "Error occured releasing %s plugin", sc->ac_plugin.name); + DDS_CERROR (sc->logcfg, "Error occurred releasing %s plugin", sc->ac_plugin.name); sc->authentication_context = NULL; sc->access_control_context = NULL; sc->crypto_context = NULL; } -void q_omg_security_deinit (struct dds_security_context **sc) +void q_omg_security_deinit (struct ddsi_domaingv *gv) { - assert (sc != NULL); - assert (*sc != NULL); + dds_security_context *sc = gv->security_context; -#if HANDSHAKE_IMPLEMENTED - //remote_participant_crypto_handle_list_deinit(); -#endif + assert (gv->security_context != NULL); - if ((*sc)->authentication_context != NULL && (*sc)->access_control_context != NULL && (*sc)->crypto_context != NULL){ - release_plugins (*sc); + 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); } - ddsrt_mutex_destroy (&(*sc)->omg_security_lock); + ddsi_handshake_admin_deinit(gv); - //DDS_CTRACE ((*sc)->logcfg, "DDS Security deinit\n"); - ddsrt_free (*sc); - *sc = NULL; + 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); + gv->security_context = NULL; } static void dds_qos_to_security_plugin_configuration (const dds_qos_t *qos, dds_security_plugin_suite_config *suite_config) @@ -278,99 +740,738 @@ error: return DDS_RETCODE_ERROR; } -bool q_omg_participant_is_secure (const struct participant *pp) +static const char * get_builtin_topic_name(ddsi_entityid_t id) { - /* TODO: Register local participant. */ - DDSRT_UNUSED_ARG (pp); - return false; + switch (id.u) { + case NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER: + case NN_ENTITYID_SEDP_BUILTIN_TOPIC_READER: + return "DCPSTopic"; + break; + case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER: + case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER: + return "DCPSPublication"; + break; + case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER: + case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER: + return "DCPSSubscription"; + break; + case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER: + case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER: + return "DCPSParticipant"; + break; + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER: + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER: + return "DCPSParticipantMessage"; + break; + case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER: + case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_READER: + return "DCPSPublicationsSecure"; + break; + case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER: + case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_READER: + return "DCPSSubscriptionsSecure"; + break; + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER: + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_READER: + return "DCPSParticipantStatelessMessage"; + break; + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER: + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_READER: + return "DCPSParticipantMessageSecure"; + break; + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER: + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER: + return "DCPSParticipantVolatileMessageSecure"; + break; + case NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER: + case NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_READER: + return "DCPSParticipantsSecure"; + break; + default: + return "(null)"; + break; + } + + return NULL; +} + +static void notify_handshake_recv_token(struct participant *pp, struct proxy_participant *proxypp) +{ + struct ddsi_handshake *handshake; + + handshake = ddsi_handshake_find(pp, proxypp); + if (handshake) { + ddsi_handshake_crypto_tokens_received(handshake); + ddsi_handshake_release(handshake); + } +} + +static const char * get_reader_topic_name(struct reader *rd) +{ + if (rd->topic) { + return rd->topic->name; + } + return get_builtin_topic_name(rd->e.guid.entityid); +} + +static const char * get_writer_topic_name(struct writer *wr) +{ + if (wr->topic) { + return wr->topic->name; + } + return get_builtin_topic_name(wr->e.guid.entityid); +} + +bool q_omg_participant_is_secure(const struct participant *pp) +{ + return ((pp->sec_attr != NULL) && (pp->sec_attr->crypto_handle != DDS_SECURITY_HANDLE_NIL)); } bool q_omg_proxy_participant_is_secure (const struct proxy_participant *proxypp) { - /* TODO: Register remote participant */ - DDSRT_UNUSED_ARG (proxypp); - return false; + return (proxypp->sec_attr != NULL); } -static bool q_omg_writer_is_discovery_protected (const struct writer *wr) +bool q_omg_participant_allow_unauthenticated(struct participant *pp) { - /* TODO: Register local writer. */ - DDSRT_UNUSED_ARG (wr); - return false; + return ((pp->sec_attr != NULL) && pp->sec_attr->attr.allow_unauthenticated_participants); } -static bool q_omg_reader_is_discovery_protected (const struct reader *rd) +bool q_omg_security_check_create_participant(struct participant *pp, uint32_t domain_id) { - /* TODO: Register local reader. */ - DDSRT_UNUSED_ARG (rd); - return false; + bool allowed = false; + struct dds_security_context *sc = q_omg_security_get_secure_context(pp); + DDS_Security_IdentityHandle identity_handle = DDS_SECURITY_HANDLE_NIL; + DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + DDS_Security_ValidationResult_t result = 0; + DDS_Security_IdentityToken identity_token; + DDS_Security_PermissionsToken permissions_token = DDS_SECURITY_TOKEN_INIT; + DDS_Security_PermissionsCredentialToken credential_token = DDS_SECURITY_TOKEN_INIT; + struct participant_sec_attributes *sec_attr = NULL; + DDS_Security_Qos par_qos; + ddsi_guid_t candidate_guid; + ddsi_guid_t adjusted_guid; + + if (!sc) + return true; + + /* Validate local identity */ + ETRACE (pp, "validate_local_identity: candidate_guid: "PGUIDFMT" ", PGUID (pp->e.guid)); + + candidate_guid = nn_hton_guid(pp->e.guid); + q_omg_shallow_copy_security_qos(&par_qos, &(pp->plist->qos)); + + result = sc->authentication_context->validate_local_identity( + sc->authentication_context, &identity_handle, + (DDS_Security_GUID_t *) &adjusted_guid, (DDS_Security_DomainId) domain_id, &par_qos, + (DDS_Security_GUID_t *) &candidate_guid, &exception); + if (result != DDS_SECURITY_VALIDATION_OK) + { + EXCEPTION_ERROR(sc, &exception, "Error occurred while validating local permission"); + goto validation_failed; + } + pp->e.guid = nn_ntoh_guid(adjusted_guid); + + sec_attr = participant_sec_attributes_new(&pp->e.guid); + sec_attr->local_identity_handle = identity_handle; + + ETRACE (pp, "adjusted_guid: "PGUIDFMT" ", PGUID (pp->e.guid)); + + /* Get the identity token and add this to the plist of the participant */ + if (!sc->authentication_context->get_identity_token(sc->authentication_context, &identity_token, identity_handle, &exception)) + { + EXCEPTION_ERROR(sc, &exception, "Error occurred while retrieving the identity token"); + goto validation_failed; + } + assert(exception.code == 0); + + q_omg_security_dataholder_copyin(&pp->plist->identity_token, &identity_token); + DDS_Security_DataHolder_deinit(&identity_token); + pp->plist->present |= PP_IDENTITY_TOKEN; + + sec_attr->permissions_handle = sc->access_control_context->validate_local_permissions( + sc->access_control_context, sc->authentication_context, identity_handle, + (DDS_Security_DomainId)domain_id, &par_qos, &exception); + if (sec_attr->permissions_handle == DDS_SECURITY_HANDLE_NIL) + { + EXCEPTION_ERROR(sc, &exception, "Error occurred while validating local permissions"); + goto not_allowed; + } + + /* ask to access control security plugin for create participant permissions related to this identity*/ + if (!sc->access_control_context->check_create_participant(sc->access_control_context, sec_attr->permissions_handle, (DDS_Security_DomainId) domain_id, &par_qos, &exception)) + { + EXCEPTION_ERROR(sc, &exception, "It is not allowed to create participant"); + goto not_allowed; + } + + /* Get the identity token and add this to the plist of the participant */ + if (!sc->access_control_context->get_permissions_token(sc->access_control_context, &permissions_token, sec_attr->permissions_handle, &exception)) + { + EXCEPTION_ERROR(sc, &exception, "Error occurred while retrieving the permissions token"); + goto not_allowed; + } + + q_omg_security_dataholder_copyin(&pp->plist->permissions_token, &permissions_token); + pp->plist->present |= PP_PERMISSIONS_TOKEN; + + if (!sc->access_control_context->get_permissions_credential_token(sc->access_control_context, &credential_token, sec_attr->permissions_handle, &exception)) + { + EXCEPTION_ERROR(sc, &exception, "Error occurred while retrieving the permissions credential token"); + goto no_credentials; + } + + if (!sc->authentication_context->set_permissions_credential_and_token(sc->authentication_context, sec_attr->local_identity_handle, &credential_token, &permissions_token, &exception)) + { + EXCEPTION_ERROR(sc, &exception, "Error occurred while setting the permissions credential token"); + goto no_credentials; + } + + if (!sc->access_control_context->get_participant_sec_attributes(sc->access_control_context, sec_attr->permissions_handle, &sec_attr->attr, &exception)) + { + EXCEPTION_ERROR(sc, &exception, "Failed to get participant security attributes"); + goto no_sec_attr; + } + + sec_attr->plugin_attr = true; + sec_attr->crypto_handle = sc->crypto_context->crypto_key_factory->register_local_participant( + sc->crypto_context->crypto_key_factory, sec_attr->local_identity_handle, sec_attr->permissions_handle, NULL, &sec_attr->attr, &exception); + if (!sec_attr->crypto_handle) { + EXCEPTION_ERROR(sc, &exception, "Failed to register participant with crypto key factory"); + goto no_crypto; + } + + participant_index_add(sc, sec_attr); + pp->sec_attr = sec_attr; + + ETRACE (pp, "\n"); + + allowed = true; + +no_crypto: +no_sec_attr: +no_credentials: + if (permissions_token.class_id) + (void)sc->access_control_context->return_permissions_token(sc->access_control_context, &permissions_token, NULL); + if (credential_token.class_id) + (void)sc->access_control_context->return_permissions_credential_token(sc->access_control_context, &credential_token, NULL); +not_allowed: + if (!allowed) + participant_sec_attributes_free(sec_attr); +validation_failed: + q_omg_shallow_free_security_qos(&par_qos); + return allowed; } -bool q_omg_get_writer_security_info (const struct writer *wr, nn_security_info_t *info) +void q_omg_security_participant_set_initialized(struct participant *pp) { - assert (wr); - assert (info); - /* TODO: Register local writer. */ - DDSRT_UNUSED_ARG (wr); + if (pp->sec_attr) + { + ddsrt_mutex_lock(&pp->sec_attr->lock); + pp->sec_attr->initialized = true; + ddsrt_mutex_unlock(&pp->sec_attr->lock); + } +} +bool q_omg_security_participant_is_initialized(struct participant *pp) +{ + bool initialized = false; + + if (pp->sec_attr) + { + ddsrt_mutex_lock(&pp->sec_attr->lock); + initialized = pp->sec_attr->initialized; + ddsrt_mutex_unlock(&pp->sec_attr->lock); + } + return initialized; +} + +struct cleanup_participant_sec_attributes_arg { + struct ddsi_domaingv *gv; + int64_t crypto_handle; +}; + +static void cleanup_participant_sec_attributes(void *arg) +{ + DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + struct cleanup_participant_sec_attributes_arg *info = arg; + struct ddsi_domaingv * gv = info->gv; + dds_security_context *sc = gv->security_context; + struct participant_sec_attributes *attr; + + struct pp_proxypp_match *pm; + + if ((attr = participant_index_remove(sc, info->crypto_handle)) == NULL) + return; + + pm = ddsrt_avl_cfind_min(&pp_proxypp_treedef, &attr->proxy_participants); + while (pm) + { + struct pp_proxypp_match *next = ddsrt_avl_cfind_succ(&pp_proxypp_treedef, &attr->proxy_participants, pm); + ddsrt_mutex_lock(&gv->lock); + struct proxy_participant *proxypp = entidx_lookup_proxy_participant_guid(gv->entity_index, &pm->proxypp_guid); + if (proxypp) + proxypp_pp_unrelate(sc, proxypp, &attr->pp_guid, attr->crypto_handle); + ddsrt_mutex_unlock(&gv->lock); + ddsrt_avl_cdelete(&pp_proxypp_treedef, &attr->proxy_participants, pm); + ddsrt_free(pm); + pm = next; + } + + if (attr->permissions_handle != DDS_SECURITY_HANDLE_NIL) + { + if (!sc->access_control_context->return_permissions_handle(sc->access_control_context, attr->permissions_handle, &exception)) + EXCEPTION_ERROR(sc, &exception, "Failed to return local permissions handle"); + } + if (attr->local_identity_handle != DDS_SECURITY_HANDLE_NIL) + { + if (!sc->authentication_context->return_identity_handle(sc->authentication_context, attr->local_identity_handle, &exception)) + EXCEPTION_ERROR(sc, &exception, "Failed to return local identity handle"); + } + if (attr->plugin_attr) + { + if (!sc->access_control_context->return_participant_sec_attributes(sc->access_control_context, &attr->attr, &exception)) + EXCEPTION_ERROR(sc, &exception, "Failed to return participant security attributes"); + } + + (void)sc->crypto_context->crypto_key_factory->unregister_participant(sc->crypto_context->crypto_key_factory, attr->crypto_handle, NULL); + + ddsrt_avl_cfree(&pp_proxypp_treedef, &attr->proxy_participants, NULL); + ddsrt_mutex_unlock(&attr->lock); + ddsrt_free(attr); + ddsrt_free(arg); +} + +void q_omg_security_deregister_participant(struct participant *pp) +{ +// DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + struct dds_security_context *sc = q_omg_security_get_secure_context(pp); + + if (!sc) + return; + + /* When the participant is deleted the timed event queue may still contain + * messages from this participant. Therefore the crypto handle should still + * be available to ensure that the rtps message can be encoded. + * For this purpose the cleanup of the associated crypto handle is delayed. + * A callback is scheduled to be called after some delay to cleanup this + * crypto handle. + */ + if (pp->sec_attr->crypto_handle != DDS_SECURITY_HANDLE_NIL) { + struct cleanup_participant_sec_attributes_arg *arg = ddsrt_malloc (sizeof (*arg)); + arg->crypto_handle = pp->sec_attr->crypto_handle; + arg->gv = pp->e.gv; + qxev_nt_callback(pp->e.gv->xevents, cleanup_participant_sec_attributes, arg); + } + + pp->sec_attr = NULL; +} + +int64_t q_omg_security_get_local_participant_handle(const struct participant *pp) +{ + if (pp->sec_attr) + return pp->sec_attr->crypto_handle; + return 0; +} + +bool q_omg_participant_is_access_protected(const struct participant *pp) +{ + return ((pp->sec_attr != NULL) && pp->sec_attr->attr.is_access_protected); +} + +bool q_omg_participant_is_rtps_protected(const struct participant *pp) +{ + return ((pp->sec_attr != NULL) && pp->sec_attr->attr.is_rtps_protected); +} + +bool q_omg_participant_is_liveliness_protected(const struct participant *pp) +{ + return ((pp->sec_attr != NULL) && pp->sec_attr->attr.is_liveliness_protected); +} + + +static bool maybe_rtps_protected(ddsi_entityid_t entityid) +{ + if (!is_builtin_entityid(entityid, NN_VENDORID_ECLIPSE)) + return true; + + switch (entityid.u) + { + case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER: + case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_READER: + case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER: + case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_READER: + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER: + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_READER: + case NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER: + case NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_READER: + return true; + default: + return false; + } +} + +static bool proxypp_is_rtps_protected(const struct proxy_participant *proxypp) +{ + return (proxypp->sec_attr != NULL && SECURITY_INFO_IS_RTPS_PROTECTED(proxypp->security_info)); +} + +bool q_omg_security_is_remote_rtps_protected(const struct proxy_participant *proxypp, ddsi_entityid_t entityid) +{ + return q_omg_proxy_participant_is_secure(proxypp) && + SECURITY_INFO_IS_RTPS_PROTECTED(proxypp->security_info) && + maybe_rtps_protected(entityid); +} + +bool q_omg_security_is_local_rtps_protected(const struct participant *pp, ddsi_entityid_t entityid) +{ + return q_omg_participant_is_rtps_protected(pp) && maybe_rtps_protected(entityid); +} + +bool q_omg_get_participant_security_info(const struct participant *pp, nn_security_info_t *info) +{ + assert(pp); + assert(info); + + if (q_omg_participant_is_secure(pp)) { + const DDS_Security_ParticipantSecurityAttributes *attr = &(pp->sec_attr->attr); + + info->security_attributes = NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID; + info->plugin_security_attributes = attr->plugin_participant_attributes; + + if (attr->is_discovery_protected) + info->security_attributes |= NN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_DISCOVERY_PROTECTED; + + if (attr->is_liveliness_protected) + info->security_attributes |= NN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_LIVELINESS_PROTECTED; + + if (attr->is_rtps_protected) + info->security_attributes |= NN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_RTPS_PROTECTED; + + return true; + } + + info->security_attributes = 0; info->plugin_security_attributes = 0; - if (q_omg_writer_is_payload_protected (wr)) - { - info->security_attributes = - NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID | - NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_PAYLOAD_PROTECTED; - } - else - { - info->security_attributes = 0; - } - return true; + + return false; } -bool q_omg_get_reader_security_info (const struct reader *rd, nn_security_info_t *info) +static void q_omg_get_endpoint_security_info(DDS_Security_EndpointSecurityAttributes *attr, nn_security_info_t *info) { - assert (rd); - assert (info); - /* TODO: Register local reader. */ - DDSRT_UNUSED_ARG (rd); + info->security_attributes = NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID; + info->plugin_security_attributes = attr->plugin_endpoint_attributes; + + if (attr->is_read_protected) + info->security_attributes |= NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_READ_PROTECTED; + + if (attr->is_write_protected) + info->security_attributes |= NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_WRITE_PROTECTED; + + if (attr->is_discovery_protected) + info->security_attributes |= NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_DISCOVERY_PROTECTED; + + if (attr->is_liveliness_protected) + info->security_attributes |= NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_LIVELINESS_PROTECTED; + + if (attr->is_submessage_protected) + info->security_attributes |= NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_PROTECTED; + + if (attr->is_payload_protected) + info->security_attributes |= NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_PAYLOAD_PROTECTED; + + if (attr->is_key_protected) + info->security_attributes |= NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_KEY_PROTECTED; +} + +static bool is_topic_discovery_protected(DDS_Security_PermissionsHandle permission_handle, dds_security_access_control *access_control, const char *topic_name) +{ + DDS_Security_TopicSecurityAttributes attributes = {0,0,0,0}; + DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + + if (access_control->get_topic_sec_attributes(access_control, permission_handle, topic_name, &attributes, &exception)) + return attributes.is_discovery_protected; + else + DDS_Security_Exception_reset(&exception); + return false; +} + +bool q_omg_security_check_create_topic(const struct ddsi_domaingv *gv, const ddsi_guid_t *pp_guid, const char *topic_name, const struct dds_qos *qos) +{ + bool result = true; + struct participant *pp; + struct dds_security_context *sc; + DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + DDS_Security_Qos topic_qos; + + thread_state_awake (lookup_thread_state (), gv); + pp = entidx_lookup_participant_guid (gv->entity_index, pp_guid); + + if ((sc = q_omg_security_get_secure_context(pp)) != NULL) + { + q_omg_shallow_copy_security_qos(&topic_qos, qos); + result = sc->access_control_context->check_create_topic(sc->access_control_context, pp->sec_attr->permissions_handle, (DDS_Security_DomainId)gv->config.domainId, topic_name, &topic_qos, &exception); + if (!result) + { + /*log if the topic discovery is not protected*/ + if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, topic_name)) + EXCEPTION_ERROR(sc, &exception, "Local topic permission denied"); + else + DDS_Security_Exception_reset(&exception); + } + q_omg_shallow_free_security_qos(&topic_qos); + } + thread_state_asleep (lookup_thread_state ()); + + return result; +} + +bool q_omg_security_check_create_writer(struct participant *pp, uint32_t domain_id, const char *topic_name, const struct dds_qos *writer_qos) +{ + struct dds_security_context *sc = q_omg_security_get_secure_context(pp) ; + DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + DDS_Security_PartitionQosPolicy partitions; + DDS_Security_Qos security_qos; + bool result; + + if (!sc) + return true; + + if (writer_qos->present & QP_PARTITION) + g_omg_shallow_copy_StringSeq(&partitions.name, &(writer_qos->partition)); + else + memset(&(partitions), 0, sizeof(DDS_Security_PartitionQosPolicy)); + + q_omg_shallow_copy_security_qos(&security_qos, writer_qos); + + result = sc->access_control_context->check_create_datawriter(sc->access_control_context, pp->sec_attr->permissions_handle, (DDS_Security_DomainId)domain_id, topic_name, &security_qos, &partitions, NULL, &exception); + if (!result) + { + /*log if the topic discovery is not protected*/ + if (!is_topic_discovery_protected( pp->sec_attr->permissions_handle, sc->access_control_context, topic_name)) + EXCEPTION_ERROR(sc, &exception, "Local topic permission denied"); + else + DDS_Security_Exception_reset(&exception); + } + + q_omg_shallow_free_security_qos(&security_qos); + g_omg_shallow_free_StringSeq(&partitions.name); + + return result; +} + +void q_omg_security_register_writer(struct writer *wr) +{ + struct participant *pp = wr->c.pp; + struct dds_security_context *sc = q_omg_security_get_secure_context(pp); + DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + DDS_Security_PartitionQosPolicy partitions; + DDS_Security_PropertySeq properties; + const char *topic_name; + + if (!sc) + return; + + if (wr->xqos->present & QP_PARTITION) + g_omg_shallow_copy_StringSeq(&partitions.name, &(wr->xqos->partition)); + else + memset(&(partitions), 0, sizeof(DDS_Security_PartitionQosPolicy)); + + wr->sec_attr = writer_sec_attributes_new(); + topic_name = get_writer_topic_name(wr); + if (!sc->access_control_context->get_datawriter_sec_attributes(sc->access_control_context, pp->sec_attr->permissions_handle, topic_name, &partitions, NULL, &wr->sec_attr->attr, &exception)) + { + EXCEPTION_ERROR(sc, &exception, "Failed to retrieve writer security attributes"); + goto no_attr; + } + wr->sec_attr->plugin_attr = true; + + if (wr->sec_attr->attr.is_payload_protected || wr->sec_attr->attr.is_submessage_protected) + { + if (wr->xqos->present & QP_PROPERTY_LIST) + q_omg_copy_PropertySeq(&properties, &wr->xqos->property.value); + else + memset(&properties, 0, sizeof(DDS_Security_PropertySeq)); + + wr->sec_attr->crypto_handle = sc->crypto_context->crypto_key_factory->register_local_datawriter( + sc->crypto_context->crypto_key_factory, pp->sec_attr->crypto_handle, &properties, &wr->sec_attr->attr, &exception); + DDS_Security_PropertySeq_freebuf(&properties); + if (wr->sec_attr->crypto_handle == DDS_SECURITY_HANDLE_NIL) + { + EXCEPTION_ERROR(sc, &exception, "Failed to register writer with crypto"); + goto not_registered; + } + } + + if (wr->sec_attr->attr.is_key_protected) + wr->include_keyhash = 1; + +not_registered: +no_attr: + g_omg_shallow_free_StringSeq(&partitions.name); +} + +void q_omg_security_deregister_writer(struct writer *wr) +{ + struct dds_security_context *sc = q_omg_security_get_secure_context(wr->c.pp); + DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + + if (wr->sec_attr) + { + 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)) + EXCEPTION_ERROR(sc, &exception, "Failed to unregister writer with crypto"); + } + if (wr->sec_attr->plugin_attr) + { + if (!sc->access_control_context->return_datawriter_sec_attributes(sc->access_control_context, &wr->sec_attr->attr, &exception)) + EXCEPTION_ERROR(sc, &exception, "Failed to return writer security attributes"); + } + writer_sec_attributes_free(wr->sec_attr); + wr->sec_attr = NULL; + } +} + +bool q_omg_get_writer_security_info(const struct writer *wr, nn_security_info_t *info) +{ + assert(wr); + assert(info); + + if (wr->sec_attr) { + q_omg_get_endpoint_security_info(&wr->sec_attr->attr, info); + return true; + } info->plugin_security_attributes = 0; info->security_attributes = 0; return false; } -void q_omg_security_init_remote_participant (struct proxy_participant *proxypp) +bool q_omg_security_check_create_reader(struct participant *pp, uint32_t domain_id, const char *topic_name, const struct dds_qos *reader_qos) { - DDSRT_UNUSED_ARG (proxypp); + struct dds_security_context *sc = q_omg_security_get_secure_context(pp); + DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + DDS_Security_PartitionQosPolicy partitions; + DDS_Security_Qos security_qos; + bool result; + + if (!sc) + return true; + + if (reader_qos->present & QP_PARTITION) + g_omg_shallow_copy_StringSeq(&partitions.name, &(reader_qos->partition)); + else + memset(&(partitions), 0, sizeof(DDS_Security_PartitionQosPolicy)); + + q_omg_shallow_copy_security_qos(&security_qos, reader_qos); + + result = sc->access_control_context->check_create_datareader(sc->access_control_context, pp->sec_attr->permissions_handle, (DDS_Security_DomainId)domain_id, topic_name, &security_qos, &partitions, NULL, &exception); + if (!result) + { + /*log if the topic discovery is not protected*/ + if (!is_topic_discovery_protected( pp->sec_attr->permissions_handle, sc->access_control_context, topic_name)) + EXCEPTION_ERROR(sc, &exception, "Reader is not permitted"); + else + DDS_Security_Exception_reset(&exception); + } + + q_omg_shallow_free_security_qos(&security_qos); + g_omg_shallow_free_StringSeq(&partitions.name); + + return result; } -static bool q_omg_proxyparticipant_is_authenticated (const struct proxy_participant *proxy_pp) +void q_omg_security_register_reader(struct reader *rd) { - /* TODO: Handshake */ - DDSRT_UNUSED_ARG (proxy_pp); + struct participant *pp = rd->c.pp; + struct dds_security_context *sc = q_omg_security_get_secure_context(pp); + DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + DDS_Security_PartitionQosPolicy partitions; + DDS_Security_PropertySeq properties; + const char *topic_name; + + if (!sc) + return; + + if (rd->xqos->present & QP_PARTITION) + g_omg_shallow_copy_StringSeq(&partitions.name, &(rd->xqos->partition)); + else + memset(&(partitions), 0, sizeof(DDS_Security_PartitionQosPolicy)); + + rd->sec_attr = reader_sec_attributes_new(); + + topic_name = get_reader_topic_name(rd); + if (!sc->access_control_context->get_datareader_sec_attributes(sc->access_control_context, pp->sec_attr->permissions_handle, topic_name, &partitions, NULL, &rd->sec_attr->attr, &exception)) + { + EXCEPTION_ERROR(sc, &exception, "Failed to retrieve reader security attributes"); + goto no_attr; + } + rd->sec_attr->plugin_attr = true; + + if (rd->sec_attr->attr.is_payload_protected || rd->sec_attr->attr.is_submessage_protected) + { + if (rd->xqos->present & QP_PROPERTY_LIST) + q_omg_copy_PropertySeq(&properties, &rd->xqos->property.value); + else + memset(&properties, 0, sizeof(DDS_Security_PropertySeq)); + + rd->sec_attr->crypto_handle = sc->crypto_context->crypto_key_factory->register_local_datareader( + sc->crypto_context->crypto_key_factory, pp->sec_attr->crypto_handle, &properties, &rd->sec_attr->attr, &exception); + DDS_Security_PropertySeq_freebuf(&properties); + if (rd->sec_attr->crypto_handle == DDS_SECURITY_HANDLE_NIL) + { + EXCEPTION_ERROR(sc, &exception, "Failed to register reader with crypto"); + goto not_registered; + } + } + +not_registered: +no_attr: + g_omg_shallow_free_StringSeq(&partitions.name); +} + +void q_omg_security_deregister_reader(struct reader *rd) +{ + struct dds_security_context *sc = q_omg_security_get_secure_context(rd->c.pp); + DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + + if (rd->sec_attr) + { + assert(sc); + 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)) + { + EXCEPTION_ERROR(sc, &exception, "Failed to unregister reader with crypto"); + } + } + if (rd->sec_attr->plugin_attr) + { + if (!sc->access_control_context->return_datareader_sec_attributes(sc->access_control_context, &rd->sec_attr->attr, &exception)) + { + EXCEPTION_ERROR(sc, &exception, "Failed to return reader security attributes"); + } + } + reader_sec_attributes_free(rd->sec_attr); + rd->sec_attr = NULL; + } +} + +bool q_omg_get_reader_security_info(const struct reader *rd, nn_security_info_t *info) +{ + assert(rd); + assert(info); + + if (rd->sec_attr) { + q_omg_get_endpoint_security_info(&rd->sec_attr->attr, info); + return true; + } + info->plugin_security_attributes = 0; + info->security_attributes = 0; return false; } -int64_t q_omg_security_get_local_participant_handle (struct participant *pp) -{ - /* TODO: Local registration */ - DDSRT_UNUSED_ARG (pp); - return 0; -} - -int64_t q_omg_security_get_remote_participant_handle (struct proxy_participant *proxypp) -{ - /* TODO: Handshake */ - DDSRT_UNUSED_ARG(proxypp); - return 0; -} - -bool q_omg_participant_allow_unauthenticated (struct participant *pp) -{ - DDSRT_UNUSED_ARG (pp); - return true; -} - -unsigned determine_subscription_writer (const struct reader *rd) +unsigned determine_subscription_writer(const struct reader *rd) { if (q_omg_reader_is_discovery_protected (rd)) return NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER; @@ -386,17 +1487,292 @@ unsigned determine_publication_writer (const struct writer *wr) return NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER; } -void q_omg_security_register_remote_participant (struct participant *pp, struct proxy_participant *proxypp, int64_t shared_secret, int64_t proxy_permissions) +static int64_t check_remote_participant_permissions(uint32_t domain_id, struct participant *pp, struct proxy_participant *proxypp, int64_t remote_identity_handle) { - DDSRT_UNUSED_ARG (pp); - DDSRT_UNUSED_ARG (proxypp); - DDSRT_UNUSED_ARG (shared_secret); - DDSRT_UNUSED_ARG (proxy_permissions); + struct dds_security_context *sc = q_omg_security_get_secure_context(pp); + DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + struct ddsi_handshake *handshake; + DDS_Security_PermissionsToken permissions_token = DDS_SECURITY_TOKEN_INIT; + DDS_Security_AuthenticatedPeerCredentialToken peer_credential_token = DDS_SECURITY_TOKEN_INIT; + int64_t permissions_hdl = DDS_SECURITY_HANDLE_NIL; + + if (proxypp->plist->present & PP_PERMISSIONS_TOKEN) + q_omg_shallow_copyin_DataHolder(&permissions_token, &proxypp->plist->permissions_token); + else + memset(&permissions_token, 0, sizeof(DDS_Security_PermissionsToken)); + + handshake = ddsi_handshake_find(pp, proxypp); + if (!handshake) + { + ELOG(DDS_LC_ERROR, pp, "Could not find handshake local participant "PGUIDFMT" and remote participant "PGUIDFMT, + PGUID(pp->e.guid), PGUID(proxypp->e.guid)); + goto no_handshake; + } + + if (!sc->authentication_context->get_authenticated_peer_credential_token(sc->authentication_context, &peer_credential_token, ddsi_handshake_get_handle(handshake), &exception)) + { + if (q_omg_participant_is_access_protected(pp)) + { + EXCEPTION_ERROR(sc, &exception, "Could not authenticate_peer_credential_token for local participan1152t "PGUIDFMT" and remote participant "PGUIDFMT, + PGUID(pp->e.guid), PGUID(proxypp->e.guid)); + goto no_credentials; + } + /* Failing is allowed due to the non-protection of access. */ + EXCEPTION_WARNING(sc, &exception, "Could not authenticate_peer_credential_token for local participant "PGUIDFMT" and remote participant "PGUIDFMT , + PGUID(pp->e.guid), PGUID(proxypp->e.guid)); + } + + permissions_hdl = sc->access_control_context->validate_remote_permissions( + sc->access_control_context, sc->authentication_context, pp->sec_attr->local_identity_handle, remote_identity_handle, &permissions_token, &peer_credential_token, &exception); + if (permissions_hdl == DDS_SECURITY_HANDLE_NIL) + { + if (q_omg_participant_is_access_protected(pp)) + { + EXCEPTION_ERROR(sc, &exception, "Could not get remote participant "PGUIDFMT" permissions from plugin", PGUID(proxypp->e.guid)); + goto no_permissions; + } + /* Failing is allowed due to the non-protection of access. */ + EXCEPTION_WARNING(sc, &exception, "Could not get remote participant "PGUIDFMT" permissions from plugin", PGUID(proxypp->e.guid)); + } + + /* Only check remote participant if joining access is protected. */ + if (q_omg_participant_is_access_protected(pp)) + { + DDS_Security_ParticipantBuiltinTopicDataSecure participant_data; + + q_omg_shallow_copy_ParticipantBuiltinTopicDataSecure(&participant_data, &(proxypp->e.guid), proxypp->plist); + if (!sc->access_control_context->check_remote_participant(sc->access_control_context, permissions_hdl, (DDS_Security_DomainId)domain_id, &participant_data, &exception)) + { + EXCEPTION_WARNING(sc, &exception, "Plugin does not allow remote participant "PGUIDFMT, PGUID(proxypp->e.guid)); + if (!sc->access_control_context->return_permissions_handle(sc->access_control_context, permissions_hdl, &exception)) + { + EXCEPTION_ERROR(sc, &exception, "Failed to return remote permissions handle"); + } + permissions_hdl = DDS_SECURITY_HANDLE_NIL; + } + q_omg_shallow_free_ParticipantBuiltinTopicDataSecure(&participant_data); + } + +no_permissions: + if (!sc->authentication_context->return_authenticated_peer_credential_token(sc->authentication_context, &peer_credential_token, &exception)) + { + EXCEPTION_ERROR(sc, &exception, "Failed to return peer credential token"); + } +no_credentials: + ddsi_handshake_release(handshake); +no_handshake: + q_omg_shallow_free_DataHolder(&permissions_token); + return permissions_hdl; } -void q_omg_security_deregister_remote_participant (struct proxy_participant *proxypp) +static void send_participant_crypto_tokens(struct participant *pp, struct proxy_participant *proxypp, DDS_Security_ParticipantCryptoHandle local_crypto, DDS_Security_ParticipantCryptoHandle remote_crypto) { - DDSRT_UNUSED_ARG (proxypp); + struct dds_security_context *sc = q_omg_security_get_secure_context(pp); + DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + DDS_Security_ParticipantCryptoTokenSeq tokens = DDS_SECURITY_SEQUENCE_INIT; + bool r; + + r = sc->crypto_context->crypto_key_exchange->create_local_participant_crypto_tokens(sc->crypto_context->crypto_key_exchange, &tokens, local_crypto, remote_crypto, &exception); + if (!r) + EXCEPTION_ERROR(sc, &exception, "Failed to create local participant crypto tokens "PGUIDFMT" for remote participant "PGUIDFMT, PGUID(pp->e.guid), PGUID(proxypp->e.guid)); + else if (tokens._length > 0) + { + nn_dataholderseq_t tholder; + + q_omg_shallow_copyout_DataHolderSeq(&tholder, &tokens); + write_crypto_participant_tokens(pp, proxypp, &tholder); + q_omg_shallow_free_nn_dataholderseq(&tholder); + + if (!sc->crypto_context->crypto_key_exchange->return_crypto_tokens(sc->crypto_context->crypto_key_exchange, &tokens, &exception)) + EXCEPTION_ERROR(sc, &exception, "Failed to return local participant crypto tokens "PGUIDFMT" for remote participant "PGUIDFMT, PGUID(pp->e.guid), PGUID(proxypp->e.guid)); + } +} + +static int64_t get_permissions_handle(struct participant *pp, struct proxy_participant *proxypp) +{ + int64_t hdl = 0; + struct proxypp_pp_match *pm; + + ddsrt_mutex_lock(&proxypp->sec_attr->lock); + pm = ddsrt_avl_lookup(&proxypp_pp_treedef, &proxypp->sec_attr->participants, &pp->sec_attr->crypto_handle); + if (pm) + hdl = pm->permissions_handle; + ddsrt_mutex_unlock(&proxypp->sec_attr->lock); + + return hdl; +} + +void q_omg_security_init_remote_participant(struct proxy_participant *proxypp) +{ + proxypp->sec_attr = ddsrt_malloc(sizeof(*proxypp->sec_attr)); + ddsrt_mutex_init(&proxypp->sec_attr->lock); + ddsrt_avl_init (&proxypp_pp_treedef, &proxypp->sec_attr->participants); + proxypp->sec_attr->sc = proxypp->e.gv->security_context; + proxypp->sec_attr->remote_identity_handle = 0; + proxypp->sec_attr->crypto_handle = 0; + proxypp->sec_attr->initialized = false; +} + +void q_omg_security_remote_participant_set_initialized(struct proxy_participant *proxypp) +{ + if (proxypp->sec_attr) + { + ddsrt_mutex_lock(&proxypp->sec_attr->lock); + proxypp->sec_attr->initialized = true; + ddsrt_mutex_unlock(&proxypp->sec_attr->lock); + } +} + +bool q_omg_security_remote_participant_is_initialized(struct proxy_participant *proxypp) +{ + bool initialized = false; + + if (proxypp->sec_attr) + { + ddsrt_mutex_lock(&proxypp->sec_attr->lock); + initialized = proxypp->sec_attr->initialized; + ddsrt_mutex_unlock(&proxypp->sec_attr->lock); + } + return initialized; +} + +static bool proxypp_is_authenticated(const struct proxy_participant *proxypp) +{ + bool authenticated = false; + + if (proxypp->sec_attr) + { + ddsrt_mutex_lock(&proxypp->sec_attr->lock); + authenticated = !ddsrt_avl_is_empty(&proxypp->sec_attr->participants); + ddsrt_mutex_unlock(&proxypp->sec_attr->lock); + } + return authenticated; +} + +static void match_proxypp_pp(struct participant *pp, struct proxy_participant *proxypp, DDS_Security_PermissionsHandle permissions_handle, DDS_Security_SharedSecretHandle shared_secret_handle) +{ + struct proxypp_pp_match *pm; + struct pp_proxypp_match *pc; + + pm = proxypp_pp_match_new(pp, permissions_handle, shared_secret_handle); + ddsrt_mutex_lock(&proxypp->sec_attr->lock); + ddsrt_avl_insert(&proxypp_pp_treedef, &proxypp->sec_attr->participants, pm); + ddsrt_mutex_unlock(&proxypp->sec_attr->lock); + + pc = pp_proxypp_match_new(proxypp, proxypp->sec_attr->crypto_handle); + + ddsrt_mutex_lock(&pp->sec_attr->lock); + ddsrt_avl_cinsert(&pp_proxypp_treedef, &pp->sec_attr->proxy_participants, pc); + ddsrt_mutex_unlock(&pp->sec_attr->lock); +} + +bool q_omg_security_register_remote_participant(struct participant *pp, struct proxy_participant *proxypp, int64_t shared_secret) +{ + bool ret = true; + 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; + DDS_Security_ParticipantCryptoHandle crypto_handle; + int64_t permissions_handle; + bool notify_handshake = false; + + permissions_handle = check_remote_participant_permissions(gv->config.domainId, pp, proxypp, proxypp->sec_attr->remote_identity_handle); + if (permissions_handle == 0) + return false; + + GVTRACE("register remote participant "PGUIDFMT" with "PGUIDFMT"\n", PGUID(proxypp->e.guid), PGUID(pp->e.guid)); + + crypto_handle = sc->crypto_context->crypto_key_factory->register_matched_remote_participant( + sc->crypto_context->crypto_key_factory, pp->sec_attr->crypto_handle, proxypp->sec_attr->remote_identity_handle, permissions_handle, shared_secret, &exception); + if (crypto_handle == DDS_SECURITY_HANDLE_NIL) + { + EXCEPTION_ERROR(sc, &exception, "Failed to register matched remote participant "PGUIDFMT" with participant "PGUIDFMT, PGUID(proxypp->e.guid), PGUID(pp->e.guid)); + ret = false; + goto register_failed; + } + + ddsrt_mutex_lock(&pp->e.lock); + + proxypp->sec_attr->crypto_handle = crypto_handle; + + GVTRACE("match pp->crypto=%"PRId64" proxypp->crypto=%"PRId64"\n", pp->sec_attr->crypto_handle, crypto_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); + + 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) + { + 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)); + } + else + { + EXCEPTION_ERROR(sc, &exception, "Failed to set remote participant crypto tokens "PGUIDFMT" --> "PGUIDFMT, PGUID(proxypp->e.guid), PGUID(pp->e.guid)); + ret = false; + } + } + else + notify_handshake = true; + } + ddsrt_mutex_unlock(&pp->e.lock); + + if (notify_handshake) + notify_handshake_recv_token(pp, proxypp); + +register_failed: + return ret; +} + +void q_omg_security_deregister_remote_participant(struct proxy_participant *proxypp) +{ + struct ddsi_domaingv *gv = proxypp->e.gv; + DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + + if (proxypp->sec_attr) { + dds_security_context *sc = proxypp->sec_attr->sc; + struct proxypp_pp_match *pm; + struct participant *pp; + + pm = ddsrt_avl_find_min(&proxypp_pp_treedef, &proxypp->sec_attr->participants); + while (pm) + { + struct proxypp_pp_match *next = ddsrt_avl_find_succ(&proxypp_pp_treedef, &proxypp->sec_attr->participants, pm); + + ddsrt_avl_delete(&proxypp_pp_treedef, &proxypp->sec_attr->participants, pm); + pp = entidx_lookup_participant_guid(gv->entity_index, &pm->pp_guid); + if (pp) + pp_proxypp_unrelate(sc, pp, &proxypp->e.guid); + proxypp_pp_match_free(sc, pm); + pm = next; + } + + 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)) + EXCEPTION_ERROR(sc, &exception, "2:Failed to return remote crypto handle"); + } + + if (proxypp->sec_attr->remote_identity_handle != DDS_SECURITY_HANDLE_NIL) + { + if (!sc->authentication_context->return_identity_handle(sc->authentication_context, proxypp->sec_attr->remote_identity_handle, &exception)) + EXCEPTION_ERROR(sc, &exception, "Failed to return remote identity handle"); + } + + ddsrt_mutex_destroy(&proxypp->sec_attr->lock); + ddsrt_free(proxypp->sec_attr); + proxypp->sec_attr = NULL; + } } bool is_proxy_participant_deletion_allowed (struct ddsi_domaingv * const gv, const struct ddsi_guid *guid, const ddsi_entityid_t pwr_entityid) @@ -421,98 +1797,103 @@ bool is_proxy_participant_deletion_allowed (struct ddsi_domaingv * const gv, con GVLOGDISC (" unknown"); return false; } - return (!q_omg_proxyparticipant_is_authenticated (proxypp)); + + return (!proxypp_is_authenticated(proxypp)); } -/* ask to access control security plugin for the remote participant permissions */ -int64_t q_omg_security_check_remote_participant_permissions (uint32_t domain_id, struct participant *pp, struct proxy_participant *proxypp) +bool q_omg_is_similar_participant_security_info(struct participant *pp, struct proxy_participant *proxypp) { - DDSRT_UNUSED_ARG (domain_id); - DDSRT_UNUSED_ARG (pp); - DDSRT_UNUSED_ARG (proxypp); + bool matching; + nn_security_info_t pp_security_info; + + if (!q_omg_get_participant_security_info(pp, &pp_security_info)) + return false; + + matching = SECURITY_INFO_COMPATIBLE(pp_security_info, proxypp->security_info, NN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_VALID); + if (!matching) { + DDS_CLOG (DDS_LC_WARNING, &pp->e.gv->logconfig, "match remote_participant "PGUIDFMT" with participant "PGUIDFMT" security_attributes mismatch: 0x%08x.0x%08x - 0x%08x.0x%08x\n", + PGUID(proxypp->e.guid), PGUID(pp->e.guid), + proxypp->security_info.security_attributes, proxypp->security_info.plugin_security_attributes, + pp_security_info.security_attributes, pp_security_info.plugin_security_attributes); + } else { + /* We previously checked for attribute compatibility. That doesn't + * mean equal, because compatibility depends on the valid flag. + * Some products don't properly send the attributes, in which case + * the valid flag is 0. To be able to support these product, assume + * that the attributes are the same. If there is actually a mismatch, + * communication will fail at a later moment anyway. */ + if (!SECURITY_ATTR_IS_VALID(proxypp->security_info.security_attributes)) { + proxypp->security_info.security_attributes = pp_security_info.security_attributes; + } + if (!SECURITY_ATTR_IS_VALID(proxypp->security_info.plugin_security_attributes)) { + proxypp->security_info.plugin_security_attributes = pp_security_info.plugin_security_attributes; + } + } + assert(matching); + return matching; +} + +void q_omg_security_set_participant_crypto_tokens(struct participant *pp, struct proxy_participant *proxypp, const nn_dataholderseq_t *tokens) +{ + 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; + DDS_Security_DatawriterCryptoTokenSeq *tseq; + struct security_entity_match *m; + + if (!sc) + return; + + 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; + } + 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)); + 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)); + } + ddsrt_mutex_unlock(&pp->e.lock); + + notify_handshake_recv_token(pp, proxypp); +} + +void q_omg_security_participant_send_tokens(struct participant *pp, struct proxy_participant *proxypp) +{ + if (proxypp->sec_attr->crypto_handle != 0) + send_participant_crypto_tokens(pp, proxypp, pp->sec_attr->crypto_handle, proxypp->sec_attr->crypto_handle); +} + +int64_t q_omg_security_get_remote_participant_handle(struct proxy_participant *proxypp) +{ + if (proxypp->sec_attr) + return proxypp->sec_attr->crypto_handle; + return 0; } -bool q_omg_is_similar_participant_security_info (struct participant *pp, struct proxy_participant *proxypp) +void set_proxy_participant_security_info(struct proxy_participant *proxypp, const ddsi_plist_t *plist) { - DDSRT_UNUSED_ARG (pp); - DDSRT_UNUSED_ARG (proxypp); - return true; -} - -bool q_omg_security_check_create_participant (struct participant *pp, uint32_t domain_id) -{ - DDSRT_UNUSED_ARG (pp); - DDSRT_UNUSED_ARG (domain_id); - return true; -} - -void q_omg_security_participant_send_tokens (struct participant *pp, struct proxy_participant *proxypp) -{ - DDSRT_UNUSED_ARG (pp); - DDSRT_UNUSED_ARG (proxypp); -} - -bool q_omg_security_match_remote_writer_enabled (struct reader *rd, struct proxy_writer *pwr) -{ - DDSRT_UNUSED_ARG (rd); - DDSRT_UNUSED_ARG (pwr); - assert (rd); - assert (pwr); - return true; -} - -bool q_omg_security_match_remote_reader_enabled (struct writer *wr, struct proxy_reader *prd) -{ - DDSRT_UNUSED_ARG (wr); - DDSRT_UNUSED_ARG (prd); - assert (wr); - assert (prd); - return true; -} - -bool q_omg_security_check_remote_writer_permissions (const struct proxy_writer *pwr, uint32_t domain_id, struct participant *pp) -{ - DDSRT_UNUSED_ARG (pwr); - DDSRT_UNUSED_ARG (domain_id); - DDSRT_UNUSED_ARG (pp); - assert (pwr); - assert (pp); - assert (pwr->c.proxypp); - return true; -} - -bool q_omg_security_check_remote_reader_permissions (const struct proxy_reader *prd, uint32_t domain_id, struct participant *pp) -{ - DDSRT_UNUSED_ARG (prd); - DDSRT_UNUSED_ARG (domain_id); - DDSRT_UNUSED_ARG (pp); - assert (prd); - assert (pp); - assert (prd->c.proxypp); - return true; -} - -bool q_omg_security_is_remote_rtps_protected (const struct proxy_participant *proxy_pp, ddsi_entityid_t entityid) -{ - /* TODO: Handshake */ - DDSRT_UNUSED_ARG (proxy_pp); - DDSRT_UNUSED_ARG (entityid); - return false; -} - -bool q_omg_security_is_local_rtps_protected (const struct participant *pp, ddsi_entityid_t entityid) -{ - /* TODO: Handshake */ - DDSRT_UNUSED_ARG (pp); - DDSRT_UNUSED_ARG (entityid); - return false; -} - -void set_proxy_participant_security_info (struct proxy_participant *proxypp, const ddsi_plist_t *plist) -{ - assert (proxypp); - assert (plist); + assert(proxypp); + assert(plist); if (plist->present & PP_PARTICIPANT_SECURITY_INFO) { proxypp->security_info.security_attributes = plist->participant_security_info.security_attributes; proxypp->security_info.plugin_security_attributes = plist->participant_security_info.plugin_security_attributes; @@ -522,7 +1903,300 @@ void set_proxy_participant_security_info (struct proxy_participant *proxypp, con } } -static void q_omg_get_proxy_endpoint_security_info (const struct entity_common *entity, nn_security_info_t *proxypp_sec_info, const ddsi_plist_t *plist, nn_security_info_t *info) +bool q_omg_writer_is_discovery_protected(const struct writer *wr) +{ + assert (wr != NULL); + return wr->sec_attr != NULL && wr->sec_attr->attr.is_discovery_protected; +} + +bool q_omg_writer_is_submessage_protected(const struct writer *wr) +{ + assert (wr != NULL); + return wr->sec_attr != NULL && wr->sec_attr->attr.is_submessage_protected; +} + +bool q_omg_writer_is_payload_protected(const struct writer *wr) +{ + assert (wr != NULL); + return wr->sec_attr != NULL && wr->sec_attr->attr.is_payload_protected; +} + +bool q_omg_security_check_remote_writer_permissions(const struct proxy_writer *pwr, uint32_t domain_id, struct participant *pp) +{ + 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; + DDS_Security_PublicationBuiltinTopicDataSecure publication_data; + bool ok = true; + + if (!sc) + return true; + + if (!q_omg_proxy_participant_is_secure(pwr->c.proxypp)) + { + if (q_omg_participant_allow_unauthenticated(pp)) + { + GVTRACE (" allow non-secure remote writer "PGUIDFMT, PGUID (pwr->e.guid)); + return true; + } + else + { + GVWARNING("Non secure remote writer "PGUIDFMT" is not allowed.", PGUID(pwr->e.guid)); + return false; + } + } + + if (SECURITY_INFO_IS_WRITE_PROTECTED(pwr->security_info)) + { + DDS_Security_PermissionsHandle permissions_handle; + + if ((permissions_handle = get_permissions_handle(pp, pwr->c.proxypp)) != 0) + { + GVTRACE("Secure remote writer "PGUIDFMT" proxypp does not have permissions handle yet\n", PGUID(pwr->e.guid)); + return false; + } + else + { + q_omg_shallow_copy_PublicationBuiltinTopicDataSecure(&publication_data, &pwr->e.guid, pwr->c.xqos, &pwr->security_info); + ok = sc->access_control_context->check_remote_datawriter(sc->access_control_context, permissions_handle, (int)domain_id, &publication_data, &exception); + q_omg_shallow_free_PublicationBuiltinTopicDataSecure(&publication_data); + if (!ok) + { + if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, publication_data.topic_name)) + EXCEPTION_ERROR(sc, &exception, "Access control does not allow remote writer "PGUIDFMT": %s", PGUID(pwr->e.guid)); + else + DDS_Security_Exception_reset(&exception); + } + } + } + + return ok; +} + +static void send_reader_crypto_tokens(struct reader *rd, struct proxy_writer *pwr, DDS_Security_DatareaderCryptoHandle local_crypto, DDS_Security_DatawriterCryptoHandle remote_crypto) +{ + 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; + DDS_Security_DatawriterCryptoTokenSeq tokens = {0, 0, NULL}; + bool r; + + GVTRACE("send reader tokens "PGUIDFMT" to writer "PGUIDFMT"\n", PGUID(rd->e.guid), PGUID(pwr->e.guid)); + + r = sc->crypto_context->crypto_key_exchange->create_local_datareader_crypto_tokens(sc->crypto_context->crypto_key_exchange, &tokens, local_crypto, remote_crypto, &exception); + if (!r) + EXCEPTION_ERROR(sc, &exception,"Failed to create local reader crypto tokens "PGUIDFMT" for remote writer "PGUIDFMT, PGUID(rd->e.guid), PGUID(pwr->e.guid)); + else if (tokens._length > 0) + { + nn_dataholderseq_t tholder; + + q_omg_shallow_copyout_DataHolderSeq(&tholder, &tokens); + write_crypto_reader_tokens(rd, pwr, &tholder); + q_omg_shallow_free_nn_dataholderseq(&tholder); + + if (!sc->crypto_context->crypto_key_exchange->return_crypto_tokens(sc->crypto_context->crypto_key_exchange, &tokens, &exception)) + EXCEPTION_ERROR(sc, &exception, "Failed to return local reader crypto tokens "PGUIDFMT" for remote writer "PGUIDFMT, PGUID(rd->e.guid), PGUID(pwr->e.guid)); + } +} + +static bool q_omg_security_register_remote_writer_match(struct proxy_writer *pwr, struct reader *rd, int64_t *crypto_handle) +{ + struct participant *pp = rd->c.pp; + struct proxy_participant *proxypp = pwr->c.proxypp; + 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; + bool send_tokens = false; + + 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); + + if (!pm) + 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 + { + /* 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); + + *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) + { + /* 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); + } + else + { + send_tokens = true; + if (match->tokens) + { + 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)) + { + 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)); + } + 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); + + return match->matched; +} + +bool q_omg_security_match_remote_writer_enabled(struct reader *rd, struct proxy_writer *pwr, int64_t *crypto_handle) +{ + struct ddsi_domaingv *gv = rd->e.gv; + nn_security_info_t info; + + if (!rd->sec_attr) + return true; + + /* + * Check if the security settings match by checking the attributes. + * + * The attributes will be 0 when security is not enabled for the related + * federation or the security configuration told that this endpoint should + * not be protected. + * + * This can mean that an unprotected endpoint of a secure federation can + * connect to an endpoint of a non-secure federation. However, that will + * be blocked by q_omg_security_check_remote_writer_permissions() if + * q_omg_participant_allow_unauthenticated() returns FALSE there. + */ + (void)q_omg_get_reader_security_info(rd, &info); + if (!SECURITY_INFO_COMPATIBLE(pwr->security_info, info, NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID)) + { + GVWARNING("match_remote_writer "PGUIDFMT" with reader "PGUIDFMT" security_attributes mismatch: 0x%08x.0x%08x - 0x%08x.0x%08x\n", + PGUID(pwr->e.guid), PGUID(rd->e.guid), + pwr->security_info.security_attributes, pwr->security_info.plugin_security_attributes, + info.security_attributes, info.plugin_security_attributes); + return false; + } + + if ((!rd->sec_attr->attr.is_payload_protected ) && (!rd->sec_attr->attr.is_submessage_protected)) + return true; + + if (!q_omg_proxy_participant_is_secure(pwr->c.proxypp)) + { + /* Remote proxy was downgraded to a non-secure participant, + * but the local endpoint is protected. */ + return false; + } + + /* We previously checked for attribute compatibility. That doesn't + * mean equal, because compatibility depends on the valid flag. + * Some products don't properly send the attributes, in which case + * the valid flag is 0. To be able to support these product, assume + * that the attributes are the same. If there is actually a mismatch, + * communication will fail at a later moment anyway. */ + if (!SECURITY_ATTR_IS_VALID(pwr->security_info.security_attributes)) { + pwr->security_info.security_attributes = info.security_attributes; + } + if (!SECURITY_ATTR_IS_VALID(pwr->security_info.plugin_security_attributes)) { + pwr->security_info.plugin_security_attributes = info.plugin_security_attributes; + } + + return q_omg_security_register_remote_writer_match(pwr, rd, crypto_handle); +} + +void q_omg_security_deregister_remote_writer_match(const struct ddsi_domaingv *gv, const ddsi_guid_t *rd_guid, struct rd_pwr_match *m) +{ + 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); + } + } +} + +bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *prd, uint32_t domain_id, struct participant *pp) +{ + 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; + bool ok = true; + + if (!sc) + return true; + + if (!q_omg_proxy_participant_is_secure(prd->c.proxypp)) + { + if (q_omg_participant_allow_unauthenticated(pp)) + { + GVTRACE (" allow non-secure remote reader "PGUIDFMT, PGUID (prd->e.guid)); + return true; + } + else + { + GVWARNING("Non secure remote reader "PGUIDFMT" is not allowed.", PGUID(prd->e.guid)); + return false; + } + } + + if (SECURITY_INFO_IS_READ_PROTECTED(prd->security_info)) + { + DDS_Security_PermissionsHandle permissions_handle; + + if ((permissions_handle = get_permissions_handle(pp, prd->c.proxypp)) != 0) + { + GVTRACE("Secure remote reader "PGUIDFMT" proxypp does not have permissions handle yet\n", PGUID(prd->e.guid)); + return false; + } + else + { + DDS_Security_SubscriptionBuiltinTopicDataSecure subscription_data; + + q_omg_shallow_copy_SubscriptionBuiltinTopicDataSecure(&subscription_data, &prd->e.guid, prd->c.xqos, &prd->security_info); + ok = sc->access_control_context->check_remote_datareader(sc->access_control_context, permissions_handle, (int)domain_id, &subscription_data, false, &exception); + q_omg_shallow_free_SubscriptionBuiltinTopicDataSecure(&subscription_data); + if (!ok) + { + if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, subscription_data.topic_name)) + EXCEPTION_ERROR(sc, &exception, "Access control does not allow remote reader "PGUIDFMT": %s", PGUID(prd->e.guid)); + else + DDS_Security_Exception_reset(&exception); + } + } + } + + return ok; +} + +static void q_omg_get_proxy_endpoint_security_info(const struct entity_common *entity, nn_security_info_t *proxypp_sec_info, const ddsi_plist_t *plist, nn_security_info_t *info) { const bool proxypp_info_available = (proxypp_sec_info->security_attributes != 0 || proxypp_sec_info->plugin_security_attributes != 0); @@ -600,120 +2274,821 @@ static void q_omg_get_proxy_endpoint_security_info (const struct entity_common * } } -void set_proxy_reader_security_info (struct proxy_reader *prd, const ddsi_plist_t *plist) +void q_omg_get_proxy_reader_security_info(struct proxy_reader *prd, const ddsi_plist_t *plist, nn_security_info_t *info) +{ + q_omg_get_proxy_endpoint_security_info(&(prd->e), &(prd->c.proxypp->security_info), plist, info); +} + +void set_proxy_reader_security_info(struct proxy_reader *prd, const ddsi_plist_t *plist) { assert (prd); q_omg_get_proxy_endpoint_security_info (&prd->e, &prd->c.proxypp->security_info, plist, &prd->c.security_info); } -void set_proxy_writer_security_info (struct proxy_writer *pwr, const ddsi_plist_t *plist) + +void q_omg_get_proxy_writer_security_info(struct proxy_writer *pwr, const ddsi_plist_t *plist, nn_security_info_t *info) +{ + q_omg_get_proxy_endpoint_security_info(&(pwr->e), &(pwr->c.proxypp->security_info), plist, info); +} + +void set_proxy_writer_security_info(struct proxy_writer *pwr, const ddsi_plist_t *plist) { assert (pwr); q_omg_get_proxy_endpoint_security_info (&pwr->e, &pwr->c.proxypp->security_info, plist, &pwr->c.security_info); } - -static bool q_omg_security_encode_datareader_submessage (struct reader *rd, const ddsi_guid_prefix_t *dst_prefix, const unsigned char *src_buf, size_t src_len, unsigned char **dst_buf, size_t *dst_len) +void q_omg_security_deregister_remote_reader_match(const struct ddsi_domaingv *gv, const ddsi_guid_t *wr_guid, struct wr_prd_match *m) { - /* TODO: Use proper keys to actually encode (need key-exchange). */ - DDSRT_UNUSED_ARG (rd); - DDSRT_UNUSED_ARG (dst_prefix); - DDSRT_UNUSED_ARG (src_buf); - DDSRT_UNUSED_ARG (src_len); - DDSRT_UNUSED_ARG (dst_buf); - DDSRT_UNUSED_ARG (dst_len); - return false; + 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) + { + 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); + } + } +} + +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); + struct ddsi_domaingv *gv = wr->e.gv; + DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + DDS_Security_DatawriterCryptoTokenSeq tokens = {0, 0, NULL}; + bool r; + + GVTRACE("send writer tokens "PGUIDFMT" to reader "PGUIDFMT"\n", PGUID(wr->e.guid), PGUID(prd->e.guid)); + + r = sc->crypto_context->crypto_key_exchange->create_local_datawriter_crypto_tokens(sc->crypto_context->crypto_key_exchange, &tokens, local_crypto, remote_crypto, &exception); + if (!r) + EXCEPTION_ERROR(sc, &exception,"Failed to create local writer crypto tokens "PGUIDFMT" for remote reader "PGUIDFMT, PGUID(wr->e.guid), PGUID(prd->e.guid)); + else if (tokens._length > 0) + { + nn_dataholderseq_t tholder; + + q_omg_shallow_copyout_DataHolderSeq(&tholder, &tokens); + write_crypto_writer_tokens(wr, prd, &tholder); + q_omg_shallow_free_nn_dataholderseq(&tholder); + + if (!sc->crypto_context->crypto_key_exchange->return_crypto_tokens(sc->crypto_context->crypto_key_exchange, &tokens, &exception)) + EXCEPTION_ERROR(sc, &exception, "Failed to return local writer crypto tokens "PGUIDFMT" for remote reader "PGUIDFMT, PGUID(wr->e.guid), PGUID(prd->e.guid)); + } +} + +static bool q_omg_security_register_remote_reader_match(struct proxy_reader *prd, struct writer *wr, int64_t *crypto_handle) +{ + struct participant *pp = wr->c.pp; + struct proxy_participant *proxypp = prd->c.proxypp; + 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; + bool send_tokens = false; + + *crypto_handle = 0; + + 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); + if (!pm) + 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 + { + /* 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, false, &exception); + + *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) + { + /* 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); + } + else + { + send_tokens = true; + if (match->tokens) + { + 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)) + { + 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)); + } + 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); + + return match->matched; +} + +bool q_omg_security_match_remote_reader_enabled(struct writer *wr, struct proxy_reader *prd, int64_t *crypto_handle) +{ + struct ddsi_domaingv *gv = wr->e.gv; + nn_security_info_t info; + + if (!wr->sec_attr) + return true; + + /* + * Check if the security settings match by checking the attributes. + * + * The attributes will be 0 when security is not enabled for the related + * federation or the security configuration told that this endpoint should + * not be protected. + * + * This can mean that an unprotected endpoint of a secure federation can + * connect to an endpoint of a non-secure federation. However, that will + * be blocked by q_omg_security_check_remote_reader_permissions() if + * q_omg_participant_allow_unauthenticated() returns FALSE there. + */ + (void)q_omg_get_writer_security_info(wr, &info); + if (!SECURITY_INFO_COMPATIBLE(prd->security_info, info, NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID)) + { + GVWARNING("match_remote_reader "PGUIDFMT" with writer "PGUIDFMT" security_attributes mismatch: 0x%08x.0x%08x - 0x%08x.0x%08x\n", + PGUID(prd->e.guid), PGUID(wr->e.guid), + prd->security_info.security_attributes, prd->security_info.plugin_security_attributes, + info.security_attributes, info.plugin_security_attributes); + return false; + } + + if (!wr->sec_attr->attr.is_submessage_protected && !wr->sec_attr->attr.is_payload_protected) + return true; + + if (!q_omg_proxy_participant_is_secure(prd->c.proxypp)) + { + /* Remote proxy was downgraded to a non-secure participant, + * but the local endpoint is protected. */ + return false; + } + + /* We previously checked for attribute compatibility. That doesn't + * mean equal, because compatibility depends on the valid flag. + * Some products don't properly send the attributes, in which case + * the valid flag is 0. To be able to support these product, assume + * that the attributes are the same. If there is actually a mismatch, + * communication will fail at a later moment anyway. */ + if (!SECURITY_ATTR_IS_VALID(prd->security_info.security_attributes)) { + prd->security_info.security_attributes = info.security_attributes; + } + if (!SECURITY_ATTR_IS_VALID(prd->security_info.plugin_security_attributes)) { + prd->security_info.plugin_security_attributes = info.plugin_security_attributes; + } + + return q_omg_security_register_remote_reader_match(prd, wr, crypto_handle); +} + +void q_omg_security_set_remote_writer_crypto_tokens(struct reader *rd, const ddsi_guid_t *pwr_guid, const nn_dataholderseq_t *tokens) +{ + 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 proxy_writer *pwr = NULL; + + 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 ) + { + 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)) + { + GVTRACE("set_remote_writer_crypto_tokens "PGUIDFMT" with reader "PGUIDFMT"\n", PGUID(pwr->e.guid), PGUID(rd->e.guid)); + match->matched = true; + DDS_Security_DataHolderSeq_free(tseq); + } + else + EXCEPTION_ERROR(sc, &exception, "Failed to set remote writer crypto tokens "PGUIDFMT" for reader "PGUIDFMT, PGUID(pwr->e.guid), PGUID(rd->e.guid)); + } + ddsrt_mutex_unlock(&rd->e.lock); + + if (match->matched) + connect_reader_with_proxy_writer_secure(rd, pwr, now_mt (), match->crypto_handle); + + if (pwr) + notify_handshake_recv_token(rd->c.pp, pwr->c.proxypp); +} + +void q_omg_security_set_remote_reader_crypto_tokens(struct writer *wr, const ddsi_guid_t *prd_guid, const nn_dataholderseq_t *tokens) +{ + 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 proxy_reader *prd = NULL; + + 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); + + 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; + DDS_Security_DataHolderSeq_free(tseq); + } + else + EXCEPTION_ERROR(sc, &exception, "Failed to set remote reader crypto tokens "PGUIDFMT" for writer "PGUIDFMT, PGUID(prd->e.guid), PGUID(wr->e.guid)); + } + ddsrt_mutex_unlock(&wr->e.lock); + + if (match->matched) + connect_writer_with_proxy_reader_secure(wr, prd, now_mt (), match->crypto_handle); + + if (prd) + notify_handshake_recv_token(wr->c.pp, prd->c.proxypp); +} + +bool q_omg_reader_is_discovery_protected(const struct reader *rd) +{ + assert (rd != NULL); + return rd->sec_attr != NULL && rd->sec_attr->attr.is_discovery_protected; +} + +static bool q_omg_security_encode_datareader_submessage(struct reader *rd, const ddsi_guid_prefix_t *dst_prefix, const unsigned char *src_buf, size_t src_len, unsigned char **dst_buf, size_t *dst_len) +{ + DDS_Security_SecurityException ex = DDS_SECURITY_EXCEPTION_INIT; + struct rd_pwr_match *m; + ddsrt_avl_iter_t it; + DDS_Security_DatareaderCryptoHandleSeq hdls = { 0, 0, NULL }; + DDS_Security_OctetSeq encoded_buffer; + DDS_Security_OctetSeq plain_buffer; + bool result = false; + int32_t idx = 0; + + assert (rd); + assert (src_len <= UINT32_MAX); + assert (src_buf); + assert (dst_len); + assert (dst_buf); + assert (rd->sec_attr); + assert (q_omg_reader_is_submessage_protected (rd)); + + const struct ddsi_domaingv *gv = rd->e.gv; + const struct dds_security_context *sc = q_omg_security_get_secure_context (rd->c.pp); + assert (sc); + + GVTRACE (" encode_datareader_submessage "PGUIDFMT" %s/%s", PGUID (rd->e.guid), get_reader_topic_name (rd), rd->topic ? rd->topic->type_name : "(null)"); + // FIXME: print_buf(src_buf, src_len, "q_omg_security_encode_datareader_submessage(SOURCE)"); + + ddsrt_mutex_lock (&rd->e.lock); + hdls._buffer = DDS_Security_DatawriterCryptoHandleSeq_allocbuf (rd->num_writers); + hdls._maximum = rd->num_writers; + for (m = ddsrt_avl_iter_first (&rd_writers_treedef, &rd->writers, &it); m; m = ddsrt_avl_iter_next (&it)) + { + if (m->crypto_handle && (!dst_prefix || guid_prefix_eq (&m->pwr_guid.prefix, dst_prefix))) + hdls._buffer[idx++] = m->crypto_handle; + } + ddsrt_mutex_unlock (&rd->e.lock); + + if ((hdls._length = (DDS_Security_unsigned_long) idx) == 0) + { + GVTRACE ("Submsg encoding failed for datareader "PGUIDFMT" %s/%s: no matching writers\n", PGUID (rd->e.guid), + get_reader_topic_name (rd), rd->topic ? rd->topic->type_name : "(null)"); + goto err_enc_drd_subm; + } + + memset (&encoded_buffer, 0, sizeof (encoded_buffer)); + plain_buffer._buffer = (DDS_Security_octet*) src_buf; + plain_buffer._length = (uint32_t) src_len; + plain_buffer._maximum = (uint32_t) src_len; + + if (!(result = sc->crypto_context->crypto_transform->encode_datareader_submessage ( + sc->crypto_context->crypto_transform, &encoded_buffer, &plain_buffer, rd->sec_attr->crypto_handle, &hdls, &ex))) + { + GVWARNING ("Submsg encoding failed for datareader "PGUIDFMT" %s/%s: %s", PGUID (rd->e.guid), get_reader_topic_name (rd), + rd->topic ? rd->topic->type_name : "(null)", ex.message ? ex.message : "Unknown error"); + GVTRACE ("\n"); + DDS_Security_Exception_reset (&ex); + goto err_enc_drd_subm; + } + assert (encoded_buffer._buffer); + *dst_buf = encoded_buffer._buffer; + *dst_len = encoded_buffer._length; + // FIXME: print_buf (*dst_buf, *dst_len, "q_omg_security_encode_datareader_submessage(DEST)"); + goto end_enc_drd_subm; + +err_enc_drd_subm: + *dst_buf = NULL; + *dst_len = 0; + +end_enc_drd_subm: + DDS_Security_DatawriterCryptoHandleSeq_freebuf (&hdls); + return result; } static bool q_omg_security_encode_datawriter_submessage (struct writer *wr, const ddsi_guid_prefix_t *dst_prefix, const unsigned char *src_buf, size_t src_len, unsigned char **dst_buf, size_t *dst_len) { - /* TODO: Use proper keys to actually encode (need key-exchange). */ - DDSRT_UNUSED_ARG (wr); - DDSRT_UNUSED_ARG (dst_prefix); - DDSRT_UNUSED_ARG (src_buf); - DDSRT_UNUSED_ARG (src_len); - DDSRT_UNUSED_ARG (dst_buf); - DDSRT_UNUSED_ARG (dst_len); - return false; + DDS_Security_SecurityException ex = DDS_SECURITY_EXCEPTION_INIT; + struct wr_prd_match *m; + ddsrt_avl_iter_t it; + DDS_Security_DatareaderCryptoHandleSeq hdls = { 0, 0, NULL }; + DDS_Security_OctetSeq encoded_buffer; + DDS_Security_OctetSeq plain_buffer; + bool result = false; + int32_t idx = 0; + + assert (wr); + assert (src_len <= UINT32_MAX); + assert (src_buf); + assert (dst_len); + assert (dst_buf); + assert (wr->sec_attr); + assert (q_omg_writer_is_submessage_protected (wr)); + ASSERT_MUTEX_HELD (wr->e.lock); + + const struct ddsi_domaingv *gv = wr->e.gv; + const struct dds_security_context *sc = q_omg_security_get_secure_context (wr->c.pp); + assert (sc); + + GVTRACE (" encode_datawriter_submessage "PGUIDFMT" %s/%s", PGUID (wr->e.guid), get_writer_topic_name (wr), wr->topic ? wr->topic->type_name : "(null)"); + + // FIXME: print_buf(src_buf, src_len, "q_omg_security_encode_datawriter_submessage(SOURCE)"); + + hdls._buffer = DDS_Security_DatareaderCryptoHandleSeq_allocbuf (wr->num_readers); + hdls._maximum = wr->num_readers; + for (m = ddsrt_avl_iter_first (&wr_readers_treedef, &wr->readers, &it); m; m = ddsrt_avl_iter_next (&it)) + { + if (m->crypto_handle && (!dst_prefix || guid_prefix_eq (&m->prd_guid.prefix, dst_prefix))) + hdls._buffer[idx++] = m->crypto_handle; + } + + if ((hdls._length = (DDS_Security_unsigned_long) idx) == 0) + { + GVTRACE ("Submsg encoding failed for datawriter "PGUIDFMT" %s/%s: no matching readers\n", PGUID (wr->e.guid), + get_writer_topic_name (wr), wr->topic ? wr->topic->type_name : "(null)"); + goto err_enc_dwr_subm; + } + + memset (&encoded_buffer, 0, sizeof (encoded_buffer)); + plain_buffer._buffer = (DDS_Security_octet*) src_buf; + plain_buffer._length = (uint32_t) src_len; + plain_buffer._maximum = (uint32_t) src_len; + result = true; + idx = 0; + while (result && idx < (int32_t)hdls._length) + { + /* If the plugin thinks a new call is unnecessary, the index will be set to the size of the hdls sequence. */ + result = sc->crypto_context->crypto_transform->encode_datawriter_submessage (sc->crypto_context->crypto_transform, + &encoded_buffer, &plain_buffer, wr->sec_attr->crypto_handle, &hdls, &idx, &ex); + + /* With a possible second call to encode, the plain buffer should be NULL. */ + plain_buffer._buffer = NULL; + plain_buffer._length = 0; + plain_buffer._maximum = 0; + } + + if (!result) + { + GVWARNING ("Submsg encoding failed for datawriter "PGUIDFMT" %s/%s: %s", PGUID (wr->e.guid), get_writer_topic_name (wr), + wr->topic ? wr->topic->type_name : "(null)", ex.message ? ex.message : "Unknown error"); + GVTRACE ("\n"); + DDS_Security_Exception_reset (&ex); + goto err_enc_dwr_subm; + } + + assert (encoded_buffer._buffer); + *dst_buf = encoded_buffer._buffer; + *dst_len = encoded_buffer._length; + // FIXME: print_buf (*dst_buf, *dst_len, "q_omg_security_encode_datawriter_submessage(DEST)"); + goto end_enc_dwr_subm; + +err_enc_dwr_subm: + *dst_buf = NULL; + *dst_len = 0; + +end_enc_dwr_subm: + DDS_Security_DatareaderCryptoHandleSeq_freebuf (&hdls); + return result; } -static bool q_omg_security_decode_submessage (const ddsi_guid_prefix_t * const src_prefix, const ddsi_guid_prefix_t * const dst_prefix, const unsigned char *src_buf, size_t src_len, unsigned char **dst_buf, size_t *dst_len) +static bool q_omg_security_decode_submessage (const struct ddsi_domaingv *gv, const ddsi_guid_prefix_t * const src_prefix, const ddsi_guid_prefix_t * const dst_prefix, const unsigned char *src_buf, size_t src_len, unsigned char **dst_buf, size_t *dst_len) { - /* TODO: Use proper keys to actually decode (need key-exchange). */ - DDSRT_UNUSED_ARG (src_prefix); - DDSRT_UNUSED_ARG (dst_prefix); - DDSRT_UNUSED_ARG (src_buf); - DDSRT_UNUSED_ARG (src_len); - DDSRT_UNUSED_ARG (dst_buf); - DDSRT_UNUSED_ARG (dst_len); - return false; + DDS_Security_SecurityException ex = DDS_SECURITY_EXCEPTION_INIT; + struct dds_security_context *sc = gv->security_context; + DDS_Security_SecureSubmessageCategory_t cat = 0; + DDS_Security_DatawriterCryptoHandle pp_crypto_hdl = DDS_SECURITY_HANDLE_NIL; + DDS_Security_DatawriterCryptoHandle proxypp_crypto_hdl = DDS_SECURITY_HANDLE_NIL; + DDS_Security_DatawriterCryptoHandle wr_crypto_hdl = DDS_SECURITY_HANDLE_NIL; + DDS_Security_DatareaderCryptoHandle rd_crypto_hdl = DDS_SECURITY_HANDLE_NIL; + DDS_Security_OctetSeq encoded_buffer; + DDS_Security_OctetSeq plain_buffer; + struct participant *pp = NULL; + struct proxy_participant *proxypp; + ddsi_guid_t proxypp_guid, pp_guid = { .prefix= {.u = {0,0,0} }, .entityid.u = 0 }; + bool result; + + assert (src_len <= UINT32_MAX); + assert (src_buf); + assert (dst_len); + assert (dst_buf); + + // FIXME: print_buf(src_buf, src_len, "q_omg_security_decode_submessage(SOURCE)"); + + proxypp_guid.prefix = *src_prefix; + proxypp_guid.entityid.u = NN_ENTITYID_PARTICIPANT; + if (!(proxypp = entidx_lookup_proxy_participant_guid (gv->entity_index, &proxypp_guid))) + { + GVTRACE (" Unknown remote participant "PGUIDFMT" for decoding submsg\n", PGUID (proxypp_guid)); + return false; + } + if (!proxypp->sec_attr) + { + GVTRACE (" Remote participant "PGUIDFMT" not secure for decoding submsg\n", PGUID (proxypp_guid)); + return false; + } + proxypp_crypto_hdl = proxypp->sec_attr->crypto_handle; + + if (proxypp_crypto_hdl == DDS_SECURITY_HANDLE_NIL) + { + GVTRACE (" Remote participant "PGUIDFMT" not matched yet for decoding submsg\n", PGUID (proxypp_guid)); + return false; + } + + if (dst_prefix && !guid_prefix_zero (dst_prefix)) + { + pp_guid.prefix = *dst_prefix; + pp_guid.entityid.u = NN_ENTITYID_PARTICIPANT; + if (!(pp = entidx_lookup_participant_guid (gv->entity_index, &pp_guid))) + return false; + pp_crypto_hdl = pp->sec_attr->crypto_handle; + } + + GVTRACE(" decode: pp_crypto=%"PRId64" proxypp_crypto=%"PRId64"\n", pp_crypto_hdl, proxypp_crypto_hdl); + /* Prepare buffers. */ + memset (&plain_buffer, 0, sizeof (plain_buffer)); + encoded_buffer._buffer = (DDS_Security_octet*) src_buf; + encoded_buffer._length = (uint32_t) src_len; + encoded_buffer._maximum = (uint32_t) src_len; + + /* Determine how the RTPS sub-message was encoded. */ + assert (sc); + result = sc->crypto_context->crypto_transform->preprocess_secure_submsg (sc->crypto_context->crypto_transform, &wr_crypto_hdl, &rd_crypto_hdl, + &cat, &encoded_buffer, pp_crypto_hdl, proxypp_crypto_hdl, &ex); + GVTRACE ( "decode_submessage: pp("PGUIDFMT") proxypp("PGUIDFMT"), cat(%d)", PGUID (pp_guid), PGUID (proxypp_guid), (int) cat); + if (!result) + { + GVTRACE (" Pre-process submsg failed: %s\n", ex.message ? ex.message : "Unknown error"); + DDS_Security_Exception_reset (&ex); + return false; + } + + switch (cat) + { + case DDS_SECURITY_DATAWRITER_SUBMESSAGE: + result = sc->crypto_context->crypto_transform->decode_datawriter_submessage(sc->crypto_context->crypto_transform, &plain_buffer, &encoded_buffer, rd_crypto_hdl, wr_crypto_hdl, &ex); + break; + case DDS_SECURITY_DATAREADER_SUBMESSAGE: + result = sc->crypto_context->crypto_transform->decode_datareader_submessage(sc->crypto_context->crypto_transform, &plain_buffer, &encoded_buffer, wr_crypto_hdl, rd_crypto_hdl, &ex); + break; + case DDS_SECURITY_INFO_SUBMESSAGE: + /* No decoding needed. + * TODO: Is DDS_SECURITY_INFO_SUBMESSAGE even possible when there's a SMID_SEC_PREFIX? + * + * This function is only called when there is a prefix. If it is possible, + * then I might have a problem because the further parsing expects a new + * buffer (without the security sub-messages). + * + */ + result = true; + break; + default: + result = false; + break; + } + + if (!result) + { + GVTRACE (" Submsg decoding failed: %s\n", ex.message ? ex.message : "Unknown error"); + DDS_Security_Exception_reset (&ex); + *dst_buf = NULL; + *dst_len = 0; + return false; + } + + assert (plain_buffer._buffer); + *dst_buf = plain_buffer._buffer; + *dst_len = plain_buffer._length; + // FIXME: print_buf(*dst_buf, *dst_len, "q_omg_security_decode_submessage(DEST-DATAWRITER)"); + return true; } static bool q_omg_security_encode_serialized_payload (const struct writer *wr, const unsigned char *src_buf, size_t src_len, unsigned char **dst_buf, size_t *dst_len) { - /* TODO: Use proper keys to actually encode (need key-exchange). */ - DDSRT_UNUSED_ARG (wr); - DDSRT_UNUSED_ARG (src_buf); - DDSRT_UNUSED_ARG (src_len); - DDSRT_UNUSED_ARG (dst_buf); - DDSRT_UNUSED_ARG (dst_len); - return false; + DDS_Security_SecurityException ex = DDS_SECURITY_EXCEPTION_INIT; + DDS_Security_OctetSeq extra_inline_qos; + DDS_Security_OctetSeq encoded_buffer; + DDS_Security_OctetSeq plain_buffer; + + assert (wr); + assert (src_buf); + assert (src_len <= UINT32_MAX); + assert (dst_buf); + assert (dst_len); + assert (wr->sec_attr); + assert (q_omg_writer_is_payload_protected (wr)); + + const struct ddsi_domaingv *gv = wr->e.gv; + const struct dds_security_context *sc = q_omg_security_get_secure_context (wr->c.pp); + assert (sc); + + // FIXME: print_buf(src_buf, src_len, "q_omg_security_encode_serialized_payload(SOURCE)"); + + GVTRACE (" encode_payload "PGUIDFMT" %s/%s\n", PGUID (wr->e.guid), wr->topic ? wr->topic->name : "(null)", wr->topic ? wr->topic->type_name : "(null)"); + + memset (&extra_inline_qos, 0, sizeof (extra_inline_qos)); + memset (&encoded_buffer, 0, sizeof (encoded_buffer)); + plain_buffer._buffer = (DDS_Security_octet *) src_buf; + plain_buffer._length = (uint32_t) src_len; + plain_buffer._maximum = (uint32_t) src_len; + + if (!sc->crypto_context->crypto_transform->encode_serialized_payload (sc->crypto_context->crypto_transform, + &encoded_buffer, &extra_inline_qos, &plain_buffer, wr->sec_attr->crypto_handle, &ex)) + { + GVERROR ("Payload encoding failed for datawriter "PGUIDFMT": %s\n", PGUID (wr->e.guid), ex.message ? ex.message : "Unknown error"); + DDS_Security_Exception_reset (&ex); + *dst_buf = NULL; + *dst_len = 0; + return false; + } + + *dst_buf = encoded_buffer._buffer; + *dst_len = encoded_buffer._length; + // FIXME: print_buf(*dst_buf, *dst_len, "q_omg_security_encode_serialized_payload(DEST)"); + + return true; } static bool q_omg_security_decode_serialized_payload (struct proxy_writer *pwr, const unsigned char *src_buf, size_t src_len, unsigned char **dst_buf, size_t *dst_len) { - /* TODO: Use proper keys to actually decode (need key-exchange). */ - DDSRT_UNUSED_ARG (pwr); - DDSRT_UNUSED_ARG (src_buf); - DDSRT_UNUSED_ARG (src_len); - DDSRT_UNUSED_ARG (dst_buf); - DDSRT_UNUSED_ARG (dst_len); - return false; + DDS_Security_SecurityException ex = DDS_SECURITY_EXCEPTION_INIT; + DDS_Security_OctetSeq extra_inline_qos; + DDS_Security_OctetSeq encoded_buffer; + DDS_Security_OctetSeq plain_buffer; + struct pwr_rd_match *pwr_rd_match; + struct reader *rd; + ddsrt_avl_iter_t it; + + assert (pwr); + assert (src_buf); + assert (src_len <= UINT32_MAX); + assert (dst_buf); + assert (dst_len); + + const struct ddsi_domaingv *gv = pwr->e.gv; + const struct dds_security_context *sc = q_omg_security_get_secure_context_from_proxypp (pwr->c.proxypp); + assert (sc); + + // FIXME: print_buf(src_buf, src_len, "q_omg_security_decode_serialized_payload(SOURCE)"); + + *dst_buf = NULL; + *dst_len = 0; + GVTRACE ("decode_payload "PGUIDFMT"", PGUID (pwr->e.guid)); + + /* Only one reader is enough to decrypt the data, so use only the first match. */ + ddsrt_mutex_lock (&pwr->e.lock); + pwr_rd_match = ddsrt_avl_iter_first (&pwr_readers_treedef, &pwr->readers, &it); + ddsrt_mutex_unlock (&pwr->e.lock); + if (!pwr_rd_match) + { + GVTRACE (" Payload decoding failed for from remote datawriter "PGUIDFMT": no local reader\n", PGUID (pwr->e.guid)); + return false; + } + if (!pwr_rd_match->crypto_handle) + { + GVTRACE (" Payload decoding from datawriter "PGUIDFMT": no crypto handle\n", PGUID (pwr->e.guid)); + return false; + } + if (!(rd = entidx_lookup_reader_guid (gv->entity_index, &pwr_rd_match->rd_guid))) + { + GVTRACE (" No datareader "PGUIDFMT" for decoding data from datawriter "PGUIDFMT"", PGUID (pwr_rd_match->rd_guid), PGUID (pwr->e.guid)); + return false; + } + + memset (&extra_inline_qos, 0, sizeof (extra_inline_qos)); + memset (&plain_buffer, 0, sizeof (plain_buffer)); + encoded_buffer._buffer = (DDS_Security_octet *) src_buf; + encoded_buffer._length = (uint32_t) src_len; + encoded_buffer._maximum = (uint32_t) src_len; + if (!sc->crypto_context->crypto_transform->decode_serialized_payload (sc->crypto_context->crypto_transform, + &plain_buffer, &encoded_buffer, &extra_inline_qos, rd->sec_attr->crypto_handle, pwr_rd_match->crypto_handle, &ex)) + { + GVTRACE (" Payload decoding failed for datareader "PGUIDFMT" from datawriter "PGUIDFMT": %s\n", PGUID (pwr_rd_match->rd_guid), PGUID (pwr->e.guid), ex.message ? ex.message : "Unknown error"); + DDS_Security_Exception_reset (&ex); + return false; + } + *dst_buf = plain_buffer._buffer; + *dst_len = plain_buffer._length; + // FIXME: print_buf(*dst_buf, *dst_len, "q_omg_security_decode_serialized_payload(DEST)"); + return true; } -bool q_omg_security_encode_rtps_message (int64_t src_handle, ddsi_guid_t *src_guid, const unsigned char *src_buf, size_t src_len, unsigned char **dst_buf, size_t *dst_len, int64_t dst_handle) +bool q_omg_security_encode_rtps_message (const struct ddsi_domaingv *gv, int64_t src_handle, const ddsi_guid_t *src_guid, const unsigned char *src_buf, size_t src_len, unsigned char **dst_buf, size_t *dst_len, int64_t dst_handle) { - /* TODO: Use proper keys to actually encode (need key-exchange). */ - DDSRT_UNUSED_ARG (src_handle); - DDSRT_UNUSED_ARG (src_guid); - DDSRT_UNUSED_ARG (src_buf); - DDSRT_UNUSED_ARG (src_len); - DDSRT_UNUSED_ARG (dst_buf); - DDSRT_UNUSED_ARG (dst_len); - DDSRT_UNUSED_ARG (dst_handle); - return false; + struct dds_security_context *sc = gv->security_context; + DDS_Security_SecurityException ex = DDS_SECURITY_EXCEPTION_INIT; + DDS_Security_ParticipantCryptoHandleSeq hdls = { 0, 0, NULL }; + DDS_Security_OctetSeq encoded_buffer; + DDS_Security_OctetSeq plain_buffer; + struct participant_sec_attributes *pp_attr = NULL; + bool result = false; + int32_t idx = 0; + + assert (src_buf); + assert (src_len <= UINT32_MAX); + assert (dst_buf); + assert (dst_len); + + if (dst_handle != 0) + { + hdls._buffer = (DDS_Security_long_long *) &dst_handle; + hdls._length = hdls._maximum = 1; + } + else if ((pp_attr = participant_index_find(sc, src_handle)) != NULL) + { + if (SECURITY_INFO_USE_RTPS_AUTHENTICATION(pp_attr->attr)) + { + if (get_matched_proxypp_crypto_handles(pp_attr, &hdls) == 0) + return false; + } + else + { + if ((dst_handle = get_first_matched_proxypp_crypto_handle(pp_attr)) != DDS_SECURITY_HANDLE_NIL) + { + hdls._buffer = (DDS_Security_long_long *) &dst_handle; + hdls._length = hdls._maximum = 1; + } + } + } + else + return false; + + GVTRACE (" ] encode_rtps_message ["PGUIDFMT, PGUID (*src_guid)); + + if (hdls._length > 0) + { + memset (&encoded_buffer, 0, sizeof (encoded_buffer)); + plain_buffer._buffer = (DDS_Security_octet *) src_buf; + plain_buffer._length = (uint32_t) src_len; + plain_buffer._maximum = (uint32_t) src_len; + + result = true; + idx = 0; + while (result && idx < (int32_t) hdls._length) + { + /* If the plugin thinks a new call is unnecessary, the index will be set to the size of the hdls sequence. */ + result = sc->crypto_context->crypto_transform->encode_rtps_message (sc->crypto_context->crypto_transform, + &encoded_buffer, &plain_buffer, src_handle, &hdls, &idx, &ex); + + /* With a possible second call to encode, the plain buffer should be NULL. */ + plain_buffer._buffer = NULL; + plain_buffer._length = 0; + plain_buffer._maximum = 0; + } + + if (!result) + { + GVTRACE ("]\n"); + GVTRACE ("encoding rtps message for participant "PGUIDFMT" failed: %s", PGUID (*src_guid), ex.message ? ex.message : "Unknown error"); + GVTRACE ("["); + DDS_Security_Exception_reset (&ex); + *dst_buf = NULL; + *dst_len = 0; + } + else + { + assert (encoded_buffer._buffer); + *dst_buf = encoded_buffer._buffer; + *dst_len = encoded_buffer._length; + } + } + + if (dst_handle == DDS_SECURITY_HANDLE_NIL) + ddsrt_free(hdls._buffer); + + return result; } static bool q_omg_security_decode_rtps_message (struct proxy_participant *proxypp, const unsigned char *src_buf, size_t src_len, unsigned char **dst_buf, size_t *dst_len) { - /* TODO: Use proper keys to actually decode (need key-exchange). */ - DDSRT_UNUSED_ARG (proxypp); - DDSRT_UNUSED_ARG (src_buf); - DDSRT_UNUSED_ARG (src_len); - DDSRT_UNUSED_ARG (dst_buf); - DDSRT_UNUSED_ARG (dst_len); - return false; + DDS_Security_SecurityException ex = DDS_SECURITY_EXCEPTION_INIT; + struct dds_security_context *sc; + DDS_Security_OctetSeq encoded_buffer; + DDS_Security_OctetSeq plain_buffer = {0, 0, NULL}; + ddsrt_avl_iter_t it; + + assert (proxypp); + assert (src_buf); + assert (src_len <= UINT32_MAX); + assert (dst_buf); + assert (dst_len); + + const struct ddsi_domaingv *gv = proxypp->e.gv; + GVTRACE ("decode_rtps_message from "PGUIDFMT"\n", PGUID (proxypp->e.guid)); + + *dst_buf = NULL; + *dst_len = 0; + encoded_buffer._buffer = (DDS_Security_octet *) src_buf; + encoded_buffer._length = (uint32_t) src_len; + encoded_buffer._maximum = (uint32_t) src_len; + + ddsrt_mutex_lock (&proxypp->sec_attr->lock); + for (struct proxypp_pp_match *pm = ddsrt_avl_iter_first (&proxypp_pp_treedef, &proxypp->sec_attr->participants, &it); pm; pm = ddsrt_avl_iter_next (&it)) + { + sc = q_omg_security_get_secure_context_from_proxypp(proxypp); + assert (sc); + if (!sc->crypto_context->crypto_transform->decode_rtps_message (sc->crypto_context->crypto_transform, &plain_buffer, &encoded_buffer, pm->pp_crypto_handle, proxypp->sec_attr->crypto_handle, &ex)) + { + if (ex.code == DDS_SECURITY_ERR_INVALID_CRYPTO_RECEIVER_SIGN_CODE) + continue; /* Could be caused by 'with_origin_authentication' being used, so try next match */ + GVTRACE ("decoding rtps message from remote participant "PGUIDFMT" failed: %s\n", PGUID (proxypp->e.guid), ex.message ? ex.message : "Unknown error"); + DDS_Security_Exception_reset (&ex); + ddsrt_mutex_unlock (&proxypp->sec_attr->lock); + return false; + } + *dst_buf = plain_buffer._buffer; + *dst_len = plain_buffer._length; + } + ddsrt_mutex_unlock (&proxypp->sec_attr->lock); + if (*dst_buf == NULL) + { + GVTRACE ("No match found for remote participant "PGUIDFMT" for decoding rtps message\n", PGUID (proxypp->e.guid)); + return false; + } + + return true; } -static bool q_omg_writer_is_payload_protected (const struct writer *wr) +bool q_omg_reader_is_submessage_protected(const struct reader *rd) { - /* TODO: Local registration. */ - DDSRT_UNUSED_ARG (wr); - return false; -} - -static bool q_omg_writer_is_submessage_protected (struct writer *wr) -{ - /* TODO: Local registration. */ - DDSRT_UNUSED_ARG (wr); - return false; -} - -static bool q_omg_reader_is_submessage_protected (struct reader *rd) -{ - /* TODO: Local registration. */ - DDSRT_UNUSED_ARG (rd); - return false; + assert (rd != NULL); + return rd->sec_attr != NULL && rd->sec_attr->attr.is_submessage_protected; } bool encode_payload (struct writer *wr, ddsrt_iovec_t *vec, unsigned char **buf) @@ -735,7 +3110,6 @@ bool encode_payload (struct writer *wr, ddsrt_iovec_t *vec, unsigned char **buf) return true; } - static bool decode_payload (const struct ddsi_domaingv *gv, struct nn_rsample_info *sampleinfo, unsigned char *payloadp, uint32_t *payloadsz, size_t *submsg_len) { assert (payloadp); @@ -757,8 +3131,8 @@ static bool decode_payload (const struct ddsi_domaingv *gv, struct nn_rsample_in size_t dst_len = 0; if (!q_omg_security_decode_serialized_payload (sampleinfo->pwr, payloadp, *payloadsz, &dst_buf, &dst_len)) { - GVWARNING ("decode_payload: failed to decrypt data from "PGUIDFMT"", PGUID (sampleinfo->pwr->e.guid)); - return false; + GVTRACE ("decode_payload: failed to decrypt data from "PGUIDFMT"\n", PGUID (sampleinfo->pwr->e.guid)); + return true; } /* Expect result to always fit into the original buffer. */ @@ -803,10 +3177,7 @@ void encode_datareader_submsg (struct nn_xmsg *msg, struct nn_xmsg_marker sm_mar struct reader * const rd = entidx_lookup_reader_guid (pwr->e.gv->entity_index, rd_guid); /* surely a reader can only be protected if the participant has security enabled? */ if (rd == NULL || !q_omg_reader_is_submessage_protected (rd)) - { - assert (rd == NULL || !q_omg_participant_is_secure (rd->c.pp)); return; - } assert (q_omg_participant_is_secure (rd->c.pp)); unsigned char *src_buf; @@ -835,11 +3206,12 @@ void encode_datareader_submsg (struct nn_xmsg *msg, struct nn_xmsg_marker sm_mar void encode_datawriter_submsg (struct nn_xmsg *msg, struct nn_xmsg_marker sm_marker, struct writer *wr) { - /* Only encode when needed. Surely a writer can only be protected if the participant has security enabled? */ - assert (!q_omg_writer_is_submessage_protected (wr) || q_omg_participant_is_secure (wr->c.pp)); if (!q_omg_writer_is_submessage_protected (wr)) return; + /* Only encode when needed. Surely a writer can only be protected if the participant has security enabled? */ + assert (q_omg_participant_is_secure (wr->c.pp)); + unsigned char *src_buf; size_t src_len; unsigned char *dst_buf; @@ -974,7 +3346,7 @@ static bool decode_SecPrefix_patched_hdr_flags (const struct receiver_state *rst /* Decode all three submessages. */ unsigned char *dst_buf; size_t dst_len; - const bool decoded = q_omg_security_decode_submessage (src_prefix, dst_prefix, submsg, totalsize, &dst_buf, &dst_len); + const bool decoded = q_omg_security_decode_submessage (rst->gv, src_prefix, dst_prefix, submsg, totalsize, &dst_buf, &dst_len); if (decoded && dst_buf) { /* @@ -1057,7 +3429,7 @@ static nn_rtps_msg_state_t check_rtps_message_is_secure (struct ddsi_domaingv *g GVTRACE ("received encoded rtps message from unknown participant\n"); return NN_RTPS_MSG_STATE_ERROR; } - else if (!q_omg_proxyparticipant_is_authenticated (*proxypp)) + else if (!proxypp_is_authenticated (*proxypp)) { GVTRACE ("received encoded rtps message from unauthenticated participant\n"); return NN_RTPS_MSG_STATE_ERROR; @@ -1147,6 +3519,7 @@ decode_rtps_message ( ssize_t secure_conn_write( + const struct ddsi_domaingv *gv, ddsi_tran_conn_t conn, const nn_locator_t *dst, size_t niov, @@ -1211,7 +3584,7 @@ secure_conn_write( } ssize_t ret = -1; - if (!q_omg_security_encode_rtps_message (sec_info->src_pp_handle, &guid, srcbuf, srclen, &dstbuf, &dstlen, dst_handle)) + if (!q_omg_security_encode_rtps_message (gv, sec_info->src_pp_handle, &guid, srcbuf, srclen, &dstbuf, &dstlen, dst_handle)) ret = -1; else { @@ -1250,33 +3623,66 @@ secure_conn_write( return ret; } +bool q_omg_plist_keyhash_is_protected(const ddsi_plist_t *plist) +{ + assert(plist); + if (plist->present & PP_ENDPOINT_SECURITY_INFO) + { + unsigned attr = plist->endpoint_security_info.security_attributes; + return attr & NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID && + attr & NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_KEY_PROTECTED; + } + return false; +} + +bool q_omg_is_endpoint_protected(const ddsi_plist_t *plist) +{ + assert(plist); + return plist->present & PP_ENDPOINT_SECURITY_INFO && + !SECURITY_INFO_CLEAR(plist->endpoint_security_info, NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID); +} + +void q_omg_log_endpoint_protection(struct ddsi_domaingv * const gv, const ddsi_plist_t *plist) +{ + GVLOGDISC (" p("); + if (plist->present & PP_ENDPOINT_SECURITY_INFO) + GVLOGDISC ("0x%08x.0x%08x", plist->endpoint_security_info.security_attributes, plist->endpoint_security_info.plugin_security_attributes); + else + GVLOGDISC ("open"); + GVLOGDISC (")"); +} + #else /* DDSI_INCLUDE_SECURITY */ #include "dds/ddsi/ddsi_security_omg.h" -extern inline bool q_omg_participant_is_secure(UNUSED_ARG(const struct participant *pp)); -extern inline bool q_omg_proxy_participant_is_secure(const struct proxy_participant *proxypp); extern inline bool q_omg_security_enabled(void); -extern inline bool q_omg_participant_is_secure( - UNUSED_ARG(const struct participant *pp)); +extern inline bool q_omg_participant_is_access_protected(UNUSED_ARG(const struct participant *pp)); +extern inline bool q_omg_participant_is_rtps_protected(UNUSED_ARG(const struct participant *pp)); +extern inline bool q_omg_participant_is_liveliness_protected(UNUSED_ARG(const struct participant *pp)); +extern inline bool q_omg_participant_is_secure(UNUSED_ARG(const struct participant *pp)); +extern inline bool q_omg_proxy_participant_is_secure(UNUSED_ARG(const struct proxy_participant *proxypp)); -extern inline unsigned determine_subscription_writer( - UNUSED_ARG(const struct reader *rd)); +extern inline unsigned determine_subscription_writer(UNUSED_ARG(const struct reader *rd)); -extern inline bool q_omg_security_match_remote_writer_enabled(UNUSED_ARG(struct reader *rd), UNUSED_ARG(struct proxy_writer *pwr)); -extern inline bool q_omg_security_match_remote_reader_enabled(UNUSED_ARG(struct writer *wr), UNUSED_ARG(struct proxy_reader *prd)); +extern inline bool q_omg_security_match_remote_writer_enabled(UNUSED_ARG(struct reader *rd), UNUSED_ARG(struct proxy_writer *pwr), UNUSED_ARG(int64_t *crypto_handle)); +extern inline bool q_omg_security_match_remote_reader_enabled(UNUSED_ARG(struct writer *wr), UNUSED_ARG(struct proxy_reader *prd), UNUSED_ARG(int64_t *crypto_handle)); +extern inline bool q_omg_writer_is_discovery_protected(UNUSED_ARG(const struct writer *wr)); +extern inline bool q_omg_writer_is_submessage_protected(UNUSED_ARG(const struct writer *wr)); +extern inline bool q_omg_writer_is_payload_protected(UNUSED_ARG(const struct writer *wr)); + +extern inline void q_omg_get_proxy_writer_security_info(UNUSED_ARG(struct proxy_writer *pwr), UNUSED_ARG(const ddsi_plist_t *plist), UNUSED_ARG(nn_security_info_t *info)); extern inline bool q_omg_security_check_remote_writer_permissions(UNUSED_ARG(const struct proxy_writer *pwr), UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(struct participant *pp)); +extern inline void q_omg_security_deregister_remote_writer_match(UNUSED_ARG(const struct proxy_writer *pwr), UNUSED_ARG(const struct reader *rd), UNUSED_ARG(struct rd_pwr_match *match)); +extern inline void q_omg_get_proxy_reader_security_info(UNUSED_ARG(struct proxy_reader *prd), UNUSED_ARG(const ddsi_plist_t *plist), UNUSED_ARG(nn_security_info_t *info)); extern inline bool q_omg_security_check_remote_reader_permissions(UNUSED_ARG(const struct proxy_reader *prd), UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(struct participant *par)); +extern inline void q_omg_security_deregister_remote_reader_match(UNUSED_ARG(const struct proxy_reader *prd), UNUSED_ARG(const struct writer *wr), UNUSED_ARG(struct wr_prd_match *match)); -extern inline unsigned determine_publication_writer( - UNUSED_ARG(const struct writer *wr)); +extern inline unsigned determine_publication_writer(UNUSED_ARG(const struct writer *wr)); -extern inline bool is_proxy_participant_deletion_allowed( - UNUSED_ARG(struct ddsi_domaingv * const gv), - UNUSED_ARG(const struct ddsi_guid *guid), - UNUSED_ARG(const ddsi_entityid_t pwr_entityid)); +extern inline bool is_proxy_participant_deletion_allowed(UNUSED_ARG(struct ddsi_domaingv * const gv), UNUSED_ARG(const struct ddsi_guid *guid), UNUSED_ARG(const ddsi_entityid_t pwr_entityid)); extern inline bool q_omg_is_similar_participant_security_info(UNUSED_ARG(struct participant *pp), UNUSED_ARG(struct proxy_participant *proxypp)); @@ -1284,29 +3690,43 @@ extern inline bool q_omg_participant_allow_unauthenticated(UNUSED_ARG(struct par extern inline bool q_omg_security_check_create_participant(UNUSED_ARG(struct participant *pp), UNUSED_ARG(uint32_t domain_id)); +extern inline void q_omg_security_deregister_participant(UNUSED_ARG(struct participant *pp)); + +extern inline bool q_omg_security_check_create_topic(UNUSED_ARG(const struct ddsi_domaingv *gv), UNUSED_ARG(const ddsi_guid_t *pp_guid), UNUSED_ARG(const char *topic_name), UNUSED_ARG(const struct dds_qos *qos)); + +extern inline int64_t q_omg_security_get_local_participant_handle(UNUSED_ARG(const struct participant *pp)); + +extern inline bool q_omg_security_check_create_writer(UNUSED_ARG(struct participant *pp), UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(const char *topic_name), UNUSED_ARG(const struct dds_qos *writer_qos)); + +extern inline void q_omg_security_register_writer(UNUSED_ARG(struct writer *wr)); + +extern inline void q_omg_security_deregister_writer(UNUSED_ARG(struct writer *wr)); + +extern inline bool q_omg_security_check_create_reader(UNUSED_ARG(struct participant *pp), UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(const char *topic_name), UNUSED_ARG(const struct dds_qos *reader_qos)); + +extern inline void q_omg_security_register_reader(UNUSED_ARG(struct reader *rd)); + +extern inline void q_omg_security_deregister_reader(UNUSED_ARG(struct reader *rd)); + +extern inline bool q_omg_security_is_remote_rtps_protected(UNUSED_ARG(const struct proxy_participant *proxypp), UNUSED_ARG(ddsi_entityid_t entityid)); + /* initialize the proxy participant security attributes */ extern inline void q_omg_security_init_remote_participant(UNUSED_ARG(struct proxy_participant *proxypp)); /* ask to access control security plugin for the remote participant permissions */ extern inline int64_t q_omg_security_check_remote_participant_permissions(UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(struct participant *pp), UNUSED_ARG(struct proxy_participant *proxypp)); -extern inline void q_omg_security_register_remote_participant(UNUSED_ARG(struct participant *pp), UNUSED_ARG(struct proxy_participant *proxypp), UNUSED_ARG(int64_t shared_secret), UNUSED_ARG(int64_t proxy_permissions)); +extern inline bool q_omg_security_register_remote_participant(UNUSED_ARG(struct participant *pp), UNUSED_ARG(struct proxy_participant *proxypp), UNUSED_ARG(int64_t identity_handle), UNUSED_ARG(int64_t shared_secret)); extern inline void q_omg_security_deregister_remote_participant(UNUSED_ARG(struct proxy_participant *proxypp)); extern inline void q_omg_security_participant_send_tokens(UNUSED_ARG(struct participant *pp), UNUSED_ARG(struct proxy_participant *proxypp)); -extern inline void set_proxy_participant_security_info( - UNUSED_ARG(struct proxy_participant *prd), - UNUSED_ARG(const ddsi_plist_t *plist)); +extern inline void set_proxy_participant_security_info(UNUSED_ARG(struct proxy_participant *prd), UNUSED_ARG(const ddsi_plist_t *plist)); -extern inline void set_proxy_reader_security_info( - UNUSED_ARG(struct proxy_reader *prd), - UNUSED_ARG(const ddsi_plist_t *plist)); +extern inline void set_proxy_reader_security_info(UNUSED_ARG(struct proxy_reader *prd), UNUSED_ARG(const ddsi_plist_t *plist)); -extern inline void set_proxy_writer_security_info( - UNUSED_ARG(struct proxy_writer *pwr), - UNUSED_ARG(const ddsi_plist_t *plist)); +extern inline void set_proxy_writer_security_info(UNUSED_ARG(struct proxy_writer *pwr), UNUSED_ARG(const ddsi_plist_t *plist)); extern inline bool decode_Data( UNUSED_ARG(const struct ddsi_domaingv *gv), @@ -1359,4 +3779,17 @@ extern inline nn_rtps_msg_state_t decode_rtps_message( UNUSED_ARG(struct nn_rbufpool *rbpool), UNUSED_ARG(bool isstream)); +extern inline int64_t q_omg_security_get_remote_participant_handle(UNUSED_ARG(struct proxy_participant *proxypp)); + +extern inline bool q_omg_reader_is_discovery_protected(UNUSED_ARG(const struct reader *rd)); + +extern inline bool q_omg_reader_is_submessage_protected(UNUSED_ARG(const struct reader *rd)); + +extern inline bool q_omg_plist_keyhash_is_protected(UNUSED_ARG(const ddsi_plist_t *plist)); + +extern inline bool q_omg_is_endpoint_protected(UNUSED_ARG(const ddsi_plist_t *plist)); + +extern inline void q_omg_log_endpoint_protection(UNUSED_ARG(struct ddsi_domaingv * const gv), UNUSED_ARG(const ddsi_plist_t *plist)); + + #endif /* DDSI_INCLUDE_SECURITY */ diff --git a/src/core/ddsi/src/ddsi_security_util.c b/src/core/ddsi/src/ddsi_security_util.c new file mode 100644 index 0000000..388fb4e --- /dev/null +++ b/src/core/ddsi/src/ddsi_security_util.c @@ -0,0 +1,708 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#ifdef DDSI_INCLUDE_SECURITY + +#include +#include + +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/bswap.h" + +#include "dds/ddsi/ddsi_security_util.h" + +void +g_omg_shallow_copy_StringSeq( + DDS_Security_StringSeq *dst, + const ddsi_stringseq_t *src) +{ + unsigned i; + assert(dst); + assert(src); + + dst->_length = src->n; + dst->_maximum = src->n; + dst->_buffer = NULL; + if (src->n > 0) + { + dst->_buffer = ddsrt_malloc(src->n * sizeof(DDS_Security_string)); + for (i = 0; i < src->n; i++) + dst->_buffer[i] = src->strs[i]; + } +} + +void +g_omg_shallow_free_StringSeq( + DDS_Security_StringSeq *obj) +{ + if (obj) + ddsrt_free(obj->_buffer); +} + +void +q_omg_copy_PropertySeq( + DDS_Security_PropertySeq *dst, + const dds_propertyseq_t *src) +{ + uint32_t i; + + if (src) + { + dst->_length = dst->_maximum = src->n; + if (src->n > 0) + dst->_buffer = DDS_Security_PropertySeq_allocbuf(src->n); + else + dst->_buffer = NULL; + + for (i = 0; i < src->n; i++) + { + dst->_buffer[i].name = src->props->name ? ddsrt_strdup(src->props->name) : ddsrt_strdup(""); + dst->_buffer[i].value = src->props->value ? ddsrt_strdup(src->props->value) : ddsrt_strdup(""); + } + } + else + memset(dst, 0, sizeof(*dst)); +} + +void +q_omg_shallow_copyin_PropertySeq( + DDS_Security_PropertySeq *dst, + const dds_propertyseq_t *src) +{ + unsigned i; + assert(dst); + assert(src); + + dst->_length = src->n; + dst->_maximum = src->n; + dst->_buffer = NULL; + + if (src->n > 0) + { + dst->_buffer = ddsrt_malloc(src->n * sizeof(DDS_Security_Property_t)); + for (i = 0; i < src->n; i++) + { + dst->_buffer[i].name = src->props[i].name; + dst->_buffer[i].value = src->props[i].value; + dst->_buffer[i].propagate = src->props[i].propagate; + } + } +} + +void +q_omg_shallow_copyout_PropertySeq( + dds_propertyseq_t *dst, + const DDS_Security_PropertySeq *src) +{ + unsigned i; + assert(dst); + assert(src); + + dst->n = src->_length; + dst->props = NULL; + + if (src->_length > 0) + { + dst->props = ddsrt_malloc(src->_length * sizeof(dds_property_t)); + for (i = 0; i < src->_length; i++) + { + dst->props[i].name = src->_buffer[i].name; + dst->props[i].value = src->_buffer[i].value; +// dst->props[i].propagate = src->_buffer[i].propagate; + dst->props[i].propagate = true; + } + } +} + +void +q_omg_shallow_free_PropertySeq( + DDS_Security_PropertySeq *obj) +{ + assert(obj); + ddsrt_free(obj->_buffer); + obj->_length = 0; + obj->_maximum = 0; + obj->_buffer = NULL; +} + +static void +q_omg_shallow_free_dds_propertyseq( + dds_propertyseq_t *obj) +{ + ddsrt_free(obj->props); + obj->n = 0; + obj->props = NULL; +} + +void +q_omg_shallow_copyin_BinaryPropertySeq( + DDS_Security_BinaryPropertySeq *dst, + const dds_binarypropertyseq_t *src) +{ + unsigned i; + assert(dst); + assert(src); + + dst->_length = src->n; + dst->_maximum = src->n; + dst->_buffer = NULL; + + if (src->n > 0) + { + dst->_buffer = ddsrt_malloc(src->n * sizeof(DDS_Security_BinaryProperty_t)); + for (i = 0; i < src->n; i++) + { + dst->_buffer[i].name = src->props[i].name; + dst->_buffer[i].value._length = src->props[i].value.length; + dst->_buffer[i].value._maximum = src->props[i].value.length; + dst->_buffer[i].value._buffer = src->props[i].value.value; +// dst->_buffer[i].propagate = src->props[i].propagate; + dst->_buffer[i].propagate = true; + } + } +} + +void +q_omg_shallow_copyout_BinaryPropertySeq( + dds_binarypropertyseq_t *dst, + const DDS_Security_BinaryPropertySeq *src) +{ + unsigned i; + assert(dst); + assert(src); + + dst->n = src->_length; + dst->props = NULL; + + if (src->_length > 0) + { + dst->props = ddsrt_malloc(src->_length * sizeof(dds_binaryproperty_t)); + for (i = 0; i < src->_length; i++) + { + dst->props[i].name = src->_buffer[i].name; + dst->props[i].value.length = src->_buffer[i].value._length; + dst->props[i].value.value = src->_buffer[i].value._buffer; + dst->props[i].propagate = src->_buffer[i].propagate; + } + } +} + +void +q_omg_shallow_free_BinaryPropertySeq( + DDS_Security_BinaryPropertySeq *obj) +{ + ddsrt_free(obj->_buffer); + obj->_length = 0; + obj->_maximum = 0; + obj->_buffer = NULL; +} + +static void +q_omg_shallow_free_dds_binarypropertyseq( + dds_binarypropertyseq_t *obj) +{ + ddsrt_free(obj->props); + obj->n = 0; + obj->props = NULL; +} + +void +q_omg_shallow_copy_PropertyQosPolicy( + DDS_Security_PropertyQosPolicy *dst, + const dds_property_qospolicy_t *src) +{ + assert(dst); + assert(src); + q_omg_shallow_copyin_PropertySeq(&(dst->value), &(src->value)); + q_omg_shallow_copyin_BinaryPropertySeq(&(dst->binary_value), &(src->binary_value)); +} + +void +q_omg_shallow_copy_security_qos( + DDS_Security_Qos *dst, + const struct dds_qos *src) +{ + assert(src); + assert(dst); + + /* DataTags not supported yet. */ + memset(&(dst->data_tags), 0, sizeof(DDS_Security_DataTagQosPolicy)); + + if (src->present & QP_PROPERTY_LIST) + q_omg_shallow_copy_PropertyQosPolicy(&(dst->property), &(src->property)); + else + memset(&(dst->property), 0, sizeof(DDS_Security_PropertyQosPolicy)); +} + +void +q_omg_shallow_free_PropertyQosPolicy( + DDS_Security_PropertyQosPolicy *obj) +{ + q_omg_shallow_free_PropertySeq(&(obj->value)); + q_omg_shallow_free_BinaryPropertySeq(&(obj->binary_value)); +} + +void +q_omg_shallow_free_security_qos( + DDS_Security_Qos *obj) +{ + q_omg_shallow_free_PropertyQosPolicy(&(obj->property)); +} + +void +q_omg_security_dataholder_copyin( + nn_dataholder_t *dh, + const DDS_Security_DataHolder *holder) +{ + uint32_t i; + + dh->class_id = holder->class_id ? ddsrt_strdup(holder->class_id) : NULL; + dh->properties.n = holder->properties._length; + dh->properties.props = dh->properties.n ? ddsrt_malloc(dh->properties.n * sizeof(dds_property_t)) : NULL; + for (i = 0; i < dh->properties.n; i++) + { + DDS_Security_Property_t *prop = &(holder->properties._buffer[i]); + dh->properties.props[i].name = prop->name ? ddsrt_strdup(prop->name) : NULL; + dh->properties.props[i].value = prop->value ? ddsrt_strdup(prop->value) : NULL; + dh->properties.props[i].propagate = prop->propagate; + } + dh->binary_properties.n = holder->binary_properties._length; + dh->binary_properties.props = dh->binary_properties.n ? ddsrt_malloc(dh->binary_properties.n * sizeof(dds_binaryproperty_t)) : NULL; + for (i = 0; i < dh->binary_properties.n; i++) + { + DDS_Security_BinaryProperty_t *prop = &(holder->binary_properties._buffer[i]); + dh->binary_properties.props[i].name = prop->name ? ddsrt_strdup(prop->name) : NULL; + dh->binary_properties.props[i].value.length = prop->value._length; + if (dh->binary_properties.props[i].value.length) + { + dh->binary_properties.props[i].value.value = ddsrt_malloc(prop->value._length); + memcpy(dh->binary_properties.props[i].value.value, prop->value._buffer, prop->value._length); + } + else + { + dh->binary_properties.props[i].value.value = NULL; + } + dh->binary_properties.props[i].propagate = prop->propagate; + } +} + +void +q_omg_security_dataholder_copyout( + DDS_Security_DataHolder *holder, + const nn_dataholder_t *dh) +{ + uint32_t i; + + holder->class_id = dh->class_id ? ddsrt_strdup(dh->class_id) : NULL; + holder->properties._length = holder->properties._maximum = dh->properties.n; + holder->properties._buffer = dh->properties.n ? DDS_Security_PropertySeq_allocbuf(dh->properties.n) : NULL; + for (i = 0; i < dh->properties.n; i++) + { + dds_property_t *props = &(dh->properties.props[i]); + holder->properties._buffer[i].name = props->name ? ddsrt_strdup(props->name) : NULL; + holder->properties._buffer[i].value = props->value ? ddsrt_strdup(props->value) : NULL; + holder->properties._buffer[i].propagate = props->propagate; + } + holder->binary_properties._length = holder->binary_properties._maximum = dh->binary_properties.n; + holder->binary_properties._buffer = dh->binary_properties.n ? DDS_Security_BinaryPropertySeq_allocbuf(dh->binary_properties.n) : NULL; + for (i = 0; i < dh->binary_properties.n; i++) + { + dds_binaryproperty_t *props = &(dh->binary_properties.props[i]); + holder->binary_properties._buffer[i].name = props->name ? ddsrt_strdup(props->name) : NULL; + holder->binary_properties._buffer[i].value._length = holder->binary_properties._buffer[i].value._maximum = props->value.length; + if (props->value.length) + { + holder->binary_properties._buffer[i].value._buffer = ddsrt_malloc(props->value.length); + memcpy(holder->binary_properties._buffer[i].value._buffer, props->value.value, props->value.length); + } + else + { + holder->binary_properties._buffer[i].value._buffer= NULL; + } + holder->binary_properties._buffer[i].propagate = props->propagate; + } +} + +void +q_omg_shallow_copyin_DataHolder( + DDS_Security_DataHolder *dst, + const nn_dataholder_t *src) +{ + assert(dst); + assert(src); + dst->class_id = src->class_id; + q_omg_shallow_copyin_PropertySeq(&dst->properties, &src->properties); + q_omg_shallow_copyin_BinaryPropertySeq(&dst->binary_properties, &src->binary_properties); +} + +void +q_omg_shallow_copyout_DataHolder( + nn_dataholder_t *dst, + const DDS_Security_DataHolder *src) +{ + assert(dst); + assert(src); + dst->class_id = src->class_id; + q_omg_shallow_copyout_PropertySeq(&dst->properties, &src->properties); + q_omg_shallow_copyout_BinaryPropertySeq(&dst->binary_properties, &src->binary_properties); +} + +void +q_omg_shallow_free_DataHolder( + DDS_Security_DataHolder *obj) +{ + q_omg_shallow_free_PropertySeq(&obj->properties); + q_omg_shallow_free_BinaryPropertySeq(&obj->binary_properties); +} + +void +q_omg_shallow_free_nn_dataholder( + nn_dataholder_t *holder) +{ + q_omg_shallow_free_dds_propertyseq(&holder->properties); + q_omg_shallow_free_dds_binarypropertyseq(&holder->binary_properties); +} + +void +q_omg_shallow_copyin_DataHolderSeq( + DDS_Security_DataHolderSeq *dst, + const nn_dataholderseq_t *src) +{ + unsigned i; + + dst->_length = src->n; + dst->_maximum = src->n; + dst->_buffer = NULL; + + if (src->n > 0) + { + dst->_buffer = ddsrt_malloc(src->n * sizeof(DDS_Security_DataHolder)); + for (i = 0; i < src->n; i++) + { + q_omg_shallow_copyin_DataHolder(&dst->_buffer[i], &src->tags[i]); + } + } +} + +void +q_omg_copyin_DataHolderSeq( + DDS_Security_DataHolderSeq *dst, + const nn_dataholderseq_t *src) +{ + unsigned i; + + dst->_length = src->n; + dst->_maximum = src->n; + dst->_buffer = NULL; + + if (src->n > 0) + { + dst->_buffer = ddsrt_malloc(src->n * sizeof(DDS_Security_DataHolder)); + for (i = 0; i < src->n; i++) + { + q_omg_security_dataholder_copyout(&dst->_buffer[i], &src->tags[i]); + } + } +} + + + +void +q_omg_shallow_copyout_DataHolderSeq( + nn_dataholderseq_t *dst, + const DDS_Security_DataHolderSeq *src) +{ + unsigned i; + + dst->n = src->_length; + dst->tags = NULL; + + if (src->_length > 0) + { + dst->tags = ddsrt_malloc(src->_length * sizeof(nn_dataholder_t)); + for (i = 0; i < src->_length; i++) + { + q_omg_shallow_copyout_DataHolder(&dst->tags[i], &src->_buffer[i]); + } + } +} + +void +q_omg_shallow_free_DataHolderSeq( + DDS_Security_DataHolderSeq *obj) +{ + unsigned i; + + for (i = 0; i < obj->_length; i++) + { + q_omg_shallow_free_DataHolder(&(obj->_buffer[i])); + } +} + +void +q_omg_shallow_free_nn_dataholderseq( + nn_dataholderseq_t *obj) +{ + unsigned i; + + for (i = 0; i < obj->n; i++) + { + q_omg_shallow_free_nn_dataholder(&(obj->tags[i])); + } + if (obj->n > 0) + ddsrt_free(obj->tags); +} + +static DDS_Security_Duration_t convert_duration(dds_duration_t d) +{ + DDS_Security_Duration_t sd; + + if (d == DDS_INFINITY) + { + sd.sec = INT32_MAX; + sd.nanosec = INT32_MAX; + } + else + { + sd.sec = ((int)(d/DDS_NSECS_IN_SEC)); + sd.nanosec = ((uint32_t)((d)%DDS_NSECS_IN_SEC)); + } + return sd; +} + +static void +g_omg_shallow_copy_octSeq( + DDS_Security_OctetSeq *dst, + const ddsi_octetseq_t *src) +{ + dst->_length = src->length; + dst->_maximum = src->length; + dst->_buffer = src->value; +} + +static void +g_omg_shallow_free_octSeq( + DDS_Security_OctetSeq *obj) +{ + DDSRT_UNUSED_ARG(obj); + /* Nothing to free. */ +} + +void +q_omg_shallow_copy_ParticipantBuiltinTopicDataSecure( + DDS_Security_ParticipantBuiltinTopicDataSecure *dst, + const ddsi_guid_t *guid, + const ddsi_plist_t *plist) +{ + assert(dst); + assert(guid); + assert(plist); + + memset(dst, 0, sizeof(DDS_Security_ParticipantBuiltinTopicDataSecure)); + + /* The participant guid is the key. */ + dst->key[0] = guid->prefix.u[0]; + dst->key[1] = guid->prefix.u[1]; + dst->key[2] = guid->prefix.u[2]; + + /* Copy the DDS_Security_OctetSeq content (length, pointer, etc), not the buffer content. */ + if (plist->qos.present & QP_USER_DATA) + memcpy(&(dst->user_data.value), &(plist->qos.user_data.value), sizeof(DDS_Security_OctetSeq)); + /* Tokens are actually DataHolders. */ + if (plist->present & PP_IDENTITY_TOKEN) + q_omg_shallow_copyin_DataHolder(&(dst->identity_token), &(plist->identity_token)); + if (plist->present & PP_PERMISSIONS_TOKEN) + q_omg_shallow_copyin_DataHolder(&(dst->permissions_token), &(plist->permissions_token)); + if (plist->present & PP_IDENTITY_STATUS_TOKEN) + q_omg_shallow_copyin_DataHolder(&(dst->identity_status_token), &(plist->identity_status_token)); + if (plist->qos.present & QP_PROPERTY_LIST) + q_omg_shallow_copy_PropertyQosPolicy(&(dst->property), &(plist->qos.property)); + if (plist->present & PP_PARTICIPANT_SECURITY_INFO) + { + dst->security_info.participant_security_attributes = plist->participant_security_info.security_attributes; + dst->security_info.plugin_participant_security_attributes = plist->participant_security_info.plugin_security_attributes; + } +} + +void +q_omg_shallow_free_ParticipantBuiltinTopicDataSecure( + DDS_Security_ParticipantBuiltinTopicDataSecure *obj) +{ + assert(obj); + q_omg_shallow_free_DataHolder(&(obj->identity_token)); + q_omg_shallow_free_DataHolder(&(obj->permissions_token)); + q_omg_shallow_free_DataHolder(&(obj->identity_status_token)); + q_omg_shallow_free_PropertyQosPolicy(&(obj->property)); +} + +void +q_omg_shallow_copy_SubscriptionBuiltinTopicDataSecure( + DDS_Security_SubscriptionBuiltinTopicDataSecure *dst, + const ddsi_guid_t *guid, + const struct dds_qos *qos, + const nn_security_info_t *secinfo) +{ + memset(dst, 0, sizeof(DDS_Security_SubscriptionBuiltinTopicDataSecure)); + + /* Keys are inspired by write_builtin_topic_copyin_subscriptionInfo() */ + dst->key[0] = ddsrt_toBE4u(guid->prefix.u[0]); + dst->key[1] = ddsrt_toBE4u(guid->prefix.u[1]); + dst->key[2] = ddsrt_toBE4u(guid->prefix.u[2]); + + dst->participant_key[0] = ddsrt_toBE4u(guid->prefix.u[0]); + dst->participant_key[1] = ddsrt_toBE4u(guid->prefix.u[1]); + dst->participant_key[2] = ddsrt_toBE4u(guid->prefix.u[2]); + + if (qos->present & QP_TOPIC_NAME) + dst->topic_name = (DDS_Security_string)qos->topic_name; + if (qos->present & QP_TYPE_NAME) + dst->type_name = (DDS_Security_string)qos->type_name; + + dst->security_info.endpoint_security_mask = secinfo->security_attributes; + dst->security_info.plugin_endpoint_security_mask = secinfo->plugin_security_attributes; + + if (qos->present & QP_DURABILITY) + dst->durability.kind = (DDS_Security_DurabilityQosPolicyKind)qos->durability.kind; + if (qos->present & QP_DEADLINE) + dst->deadline.period = convert_duration(qos->deadline.deadline); + if (qos->present & QP_LATENCY_BUDGET) + dst->latency_budget.duration = convert_duration(qos->latency_budget.duration); + if (qos->present & QP_LIVELINESS) + { + dst->liveliness.kind = (DDS_Security_LivelinessQosPolicyKind)qos->liveliness.kind; + dst->liveliness.lease_duration = convert_duration(qos->liveliness.lease_duration); + } + if (qos->present & QP_OWNERSHIP) + dst->ownership.kind = qos->ownership.kind == DDS_OWNERSHIP_SHARED ? DDS_SECURITY_SHARED_OWNERSHIP_QOS : DDS_SECURITY_EXCLUSIVE_OWNERSHIP_QOS; + if (qos->present & QP_DESTINATION_ORDER) + dst->destination_order.kind = (DDS_Security_DestinationOrderQosPolicyKind)qos->destination_order.kind; + if (qos->present & QP_PRESENTATION) + { + dst->presentation.access_scope = (DDS_Security_PresentationQosPolicyAccessScopeKind)qos->presentation.access_scope; + dst->presentation.coherent_access = qos->presentation.coherent_access; + dst->presentation.ordered_access = qos->presentation.ordered_access; + } + if (qos->present & QP_TIME_BASED_FILTER) + dst->time_based_filter.minimum_separation = convert_duration(qos->time_based_filter.minimum_separation); + if (qos->present & QP_RELIABILITY) + { + dst->reliability.kind = (DDS_Security_ReliabilityQosPolicyKind)(qos->reliability.kind); + dst->reliability.max_blocking_time = convert_duration(qos->reliability.max_blocking_time); + dst->reliability.synchronous = 0; + } + if (qos->present & QP_PARTITION) + g_omg_shallow_copy_StringSeq(&dst->partition.name, &qos->partition); + if (qos->present & QP_USER_DATA) + g_omg_shallow_copy_octSeq(&dst->user_data.value, &qos->user_data); + if (qos->present & QP_TOPIC_DATA) + g_omg_shallow_copy_octSeq(&dst->topic_data.value, &qos->topic_data); + if (qos->present & QP_GROUP_DATA) + g_omg_shallow_copy_octSeq(&dst->group_data.value, &qos->group_data); + + /* The dst->data_tags is not supported yet. It is memset to 0, so ok. */ +} + +void +q_omg_shallow_free_SubscriptionBuiltinTopicDataSecure( + DDS_Security_SubscriptionBuiltinTopicDataSecure *obj) +{ + g_omg_shallow_free_octSeq(&obj->user_data.value); + g_omg_shallow_free_octSeq(&obj->topic_data.value); + g_omg_shallow_free_octSeq(&obj->group_data.value); + g_omg_shallow_free_StringSeq(&obj->partition.name); +} + +void +q_omg_shallow_copy_PublicationBuiltinTopicDataSecure( + DDS_Security_PublicationBuiltinTopicDataSecure *dst, + const ddsi_guid_t *guid, + const struct dds_qos *qos, + const nn_security_info_t *secinfo) +{ + + memset(dst, 0, sizeof(DDS_Security_PublicationBuiltinTopicDataSecure)); + + /* Keys are inspired by write_builtin_topic_copyin_subscriptionInfo() */ + dst->key[0] = ddsrt_toBE4u(guid->prefix.u[0]); + dst->key[1] = ddsrt_toBE4u(guid->prefix.u[1]); + dst->key[2] = ddsrt_toBE4u(guid->prefix.u[2]); + + dst->participant_key[0] = ddsrt_toBE4u(guid->prefix.u[0]); + dst->participant_key[1] = ddsrt_toBE4u(guid->prefix.u[1]); + dst->participant_key[2] = ddsrt_toBE4u(guid->prefix.u[2]); + + if (qos->present & QP_TOPIC_NAME) + dst->topic_name = (DDS_Security_string)qos->topic_name; + if (qos->present & QP_TYPE_NAME) + dst->type_name = (DDS_Security_string)qos->type_name; + + dst->security_info.endpoint_security_mask = secinfo->security_attributes; + dst->security_info.plugin_endpoint_security_mask = secinfo->plugin_security_attributes; + + if (qos->present & QP_DURABILITY) + dst->durability.kind = (DDS_Security_DurabilityQosPolicyKind)qos->durability.kind; + if (qos->present & QP_DEADLINE) + dst->deadline.period = convert_duration(qos->deadline.deadline); + if (qos->present & QP_LATENCY_BUDGET) + dst->latency_budget.duration = convert_duration(qos->latency_budget.duration); + if (qos->present & QP_LIVELINESS) + { + dst->liveliness.kind = (DDS_Security_LivelinessQosPolicyKind)qos->liveliness.kind; + dst->liveliness.lease_duration = convert_duration(qos->liveliness.lease_duration); + } + if (qos->present & QP_OWNERSHIP) + dst->ownership.kind = qos->ownership.kind == DDS_OWNERSHIP_SHARED ? DDS_SECURITY_SHARED_OWNERSHIP_QOS : DDS_SECURITY_EXCLUSIVE_OWNERSHIP_QOS; + if (qos->present & QP_DESTINATION_ORDER) + dst->destination_order.kind = (DDS_Security_DestinationOrderQosPolicyKind)qos->destination_order.kind; + if (qos->present & QP_PRESENTATION) + { + dst->presentation.access_scope = (DDS_Security_PresentationQosPolicyAccessScopeKind)qos->presentation.access_scope; + dst->presentation.coherent_access = qos->presentation.coherent_access; + dst->presentation.ordered_access = qos->presentation.ordered_access; + } + if (qos->present & QP_OWNERSHIP_STRENGTH) + dst->ownership_strength.value = qos->ownership_strength.value; + if (qos->present & QP_RELIABILITY) + { + dst->reliability.kind = (DDS_Security_ReliabilityQosPolicyKind)(qos->reliability.kind); + dst->reliability.max_blocking_time = convert_duration(qos->reliability.max_blocking_time); + dst->reliability.synchronous = 0; + } + if (qos->present & QP_LIFESPAN) + dst->lifespan.duration = convert_duration(qos->lifespan.duration); + if (qos->present & QP_PARTITION) + g_omg_shallow_copy_StringSeq(&dst->partition.name, &qos->partition); + if (qos->present & QP_USER_DATA) + g_omg_shallow_copy_octSeq(&dst->user_data.value, &qos->user_data); + + if (qos->present & QP_TOPIC_DATA) + g_omg_shallow_copy_octSeq(&dst->topic_data.value, &qos->topic_data); + if (qos->present & QP_GROUP_DATA) + g_omg_shallow_copy_octSeq(&dst->group_data.value, &qos->group_data); + + /* The dst->data_tags is not supported yet. It is memset to 0, so ok. */ +} + +void +q_omg_shallow_free_PublicationBuiltinTopicDataSecure( + DDS_Security_PublicationBuiltinTopicDataSecure *obj) +{ + g_omg_shallow_free_octSeq(&obj->user_data.value); + g_omg_shallow_free_octSeq(&obj->topic_data.value); + g_omg_shallow_free_octSeq(&obj->group_data.value); + g_omg_shallow_free_StringSeq(&obj->partition.name); +} + + + +#endif /* DDSI_INCLUDE_SECURITY */ diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 05cdea6..589276a 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -45,6 +45,9 @@ #include "dds/ddsi/q_feature_check.h" #include "dds/ddsi/ddsi_security_omg.h" #include "dds/ddsi/ddsi_pmd.h" +#ifdef DDSI_INCLUDE_SECURITY +#include "dds/ddsi/ddsi_security_exchange.h" +#endif static int get_locator (const struct ddsi_domaingv *gv, nn_locator_t *loc, const nn_locators_t *locs, int uc_same_subnet) { @@ -184,37 +187,13 @@ static int write_mpayload (struct writer *wr, int alive, nn_parameterid_t keypar return write_sample_nogc_notk (ts1, NULL, wr, serdata); } -int spdp_write (struct participant *pp) +void get_participant_builtin_topic_data(const struct participant *pp, struct nn_xmsg *mpayload, bool be) { - struct nn_xmsg *mpayload; struct nn_locators_one def_uni_loc_one, def_multi_loc_one, meta_uni_loc_one, meta_multi_loc_one; ddsi_plist_t ps; - struct writer *wr; size_t size; char node[64]; uint64_t qosdiff; - int ret; - - if (pp->e.onlylocal) { - /* This topic is only locally available. */ - return 0; - } - - ETRACE (pp, "spdp_write("PGUIDFMT")\n", PGUID (pp->e.guid)); - - if ((wr = get_builtin_writer (pp, NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)) == NULL) - { - ETRACE (pp, "spdp_write("PGUIDFMT") - builtin participant writer not found\n", PGUID (pp->e.guid)); - return 0; - } - - /* First create a fake message for the payload: we can add plists to - xmsgs easily, but not to serdata. But it is rather easy to copy - the payload of an xmsg over to a serdata ... Expected size isn't - terribly important, the msg will grow as needed, address space is - essentially meaningless because we only use the message to - construct the payload. */ - mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid, NULL, 0, NN_XMSG_KIND_DATA); ddsi_plist_init_empty (&ps); ps.present |= PP_PARTICIPANT_GUID | PP_BUILTIN_ENDPOINT_SET | @@ -321,6 +300,210 @@ int spdp_write (struct participant *pp) ETRACE (pp, "spdp_write("PGUIDFMT") - internals: %s\n", PGUID (pp->e.guid), ps.prismtech_participant_version_info.internals); } +#ifdef DDSI_INCLUDE_SECURITY + /* Add Security specific information. */ + if (q_omg_get_participant_security_info(pp, &(ps.participant_security_info))) { + ps.present |= PP_PARTICIPANT_SECURITY_INFO; + ps.aliased |= PP_PARTICIPANT_SECURITY_INFO; + } +#endif + + /* Participant QoS's insofar as they are set, different from the default, and mapped to the SPDP data, rather than to the PrismTech-specific CMParticipant endpoint. Currently, that means just USER_DATA. */ + qosdiff = ddsi_xqos_delta (&pp->plist->qos, &pp->e.gv->default_plist_pp.qos, QP_USER_DATA); + if (pp->e.gv->config.explicitly_publish_qos_set_to_default) + qosdiff |= ~QP_UNRECOGNIZED_INCOMPATIBLE_MASK; + + assert (ps.qos.present == 0); + ddsi_plist_addtomsg_bo (mpayload, &ps, ~(uint64_t)0, 0, be); + ddsi_plist_addtomsg_bo (mpayload, pp->plist, 0, qosdiff, be); +#ifdef DDSI_INCLUDE_SECURITY + if (q_omg_participant_is_secure(pp)) + ddsi_plist_addtomsg_bo (mpayload, pp->plist, PP_IDENTITY_TOKEN | PP_PERMISSIONS_TOKEN, 0, be); +#endif + nn_xmsg_addpar_sentinel_bo (mpayload, be); + ddsi_plist_fini (&ps); +} + +int spdp_write (struct participant *pp) +{ + struct nn_xmsg *mpayload; + struct writer *wr; + int ret; + + if (pp->e.onlylocal) { + /* This topic is only locally available. */ + return 0; + } + + ETRACE (pp, "spdp_write("PGUIDFMT")\n", PGUID (pp->e.guid)); + + if ((wr = get_builtin_writer (pp, NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)) == NULL) + { + ETRACE (pp, "spdp_write("PGUIDFMT") - builtin participant writer not found\n", PGUID (pp->e.guid)); + return 0; + } + + /* First create a fake message for the payload: we can add plists to + xmsgs easily, but not to serdata. But it is rather easy to copy + the payload of an xmsg over to a serdata ... Expected size isn't + terribly important, the msg will grow as needed, address space is + essentially meaningless because we only use the message to + construct the payload. */ + mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid, pp, 0, NN_XMSG_KIND_DATA); + get_participant_builtin_topic_data(pp, mpayload, false); + ret = write_mpayload (wr, 1, PID_PARTICIPANT_GUID, mpayload); + nn_xmsg_free (mpayload); + return ret; +} + + + +#if 0 +int spdp_write (struct participant *pp) +{ + struct nn_xmsg *mpayload; + struct nn_locators_one def_uni_loc_one, def_multi_loc_one, meta_uni_loc_one, meta_multi_loc_one; + ddsi_plist_t ps; + struct writer *wr; + size_t size; + char node[64]; + uint64_t qosdiff; + int ret; + + if (pp->e.onlylocal) { + /* This topic is only locally available. */ + return 0; + } + + ETRACE (pp, "spdp_write("PGUIDFMT")\n", PGUID (pp->e.guid)); + + if ((wr = get_builtin_writer (pp, NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)) == NULL) + { + ETRACE (pp, "spdp_write("PGUIDFMT") - builtin participant writer not found\n", PGUID (pp->e.guid)); + return 0; + } + + /* First create a fake message for the payload: we can add plists to + xmsgs easily, but not to serdata. But it is rather easy to copy + the payload of an xmsg over to a serdata ... Expected size isn't + terribly important, the msg will grow as needed, address space is + essentially meaningless because we only use the message to + construct the payload. */ + mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid, pp, 0, NN_XMSG_KIND_DATA); + + ddsi_plist_init_empty (&ps); + ps.present |= PP_PARTICIPANT_GUID | PP_BUILTIN_ENDPOINT_SET | + PP_PROTOCOL_VERSION | PP_VENDORID | PP_PARTICIPANT_LEASE_DURATION | + PP_DOMAIN_ID; + ps.participant_guid = pp->e.guid; + ps.builtin_endpoint_set = pp->bes; + ps.protocol_version.major = RTPS_MAJOR; + ps.protocol_version.minor = RTPS_MINOR; + ps.vendorid = NN_VENDORID_ECLIPSE; + ps.domain_id = pp->e.gv->config.extDomainId.value; + /* Be sure not to send a DOMAIN_TAG when it is the default (an empty) + string: it is an "incompatible-if-unrecognized" parameter, and so + implementations that don't understand the parameter will refuse to + discover us, and so sending the default would break backwards + compatibility. */ + if (strcmp (pp->e.gv->config.domainTag, "") != 0) + { + ps.present |= PP_DOMAIN_TAG; + ps.aliased |= PP_DOMAIN_TAG; + ps.domain_tag = pp->e.gv->config.domainTag; + } + ps.default_unicast_locators.n = 1; + ps.default_unicast_locators.first = + ps.default_unicast_locators.last = &def_uni_loc_one; + ps.metatraffic_unicast_locators.n = 1; + ps.metatraffic_unicast_locators.first = + ps.metatraffic_unicast_locators.last = &meta_uni_loc_one; + def_uni_loc_one.next = NULL; + meta_uni_loc_one.next = NULL; + + if (pp->e.gv->config.many_sockets_mode == MSM_MANY_UNICAST) + { + def_uni_loc_one.loc = pp->m_locator; + meta_uni_loc_one.loc = pp->m_locator; + } + else + { + def_uni_loc_one.loc = pp->e.gv->loc_default_uc; + meta_uni_loc_one.loc = pp->e.gv->loc_meta_uc; + } + + if (pp->e.gv->config.publish_uc_locators) + { + ps.present |= PP_DEFAULT_UNICAST_LOCATOR | PP_METATRAFFIC_UNICAST_LOCATOR; + ps.aliased |= PP_DEFAULT_UNICAST_LOCATOR | PP_METATRAFFIC_UNICAST_LOCATOR; + } + + if (pp->e.gv->config.allowMulticast) + { + int include = 0; +#ifdef DDSI_INCLUDE_SSM + /* Note that if the default multicast address is an SSM address, + we will simply advertise it. The recipients better understand + it means the writers will publish to address and the readers + favour SSM. */ + if (ddsi_is_ssm_mcaddr (pp->e.gv, &pp->e.gv->loc_default_mc)) + include = (pp->e.gv->config.allowMulticast & AMC_SSM) != 0; + else + include = (pp->e.gv->config.allowMulticast & AMC_ASM) != 0; +#else + if (pp->e.gv->config.allowMulticast & AMC_ASM) + include = 1; +#endif + if (include) + { + ps.present |= PP_DEFAULT_MULTICAST_LOCATOR | PP_METATRAFFIC_MULTICAST_LOCATOR; + ps.aliased |= PP_DEFAULT_MULTICAST_LOCATOR | PP_METATRAFFIC_MULTICAST_LOCATOR; + ps.default_multicast_locators.n = 1; + ps.default_multicast_locators.first = + ps.default_multicast_locators.last = &def_multi_loc_one; + ps.metatraffic_multicast_locators.n = 1; + ps.metatraffic_multicast_locators.first = + ps.metatraffic_multicast_locators.last = &meta_multi_loc_one; + def_multi_loc_one.next = NULL; + def_multi_loc_one.loc = pp->e.gv->loc_default_mc; + meta_multi_loc_one.next = NULL; + meta_multi_loc_one.loc = pp->e.gv->loc_meta_mc; + } + } + ps.participant_lease_duration = pp->lease_duration; + + /* Add PrismTech specific version information */ + { + ps.present |= PP_PRISMTECH_PARTICIPANT_VERSION_INFO; + memset (&ps.prismtech_participant_version_info, 0, sizeof (ps.prismtech_participant_version_info)); + ps.prismtech_participant_version_info.version = 0; + ps.prismtech_participant_version_info.flags = + NN_PRISMTECH_FL_DDSI2_PARTICIPANT_FLAG | + NN_PRISMTECH_FL_PTBES_FIXED_0 | + NN_PRISMTECH_FL_SUPPORTS_STATUSINFOX; + if (pp->e.gv->config.besmode == BESMODE_MINIMAL) + ps.prismtech_participant_version_info.flags |= NN_PRISMTECH_FL_MINIMAL_BES_MODE; + ddsrt_mutex_lock (&pp->e.gv->privileged_pp_lock); + if (pp->is_ddsi2_pp) + ps.prismtech_participant_version_info.flags |= NN_PRISMTECH_FL_PARTICIPANT_IS_DDSI2; + ddsrt_mutex_unlock (&pp->e.gv->privileged_pp_lock); + + if (ddsrt_gethostname(node, sizeof(node)-1) < 0) + (void) ddsrt_strlcpy (node, "unknown", sizeof (node)); + size = strlen(node) + strlen(DDS_VERSION) + strlen(DDS_HOST_NAME) + strlen(DDS_TARGET_NAME) + 4; /* + ///'\0' */ + ps.prismtech_participant_version_info.internals = ddsrt_malloc(size); + (void) snprintf(ps.prismtech_participant_version_info.internals, size, "%s/%s/%s/%s", node, DDS_VERSION, DDS_HOST_NAME, DDS_TARGET_NAME); + ETRACE (pp, "spdp_write("PGUIDFMT") - internals: %s\n", PGUID (pp->e.guid), ps.prismtech_participant_version_info.internals); + } + +#ifdef DDSI_INCLUDE_SECURITY + /* Add Security specific information. */ + if (q_omg_get_participant_security_info(pp, &(ps.participant_security_info))) { + ps.present |= PP_PARTICIPANT_SECURITY_INFO; + ps.aliased |= PP_PARTICIPANT_SECURITY_INFO; + } +#endif + /* Participant QoS's insofar as they are set, different from the default, and mapped to the SPDP data, rather than to the PrismTech-specific CMParticipant endpoint. Currently, that means just USER_DATA. */ qosdiff = ddsi_xqos_delta (&pp->plist->qos, &pp->e.gv->default_plist_pp.qos, QP_USER_DATA); if (pp->e.gv->config.explicitly_publish_qos_set_to_default) @@ -329,6 +512,10 @@ int spdp_write (struct participant *pp) assert (ps.qos.present == 0); ddsi_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, 0); ddsi_plist_addtomsg (mpayload, pp->plist, 0, qosdiff); +#ifdef DDSI_INCLUDE_SECURITY + if (q_omg_participant_is_secure(pp)) + ddsi_plist_addtomsg (mpayload, pp->plist, PP_IDENTITY_TOKEN | PP_PERMISSIONS_TOKEN, 0); +#endif nn_xmsg_addpar_sentinel (mpayload); ddsi_plist_fini (&ps); @@ -336,6 +523,7 @@ int spdp_write (struct participant *pp) nn_xmsg_free (mpayload); return ret; } +#endif static int spdp_dispose_unregister_with_wr (struct participant *pp, unsigned entityid) { @@ -352,7 +540,7 @@ static int spdp_dispose_unregister_with_wr (struct participant *pp, unsigned ent return 0; } - mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid, NULL, 0, NN_XMSG_KIND_DATA); + mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid, pp, 0, NN_XMSG_KIND_DATA); ddsi_plist_init_empty (&ps); ps.present |= PP_PARTICIPANT_GUID; ps.participant_guid = pp->e.guid; @@ -1009,7 +1197,7 @@ static int sedp_write_endpoint the QoS and other settings. So the header fields aren't really important, except that they need to be set to reasonable things or it'll crash */ - mpayload = nn_xmsg_new (gv->xmsgpool, &wr->e.guid, NULL, 0, NN_XMSG_KIND_DATA); + mpayload = nn_xmsg_new (gv->xmsgpool, &wr->e.guid, wr->c.pp, 0, NN_XMSG_KIND_DATA); ddsi_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0); if (xqos) ddsi_xqos_addtomsg (mpayload, xqos, qosdiff); nn_xmsg_addpar_sentinel (mpayload); @@ -1268,6 +1456,12 @@ static void handle_SEDP_alive (const struct receiver_state *rst, seqno_t seq, dd E ("******* AARGH - it expects inline QoS ********\n", err); } + q_omg_log_endpoint_protection(gv, datap); + if (q_omg_is_endpoint_protected(datap) && !q_omg_proxy_participant_is_secure(pp)) + { + E (" remote endpoint is protected while local federation is not secure\n", err); + } + if (is_writer) { pwr = entidx_lookup_proxy_writer_guid (gv->entity_index, &datap->endpoint_guid); @@ -1472,7 +1666,7 @@ int sedp_write_topic (struct participant *pp, const struct ddsi_plist *datap) sedp_wr = get_sedp_writer (pp, NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER); - mpayload = nn_xmsg_new (sedp_wr->e.gv->xmsgpool, &sedp_wr->e.guid, NULL, 0, NN_XMSG_KIND_DATA); + mpayload = nn_xmsg_new (sedp_wr->e.gv->xmsgpool, &sedp_wr->e.guid, pp, 0, NN_XMSG_KIND_DATA); delta = ddsi_xqos_delta (&datap->qos, &sedp_wr->e.gv->default_xqos_tp, ~(uint64_t)0); if (sedp_wr->e.gv->config.explicitly_publish_qos_set_to_default) delta |= ~QP_UNRECOGNIZED_INCOMPATIBLE_MASK; @@ -1718,10 +1912,10 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str break; #ifdef DDSI_INCLUDE_SECURITY case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER: - /* TODO: Handshake */ + handle_auth_handshake_message(sampleinfo->rst, srcguid.entityid, timestamp, statusinfo, datap, datasz); break; case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER: - /* TODO: Key exchange */ + handle_crypto_exchange_message(sampleinfo->rst, srcguid.entityid, timestamp, statusinfo, datap, datasz); break; #endif default: diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 72df23f..ab60485 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -109,7 +109,7 @@ static void unref_participant (struct participant *pp, const struct ddsi_guid *g static struct entity_common *entity_common_from_proxy_endpoint_common (const struct proxy_endpoint_common *c); #ifdef DDSI_INCLUDE_SECURITY -static void handshake_end_cb(struct ddsi_domaingv const * const gv, struct ddsi_handshake *handshake, const struct ddsi_guid *lpguid, const struct ddsi_guid *ppguid, enum ddsi_handshake_state result); +static void handshake_end_cb(struct ddsi_handshake *handshake, struct participant *pp, struct proxy_participant *proxypp, enum ddsi_handshake_state result); static void downgrade_to_nonsecure(struct proxy_participant *proxypp); #endif @@ -217,6 +217,13 @@ static int is_builtin_volatile_endpoint (ddsi_entityid_t id) } return 0; } +#else + +static int is_builtin_volatile_endpoint (ddsi_entityid_t id) +{ + DDSRT_UNUSED_ARG(id); + return 0; +} #endif @@ -637,14 +644,14 @@ static void connect_participant_secure(struct ddsi_domaingv *gv, struct particip if (q_omg_participant_is_secure(pp)) { + q_omg_security_participant_set_initialized(pp); + entidx_enum_proxy_participant_init (&it, gv->entity_index); while ((proxypp = entidx_enum_proxy_participant_next (&it)) != NULL) { /* Do not start handshaking when security info doesn't match. */ - if (q_omg_is_similar_participant_security_info(pp, proxypp)) - { + if (q_omg_security_remote_participant_is_initialized(proxypp) && q_omg_is_similar_participant_security_info(pp, proxypp)) ddsi_handshake_register(pp, proxypp, handshake_end_cb); - } } entidx_enum_proxy_participant_fini (&it); } @@ -743,7 +750,7 @@ static void participant_remove_wr_lease_locked (struct participant * pp, struct } } -dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct ddsi_domaingv *gv, unsigned flags, const ddsi_plist_t *plist) +dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv, unsigned flags, const ddsi_plist_t *plist) { struct participant *pp; ddsi_guid_t subguid, group_guid; @@ -806,6 +813,7 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct ddsi_domain ddsi_plist_mergein_missing (pp->plist, &gv->default_local_plist_pp, ~(uint64_t)0, ~(uint64_t)0); #ifdef DDSI_INCLUDE_SECURITY + pp->sec_attr = NULL; /* * if there there are security properties check them . * if there are no security properties, then merge from security configuration if there is @@ -876,6 +884,7 @@ dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct ddsi_domain ret = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY; goto not_allowed; } + *ppguid = pp->e.guid; } #endif @@ -1257,6 +1266,9 @@ static void unref_participant (struct participant *pp, const struct ddsi_guid *g while longer for it to wakeup. */ ddsi_conn_free (pp->m_conn); } +#ifdef DDSI_INCLUDE_SECURITY + q_omg_security_deregister_participant(pp); +#endif ddsi_plist_fini (pp->plist); ddsrt_free (pp->plist); ddsrt_mutex_destroy (&pp->refc_lock); @@ -1735,19 +1747,30 @@ void rebuild_or_clear_writer_addrsets (struct ddsi_domaingv *gv, int rebuild) GVLOGDISC ("rebuild_or_delete_writer_addrsets(%d) done\n", rebuild); } -static void free_wr_prd_match (struct wr_prd_match *m) +static void free_wr_prd_match (const struct ddsi_domaingv *gv, const ddsi_guid_t *wr_guid, struct wr_prd_match *m) { if (m) { +#ifdef DDSI_INCLUDE_SECURITY + q_omg_security_deregister_remote_reader_match (gv, wr_guid, m); +#else + (void) gv; + (void) wr_guid; +#endif nn_lat_estim_fini (&m->hb_to_ack_latency); ddsrt_free (m); } } -static void free_rd_pwr_match (struct ddsi_domaingv *gv, struct rd_pwr_match *m) +static void free_rd_pwr_match (struct ddsi_domaingv *gv, const ddsi_guid_t *rd_guid, struct rd_pwr_match *m) { if (m) { +#ifdef DDSI_INCLUDE_SECURITY + q_omg_security_deregister_remote_writer_match (gv, rd_guid, m); +#else + (void) rd_guid; +#endif #ifdef DDSI_INCLUDE_SSM if (!is_unspec_locator (&m->ssm_mc_loc)) { @@ -1756,7 +1779,8 @@ static void free_rd_pwr_match (struct ddsi_domaingv *gv, struct rd_pwr_match *m) if (ddsi_leave_mc (gv, gv->mship, gv->data_conn_mc, &m->ssm_src_loc, &m->ssm_mc_loc) < 0) GVWARNING ("failed to leave network partition ssm group\n"); } -#else +#endif +#if !(defined DDSI_INCLUDE_SECURITY || defined DDSI_INCLUDE_SSM) (void) gv; #endif ddsrt_free (m); @@ -1829,8 +1853,10 @@ static void writer_drop_connection (const struct ddsi_guid *wr_guid, const struc ddsrt_avl_delete (&wr_readers_treedef, &wr->readers, m); rebuild_writer_addrset (wr); remove_acked_messages (wr, &whcst, &deferred_free_list); + wr->num_readers--; wr->num_reliable_readers -= m->is_reliable; } + ddsrt_mutex_unlock (&wr->e.lock); if (m != NULL && wr->status_cb) { @@ -1841,7 +1867,7 @@ static void writer_drop_connection (const struct ddsi_guid *wr_guid, const struc (wr->status_cb) (wr->status_cb_entity, &data); } whc_free_deferred_free_list (wr->whc, deferred_free_list); - free_wr_prd_match (m); + free_wr_prd_match (wr->e.gv, &wr->e.guid, m); } } @@ -1981,7 +2007,11 @@ static void reader_drop_connection (const struct ddsi_guid *rd_guid, const struc struct rd_pwr_match *m; ddsrt_mutex_lock (&rd->e.lock); if ((m = ddsrt_avl_lookup (&rd_writers_treedef, &rd->writers, &pwr->e.guid)) != NULL) + { ddsrt_avl_delete (&rd_writers_treedef, &rd->writers, m); + rd->num_writers--; + } + ddsrt_mutex_unlock (&rd->e.lock); if (m != NULL) { @@ -2005,7 +2035,7 @@ static void reader_drop_connection (const struct ddsi_guid *rd_guid, const struc (rd->status_cb) (rd->status_cb_entity, &data); } } - free_rd_pwr_match (pwr->e.gv, m); + free_rd_pwr_match (pwr->e.gv, &rd->e.guid, m); } } @@ -2122,7 +2152,7 @@ static void proxy_reader_drop_connection (const struct ddsi_guid *prd_guid, stru } } -static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) +static void writer_add_connection (struct writer *wr, struct proxy_reader *prd, int64_t crypto_handle) { struct wr_prd_match *m = ddsrt_malloc (sizeof (*m)); ddsrt_avl_ipath_t path; @@ -2134,6 +2164,11 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) m->all_have_replied_to_hb = 0; m->non_responsive_count = 0; m->rexmit_requests = 0; +#ifdef DDSI_INCLUDE_SECURITY + m->crypto_handle = crypto_handle; +#else + DDSRT_UNUSED_ARG(crypto_handle); +#endif /* m->demoted: see below */ ddsrt_mutex_lock (&prd->e.lock); if (prd->deleting) @@ -2179,6 +2214,7 @@ static void writer_add_connection (struct writer *wr, struct proxy_reader *prd) PGUID (wr->e.guid), PGUID (prd->e.guid), m->seq); ddsrt_avl_insert_ipath (&wr_readers_treedef, &wr->readers, m, &path); rebuild_writer_addrset (wr); + wr->num_readers++; wr->num_reliable_readers += m->is_reliable; ddsrt_mutex_unlock (&wr->e.lock); @@ -2275,7 +2311,7 @@ static void writer_add_local_connection (struct writer *wr, struct reader *rd) } } -static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, nn_count_t *init_count, const struct alive_state *alive_state) +static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, nn_count_t *init_count, const struct alive_state *alive_state, int64_t crypto_handle) { struct rd_pwr_match *m = ddsrt_malloc (sizeof (*m)); ddsrt_avl_ipath_t path; @@ -2283,6 +2319,11 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, m->pwr_guid = pwr->e.guid; m->pwr_alive = alive_state->alive; m->pwr_alive_vclock = alive_state->vclock; +#ifdef DDSI_INCLUDE_SECURITY + m->crypto_handle = crypto_handle; +#else + DDSRT_UNUSED_ARG(crypto_handle); +#endif ddsrt_mutex_lock (&rd->e.lock); @@ -2307,7 +2348,9 @@ static void reader_add_connection (struct reader *rd, struct proxy_writer *pwr, { ELOGDISC (rd, " reader_add_connection(pwr "PGUIDFMT" rd "PGUIDFMT")\n", PGUID (pwr->e.guid), PGUID (rd->e.guid)); + ddsrt_avl_insert_ipath (&rd_writers_treedef, &rd->writers, m, &path); + rd->num_writers++; ddsrt_mutex_unlock (&rd->e.lock); #ifdef DDSI_INCLUDE_SSM @@ -2390,7 +2433,7 @@ static void reader_add_local_connection (struct reader *rd, struct writer *wr, c } } -static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader *rd, nn_mtime_t tnow, nn_count_t init_count) +static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader *rd, nn_mtime_t tnow, nn_count_t init_count, int64_t crypto_handle) { struct pwr_rd_match *m = ddsrt_malloc (sizeof (*m)); ddsrt_avl_ipath_t path; @@ -2428,6 +2471,12 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader m->last_seq = 0; m->filtered = 0; +#ifdef DDSI_INCLUDE_SECURITY + m->crypto_handle = crypto_handle; +#else + DDSRT_UNUSED_ARG(crypto_handle); +#endif + /* These can change as a consequence of handling data and/or discovery activities. The safe way of dealing with them is to lock the proxy writer */ @@ -2525,12 +2574,18 @@ already_matched: -static void proxy_reader_add_connection (struct proxy_reader *prd, struct writer *wr) +static void proxy_reader_add_connection (struct proxy_reader *prd, struct writer *wr, int64_t crypto_handle) { struct prd_wr_match *m = ddsrt_malloc (sizeof (*m)); ddsrt_avl_ipath_t path; m->wr_guid = wr->e.guid; +#ifdef DDSI_INCLUDE_SECURITY + m->crypto_handle = crypto_handle; +#else + DDSRT_UNUSED_ARG(crypto_handle); +#endif + ddsrt_mutex_lock (&prd->e.lock); if (ddsrt_avl_lookup_ipath (&prd_writers_treedef, &prd->writers, &wr->e.guid, &path)) { @@ -2547,6 +2602,7 @@ static void proxy_reader_add_connection (struct proxy_reader *prd, struct writer ddsrt_avl_insert_ipath (&prd_writers_treedef, &prd->writers, m, &path); ddsrt_mutex_unlock (&prd->e.lock); qxev_prd_entityid (prd, &wr->e.guid); + } } @@ -2680,14 +2736,14 @@ static bool topickind_qos_match_p_lock (struct entity_common *rd, const dds_qos_ return ret; } -void connect_writer_with_proxy_reader_secure(struct writer *wr, struct proxy_reader *prd, nn_mtime_t tnow) +void connect_writer_with_proxy_reader_secure(struct writer *wr, struct proxy_reader *prd, nn_mtime_t tnow, int64_t crypto_handle) { DDSRT_UNUSED_ARG(tnow); - proxy_reader_add_connection (prd, wr); - writer_add_connection (wr, prd); + proxy_reader_add_connection (prd, wr, crypto_handle); + writer_add_connection (wr, prd, crypto_handle); } -void connect_reader_with_proxy_writer_secure(struct reader *rd, struct proxy_writer *pwr, nn_mtime_t tnow) +void connect_reader_with_proxy_writer_secure(struct reader *rd, struct proxy_writer *pwr, nn_mtime_t tnow, int64_t crypto_handle) { nn_count_t init_count; struct alive_state alive_state; @@ -2696,8 +2752,8 @@ void connect_reader_with_proxy_writer_secure(struct reader *rd, struct proxy_wri sensible, but that may be outdated by the time the reader gets added to the writer's list of matching readers. */ proxy_writer_get_alive_state (pwr, &alive_state); - reader_add_connection (rd, pwr, &init_count, &alive_state); - proxy_writer_add_connection (pwr, rd, tnow, init_count); + reader_add_connection (rd, pwr, &init_count, &alive_state, crypto_handle); + proxy_writer_add_connection (pwr, rd, tnow, init_count, crypto_handle); /* Once everything is set up: update with the latest state, any updates to the alive state happening in parallel will cause this to become a no-op. */ @@ -2710,6 +2766,8 @@ static void connect_writer_with_proxy_reader (struct writer *wr, struct proxy_re const int isb0 = (is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE) != 0); const int isb1 = (is_builtin_entityid (prd->e.guid.entityid, prd->c.vendor) != 0); dds_qos_policy_id_t reason; + int64_t crypto_handle; + DDSRT_UNUSED_ARG(tnow); if (isb0 != isb1) return; @@ -2726,15 +2784,15 @@ static void connect_writer_with_proxy_reader (struct writer *wr, struct proxy_re EELOGDISC (&wr->e, "connect_writer_with_proxy_reader (wr "PGUIDFMT") with (prd "PGUIDFMT") not allowed by security\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); } - else if (!q_omg_security_match_remote_reader_enabled (wr, prd)) + else if (!q_omg_security_match_remote_reader_enabled (wr, prd, &crypto_handle)) { EELOGDISC (&wr->e, "connect_writer_with_proxy_reader (wr "PGUIDFMT") with (prd "PGUIDFMT") waiting for approval by security\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); } else { - proxy_reader_add_connection (prd, wr); - writer_add_connection (wr, prd); + proxy_reader_add_connection (prd, wr, crypto_handle); + writer_add_connection (wr, prd, crypto_handle); } } @@ -2745,6 +2803,8 @@ static void connect_proxy_writer_with_reader (struct proxy_writer *pwr, struct r dds_qos_policy_id_t reason; nn_count_t init_count; struct alive_state alive_state; + int64_t crypto_handle; + if (isb0 != isb1) return; if (rd->e.onlylocal) @@ -2760,7 +2820,7 @@ static void connect_proxy_writer_with_reader (struct proxy_writer *pwr, struct r EELOGDISC (&rd->e, "connect_proxy_writer_with_reader (pwr "PGUIDFMT") with (rd "PGUIDFMT") not allowed by security\n", PGUID (pwr->e.guid), PGUID (rd->e.guid)); } - else if (!q_omg_security_match_remote_writer_enabled(rd, pwr)) + else if (!q_omg_security_match_remote_writer_enabled(rd, pwr, &crypto_handle)) { EELOGDISC (&rd->e, "connect_proxy_writer_with_reader (pwr "PGUIDFMT") with (rd "PGUIDFMT") waiting for approval by security\n", PGUID (pwr->e.guid), PGUID (rd->e.guid)); @@ -2771,8 +2831,8 @@ static void connect_proxy_writer_with_reader (struct proxy_writer *pwr, struct r sensible, but that may be outdated by the time the reader gets added to the writer's list of matching readers. */ proxy_writer_get_alive_state (pwr, &alive_state); - reader_add_connection (rd, pwr, &init_count, &alive_state); - proxy_writer_add_connection (pwr, rd, tnow, init_count); + reader_add_connection (rd, pwr, &init_count, &alive_state, crypto_handle); + proxy_writer_add_connection (pwr, rd, tnow, init_count, crypto_handle); /* Once everything is set up: update with the latest state, any updates to the alive state happening in parallel will cause this to become a no-op. */ @@ -3108,7 +3168,7 @@ static void update_proxy_participant_endpoint_matching (struct proxy_participant enum entity_kind mkind; guid.entityid = endpoint_ids[i]; - if ((e = entidx_lookup_guid_untyped(proxypp->e.gv->entity_index, &guid)) == NULL) + if ((e = entidx_lookup_guid_untyped(entidx, &guid)) == NULL) continue; mkind = generic_do_match_mkind (e->kind, false); @@ -3119,10 +3179,10 @@ static void update_proxy_participant_endpoint_matching (struct proxy_participant struct match_entities_range_key max; const char *tp = entity_topic_name (e); - entidx_enum_init_topic_w_prefix (&it, entidx, mkind, tp, &pp->e.guid.prefix, &max); + entidx_enum_init_topic(&it, entidx, mkind, tp, &max); while ((em = entidx_enum_next_max (&it, &max)) != NULL) { - if (&pp->e == get_entity_parent(e)) + if (&pp->e == get_entity_parent(em)) generic_do_match_connect (e, em, tnow, false); } entidx_enum_fini (&it); @@ -3498,6 +3558,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se wr->retransmitting = 0; wr->t_rexmit_end.v = 0; wr->t_whc_high_upd.v = 0; + wr->num_readers = 0; wr->num_reliable_readers = 0; wr->num_acks_received = 0; wr->num_nacks_received = 0; @@ -3511,6 +3572,9 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se wr->status_cb = status_cb; wr->status_cb_entity = status_entity; +#ifdef DDSI_INCLUDE_SECURITY + wr->sec_attr = NULL; +#endif /* Copy QoS, merging in defaults */ @@ -3646,8 +3710,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se wr->whc_low = wr->e.gv->config.whc_lowwater_mark; wr->whc_high = wr->e.gv->config.whc_init_highwater_mark.value; } - assert (!(wr->e.guid.entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER) - || + assert (!(is_builtin_entityid(wr->e.guid.entityid, NN_VENDORID_ECLIPSE) && !is_builtin_volatile_endpoint(wr->e.guid.entityid)) || (wr->whc_low == wr->whc_high && wr->whc_low == INT32_MAX)); /* Connection admin */ @@ -3679,6 +3742,10 @@ static dds_return_t new_writer_guid (struct writer **wr_out, const struct ddsi_g endpoint_common_init (&wr->e, &wr->c, pp->e.gv, EK_WRITER, guid, group_guid, pp, onlylocal); new_writer_guid_common_init(wr, topic, xqos, whc, status_cb, status_entity); +#ifdef DDSI_INCLUDE_SECURITY + q_omg_security_register_writer(wr); +#endif + /* entity_index needed for protocol handling, so add it before we send out our first message. Also: needed for matching, and swapping the order if hash insert & matching creates a window during which @@ -3745,6 +3812,16 @@ dds_return_t new_writer (struct writer **wr_out, struct ddsi_domaingv *gv, struc return DDS_RETCODE_BAD_PARAMETER; } +#ifdef DDSI_INCLUDE_SECURITY + /* Check if DDS Security is enabled */ + if (q_omg_participant_is_secure (pp)) + { + /* ask to access control security plugin for create writer permissions */ + if (!q_omg_security_check_create_writer (pp, gv->config.domainId, topic->name, xqos)) + return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY; + } +#endif + /* participant can't be freed while we're mucking around cos we are awake and do not touch the thread's vtime (entidx_lookup already verifies we're awake) */ @@ -3811,7 +3888,7 @@ static void gc_delete_writer (struct gcreq *gcreq) struct wr_prd_match *m = ddsrt_avl_root_non_empty (&wr_readers_treedef, &wr->readers); ddsrt_avl_delete (&wr_readers_treedef, &wr->readers, m); proxy_reader_drop_connection (&m->prd_guid, wr); - free_wr_prd_match (m); + free_wr_prd_match (wr->e.gv, &wr->e.guid, m); } while (!ddsrt_avl_is_empty (&wr->local_readers)) { @@ -3835,6 +3912,9 @@ static void gc_delete_writer (struct gcreq *gcreq) if (wr->status_cb) (wr->status_cb) (wr->status_cb_entity, NULL); +#ifdef DDSI_INCLUDE_SECURITY + q_omg_security_deregister_writer(wr); +#endif #ifdef DDSI_INCLUDE_SSM if (wr->ssm_as) unref_addrset (wr->ssm_as); @@ -3956,6 +4036,9 @@ dds_return_t delete_writer_nolinger (struct ddsi_domaingv *gv, const struct ddsi return DDS_RETCODE_BAD_PARAMETER; } GVLOGDISC ("delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (*guid)); +#ifdef DDSI_INCLUDE_SECURITY + q_omg_security_deregister_writer(wr); +#endif ddsrt_mutex_lock (&wr->e.lock); delete_writer_nolinger_locked (wr); ddsrt_mutex_unlock (&wr->e.lock); @@ -4174,8 +4257,12 @@ static dds_return_t new_reader_guid rd->ddsi2direct_cb = 0; rd->ddsi2direct_cbarg = 0; rd->init_acknack_count = 0; + rd->num_writers = 0; #ifdef DDSI_INCLUDE_SSM rd->favours_ssm = 0; +#endif +#ifdef DDSI_INCLUDE_SECURITY + rd->sec_attr = NULL; #endif if (topic == NULL) { @@ -4191,6 +4278,10 @@ static dds_return_t new_reader_guid } assert (rd->xqos->present & QP_LIVELINESS); +#ifdef DDSI_INCLUDE_SECURITY + q_omg_security_register_reader(rd); +#endif + #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS rd->as = new_addrset (); if (pp->e.gv->config.allowMulticast & ~AMC_SPDP) @@ -4282,6 +4373,17 @@ dds_return_t new_reader GVLOGDISC ("new_reader - participant "PGUIDFMT" not found\n", PGUID (*ppguid)); return DDS_RETCODE_BAD_PARAMETER; } + +#ifdef DDSI_INCLUDE_SECURITY + /* Check if DDS Security is enabled */ + if (q_omg_participant_is_secure (pp)) + { + /* ask to access control security plugin for create writer permissions */ + if (!q_omg_security_check_create_reader (pp, gv->config.domainId, topic->name, xqos)) + return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY; + } +#endif + rdguid->prefix = pp->e.guid.prefix; kind = topic->topickind_no_key ? NN_ENTITYID_KIND_READER_NO_KEY : NN_ENTITYID_KIND_READER_WITH_KEY; if ((rc = pp_allocate_entityid (&rdguid->entityid, kind, pp)) < 0) @@ -4301,7 +4403,7 @@ static void gc_delete_reader (struct gcreq *gcreq) struct rd_pwr_match *m = ddsrt_avl_root_non_empty (&rd_writers_treedef, &rd->writers); ddsrt_avl_delete (&rd_writers_treedef, &rd->writers, m); proxy_writer_drop_connection (&m->pwr_guid, rd); - free_rd_pwr_match (rd->e.gv, m); + free_rd_pwr_match (rd->e.gv, &rd->e.guid, m); } while (!ddsrt_avl_is_empty (&rd->local_writers)) { @@ -4311,6 +4413,10 @@ static void gc_delete_reader (struct gcreq *gcreq) free_rd_wr_match (m); } +#ifdef DDSI_INCLUDE_SECURITY + q_omg_security_deregister_reader(rd); +#endif + if (!is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE)) sedp_dispose_unregister_reader (rd); #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS @@ -4353,6 +4459,9 @@ dds_return_t delete_reader (struct ddsi_domaingv *gv, const struct ddsi_guid *gu GVLOGDISC ("delete_reader_guid(guid "PGUIDFMT") ...\n", PGUID (*guid)); builtintopic_write (rd->e.gv->builtin_topic_interface, &rd->e, now(), false); entidx_remove_reader_guid (gv->entity_index, rd); +#ifdef DDSI_INCLUDE_SECURITY + q_omg_security_deregister_reader(rd); +#endif gcreq_reader (rd); return 0; } @@ -4639,58 +4748,34 @@ static void proxy_participant_remove_pwr_lease_locked (struct proxy_participant #ifdef DDSI_INCLUDE_SECURITY -void handshake_end_cb -( - struct ddsi_domaingv const * const gv, - struct ddsi_handshake *handshake, - const struct ddsi_guid *lpguid, - const struct ddsi_guid *ppguid, - enum ddsi_handshake_state result) +void handshake_end_cb(struct ddsi_handshake *handshake, struct participant *pp, struct proxy_participant *proxypp, enum ddsi_handshake_state result) { - struct proxy_participant *proxypp; - struct participant *pp; + const struct ddsi_domaingv * const gv = pp->e.gv; int64_t shared_secret; - int64_t permissions_hdl; - - assert(handshake); - assert(lpguid); - assert(ppguid); - - assert(gv); - - proxypp = entidx_lookup_proxy_participant_guid (gv->entity_index, ppguid); - if (!proxypp) - return; - - pp = entidx_lookup_participant_guid (gv->entity_index, lpguid); - if (!pp) - return; switch(result) { case STATE_HANDSHAKE_PROCESSED: shared_secret = ddsi_handshake_get_shared_secret(handshake); - DDS_CLOG (DDS_LC_DISCOVERY, &gv->logconfig, "handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") processed\n", PGUID (*lpguid), PGUID (*ppguid)); - permissions_hdl = q_omg_security_check_remote_participant_permissions(gv->config.domainId, pp, proxypp); - if (permissions_hdl != 0) { - q_omg_security_register_remote_participant(pp, proxypp, shared_secret, permissions_hdl); + DDS_CLOG (DDS_LC_DISCOVERY, &gv->logconfig, "handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") processed\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid)); + if (q_omg_security_register_remote_participant(pp, proxypp, shared_secret)) { match_volatile_secure_endpoints(pp, proxypp); } break; case STATE_HANDSHAKE_SEND_TOKENS: - DDS_CLOG (DDS_LC_DISCOVERY, &gv->logconfig, "handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") send tokens\n", PGUID (*lpguid), PGUID (*ppguid)); + DDS_CLOG (DDS_LC_DISCOVERY, &gv->logconfig, "handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") send tokens\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid)); q_omg_security_participant_send_tokens(pp, proxypp); break; case STATE_HANDSHAKE_OK: - DDS_CLOG (DDS_LC_DISCOVERY, &gv->logconfig, "handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") succeeded\n", PGUID (*lpguid), PGUID (*ppguid)); + DDS_CLOG (DDS_LC_DISCOVERY, &gv->logconfig, "handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") succeeded\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid)); update_proxy_participant_endpoint_matching(proxypp, pp); ddsi_handshake_remove(pp, proxypp, handshake); break; case STATE_HANDSHAKE_TIMED_OUT: - DDS_CERROR (&gv->logconfig, "handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") failed: (%d) Timed out\n", PGUID (*lpguid), PGUID (*ppguid), (int)result); + DDS_CERROR (&gv->logconfig, "handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") failed: (%d) Timed out\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid), (int)result); if (q_omg_participant_allow_unauthenticated(pp)) { downgrade_to_nonsecure(proxypp); update_proxy_participant_endpoint_matching(proxypp, pp); @@ -4698,7 +4783,7 @@ void handshake_end_cb ddsi_handshake_remove(pp, proxypp, handshake); break; case STATE_HANDSHAKE_FAILED: - DDS_CERROR (&gv->logconfig, "handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") failed: (%d) Failed\n", PGUID (*lpguid), PGUID (*ppguid), (int)result); + DDS_CERROR (&gv->logconfig, "handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") failed: (%d) Failed\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid), (int)result); if (q_omg_participant_allow_unauthenticated(pp)) { downgrade_to_nonsecure(proxypp); update_proxy_participant_endpoint_matching(proxypp, pp); @@ -4706,7 +4791,7 @@ void handshake_end_cb ddsi_handshake_remove(pp, proxypp, handshake); break; default: - DDS_CERROR (&gv->logconfig, "handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") failed: (%d) Unknown failure\n", PGUID (*lpguid), PGUID (*ppguid), (int)result); + DDS_CERROR (&gv->logconfig, "handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") failed: (%d) Unknown failure\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid), (int)result); ddsi_handshake_remove(pp, proxypp, handshake); break; } @@ -4729,22 +4814,37 @@ static int proxy_participant_check_security_info(struct ddsi_domaingv *gv, struc return r; } - static void proxy_participant_create_handshakes(struct ddsi_domaingv *gv, struct proxy_participant *proxypp) { struct participant *pp; struct entidx_enum_participant est; + q_omg_security_remote_participant_set_initialized(proxypp); + entidx_enum_participant_init (&est, gv->entity_index); while (((pp = entidx_enum_participant_next (&est)) != NULL)) { - if (q_omg_participant_is_secure(pp)) - { + if (q_omg_security_participant_is_initialized(pp)) ddsi_handshake_register(pp, proxypp, handshake_end_cb); - } } entidx_enum_participant_fini(&est); } +static void disconnect_proxy_participant_secure(struct proxy_participant *proxypp) +{ + struct participant *pp; + struct entidx_enum_participant it; + struct ddsi_domaingv * const gv = proxypp->e.gv; + + if (q_omg_proxy_participant_is_secure(proxypp)) + { + entidx_enum_participant_init (&it, gv->entity_index); + while ((pp = entidx_enum_participant_next (&it)) != NULL) + { + ddsi_handshake_remove(pp, proxypp, NULL); + } + entidx_enum_participant_fini (&it); + } +} #endif static void free_proxy_participant(struct proxy_participant *proxypp) @@ -4765,6 +4865,7 @@ static void free_proxy_participant(struct proxy_participant *proxypp) lease_free (proxypp->lease); } #ifdef DDSI_INCLUDE_SECURITY + disconnect_proxy_participant_secure(proxypp); q_omg_security_deregister_remote_participant(proxypp); #endif unref_addrset (proxypp->as_default); @@ -4870,7 +4971,6 @@ void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *pp ddsrt_avl_init (&proxypp_groups_treedef, &proxypp->groups); #ifdef DDSI_INCLUDE_SECURITY - proxypp->remote_identity_handle = 0; proxypp->sec_attr = NULL; set_proxy_participant_security_info (proxypp, plist); if (is_secure) @@ -4879,7 +4979,7 @@ void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *pp /* check if the proxy participant has a match with a local participant */ if (!proxy_participant_check_security_info (gv, proxypp)) { - GVWARNING ("Remote secure participant "PGUIDFMT" not allowed\n", PGUID (*ppguid)); + // GVWARNING ("Remote secure participant "PGUIDFMT" not allowed\n", PGUID (*ppguid)); free_proxy_participant (proxypp); return; } @@ -4903,7 +5003,9 @@ void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *pp #ifdef DDSI_INCLUDE_SECURITY if (is_secure) + { proxy_participant_create_handshakes (gv, proxypp); + } #endif } @@ -5399,7 +5501,10 @@ int new_proxy_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, pwr->ddsi2direct_cb = 0; pwr->ddsi2direct_cbarg = 0; +#ifdef DDSI_INCLUDE_SECURITY set_proxy_writer_security_info(pwr, plist); + q_omg_get_proxy_writer_security_info(pwr, plist, &(pwr->security_info)); +#endif local_reader_ary_init (&pwr->rdary); @@ -5678,11 +5783,14 @@ int new_proxy_reader (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, #endif prd->is_fict_trans_reader = 0; +#ifdef DDSI_INCLUDE_SECURITY set_proxy_reader_security_info(prd, plist); +#endif ddsrt_avl_init (&prd_writers_treedef, &prd->writers); #ifdef DDSI_INCLUDE_SECURITY + q_omg_get_proxy_reader_security_info(prd, plist, &(prd->security_info)); if (prd->e.guid.entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER) prd->filter = volatile_secure_data_filter; else @@ -5762,7 +5870,6 @@ static void gc_delete_proxy_reader (struct gcreq *gcreq) writer_drop_connection (&m->wr_guid, prd); free_prd_wr_match (m); } - 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 a140b33..ed8e8e2 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -57,6 +57,7 @@ #include "dds/ddsi/ddsi_raweth.h" #include "dds/ddsi/ddsi_mcgroup.h" #include "dds/ddsi/ddsi_serdata_default.h" +#include "dds/ddsi/ddsi_security_omg.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds__whc.h" @@ -1131,7 +1132,7 @@ int rtps_init (struct ddsi_domaingv *gv) 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->security_context, &gv->logconfig ); + q_omg_security_init(gv); #endif ddsrt_mutex_init (&gv->sertopics_lock); @@ -1482,7 +1483,7 @@ err_unicast_sockets: ddsi_xqos_fini (&gv->builtin_volatile_xqos_wr); ddsi_xqos_fini (&gv->builtin_volatile_xqos_rd); - q_omg_security_deinit( &gv->security_context ); + q_omg_security_deinit (gv); #endif ddsi_xqos_fini (&gv->builtin_endpoint_xqos_wr); ddsi_xqos_fini (&gv->builtin_endpoint_xqos_rd); @@ -1838,7 +1839,7 @@ void rtps_fini (struct ddsi_domaingv *gv) ddsi_xqos_fini (&gv->builtin_volatile_xqos_wr); ddsi_xqos_fini (&gv->builtin_volatile_xqos_rd); - q_omg_security_deinit( &gv->security_context); + q_omg_security_deinit (gv); #endif ddsi_xqos_fini (&gv->builtin_endpoint_xqos_wr); ddsi_xqos_fini (&gv->builtin_endpoint_xqos_rd); diff --git a/src/core/ddsi/src/q_misc.c b/src/core/ddsi/src/q_misc.c index 06a6a2c..dac4cbe 100644 --- a/src/core/ddsi/src/q_misc.c +++ b/src/core/ddsi/src/q_misc.c @@ -42,6 +42,11 @@ int WildcardOverlap(char * p1, char * p2) } #endif +bool guid_prefix_zero (const ddsi_guid_prefix_t *a) +{ + return a->u[0] == 0 && a->u[1] == 0 && a->u[2] == 0; +} + int guid_prefix_eq (const ddsi_guid_prefix_t *a, const ddsi_guid_prefix_t *b) { return a->u[0] == b->u[0] && a->u[1] == b->u[1] && a->u[2] == b->u[2]; diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 7cc6f7b..640436b 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -80,11 +80,6 @@ static void deliver_user_data_synchronously (struct nn_rsample_chain *sc, const static void maybe_set_reader_in_sync (struct proxy_writer *pwr, struct pwr_rd_match *wn, seqno_t last_deliv_seq) { - if (wn->filtered) - { - wn->in_sync = PRMSS_OUT_OF_SYNC; - return; - } switch (wn->in_sync) { case PRMSS_SYNC: @@ -99,12 +94,15 @@ static void maybe_set_reader_in_sync (struct proxy_writer *pwr, struct pwr_rd_ma } break; case PRMSS_OUT_OF_SYNC: - assert (nn_reorder_next_seq (wn->u.not_in_sync.reorder) <= nn_reorder_next_seq (pwr->reorder)); - if (pwr->have_seen_heartbeat && nn_reorder_next_seq (wn->u.not_in_sync.reorder) == nn_reorder_next_seq (pwr->reorder)) + if (!wn->filtered) { - ETRACE (pwr, " msr_in_sync("PGUIDFMT" out-of-sync to tlcatchup)", PGUID (wn->rd_guid)); - wn->in_sync = PRMSS_TLCATCHUP; - maybe_set_reader_in_sync (pwr, wn, last_deliv_seq); + assert (nn_reorder_next_seq (wn->u.not_in_sync.reorder) <= nn_reorder_next_seq (pwr->reorder)); + if (pwr->have_seen_heartbeat && nn_reorder_next_seq (wn->u.not_in_sync.reorder) == nn_reorder_next_seq (pwr->reorder)) + { + ETRACE (pwr, " msr_in_sync("PGUIDFMT" out-of-sync to tlcatchup)", PGUID (wn->rd_guid)); + wn->in_sync = PRMSS_TLCATCHUP; + maybe_set_reader_in_sync (pwr, wn, last_deliv_seq); + } } break; } @@ -1929,6 +1927,12 @@ static struct ddsi_serdata *remote_make_sample (struct ddsi_tkmap_instance **tk, failmsg = "no content"; else if (!(qos->present & PP_KEYHASH)) failmsg = "qos present but without keyhash"; + else if (q_omg_plist_keyhash_is_protected(qos)) + { + /* If the keyhash is protected, then it is forced to be an actual MD5 + * hash. This means the keyhash can't be decoded into a sample. */ + failmsg = "keyhash is protected"; + } else if ((sample = ddsi_serdata_from_keyhash (topic, &qos->keyhash)) == NULL) failmsg = "keyhash is MD5 and can't be converted to key value"; else @@ -3018,7 +3022,7 @@ static int handle_submsg_sequence case SMID_SEC_PREFIX: state = "parse:sec_prefix"; { - GVTRACE ("SEC_PREFIX"); + GVTRACE ("SEC_PREFIX "); if (!decode_SecPrefix(rst, submsg, submsg_size, end, &rst->src_guid_prefix, &rst->dst_guid_prefix, byteswap)) goto malformed; } diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 063d2a1..cdc7485 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -867,7 +867,7 @@ static void transmit_sample_unlocks_wr (struct nn_xpack *xp, struct writer *wr, assert((wr->heartbeat_xevent != NULL) == (whcst != NULL)); sz = ddsi_serdata_size (serdata); - if (sz > gv->config.fragment_size || !isnew || plist != NULL || prd != NULL) + if (sz > gv->config.fragment_size || !isnew || plist != NULL || prd != NULL || q_omg_writer_is_submessage_protected(wr)) { uint32_t nfrags; ddsrt_mutex_unlock (&wr->e.lock); diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index 41b91a7..3b3e22a 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -104,7 +104,8 @@ enum xeventkind_nt { XEVK_MSG, XEVK_MSG_REXMIT, - XEVK_ENTITYID + XEVK_ENTITYID, + XEVK_NT_CALLBACK }; struct untimed_listelem { @@ -131,6 +132,10 @@ struct xevent_nt /* xmsg is self-contained / relies on reference counts */ struct nn_xmsg *msg; } entityid; + struct { + void (*cb) (void *arg); + void *arg; + } callback; } u; }; @@ -972,12 +977,16 @@ static void handle_xevk_acknack (struct nn_xpack *xp, struct xevent *ev, nn_mtim if (addrset_any_uc (pwr->c.as, &loc) || addrset_any_mc (pwr->c.as, &loc)) { + struct participant *pp = NULL; seqno_t nack_seq; - struct participant *pp = NULL; - struct reader *rd = entidx_lookup_reader_guid(pwr->e.gv->entity_index, &ev->u.acknack.rd_guid); - if (rd) - pp = rd->c.pp; + if (q_omg_proxy_participant_is_secure(pwr->c.proxypp)) + { + struct reader *rd = entidx_lookup_reader_guid(pwr->e.gv->entity_index, &ev->u.acknack.rd_guid); + + if (rd) + pp = rd->c.pp; + } if ((msg = nn_xmsg_new (gv->xmsgpool, &ev->u.acknack.rd_guid, pp, ACKNACK_SIZE_MAX, NN_XMSG_KIND_CONTROL)) == NULL) goto outofmem; @@ -1303,6 +1312,9 @@ static void handle_individual_xevent_nt (struct xevent_nt *xev, struct nn_xpack case XEVK_ENTITYID: handle_xevk_entityid (xp, xev); break; + case XEVK_NT_CALLBACK: + xev->u.callback.cb (xev->u.callback.arg); + break; } ddsrt_free (xev); } @@ -1459,6 +1471,18 @@ void qxev_msg (struct xeventq *evq, struct nn_xmsg *msg) ddsrt_mutex_unlock (&evq->lock); } +void qxev_nt_callback (struct xeventq *evq, void (*cb) (void *arg), void *arg) +{ + struct xevent_nt *ev; + assert (evq); + ddsrt_mutex_lock (&evq->lock); + ev = qxev_common_nt (evq, XEVK_NT_CALLBACK); + ev->u.callback.cb = cb; + ev->u.callback.arg = arg; + qxev_insert_nt (ev); + ddsrt_mutex_unlock (&evq->lock); +} + void qxev_prd_entityid (struct proxy_reader *prd, const ddsi_guid_t *guid) { struct ddsi_domaingv * const gv = prd->e.gv; diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 695c47d..93a70a2 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -920,22 +920,31 @@ void nn_xmsg_setwriterseq_fragid (struct nn_xmsg *msg, const ddsi_guid_t *wrguid msg->kindspecific.data.wrfragid = wrfragid; } -void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len) +void *nn_xmsg_addpar_bo (struct nn_xmsg *m, nn_parameterid_t pid, size_t len, bool be) { +#define BO2U(x) (be ? ddsrt_toBE2u((x)) : (x)) + const size_t len4 = (len + 3) & ~(size_t)3; /* must alloc a multiple of 4 */ nn_parameter_t *phdr; char *p; assert (len4 < UINT16_MAX); /* FIXME: return error */ m->have_params = 1; phdr = nn_xmsg_append (m, NULL, sizeof (nn_parameter_t) + len4); - phdr->parameterid = pid; - phdr->length = (uint16_t) len4; + phdr->parameterid = BO2U(pid); + phdr->length = BO2U((uint16_t) len4); p = (char *) (phdr + 1); /* zero out padding bytes added to satisfy parameter alignment: this way valgrind can tell us where we forgot to initialize something */ while (len < len4) p[len++] = 0; return p; + +#undef BO2U +} + +void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len) +{ + return nn_xmsg_addpar_bo(m, pid, len, false); } void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serdata, bool force_md5) @@ -974,6 +983,11 @@ void nn_xmsg_addpar_sentinel (struct nn_xmsg * m) nn_xmsg_addpar (m, PID_SENTINEL, 0); } +void nn_xmsg_addpar_sentinel_bo (struct nn_xmsg * m, bool be) +{ + nn_xmsg_addpar_bo (m, PID_SENTINEL, 0, be); +} + int nn_xmsg_addpar_sentinel_ifparam (struct nn_xmsg * m) { if (m->have_params) @@ -1188,6 +1202,7 @@ static ssize_t nn_xpack_send_rtps(struct nn_xpack * xp, const nn_locator_t *loc) if (xp->sec_info.use_rtps_encoding) { ret = secure_conn_write( + xp->gv, xp->conn, loc, xp->niov, diff --git a/src/security/builtin_plugins/access_control/src/access_control_parser.c b/src/security/builtin_plugins/access_control/src/access_control_parser.c index fbf106c..efd72ef 100644 --- a/src/security/builtin_plugins/access_control/src/access_control_parser.c +++ b/src/security/builtin_plugins/access_control/src/access_control_parser.c @@ -958,8 +958,10 @@ static int permissions_element_open_cb(void *varg, uintptr_t parentinfo, uintptr { parser->current = new_element(ELEMENT_KIND_IGNORED, parser->current, sizeof(struct element)); /*if this is the first element in the IGNORED branch, then give warning for the user*/ +#if 0 if (parser->current->parent->kind != ELEMENT_KIND_IGNORED) printf("Warning: Unsupported element \"%s\" has been ignored in permissions file.\n", name); +#endif } else { diff --git a/src/security/builtin_plugins/authentication/src/auth_utils.c b/src/security/builtin_plugins/authentication/src/auth_utils.c index 54b2224..d2ec77a 100644 --- a/src/security/builtin_plugins/authentication/src/auth_utils.c +++ b/src/security/builtin_plugins/authentication/src/auth_utils.c @@ -1225,7 +1225,8 @@ get_trusted_ca_list ( const char* trusted_ca_dir, if( loading_result == DDS_SECURITY_VALIDATION_OK ){ ca_buffer_array[ca_buffer_array_size] = identityCA; ca_buffer_array_size++; - + } else { + DDS_Security_Exception_reset(ex); } } } diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index 09d3425..63f4a60 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -21,7 +21,6 @@ #include #include "authentication.h" #include "dds/ddsrt/heap.h" -#include "dds/ddsrt/avl.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_timed_cb.h" @@ -120,8 +119,8 @@ typedef enum { typedef enum { CREATEDREQUEST, CREATEDREPLY -} CreatedHandshakeStep_t; +} CreatedHandshakeStep_t; typedef struct SecurityObject SecurityObject; @@ -130,6 +129,7 @@ typedef void (*SecurityObjectDestructor)(SecurityObject *obj); struct SecurityObject { int64_t handle; SecurityObjectKind_t kind; + SecurityObjectDestructor destructor; }; @@ -146,35 +146,6 @@ struct SecurityObject { #define SECURITY_OBJECT_VALID(o,k) security_object_valid((SecurityObject *)(o), k) -struct LocalIdentityInfo; -struct HandshakeInfo; - -typedef struct RemoteIdentityInfo { - SecurityObject _parent; - uint32_t refc; - DDS_Security_GUID_t guid; - X509 *identityCert; - AuthenticationAlgoKind_t dsignAlgoKind; - AuthenticationAlgoKind_t kagreeAlgoKind; - DDS_Security_IdentityToken *remoteIdentityToken; - DDS_Security_OctetSeq pdata; - char *permissionsDocument; -} RemoteIdentityInfo; - -/* This structure contains the relation between a local and a remote identity - * The handle for this object is the same as the handle of the associated - * local identity object. The IdentityRelation object will be stored with the - * remote identity. - */ -typedef struct IdentityRelation { - SecurityObject _parent; - ddsrt_avl_node_t avlnode; - struct LocalIdentityInfo *localIdentity; - struct RemoteIdentityInfo *remoteIdentity; - AuthenticationChallenge *lchallenge; - AuthenticationChallenge *rchallenge; - struct HandshakeInfo *handshake; -} IdentityRelation; typedef struct LocalIdentityInfo { SecurityObject _parent; @@ -188,12 +159,36 @@ typedef struct LocalIdentityInfo { AuthenticationAlgoKind_t dsignAlgoKind; AuthenticationAlgoKind_t kagreeAlgoKind; char *permissionsDocument; - ddsrt_avl_tree_t relations; /* contains the IdentityRelation objects */ } LocalIdentityInfo; +typedef struct RemoteIdentityInfo { + SecurityObject _parent; + DDS_Security_GUID_t guid; + X509 *identityCert; + AuthenticationAlgoKind_t dsignAlgoKind; + AuthenticationAlgoKind_t kagreeAlgoKind; + DDS_Security_IdentityToken *remoteIdentityToken; + DDS_Security_OctetSeq pdata; + char *permissionsDocument; + struct ddsrt_hh *linkHash; /* contains the IdentityRelation objects */ +} RemoteIdentityInfo; + + +/* This structure contains the relation between a local and a remote identity + * The handle for this object is the same as the handle of the associated + * local identity object. The IdentityRelation object will be stored with the + * remote identity. + */ +typedef struct IdentityRelation { + SecurityObject _parent; + LocalIdentityInfo *localIdentity; + RemoteIdentityInfo *remoteIdentity; + AuthenticationChallenge *lchallenge; + AuthenticationChallenge *rchallenge; +} IdentityRelation; + typedef struct HandshakeInfo { SecurityObject _parent; - ddsrt_avl_node_t avlnode; IdentityRelation *relation; HashValue_t hash_c1; HashValue_t hash_c2; @@ -208,7 +203,6 @@ typedef struct dds_security_authentication_impl { ddsrt_mutex_t lock; struct ddsrt_hh *objectHash; struct ddsrt_hh *remoteGuidHash; - struct ddsrt_hh *handshakes; struct dds_security_timed_cb_data *timed_callbacks; struct dds_security_timed_dispatcher_t *dispatcher; X509Seq trustedCAList; @@ -221,11 +215,6 @@ typedef struct { } validity_cb_info; -static int compare_relation (const void *va, const void *vb); - -const ddsrt_avl_treedef_t relations_treedef = - DDSRT_AVL_TREEDEF_INITIALIZER_INDKEY (offsetof (struct IdentityRelation, avlnode), offsetof (struct IdentityRelation, remoteIdentity), compare_relation, 0); - static bool security_object_valid( SecurityObject *obj, @@ -233,7 +222,14 @@ security_object_valid( { if (!obj) return false; if (obj->kind != kind) return false; - if ((uintptr_t)obj->handle != (uintptr_t)obj) return false; + if (kind == SECURITY_OBJECT_KIND_IDENTITY_RELATION) { + IdentityRelation *relation = (IdentityRelation *)obj; + if (!relation->localIdentity || !relation->remoteIdentity || (ddsrt_address)obj->handle != (ddsrt_address)relation->localIdentity) { + return false; + } + } else if ((ddsrt_address)obj->handle != (ddsrt_address)obj) { + return false; + } return true; } @@ -269,31 +265,20 @@ security_object_find( template.handle = handle; - return (SecurityObject *) ddsrt_hh_lookup(hh, &template); -} - -static int compare_relation (const void *va, const void *vb) -{ - const struct RemoteIdentityInfo * ha = va; - const struct RemoteIdentityInfo * hb = vb; - - if (IDENTITY_HANDLE(ha) < IDENTITY_HANDLE(hb)) { - return -1; - } else if (IDENTITY_HANDLE(ha) > IDENTITY_HANDLE(hb)) { - return 1; - } - return 0; + return (SecurityObject *) ddsrt_hh_lookup(hh, &template);; } static void security_object_init( SecurityObject *obj, - SecurityObjectKind_t kind) + SecurityObjectKind_t kind, + SecurityObjectDestructor destructor) { assert(obj); obj->kind = kind; - obj->handle = (int64_t)(uintptr_t)obj; + obj->handle = (int64_t)(ddsrt_address)obj; + obj->destructor = destructor; } static void @@ -304,8 +289,25 @@ security_object_deinit( assert(obj); obj->handle = DDS_SECURITY_HANDLE_NIL; obj->kind = SECURITY_OBJECT_KIND_UNKNOWN; + obj->destructor = NULL; } +static void +security_object_free( + SecurityObject *obj) +{ + assert(obj); + if (obj && obj->destructor) { + obj->destructor(obj); + } +} + +static void +localIdentityInfoFree( + SecurityObject *obj); + + + static LocalIdentityInfo * localIdentityInfoNew( DDS_Security_DomainId domainId, @@ -327,7 +329,10 @@ localIdentityInfoNew( identity = ddsrt_malloc(sizeof(*identity)); memset(identity, 0, sizeof(*identity)); - security_object_init((SecurityObject *)identity, SECURITY_OBJECT_KIND_LOCAL_IDENTITY); + security_object_init((SecurityObject *)identity, SECURITY_OBJECT_KIND_LOCAL_IDENTITY, localIdentityInfoFree); + + + identity->domainId = domainId; identity->identityCert = identityCert; @@ -340,33 +345,31 @@ localIdentityInfoNew( memcpy(&identity->candidateGUID, candidate_participant_guid, sizeof(DDS_Security_GUID_t)); memcpy(&identity->adjustedGUID, adjusted_participant_guid, sizeof(DDS_Security_GUID_t)); - ddsrt_avl_init(&relations_treedef, &identity->relations); - return identity; } static void localIdentityInfoFree( - LocalIdentityInfo *info) + SecurityObject *obj) { - CHECK_OBJECT_KIND(info, SECURITY_OBJECT_KIND_LOCAL_IDENTITY); + LocalIdentityInfo *identity = (LocalIdentityInfo *)obj; - if (info) { - assert(ddsrt_avl_is_empty(&info->relations)); - ddsrt_avl_free(&relations_treedef, &info->relations, NULL); - if (info->identityCert) { - X509_free(info->identityCert); + CHECK_OBJECT_KIND(obj, SECURITY_OBJECT_KIND_LOCAL_IDENTITY); + + if (identity) { + if (identity->identityCert) { + X509_free(identity->identityCert); } - if (info->identityCA) { - X509_free(info->identityCA); + if (identity->identityCA) { + X509_free(identity->identityCA); } - if (info->privateKey) { - EVP_PKEY_free(info->privateKey); + if (identity->privateKey) { + EVP_PKEY_free(identity->privateKey); } - ddsrt_free(info->pdata._buffer); - ddsrt_free(info->permissionsDocument); - security_object_deinit((SecurityObject *)info); - ddsrt_free(info); + ddsrt_free(identity->pdata._buffer); + ddsrt_free(identity->permissionsDocument); + security_object_deinit((SecurityObject *)identity); + ddsrt_free(identity); } } @@ -405,6 +408,10 @@ find_remote_identity_by_guid( return (RemoteIdentityInfo *) ddsrt_hh_lookup(hh, &template); } +static void +remoteIdentityInfoFree( + SecurityObject *obj); + static RemoteIdentityInfo * remoteIdentityInfoNew( const DDS_Security_GUID_t *guid, @@ -418,39 +425,47 @@ remoteIdentityInfoNew( identity = ddsrt_malloc(sizeof(*identity)); memset(identity, 0, sizeof(*identity)); - security_object_init((SecurityObject *)identity, SECURITY_OBJECT_KIND_REMOTE_IDENTITY); + security_object_init((SecurityObject *)identity, SECURITY_OBJECT_KIND_REMOTE_IDENTITY, remoteIdentityInfoFree); memcpy(&identity->guid, guid, sizeof(DDS_Security_GUID_t)); - identity->refc = 0; identity->remoteIdentityToken = DDS_Security_DataHolder_alloc(); DDS_Security_DataHolder_copy(identity->remoteIdentityToken, remote_identity_token); identity->identityCert = NULL; identity->dsignAlgoKind = AUTH_ALGO_KIND_UNKNOWN; identity->kagreeAlgoKind = AUTH_ALGO_KIND_UNKNOWN; identity->permissionsDocument = ddsrt_strdup(""); + identity->linkHash = ddsrt_hh_new(32, security_object_hash, security_object_equal); return identity; } static void remoteIdentityInfoFree( - RemoteIdentityInfo *info) + SecurityObject *obj) { - CHECK_OBJECT_KIND(info, SECURITY_OBJECT_KIND_REMOTE_IDENTITY); + RemoteIdentityInfo *identity = (RemoteIdentityInfo *)obj; - if (info) { - assert(info->refc == 0); - if (info->identityCert) { - X509_free(info->identityCert); + CHECK_OBJECT_KIND(obj, SECURITY_OBJECT_KIND_REMOTE_IDENTITY); + + if (identity) { + if (identity->identityCert) { + X509_free(identity->identityCert); } - DDS_Security_DataHolder_free(info->remoteIdentityToken); - ddsrt_free(info->pdata._buffer); - ddsrt_free(info->permissionsDocument); - security_object_deinit((SecurityObject *)info); - ddsrt_free(info); + DDS_Security_DataHolder_free(identity->remoteIdentityToken); + + ddsrt_hh_free(identity->linkHash); + + ddsrt_free(identity->pdata._buffer); + ddsrt_free(identity->permissionsDocument); + security_object_deinit((SecurityObject *)identity); + ddsrt_free(identity); } } +static void +identityRelationFree( + SecurityObject *obj); + /* The IdentityRelation provides the association between a local and a remote * identity. This object manages the challenges which are created for * each association between a local and a remote identity. @@ -474,23 +489,24 @@ identityRelationNew( relation = ddsrt_malloc(sizeof(*relation)); memset(relation, 0, sizeof(*relation)); - security_object_init((SecurityObject *)relation, SECURITY_OBJECT_KIND_IDENTITY_RELATION); + security_object_init((SecurityObject *)relation, SECURITY_OBJECT_KIND_IDENTITY_RELATION, identityRelationFree); + relation->_parent.handle = SECURITY_OBJECT_HANDLE(localIdentity); relation->localIdentity = localIdentity; relation->remoteIdentity = remoteIdentity; - remoteIdentity->refc++; relation->lchallenge = lchallenge; relation->rchallenge = rchallenge; - relation->handshake = NULL; return relation; } static void identityRelationFree( - IdentityRelation *relation) + SecurityObject *obj) { - CHECK_OBJECT_KIND(relation, SECURITY_OBJECT_KIND_IDENTITY_RELATION); + IdentityRelation *relation = (IdentityRelation *)obj; + + CHECK_OBJECT_KIND(obj, SECURITY_OBJECT_KIND_IDENTITY_RELATION); if (relation) { ddsrt_free(relation->lchallenge); @@ -500,16 +516,27 @@ identityRelationFree( } } +static void +handshakeInfoFree( + SecurityObject *obj); + static HandshakeInfo * handshakeInfoNew( + LocalIdentityInfo *localIdentity, + RemoteIdentityInfo *remoteIdentity, IdentityRelation *relation) { HandshakeInfo *handshake; + assert(localIdentity); + assert(remoteIdentity); + + DDSRT_UNUSED_ARG(localIdentity); + DDSRT_UNUSED_ARG(remoteIdentity); handshake = ddsrt_malloc(sizeof(*handshake)); memset(handshake, 0, sizeof(*handshake)); - security_object_init((SecurityObject *)handshake, SECURITY_OBJECT_KIND_HANDSHAKE); + security_object_init((SecurityObject *)handshake, SECURITY_OBJECT_KIND_HANDSHAKE, handshakeInfoFree); handshake->relation = relation; handshake->shared_secret_handle_impl = NULL; @@ -519,14 +546,13 @@ handshakeInfoNew( static void handshakeInfoFree( - HandshakeInfo *handshake) + SecurityObject *obj) { - CHECK_OBJECT_KIND(handshake, SECURITY_OBJECT_KIND_HANDSHAKE); + HandshakeInfo *handshake = (HandshakeInfo *)obj; + + CHECK_OBJECT_KIND(obj, SECURITY_OBJECT_KIND_HANDSHAKE); if (handshake) { - assert(handshake->relation && handshake->relation->handshake == handshake); - handshake->relation->handshake = NULL; - if (handshake->ldh) { EVP_PKEY_free(handshake->ldh); } @@ -542,6 +568,48 @@ handshakeInfoFree( } } +static IdentityRelation * +find_identity_relation( + const RemoteIdentityInfo *remote, + int64_t lid) +{ + return (IdentityRelation *)security_object_find(remote->linkHash, lid); +} + +static void +remove_identity_relation( + RemoteIdentityInfo *remote, + IdentityRelation *relation) +{ + (void)ddsrt_hh_remove(remote->linkHash, relation); + security_object_free((SecurityObject *) relation); +} + +static HandshakeInfo * +find_handshake( + const dds_security_authentication_impl *auth, + int64_t localId, + int64_t remoteId) +{ + struct ddsrt_hh_iter it; + SecurityObject *obj; + IdentityRelation *relation; + HandshakeInfo *found = NULL; + + for (obj = ddsrt_hh_iter_first(auth->objectHash, &it); obj && !found; obj = ddsrt_hh_iter_next(&it)) { + if (obj->kind == SECURITY_OBJECT_KIND_HANDSHAKE) { + relation = ((HandshakeInfo *)obj)->relation; + assert(relation); + if ((SECURITY_OBJECT_HANDLE(relation->localIdentity) == localId) && + (SECURITY_OBJECT_HANDLE(relation->remoteIdentity) == remoteId)) { + found = (HandshakeInfo *)obj; + } + } + } + + return found; +} + static char * get_authentication_class_id( void) @@ -1287,6 +1355,8 @@ fill_auth_request_token( token->binary_properties._buffer->value._length = len; token->binary_properties._buffer->value._buffer = ddsrt_malloc(len); memcpy(token->binary_properties._buffer->value._buffer, challenge->value, len); + token->binary_properties._buffer->propagate = true; + } DDS_Security_ValidationResult_t @@ -1303,10 +1373,11 @@ validate_remote_identity( DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; dds_security_authentication_impl *impl = (dds_security_authentication_impl *) instance; SecurityObject *obj; - LocalIdentityInfo *linfo; - RemoteIdentityInfo *rinfo; - IdentityRelation *relation = NULL; + LocalIdentityInfo *localIdent; + RemoteIdentityInfo *remoteIdent; + IdentityRelation *relation; AuthenticationChallenge *lchallenge = NULL, *rchallenge = NULL; + int r; /* validate provided arguments */ if (!instance || !remote_identity_handle || !local_auth_request_token || !remote_identity_token || !remote_participant_guid) { @@ -1321,10 +1392,10 @@ validate_remote_identity( DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "validate_remote_identity: Invalid handle provided"); goto err_inv_handle; } - linfo = (LocalIdentityInfo *) obj; + localIdent = (LocalIdentityInfo *) obj; /* Check if the provided remote_identity_token is compatible */ - result = validate_remote_identity_token(linfo, remote_identity_token, ex); + result = validate_remote_identity_token(localIdent, remote_identity_token, ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_remote_identity_token; } @@ -1349,29 +1420,30 @@ validate_remote_identity( */ /* Check if the remote identity has already been validated by a previous validation request. */ - rinfo = find_remote_identity_by_guid(impl->remoteGuidHash, remote_participant_guid); - if (!rinfo) { - rinfo = remoteIdentityInfoNew(remote_participant_guid, remote_identity_token); - (void)ddsrt_hh_add(impl->remoteGuidHash, rinfo); - relation = identityRelationNew(linfo, rinfo, lchallenge, rchallenge); - (void)ddsrt_hh_add(impl->objectHash, relation); - ddsrt_avl_insert(&relations_treedef, &linfo->relations, relation); + remoteIdent = find_remote_identity_by_guid(impl->remoteGuidHash, remote_participant_guid); + if (!remoteIdent) { + remoteIdent = remoteIdentityInfoNew(remote_participant_guid, remote_identity_token); + (void)ddsrt_hh_add(impl->objectHash, remoteIdent); + (void)ddsrt_hh_add(impl->remoteGuidHash, remoteIdent); + relation = identityRelationNew(localIdent, remoteIdent, lchallenge, rchallenge); + (void)ddsrt_hh_add(remoteIdent->linkHash, relation); } else { - ddsrt_avl_ipath_t path; /* When the remote identity has already been validated before, check if the remote identity token matches with the existing one */ - if (!DDS_Security_DataHolder_equal(rinfo->remoteIdentityToken, remote_identity_token)) { + if (!DDS_Security_DataHolder_equal(remoteIdent->remoteIdentityToken, remote_identity_token)) { result = DDS_SECURITY_VALIDATION_FAILED; DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "validate_remote_identity: remote_identity_token does not match with previously received one"); goto err_inv_duplicate; } - relation = ddsrt_avl_lookup_ipath(&relations_treedef, &linfo->relations, rinfo, &path); + + relation = find_identity_relation(remoteIdent, SECURITY_OBJECT_HANDLE(localIdent)); if (!relation) { - relation = identityRelationNew(linfo, rinfo, lchallenge, rchallenge); - (void)ddsrt_hh_add(impl->objectHash, relation); - ddsrt_avl_insert_ipath(&relations_treedef, &linfo->relations, relation, &path); + relation = identityRelationNew(localIdent, remoteIdent, lchallenge, rchallenge); + r = ddsrt_hh_add(remoteIdent->linkHash, relation); + assert(r); + (void)r; } else { if (remote_auth_request_token) { assert(rchallenge); @@ -1392,9 +1464,9 @@ validate_remote_identity( DDS_Security_set_token_nil(local_auth_request_token); } - *remote_identity_handle = IDENTITY_HANDLE(relation); + *remote_identity_handle = IDENTITY_HANDLE(remoteIdent);; - if (memcmp(&linfo->adjustedGUID, &rinfo->guid, sizeof(DDS_Security_GUID_t)) < 0) { + if (memcmp(&localIdent->adjustedGUID, &remoteIdent->guid, sizeof(DDS_Security_GUID_t)) < 0) { result = DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_REQUEST; } else { result = DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE; @@ -1429,7 +1501,8 @@ begin_handshake_request( HandshakeInfo *handshake = NULL; IdentityRelation *relation = NULL; SecurityObject *obj; - LocalIdentityInfo *linfo; + LocalIdentityInfo *localIdent; + RemoteIdentityInfo *remoteIdent; EVP_PKEY *dhkey; DDS_Security_BinaryProperty_t *tokens; DDS_Security_BinaryProperty_t *c_id; @@ -1460,47 +1533,50 @@ begin_handshake_request( "begin_handshake_request: Invalid initiator_identity_handle provided"); goto err_inv_handle; } - linfo = (LocalIdentityInfo *) obj; + localIdent = (LocalIdentityInfo *) obj; obj = security_object_find(impl->objectHash, replier_identity_handle); - if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_IDENTITY_RELATION)) { + if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_REMOTE_IDENTITY)) { DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_request: Invalid replier_identity_handle provided"); goto err_inv_handle; } - relation = (IdentityRelation *)obj; - handshake = relation->handshake; + remoteIdent = (RemoteIdentityInfo *)obj; - result = get_certificate_contents(linfo->identityCert, &certData, &certDataSize, ex); + result = get_certificate_contents(localIdent->identityCert, &certData, &certDataSize, ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_alloc_cid; } + handshake = find_handshake(impl, SECURITY_OBJECT_HANDLE(localIdent), SECURITY_OBJECT_HANDLE(remoteIdent)); if (!handshake) { - handshake = handshakeInfoNew(relation); + relation = find_identity_relation(remoteIdent, SECURITY_OBJECT_HANDLE(localIdent)); + assert(relation); + handshake = handshakeInfoNew(localIdent, remoteIdent, relation); handshake->created_in = CREATEDREQUEST; - relation->handshake = handshake; - (void)ddsrt_hh_add(impl->handshakes, handshake); + (void)ddsrt_hh_add(impl->objectHash, handshake); created = 1; + } else { + relation = handshake->relation; + assert(relation); } - assert(handshake->relation == relation); - if (!handshake->ldh) { - result = generate_dh_keys(&dhkey, linfo->kagreeAlgoKind, ex); + result = generate_dh_keys(&dhkey, localIdent->kagreeAlgoKind, ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_gen_dh_keys; } + handshake->ldh = dhkey; } - result = dh_public_key_to_oct(handshake->ldh, linfo->kagreeAlgoKind, &dhPubKeyData, &dhPubKeyDataSize, ex); + result = dh_public_key_to_oct(handshake->ldh, localIdent->kagreeAlgoKind, &dhPubKeyData, &dhPubKeyDataSize, ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_get_public_key; } - if (linfo->pdata._length == 0) { - DDS_Security_OctetSeq_copy(&linfo->pdata, serialized_local_participant_data); + if (localIdent->pdata._length == 0) { + DDS_Security_OctetSeq_copy(&localIdent->pdata, serialized_local_participant_data); } tokens = DDS_Security_BinaryPropertySeq_allocbuf(8); @@ -1517,8 +1593,8 @@ begin_handshake_request( DDS_Security_BinaryProperty_set_by_ref(c_id, "c.id", certData, certDataSize); /* Store the permission document in the c.perm property */ - if (linfo->permissionsDocument) { - DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", linfo->permissionsDocument); + if (localIdent->permissionsDocument) { + DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", localIdent->permissionsDocument); } else { DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", ""); } @@ -1527,10 +1603,10 @@ begin_handshake_request( DDS_Security_BinaryProperty_set_by_value(c_pdata, "c.pdata", serialized_local_participant_data->_buffer, serialized_local_participant_data->_length); /* Set the used signing algorithm descriptor in c.dsign_algo */ - DDS_Security_BinaryProperty_set_by_string(c_dsign_algo, "c.dsign_algo", get_dsign_algo(linfo->dsignAlgoKind)); + DDS_Security_BinaryProperty_set_by_string(c_dsign_algo, "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); /* Set the used key algorithm descriptor in c.kagree_algo */ - DDS_Security_BinaryProperty_set_by_string(c_kagree_algo, "c.kagree_algo", get_kagree_algo(linfo->kagreeAlgoKind)); + DDS_Security_BinaryProperty_set_by_string(c_kagree_algo, "c.kagree_algo", get_kagree_algo(localIdent->kagreeAlgoKind)); /* Calculate the hash_c1 */ { @@ -1551,6 +1627,8 @@ begin_handshake_request( /* Set the challenge in challenge1 property */ DDS_Security_BinaryProperty_set_by_value(challenge, "challenge1", relation->lchallenge->value, sizeof(AuthenticationChallenge)); + (void)ddsrt_hh_add(impl->objectHash, handshake); + ddsrt_mutex_unlock(&impl->lock); handshake_message->class_id = ddsrt_strdup(AUTH_HANDSHAKE_REQUEST_TOKEN_ID); @@ -1565,8 +1643,8 @@ begin_handshake_request( err_get_public_key: err_gen_dh_keys: if (created) { - (void)ddsrt_hh_remove(impl->handshakes, handshake); - handshakeInfoFree(handshake); + (void)ddsrt_hh_remove(impl->objectHash, handshake); + security_object_free((SecurityObject *)handshake); } err_alloc_cid: ddsrt_free(certData); @@ -2424,8 +2502,8 @@ begin_handshake_reply( HandshakeInfo *handshake = NULL; IdentityRelation *relation = NULL; SecurityObject *obj; - LocalIdentityInfo *linfo; - RemoteIdentityInfo *rinfo; + LocalIdentityInfo *localIdent; + RemoteIdentityInfo *remoteIdent; EVP_PKEY *dhkeyLocal = NULL; DDS_Security_BinaryProperty_t *tokens; DDS_Security_BinaryProperty_t *c_id; @@ -2469,40 +2547,41 @@ begin_handshake_reply( "begin_handshake_reply: Invalid replier_identity_handle provided"); goto err_inv_handle; } - linfo = (LocalIdentityInfo *) obj; + localIdent = (LocalIdentityInfo *) obj; obj = security_object_find(impl->objectHash, initiator_identity_handle); - if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_IDENTITY_RELATION)) { + if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_REMOTE_IDENTITY)) { DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: Invalid initiator_identity_handle provided"); goto err_inv_handle; } - relation = (IdentityRelation *)obj; - rinfo = relation->remoteIdentity; - handshake = relation->handshake; + remoteIdent = (RemoteIdentityInfo *)obj; + handshake = find_handshake(impl, SECURITY_OBJECT_HANDLE(localIdent), SECURITY_OBJECT_HANDLE(remoteIdent)); if (!handshake) { - handshake = handshakeInfoNew(relation); - relation->handshake = handshake; + relation = find_identity_relation(remoteIdent, SECURITY_OBJECT_HANDLE(localIdent)); + assert(relation); + handshake = handshakeInfoNew(localIdent, remoteIdent, relation); handshake->created_in = CREATEDREPLY; - (void)ddsrt_hh_add(impl->handshakes, handshake); + (void)ddsrt_hh_add(impl->objectHash, handshake); created = 1; + } else { + relation = handshake->relation; + assert(relation); } - assert(handshake->relation == relation); - result = validate_handshake_request_token(handshake_message_in, handshake, &(impl->trustedCAList), ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_inv_token; } - result = get_certificate_contents(linfo->identityCert, &certData, &certDataSize, ex); + result = get_certificate_contents(localIdent->identityCert, &certData, &certDataSize, ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_alloc_cid; } if (!handshake->ldh) { - result = generate_dh_keys(&dhkeyLocal, rinfo->kagreeAlgoKind, ex); + result = generate_dh_keys(&dhkeyLocal, remoteIdent->kagreeAlgoKind, ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_gen_dh_keys; } @@ -2511,13 +2590,13 @@ begin_handshake_reply( EVP_PKEY_copy_parameters(handshake->rdh, handshake->ldh); } - result = dh_public_key_to_oct(handshake->ldh, rinfo->kagreeAlgoKind, &dhPubKeyData, &dhPubKeyDataSize, ex); + result = dh_public_key_to_oct(handshake->ldh, remoteIdent->kagreeAlgoKind, &dhPubKeyData, &dhPubKeyDataSize, ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_get_public_key; } - if (linfo->pdata._length == 0) { - DDS_Security_OctetSeq_copy(&linfo->pdata, serialized_local_participant_data); + if (localIdent->pdata._length == 0) { + DDS_Security_OctetSeq_copy(&localIdent->pdata, serialized_local_participant_data); } hash_c1_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "hash_c1"); @@ -2543,8 +2622,8 @@ begin_handshake_reply( certData = NULL; /* Store the permission document in the c.perm property */ - if (linfo->permissionsDocument) { - DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", linfo->permissionsDocument); + if (localIdent->permissionsDocument) { + DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", localIdent->permissionsDocument); } else { DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", ""); } @@ -2553,10 +2632,10 @@ begin_handshake_reply( DDS_Security_BinaryProperty_set_by_value(c_pdata, "c.pdata", serialized_local_participant_data->_buffer, serialized_local_participant_data->_length); /* Set the used signing algorithm descriptor in c.dsign_algo */ - DDS_Security_BinaryProperty_set_by_string(c_dsign_algo, "c.dsign_algo", get_dsign_algo(linfo->dsignAlgoKind)); + DDS_Security_BinaryProperty_set_by_string(c_dsign_algo, "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); /* Set the used key algorithm descriptor in c.kagree_algo */ - DDS_Security_BinaryProperty_set_by_string(c_kagree_algo, "c.kagree_algo", get_kagree_algo(rinfo->kagreeAlgoKind)); + DDS_Security_BinaryProperty_set_by_string(c_kagree_algo, "c.kagree_algo", get_kagree_algo(remoteIdent->kagreeAlgoKind)); /* Calculate the hash_c2 */ { @@ -2609,7 +2688,7 @@ begin_handshake_reply( binary_properties[4] = dh1; binary_properties[5] = hash_c1_val; - result = create_signature(linfo->privateKey, binary_properties, HANDSHAKE_SIGNATURE_CONTENT_SIZE , &sign, &signlen, ex); + result = create_signature(localIdent->privateKey, binary_properties, HANDSHAKE_SIGNATURE_CONTENT_SIZE , &sign, &signlen, ex); DDS_Security_BinaryProperty_free(hash_c1_val); DDS_Security_BinaryProperty_free(hash_c2_val); @@ -2620,12 +2699,15 @@ begin_handshake_reply( DDS_Security_BinaryProperty_set_by_ref(signature, "signature", sign, (uint32_t)signlen); } + (void)ddsrt_hh_add(impl->objectHash, handshake); + handshake_message_out->class_id = ddsrt_strdup(AUTH_HANDSHAKE_REPLY_TOKEN_ID); handshake_message_out->binary_properties._length = tokenSize; handshake_message_out->binary_properties._buffer = tokens; ddsrt_mutex_unlock(&impl->lock); + *handshake_handle = HANDSHAKE_HANDLE(handshake); if (result == DDS_SECURITY_VALIDATION_OK) { @@ -2642,8 +2724,8 @@ err_gen_dh_keys: err_alloc_cid: err_inv_token: if (created) { - (void)ddsrt_hh_remove(impl->handshakes, handshake); - handshakeInfoFree(handshake); + (void)ddsrt_hh_remove(impl->objectHash, handshake); + security_object_free((SecurityObject *)handshake); } err_inv_handle: ddsrt_mutex_unlock(&impl->lock); @@ -2651,6 +2733,7 @@ err_bad_param: return DDS_SECURITY_VALIDATION_FAILED; } + static bool generate_shared_secret( const HandshakeInfo *handshake, @@ -2716,6 +2799,9 @@ fail_ctx_new: return result; } + + + DDS_Security_ValidationResult_t process_handshake( dds_security_authentication *instance, @@ -2759,7 +2845,7 @@ process_handshake( ddsrt_mutex_lock(&impl->lock); - obj = security_object_find(impl->handshakes, handshake_handle); + obj = security_object_find(impl->objectHash, handshake_handle); if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_HANDSHAKE)) { DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, @@ -2847,6 +2933,7 @@ process_handshake( challenge2_ref->value._length); } + /* Calculate the signature */ { const DDS_Security_BinaryProperty_t * binary_properties[ HANDSHAKE_SIGNATURE_CONTENT_SIZE ]; @@ -2895,10 +2982,12 @@ process_handshake( goto err_inv_token; } + challenge2_ref_for_shared_secret = (DDS_Security_octet*)(handshake->relation->lchallenge); challenge1_ref_for_shared_secret = (DDS_Security_octet*)(handshake->relation->rchallenge); result = DDS_SECURITY_VALIDATION_OK; + break; default: ddsrt_mutex_unlock(&impl->lock); @@ -2931,9 +3020,10 @@ process_handshake( goto err_invalid_expiry; } else if( certExpiry != DDS_NEVER ){ add_validity_end_trigger( impl, - IDENTITY_HANDLE( handshake->relation ), + IDENTITY_HANDLE( handshake->relation->remoteIdentity ), certExpiry); } + } ddsrt_mutex_unlock(&impl->lock); @@ -2971,14 +3061,14 @@ DDS_Security_SharedSecretHandle get_shared_secret( } ddsrt_mutex_lock(&impl->lock); - obj = security_object_find(impl->handshakes, handshake_handle); + obj = security_object_find(impl->objectHash, handshake_handle); if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_HANDSHAKE)) { DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_handshake_handle: Invalid handle provided"); goto err_invalid_handle; } ddsrt_mutex_unlock(&impl->lock); - return (DDS_Security_SharedSecretHandle)(uintptr_t)((HandshakeInfo*)obj)->shared_secret_handle_impl; + return (DDS_Security_SharedSecretHandle)(ddsrt_address)((HandshakeInfo*)obj)->shared_secret_handle_impl; err_invalid_handle: @@ -3011,7 +3101,7 @@ get_authenticated_peer_credential_token( ddsrt_mutex_lock(&impl->lock); - handshake = (HandshakeInfo *) security_object_find(impl->handshakes, handshake_handle); + handshake = (HandshakeInfo *) security_object_find(impl->objectHash, handshake_handle); if (!handshake || !SECURITY_OBJECT_VALID(handshake, SECURITY_OBJECT_KIND_HANDSHAKE)) { DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, @@ -3136,15 +3226,18 @@ return_handshake_handle(dds_security_authentication *instance, } ddsrt_mutex_lock(&impl->lock); - obj = security_object_find(impl->handshakes, handshake_handle); + obj = security_object_find(impl->objectHash, handshake_handle); if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_HANDSHAKE)) { DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_handshake_handle: Invalid handle provided"); goto err_invalid_handle; } handshake = (HandshakeInfo *)obj; - (void)ddsrt_hh_remove(impl->handshakes, handshake); - handshakeInfoFree(handshake); + assert(handshake->relation); + + (void)ddsrt_hh_remove(impl->objectHash, obj); + security_object_free((SecurityObject *)handshake); + ddsrt_mutex_unlock(&impl->lock); return true; @@ -3155,63 +3248,56 @@ err_bad_param: return false; } -static void -release_remote_info( - dds_security_authentication_impl *impl, - RemoteIdentityInfo *info) -{ - if (--info->refc == 0) { - (void)ddsrt_hh_remove(impl->remoteGuidHash, info); - remoteIdentityInfoFree(info); - } -} static void invalidate_local_related_objects( dds_security_authentication_impl *impl, - LocalIdentityInfo *linfo) + LocalIdentityInfo *localIdent) { - IdentityRelation *relation; + struct ddsrt_hh_iter it; + SecurityObject *obj; - relation = ddsrt_avl_find_min(&relations_treedef, &linfo->relations); - while (relation) { - IdentityRelation *next = ddsrt_avl_find_succ(&relations_treedef, &linfo->relations, relation); + for (obj = ddsrt_hh_iter_first(impl->objectHash, &it); obj != NULL; obj = ddsrt_hh_iter_next(&it)) { + if (obj->kind == SECURITY_OBJECT_KIND_REMOTE_IDENTITY) { + RemoteIdentityInfo *remoteIdent = (RemoteIdentityInfo *)obj; + IdentityRelation *relation; + HandshakeInfo *handshake; - assert(relation->remoteIdentity); + handshake = find_handshake(impl, SECURITY_OBJECT_HANDLE(localIdent), SECURITY_OBJECT_HANDLE(remoteIdent)); + if (handshake) { + (void)ddsrt_hh_remove(impl->objectHash, handshake); + security_object_free((SecurityObject *) handshake); + } - if (relation->handshake) { - (void)ddsrt_hh_remove(impl->handshakes, relation->handshake); - handshakeInfoFree(relation->handshake); + relation = find_identity_relation(remoteIdent, SECURITY_OBJECT_HANDLE(localIdent)); + if (relation) { + remove_identity_relation(remoteIdent, relation); + } } - release_remote_info(impl, relation->remoteIdentity); - ddsrt_avl_delete(&relations_treedef, &linfo->relations, relation); - (void)ddsrt_hh_remove(impl->objectHash, relation); - identityRelationFree(relation); - relation = next; } - (void)ddsrt_hh_remove(impl->objectHash, linfo); - localIdentityInfoFree(linfo); } static void invalidate_remote_related_objects( dds_security_authentication_impl *impl, - IdentityRelation *relation) + RemoteIdentityInfo *remoteIdentity) { - assert(relation->remoteIdentity); - assert(relation->localIdentity); + struct ddsrt_hh_iter it; + IdentityRelation *relation; + HandshakeInfo *handshake; - if (relation->handshake) { - (void)ddsrt_hh_remove(impl->handshakes, relation->handshake); - handshakeInfoFree(relation->handshake); + for (relation = ddsrt_hh_iter_first(remoteIdentity->linkHash, &it); relation != NULL; relation = ddsrt_hh_iter_next(&it)) { + handshake = find_handshake(impl, SECURITY_OBJECT_HANDLE(relation->localIdentity), SECURITY_OBJECT_HANDLE(remoteIdentity)); + if (handshake) { + (void)ddsrt_hh_remove(impl->objectHash, handshake); + security_object_free((SecurityObject *) handshake); + } + + (void)ddsrt_hh_remove(remoteIdentity->linkHash, relation); + security_object_free((SecurityObject *) relation); } - release_remote_info(impl, relation->remoteIdentity); - ddsrt_avl_delete(&relations_treedef, &relation->localIdentity->relations, relation); - (void)ddsrt_hh_remove(impl->objectHash, relation); - identityRelationFree(relation); } - DDS_Security_boolean return_identity_handle( dds_security_authentication *instance, @@ -3221,8 +3307,8 @@ return_identity_handle( DDS_Security_boolean result = true; dds_security_authentication_impl *impl = (dds_security_authentication_impl *) instance; SecurityObject *obj; - LocalIdentityInfo *linfo; - IdentityRelation *relation; + LocalIdentityInfo *localIdent; + RemoteIdentityInfo *remoteIdent; /* validate provided arguments */ if (!instance || !identity_handle) { @@ -3245,12 +3331,17 @@ return_identity_handle( switch (obj->kind) { case SECURITY_OBJECT_KIND_LOCAL_IDENTITY: - linfo = (LocalIdentityInfo *) obj; - invalidate_local_related_objects(impl, linfo); + localIdent = (LocalIdentityInfo *) obj; + invalidate_local_related_objects(impl, localIdent); + (void)ddsrt_hh_remove(impl->objectHash, obj); + security_object_free(obj); break; - case SECURITY_OBJECT_KIND_IDENTITY_RELATION: - relation = (IdentityRelation *) obj; - invalidate_remote_related_objects(impl, relation); + case SECURITY_OBJECT_KIND_REMOTE_IDENTITY: + remoteIdent = (RemoteIdentityInfo *) obj; + invalidate_remote_related_objects(impl, remoteIdent); + (void)ddsrt_hh_remove(impl->remoteGuidHash, remoteIdent); + (void)ddsrt_hh_remove(impl->objectHash, obj); + security_object_free(obj); break; default: DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_identity_handle: Invalid handle provided"); @@ -3259,6 +3350,7 @@ return_identity_handle( } ddsrt_mutex_unlock(&impl->lock); + return result; err_invalid_handle: @@ -3279,8 +3371,10 @@ DDS_Security_boolean return_sharedsecret_handle( return true; } -int32_t init_authentication( const char *argument, void **context) +int32_t +init_authentication( const char *argument, void **context) { + dds_security_authentication_impl *authentication; DDSRT_UNUSED_ARG(argument); @@ -3296,31 +3390,51 @@ int32_t init_authentication( const char *argument, void **context) /* assign the interface functions */ authentication->base.validate_local_identity = &validate_local_identity; + authentication->base.get_identity_token = &get_identity_token; + authentication->base.get_identity_status_token = &get_identity_status_token; - authentication->base.set_permissions_credential_and_token = &set_permissions_credential_and_token; + + authentication->base.set_permissions_credential_and_token = + &set_permissions_credential_and_token; + authentication->base.validate_remote_identity = &validate_remote_identity; + authentication->base.begin_handshake_request = &begin_handshake_request; + authentication->base.begin_handshake_reply = &begin_handshake_reply; + authentication->base.process_handshake = &process_handshake; + authentication->base.get_shared_secret = &get_shared_secret; - authentication->base.get_authenticated_peer_credential_token = &get_authenticated_peer_credential_token; + + authentication->base.get_authenticated_peer_credential_token = + &get_authenticated_peer_credential_token; + authentication->base.set_listener = &set_listener; + authentication->base.return_identity_token = &return_identity_token; - authentication->base.return_identity_status_token = &return_identity_status_token; - authentication->base.return_authenticated_peer_credential_token = &return_authenticated_peer_credential_token; + + authentication->base.return_identity_status_token = + &return_identity_status_token; + + authentication->base.return_authenticated_peer_credential_token = + &return_authenticated_peer_credential_token; + authentication->base.return_handshake_handle = &return_handshake_handle; + authentication->base.return_identity_handle = &return_identity_handle; + authentication->base.return_sharedsecret_handle = &return_sharedsecret_handle; ddsrt_mutex_init(&authentication->lock); authentication->objectHash = ddsrt_hh_new(32, security_object_hash, security_object_equal); authentication->remoteGuidHash = ddsrt_hh_new(32, remote_guid_hash, remote_guid_equal); - authentication->handshakes = ddsrt_hh_new(32, security_object_hash, security_object_equal); memset( &authentication->trustedCAList, 0, sizeof(X509Seq)); + /* Initialize openssl */ OpenSSL_add_all_algorithms(); OpenSSL_add_all_ciphers(); @@ -3343,8 +3457,6 @@ err_mutex_failed: int32_t finalize_authentication(void *instance) { dds_security_authentication_impl *authentication = instance; - LocalIdentityInfo *linfo; - IdentityRelation *relation; if( authentication ){ ddsrt_mutex_lock(&authentication->lock); @@ -3352,37 +3464,25 @@ int32_t finalize_authentication(void *instance) dds_security_timed_dispatcher_free(authentication->timed_callbacks, authentication->dispatcher); dds_security_timed_cb_free(authentication->timed_callbacks); - if (authentication->objectHash) { - struct ddsrt_hh_iter it; - SecurityObject *obj; - for (obj = ddsrt_hh_iter_first(authentication->objectHash, &it); obj != NULL; obj = ddsrt_hh_iter_next(&it)) { - switch (obj->kind) { - case SECURITY_OBJECT_KIND_LOCAL_IDENTITY: - linfo = (LocalIdentityInfo *) obj; - invalidate_local_related_objects(authentication, linfo); - break; - case SECURITY_OBJECT_KIND_IDENTITY_RELATION: - relation = (IdentityRelation *) obj; - invalidate_remote_related_objects(authentication, relation); - break; - default: - break; - } - } - ddsrt_hh_free(authentication->objectHash); - } - if (authentication->remoteGuidHash) { ddsrt_hh_free(authentication->remoteGuidHash); } - if (authentication->handshakes) { - ddsrt_hh_free(authentication->handshakes); + if (authentication->objectHash) { + struct ddsrt_hh_iter it; + SecurityObject *obj; + for (obj = ddsrt_hh_iter_first(authentication->objectHash, &it); obj != NULL; obj = ddsrt_hh_iter_next(&it)) { + security_object_free(obj); + } + ddsrt_hh_free(authentication->objectHash); } free_ca_list_contents(&(authentication->trustedCAList)); + ddsrt_mutex_unlock(&authentication->lock); + ddsrt_mutex_destroy(&authentication->lock); + ddsrt_free((dds_security_authentication_impl*) instance); } diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_key_exchange.c b/src/security/builtin_plugins/cryptographic/src/crypto_key_exchange.c index f002ad7..59d19af 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_key_exchange.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_key_exchange.c @@ -71,21 +71,35 @@ static bool check_not_data_empty(const DDS_Security_OctetSeq *seq) return false; } -static bool check_crypto_keymaterial(const DDS_Security_KeyMaterial_AES_GCM_GMAC *keymat) +static bool check_crypto_keymaterial( + const dds_security_crypto_key_exchange_impl *impl, + const DDS_Security_KeyMaterial_AES_GCM_GMAC *keymat, + const int64_t handle) { - bool status; - + bool status = false; uint32_t transform_kind = CRYPTO_TRANSFORM_KIND(keymat->transformation_kind); uint32_t key_sz = CRYPTO_KEY_SIZE_BYTES(transform_kind); - status = (transform_kind >= CRYPTO_TRANSFORMATION_KIND_AES128_GMAC && transform_kind <= CRYPTO_TRANSFORMATION_KIND_AES256_GCM && - keymat->master_salt._length == key_sz && keymat->master_salt._buffer != NULL && check_not_data_empty(&keymat->master_salt) && - keymat->master_sender_key._length == key_sz && keymat->master_sender_key._buffer != NULL && check_not_data_empty(&keymat->master_sender_key)); - - if (status && CRYPTO_TRANSFORM_ID(keymat->receiver_specific_key_id)) + if (transform_kind != CRYPTO_TRANSFORMATION_KIND_NONE) { - status = (keymat->master_receiver_specific_key._length == key_sz && - keymat->master_receiver_specific_key._buffer != NULL && check_not_data_empty(&keymat->master_receiver_specific_key)); + status = (transform_kind <= CRYPTO_TRANSFORMATION_KIND_AES256_GCM && + keymat->master_salt._length == key_sz && keymat->master_salt._buffer != NULL && check_not_data_empty(&keymat->master_salt) && + keymat->master_sender_key._length == key_sz && keymat->master_sender_key._buffer != NULL && check_not_data_empty(&keymat->master_sender_key)); + + if (status && CRYPTO_TRANSFORM_ID(keymat->receiver_specific_key_id)) + { + status = (keymat->master_receiver_specific_key._length == key_sz && + keymat->master_receiver_specific_key._buffer != NULL && check_not_data_empty(&keymat->master_receiver_specific_key)); + } + } + else + { + const dds_security_crypto_key_factory *factory; + DDS_Security_ProtectionKind kind; + + factory = cryptography_get_crypto_key_factory(impl->crypto); + if (crypto_factory_get_protection_kind(factory, handle, &kind)) + status = (kind == DDS_SECURITY_PROTECTION_KIND_NONE); } return status; @@ -179,12 +193,34 @@ create_local_participant_crypto_tokens( tokens->_buffer[0].binary_properties._buffer[0].value._length = tokens->_buffer[0].binary_properties._buffer[0].value._maximum = length; tokens->_buffer[0].binary_properties._buffer[0].value._buffer = buffer; + tokens->_buffer[0].binary_properties._buffer[0].propagate = true; return true; fail_invalid_arg: return false; } + +static DDS_Security_boolean +allow_empty_tokens( + const dds_security_crypto_key_exchange_impl *impl, + const DDS_Security_ParticipantCryptoTokenSeq *tokens, + const int64_t handle) +{ + const dds_security_crypto_key_factory *factory; + DDS_Security_ProtectionKind kind; + + if (tokens->_length > 0) + return false; + + factory = cryptography_get_crypto_key_factory(impl->crypto); + if (crypto_factory_get_protection_kind(factory, handle, &kind)) + return (kind == DDS_SECURITY_PROTECTION_KIND_NONE); + + return false; +} + + static DDS_Security_boolean set_remote_participant_crypto_tokens( dds_security_crypto_key_exchange *instance, @@ -207,6 +243,9 @@ set_remote_participant_crypto_tokens( return false; } + if (allow_empty_tokens(impl, tokens, remote_id)) + return true; + if (!check_crypto_tokens(tokens)) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_CODE, 0, @@ -229,7 +268,7 @@ set_remote_participant_crypto_tokens( "set_remote_participant_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_MESSAGE); result = false; } - else if (!check_crypto_keymaterial(&remote_key_mat)) + else if (!check_crypto_keymaterial(impl, &remote_key_mat, remote_id)) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_CODE, 0, "set_remote_participant_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_MESSAGE); @@ -290,6 +329,7 @@ create_local_datawriter_crypto_tokens( tokens->_buffer[i].binary_properties._buffer[0].value._length = tokens->_buffer[i].binary_properties._buffer[0].value._maximum = length; tokens->_buffer[i].binary_properties._buffer[0].value._buffer = buffer; + tokens->_buffer[i].binary_properties._buffer[0].propagate = true; CRYPTO_OBJECT_RELEASE(key_mat[i]); } @@ -317,6 +357,9 @@ set_remote_datawriter_crypto_tokens( return false; } + if (allow_empty_tokens(impl, tokens, remote_writer_handle)) + return true; + if (!check_crypto_tokens(tokens)) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_CODE, 0, @@ -347,7 +390,7 @@ set_remote_datawriter_crypto_tokens( "set_remote_datawriter_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_MESSAGE); result = false; } - else if (!check_crypto_keymaterial(&remote_key_mat[i])) + else if (!check_crypto_keymaterial(impl, &remote_key_mat[i], remote_writer_handle)) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_CODE, 0, "set_remote_datawriter_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_MESSAGE); @@ -409,6 +452,7 @@ create_local_datareader_crypto_tokens( tokens->_buffer[0].binary_properties._buffer[0].value._length = tokens->_buffer[0].binary_properties._buffer[0].value._maximum = length; tokens->_buffer[0].binary_properties._buffer[0].value._buffer = buffer; + tokens->_buffer[0].binary_properties._buffer[0].propagate = true; CRYPTO_OBJECT_RELEASE(key_mat); } @@ -444,6 +488,9 @@ set_remote_datareader_crypto_tokens( return false; } + if (allow_empty_tokens(impl, tokens, remote_reader_handle)) + return true; + if (!check_crypto_tokens(tokens)) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_CODE, 0, @@ -466,7 +513,7 @@ set_remote_datareader_crypto_tokens( "set_remote_datareader_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_MESSAGE); result = false; } - else if (!check_crypto_keymaterial(&remote_key_mat)) + else if (!check_crypto_keymaterial(impl, &remote_key_mat, remote_reader_handle)) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_CODE, 0, "set_remote_datareader_crypto_tokens: " DDS_SECURITY_ERR_INVALID_CRYPTO_TOKEN_MESSAGE); diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c index e77c99c..61e3f9e 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c @@ -245,6 +245,7 @@ remove_relation_from_keymaterial( CryptoObject *remote_crypto) { endpoint_relation *relation; + relation = crypto_endpoint_relation_find_by_crypto(key_material->endpoint_relations, local_crypto, remote_crypto); if (relation) { @@ -258,24 +259,21 @@ remove_remote_writer_relation( dds_security_crypto_key_factory_impl *implementation, remote_datawriter_crypto *remote_writer) { - local_datareader_crypto *local_reader; remote_participant_crypto *remote_participant; participant_key_material *key_material; + DDSRT_UNUSED_ARG(implementation); + assert(remote_writer); remote_participant = remote_writer->participant; assert(remote_participant); - local_reader = (local_datareader_crypto *)crypto_object_table_find(implementation->crypto_objects, remote_writer->local_reader_handle); - if (local_reader) + + key_material = (participant_key_material *)crypto_object_table_find( + remote_participant->key_material, CRYPTO_OBJECT_HANDLE(remote_writer->local_reader->participant)); + if (key_material) { - key_material = (participant_key_material *)crypto_object_table_find( - remote_participant->key_material, CRYPTO_OBJECT_HANDLE(local_reader->participant)); - if (key_material) - { - remove_relation_from_keymaterial(key_material, (CryptoObject *)local_reader, (CryptoObject *)remote_writer); - CRYPTO_OBJECT_RELEASE(key_material); - } - CRYPTO_OBJECT_RELEASE(local_reader); + remove_relation_from_keymaterial(key_material, (CryptoObject *)remote_writer->local_reader, (CryptoObject *)remote_writer); + CRYPTO_OBJECT_RELEASE(key_material); } } @@ -284,24 +282,21 @@ remove_remote_reader_relation( dds_security_crypto_key_factory_impl *implementation, remote_datareader_crypto *remote_reader) { - local_datawriter_crypto *local_writer; remote_participant_crypto *remote_participant; participant_key_material *key_material; + DDSRT_UNUSED_ARG(implementation); + assert(remote_reader); remote_participant = remote_reader->participant; assert(remote_participant); - local_writer = (local_datawriter_crypto *)crypto_object_table_find(implementation->crypto_objects, remote_reader->local_writer_handle); - if (local_writer) + + key_material = (participant_key_material *)crypto_object_table_find( + remote_participant->key_material, CRYPTO_OBJECT_HANDLE(remote_reader->local_writer->participant)); + if (key_material) { - key_material = (participant_key_material *)crypto_object_table_find( - remote_participant->key_material, CRYPTO_OBJECT_HANDLE(local_writer->participant)); - if (key_material) - { - remove_relation_from_keymaterial(key_material, (CryptoObject *)local_writer, (CryptoObject *)remote_reader); - CRYPTO_OBJECT_RELEASE(key_material); - } - CRYPTO_OBJECT_RELEASE(local_writer); + remove_relation_from_keymaterial(key_material, (CryptoObject *)remote_reader->local_writer, (CryptoObject *)remote_reader); + CRYPTO_OBJECT_RELEASE(key_material); } } @@ -562,6 +557,7 @@ register_local_datawriter( crypto_object_table_insert(implementation->crypto_objects, (CryptoObject *)writer_crypto); CRYPTO_OBJECT_RELEASE(participant_crypto); CRYPTO_OBJECT_RELEASE(writer_crypto); + return writer_crypto->_parent.handle; err_random_generation: @@ -619,7 +615,7 @@ register_matched_remote_datareader( data_protectionKind = local_writer->data_protectionKind; metadata_protectionKind = local_writer->metadata_protectionKind; - reader_crypto = crypto_remote_datareader_crypto__new(remote_participant, metadata_protectionKind, data_protectionKind, local_datawriter_crypto_handle); + reader_crypto = crypto_remote_datareader_crypto__new(remote_participant, metadata_protectionKind, data_protectionKind, local_writer); /* check if the writer is BuiltinParticipantVolatileMessageSecureWriter */ if (local_writer->is_builtin_participant_volatile_message_secure_writer) @@ -667,6 +663,7 @@ register_matched_remote_datareader( CRYPTO_OBJECT_RELEASE(remote_participant); CRYPTO_OBJECT_RELEASE(local_writer); CRYPTO_OBJECT_RELEASE(reader_crypto); + return DATAREADER_CRYPTO_HANDLE(reader_crypto); err_random_generation: @@ -736,6 +733,7 @@ register_local_datareader( crypto_object_table_insert(implementation->crypto_objects, (CryptoObject *)reader_crypto); CRYPTO_OBJECT_RELEASE(participant_crypto); CRYPTO_OBJECT_RELEASE(reader_crypto); + return DATAREADER_CRYPTO_HANDLE(reader_crypto); err_random_generation: @@ -786,8 +784,7 @@ register_matched_remote_datawriter( goto err_invalid_parameter; } - writer_crypto = crypto_remote_datawriter_crypto__new(remote_participant, local_reader->metadata_protectionKind, - local_reader->data_protectionKind, local_datareader_crypto_handle); + writer_crypto = crypto_remote_datawriter_crypto__new(remote_participant, local_reader->metadata_protectionKind, local_reader->data_protectionKind, local_reader); /* check if the writer is BuiltinParticipantVolatileMessageSecureWriter */ if (local_reader->is_builtin_participant_volatile_message_secure_reader) @@ -833,6 +830,7 @@ register_matched_remote_datawriter( CRYPTO_OBJECT_RELEASE(remote_participant); CRYPTO_OBJECT_RELEASE(local_reader); CRYPTO_OBJECT_RELEASE(writer_crypto); + return DATAREADER_CRYPTO_HANDLE(writer_crypto); err_random_generation: @@ -983,6 +981,51 @@ void dds_security_crypto_key_factory__dealloc(dds_security_crypto_key_factory *i ddsrt_free(implementation); } + +bool +crypto_factory_get_protection_kind( + const dds_security_crypto_key_factory *factory, + int64_t handle, + DDS_Security_ProtectionKind *kind) +{ + const dds_security_crypto_key_factory_impl *impl = (const dds_security_crypto_key_factory_impl *)factory; + CryptoObject *obj; + bool result = true; + + obj = crypto_object_table_find(impl->crypto_objects, handle); + if (!obj) + { + return false; + } + + switch (obj->kind) + { + case CRYPTO_OBJECT_KIND_LOCAL_CRYPTO: + *kind = ((local_participant_crypto *)obj)->rtps_protection_kind; + break; + case CRYPTO_OBJECT_KIND_REMOTE_CRYPTO: + *kind = ((remote_participant_crypto *)obj)->rtps_protection_kind; + break; + case CRYPTO_OBJECT_KIND_LOCAL_WRITER_CRYPTO: + *kind = ((local_datawriter_crypto *)obj)->metadata_protectionKind; + break; + case CRYPTO_OBJECT_KIND_REMOTE_WRITER_CRYPTO: + *kind = ((remote_datawriter_crypto *)obj)->metadata_protectionKind; + break; + case CRYPTO_OBJECT_KIND_LOCAL_READER_CRYPTO: + *kind = ((local_datareader_crypto *)obj)->metadata_protectionKind; + break; + case CRYPTO_OBJECT_KIND_REMOTE_READER_CRYPTO: + *kind = ((remote_datareader_crypto *)obj)->metadata_protectionKind; + break; + default: + result = false; + break; + } + CRYPTO_OBJECT_RELEASE(obj); + return result; +} + bool crypto_factory_get_participant_crypto_tokens( const dds_security_crypto_key_factory *factory, @@ -1110,7 +1153,7 @@ crypto_factory_get_datawriter_crypto_tokens( goto err_inv_remote; } - if (remote_reader_crypto->local_writer_handle != local_writer_handle) + if (CRYPTO_OBJECT_HANDLE(remote_reader_crypto->local_writer) != local_writer_handle) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); @@ -1180,7 +1223,7 @@ crypto_factory_set_datawriter_crypto_tokens( goto err_inv_local; } - if (remote_writer_crypto->local_reader_handle != local_reader_handle) + if (CRYPTO_OBJECT_HANDLE(remote_writer_crypto->local_reader) != local_reader_handle) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); @@ -1254,7 +1297,7 @@ crypto_factory_get_datareader_crypto_tokens( goto err_inv_remote; } - if (remote_writer_crypto->local_reader_handle != local_reader_handle) + if (CRYPTO_OBJECT_HANDLE(remote_writer_crypto->local_reader) != local_reader_handle) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); @@ -1317,7 +1360,7 @@ crypto_factory_set_datareader_crypto_tokens( goto err_inv_local; } - if (remote_reader_crypto->local_writer_handle != local_writer_handle) + if (CRYPTO_OBJECT_HANDLE(remote_reader_crypto->local_writer) != local_writer_handle) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); @@ -1582,7 +1625,7 @@ crypto_factory_get_remote_writer_key_material( DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); goto err_inv_crypto; } - if (writer_crypto->local_reader_handle != reader_id) + if (CRYPTO_OBJECT_HANDLE(writer_crypto->local_reader) != reader_id) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); @@ -1646,7 +1689,7 @@ crypto_factory_get_remote_reader_key_material( DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); goto err_inv_crypto; } - if (reader_crypto->local_writer_handle != writer_id) + if (CRYPTO_OBJECT_HANDLE(reader_crypto->local_writer) != writer_id) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.h b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.h index 5818b37..2fec8d7 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.h +++ b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.h @@ -29,6 +29,11 @@ int generate_key_pairs( char **private_key, char **public_key); +bool crypto_factory_get_protection_kind( + const dds_security_crypto_key_factory *factory, + int64_t handle, + DDS_Security_ProtectionKind *kind); + bool crypto_factory_get_participant_crypto_tokens( const dds_security_crypto_key_factory *factory, DDS_Security_ParticipantCryptoHandle local_id, diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_objects.c b/src/security/builtin_plugins/cryptographic/src/crypto_objects.c index 8fa9a06..86b1ea0 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_objects.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_objects.c @@ -11,6 +11,7 @@ */ #include #include +#include #include "dds/ddsrt/heap.h" #include "dds/ddsrt/hopscotch.h" #include "dds/ddsrt/types.h" @@ -63,7 +64,9 @@ void crypto_object_free(CryptoObject *obj) CryptoObject * crypto_object_keep(CryptoObject *obj) { if (obj) + { ddsrt_atomic_inc32(&obj->refcount); + } return obj; } @@ -455,6 +458,7 @@ static void remote_datawriter_crypto__free(CryptoObject *obj) CRYPTO_OBJECT_RELEASE(datawriter_crypto->reader2writer_key_material); CRYPTO_OBJECT_RELEASE(datawriter_crypto->writer2reader_key_material[0]); CRYPTO_OBJECT_RELEASE(datawriter_crypto->writer2reader_key_material[1]); + CRYPTO_OBJECT_RELEASE(datawriter_crypto->local_reader); CRYPTO_OBJECT_RELEASE(datawriter_crypto->participant); crypto_object_deinit((CryptoObject *)datawriter_crypto); ddsrt_free(datawriter_crypto); @@ -462,14 +466,14 @@ static void remote_datawriter_crypto__free(CryptoObject *obj) } remote_datawriter_crypto * crypto_remote_datawriter_crypto__new(const remote_participant_crypto *participant, - DDS_Security_ProtectionKind meta_protection, DDS_Security_BasicProtectionKind data_protection, DDS_Security_DatareaderCryptoHandle local_reader_handle) + DDS_Security_ProtectionKind meta_protection, DDS_Security_BasicProtectionKind data_protection, local_datareader_crypto *local_reader) { remote_datawriter_crypto *writer_crypto = ddsrt_calloc(1, sizeof(*writer_crypto)); crypto_object_init((CryptoObject *)writer_crypto, CRYPTO_OBJECT_KIND_REMOTE_WRITER_CRYPTO, remote_datawriter_crypto__free); writer_crypto->participant = (remote_participant_crypto *)CRYPTO_OBJECT_KEEP(participant); writer_crypto->metadata_protectionKind = meta_protection; writer_crypto->data_protectionKind = data_protection; - writer_crypto->local_reader_handle = local_reader_handle; + writer_crypto->local_reader = (local_datareader_crypto *)CRYPTO_OBJECT_KEEP(local_reader); writer_crypto->is_builtin_participant_volatile_message_secure_writer = false; return writer_crypto; @@ -514,6 +518,7 @@ static void remote_datareader_crypto__free(CryptoObject *obj) CRYPTO_OBJECT_RELEASE(datareader_crypto->reader2writer_key_material); CRYPTO_OBJECT_RELEASE(datareader_crypto->writer2reader_key_material_message); CRYPTO_OBJECT_RELEASE(datareader_crypto->writer2reader_key_material_payload); + CRYPTO_OBJECT_RELEASE(datareader_crypto->local_writer); CRYPTO_OBJECT_RELEASE(datareader_crypto->participant); crypto_object_deinit((CryptoObject *)datareader_crypto); ddsrt_free(datareader_crypto); @@ -521,14 +526,14 @@ static void remote_datareader_crypto__free(CryptoObject *obj) } remote_datareader_crypto *crypto_remote_datareader_crypto__new(const remote_participant_crypto *participant, DDS_Security_ProtectionKind metadata_protectionKind, - DDS_Security_BasicProtectionKind data_protectionKind, DDS_Security_DatawriterCryptoHandle local_writer_handle) + DDS_Security_BasicProtectionKind data_protectionKind, local_datawriter_crypto *local_writer) { remote_datareader_crypto *reader_crypto = ddsrt_calloc(1, sizeof(*reader_crypto)); crypto_object_init((CryptoObject *)reader_crypto, CRYPTO_OBJECT_KIND_REMOTE_READER_CRYPTO, remote_datareader_crypto__free); reader_crypto->participant = (remote_participant_crypto *)CRYPTO_OBJECT_KEEP(participant); reader_crypto->metadata_protectionKind = metadata_protectionKind; reader_crypto->data_protectionKind = data_protectionKind; - reader_crypto->local_writer_handle = local_writer_handle; + reader_crypto->local_writer = (local_datawriter_crypto *)CRYPTO_OBJECT_KEEP(local_writer); reader_crypto->is_builtin_participant_volatile_message_secure_reader = false; return reader_crypto; diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_objects.h b/src/security/builtin_plugins/cryptographic/src/crypto_objects.h index 3edb6a4..9a55570 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_objects.h +++ b/src/security/builtin_plugins/cryptographic/src/crypto_objects.h @@ -165,7 +165,7 @@ typedef struct remote_datawriter_crypto master_key_material *reader2writer_key_material; master_key_material *writer2reader_key_material[2]; session_key_material *reader_session; /* reference to the session key used by the reader */ - DDS_Security_DatareaderCryptoHandle local_reader_handle; + struct local_datareader_crypto *local_reader; bool is_builtin_participant_volatile_message_secure_writer; } remote_datawriter_crypto; @@ -190,7 +190,7 @@ typedef struct remote_datareader_crypto master_key_material *writer2reader_key_material_message; master_key_material *writer2reader_key_material_payload; session_key_material *writer_session; /* reference to the session key used by the writer */ - DDS_Security_DatawriterCryptoHandle local_writer_handle; + local_datawriter_crypto *local_writer; bool is_builtin_participant_volatile_message_secure_reader; } remote_datareader_crypto; @@ -257,7 +257,7 @@ crypto_remote_datareader_crypto__new( const remote_participant_crypto *participant, DDS_Security_ProtectionKind metadata_protectionKind, DDS_Security_BasicProtectionKind data_protectionKind, - DDS_Security_DatawriterCryptoHandle local_writer_handle); + local_datawriter_crypto *local_writer); local_datareader_crypto * crypto_local_datareader_crypto__new( @@ -270,7 +270,7 @@ crypto_remote_datawriter_crypto__new( const remote_participant_crypto *participant, DDS_Security_ProtectionKind meta_protection, DDS_Security_BasicProtectionKind data_protection, - DDS_Security_DatareaderCryptoHandle local_reader_handle); + local_datareader_crypto *local_reader); CryptoObject * crypto_object_keep( diff --git a/src/security/builtin_plugins/tests/set_remote_datareader_crypto_tokens/src/set_remote_datareader_crypto_tokens_utests.c b/src/security/builtin_plugins/tests/set_remote_datareader_crypto_tokens/src/set_remote_datareader_crypto_tokens_utests.c index c8297bb..68e3448 100644 --- a/src/security/builtin_plugins/tests/set_remote_datareader_crypto_tokens/src/set_remote_datareader_crypto_tokens_utests.c +++ b/src/security/builtin_plugins/tests/set_remote_datareader_crypto_tokens/src/set_remote_datareader_crypto_tokens_utests.c @@ -149,6 +149,7 @@ register_local_datawriter(void) memset(&datawriter_security_attributes, 0, sizeof(DDS_Security_EndpointSecurityAttributes)); datawriter_security_attributes.is_discovery_protected = true; + datawriter_security_attributes.is_submessage_protected = true; local_writer_crypto = crypto->crypto_key_factory->register_local_datawriter( diff --git a/src/security/builtin_plugins/tests/set_remote_datawriter_crypto_tokens/src/set_remote_datawriter_crypto_tokens_utests.c b/src/security/builtin_plugins/tests/set_remote_datawriter_crypto_tokens/src/set_remote_datawriter_crypto_tokens_utests.c index 90c8112..a223604 100644 --- a/src/security/builtin_plugins/tests/set_remote_datawriter_crypto_tokens/src/set_remote_datawriter_crypto_tokens_utests.c +++ b/src/security/builtin_plugins/tests/set_remote_datawriter_crypto_tokens/src/set_remote_datawriter_crypto_tokens_utests.c @@ -141,6 +141,7 @@ static int register_local_datareader(void) memset(&datareader_properties, 0, sizeof(datareader_properties)); memset(&datareader_security_attributes, 0, sizeof(datareader_security_attributes)); datareader_security_attributes.is_discovery_protected = true; + datareader_security_attributes.is_submessage_protected = true; local_reader_crypto = crypto->crypto_key_factory->register_local_datareader( diff --git a/src/security/core/CMakeLists.txt b/src/security/core/CMakeLists.txt index 8719946..41ea708 100644 --- a/src/security/core/CMakeLists.txt +++ b/src/security/core/CMakeLists.txt @@ -53,7 +53,8 @@ target_include_directories(security_core if(BUILD_TESTING) add_subdirectory(tests) - add_subdirectory(tests/plugin_loading) +# Temporarily disabled because needs refractoring w.r.t. security implementation +# add_subdirectory(tests/plugin_loading) endif() install( diff --git a/src/security/core/include/dds/security/core/dds_security_utils.h b/src/security/core/include/dds/security/core/dds_security_utils.h index a66c4d3..d6a745e 100644 --- a/src/security/core/include/dds/security/core/dds_security_utils.h +++ b/src/security/core/include/dds/security/core/dds_security_utils.h @@ -26,8 +26,8 @@ typedef DDS_Security_long_long DDS_Security_Handle; typedef DDS_Security_LongLongSeq DDS_Security_HandleSeq; #define DDS_SECURITY_SEQUENCE_INIT {0, 0, NULL} -#define DDS_SECURITY_TOKEN_INIT {NULL, DDS_SECURITY_SEQUENCE_INIT, DDS_SECURITY_SEQUENCE_INIT} - +#define DDS_SECURITY_TOKEN_INIT {NULL, DDS_SECURITY_SEQUENCE_INIT, DDS_SECURITY_SEQUENCE_INIT} +#define DDS_SECURITY_EXCEPTION_INIT {NULL, 0, 0} typedef enum { DDS_SECURITY_CONFIG_ITEM_PREFIX_UNKNOWN, diff --git a/src/security/core/src/dds_security_fsm.c b/src/security/core/src/dds_security_fsm.c index ce1a2bb..8685ed0 100644 --- a/src/security/core/src/dds_security_fsm.c +++ b/src/security/core/src/dds_security_fsm.c @@ -49,7 +49,8 @@ struct dds_security_fsm { struct dds_security_fsm *next_fsm; struct dds_security_fsm *prev_fsm; - bool active; + bool busy; + bool deleting; struct dds_security_fsm_control *control; const dds_security_fsm_transition *transitions; uint32_t size; @@ -69,8 +70,10 @@ struct dds_security_fsm_control struct ddsi_domaingv *gv; struct dds_security_fsm *first_fsm; struct dds_security_fsm *last_fsm; - struct fsm_event *event_queue; + struct fsm_event *first_event; + struct fsm_event *last_event; ddsrt_fibheap_t timers; + ddsrt_thread_t tid; bool running; }; @@ -86,6 +89,68 @@ static int compare_timer_event (const void *va, const void *vb) return (a->endtime == b->endtime) ? 0 : (a->endtime < b->endtime) ? -1 : 1; } +static void append_event(struct dds_security_fsm_control *control, struct fsm_event *event) +{ + event->next = NULL; + event->prev = control->last_event; + if (control->last_event) + control->last_event->next = event; + else + control->first_event = event; + control->last_event = event; +} + +static void insert_event(struct dds_security_fsm_control *control, struct fsm_event *event) +{ + event->prev = NULL; + event->next = control->first_event; + if (control->first_event) + control->first_event->prev = event; + else + control->last_event = event; + control->first_event = event; +} + +static struct fsm_event *get_event(struct dds_security_fsm_control *control) +{ + struct fsm_event *event = control->first_event; + + if (event) + { + control->first_event = event->next; + if (event->next) + event->next->prev = NULL; + else + control->last_event = NULL; + event->next = NULL; + event->prev = NULL; + } + return event; +} + +static void remove_events(struct dds_security_fsm_control *control, struct dds_security_fsm *fsm) +{ + struct fsm_event *event = control->first_event; + + while (event) + { + struct fsm_event *next = event->next; + if (event->fsm == fsm) + { + if (event->prev) + event->prev->next = event->next; + else + control->first_event = event->next; + if (event->next) + event->next->prev = event->prev; + else + control->last_event = event->prev; + ddsrt_free(event); + } + event = next; + } +} + static void fsm_dispatch (struct dds_security_fsm *fsm, int event_id, bool lifo) { struct dds_security_fsm_control *control = fsm->control; @@ -103,26 +168,10 @@ static void fsm_dispatch (struct dds_security_fsm *fsm, int event_id, bool lifo) event->next = NULL; event->prev = NULL; - if (lifo) { - /* Insert event at the top of the event list */ - if (control->event_queue) { - control->event_queue->prev = event; - } - event->next = control->event_queue; - control->event_queue = event; - } else { - /* Insert FIFO event */ - if (control->event_queue) { - struct fsm_event *last = control->event_queue; - while (last->next != NULL ) { - last = last->next; - } - last->next = event; - event->prev = last; - } else { - control->event_queue = event; - } - } + if (lifo) + insert_event(control, event); + else + append_event(control, event); } static void set_state_timer (struct dds_security_fsm *fsm) @@ -142,16 +191,18 @@ static void clear_state_timer (struct dds_security_fsm *fsm) { struct dds_security_fsm_control *control = fsm->control; - if (fsm->current && fsm->state_timeout_event.endtime != DDS_NEVER) + if (fsm->state_timeout_event.endtime != DDS_NEVER) ddsrt_fibheap_delete (&timer_events_fhdef, &control->timers, &fsm->state_timeout_event); + fsm->state_timeout_event.endtime = DDS_NEVER; } static void clear_overall_timer (struct dds_security_fsm *fsm) { struct dds_security_fsm_control *control = fsm->control; - if (fsm->current && fsm->overall_timeout_event.endtime != DDS_NEVER) + if (fsm->overall_timeout_event.endtime != DDS_NEVER) ddsrt_fibheap_delete (&timer_events_fhdef, &control->timers, &fsm->overall_timeout_event); + fsm->overall_timeout_event.endtime = DDS_NEVER; } static dds_time_t first_timeout (struct dds_security_fsm_control *control) @@ -185,57 +236,57 @@ static void fsm_state_change (struct thread_state1 *ts1, struct dds_security_fsm int event_id = event->event_id; uint32_t i; - if (fsm->active) + if (fsm->debug_func) + fsm->debug_func (fsm, DDS_SECURITY_FSM_DEBUG_ACT_HANDLING, fsm->current, event_id, fsm->arg); + + for (i = 0; i < fsm->size; i++) { - if (fsm->debug_func) - fsm->debug_func (fsm, DDS_SECURITY_FSM_DEBUG_ACT_HANDLING, fsm->current, event_id, fsm->arg); - - for (i = 0; i < fsm->size; i++) + if ((fsm->transitions[i].begin == fsm->current) && (fsm->transitions[i].event_id == event_id)) { - if ((fsm->transitions[i].begin == fsm->current) && (fsm->transitions[i].event_id == event_id)) - { - clear_state_timer (fsm); - fsm->current = fsm->transitions[i].end; - set_state_timer (fsm); + clear_state_timer (fsm); + fsm->current = fsm->transitions[i].end; + set_state_timer (fsm); + fsm->busy = true; - ddsrt_mutex_unlock (&control->lock); + ddsrt_mutex_unlock (&control->lock); - thread_state_asleep (ts1); - if (fsm->transitions[i].func) - fsm->transitions[i].func (fsm, fsm->arg); - if (fsm->current && fsm->current->func) - fsm->current->func (fsm, fsm->arg); + thread_state_awake (ts1, control->gv); + if (fsm->transitions[i].func) + fsm->transitions[i].func (fsm, fsm->arg); + if (fsm->current && fsm->current->func) + fsm->current->func (fsm, fsm->arg); - thread_state_awake (ts1, control->gv); - ddsrt_mutex_lock (&control->lock); + thread_state_asleep (ts1); + ddsrt_mutex_lock (&control->lock); + fsm->busy = false; + if (!fsm->deleting) fsm_check_auto_state_change (fsm); - break; - } + else + ddsrt_cond_broadcast(&control->cond); + break; } } - else if (event_id == DDS_SECURITY_FSM_EVENT_DELETE) - fsm_delete (control, fsm); - } static void fsm_handle_timeout (struct dds_security_fsm_control *control, struct fsm_timer_event *timer_event) { struct dds_security_fsm *fsm = timer_event->fsm; - if (fsm->active) + switch (timer_event->kind) { - switch (timer_event->kind) - { - case FSM_TIMEOUT_STATE: - fsm_dispatch (fsm, DDS_SECURITY_FSM_EVENT_TIMEOUT, true); - break; - case FSM_TIMEOUT_OVERALL: - ddsrt_mutex_unlock (&control->lock); - if (fsm->overall_timeout_action) - fsm->overall_timeout_action (fsm, fsm->arg); - ddsrt_mutex_lock (&control->lock); - break; - } + case FSM_TIMEOUT_STATE: + fsm_dispatch (fsm, DDS_SECURITY_FSM_EVENT_TIMEOUT, true); + break; + case FSM_TIMEOUT_OVERALL: + fsm->busy = true; + ddsrt_mutex_unlock (&control->lock); + if (fsm->overall_timeout_action) + fsm->overall_timeout_action (fsm, fsm->arg); + ddsrt_mutex_lock (&control->lock); + fsm->busy = false; + if (fsm->deleting) + ddsrt_cond_broadcast(&control->cond); + break; } /* mark timer event as being processed */ @@ -245,17 +296,16 @@ static void fsm_handle_timeout (struct dds_security_fsm_control *control, struct static uint32_t handle_events (struct dds_security_fsm_control *control) { struct thread_state1 * const ts1 = lookup_thread_state (); + struct fsm_event *event; + + control->tid = ddsrt_thread_self(); + thread_state_awake (ts1, control->gv); ddsrt_mutex_lock (&control->lock); while (control->running) { - if (control->event_queue) + if ((event = get_event(control)) != NULL) { - struct fsm_event *event = control->event_queue; - - control->event_queue = event->next; - if (control->event_queue) - control->event_queue->prev = NULL; fsm_state_change (ts1, control, event); ddsrt_free (event); } @@ -288,7 +338,7 @@ void dds_security_fsm_set_timeout (struct dds_security_fsm *fsm, dds_security_fs assert(timeout > 0); ddsrt_mutex_lock (&fsm->control->lock); - if (fsm->active) + if (!fsm->deleting) { if (timeout != DDS_NEVER) { @@ -297,7 +347,7 @@ void dds_security_fsm_set_timeout (struct dds_security_fsm *fsm, dds_security_fs fsm->overall_timeout_event.endtime = ddsrt_time_add_duration(dds_time(), timeout); ddsrt_fibheap_insert (&timer_events_fhdef, &fsm->control->timers, &fsm->overall_timeout_event); if (fsm->overall_timeout_event.endtime < first_timeout(fsm->control)) - ddsrt_cond_signal (&fsm->control->cond); + ddsrt_cond_broadcast (&fsm->control->cond); } else clear_overall_timer (fsm); @@ -311,10 +361,10 @@ void dds_security_fsm_dispatch (struct dds_security_fsm *fsm, int32_t event_id, assert(fsm->control); ddsrt_mutex_lock (&fsm->control->lock); - if (fsm->active) + if (!fsm->deleting) { fsm_dispatch (fsm, event_id, prio); - ddsrt_cond_signal (&fsm->control->cond); + ddsrt_cond_broadcast (&fsm->control->cond); } ddsrt_mutex_unlock (&fsm->control->lock); } @@ -324,7 +374,6 @@ const dds_security_fsm_state * dds_security_fsm_current_state (struct dds_securi const dds_security_fsm_state *state; assert(fsm); - assert(fsm->active); ddsrt_mutex_lock (&fsm->control->lock); state = fsm->current; @@ -407,7 +456,8 @@ struct dds_security_fsm * dds_security_fsm_create (struct dds_security_fsm_contr fsm->overall_timeout_event.kind = FSM_TIMEOUT_OVERALL; fsm->overall_timeout_event.endtime = DDS_NEVER; fsm->overall_timeout_event.fsm = fsm; - fsm->active = true; + fsm->busy = false; + fsm->deleting = false; fsm->next_fsm = NULL; fsm->prev_fsm = NULL; fsm->control = control; @@ -425,16 +475,17 @@ dds_security_fsm_start (struct dds_security_fsm *fsm) dds_security_fsm_dispatch(fsm, DDS_SECURITY_FSM_EVENT_AUTO, false); } -static void fsm_deactivate (struct dds_security_fsm *fsm, bool gen_del_event) +static void fsm_deactivate (struct dds_security_fsm_control *control, struct dds_security_fsm *fsm) { - if (fsm->active) + fsm->deleting = true; + remove_events(control, fsm); + clear_state_timer (fsm); + clear_overall_timer (fsm); + fsm->current = NULL; + if (!ddsrt_thread_equal(control->tid, ddsrt_thread_self())) { - fsm->active = false; - clear_state_timer (fsm); - clear_overall_timer (fsm); - fsm->current = NULL; - if (gen_del_event) - fsm_dispatch (fsm, DDS_SECURITY_FSM_EVENT_DELETE, false); + while (fsm->busy) + ddsrt_cond_wait(&control->cond, &control->lock); } } @@ -447,14 +498,14 @@ void dds_security_fsm_free (struct dds_security_fsm *fsm) control = fsm->control; ddsrt_mutex_lock (&control->lock); - fsm_deactivate (fsm, true); + fsm_deactivate (control, fsm); ddsrt_mutex_unlock (&control->lock); } static void fsm_delete (struct dds_security_fsm_control *control, struct dds_security_fsm *fsm) { - fsm_deactivate (fsm, false); remove_fsm_from_list (control, fsm); + fsm_deactivate (control, fsm); ddsrt_free(fsm); } @@ -464,7 +515,8 @@ struct dds_security_fsm_control * dds_security_fsm_control_create (struct ddsi_d control = ddsrt_malloc (sizeof(*control)); control->running = false; - control->event_queue = NULL; + control->first_event = NULL; + control->last_event = NULL; control->first_fsm = NULL; control->last_fsm = NULL; control->gv = gv; @@ -486,12 +538,11 @@ void dds_security_fsm_control_free (struct dds_security_fsm_control *control) while ((fsm = control->first_fsm) != NULL) { control->first_fsm = fsm->next_fsm; - fsm_deactivate (fsm, false); - ddsrt_free (fsm); + fsm_delete (control, fsm); } - while ((event = control->event_queue) != NULL) + while ((event = control->first_event) != NULL) { - control->event_queue = event->next; + control->first_event = event->next; ddsrt_free (event); } @@ -520,7 +571,7 @@ void dds_security_fsm_control_stop (struct dds_security_fsm_control *control) ddsrt_mutex_lock (&control->lock); control->running = false; - ddsrt_cond_signal (&control->cond); + ddsrt_cond_broadcast (&control->cond); ddsrt_mutex_unlock (&control->lock); join_thread (control->ts); diff --git a/src/security/core/src/dds_security_utils.c b/src/security/core/src/dds_security_utils.c index 42610af..ea5a7d8 100644 --- a/src/security/core/src/dds_security_utils.c +++ b/src/security/core/src/dds_security_utils.c @@ -124,6 +124,7 @@ DDS_Security_BinaryProperty_set_by_value( bp->name = ddsrt_strdup(name); bp->value._length = length; bp->value._maximum = length; + bp->propagate = true; if (length) { bp->value._buffer = ddsrt_malloc(length); memcpy(bp->value._buffer, data, length); @@ -164,6 +165,7 @@ DDS_Security_BinaryProperty_set_by_ref( bp->value._length = length; bp->value._maximum = length; bp->value._buffer = data; + bp->propagate = true; } DDS_Security_BinaryPropertySeq * @@ -840,7 +842,7 @@ DDS_Security_Exception_set_with_openssl_error( void DDS_Security_Exception_reset( - DDS_Security_SecurityException *ex) + DDS_Security_SecurityException *ex) { if (ex) { if (ex->message) { @@ -855,7 +857,9 @@ DDS_Security_Exception_clean( DDS_Security_SecurityException *ex) { if (ex) { - memset(ex, 0, sizeof(DDS_Security_SecurityException)); + ex->code = 0; + ex->minor_code = 0; + ex->message = NULL; } } diff --git a/src/security/core/tests/plugin_loading/plugin_loading.c b/src/security/core/tests/plugin_loading/plugin_loading.c index b3d145d..09c6c0b 100644 --- a/src/security/core/tests/plugin_loading/plugin_loading.c +++ b/src/security/core/tests/plugin_loading/plugin_loading.c @@ -20,6 +20,7 @@ #include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/environ.h" #include "dds/ddsrt/heap.h" +#include "plugin_mock_common.h" //#include "dds/ddsi/ddsi_security_omg.h" #define FORCE_ENV @@ -87,7 +88,7 @@ static uint32_t found; static void logger(void *ptr, const dds_log_data_t *data) { char **expected = (char **) ptr; if (print_log) { - printf("%s\n", data->message); + fputs(data->message, stdout); } for (uint32_t i = 0; expected[i] != NULL; i++) { if (patmatch(expected[i], data->message)) { @@ -112,9 +113,9 @@ CU_Test(ddssec_security_plugin_loading, all_ok, .init = ddsrt_init, .fini = ddsr "" "" "" - "testtext_IdentityCertificate_testtext" - "testtext_IdentityCA_testtext" - "testtext_PrivateKey_testtext" + ""TEST_IDENTITY_CERTIFICATE_ALL_OK"" + ""TEST_CA_CERTIFICATE_ALL_OK"" + ""TEST_PRIVATE_KEY_ALL_OK"" "testtext_Password_testtext" "testtext_Dir_testtext" "" @@ -469,7 +470,7 @@ CU_Test(ddssec_security_plugin_loading, no_library_in_path, .init = ddsrt_init, #else dds_delete(participant); #endif - + CU_ASSERT_FATAL(found == 0xd || found == 0xe); dds_delete(participant); @@ -551,13 +552,13 @@ CU_Test(ddssec_security_plugin_loading, all_ok_with_props, .init = ddsrt_init, . dds_entity_t participant; dds_qos_t * qos; - - + + /* Set up the trace sinks to detect the config parsing. */ dds_set_log_mask(DDS_LC_INFO); dds_set_log_sink(&logger, (void*)log_expected); dds_set_trace_sink(&logger, (void*)log_expected); - + /* Create the qos */ unsigned char bvalue[3] = { 0x01, 0x02, 0x03 }; CU_ASSERT_FATAL ((qos = dds_create_qos()) != NULL); diff --git a/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok/mock_authentication.c b/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok/mock_authentication.c index cfe680a..03f9666 100644 --- a/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok/mock_authentication.c +++ b/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok/mock_authentication.c @@ -28,6 +28,11 @@ typedef struct dds_security_authentication_impl { int id; //sample internal member } dds_security_authentication_impl; + +static const char *test_identity_certificate = TEST_IDENTITY_CERTIFICATE_ALL_OK; +static const char *test_ca_certificate = TEST_CA_CERTIFICATE_ALL_OK; +static const char *test_private_key = TEST_PRIVATE_KEY_ALL_OK; + DDS_Security_ValidationResult_t validate_local_identity( dds_security_authentication *instance, DDS_Security_IdentityHandle *local_identity_handle, @@ -76,14 +81,17 @@ DDS_Security_ValidationResult_t validate_local_identity( } if( strcmp(identity_certificate, test_identity_certificate) != 0){ - + printf("identity received=%s\n", identity_certificate); + printf("identity expected=%s\n", test_identity_certificate); result = DDS_SECURITY_VALIDATION_FAILED; printf("FAILED: Could not get identity_certificate value properly\n"); } else if( strcmp(identity_ca, test_ca_certificate) != 0){ + printf("ca received=%s\n", identity_ca); + printf("ca expected=%s\n", test_ca_certificate); printf("FAILED: Could not get identity_ca value properly\n"); result = DDS_SECURITY_VALIDATION_FAILED; - }else if( strcmp(private_key, test_privatekey) != 0){ + }else if( strcmp(private_key, test_private_key) != 0){ printf("FAILED: Could not get private_key value properly\n"); result = DDS_SECURITY_VALIDATION_FAILED; } diff --git a/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok/mock_authentication.h b/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok/mock_authentication.h index 56d297c..bb4479f 100644 --- a/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok/mock_authentication.h +++ b/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok/mock_authentication.h @@ -9,6 +9,7 @@ #define SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ #include "dds/security/authentication_all_ok_export.h" +#include "../../plugin_mock_common.h" SECURITY_EXPORT int32_t init_authentication(const char *argument, void **context); @@ -16,83 +17,6 @@ init_authentication(const char *argument, void **context); SECURITY_EXPORT int32_t finalize_authentication(void *context); -char *test_identity_certificate="data:,-----BEGIN CERTIFICATE-----\n\ -MIIDYDCCAkigAwIBAgIBBDANBgkqhkiG9w0BAQsFADByMQswCQYDVQQGEwJOTDEL\n\ -MAkGA1UECBMCT1YxEzARBgNVBAoTCkFETGluayBJU1QxGTAXBgNVBAMTEElkZW50\n\ -aXR5IENBIFRlc3QxJjAkBgkqhkiG9w0BCQEWF2luZm9AaXN0LmFkbGlua3RlY2gu\n\ -Y29tMB4XDTE4MDMxMjAwMDAwMFoXDTI3MDMxMTIzNTk1OVowdTELMAkGA1UEBhMC\n\ -TkwxCzAJBgNVBAgTAk9WMRAwDgYDVQQKEwdBRExpbmsgMREwDwYDVQQLEwhJU1Qg\n\ -VGVzdDETMBEGA1UEAxMKQWxpY2UgVGVzdDEfMB0GCSqGSIb3DQEJARYQYWxpY2VA\n\ -YWRsaW5rLmlzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANBW+tEZ\n\ -Baw7EQCEXyzH9n7IkZ8PQIKe8hG1LAOGYOF/oUYQZJO/HxbWoC4rFqOC20+A6is6\n\ -kFwr1Zzp/Wurk9CrFXo5Nomi6ActH6LUM57nYqN68w6U38z/XkQxVY/ESZ5dySfD\n\ -9Q1C8R+zdE8gwbimdYmwX7ioz336nghM2CoAHPDRthQeJupl8x4V7isOltr9CGx8\n\ -+imJXbGr39OK6u87cNLeu23sUkOIC0lSRMIqIQK3oJtHS70J2qecXdqp9MhE7Xky\n\ -/GPlI8ptQ1gJ8A3cAOvtI9mtMJMszs2EKWTLfeTcmfJHKKhKjvCgDdh3Jan4x5YP\n\ -Yg7HG6H+ceOUkMMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAkvuqZzyJ3Nu4/Eo5\n\ -kD0nVgYGBUl7cspu+636q39zPSrxLEDMUWz+u8oXLpyGcgiZ8lZulPTV8dmOn+3C\n\ -Vg55c5C+gbnbX3MDyb3wB17296RmxYf6YNul4sFOmj6+g2i+Dw9WH0PBCVKbA84F\n\ -jR3Gx2Pfoifor3DvT0YFSsjNIRt090u4dQglbIb6cWEafC7O24t5jFhGPvJ7L9SE\n\ -gB0Drh/HmKTVuaqaRkoOKkKaKuWoXsszK1ZFda1DHommnR5LpYPsDRQ2fVM4EuBF\n\ -By03727uneuG8HLuNcLEV9H0i7LxtyfFkyCPUQvWG5jehb7xPOz/Ml26NAwwjlTJ\n\ -xEEFrw==\n\ ------END CERTIFICATE-----"; - -char *test_ca_certificate="data:,-----BEGIN CERTIFICATE-----\n\ -MIIEKTCCAxGgAwIBAgIBATANBgkqhkiG9w0BAQsFADByMQswCQYDVQQGEwJOTDEL\n\ -MAkGA1UECBMCT1YxEzARBgNVBAoTCkFETGluayBJU1QxGTAXBgNVBAMTEElkZW50\n\ -aXR5IENBIFRlc3QxJjAkBgkqhkiG9w0BCQEWF2luZm9AaXN0LmFkbGlua3RlY2gu\n\ -Y29tMB4XDTE4MDMxMjAwMDAwMFoXDTI3MDMxMTIzNTk1OVowcjELMAkGA1UEBhMC\n\ -TkwxCzAJBgNVBAgTAk9WMRMwEQYDVQQKEwpBRExpbmsgSVNUMRkwFwYDVQQDExBJ\n\ -ZGVudGl0eSBDQSBUZXN0MSYwJAYJKoZIhvcNAQkBFhdpbmZvQGlzdC5hZGxpbmt0\n\ -ZWNoLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANa/ENFfGVXg\n\ -bPLTzBdDfiZQcp5dWZ//Pb8ErFOJu8uosVHFv8t69dgjHgNHB4OsjmjnR7GfKUZT\n\ -0cMvWJnjsC7DDlBwFET9rj4k40n96bbVCH9I7+tNhsoqzc6Eu+5h4sk7VfNGTM2Z\n\ -SyCd4GiSZRuA44rRbhXI7/LDpr4hY5J9ZDo5AM9ZyoLAoh774H3CZWD67S35XvUs\n\ -72dzE6uKG/vxBbvZ7eW2GLO6ewa9UxlnLVMPfJdpkp/xYXwwcPW2+2YXCge1ujxs\n\ -tjrOQJ5HUySh6DkE/kZpx8zwYWm9AaCrsvCIX1thsqgvKy+U5v1FS1L58eGc6s//\n\ -9yMgNhU29R0CAwEAAaOByTCBxjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRNVUJN\n\ -FzhJPReYT4QSx6dK53CXCTAfBgNVHSMEGDAWgBRNVUJNFzhJPReYT4QSx6dK53CX\n\ -CTAPBgNVHQ8BAf8EBQMDB/+AMGUGA1UdJQEB/wRbMFkGCCsGAQUFBwMBBggrBgEF\n\ -BQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkGCCsG\n\ -AQUFBwMNBggrBgEFBQcDDgYHKwYBBQIDBTANBgkqhkiG9w0BAQsFAAOCAQEAcOLF\n\ -ZYdJguj0uxeXB8v3xnUr1AWz9+gwg0URdfNLU2KvF2lsb/uznv6168b3/FcPgezN\n\ -Ihl9GqB+RvGwgXS/1UelCGbQiIUdsNxk246P4uOGPIyW32RoJcYPWZcpY+cw11tQ\n\ -NOnk994Y5/8ad1DmcxVLLqq5kwpXGWQufV1zOONq8B+mCvcVAmM4vkyF/de56Lwa\n\ -sAMpk1p77uhaDnuq2lIR4q3QHX2wGctFid5Q375DRscFQteY01r/dtwBBrMn0wuL\n\ -AMNx9ZGD+zAoOUaslpIlEQ+keAxk3jgGMWFMxF81YfhEnXzevSQXWpyek86XUyFL\n\ -O9IAQi5pa15gXjSbUg==\n\ ------END CERTIFICATE-----"; - -char *test_privatekey = "data:,-----BEGIN RSA PRIVATE KEY-----\n\ -MIIEowIBAAKCAQEA0Fb60RkFrDsRAIRfLMf2fsiRnw9Agp7yEbUsA4Zg4X+hRhBk\n\ -k78fFtagLisWo4LbT4DqKzqQXCvVnOn9a6uT0KsVejk2iaLoBy0fotQznudio3rz\n\ -DpTfzP9eRDFVj8RJnl3JJ8P1DULxH7N0TyDBuKZ1ibBfuKjPffqeCEzYKgAc8NG2\n\ -FB4m6mXzHhXuKw6W2v0IbHz6KYldsavf04rq7ztw0t67bexSQ4gLSVJEwiohAreg\n\ -m0dLvQnap5xd2qn0yETteTL8Y+Ujym1DWAnwDdwA6+0j2a0wkyzOzYQpZMt95NyZ\n\ -8kcoqEqO8KAN2HclqfjHlg9iDscbof5x45SQwwIDAQABAoIBAG0dYPeqd0IhHWJ7\n\ -8azufbchLMN1pX/D51xG2uptssfnpHuhkkufSZUYi4QipRS2ME6PYhWJ8pmTi6lH\n\ -E6cUkbI0KGd/F4U2gPdhNrR9Fxwea5bbifkVF7Gx/ZkRjZJiZ3w9+mCNTQbJDKhh\n\ -wITAzzT6WYznhvqbzzBX1fTa6kv0GAQtX7aHKM+XIwkhX2gzU5TU80bvH8aMrT05\n\ -tAMGQqkUeRnpo0yucBl4VmTZzd/+X/d2UyXR0my15jE5iH5o+p+E6qTRE9D+MGUd\n\ -MQ6Ftj0Untqy1lcog1ZLL6zPlnwcD4jgY5VCYDgvabnrSwymOJapPLsAEdWdq+U5\n\ -ec44BMECgYEA/+3qPUrd4XxA517qO3fCGBvf2Gkr7w5ZDeATOTHGuD8QZeK0nxPl\n\ -CWhRjdgkqo0fyf1cjczL5XgYayo+YxkO1Z4RUU+8lJAHlVx9izOQo+MTQfkwH4BK\n\ -LYlHxMoHJwAOXXoE+dmBaDh5xT0mDUGU750r763L6EFovE4qRBn9hxkCgYEA0GWz\n\ -rpOPNxb419WxG9npoQYdCZ5IbmEOGDH3ReggVzWHmW8sqtkqTZm5srcyDpqAc1Gu\n\ -paUveMblEBbU+NFJjLWOfwB5PCp8jsrqRgCQSxolShiVkc3Vu3oyzMus9PDge1eo\n\ -9mwVGO7ojQKWRu/WVAakENPaAjeyyhv4dqSNnjsCgYEAlwe8yszqoY1k8+U0T0G+\n\ -HeIdOCXgkmOiNCj+zyrLvaEhuS6PLq1b5TBVqGJcSPWdQ+MrglbQIKu9pUg5ptt7\n\ -wJ5WU+i9PeK9Ruxc/g/BFKYFkFJQjtZzb+nqm3wpul8zGwDN/O/ZiTqCyd3rHbmM\n\ -/dZ/viKPCZHIEBAEq0m3LskCgYBndzcAo+5k8ZjWwBfQth5SfhCIp/daJgGzbYtR\n\ -P/BenAsY2KOap3tjT8Fsw5usuHSxzIojX6H0Gvu7Qzq11mLn43Q+BeQrRQTWeFRc\n\ -MQdy4iZFZXNNEp7dF8yE9VKHwdgSJPGUdxD6chMvf2tRCN6mlS171VLV6wVvZvez\n\ -H/vX5QKBgD2Dq/NHpjCpAsECP9awmNF5Akn5WJbRGmegwXIih2mOtgtYYDeuQyxY\n\ -ZCrdJFfIUjUVPagshEmUklKhkYMYpzy2PQDVtaVcm6UNFroxT5h+J+KDs1LN1H8G\n\ -LsASrzyAg8EpRulwXEfLrWKiu9DKv8bMEgO4Ovgz8zTKJZIFhcac\n\ ------END RSA PRIVATE KEY-----"; - - DDS_Security_ValidationResult_t validate_local_identity( dds_security_authentication *instance, diff --git a/src/security/core/tests/plugin_loading/plugin_mock_common.h b/src/security/core/tests/plugin_loading/plugin_mock_common.h new file mode 100644 index 0000000..3fe2768 --- /dev/null +++ b/src/security/core/tests/plugin_loading/plugin_mock_common.h @@ -0,0 +1,98 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#ifndef PLUGIN_MOCK_COMMON_H_ +#define PLUGIN_MOCK_COMMON_H_ + +#define TEST_IDENTITY_CERTIFICATE_ALL_OK "testtext_IdentityCertificate_testtext" +#define TEST_CA_CERTIFICATE_ALL_OK "testtext_IdentityCA_testtext" +#define TEST_PRIVATE_KEY_ALL_OK "testtext_PrivateKey_testtext" + +#define TEST_IDENTITY_CERTIFICATE "data:,-----BEGIN CERTIFICATE-----\n\ +MIIDYDCCAkigAwIBAgIBBDANBgkqhkiG9w0BAQsFADByMQswCQYDVQQGEwJOTDEL\n\ +MAkGA1UECBMCT1YxEzARBgNVBAoTCkFETGluayBJU1QxGTAXBgNVBAMTEElkZW50\n\ +aXR5IENBIFRlc3QxJjAkBgkqhkiG9w0BCQEWF2luZm9AaXN0LmFkbGlua3RlY2gu\n\ +Y29tMB4XDTE4MDMxMjAwMDAwMFoXDTI3MDMxMTIzNTk1OVowdTELMAkGA1UEBhMC\n\ +TkwxCzAJBgNVBAgTAk9WMRAwDgYDVQQKEwdBRExpbmsgMREwDwYDVQQLEwhJU1Qg\n\ +VGVzdDETMBEGA1UEAxMKQWxpY2UgVGVzdDEfMB0GCSqGSIb3DQEJARYQYWxpY2VA\n\ +YWRsaW5rLmlzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANBW+tEZ\n\ +Baw7EQCEXyzH9n7IkZ8PQIKe8hG1LAOGYOF/oUYQZJO/HxbWoC4rFqOC20+A6is6\n\ +kFwr1Zzp/Wurk9CrFXo5Nomi6ActH6LUM57nYqN68w6U38z/XkQxVY/ESZ5dySfD\n\ +9Q1C8R+zdE8gwbimdYmwX7ioz336nghM2CoAHPDRthQeJupl8x4V7isOltr9CGx8\n\ ++imJXbGr39OK6u87cNLeu23sUkOIC0lSRMIqIQK3oJtHS70J2qecXdqp9MhE7Xky\n\ +/GPlI8ptQ1gJ8A3cAOvtI9mtMJMszs2EKWTLfeTcmfJHKKhKjvCgDdh3Jan4x5YP\n\ +Yg7HG6H+ceOUkMMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAkvuqZzyJ3Nu4/Eo5\n\ +kD0nVgYGBUl7cspu+636q39zPSrxLEDMUWz+u8oXLpyGcgiZ8lZulPTV8dmOn+3C\n\ +Vg55c5C+gbnbX3MDyb3wB17296RmxYf6YNul4sFOmj6+g2i+Dw9WH0PBCVKbA84F\n\ +jR3Gx2Pfoifor3DvT0YFSsjNIRt090u4dQglbIb6cWEafC7O24t5jFhGPvJ7L9SE\n\ +gB0Drh/HmKTVuaqaRkoOKkKaKuWoXsszK1ZFda1DHommnR5LpYPsDRQ2fVM4EuBF\n\ +By03727uneuG8HLuNcLEV9H0i7LxtyfFkyCPUQvWG5jehb7xPOz/Ml26NAwwjlTJ\n\ +xEEFrw==\n\ +-----END CERTIFICATE-----" + +#define TEST_CA_CERTIFICATE_ALL "data:,-----BEGIN CERTIFICATE-----\n\ +MIIEKTCCAxGgAwIBAgIBATANBgkqhkiG9w0BAQsFADByMQswCQYDVQQGEwJOTDEL\n\ +MAkGA1UECBMCT1YxEzARBgNVBAoTCkFETGluayBJU1QxGTAXBgNVBAMTEElkZW50\n\ +aXR5IENBIFRlc3QxJjAkBgkqhkiG9w0BCQEWF2luZm9AaXN0LmFkbGlua3RlY2gu\n\ +Y29tMB4XDTE4MDMxMjAwMDAwMFoXDTI3MDMxMTIzNTk1OVowcjELMAkGA1UEBhMC\n\ +TkwxCzAJBgNVBAgTAk9WMRMwEQYDVQQKEwpBRExpbmsgSVNUMRkwFwYDVQQDExBJ\n\ +ZGVudGl0eSBDQSBUZXN0MSYwJAYJKoZIhvcNAQkBFhdpbmZvQGlzdC5hZGxpbmt0\n\ +ZWNoLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANa/ENFfGVXg\n\ +bPLTzBdDfiZQcp5dWZ//Pb8ErFOJu8uosVHFv8t69dgjHgNHB4OsjmjnR7GfKUZT\n\ +0cMvWJnjsC7DDlBwFET9rj4k40n96bbVCH9I7+tNhsoqzc6Eu+5h4sk7VfNGTM2Z\n\ +SyCd4GiSZRuA44rRbhXI7/LDpr4hY5J9ZDo5AM9ZyoLAoh774H3CZWD67S35XvUs\n\ +72dzE6uKG/vxBbvZ7eW2GLO6ewa9UxlnLVMPfJdpkp/xYXwwcPW2+2YXCge1ujxs\n\ +tjrOQJ5HUySh6DkE/kZpx8zwYWm9AaCrsvCIX1thsqgvKy+U5v1FS1L58eGc6s//\n\ +9yMgNhU29R0CAwEAAaOByTCBxjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRNVUJN\n\ +FzhJPReYT4QSx6dK53CXCTAfBgNVHSMEGDAWgBRNVUJNFzhJPReYT4QSx6dK53CX\n\ +CTAPBgNVHQ8BAf8EBQMDB/+AMGUGA1UdJQEB/wRbMFkGCCsGAQUFBwMBBggrBgEF\n\ +BQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkGCCsG\n\ +AQUFBwMNBggrBgEFBQcDDgYHKwYBBQIDBTANBgkqhkiG9w0BAQsFAAOCAQEAcOLF\n\ +ZYdJguj0uxeXB8v3xnUr1AWz9+gwg0URdfNLU2KvF2lsb/uznv6168b3/FcPgezN\n\ +Ihl9GqB+RvGwgXS/1UelCGbQiIUdsNxk246P4uOGPIyW32RoJcYPWZcpY+cw11tQ\n\ +NOnk994Y5/8ad1DmcxVLLqq5kwpXGWQufV1zOONq8B+mCvcVAmM4vkyF/de56Lwa\n\ +sAMpk1p77uhaDnuq2lIR4q3QHX2wGctFid5Q375DRscFQteY01r/dtwBBrMn0wuL\n\ +AMNx9ZGD+zAoOUaslpIlEQ+keAxk3jgGMWFMxF81YfhEnXzevSQXWpyek86XUyFL\n\ +O9IAQi5pa15gXjSbUg==\n\ +-----END CERTIFICATE-----" + +#define TEST_PRIVATE_KEY_ALL "data:,-----BEGIN RSA PRIVATE KEY-----\n\ +MIIEowIBAAKCAQEA0Fb60RkFrDsRAIRfLMf2fsiRnw9Agp7yEbUsA4Zg4X+hRhBk\n\ +k78fFtagLisWo4LbT4DqKzqQXCvVnOn9a6uT0KsVejk2iaLoBy0fotQznudio3rz\n\ +DpTfzP9eRDFVj8RJnl3JJ8P1DULxH7N0TyDBuKZ1ibBfuKjPffqeCEzYKgAc8NG2\n\ +FB4m6mXzHhXuKw6W2v0IbHz6KYldsavf04rq7ztw0t67bexSQ4gLSVJEwiohAreg\n\ +m0dLvQnap5xd2qn0yETteTL8Y+Ujym1DWAnwDdwA6+0j2a0wkyzOzYQpZMt95NyZ\n\ +8kcoqEqO8KAN2HclqfjHlg9iDscbof5x45SQwwIDAQABAoIBAG0dYPeqd0IhHWJ7\n\ +8azufbchLMN1pX/D51xG2uptssfnpHuhkkufSZUYi4QipRS2ME6PYhWJ8pmTi6lH\n\ +E6cUkbI0KGd/F4U2gPdhNrR9Fxwea5bbifkVF7Gx/ZkRjZJiZ3w9+mCNTQbJDKhh\n\ +wITAzzT6WYznhvqbzzBX1fTa6kv0GAQtX7aHKM+XIwkhX2gzU5TU80bvH8aMrT05\n\ +tAMGQqkUeRnpo0yucBl4VmTZzd/+X/d2UyXR0my15jE5iH5o+p+E6qTRE9D+MGUd\n\ +MQ6Ftj0Untqy1lcog1ZLL6zPlnwcD4jgY5VCYDgvabnrSwymOJapPLsAEdWdq+U5\n\ +ec44BMECgYEA/+3qPUrd4XxA517qO3fCGBvf2Gkr7w5ZDeATOTHGuD8QZeK0nxPl\n\ +CWhRjdgkqo0fyf1cjczL5XgYayo+YxkO1Z4RUU+8lJAHlVx9izOQo+MTQfkwH4BK\n\ +LYlHxMoHJwAOXXoE+dmBaDh5xT0mDUGU750r763L6EFovE4qRBn9hxkCgYEA0GWz\n\ +rpOPNxb419WxG9npoQYdCZ5IbmEOGDH3ReggVzWHmW8sqtkqTZm5srcyDpqAc1Gu\n\ +paUveMblEBbU+NFJjLWOfwB5PCp8jsrqRgCQSxolShiVkc3Vu3oyzMus9PDge1eo\n\ +9mwVGO7ojQKWRu/WVAakENPaAjeyyhv4dqSNnjsCgYEAlwe8yszqoY1k8+U0T0G+\n\ +HeIdOCXgkmOiNCj+zyrLvaEhuS6PLq1b5TBVqGJcSPWdQ+MrglbQIKu9pUg5ptt7\n\ +wJ5WU+i9PeK9Ruxc/g/BFKYFkFJQjtZzb+nqm3wpul8zGwDN/O/ZiTqCyd3rHbmM\n\ +/dZ/viKPCZHIEBAEq0m3LskCgYBndzcAo+5k8ZjWwBfQth5SfhCIp/daJgGzbYtR\n\ +P/BenAsY2KOap3tjT8Fsw5usuHSxzIojX6H0Gvu7Qzq11mLn43Q+BeQrRQTWeFRc\n\ +MQdy4iZFZXNNEp7dF8yE9VKHwdgSJPGUdxD6chMvf2tRCN6mlS171VLV6wVvZvez\n\ +H/vX5QKBgD2Dq/NHpjCpAsECP9awmNF5Akn5WJbRGmegwXIih2mOtgtYYDeuQyxY\n\ +ZCrdJFfIUjUVPagshEmUklKhkYMYpzy2PQDVtaVcm6UNFroxT5h+J+KDs1LN1H8G\n\ +LsASrzyAg8EpRulwXEfLrWKiu9DKv8bMEgO4Ovgz8zTKJZIFhcac\n\ +-----END RSA PRIVATE KEY-----" + + + +#endif diff --git a/src/security/core/tests/plugin_loading/security_config.c b/src/security/core/tests/plugin_loading/security_config.c index 3c91f60..dbd0806 100644 --- a/src/security/core/tests/plugin_loading/security_config.c +++ b/src/security/core/tests/plugin_loading/security_config.c @@ -21,6 +21,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsi/q_misc.h" #include "dds/ddsi/ddsi_xqos.h" +#include "plugin_mock_common.h" #include "dds/security/dds_security_api_defs.h" @@ -50,9 +51,9 @@ "0:\"dds.sec.access.library.path\":\""ac"\"," \ "0:\"dds.sec.access.library.init\":\"init_access_control\"," \ "0:\"dds.sec.access.library.finalize\":\"finalize_access_control\"," \ - "0:\"dds.sec.auth.identity_ca\":\"testtext_IdentityCA_testtext\"," \ - "0:\"dds.sec.auth.private_key\":\"testtext_PrivateKey_testtext\"," \ - "0:\"dds.sec.auth.identity_certificate\":\"testtext_IdentityCertificate_testtext\"," \ + "0:\"dds.sec.auth.identity_ca\":\"" TEST_CA_CERTIFICATE_ALL_OK "\"," \ + "0:\"dds.sec.auth.private_key\":\"" TEST_PRIVATE_KEY_ALL_OK "\"," \ + "0:\"dds.sec.auth.identity_certificate\":\"" TEST_IDENTITY_CERTIFICATE_ALL_OK "\"," \ "0:\"dds.sec.access.permissions_ca\":\"file:Permissions_CA.pem\"," \ "0:\"dds.sec.access.governance\":\"file:Governance.p7s\"," \ "0:\"dds.sec.access.permissions\":\"file:Permissions.p7s\"" \ @@ -206,9 +207,9 @@ CU_Test(ddsc_security_config, all, .init = ddsrt_init, .fini = ddsrt_fini) "config: Domain/DDSSecurity/Authentication/Library[@path]: "MOCKLIB_PATH("dds_security_authentication_all_ok")"*", "config: Domain/DDSSecurity/Authentication/Library[@initFunction]: init_authentication*", "config: Domain/DDSSecurity/Authentication/Library[@finalizeFunction]: finalize_authentication*", - "config: Domain/DDSSecurity/Authentication/IdentityCertificate/#text: testtext_IdentityCertificate_testtext*", - "config: Domain/DDSSecurity/Authentication/IdentityCA/#text: testtext_IdentityCA_testtext*", - "config: Domain/DDSSecurity/Authentication/PrivateKey/#text: testtext_PrivateKey_testtext*", + "config: Domain/DDSSecurity/Authentication/IdentityCertificate/#text: "TEST_IDENTITY_CERTIFICATE_ALL_OK"*", + "config: Domain/DDSSecurity/Authentication/IdentityCA/#text: "TEST_CA_CERTIFICATE_ALL_OK"*", + "config: Domain/DDSSecurity/Authentication/PrivateKey/#text: "TEST_PRIVATE_KEY_ALL_OK"*", "config: Domain/DDSSecurity/Authentication/Password/#text: testtext_Password_testtext*", "config: Domain/DDSSecurity/Authentication/TrustedCADirectory/#text: testtext_Dir_testtext*", "config: Domain/DDSSecurity/AccessControl/Library/#text: "MOCKLIB_PATH("dds_security_access_control_all_ok")"*", @@ -233,9 +234,9 @@ CU_Test(ddsc_security_config, all, .init = ddsrt_init, .fini = ddsrt_fini) " " " " " "MOCKLIB_ELEM_AUTH("dds_security_authentication_all_ok") - " testtext_IdentityCertificate_testtext" - " testtext_IdentityCA_testtext" - " testtext_PrivateKey_testtext" + " "TEST_IDENTITY_CERTIFICATE_ALL_OK"" + " "TEST_CA_CERTIFICATE_ALL_OK"" + " "TEST_PRIVATE_KEY_ALL_OK"" " testtext_Password_testtext" " testtext_Dir_testtext" " " @@ -281,9 +282,9 @@ CU_Test(ddsc_security_config, security, .init = ddsrt_init, .fini = ddsrt_fini) "config: Domain/DDSSecurity/Authentication/Library[@path]: "MOCKLIB_PATH("dds_security_authentication_all_ok")"*", "config: Domain/DDSSecurity/Authentication/Library[@initFunction]: init_authentication*", "config: Domain/DDSSecurity/Authentication/Library[@finalizeFunction]: finalize_authentication*", - "config: Domain/DDSSecurity/Authentication/IdentityCertificate/#text: testtext_IdentityCertificate_testtext*", - "config: Domain/DDSSecurity/Authentication/IdentityCA/#text: testtext_IdentityCA_testtext*", - "config: Domain/DDSSecurity/Authentication/PrivateKey/#text: testtext_PrivateKey_testtext*", + "config: Domain/DDSSecurity/Authentication/IdentityCertificate/#text: "TEST_IDENTITY_CERTIFICATE_ALL_OK"*", + "config: Domain/DDSSecurity/Authentication/IdentityCA/#text: "TEST_CA_CERTIFICATE_ALL_OK"*", + "config: Domain/DDSSecurity/Authentication/PrivateKey/#text: "TEST_PRIVATE_KEY_ALL_OK"*", "config: Domain/DDSSecurity/Authentication/Password/#text: {}*", "config: Domain/DDSSecurity/Authentication/TrustedCADirectory/#text: {}*", "config: Domain/DDSSecurity/AccessControl/Library/#text: "MOCKLIB_PATH("dds_security_access_control_all_ok")"*", @@ -307,9 +308,9 @@ CU_Test(ddsc_security_config, security, .init = ddsrt_init, .fini = ddsrt_fini) "" " " " "MOCKLIB_ELEM_AUTH("dds_security_authentication_all_ok") - " testtext_IdentityCertificate_testtext" - " testtext_IdentityCA_testtext" - " testtext_PrivateKey_testtext" + " "TEST_IDENTITY_CERTIFICATE_ALL_OK"" + " "TEST_CA_CERTIFICATE_ALL_OK"" + " "TEST_PRIVATE_KEY_ALL_OK"" " " " " " "MOCKLIB_ELEM_CRYPTO("dds_security_cryptography_all_ok") @@ -351,9 +352,9 @@ CU_Test(ddsc_security_config, deprecated, .init = ddsrt_init, .fini = ddsrt_fini "config: Domain/DDSSecurity/Authentication/Library[@path]: "MOCKLIB_PATH("dds_security_authentication_all_ok")"*", "config: Domain/DDSSecurity/Authentication/Library[@initFunction]: init_authentication*", "config: Domain/DDSSecurity/Authentication/Library[@finalizeFunction]: finalize_authentication*", - "config: Domain/DDSSecurity/Authentication/IdentityCertificate/#text: testtext_IdentityCertificate_testtext*", - "config: Domain/DDSSecurity/Authentication/IdentityCA/#text: testtext_IdentityCA_testtext*", - "config: Domain/DDSSecurity/Authentication/PrivateKey/#text: testtext_PrivateKey_testtext*", + "config: Domain/DDSSecurity/Authentication/IdentityCertificate/#text: "TEST_IDENTITY_CERTIFICATE_ALL_OK"*", + "config: Domain/DDSSecurity/Authentication/IdentityCA/#text: "TEST_CA_CERTIFICATE_ALL_OK"*", + "config: Domain/DDSSecurity/Authentication/PrivateKey/#text: "TEST_PRIVATE_KEY_ALL_OK"*", "config: Domain/DDSSecurity/Authentication/Password/#text: testtext_Password_testtext*", "config: Domain/DDSSecurity/Authentication/TrustedCADirectory/#text: testtext_Dir_testtext*", "config: Domain/DDSSecurity/AccessControl/Library/#text: "MOCKLIB_PATH("dds_security_access_control_all_ok")"*", @@ -378,9 +379,9 @@ CU_Test(ddsc_security_config, deprecated, .init = ddsrt_init, .fini = ddsrt_fini " " " " " "MOCKLIB_ELEM_AUTH("dds_security_authentication_all_ok") - " testtext_IdentityCertificate_testtext" - " testtext_IdentityCA_testtext" - " testtext_PrivateKey_testtext" + " "TEST_IDENTITY_CERTIFICATE_ALL_OK"" + " "TEST_CA_CERTIFICATE_ALL_OK"" + " "TEST_PRIVATE_KEY_ALL_OK"" " testtext_Password_testtext" " testtext_Dir_testtext" " " @@ -448,9 +449,9 @@ CU_Test(ddsc_security_config, qos, .init = ddsrt_init, .fini = ddsrt_fini) dds_qset_prop(qos, "dds.sec.access.library.path", ""MOCKLIB_PATH("dds_security_access_control_all_ok")""); dds_qset_prop(qos, "dds.sec.access.library.init", "init_access_control"); dds_qset_prop(qos, "dds.sec.access.library.finalize", "finalize_access_control"); - dds_qset_prop(qos, "dds.sec.auth.identity_ca", "testtext_IdentityCA_testtext"); - dds_qset_prop(qos, "dds.sec.auth.private_key", "testtext_PrivateKey_testtext"); - dds_qset_prop(qos, "dds.sec.auth.identity_certificate", "testtext_IdentityCertificate_testtext"); + dds_qset_prop(qos, "dds.sec.auth.identity_ca", TEST_CA_CERTIFICATE_ALL_OK); + dds_qset_prop(qos, "dds.sec.auth.private_key", TEST_PRIVATE_KEY_ALL_OK); + dds_qset_prop(qos, "dds.sec.auth.identity_certificate", TEST_IDENTITY_CERTIFICATE_ALL_OK); dds_qset_prop(qos, "dds.sec.access.permissions_ca", "file:Permissions_CA.pem"); dds_qset_prop(qos, "dds.sec.access.governance", "file:Governance.p7s"); dds_qset_prop(qos, "dds.sec.access.permissions", "file:Permissions.p7s"); @@ -494,6 +495,7 @@ CU_Test(ddsc_security_config, qos_props, .init = ddsrt_init, .fini = ddsrt_fini) PARTICIPANT_QOS_ALL_OK to work, the order must match that one */ unsigned char bvalue[3] = { 0x01, 0x02, 0x03 }; CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); + dds_qset_prop(qos, "dds.sec.auth.library.path", ""MOCKLIB_PATH("dds_security_authentication_all_ok")""); dds_qset_prop(qos, "dds.sec.auth.library.init", "init_authentication"); dds_qset_prop(qos, "dds.sec.auth.library.finalize", "finalize_authentication"); @@ -503,9 +505,9 @@ CU_Test(ddsc_security_config, qos_props, .init = ddsrt_init, .fini = ddsrt_fini) dds_qset_prop(qos, "dds.sec.access.library.path", ""MOCKLIB_PATH("dds_security_access_control_all_ok")""); dds_qset_prop(qos, "dds.sec.access.library.init", "init_access_control"); dds_qset_prop(qos, "dds.sec.access.library.finalize", "finalize_access_control"); - dds_qset_prop(qos, "dds.sec.auth.identity_ca", "testtext_IdentityCA_testtext"); - dds_qset_prop(qos, "dds.sec.auth.private_key", "testtext_PrivateKey_testtext"); - dds_qset_prop(qos, "dds.sec.auth.identity_certificate", "testtext_IdentityCertificate_testtext"); + dds_qset_prop(qos, "dds.sec.auth.identity_ca", TEST_CA_CERTIFICATE_ALL_OK); + dds_qset_prop(qos, "dds.sec.auth.private_key", TEST_PRIVATE_KEY_ALL_OK); + dds_qset_prop(qos, "dds.sec.auth.identity_certificate", TEST_IDENTITY_CERTIFICATE_ALL_OK); dds_qset_prop(qos, "dds.sec.access.permissions_ca", "file:Permissions_CA.pem"); dds_qset_prop(qos, "dds.sec.access.governance", "file:Governance.p7s"); dds_qset_prop(qos, "dds.sec.access.permissions", "file:Permissions.p7s"); @@ -514,7 +516,6 @@ CU_Test(ddsc_security_config, qos_props, .init = ddsrt_init, .fini = ddsrt_fini) dds_qset_prop(qos, "test.prop1", "testtext_value1_testtext"); dds_qset_prop(qos, "test.prop2", "testtext_value2_testtext"); - dds_qset_bprop(qos, "test.bprop1", bvalue, 3); /* Create participant with security config in qos. */ @@ -546,9 +547,9 @@ CU_Test(ddsc_security_config, config_qos, .init = ddsrt_init, .fini = ddsrt_fini "finest" "" " " - " testtext_IdentityCertificate_testtext" - " testtext_IdentityCA_testtext" - " testtext_PrivateKey_testtext" + " "TEST_IDENTITY_CERTIFICATE_ALL_OK"" + " "TEST_CA_CERTIFICATE_ALL_OK"" + " "TEST_PRIVATE_KEY_ALL_OK"" " " " " " file:Governance.p7s" @@ -572,9 +573,9 @@ CU_Test(ddsc_security_config, config_qos, .init = ddsrt_init, .fini = ddsrt_fini dds_qset_prop(qos, "dds.sec.access.library.path", ""MOCKLIB_PATH("dds_security_access_control_all_ok")""); dds_qset_prop(qos, "dds.sec.access.library.init", "init_access_control"); dds_qset_prop(qos, "dds.sec.access.library.finalize", "finalize_access_control"); - dds_qset_prop(qos, "dds.sec.auth.identity_ca", "testtext_IdentityCA_testtext"); - dds_qset_prop(qos, "dds.sec.auth.private_key", "testtext_PrivateKey_testtext"); - dds_qset_prop(qos, "dds.sec.auth.identity_certificate", "testtext_IdentityCertificate_testtext"); + dds_qset_prop(qos, "dds.sec.auth.identity_ca", TEST_CA_CERTIFICATE_ALL_OK); + dds_qset_prop(qos, "dds.sec.auth.private_key", TEST_PRIVATE_KEY_ALL_OK); + dds_qset_prop(qos, "dds.sec.auth.identity_certificate", TEST_IDENTITY_CERTIFICATE_ALL_OK); dds_qset_prop(qos, "dds.sec.access.permissions_ca", "file:Permissions_CA.pem"); dds_qset_prop(qos, "dds.sec.access.governance", "file:Governance.p7s"); dds_qset_prop(qos, "dds.sec.access.permissions", "file:Permissions.p7s"); @@ -614,9 +615,9 @@ CU_Test(ddsc_security_config, other_prop, .init = ddsrt_init, .fini = ddsrt_fini "" " " " "MOCKLIB_ELEM_AUTH("dds_security_authentication_all_ok") - " testtext_IdentityCertificate_testtext" - " testtext_IdentityCA_testtext" - " testtext_PrivateKey_testtext" + " "TEST_IDENTITY_CERTIFICATE_ALL_OK"" + " "TEST_CA_CERTIFICATE_ALL_OK"" + " "TEST_PRIVATE_KEY_ALL_OK"" " testtext_Password_testtext" " testtext_Dir_testtext" " " @@ -685,9 +686,9 @@ CU_Test(ddsc_security_config, qos_invalid, .init = ddsrt_init, .fini = ddsrt_fin "finest" "" " " - " testtext_IdentityCertificate_testtext" - " testtext_IdentityCA_testtext" - " testtext_PrivateKey_testtext" + " "TEST_IDENTITY_CERTIFICATE_ALL_OK"" + " "TEST_CA_CERTIFICATE_ALL_OK"" + " "TEST_PRIVATE_KEY_ALL_OK"" " " " " " file:Governance.p7s" diff --git a/src/security/core/tests/tc_fsm.c b/src/security/core/tests/tc_fsm.c index c2c7647..5489d19 100644 --- a/src/security/core/tests/tc_fsm.c +++ b/src/security/core/tests/tc_fsm.c @@ -369,16 +369,19 @@ static const uint32_t TransitionsSize = sizeof(Transitions)/sizeof(Transitions[0 **********************************************************************/ typedef enum { - eventToTimeout, eventToEnd, + eventToTimeout, eventToInterupt, eventToEnd, } timeout_events; +struct fsm_timeout_arg { + int id; +}; + static struct dds_security_fsm *fsm_timeout; static uint32_t visited_timeout = 0; static uint32_t correct_fsm_timeout = 0; static uint32_t correct_arg_timeout = 0; -static ddsrt_cond_t stop_timeout_cond; -static ddsrt_mutex_t stop_timeout_cond_mutex; -static uint32_t stop_timeout_cond_cnt = 0; +static struct fsm_timeout_arg fsm_arg = { .id = FSM_AUTH_ARG }; + /* The functions called from the state-machine. */ static void doInterupt(struct dds_security_fsm *fsm, void *arg) @@ -393,24 +396,15 @@ static void doInterupt(struct dds_security_fsm *fsm, void *arg) static void doTimeout(struct dds_security_fsm *fsm, void *arg) { - dds_duration_t delay4 = 4 * DDS_NSECS_IN_SEC; - DDSRT_UNUSED_ARG(arg); if (DB_TC_PRINT_DEBUG) { - printf("Transition >>>> %s %d\n", __FUNCTION__, stop_timeout_cond_cnt); + printf("Transition >>>> %s\n", __FUNCTION__); } visited_timeout |= 1UL << 1; - stop_timeout_cond_cnt++; - ddsrt_mutex_lock(&stop_timeout_cond_mutex); - (void) ddsrt_cond_waitfor(&stop_timeout_cond, &stop_timeout_cond_mutex, - delay4); - ddsrt_mutex_unlock(&stop_timeout_cond_mutex); - stop_timeout_cond_cnt--; - if (DB_TC_PRINT_DEBUG) { - printf("Transition <<<< %s %d\n", __FUNCTION__, stop_timeout_cond_cnt); + printf("Transition <<<< %s\n", __FUNCTION__); } dds_security_fsm_dispatch(fsm, eventToTimeout, false); @@ -418,7 +412,7 @@ static void doTimeout(struct dds_security_fsm *fsm, void *arg) static void TimeoutCallback(struct dds_security_fsm *fsm, void *arg) { - int *fsm_arg; + struct fsm_timeout_arg *farg = arg; if (DB_TC_PRINT_DEBUG) { printf("TimeoutCallback\n"); @@ -426,10 +420,8 @@ static void TimeoutCallback(struct dds_security_fsm *fsm, void *arg) visited_timeout |= 1UL << 2; - if (arg != NULL) { - fsm_arg = (int *) arg; - - if (*fsm_arg == FSM_AUTH_ARG) { + if (farg != NULL) { + if (farg->id == FSM_AUTH_ARG) { correct_arg_timeout = 1; } else { correct_arg_timeout = 0; @@ -452,14 +444,17 @@ static void TimeoutCallback2(struct dds_security_fsm *fsm, void *arg) visited_timeout |= 1UL << 3; } -static dds_security_fsm_state StateTimeout = {doTimeout, 0};static int fsm_arg = FSM_AUTH_ARG; +static dds_security_fsm_state StateInitial = {doTimeout, 0}; +static dds_security_fsm_state StateWaitTimeout = {NULL, DDS_SECS(4)}; +static dds_security_fsm_state StateInterupt = {doInterupt, 0}; -static dds_security_fsm_state StateInterupt = {doInterupt, 0}; static const dds_security_fsm_transition TimeoutTransitions[] = { - {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateTimeout}, // NULL state is the start state - {&StateTimeout, eventToTimeout, NULL, &StateInterupt}, - {&StateInterupt,eventToEnd, NULL, NULL}, // Reaching NULL means end of state-diagram + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateInitial}, // NULL state is the start state + {&StateInitial, eventToTimeout, NULL, &StateWaitTimeout}, + {&StateWaitTimeout, DDS_SECURITY_FSM_EVENT_TIMEOUT, NULL, &StateInterupt}, + {&StateWaitTimeout, eventToInterupt, NULL, &StateInterupt}, + {&StateInterupt, eventToEnd, NULL, NULL}, // Reaching NULL means end of state-diagram }; static const uint32_t TimeoutTransitionsSize = sizeof(TimeoutTransitions)/sizeof(TimeoutTransitions[0]); @@ -541,16 +536,10 @@ static void fsm_control_init(void) rc = dds_security_fsm_control_start (g_fsm_control, NULL); CU_ASSERT_FATAL(rc == 0); - - ddsrt_mutex_init(&stop_timeout_cond_mutex); - ddsrt_cond_init(&stop_timeout_cond); } static void fsm_control_fini(void) { - ddsrt_cond_destroy(&stop_timeout_cond); - ddsrt_mutex_destroy(&stop_timeout_cond_mutex); - dds_security_fsm_control_stop(g_fsm_control); dds_security_fsm_control_free(g_fsm_control); @@ -697,12 +686,10 @@ CU_Test(ddssec_fsm, timeout, .init = fsm_control_init, .fini = fsm_control_fini) timeout--; } CU_ASSERT(timeout > 0); - CU_ASSERT( - CHECK_BIT(visited_timeout, 0) && CHECK_BIT(visited_timeout, 1) && CHECK_BIT(visited_timeout, 2)); + CU_ASSERT(CHECK_BIT(visited_timeout, 0) && CHECK_BIT(visited_timeout, 1) && CHECK_BIT(visited_timeout, 2)); CU_ASSERT(correct_arg_timeout && correct_fsm_timeout); dds_security_fsm_free(fsm_timeout); - } /** @@ -740,10 +727,6 @@ CU_Test(ddssec_fsm, double_timeout, .init = fsm_control_init, .fini = fsm_contro CU_ASSERT(CHECK_BIT(visited_timeout, 3)); dds_security_fsm_free(fsm_timeout); dds_security_fsm_free(fsm_timeout2); - ddsrt_mutex_lock(&stop_timeout_cond_mutex); - ddsrt_cond_signal(&stop_timeout_cond); - ddsrt_mutex_unlock(&stop_timeout_cond_mutex); - } /** @@ -840,15 +823,5 @@ CU_Test(ddssec_fsm, delete_with_timeout, .init = fsm_control_init, .fini = fsm_c } dds_security_fsm_free(fsm_timeout); - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - - /* Just for safety to be certain that the condition isn't used anymore before destroying it. */ - while (stop_timeout_cond_cnt > 0) { - dds_time_t d = DDS_NSECS_IN_SEC; - ddsrt_cond_signal(&stop_timeout_cond); - dds_sleepfor(d); - } - - } From 1dad535bc09aa9b0c0074baba49e25f9475d6707 Mon Sep 17 00:00:00 2001 From: Marcel Jordense Date: Fri, 28 Feb 2020 18:01:58 +0100 Subject: [PATCH 105/238] Correct misplaced lock Signed-off-by: Marcel Jordense --- src/core/ddsi/src/ddsi_security_exchange.c | 4 ++-- src/core/ddsi/src/ddsi_security_omg.c | 5 ++--- src/core/ddsi/src/q_receive.c | 23 ++++++++++++---------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/core/ddsi/src/ddsi_security_exchange.c b/src/core/ddsi/src/ddsi_security_exchange.c index c583f71..e510e2c 100644 --- a/src/core/ddsi/src/ddsi_security_exchange.c +++ b/src/core/ddsi/src/ddsi_security_exchange.c @@ -296,10 +296,10 @@ static bool write_crypto_exchange_message(const struct participant *pp, const dd }; serdata = ddsi_serdata_from_sample (gv->rawcdr_topic, SDK_DATA, &raw); tk = ddsi_tkmap_lookup_instance_ref (gv->m_tkmap, serdata); - ddsrt_mutex_unlock (&wr->e.lock); - ddsrt_free(data); r = write_sample_p2p_wrlock_held(wr, seq, NULL, serdata, tk, prd); + ddsrt_mutex_unlock (&wr->e.lock); + ddsrt_free(data); ddsi_tkmap_instance_unref (gv->m_tkmap, tk); ddsi_serdata_unref (serdata); diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 8e3808d..7204515 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -1829,7 +1829,6 @@ bool q_omg_is_similar_participant_security_info(struct participant *pp, struct p proxypp->security_info.plugin_security_attributes = pp_security_info.plugin_security_attributes; } } - assert(matching); return matching; } @@ -2504,10 +2503,10 @@ void q_omg_security_set_remote_writer_crypto_tokens(struct reader *rd, const dds { GVTRACE("set_remote_writer_crypto_tokens "PGUIDFMT" with reader "PGUIDFMT"\n", PGUID(pwr->e.guid), PGUID(rd->e.guid)); match->matched = true; - DDS_Security_DataHolderSeq_free(tseq); } 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); } ddsrt_mutex_unlock(&rd->e.lock); @@ -2551,10 +2550,10 @@ void q_omg_security_set_remote_reader_crypto_tokens(struct writer *wr, const dds { GVTRACE("set_remote_reader_crypto_tokens "PGUIDFMT" with writer "PGUIDFMT"\n", PGUID(prd->e.guid), PGUID(wr->e.guid)); match->matched = true; - DDS_Security_DataHolderSeq_free(tseq); } 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); diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 640436b..7a5f9a7 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -1649,23 +1649,26 @@ static int handle_InfoTS (const struct receiver_state *rst, const InfoTS_t *msg, static int handle_one_gap (struct proxy_writer *pwr, struct pwr_rd_match *wn, seqno_t a, seqno_t b, struct nn_rdata *gap, int *refc_adjust) { struct nn_rsample_chain sc; - nn_reorder_result_t res; + nn_reorder_result_t res = 0; int gap_was_valuable = 0; ASSERT_MUTEX_HELD (&pwr->e.lock); /* Clean up the defrag admin: no fragments of a missing sample will be arriving in the future */ if (!(wn && wn->filtered)) - nn_defrag_notegap (pwr->defrag, a, b); - - /* Primary reorder: the gap message may cause some samples to become - deliverable. */ - if ((res = nn_reorder_gap (&sc, pwr->reorder, gap, a, b, refc_adjust)) > 0) { - if (pwr->deliver_synchronously) - deliver_user_data_synchronously (&sc, NULL); - else - nn_dqueue_enqueue (pwr->dqueue, &sc, res); + nn_defrag_notegap (pwr->defrag, a, b); + + /* Primary reorder: the gap message may cause some samples to become + deliverable. */ + + if ((res = nn_reorder_gap (&sc, pwr->reorder, gap, a, b, refc_adjust)) > 0) + { + if (pwr->deliver_synchronously) + deliver_user_data_synchronously (&sc, NULL); + else + nn_dqueue_enqueue (pwr->dqueue, &sc, res); + } } /* If the result was REJECT or TOO_OLD, then this gap didn't add From a0b4245600c7af3efedc610b543c4bcd083387a8 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 3 Mar 2020 12:41:47 +0100 Subject: [PATCH 106/238] Fix FSM timeout test race Signed-off-by: Erik Boasson --- src/security/core/tests/tc_fsm.c | 212 +++++++++++-------------------- 1 file changed, 71 insertions(+), 141 deletions(-) diff --git a/src/security/core/tests/tc_fsm.c b/src/security/core/tests/tc_fsm.c index 5489d19..666a641 100644 --- a/src/security/core/tests/tc_fsm.c +++ b/src/security/core/tests/tc_fsm.c @@ -29,11 +29,21 @@ #define DB_TC_PRINT_DEBUG (true) static dds_entity_t g_participant = 0; +static ddsrt_mutex_t g_lock; static struct dds_security_fsm_control *g_fsm_control = NULL; static const dds_duration_t msec100 = DDS_MSECS(100); //static int fsm_arg = FSM_AUTH_ARG; +#define DO_SIMPLE(name, var, bit) static void name(struct dds_security_fsm *fsm, void *arg) { \ + DDSRT_UNUSED_ARG(fsm); \ + DDSRT_UNUSED_ARG(arg); \ + if (DB_TC_PRINT_DEBUG) \ + printf("Transition %s\n", __FUNCTION__); \ + ddsrt_mutex_lock(&g_lock); \ + visited_##var |= 1u << (bit); \ + ddsrt_mutex_unlock(&g_lock); \ +} /********************************************************************** @@ -136,6 +146,7 @@ static void a(struct dds_security_fsm *fsm, void *arg) printf("[%p] Transition %s\n", fsm, __FUNCTION__); } + ddsrt_mutex_lock (&g_lock); if (arg != NULL) { fsm_arg = (int *) arg; @@ -151,71 +162,17 @@ static void a(struct dds_security_fsm *fsm, void *arg) } else { correct_fsm = 0; } - visited_auth |= 1UL << 0; + visited_auth |= 1u << 0; + ddsrt_mutex_unlock (&g_lock); } -static void b(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - if (DB_TC_PRINT_DEBUG) - printf("[%p] Transition %s\n", fsm, __FUNCTION__); - visited_auth |= 1UL << 1; -} - -static void c(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - if (DB_TC_PRINT_DEBUG) - printf("[%p] Transition %s\n", fsm, __FUNCTION__); - visited_auth |= 1UL << 2; -} - -static void d(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - if (DB_TC_PRINT_DEBUG) - printf("[%p] Transition %s\n", fsm, __FUNCTION__); - visited_auth |= 1UL << 3; -} - -static void e(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - if (DB_TC_PRINT_DEBUG) - printf("[%p] Transition %s\n", fsm, __FUNCTION__); - visited_auth |= 1UL << 4; -} - -static void f(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - if (DB_TC_PRINT_DEBUG) - printf("[%p] Transition %s\n", fsm, __FUNCTION__); - visited_auth |= 1UL << 5; -} - -static void g(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - if (DB_TC_PRINT_DEBUG) - printf("[%p] Transition %s\n", fsm, __FUNCTION__); - visited_auth |= 1UL << 6; -} - -static void h(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - if (DB_TC_PRINT_DEBUG) - printf("[%p] Transition %s\n", fsm, __FUNCTION__); - visited_auth |= 1UL << 7; -} +DO_SIMPLE(b, auth, 1) +DO_SIMPLE(c, auth, 2) +DO_SIMPLE(d, auth, 3) +DO_SIMPLE(e, auth, 4) +DO_SIMPLE(f, auth, 5) +DO_SIMPLE(g, auth, 6) +DO_SIMPLE(h, auth, 7) #define SHM_MSG_RECEIVED (PluginReturn_MAX + 1) @@ -279,33 +236,9 @@ static uint32_t visited_test = 0; static int do_stuff_counter = 0; static int do_other_stuff_counter = 0; -/* The functions called from the state-machine. */ -static void doStart(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - if (DB_TC_PRINT_DEBUG) - printf("Transition %s\n", __FUNCTION__); - visited_test |= 1UL << 0; -} - -static void doRestart(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - if (DB_TC_PRINT_DEBUG) - printf("Transition %s\n", __FUNCTION__); - visited_test |= 1UL << 1; -} - -static void doEventStuff(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - if (DB_TC_PRINT_DEBUG) - printf("Transition %s\n", __FUNCTION__); - visited_test |= 1UL << 4; -} +DO_SIMPLE(doStart, test, 0) +DO_SIMPLE(doRestart, test, 1) +DO_SIMPLE(doEventStuff, test, 4) static void doStuff(struct dds_security_fsm *fsm, void *arg) { @@ -315,7 +248,9 @@ static void doStuff(struct dds_security_fsm *fsm, void *arg) if (DB_TC_PRINT_DEBUG) { printf("Transition %s - %d\n", __FUNCTION__, do_stuff_counter); } - visited_test |= 1UL << 2; + ddsrt_mutex_lock (&g_lock); + visited_test |= 1u << 2; + ddsrt_mutex_unlock (&g_lock); if (do_stuff_counter < 2) { dds_security_fsm_dispatch(fsm, eventZ, false); @@ -333,7 +268,10 @@ static void doOtherStuff(struct dds_security_fsm *fsm, void *arg) if (DB_TC_PRINT_DEBUG) { printf("Transition %s - %d\n", __FUNCTION__, do_other_stuff_counter); } - visited_test |= 1UL << 3; + ddsrt_mutex_lock (&g_lock); + visited_test |= 1u << 3; + ddsrt_mutex_unlock (&g_lock); + if (do_other_stuff_counter == 0) { dds_security_fsm_dispatch(fsm, DDS_SECURITY_FSM_EVENT_AUTO, false); } @@ -382,17 +320,8 @@ static uint32_t correct_fsm_timeout = 0; static uint32_t correct_arg_timeout = 0; static struct fsm_timeout_arg fsm_arg = { .id = FSM_AUTH_ARG }; - -/* The functions called from the state-machine. */ -static void doInterupt(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - if (DB_TC_PRINT_DEBUG) { - printf("Transition %s\n", __FUNCTION__); - } - visited_timeout |= 1UL << 0; -} +DO_SIMPLE(doInterrupt, timeout, 0) +DO_SIMPLE(TimeoutCallback2, timeout, 3) static void doTimeout(struct dds_security_fsm *fsm, void *arg) { @@ -401,7 +330,9 @@ static void doTimeout(struct dds_security_fsm *fsm, void *arg) if (DB_TC_PRINT_DEBUG) { printf("Transition >>>> %s\n", __FUNCTION__); } - visited_timeout |= 1UL << 1; + ddsrt_mutex_lock (&g_lock); + visited_timeout |= 1u << 1; + ddsrt_mutex_unlock (&g_lock); if (DB_TC_PRINT_DEBUG) { printf("Transition <<<< %s\n", __FUNCTION__); @@ -418,7 +349,8 @@ static void TimeoutCallback(struct dds_security_fsm *fsm, void *arg) printf("TimeoutCallback\n"); } - visited_timeout |= 1UL << 2; + ddsrt_mutex_lock (&g_lock); + visited_timeout |= 1u << 2; if (farg != NULL) { if (farg->id == FSM_AUTH_ARG) { @@ -432,21 +364,12 @@ static void TimeoutCallback(struct dds_security_fsm *fsm, void *arg) } else { correct_fsm_timeout = 0; } -} - -static void TimeoutCallback2(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - if (DB_TC_PRINT_DEBUG) { - printf("TimeoutCallback2\n"); - } - visited_timeout |= 1UL << 3; + ddsrt_mutex_unlock (&g_lock); } static dds_security_fsm_state StateInitial = {doTimeout, 0}; static dds_security_fsm_state StateWaitTimeout = {NULL, DDS_SECS(4)}; -static dds_security_fsm_state StateInterupt = {doInterupt, 0}; +static dds_security_fsm_state StateInterupt = {doInterrupt, 0}; static const dds_security_fsm_transition TimeoutTransitions[] = { @@ -515,9 +438,6 @@ static dds_security_fsm_transition ParallelTimeoutTransitions_3[] = { }; static const uint32_t ParallelTimeoutTransitionsSize_3 = sizeof(ParallelTimeoutTransitions_3) / sizeof(ParallelTimeoutTransitions_3[0]); - - - static void fsm_control_init(void) { dds_return_t rc; @@ -526,6 +446,8 @@ static void fsm_control_init(void) g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); CU_ASSERT_FATAL(g_participant > 0); + ddsrt_mutex_init (&g_lock); + rc = dds_entity_pin(g_participant, &e); CU_ASSERT_FATAL(rc == 0); @@ -542,6 +464,7 @@ static void fsm_control_fini(void) { dds_security_fsm_control_stop(g_fsm_control); dds_security_fsm_control_free(g_fsm_control); + ddsrt_mutex_destroy (&g_lock); dds_delete(g_participant); } @@ -582,10 +505,9 @@ CU_Test(ddssec_fsm, create, .init = fsm_control_init, .fini = fsm_control_fini) } CU_ASSERT(timeout > 0); - CU_ASSERT( - CHECK_BIT(visited_auth, 0) && CHECK_BIT(visited_auth, 1) && CHECK_BIT(visited_auth, 2) && - CHECK_BIT(visited_auth, 3) && CHECK_BIT(visited_auth, 4) && CHECK_BIT(visited_auth, 5) && - CHECK_BIT(visited_auth, 6) && CHECK_BIT(visited_auth, 7)); + ddsrt_mutex_lock (&g_lock); + CU_ASSERT(visited_auth == 0xff); + ddsrt_mutex_unlock (&g_lock); /* * "Check correct callback parameter passing (from fsm to user defined methods) "); @@ -594,7 +516,9 @@ CU_Test(ddssec_fsm, create, .init = fsm_control_init, .fini = fsm_control_fini) dds_security_fsm_free(fsm_auth); /* Check whether timeout callback has NOT been invoked */ + ddsrt_mutex_lock (&g_lock); CU_ASSERT(visited_timeout == 0); + ddsrt_mutex_unlock (&g_lock); } /* @@ -638,10 +562,9 @@ CU_Test(ddssec_fsm, multiple, .init = fsm_control_init, .fini = fsm_control_fini CU_ASSERT_FATAL(timeout > 0); // not all bits are set since we're running the state machine a second time - CU_ASSERT_FATAL( - CHECK_BIT(visited_auth, 0) && !CHECK_BIT(visited_auth, 1) && CHECK_BIT(visited_auth, 2) && - !CHECK_BIT(visited_auth, 3) && CHECK_BIT(visited_auth, 4) && !CHECK_BIT(visited_auth, 5) && - CHECK_BIT(visited_auth, 6) && !CHECK_BIT(visited_auth, 7)); + ddsrt_mutex_lock (&g_lock); + CU_ASSERT_FATAL(visited_auth == 0x55); + ddsrt_mutex_unlock (&g_lock); /* Wait for the last state to occur */ timeout = 100; /* 10 sec */ @@ -651,9 +574,9 @@ CU_Test(ddssec_fsm, multiple, .init = fsm_control_init, .fini = fsm_control_fini } CU_ASSERT_FATAL(timeout > 0); - CU_ASSERT( - CHECK_BIT(visited_test, 0) && CHECK_BIT(visited_test, 1) && CHECK_BIT(visited_test, 2) && - CHECK_BIT(visited_test, 3)); + ddsrt_mutex_lock (&g_lock); + CU_ASSERT(visited_test == 0x1f); + ddsrt_mutex_unlock (&g_lock); dds_security_fsm_free(fsm_auth); dds_security_fsm_free(fsm_test); @@ -668,6 +591,8 @@ CU_Test(ddssec_fsm, timeout, .init = fsm_control_init, .fini = fsm_control_fini) dds_time_t delay1 = DDS_SECS(1); int timeout; + visited_timeout = 0; + /* * Test timeout monitoring of state machines */ @@ -681,13 +606,17 @@ CU_Test(ddssec_fsm, timeout, .init = fsm_control_init, .fini = fsm_control_fini) // Wait for the last state to occur timeout = 100; /* 10 sec */ - while ((dds_security_fsm_current_state(fsm_timeout) != &StateInterupt) && (timeout > 0)) { + ddsrt_mutex_lock (&g_lock); + while (visited_timeout != 0x7 && (timeout > 0)) { + ddsrt_mutex_unlock (&g_lock); dds_sleepfor(100 * DDS_NSECS_IN_MSEC); timeout--; + ddsrt_mutex_lock (&g_lock); } CU_ASSERT(timeout > 0); - CU_ASSERT(CHECK_BIT(visited_timeout, 0) && CHECK_BIT(visited_timeout, 1) && CHECK_BIT(visited_timeout, 2)); + CU_ASSERT(visited_timeout == 0x7); CU_ASSERT(correct_arg_timeout && correct_fsm_timeout); + ddsrt_mutex_unlock (&g_lock); dds_security_fsm_free(fsm_timeout); } @@ -713,18 +642,15 @@ CU_Test(ddssec_fsm, double_timeout, .init = fsm_control_init, .fini = fsm_contro dds_security_fsm_start(fsm_timeout); dds_security_fsm_start(fsm_timeout2); timeout = 100; /* 10 sec */ - while ((CHECK_BIT(visited_timeout, 2) == 0) && (timeout > 0)) { + ddsrt_mutex_lock (&g_lock); + while (visited_timeout != 0xf && (timeout > 0)) { + ddsrt_mutex_unlock (&g_lock); dds_sleepfor(100 * DDS_NSECS_IN_MSEC); timeout--; + ddsrt_mutex_lock (&g_lock); } - CU_ASSERT(CHECK_BIT(visited_timeout, 2)); -// dds_security_fsm_cleanup(fsm_timeout); - timeout = 100; /* 10 sec */ - while ((CHECK_BIT(visited_timeout, 3) == 0) && (timeout > 0)) { - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - } - CU_ASSERT(CHECK_BIT(visited_timeout, 3)); + CU_ASSERT(visited_timeout == 0xf); + ddsrt_mutex_unlock (&g_lock); dds_security_fsm_free(fsm_timeout); dds_security_fsm_free(fsm_timeout2); } @@ -817,10 +743,14 @@ CU_Test(ddssec_fsm, delete_with_timeout, .init = fsm_control_init, .fini = fsm_c /* Wait until we're in the timeout function. */ timeout = 100; /* 10 sec */ + ddsrt_mutex_lock (&g_lock); while ((visited_timeout == 0) && (timeout > 0)) { + ddsrt_mutex_unlock (&g_lock); dds_sleepfor(100 * DDS_NSECS_IN_MSEC); timeout--; + ddsrt_mutex_lock (&g_lock); } + ddsrt_mutex_unlock (&g_lock); dds_security_fsm_free(fsm_timeout); } From 7049469289d771f43ce0943bcb0c8b4318e0446b Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Sat, 29 Feb 2020 11:39:23 +0100 Subject: [PATCH 107/238] Update security documentation An update for the security documentation that is part of the CycloneDDS manual: - added openssl commands for creating a set of CA and identity certificates - code fragment for setting security by qos and example of xml security config - commands for signing governance and permissions documents using openssl Signed-off-by: Dennis Potman --- docs/manual/_static/example_governance.xml | 29 ++ docs/manual/_static/example_permissions.xml | 39 ++ docs/manual/_static/security_by_config.xml | 19 + docs/manual/_static/security_by_qos.c | 21 + docs/manual/index.rst | 1 + docs/manual/security.rst | 422 ++++++++++++++------ 6 files changed, 401 insertions(+), 130 deletions(-) create mode 100644 docs/manual/_static/example_governance.xml create mode 100644 docs/manual/_static/example_permissions.xml create mode 100644 docs/manual/_static/security_by_config.xml create mode 100644 docs/manual/_static/security_by_qos.c diff --git a/docs/manual/_static/example_governance.xml b/docs/manual/_static/example_governance.xml new file mode 100644 index 0000000..b0cb32e --- /dev/null +++ b/docs/manual/_static/example_governance.xml @@ -0,0 +1,29 @@ + + + + + + + 0 + 230 + + + false + true + NONE + NONE + NONE + + + * + true + true + true + true + SIGN + ENCRYPT + + + + + diff --git a/docs/manual/_static/example_permissions.xml b/docs/manual/_static/example_permissions.xml new file mode 100644 index 0000000..4610555 --- /dev/null +++ b/docs/manual/_static/example_permissions.xml @@ -0,0 +1,39 @@ + + + + + emailAddress=alice@cycloneddssecurity.adlinktech.com,CN=Alice Example,O=Example Organization,OU=Organizational Unit Name,L=Locality Name,ST=OV,C=NL + + + 2020-01-01T01:00:00 + 2120-01-01T01:00:00 + + + + + 0 + 230 + + + + + * + + + * + + + + + * + + + * + + + + DENY + + + \ No newline at end of file diff --git a/docs/manual/_static/security_by_config.xml b/docs/manual/_static/security_by_config.xml new file mode 100644 index 0000000..947fe78 --- /dev/null +++ b/docs/manual/_static/security_by_config.xml @@ -0,0 +1,19 @@ + + + + + file:/path/to/example_id_ca_cert.pem + file:/path/to/example_alice_cert.pem + file:/path/to/example_alice_priv_key.pem + + + + + + + file:/path/to/example_perm_ca_cert.pem + file:/path/to/example_governance.p7s + file:/path/to/example_permissions.p7s + + + diff --git a/docs/manual/_static/security_by_qos.c b/docs/manual/_static/security_by_qos.c new file mode 100644 index 0000000..86eea84 --- /dev/null +++ b/docs/manual/_static/security_by_qos.c @@ -0,0 +1,21 @@ +dds_qos_t * qos = dds_create_qos(); + +dds_qset_prop(qos, "dds.sec.auth.library.path", "dds_security_auth"); +dds_qset_prop(qos, "dds.sec.auth.library.init", "init_authentication"); +dds_qset_prop(qos, "dds.sec.auth.library.finalize", "finalize_authentication"); +dds_qset_prop(qos, "dds.sec.auth.identity_ca", "file:/path/to/example_id_ca_cert.pem"); +dds_qset_prop(qos, "dds.sec.auth.private_key", "file:/path/to/example_alice_priv_key.pem"); +dds_qset_prop(qos, "dds.sec.auth.identity_certificate", "file:/path/to/example_alice_cert.pem"); + +dds_qset_prop(qos, "dds.sec.crypto.library.path", "dds_security_crypto"); +dds_qset_prop(qos, "dds.sec.crypto.library.init", "init_crypto"); +dds_qset_prop(qos, "dds.sec.crypto.library.finalize", "finalize_crypto"); + +dds_qset_prop(qos, "dds.sec.access.library.path", "dds_security_ac"); +dds_qset_prop(qos, "dds.sec.access.library.init", "init_access_control"); +dds_qset_prop(qos, "dds.sec.access.library.finalize", "finalize_access_control"); +dds_qset_prop(qos, "dds.sec.access.permissions_ca", "file:/path/to/example_perm_ca_cert.pem"); +dds_qset_prop(qos, "dds.sec.access.governance", "file:/path/to/example_governance.p7s"); +dds_qset_prop(qos, "dds.sec.access.permissions", "file:/path/to/example_permissions.p7s"); + +dds_entity_t participant = dds_create_participant(0, qos, NULL); diff --git a/docs/manual/index.rst b/docs/manual/index.rst index 0d729a9..9def6b8 100644 --- a/docs/manual/index.rst +++ b/docs/manual/index.rst @@ -21,6 +21,7 @@ Welcome to Eclipse Cyclone DDS's documentation! GettingStartedGuide/index ddsc config + security Indices and tables ================== diff --git a/docs/manual/security.rst b/docs/manual/security.rst index b8ae578..5311b85 100644 --- a/docs/manual/security.rst +++ b/docs/manual/security.rst @@ -4,7 +4,7 @@ DDS Security ############ -CycloneDDS is (will be) compliant with The Object Management Group (OMG) DDS Security specification. +CycloneDDS is compliant with The Object Management Group (OMG) DDS Security specification. This specification defines the Security Model and Service Plugin Interface (SPI) architecture for compliant DDS implementations. The DDS Security Model is enforced by the invocation of these SPIs @@ -109,25 +109,28 @@ ID CA gets Alice's subject information and public key and generates an IdentityC Alice's certificate includes her public key and certificate of ID CA; so that her certificate can be verified if it is really issued by ID CA. -Access Control is configured with governance and permissions files. -Governance file defines the security behavior of domains and topics. -Permissions file contains the permissions of the domain participant, topics, readers and writers, -binds them to identity certificate by subject name (distinguished name). +Access Control is configured with governance and permissions files. Governance file defines the +security behavior of domains and topics. Permissions file contains the permissions of the domain +participant, topics, readers and writers, binds them to identity certificate by subject name +(distinguished name). Governance files and Permissions files are signed by Permission CA. Signed documents also contains Permissions CA certificate; so that they can be verified if they are really issued by Permissions CA. -Authenticated participants handshakes with each other and generates a shared key by Diffie-Hellman -key exchange. This shared key is used for encrypting/decrypting data with AES. +Authenticated participants perform a handshake with each other and generate a shared key by +Diffie-Hellman key exchange. This shared key is used for encrypting/decrypting data with AES. During the handshake Alice checks Bob's certificate and Bob's Permissions file if they are really issued by the ID CA certificate and Permissions CA Certificate that **she** has. Also Bob checks Alice's certificate and Alice's Permissions file if they are really issued by the ID CA certificate and Permissions CA that **he** has. -Permissions file can contain permissions for several identities; so subject name of identity +Permissions files can contain permissions for several identities; so subject name of identity certificate exist in permissions file to establish a binding between identity and its permissions. +There are several ways to set up the certificates and signed configuration files to be used with +Cyclone DDS Security. One of them is using OpenSSL, which is described in section +`Creating certificates using OpenSSL`_. ************* Configuration @@ -142,29 +145,21 @@ The configuration of DDS Security is split up into two parts. - `Plugins Configuration`_ - `Access Control Configuration`_ -This section explains the configuration in details. However, you can see a concrete example on -security section of Example Readme file. - -.. _`Plugins Configuration`: - Plugins Configuration ********************* -TODO: Update to reflect the configuration through QoS policies. +CycloneDDS gets the security configuration from DDS2I XML configuration elements or from +the participant QoS policies as stated in the DDS Security specification. -| CyclonDDS gets the plugin configuration from DDS2I configuration elements or the Participant QoS - Policies as stated in the DDS Security specification. - -| This behavior allows applications to use DDS Security without update. Only supplying a new - configuration with DDS Security enabled is enough to switch from a non-secure to a secure - deployment. However, the same DDS Security configuration is forced upon all the participants - within the federation. - -| The configuration options are bundled in the ``DDSSecurity`` configuration section in DDS2I. - -| Every DDS Security plugin has its own configuration sub-section. +This behavior allows applications to use DDS Security without recompiling the binaries. +Only supplying a new configuration with DDS Security enabled is enough to switch from a +non-secure to a secure deployment. The configuration is at domain level, which means +that all participants created for that domain receive the same DDS security settings. +The configuration options for a domain are bundled in the ``DDSSecurity`` configuration +section in the CycloneDDS configuration. Every DDS Security plugin has its own configuration +sub-section. .. _`Authentication Properties`: @@ -172,35 +167,31 @@ TODO: Update to reflect the configuration through QoS policies. Authentication Properties ========================= -| To authenticate CycloneDDS, it has to be configured with IdentityCertificate - (DDSSecurity/Authentication/IdentityCertificate - see Configuration Guide - DDS Security). - This IdentityCertificate is used to authenticate all participants of that particular - CycloneDDS domain. +To enable authentication for a node, it has to be configured with an identity certificate +(``DDSSecurity/Authentication/IdentityCertificate``). This identity certificate is used to +authenticate all participants of that particular CycloneDDS domain. Associated with the +identity certificate is the corresponding private key +(``DDSSecurity/Authentication/PrivateKey``). The private key may either be a 2048-bit RSA +or a 256-bit Elliptic Curve Key with a prime256v1 curve. -| Associated with the IdentityCertificate is the corresponding PrivateKey - (DDSSecurity/Authentication/PrivateKey). - The PrivateKey may either be a 2048-bit RSA or a 256-bit Elliptic Curve Key with - a prime256v1 curve. +The certificate of identity CA, which is the issuer of the node's identity certificate, +is configured in ``DDSSecurity/Authentication/IdentityCA``. The public key of the +identity CA (as part of its certificate) shall either be a 2048-bit RSA key or a 256-bit +Elliptic Curve Key for the prime256v1 curve. The identity CA certificate can be a +self-signed certificate. -| IdentityCA (DDSSecurity/Authentication/IdentityCA) is the certificate of Identity Certificate - Authority (CA) which is the issuer of the IdentityCertificate. The public key of the - IdentityCA shall either be a 2048-bit RSA key or a 256-bit Elliptic Curve Key for the prime256v1 - curve. The identity_ca can be a self-signed certificate. +The identity certificate, private key and the identity CA should be a X509 document in PEM +format. It may either be specified directly in the configuration file (as CDATA, prefixed +with ``data:,``) or the configuration file should contain a reference to a corresponding +file (prefixed with ``file:``). -| Currently the IdentityCertificate, IdentityCA and PrivateKey should be a X509 document in pem - format. - It may either be specified directly in the configuration file or the configuration file should - contain a reference to a corresponding file. - -| Optionally the PrivateKey could be protected by a password (DDSSecurity/Authentication/Password). - -| Furthermore the CycloneDDS configuration allows to configure a directory containing additional - IdentityCA's - which are used to verify the identity certificates that are received by remote instances - (DDSSecurity/Authentication/TrustedCADirectory). This option allows to use more than one identity - CA throughout the system. TrustedCADirectory is an extension to DDS Security specification; so it - can not be used when communicating with other vendors. +Optionally the private key could be protected by a password +(``DDSSecurity/Authentication/Password``). +Furthermore the CycloneDDS configuration allows to configure a directory containing additional +identity CA's which are used to verify the identity certificates that are received by remote instances +(``DDSSecurity/Authentication/TrustedCADirectory``). This option allows to use more than one identity +CA throughout the system. .. _`Access Control Properties`: @@ -208,11 +199,11 @@ Authentication Properties Access Control Properties ========================= -Governance Document (DDSSecurity/AccessControl/Governance), -Permissions Document (DDSSecurity/AccessControl/Permissions) and -Permissions CA Certificate (DDSSecurity/AccessControl/PermissionsCA) are required for access -control plugin. See DDS Security section of Configuration Guide for property descriptions. They -can be provided by data itself (with CDATA) or path to file on disk. +A governance document (``DDSSecurity/AccessControl/Governance``), a permissions document +(``DDSSecurity/AccessControl/Permissions``) and the permissions CA certificate +(``DDSSecurity/AccessControl/PermissionsCA``) are required for the access control plugin. +Similar to the authentication plugin properties, these values can be provided as CDATA or +by using a path to a file. .. _`Cryptography Properties`: @@ -221,7 +212,7 @@ can be provided by data itself (with CDATA) or path to file on disk. Cryptography Properties ======================= -Cryptography plugin has no property +The cryptography plugin has no properties in the configuration. .. _`Access Control Configuration`: @@ -229,15 +220,15 @@ Cryptography plugin has no property Access Control Configuration **************************** -| Access Control configuration consists of Governance document and Permissions document. - Both governance and permissions files must be signed by the Permissions CA in S/MIME format. - Participants use their own permissions CA to validate remote permissions. So, all permissions CA - Certificates must be same for all participants. +Access Control configuration consists of Governance document and Permissions document. +Both governance and permissions files must be signed by the Permissions CA in S/MIME format. +Participants use their own permissions CA to validate remote permissions. So, all permissions CA +Certificates must be same for all participants. -| The signed document should use S/MIME version 3.2 format as defined in IETF RFC 5761 using - SignedData Content Type (section 2.4.2 of IETF RFC 5761) formatted as multipart/signed (section - 3.4.3 of IETF RFC 5761). This corresponds to the mime-type application/pkcs7-signature. - Additionally the signer certificate should be be included within the signature. +The signed document should use S/MIME version 3.2 format as defined in IETF RFC 5761 using +SignedData Content Type (section 2.4.2 of IETF RFC 5761) formatted as multipart/signed (section +3.4.3 of IETF RFC 5761). This corresponds to the mime-type application/pkcs7-signature. +Additionally the signer certificate should be be included within the signature. =================== @@ -245,10 +236,12 @@ Governance Document =================== Governance document defines the security behavior of domains and topics. It is an XML document and -its format is specified in OMG DDS Security Version 1.1 Section 9.4.1.2.3 +its format is specified in OMG DDS Security Version 1.1 Section 9.4.1.2.3. -The attributes that specified in Governance document must match with the remote one for -establishing communication. +This section describes the properties that can be specified in a permissions document. An example +of a governance document is provided in `Create a signed governance document`_. The options +that are specified in Governance document must match with the remote node to establishing +communication. Protection Kinds @@ -345,9 +338,8 @@ Topic Attributes There are different settings for different domain ranges. The domain rules are evaluated in the same order as they appear in the document. A rule only applies to a particular DomainParticipant -if the domain Section matches the DDS domain_id to -which the DomainParticipant belongs. If multiple rules match, the first rule that matches is the -only one that applies. +if the domain Section matches the DDS domain_id to which the participant belongs. If multiple +rules match, the first rule that matches is the only one that applies. The topic access rules are evaluated in the same order as they appear within the Section. If multiple rules match the first rule that matches is the only one @@ -378,6 +370,9 @@ The permissions document is an XML document containing the permissions of the do and binding them to the subject name of the DomainParticipant as defined in the identity certificate. Its format is specified in OMG DDS Security Version 1.1 Section 9.4.1.3. +This section describes the properties that can be specified in a permissions document. An example +of a permissions document is provided in `Creating a signed permissions document`_. + Validity period =============== @@ -394,20 +389,19 @@ The subject name must match with Identity Certificate subject. It is checked dur participant and during handshake with remote participant. Use the following openssl command to get subject name from identity certificate: -``openssl x509 -noout -subject -nameopt RFC2253 -in `` +``openssl x509 -noout -subject -nameopt RFC2253 -in `` Rules ===== -DomainParticipant permissions are defined by set of rules. - -The rules are applied in the same order that appear in the document. If the criteria for the rule -matches the domain_id join and/or publish or subscribe operation that is being attempted, then the -allow or deny decision is applied. If the criteria for a rule does not match the operation being -attempted, the evaluation shall proceed to the next rule. If all rules have been examined without -a match, then the decision specified by the “default” rule is applied. The default rule, if -present, must appear after all allow and deny rules. If the default rule is not present, the +Participant permissions are defined by set of rules. The rules are applied in the same order +that appear in the document. If the criteria for the rule matches the domain_id join and/or publish +or subscribe operation that is being attempted, then the allow or deny decision is applied. +If the criteria for a rule does not match the operation being attempted, the evaluation +shall proceed to the next rule. If all rules have been examined without a match, then the +decision specified by the “default” rule is applied. The default rule, if present, must +appear after all allow and deny rules. If the default rule is not present, the implied default decision is DENY. The matching criteria for each rule specify the domain_id, topics (published and subscribed), the partitions (published and subscribed), and the data-tags associated with the DataWriter and DataReader. @@ -420,11 +414,11 @@ the expressions with the section). `fnmatch pattern matching`_ can be used for topic expressions and partition expressions. -Interactions with DDS Security -****************************** +Logging and tracing +******************* -DDS Security provides the responses through CycloneDDS error and info log. Users can get -messages for: +The security implementation uses the standard logging and tracing mechanism in CycloneDDS. +The following is written to log and trace: - Configuration errors such as plugin library files, certificate files, governance and permissions files that can not be found on filesystem. @@ -433,17 +427,16 @@ messages for: readers and writers. - Integrity errors such as Permissions file-Permissions CA and Identity Cert-Identity CA integrity. -Local subscription, publication and topic permission errors are written to error log. -Remote participation, subscription and publication permission errors are written to info log as -warning message. +Local subscription, publication and topic permission errors are written as errors. +Remote participation, subscription and publication permission errors are written to log as +warning messages. Data Communication And Handshake Process -******************************************* +**************************************** -Authentication handshake between participants starts after participant discovery. -If a reader and a writer created during that period, their match will be delayed until after the -handshake succeeds. +Authentication handshake between participants starts after participant discovery. If a reader and +a writer created during that period, their match will be delayed until after the handshake succeeds. This means, during the handshake process, volatile data will be lost, just like there is no reader. After publication match, the encryption / decryption keys are exchanged between reader and writer. @@ -452,12 +445,11 @@ resent. DDS Secure Discovery -****************************** +******************** Just like normal operation, DDSI will discover local and remote participants, topics, readers and -writers. -However, when DDS Security is enabled, it is more complex and will take a longer time (especially -due to the handshaking that has to happen). +writers. However, when DDS Security is enabled, it is more complex and will take a longer time +(due to the handshaking that is required). With every new node in the system, the discovery takes exponentially longer. This can become a problem if the system contains a number of slow platforms or is large. @@ -467,30 +459,199 @@ Internal/SquashParticipants configuration. Proprietary builtin endpoints -****************************** +***************************** -| The DDS standard contains some builtin endpoints. A few are added by the DDS Security - specification. The behaviour of all these builtin endpoints are specified (and thus are be - handled by the plugins that implement the DDS Security specification), meaning that they - don't have to be present in the Governance or Permissions documents and the users don't - have to be bothered with them. -| -| A few of these builtin endpoints slave according to the within - the Governance document. In short, related submessages are protected according to the value - of . This protects meta information that is send during the - discovery phase. +The DDS standard contains some builtin endpoints. A few are added by the DDS Security +specification. The behaviour of all these builtin endpoints are specified (and thus are be +handled by the plugins that implement the DDS Security specification), meaning that they +don't have to be present in the Governance or Permissions documents and the users don't +have to be bothered with them. + +A few of these builtin endpoints slave according to the within +the Governance document. In short, related submessages are protected according to the value +of . This protects meta information that is send during the +discovery phase. ******************* DataTag Permissions ******************* -| Data Tags provide an extra (optional) level of identification. This can mean f.i. that - a certain reader is not allowed to read data from writer A but it is allowed to read from - writer B (all the same topic). -| -| This optional feature is not yet supported. +Data Tags provide an extra (optional) level of identification. This can mean f.i. that +a certain reader is not allowed to read data from writer A but it is allowed to read from +writer B (all the same topic). +This optional feature is not yet supported. + + +.. _`Example configuration`: + +********************* +Example configuration +********************* + +This sections show an example configuration for DDS Security in Cyclone DDS. First step is +creating the required CA and identity certificates. Then a governance and permissions document +is created to configure access control. Next an example configuration (XML) that +is using these assets is shown, and a code fragment that shows how to set the security +properties by using the participant QoS. + + +.. _`Creating certificates using OpenSSL`: + +Creating certificates using OpenSSL +*********************************** + +This section describes how to generate a set of CA and identity certificates using OpenSSL, +and how to use OpenSSL to sign the governance and access control configuration files. + +First step is generation of the CA for identity management (authentication). First we create the +private key for the CA by: + +.. code-block:: bash + + openssl genrsa -out example_id_ca_priv_key.pem 2048 + +Next we can generate the certificate for the identity CA (which is in this case a self-signed +certificate): + +.. code-block:: bash + + openssl req -x509 -key example_id_ca_priv_key.pem -out example_id_ca_cert.pem -days 3650 -subj "/C=NL/ST=OV/L=Locality Name/OU=Example OU/O=Example ID CA Organization/CN=Example ID CA/emailAddress=authority@cycloneddssecurity.adlinktech.com" + +We repeat these steps for generating the private key of the permissions CA (used for +signing the AccessControl configiguration files): + +.. code-block:: bash + + openssl genrsa -out example_perm_ca_priv_key.pem 2048 + +And the self-signed certificate for the permissions CA: + +.. code-block:: bash + + openssl req -x509 -key example_perm_ca_priv_key.pem -out example_perm_ca_cert.pem -days 3650 -subj "/C=NL/ST=OV/L=Locality Name/OU=Example OU/O=Example CA Organization/CN=Example Permissions CA/emailAddress=authority@cycloneddssecurity.adlinktech.com" + +============================== +Create an Identity Certificate +============================== + +Now that we have set up the CA for identity management, we can create an identity certificate +signed by this CA and the private key corresponding to this identity. Here we are creating +a private key and certificate for identity named Alice. These steps need to be repeated for each +identity in the system. + +Generating the private key for Alice's identity: + +.. code-block:: bash + + openssl genrsa -out example_alice_priv_key.pem 2048 + +Now we create a 'certificate signing request' (CSR) to request the identity CA to generate a certificate: + +.. code-block:: bash + + openssl req -new -key example_alice_priv_key.pem -out example_alice.csr -subj "/C=NL/ST=OV/L=Locality Name/OU=Organizational Unit Name/O=Example Organization/CN=Alice Example/emailAddress=alice@cycloneddssecurity.adlinktech.com" + +Next Alice's identity certificate is created: + +.. code-block:: bash + + openssl x509 -req -CA example_id_ca_cert.pem -CAkey example_id_ca_priv_key.pem -CAcreateserial -days 3650 -in example_alice.csr -out example_alice_cert.pem + + +Now the file 'example_alice_cert.pem' can be used as ``IdentityCertificate`` in the DDS Security +authentication configuration and 'example_alice_priv_key.pem' for the ``PrivateKey`` setting. The +certificate of the CA used for signing this identity, 'example_id_ca_cert.pem' in this example, +should be used for the ``IdentityCA`` configuration setting. + + +.. _`Create a signed governance document`: + +=================================== +Create a signed governance document +=================================== + +An example of a governance document that is using signing for submessage and encrypted payload: + +.. literalinclude:: _static/example_governance.xml + :linenos: + :language: xml + +As mentioned before, the governance document needs to be signed by the permissions CA +that was created above. This can be done by using this openssl command: + +.. code-block:: bash + + openssl smime -sign -in example_governance.xml -text -out example_governance.p7s -signer example_perm_ca_cert.pem -inkey example_perm_ca_priv_key.pem + + +.. _`Creating a signed permissions document`: + +====================================== +Creating a signed permissions document +====================================== + +The permissions document is an XML document that contains the permissions of the participant and +binds them to the subject name of the identity certificate (distinguished name) for the participant +as defined in the DDS:Auth:PKI-DH authentication plugin. + +An example of a permissions document: + +.. literalinclude:: _static/example_permissions.xml + :linenos: + :language: xml + +This document also needs to be signed by the permissions CA: + +.. code-block:: bash + + openssl smime -sign -in example_permissions.xml -text -out example_permissions.p7s -signer example_perm_ca_cert.pem -inkey example_perm_ca_priv_key.pem + + +Example DDS Security configuration +********************************** + +With the above steps we have all certificates and documents that are required when configuring +security. In the next two sections, both configuring security by properties and configuring +security by DDS configuration are covered. + +====================================== +Security properties in participant QoS +====================================== + +This code fragment shows how to set the security properties to a QoS object and use this QoS +when creating a participant: + +.. literalinclude:: _static/security_by_qos.c + :linenos: + :language: c + + +=========================================== +Configure security in Cyclone configuration +=========================================== + +As an alternative for using the QoS, security settings can also be applied using the CycloneDDS +configuration XML. In case both QoS and the configuration XML contain security settings, the values +from the QoS will be used and the security settings in the configuration XML are ignored. + +The following XML fragment shows how to set security settings through configuration: + +.. literalinclude:: _static/security_by_config.xml + :linenos: + :language: xml + +To use this configuration file for an application, set the CYCLONEDDS_URI environment +variable to this config file: + +.. code-block:: bash + + export CYCLONEDDS_URI=/path/to/secure_config.xml + +Bacause this example configuration uses the attribute ``id=any`` for the ``domain`` element, any participant +that is created (which implicitly creates a domain) in an application using this configuration gets +these security settings. *************************** External Plugin Development @@ -502,7 +663,7 @@ The plugins are loaded in the run-time. However, you can also implement your own implementing the given API according to OMG DDS Security specification. You can implement all of the plugins or just one of them. -| The followings are the key points for implementing you own plugin: +The followings are the key points for implementing you own plugin: Interface @@ -516,24 +677,23 @@ dds_security_api_cryptography.h header files accordingly. Init and Finalize ***************** -| A plugin should have an init and a finalize functions. plugin_init and plugin_finalize - interfaces are given in dds_security_api.h header file and function should be same as in - configuration file. -| Init function is called once, just after the plugin is loaded. Finalize function is - called once, just before the plugin is unloaded. - +A plugin should have an init and a finalize functions. plugin_init and plugin_finalize +interfaces are given in dds_security_api.h header file and function should be same as in +configuration file. +Init function is called once, just after the plugin is loaded. Finalize function is +called once, just before the plugin is unloaded. Inter Plugin Communication ************************** -| There is a shared object (*DDS_Security_SharedSecretHandle*) within authentication and - cryptography plugins. If you want to implement only one of them and use the builtin for the - other one, you have to get or provide the shared object properly. -| *DDS_Security_SharedSecretHandle* is the integer representation of - *DDS_Security_SharedSecretHandleImpl* struct object. Cryptography plugin gets the - *DDS_Security_SharedSecretHandle* from authentication plugin and casts to - *DDS_Security_SharedSecretHandleImpl* struct. Then all needed information can be retieved - through *DDS_Security_SharedSecretHandleImpl* struct: +There is a shared object (*DDS_Security_SharedSecretHandle*) within authentication and +cryptography plugins. If you want to implement only one of them and use the builtin for the +other one, you have to get or provide the shared object properly. +*DDS_Security_SharedSecretHandle* is the integer representation of +*DDS_Security_SharedSecretHandleImpl* struct object. Cryptography plugin gets the +*DDS_Security_SharedSecretHandle* from authentication plugin and casts to +*DDS_Security_SharedSecretHandleImpl* struct. Then all needed information can be retieved +through *DDS_Security_SharedSecretHandleImpl* struct: :: @@ -549,9 +709,9 @@ Inter Plugin Communication Error Codes *********** -| Most of the plugin functions have parameter for reporting exception. The following exception - codes should be used in the reported exception data according to the situation. - dds_security_api_err.h header file contains the code and message constants. +Most of the plugin functions have parameter for reporting exception. The following exception +codes should be used in the reported exception data according to the situation. +dds_security_api_err.h header file contains the code and message constants. +-------+----------------------------------------------------------------+ | Code | Message | @@ -638,9 +798,11 @@ Error Codes +-------+----------------------------------------------------------------+ | 149 | Could not find valid grant in permissions | +-------+----------------------------------------------------------------+ -| 150 | Permissions of subject (%s) outside validity date: %s - %s | +| 150 | Unsupported URI type: %s | +-------+----------------------------------------------------------------+ -| 151 | Unsupported URI type: %s | +| 151 | The payload is not aligned at 4 bytes | ++-------+----------------------------------------------------------------+ +| 200 | Undefined Error Message | +-------+----------------------------------------------------------------+ .. EoF From 24e42fd658c087e9eb019c8b45429251c44140cb Mon Sep 17 00:00:00 2001 From: eboasson Date: Tue, 3 Mar 2020 16:14:33 +0100 Subject: [PATCH 108/238] Fix a few typos in security documentation Signed-off-by: Erik Boasson --- docs/manual/security.rst | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/docs/manual/security.rst b/docs/manual/security.rst index 5311b85..078a013 100644 --- a/docs/manual/security.rst +++ b/docs/manual/security.rst @@ -42,9 +42,6 @@ authentication and Diffie-Hellman is used for key exchange. AccessControl use Pe signed by shared Certificate Authority. Cryptography uses AES-GCM (AES using Galois Counter Mode) for encryption and AES-GMAC for message authentication. -The plugins are accessed by the DDSI2 service when DDS Security is enabled by supplying the -security configuration within the XML configuration or Participant QoS. - Security plugins are dynamically loaded where the locations are defined in CycloneDDS configuration or Participant QoS settings. @@ -149,7 +146,7 @@ The configuration of DDS Security is split up into two parts. Plugins Configuration ********************* -CycloneDDS gets the security configuration from DDS2I XML configuration elements or from +CycloneDDS gets the security configuration from XML configuration elements or from the participant QoS policies as stated in the DDS Security specification. This behavior allows applications to use DDS Security without recompiling the binaries. @@ -188,10 +185,10 @@ file (prefixed with ``file:``). Optionally the private key could be protected by a password (``DDSSecurity/Authentication/Password``). -Furthermore the CycloneDDS configuration allows to configure a directory containing additional -identity CA's which are used to verify the identity certificates that are received by remote instances -(``DDSSecurity/Authentication/TrustedCADirectory``). This option allows to use more than one identity -CA throughout the system. +Furthermore the CycloneDDS configuration allows configuring a directory containing additional +identity CA's which are used to verify the identity certificates that are received from remote instances +(``DDSSecurity/Authentication/TrustedCADirectory``). This option allows multiple identity +CAs throughout the system. .. _`Access Control Properties`: @@ -223,7 +220,7 @@ Access Control Configuration Access Control configuration consists of Governance document and Permissions document. Both governance and permissions files must be signed by the Permissions CA in S/MIME format. Participants use their own permissions CA to validate remote permissions. So, all permissions CA -Certificates must be same for all participants. +Certificates must be the same for all participants. The signed document should use S/MIME version 3.2 format as defined in IETF RFC 5761 using SignedData Content Type (section 2.4.2 of IETF RFC 5761) formatted as multipart/signed (section @@ -235,8 +232,8 @@ Additionally the signer certificate should be be included within the signature. Governance Document =================== -Governance document defines the security behavior of domains and topics. It is an XML document and -its format is specified in OMG DDS Security Version 1.1 Section 9.4.1.2.3. +The Governance document defines the security behavior of domains and topics. It is an XML document +and its format is specified in OMG DDS Security Version 1.1 Section 9.4.1.2.3. This section describes the properties that can be specified in a permissions document. An example of a governance document is provided in `Create a signed governance document`_. The options @@ -377,9 +374,8 @@ of a permissions document is provided in `Creating a signed permissions document Validity period =============== -It is checked before creating participant; expired permissions document results with DDSI shutdown. -Validity period is also checked during handshake with remote participant; expired remote -permissions document prevents communications to be established. +It is checked before creating participant. Validity period is also checked during handshake with +remote participant; expired remote permissions document prevents communications to be established. Subject Name @@ -447,15 +443,10 @@ resent. DDS Secure Discovery ******************** -Just like normal operation, DDSI will discover local and remote participants, topics, readers and -writers. However, when DDS Security is enabled, it is more complex and will take a longer time -(due to the handshaking that is required). - -With every new node in the system, the discovery takes exponentially longer. This can become a -problem if the system contains a number of slow platforms or is large. - -The Security discovery performance can be increased quite a bit by using the DDSI -Internal/SquashParticipants configuration. +Just like normal operation, Cyclone DDS discovers remote participants, topics, readers and writers. +However, when DDS Security is enabled, it is more complex and will take a longer time (due to the +handshaking that is required). The effort to perform discovery grows quadratically in the number of +nodes. This can become a problem if the system contains a number of slow platforms or is large. Proprietary builtin endpoints From b3c5a8d4fcf43e9c75780feb6b89a9beb2ed89f7 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Mon, 24 Feb 2020 14:03:25 +0100 Subject: [PATCH 109/238] Refactored expand_vars so that a custom lookup function can be used, which makes it usable for replacing tags by values other than environment variables Signed-off-by: Dennis Potman --- src/core/ddsc/src/dds_participant.c | 2 +- src/core/ddsc/tests/config.c | 2 +- src/core/ddsc/tests/participant.c | 2 +- src/ddsrt/CMakeLists.txt | 3 +- src/ddsrt/include/dds/ddsrt/environ.h | 3 +- src/ddsrt/include/dds/ddsrt/expand_vars.h | 78 +++++++++++++++++++ src/ddsrt/src/environ.c | 59 ++++++++++++++ src/ddsrt/src/environ/posix/environ.c | 2 +- src/ddsrt/src/environ/solaris2.6/environ.c | 2 +- src/ddsrt/src/environ/windows/environ.c | 2 +- .../src/{expand_envvars.c => expand_vars.c} | 62 ++++++--------- src/ddsrt/src/xmlparser.c | 6 +- src/ddsrt/tests/environ.c | 4 +- src/ddsrt/tests/process_app.c | 2 +- 14 files changed, 180 insertions(+), 49 deletions(-) create mode 100644 src/ddsrt/include/dds/ddsrt/expand_vars.h create mode 100644 src/ddsrt/src/environ.c rename src/ddsrt/src/{expand_envvars.c => expand_vars.c} (72%) diff --git a/src/core/ddsc/src/dds_participant.c b/src/core/ddsc/src/dds_participant.c index 3cbb48d..5d84fb8 100644 --- a/src/core/ddsc/src/dds_participant.c +++ b/src/core/ddsc/src/dds_participant.c @@ -96,7 +96,7 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_ dds_participant * pp; ddsi_plist_t plist; dds_qos_t *new_qos = NULL; - char *config = ""; + const char *config = ""; /* Make sure DDS instance is initialized. */ if ((ret = dds_init ()) < 0) diff --git a/src/core/ddsc/tests/config.c b/src/core/ddsc/tests/config.c index a7d2bec..546062a 100644 --- a/src/core/ddsc/tests/config.c +++ b/src/core/ddsc/tests/config.c @@ -29,7 +29,7 @@ static void config__check_env (const char *env_variable, const char *expected_value) { - char *env_uri = NULL; + const char *env_uri = NULL; ddsrt_getenv (env_variable, &env_uri); #ifdef FORCE_ENV { diff --git a/src/core/ddsc/tests/participant.c b/src/core/ddsc/tests/participant.c index 6100f5d..70697a5 100644 --- a/src/core/ddsc/tests/participant.c +++ b/src/core/ddsc/tests/participant.c @@ -111,7 +111,7 @@ CU_Test(ddsc_participant, create_with_conf_no_env) { ddsrt_setenv(DDS_PROJECT_NAME_NOSPACE_CAPS"_URI", CONFIG_ENV_SIMPLE_UDP); ddsrt_setenv("MAX_PARTICIPANTS", CONFIG_ENV_MAX_PARTICIPANTS); - char * env_uri = NULL; + const char * env_uri = NULL; ddsrt_getenv(DDS_PROJECT_NAME_NOSPACE_CAPS"_URI", &env_uri); CU_ASSERT_PTR_NOT_EQUAL_FATAL(env_uri, NULL); diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index 6efefdd..b81f86b 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -131,7 +131,8 @@ list(APPEND sources "${source_path}/strtol.c" "${source_path}/mh3.c" "${source_path}/avl.c" - "${source_path}/expand_envvars.c" + "${source_path}/environ.c" + "${source_path}/expand_vars.c" "${source_path}/fibheap.c" "${source_path}/hopscotch.c" "${source_path}/thread_pool.c" diff --git a/src/ddsrt/include/dds/ddsrt/environ.h b/src/ddsrt/include/dds/ddsrt/environ.h index d5d895e..dd65f01 100644 --- a/src/ddsrt/include/dds/ddsrt/environ.h +++ b/src/ddsrt/include/dds/ddsrt/environ.h @@ -14,6 +14,7 @@ #include "dds/export.h" #include "dds/ddsrt/attributes.h" +#include "dds/ddsrt/expand_vars.h" #include "dds/ddsrt/retcode.h" #if defined(__cplusplus) @@ -42,7 +43,7 @@ extern "C" { DDS_EXPORT dds_return_t ddsrt_getenv( const char *name, - char **value) + const char **value) ddsrt_nonnull_all; /** diff --git a/src/ddsrt/include/dds/ddsrt/expand_vars.h b/src/ddsrt/include/dds/ddsrt/expand_vars.h new file mode 100644 index 0000000..78b2326 --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/expand_vars.h @@ -0,0 +1,78 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSRT_EXPAND_VARS_H +#define DDSRT_EXPAND_VARS_H + +#include "dds/export.h" +#include "dds/ddsrt/attributes.h" +#include "dds/ddsrt/retcode.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef const char * (*expand_lookup_fn)(const char *name, void *data); + +/** + * @brief Expand variables within string. + * + * Expands ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, but not $X. + * + * The result string should be freed with ddsrt_free(). + * + * @param[in] string String to expand. + * @param[in] lookup Lookup function to retrieve replacement value + * @param[in] data Data passed to lookup function + * + * @returns Allocated char*. + * + * @retval NULL + * Expansion failed. + * @retval Pointer + * Copy of the string argument with the variables expanded. + */ +DDS_EXPORT char* +ddsrt_expand_vars( + const char *string, + expand_lookup_fn lookup, + void * data); + +/** + * @brief Expand variables within string. + * + * Expands $X, ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, $ and \ + * can be escaped with \. + * + * The result string should be freed with ddsrt_free(). + * + * @param[in] string String to expand. + * @param[in] lookup Lookup function to retrieve replacement value + * @param[in] data Data passed to lookup function + * + * @returns Allocated char*. + * + * @retval NULL + * Expansion failed. + * @retval Pointer + * Copy of the string argument with the variables expanded. + */ +DDS_EXPORT char* +ddsrt_expand_vars_sh( + const char *string, + expand_lookup_fn lookup, + void * data); + +#if defined(__cplusplus) +} +#endif + +#endif /* DDSRT_EXPAND_VARS_H */ diff --git a/src/ddsrt/src/environ.c b/src/ddsrt/src/environ.c new file mode 100644 index 0000000..501d92b --- /dev/null +++ b/src/ddsrt/src/environ.c @@ -0,0 +1,59 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include +#include + +#include "dds/ddsrt/expand_vars.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/log.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/process.h" + +struct expand_env_data +{ + uint32_t domid; + char idstr[20]; +}; + +static const char * expand_lookup_env(const char *name, void * data) +{ + const char *env = NULL; + struct expand_env_data * env_data = data; + + if (ddsrt_getenv (name, &env) == DDS_RETCODE_OK) { + /* ok */ + } else if (strcmp (name, "$") == 0 || strcmp (name, "CYCLONEDDS_PID") == 0) { + (void) snprintf (env_data->idstr, sizeof (env_data->idstr), "%"PRIdPID, ddsrt_getpid ()); + env = env_data->idstr; + } else if (strcmp (name, "CYCLONEDDS_DOMAIN_ID") == 0 && env_data->domid != UINT32_MAX) { + (void) snprintf (env_data->idstr, sizeof (env_data->idstr), "%"PRIu32, env_data->domid); + env = env_data->idstr; + } + return env; +} + +char *ddsrt_expand_envvars_sh (const char *src0, uint32_t domid) +{ + struct expand_env_data env = { .domid = domid, .idstr = "" }; + return ddsrt_expand_vars_sh(src0, &expand_lookup_env, &env); +} + +char *ddsrt_expand_envvars (const char *src0, uint32_t domid) +{ + struct expand_env_data env = { .domid = domid, .idstr = "" }; + return ddsrt_expand_vars(src0, &expand_lookup_env, &env); +} + diff --git a/src/ddsrt/src/environ/posix/environ.c b/src/ddsrt/src/environ/posix/environ.c index 1f8b84f..c2e61a9 100644 --- a/src/ddsrt/src/environ/posix/environ.c +++ b/src/ddsrt/src/environ/posix/environ.c @@ -24,7 +24,7 @@ isenvvar(const char *name) } dds_return_t -ddsrt_getenv(const char *name, char **value) +ddsrt_getenv(const char *name, const char **value) { char *env; diff --git a/src/ddsrt/src/environ/solaris2.6/environ.c b/src/ddsrt/src/environ/solaris2.6/environ.c index 83f0d8f..07d113a 100644 --- a/src/ddsrt/src/environ/solaris2.6/environ.c +++ b/src/ddsrt/src/environ/solaris2.6/environ.c @@ -27,7 +27,7 @@ isenvvar(const char *name) } dds_return_t -ddsrt_getenv(const char *name, char **value) +ddsrt_getenv(const char *name, const char **value) { char *env; diff --git a/src/ddsrt/src/environ/windows/environ.c b/src/ddsrt/src/environ/windows/environ.c index a5b2f90..7589545 100644 --- a/src/ddsrt/src/environ/windows/environ.c +++ b/src/ddsrt/src/environ/windows/environ.c @@ -26,7 +26,7 @@ isenvvar(const char *name) DDSRT_WARNING_MSVC_OFF(4996) dds_return_t -ddsrt_getenv(const char *name, char **value) +ddsrt_getenv(const char *name, const char **value) { char *env; diff --git a/src/ddsrt/src/expand_envvars.c b/src/ddsrt/src/expand_vars.c similarity index 72% rename from src/ddsrt/src/expand_envvars.c rename to src/ddsrt/src/expand_vars.c index faa166a..e0396bd 100644 --- a/src/ddsrt/src/expand_envvars.c +++ b/src/ddsrt/src/expand_vars.c @@ -15,13 +15,13 @@ #include #include -#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/expand_vars.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/log.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/process.h" -typedef char * (*expand_fn)(const char *src0, uint32_t domid); +typedef char * (*expand_fn)(const char *src0, expand_lookup_fn lookup, void * data); static void expand_append (char **dst, size_t *sz, size_t *pos, char c) { @@ -33,46 +33,33 @@ static void expand_append (char **dst, size_t *sz, size_t *pos, char c) (*pos)++; } -static char *expand_env (const char *name, char op, const char *alt, expand_fn expand, uint32_t domid) +static char *expand_var (const char *name, char op, const char *alt, expand_fn expand, expand_lookup_fn lookup, void * data) { - char idstr[20]; - char *env = NULL; - dds_return_t ret; - - if ((ret = ddsrt_getenv (name, &env)) == DDS_RETCODE_OK) { - /* ok */ - } else if (strcmp (name, "$") == 0 || strcmp (name, "CYCLONEDDS_PID") == 0) { - (void) snprintf (idstr, sizeof (idstr), "%"PRIdPID, ddsrt_getpid ()); - env = idstr; - } else if (strcmp (name, "CYCLONEDDS_DOMAIN_ID") == 0 && domid != UINT32_MAX) { - (void) snprintf (idstr, sizeof (idstr), "%"PRIu32, domid); - env = idstr; - } - + const char *val = lookup (name, data); switch (op) { case 0: - return ddsrt_strdup (env ? env : ""); + return ddsrt_strdup (val ? val : ""); case '-': - return env && *env ? ddsrt_strdup (env) : expand (alt, domid); + return val && *val ? ddsrt_strdup (val) : expand (alt, lookup, data); case '?': - if (env && *env) { - return ddsrt_strdup (env); + if (val && *val) { + return ddsrt_strdup (val); } else { - char *altx = expand (alt, domid); - DDS_ILOG (DDS_LC_ERROR, domid, "%s: %s\n", name, altx); + char *altx = expand (alt, lookup, data); + DDS_LOG (DDS_LC_ERROR, "%s: %s\n", name, altx); ddsrt_free (altx); return NULL; } case '+': - return env && *env ? expand (alt, domid) : ddsrt_strdup (""); + return val && *val ? expand (alt, lookup, data) : ddsrt_strdup (""); default: abort (); return NULL; } } -static char *expand_envbrace (const char **src, expand_fn expand, uint32_t domid) +static char *expand_varbrace (const char **src, expand_fn expand, expand_lookup_fn lookup, void * data) { const char *start = *src + 1; char *name, *x; @@ -89,7 +76,7 @@ static char *expand_envbrace (const char **src, expand_fn expand, uint32_t domid name[*src - start] = 0; if (**src == '}') { (*src)++; - x = expand_env (name, 0, NULL, expand, domid); + x = expand_var (name, 0, NULL, expand, lookup, data); ddsrt_free (name); return x; } else { @@ -133,7 +120,7 @@ static char *expand_envbrace (const char **src, expand_fn expand, uint32_t domid memcpy (alt, altstart, (size_t) (*src - altstart)); alt[*src - altstart] = 0; (*src)++; - x = expand_env (name, op, alt, expand, domid); + x = expand_var (name, op, alt, expand, lookup, data); ddsrt_free (alt); ddsrt_free (name); return x; @@ -143,7 +130,7 @@ err: return NULL; } -static char *expand_envsimple (const char **src, expand_fn expand, uint32_t domid) +static char *expand_varsimple (const char **src, expand_fn expand, expand_lookup_fn lookup, void * data) { const char *start = *src; char *name, *x; @@ -154,22 +141,22 @@ static char *expand_envsimple (const char **src, expand_fn expand, uint32_t domi name = ddsrt_malloc ((size_t) (*src - start) + 1); memcpy (name, start, (size_t) (*src - start)); name[*src - start] = 0; - x = expand_env (name, 0, NULL, expand, domid); + x = expand_var (name, 0, NULL, expand, lookup, data); ddsrt_free (name); return x; } -static char *expand_envchar (const char **src, expand_fn expand, uint32_t domid) +static char *expand_varchar (const char **src, expand_fn expand, expand_lookup_fn lookup, void * data) { char name[2]; assert (**src); name[0] = **src; name[1] = 0; (*src)++; - return expand_env (name, 0, NULL, expand, domid); + return expand_var (name, 0, NULL, expand, lookup, data); } -char *ddsrt_expand_envvars_sh (const char *src0, uint32_t domid) +char *ddsrt_expand_vars_sh (const char *src0, expand_lookup_fn lookup, void * data) { /* Expands $X, ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms; $ and \ can be escaped with \ */ const char *src = src0; @@ -192,11 +179,11 @@ char *ddsrt_expand_envvars_sh (const char *src0, uint32_t domid) ddsrt_free(dst); return NULL; } else if (*src == '{') { - x = expand_envbrace (&src, &ddsrt_expand_envvars_sh, domid); + x = expand_varbrace (&src, &ddsrt_expand_vars_sh, lookup, data); } else if (isalnum ((unsigned char) *src) || *src == '_') { - x = expand_envsimple (&src, &ddsrt_expand_envvars_sh, domid); + x = expand_varsimple (&src, &ddsrt_expand_vars_sh, lookup, data); } else { - x = expand_envchar (&src, &ddsrt_expand_envvars_sh, domid); + x = expand_varchar (&src, &ddsrt_expand_vars_sh, lookup, data); } if (x == NULL) { ddsrt_free(dst); @@ -215,7 +202,7 @@ char *ddsrt_expand_envvars_sh (const char *src0, uint32_t domid) return dst; } -char *ddsrt_expand_envvars (const char *src0, uint32_t domid) +char *ddsrt_expand_vars (const char *src0, expand_lookup_fn lookup, void * data) { /* Expands ${X}, ${X:-Y}, ${X:+Y}, ${X:?Y} forms, but not $X */ const char *src = src0; @@ -225,7 +212,7 @@ char *ddsrt_expand_envvars (const char *src0, uint32_t domid) if (*src == '$' && *(src + 1) == '{') { char *x, *xp; src++; - x = expand_envbrace (&src, &ddsrt_expand_envvars, domid); + x = expand_varbrace (&src, &ddsrt_expand_vars, lookup, data); if (x == NULL) { ddsrt_free(dst); return NULL; @@ -242,3 +229,4 @@ char *ddsrt_expand_envvars (const char *src0, uint32_t domid) expand_append (&dst, &sz, &pos, 0); return dst; } + diff --git a/src/ddsrt/src/xmlparser.c b/src/ddsrt/src/xmlparser.c index 873aa0d..8820b71 100644 --- a/src/ddsrt/src/xmlparser.c +++ b/src/ddsrt/src/xmlparser.c @@ -27,9 +27,12 @@ #define TOK_CLOSE_TAG -5 #define TOK_SHORTHAND_CLOSE_TAG -6 #define TOK_ERROR -7 +#define TOK_CDATA -8 #define NOMARKER (~(size_t)0) +static const char *cdata_magic = ""); return next_token (st, payload); + } else if (peek_chars (st, cdata_magic, 0)) { + tok = TOK_CDATA; } else if (peek_chars (st, ""); return next_token (st, payload); @@ -652,7 +657,6 @@ static int parse_element (struct ddsrt_xmlp_state *st, uintptr_t parentinfo) } } else { /* text */ - static const char *cdata_magic = " Date: Wed, 26 Feb 2020 10:17:01 +0100 Subject: [PATCH 110/238] Moved add_definitions in cmake files to /src/ so that all components and tests use the same definitions when compiling sources Signed-off-by: Dennis Potman --- src/CMakeLists.txt | 36 +++++++++++++++++ src/core/CMakeLists.txt | 40 ++----------------- src/security/CMakeLists.txt | 9 ++--- .../access_control/CMakeLists.txt | 2 - .../cryptographic/CMakeLists.txt | 2 - .../builtin_plugins/tests/CMakeLists.txt | 1 - 6 files changed, 44 insertions(+), 46 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b21ad73..ee0b287 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,11 +16,47 @@ if(NOT ${PROJECT_NAME} STREQUAL "CycloneDDS") message(FATAL_ERROR "Top-level CMakeLists.txt was moved to the top-level directory. Please run cmake on ${dir} instead of ${CMAKE_CURRENT_LIST_DIR}") endif() +add_definitions(-DDDSI_INCLUDE_NETWORK_PARTITIONS -DDDSI_INCLUDE_SSM) + +# OpenSSL is huge, raising the RSS by 1MB or so, and moreover find_package(OpenSSL) causes +# trouble on some older CMake versions that otherwise work fine, so provide an option to avoid +# all OpenSSL related things. +# +# Historically the option was DDSC_ENABLE_OPENSSL so make some allowance for those who are +# currently relying on it. +option(ENABLE_SSL "Enable openssl support" ON) +option(DDSC_ENABLE_OPENSSL "Deprecated: please use ENABLE_SSL instead" ON) +if(NOT DDSC_ENABLE_OPENSSL) + message(ERROR "DDSC_ENABLE_OPENSSL is deprecated, please use ENABLE_SSL instead") + set(ENABLE_SSL OFF) +endif() + +if(ENABLE_SSL) + find_package(OpenSSL) + if(OPENSSL_FOUND) + add_definitions(-DDDSI_INCLUDE_SSL) + message(STATUS "Building with OpenSSL support") + else() + message(STATUS "Building without OpenSSL support") + endif() +endif() # Support the OMG DDS Security within ddsc adds quite a bit of code. option(ENABLE_SECURITY "Enable OMG DDS Security support" ON) if(NOT ENABLE_SECURITY) message(STATUS "Building without OMG DDS Security support") +else() + add_definitions(-DDDSI_INCLUDE_SECURITY) +endif() + +option(ENABLE_LIFESPAN "Enable Lifespan QoS support" ON) +if(ENABLE_LIFESPAN) + add_definitions(-DDDSI_INCLUDE_LIFESPAN) +endif() + +option(ENABLE_DEADLINE_MISSED "Enable Deadline Missed QoS support" ON) +if(ENABLE_DEADLINE_MISSED) + add_definitions(-DDDSI_INCLUDE_DEADLINE_MISSED) endif() add_subdirectory(ddsrt) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 9da094a..b2fbfe6 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -25,47 +25,15 @@ else() add_library(ddsc) endif() -add_definitions(-DDDSI_INCLUDE_NETWORK_PARTITIONS -DDDSI_INCLUDE_SSM) - -option(ENABLE_LIFESPAN "Enable Lifespan QoS support" ON) -if(ENABLE_LIFESPAN) - add_definitions(-DDDSI_INCLUDE_LIFESPAN) -endif() - -option(ENABLE_DEADLINE_MISSED "Enable Deadline Missed QoS support" ON) -if(ENABLE_DEADLINE_MISSED) - add_definitions(-DDDSI_INCLUDE_DEADLINE_MISSED) -endif() - -# OpenSSL is huge, raising the RSS by 1MB or so, and moreover find_package(OpenSSL) causes -# trouble on some older CMake versions that otherwise work fine, so provide an option to avoid -# all OpenSSL related things. -# -# Historically the option was DDSC_ENABLE_OPENSSL so make some allowance for those who are -# currently relying on it. -option(ENABLE_SSL "Enable openssl support" ON) -option(DDSC_ENABLE_OPENSSL "Deprecated: please use ENABLE_SSL instead" ON) -if(NOT DDSC_ENABLE_OPENSSL) - message(ERROR "DDSC_ENABLE_OPENSSL is deprecated, please use ENABLE_SSL instead") - set(ENABLE_SSL OFF) -endif() -if(ENABLE_SSL) - find_package(OpenSSL) - if(OPENSSL_FOUND) - add_definitions(-DDDSI_INCLUDE_SSL) - target_link_libraries(ddsc PRIVATE OpenSSL::SSL) - if(CMAKE_GENERATOR MATCHES "Visual Studio") - set_target_properties(ddsc PROPERTIES LINK_FLAGS "/ignore:4099") - endif() - message(STATUS "Building with OpenSSL support") - else() - message(STATUS "Building without OpenSSL support") +if(ENABLE_SSL AND OPENSSL_FOUND) + target_link_libraries(ddsc PRIVATE OpenSSL::SSL) + if(CMAKE_GENERATOR MATCHES "Visual Studio") + set_target_properties(ddsc PROPERTIES LINK_FLAGS "/ignore:4099") endif() endif() # Support the OMG DDS Security within ddsc adds quite a bit of code. if(ENABLE_SECURITY) - add_definitions(-DDDSI_INCLUDE_SECURITY) target_link_libraries(ddsc PRIVATE security_core) target_include_directories( ddsc PUBLIC diff --git a/src/security/CMakeLists.txt b/src/security/CMakeLists.txt index 3b2d8f9..b96c7da 100644 --- a/src/security/CMakeLists.txt +++ b/src/security/CMakeLists.txt @@ -11,12 +11,11 @@ # cmake_minimum_required(VERSION 3.7) -if( ENABLE_SECURITY ) - add_definitions(-DDDSI_INCLUDE_SECURITY) - add_subdirectory(api) - add_subdirectory(core) +if(ENABLE_SECURITY) + add_subdirectory(api) + add_subdirectory(core) - if ( ENABLE_SSL) + if(ENABLE_SSL) add_subdirectory(builtin_plugins) endif() endif() \ No newline at end of file diff --git a/src/security/builtin_plugins/access_control/CMakeLists.txt b/src/security/builtin_plugins/access_control/CMakeLists.txt index c0cee0a..e882b2c 100644 --- a/src/security/builtin_plugins/access_control/CMakeLists.txt +++ b/src/security/builtin_plugins/access_control/CMakeLists.txt @@ -11,8 +11,6 @@ # include (GenerateExportHeader) -find_package(OpenSSL) - PREPEND(srcs_accesscontrol "${CMAKE_CURRENT_LIST_DIR}/src" access_control_objects.c access_control_parser.c diff --git a/src/security/builtin_plugins/cryptographic/CMakeLists.txt b/src/security/builtin_plugins/cryptographic/CMakeLists.txt index 3be3010..a1eb46e 100644 --- a/src/security/builtin_plugins/cryptographic/CMakeLists.txt +++ b/src/security/builtin_plugins/cryptographic/CMakeLists.txt @@ -11,8 +11,6 @@ # include (GenerateExportHeader) -find_package(OpenSSL) - PREPEND(srcs_cryptographic "${CMAKE_CURRENT_LIST_DIR}/src" crypto_cipher.c crypto_key_exchange diff --git a/src/security/builtin_plugins/tests/CMakeLists.txt b/src/security/builtin_plugins/tests/CMakeLists.txt index ac56a7f..d2a8af1 100644 --- a/src/security/builtin_plugins/tests/CMakeLists.txt +++ b/src/security/builtin_plugins/tests/CMakeLists.txt @@ -10,7 +10,6 @@ # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # include(CUnit) -find_package(OpenSSL) set(security_auth_test_sources "common/src/loader.c" From 1cf472ea06df198bdc13e2dfb84883f7c4e0511d Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Mon, 24 Feb 2020 14:08:56 +0100 Subject: [PATCH 111/238] Refactored tests for security core: introduced generic wrappers for security plugins and updated plugin loading tests to use these instead of specific wrappers per test. Added test for securing communication ad handshake fail (using different identity CAs) Signed-off-by: Dennis Potman --- .../ddsi/include/dds/ddsi/ddsi_security_omg.h | 3 +- src/core/ddsi/src/ddsi_security_omg.c | 7 + src/security/CMakeLists.txt | 2 +- .../access_control/CMakeLists.txt | 12 +- .../authentication/CMakeLists.txt | 21 +- .../authentication/src/authentication.c | 2 +- .../cryptographic/CMakeLists.txt | 11 +- .../builtin_plugins/tests/CMakeLists.txt | 19 +- src/security/core/CMakeLists.txt | 12 +- .../dds/security/core/dds_security_utils.h | 3 +- src/security/core/src/dds_security_utils.c | 4 +- src/security/core/tests/CMakeLists.txt | 79 +- src/security/core/tests/SecurityCoreTests.idl | 18 + src/security/core/tests/authentication.c | 119 +++ .../tests/common/access_control_wrapper.c | 551 +++++++++++ .../tests/common/access_control_wrapper.h | 26 + .../tests/common/authentication_wrapper.c | 566 +++++++++++ .../tests/common/authentication_wrapper.h | 38 + .../core/tests/common/config_env.h.in | 27 + .../core/tests/common/cryptography_wrapper.c | 728 ++++++++++++++ .../core/tests/common/cryptography_wrapper.h | 39 + src/security/core/tests/common/etc/create_p7s | 36 + .../tests/common/etc/default_governance.p7s | 120 +++ .../tests/common/etc/default_governance.xml | 62 ++ .../tests/common/etc/default_permissions.p7s | 97 ++ .../tests/common/etc/default_permissions.xml | 39 + .../common/etc/default_permissions_ca.pem | 26 + .../common/etc/default_permissions_ca_key.pem | 27 + .../core/tests/common/handshake_test_utils.c | 232 +++++ .../core/tests/common/handshake_test_utils.h | 48 + .../core/tests/common/plugin_wrapper_msg_q.c | 134 +++ .../core/tests/common/plugin_wrapper_msg_q.h | 62 ++ .../tests/common/security_config_test_utils.c | 156 +++ .../tests/common/security_config_test_utils.h | 28 + .../core/tests/common/test_identity.h | 184 ++++ src/security/core/tests/config.c | 631 ++++++++++++ src/security/core/tests/dds_security_core.c | 8 +- src/security/core/tests/handshake.c | 99 ++ src/security/core/tests/plugin_loading.c | 646 +++++++++++++ .../core/tests/plugin_loading/CMakeLists.txt | 85 -- .../core/tests/plugin_loading/config_env.h.in | 25 - .../tests/plugin_loading/plugin_loading.c | 911 ------------------ .../mock_access_control.c | 597 ------------ .../mock_access_control.h | 281 ------ .../mock_access_control.c | 600 ------------ .../mock_access_control.h | 280 ------ .../mock_authentication.c | 404 -------- .../mock_authentication.h | 137 --- .../mock_authentication.c | 353 ------- .../mock_authentication.h | 136 --- .../mock_authentication.c | 394 -------- .../mock_authentication.h | 264 ----- .../mock_authentication.c | 347 ------- .../mock_authentication.h | 217 ----- .../mock_authentication.c | 402 -------- .../mock_authentication.h | 218 ----- .../cryptography_all_ok/mock_cryptography.c | 667 ------------- .../cryptography_all_ok/mock_cryptography.h | 21 - .../mock_cryptography.c | 656 ------------- .../mock_cryptography.h | 26 - .../tests/plugin_loading/security_config.c | 724 -------------- .../core/tests/secure_communication.c | 481 +++++++++ 62 files changed, 5335 insertions(+), 7813 deletions(-) create mode 100644 src/security/core/tests/SecurityCoreTests.idl create mode 100644 src/security/core/tests/authentication.c create mode 100644 src/security/core/tests/common/access_control_wrapper.c create mode 100644 src/security/core/tests/common/access_control_wrapper.h create mode 100644 src/security/core/tests/common/authentication_wrapper.c create mode 100644 src/security/core/tests/common/authentication_wrapper.h create mode 100644 src/security/core/tests/common/config_env.h.in create mode 100644 src/security/core/tests/common/cryptography_wrapper.c create mode 100644 src/security/core/tests/common/cryptography_wrapper.h create mode 100755 src/security/core/tests/common/etc/create_p7s create mode 100644 src/security/core/tests/common/etc/default_governance.p7s create mode 100644 src/security/core/tests/common/etc/default_governance.xml create mode 100644 src/security/core/tests/common/etc/default_permissions.p7s create mode 100644 src/security/core/tests/common/etc/default_permissions.xml create mode 100644 src/security/core/tests/common/etc/default_permissions_ca.pem create mode 100644 src/security/core/tests/common/etc/default_permissions_ca_key.pem create mode 100644 src/security/core/tests/common/handshake_test_utils.c create mode 100644 src/security/core/tests/common/handshake_test_utils.h create mode 100644 src/security/core/tests/common/plugin_wrapper_msg_q.c create mode 100644 src/security/core/tests/common/plugin_wrapper_msg_q.h create mode 100644 src/security/core/tests/common/security_config_test_utils.c create mode 100644 src/security/core/tests/common/security_config_test_utils.h create mode 100644 src/security/core/tests/common/test_identity.h create mode 100644 src/security/core/tests/config.c create mode 100644 src/security/core/tests/handshake.c create mode 100644 src/security/core/tests/plugin_loading.c delete mode 100644 src/security/core/tests/plugin_loading/CMakeLists.txt delete mode 100644 src/security/core/tests/plugin_loading/config_env.h.in delete mode 100644 src/security/core/tests/plugin_loading/plugin_loading.c delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/access_control_all_ok/mock_access_control.c delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/access_control_all_ok/mock_access_control.h delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/access_control_missing_function/mock_access_control.c delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/access_control_missing_function/mock_access_control.h delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok/mock_authentication.c delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok/mock_authentication.h delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok_other/mock_authentication.c delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok_other/mock_authentication.h delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/authentication_finalize_error/mock_authentication.c delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/authentication_finalize_error/mock_authentication.h delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/authentication_init_error/mock_authentication.c delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/authentication_init_error/mock_authentication.h delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/authentication_missing_function/mock_authentication.c delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/authentication_missing_function/mock_authentication.h delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/cryptography_all_ok/mock_cryptography.c delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/cryptography_all_ok/mock_cryptography.h delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/cryptography_missing_function/mock_cryptography.c delete mode 100644 src/security/core/tests/plugin_loading/plugin_mock/cryptography_missing_function/mock_cryptography.h delete mode 100644 src/security/core/tests/plugin_loading/security_config.c create mode 100644 src/security/core/tests/secure_communication.c 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 534a762..674cd3f 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h @@ -123,6 +123,8 @@ struct reader_sec_attributes { struct dds_security_authentication *q_omg_participant_get_authentication(const struct participant *pp); +DDS_EXPORT struct dds_security_cryptography *q_omg_participant_get_cryptography(const struct participant *pp); + void q_omg_log_exception(const struct ddsrt_log_cfg *lc, uint32_t cat, DDS_Security_SecurityException *exception, const char *file, uint32_t line, const char *func, const char *fmt, ...); /** @@ -1083,7 +1085,6 @@ void q_omg_security_deinit( struct ddsi_domaingv *gv ); bool q_omg_is_security_loaded( struct dds_security_context *sc ); - #else /* DDSI_INCLUDE_SECURITY */ #include "dds/ddsi/q_unused.h" diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 7204515..16da442 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -559,6 +559,13 @@ get_first_matched_proxypp_crypto_handle(struct participant_sec_attributes *attr) return handle; } +struct dds_security_cryptography *q_omg_participant_get_cryptography(const struct participant *pp) +{ + if (pp && pp->e.gv->security_context && q_omg_is_security_loaded(pp->e.gv->security_context)) + return pp->e.gv->security_context->crypto_context; + return NULL; +} + bool q_omg_is_security_loaded (dds_security_context *sc) { return (sc->crypto_context != NULL || sc->authentication_context != NULL || sc->access_control_context != NULL); diff --git a/src/security/CMakeLists.txt b/src/security/CMakeLists.txt index b96c7da..fd9af5d 100644 --- a/src/security/CMakeLists.txt +++ b/src/security/CMakeLists.txt @@ -18,4 +18,4 @@ if(ENABLE_SECURITY) if(ENABLE_SSL) add_subdirectory(builtin_plugins) endif() -endif() \ No newline at end of file +endif() diff --git a/src/security/builtin_plugins/access_control/CMakeLists.txt b/src/security/builtin_plugins/access_control/CMakeLists.txt index e882b2c..e0ffc78 100644 --- a/src/security/builtin_plugins/access_control/CMakeLists.txt +++ b/src/security/builtin_plugins/access_control/CMakeLists.txt @@ -26,16 +26,12 @@ generate_export_header( EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/dds/security/export.h" ) -add_definitions(-DDDSI_INCLUDE_SSL) - target_link_libraries(dds_security_ac PUBLIC ddsc) target_link_libraries(dds_security_ac PUBLIC OpenSSL::SSL) - -target_sources(dds_security_ac - PRIVATE - ${srcs_accesscontrol} -) - +if(CMAKE_GENERATOR MATCHES "Visual Studio") + set_target_properties(dds_security_ac PROPERTIES LINK_FLAGS "/ignore:4099") +endif() +target_sources(dds_security_ac PRIVATE ${srcs_accesscontrol}) target_include_directories(dds_security_ac PUBLIC "$>" diff --git a/src/security/builtin_plugins/authentication/CMakeLists.txt b/src/security/builtin_plugins/authentication/CMakeLists.txt index 9dc9b53..91455c5 100644 --- a/src/security/builtin_plugins/authentication/CMakeLists.txt +++ b/src/security/builtin_plugins/authentication/CMakeLists.txt @@ -15,7 +15,7 @@ PREPEND(srcs_authentication "${CMAKE_CURRENT_LIST_DIR}/src" authentication.c auth_utils.c ) - + PREPEND(hdrs_private_authentication "${CMAKE_CURRENT_LIST_DIR}/src" auth_defs.h authentication.h @@ -31,21 +31,12 @@ generate_export_header( EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/dds/security/export.h" ) - - -find_package(OpenSSL ) - -add_definitions(-DDDSI_INCLUDE_SSL) - target_link_libraries(dds_security_auth PUBLIC ddsc) target_link_libraries(dds_security_auth PUBLIC OpenSSL::SSL) - -target_sources(dds_security_auth - PRIVATE - ${srcs_authentication} - -) - +if(CMAKE_GENERATOR MATCHES "Visual Studio") + set_target_properties(dds_security_auth PROPERTIES LINK_FLAGS "/ignore:4099") +endif() +target_sources(dds_security_auth PRIVATE ${srcs_authentication}) target_include_directories(dds_security_auth PUBLIC "$>" @@ -55,7 +46,7 @@ target_include_directories(dds_security_auth ) install( - TARGETS + TARGETS EXPORT "${PROJECT_NAME}" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT lib LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index 63f4a60..d6139d9 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -23,7 +23,7 @@ #include "dds/ddsrt/heap.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_timed_cb.h" - +#include "dds/security/core/dds_security_utils.h" #if OPENSLL_VERSION_NUMBER >= 0x10002000L #define AUTH_INCLUDE_EC diff --git a/src/security/builtin_plugins/cryptographic/CMakeLists.txt b/src/security/builtin_plugins/cryptographic/CMakeLists.txt index a1eb46e..3cae998 100644 --- a/src/security/builtin_plugins/cryptographic/CMakeLists.txt +++ b/src/security/builtin_plugins/cryptographic/CMakeLists.txt @@ -29,15 +29,12 @@ generate_export_header( EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/dds/security/export.h" ) -add_definitions(-DDDSI_INCLUDE_SSL) - target_link_libraries(dds_security_crypto PUBLIC ddsc) target_link_libraries(dds_security_crypto PUBLIC OpenSSL::SSL) - -target_sources(dds_security_crypto - PRIVATE - ${srcs_cryptographic} -) +if(CMAKE_GENERATOR MATCHES "Visual Studio") + set_target_properties(dds_security_crypto PROPERTIES LINK_FLAGS "/ignore:4099") +endif() +target_sources(dds_security_crypto PRIVATE ${srcs_cryptographic}) target_include_directories(dds_security_crypto PUBLIC diff --git a/src/security/builtin_plugins/tests/CMakeLists.txt b/src/security/builtin_plugins/tests/CMakeLists.txt index d2a8af1..60a9704 100644 --- a/src/security/builtin_plugins/tests/CMakeLists.txt +++ b/src/security/builtin_plugins/tests/CMakeLists.txt @@ -60,6 +60,7 @@ set(security_crypto_test_sources ) add_cunit_executable(cunit_security_plugins ${security_auth_test_sources} ${security_ac_test_sources} ${security_crypto_test_sources}) + target_include_directories( cunit_security_plugins PRIVATE "$" @@ -69,15 +70,10 @@ target_include_directories( "$" "$" ) -target_link_libraries(cunit_security_plugins PRIVATE ddsc security_api) - -if(OPENSSL_FOUND) -target_link_libraries(cunit_security_plugins PRIVATE ddsc dds_security_ac) -target_link_libraries(cunit_security_plugins PRIVATE ddsc dds_security_crypto) - target_link_libraries(cunit_security_plugins PRIVATE OpenSSL::SSL) - -else() - message(FATAL_ERROR "To build with openssl support, set ENABLE_OPENSSL to ON") +target_link_libraries(cunit_security_plugins PRIVATE ddsc security_api dds_security_ac dds_security_crypto) +target_link_libraries(cunit_security_plugins PRIVATE OpenSSL::SSL) +if(CMAKE_GENERATOR MATCHES "Visual Studio") + set_target_properties(cunit_security_plugins PROPERTIES LINK_FLAGS "/ignore:4099") endif() target_include_directories( @@ -91,11 +87,6 @@ target_include_directories( "$" ) - - set(CUnit_builtin_plugins_tests_dir "${CMAKE_CURRENT_LIST_DIR}") set(CUnit_build_dir "${CMAKE_CURRENT_BINARY_DIR}") - configure_file("config_env.h.in" "config_env.h") - - diff --git a/src/security/core/CMakeLists.txt b/src/security/core/CMakeLists.txt index 41ea708..19f4823 100644 --- a/src/security/core/CMakeLists.txt +++ b/src/security/core/CMakeLists.txt @@ -17,7 +17,7 @@ PREPEND(srcs_security_core "${CMAKE_CURRENT_LIST_DIR}/src" dds_security_fsm.c dds_security_timed_cb.c ) - + PREPEND(hdrs_public_security_core "${CMAKE_CURRENT_LIST_DIR}/include/security/core" dds_security_serialize.h dds_security_types.h @@ -35,12 +35,7 @@ endif() add_library(security_core INTERFACE) - -target_sources(security_core - INTERFACE - ${srcs_security_core} - -) +target_sources(security_core INTERFACE ${srcs_security_core}) target_include_directories(security_core INTERFACE @@ -49,12 +44,9 @@ target_include_directories(security_core "$>" "$>" ) -#target_link_libraries(security_core PRIVATE ddsrt security_api) if(BUILD_TESTING) add_subdirectory(tests) -# Temporarily disabled because needs refractoring w.r.t. security implementation -# add_subdirectory(tests/plugin_loading) endif() install( diff --git a/src/security/core/include/dds/security/core/dds_security_utils.h b/src/security/core/include/dds/security/core/dds_security_utils.h index d6a745e..c9cbf0e 100644 --- a/src/security/core/include/dds/security/core/dds_security_utils.h +++ b/src/security/core/include/dds/security/core/dds_security_utils.h @@ -271,7 +271,7 @@ DDS_Security_Exception_set( ...); -#if DDSI_INCLUDE_SSL +#ifdef DDSI_INCLUDE_SSL DDS_EXPORT void DDS_Security_Exception_set_with_openssl_error( DDS_Security_SecurityException *ex, @@ -279,7 +279,6 @@ DDS_Security_Exception_set_with_openssl_error( int code, int minor_code, const char *fmt); - #endif DDS_EXPORT void diff --git a/src/security/core/src/dds_security_utils.c b/src/security/core/src/dds_security_utils.c index ea5a7d8..3c04c60 100644 --- a/src/security/core/src/dds_security_utils.c +++ b/src/security/core/src/dds_security_utils.c @@ -22,7 +22,7 @@ #include "dds/ddsrt/string.h" #include "dds/ddsrt/misc.h" -#if DDSI_INCLUDE_SSL +#ifdef DDSI_INCLUDE_SSL #include #include #endif @@ -806,7 +806,7 @@ DDS_Security_Exception_set( ex->minor_code = minor_code; } -#if DDSI_INCLUDE_SSL +#ifdef DDSI_INCLUDE_SSL DDS_EXPORT void DDS_Security_Exception_set_with_openssl_error( DDS_Security_SecurityException *ex, diff --git a/src/security/core/tests/CMakeLists.txt b/src/security/core/tests/CMakeLists.txt index d240583..9fcc0c0 100644 --- a/src/security/core/tests/CMakeLists.txt +++ b/src/security/core/tests/CMakeLists.txt @@ -12,14 +12,78 @@ include (GenerateExportHeader) include (CUnit) +idlc_generate(SecurityCoreTests SecurityCoreTests.idl) + +function(add_wrapper libname linklibs) + set(srcs_wrapper + "${CMAKE_CURRENT_LIST_DIR}/common/${libname}_wrapper.c" + "${CMAKE_CURRENT_LIST_DIR}/common/plugin_wrapper_msg_q.c") + add_library("dds_security_${libname}_wrapper" SHARED "") + if(CMAKE_GENERATOR MATCHES "Visual Studio") + set_target_properties("dds_security_${libname}_wrapper" PROPERTIES LINK_FLAGS "/ignore:4099") + endif() + + generate_export_header( + "dds_security_${libname}_wrapper" + BASE_NAME SECURITY + EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/dds/security/${libname}_wrapper_export.h") + + set_target_properties( + "dds_security_${libname}_wrapper" + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR} + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR} + LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR} + LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR} + LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR}) + + if(APPLE) + set_target_properties("dds_security_${libname}_wrapper" PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") + endif() + + target_link_libraries("dds_security_${libname}_wrapper" PUBLIC ddsc ${linklibs}) + target_sources("dds_security_${libname}_wrapper" PRIVATE ${srcs_wrapper}) + target_include_directories("dds_security_${libname}_wrapper" + PUBLIC + "$>" + "$>" + "$>" + "$" + "$" + "$") +endfunction() + set(security_core_test_sources "tc_fsm.c" "dds_security_core.c" "security_utils.c" - ) +) + +if(ENABLE_SSL) + add_wrapper(access_control "") + add_wrapper(authentication dds_security_auth) + add_wrapper(cryptography dds_security_crypto) + + list(APPEND security_core_test_sources + "common/security_config_test_utils.c" + "common/handshake_test_utils.c" + "authentication.c" + "config.c" + "handshake.c" + "plugin_loading.c" + "secure_communication.c" + ) +endif() -add_definitions(-DDDSI_INCLUDE_SECURITY) add_cunit_executable(cunit_security_core ${security_core_test_sources}) +if(CMAKE_GENERATOR MATCHES "Visual Studio") + set_target_properties(cunit_security_core PROPERTIES LINK_FLAGS "/ignore:4099") +endif() target_include_directories( cunit_security_core PRIVATE @@ -33,6 +97,15 @@ target_include_directories( "$" ) +set(common_etc_dir "${CMAKE_CURRENT_SOURCE_DIR}/common/etc") +set(plugin_wrapper_lib_dir "${CMAKE_CURRENT_BINARY_DIR}") +file(TO_NATIVE_PATH "/" file_path_sep) +string(REPLACE "\\" "\\\\" file_path_sep ${file_path_sep}) +configure_file("common/config_env.h.in" "common/config_env.h") -target_link_libraries(cunit_security_core PRIVATE ddsc security_api) +target_link_libraries(cunit_security_core PRIVATE ddsc security_api SecurityCoreTests) +if(ENABLE_SSL) + target_link_libraries(cunit_security_core PRIVATE dds_security_auth dds_security_ac dds_security_crypto dds_security_authentication_wrapper dds_security_cryptography_wrapper) + target_link_libraries(cunit_security_core PRIVATE OpenSSL::SSL) +endif() target_include_directories(cunit_security_core PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") diff --git a/src/security/core/tests/SecurityCoreTests.idl b/src/security/core/tests/SecurityCoreTests.idl new file mode 100644 index 0000000..1eb6700 --- /dev/null +++ b/src/security/core/tests/SecurityCoreTests.idl @@ -0,0 +1,18 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +module SecurityCoreTests { + struct Type1 { + long id; //@Key + long value; + }; +#pragma keylist Type1 id +}; diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c new file mode 100644 index 0000000..e981648 --- /dev/null +++ b/src/security/core/tests/authentication.c @@ -0,0 +1,119 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include + +#include "dds/dds.h" +#include "CUnit/Test.h" + +#include "dds/version.h" +#include "dds/ddsrt/cdtors.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsi/q_config.h" +#include "dds/ddsi/ddsi_domaingv.h" +#include "dds/ddsi/q_misc.h" +#include "dds/ddsi/ddsi_xqos.h" + +#include "dds/security/dds_security_api.h" + +#include "common/config_env.h" +#include "common/authentication_wrapper.h" +#include "common/handshake_test_utils.h" +#include "common/security_config_test_utils.h" +#include "common/test_identity.h" + +static const char *config = + "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" + "0" + "" + " finest" + " " + " " + " " + " ${TEST_IDENTITY_CERTIFICATE}" + " ${TEST_IDENTITY_PRIVATE_KEY}" + " ${TEST_IDENTITY_CA_CERTIFICATE}" + " testtext_Password_testtext" + " ." + " " + " " + " " + " file:" COMMON_ETC_PATH("default_governance.p7s") "" + " file:" COMMON_ETC_PATH("default_permissions_ca.pem") "" + " file:" COMMON_ETC_PATH("default_permissions.p7s") "" + " " + " " + " " + " " + " " + ""; + +#define DDS_DOMAINID1 0 +#define DDS_DOMAINID2 1 + +static dds_entity_t g_domain1 = 0; +static dds_entity_t g_participant1 = 0; + +static dds_entity_t g_domain2 = 0; +static dds_entity_t g_participant2 = 0; + +static void authentication_init(void) +{ + struct kvp governance_vars[] = { + { "ALLOW_UNAUTH_PP", "false" }, + { "ENABLE_JOIN_AC", "true" }, + { NULL, NULL } + }; + char * gov_config_signed = get_governance_config (governance_vars); + + struct kvp config_vars1[] = { + { "GOVERNANCE_DATA", gov_config_signed }, + { "TEST_IDENTITY_CERTIFICATE", TEST_IDENTITY_CERTIFICATE }, + { "TEST_IDENTITY_PRIVATE_KEY", TEST_IDENTITY_PRIVATE_KEY }, + { "TEST_IDENTITY_CA_CERTIFICATE", TEST_IDENTITY_CA_CERTIFICATE }, + { NULL, NULL } + }; + struct kvp config_vars2[] = { + { "GOVERNANCE_DATA", gov_config_signed }, + { "TEST_IDENTITY_CERTIFICATE", TEST_IDENTITY2_CERTIFICATE }, + { "TEST_IDENTITY_PRIVATE_KEY", TEST_IDENTITY2_PRIVATE_KEY }, + { "TEST_IDENTITY_CA_CERTIFICATE", TEST_IDENTITY_CA2_CERTIFICATE }, + { NULL, NULL } + }; + + char *conf1 = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars1); + char *conf2 = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars2); + g_domain1 = dds_create_domain (DDS_DOMAINID1, conf1); + g_domain2 = dds_create_domain (DDS_DOMAINID2, conf2); + dds_free (conf1); + dds_free (conf2); + ddsrt_free (gov_config_signed); + + CU_ASSERT_FATAL ((g_participant1 = dds_create_participant (DDS_DOMAINID1, NULL, NULL)) > 0); + CU_ASSERT_FATAL ((g_participant2 = dds_create_participant (DDS_DOMAINID2, NULL, NULL)) > 0); +} + +static void authentication_fini(void) +{ + CU_ASSERT_EQUAL_FATAL (dds_delete (g_participant1), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL (dds_delete (g_participant2), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain1), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain2), DDS_RETCODE_OK); +} + +CU_Test(ddssec_authentication, different_ca, .init = authentication_init, .fini = authentication_fini) +{ + validate_handshake (DDS_DOMAINID1, true, NULL, true, "error: unable to get local issuer certificate"); + validate_handshake (DDS_DOMAINID2, true, NULL, true, "error: unable to get local issuer certificate"); +} diff --git a/src/security/core/tests/common/access_control_wrapper.c b/src/security/core/tests/common/access_control_wrapper.c new file mode 100644 index 0000000..83b88f6 --- /dev/null +++ b/src/security/core/tests/common/access_control_wrapper.c @@ -0,0 +1,551 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include "dds/dds.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsi/ddsi_domaingv.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/core/dds_security_utils.h" +#include "access_control_wrapper.h" + +enum ac_plugin_mode { + PLUGIN_MODE_ALL_OK, + PLUGIN_MODE_MISSING_FUNC +}; + +/** + * Implementation structure for storing encapsulated members of the instance + * while giving only the interface definition to user + */ +struct dds_security_access_control_impl { + dds_security_access_control base; + enum ac_plugin_mode mode; +}; + +static DDS_Security_PermissionsHandle validate_local_permissions( + dds_security_access_control *instance, + const dds_security_authentication *auth_plugin, + const DDS_Security_IdentityHandle identity, + const DDS_Security_DomainId domain_id, + const DDS_Security_Qos *participant_qos, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(auth_plugin); + DDSRT_UNUSED_ARG(auth_plugin); + DDSRT_UNUSED_ARG(identity); + DDSRT_UNUSED_ARG(domain_id); + DDSRT_UNUSED_ARG(participant_qos); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return 1; +} + +static DDS_Security_PermissionsHandle validate_remote_permissions( + dds_security_access_control *instance, + const dds_security_authentication *auth_plugin, + const DDS_Security_IdentityHandle local_identity_handle, + const DDS_Security_IdentityHandle remote_identity_handle, + const DDS_Security_PermissionsToken *remote_permissions_token, + const DDS_Security_AuthenticatedPeerCredentialToken *remote_credential_token, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(auth_plugin); + DDSRT_UNUSED_ARG(local_identity_handle); + DDSRT_UNUSED_ARG(remote_identity_handle); + DDSRT_UNUSED_ARG(remote_permissions_token); + DDSRT_UNUSED_ARG(remote_credential_token); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return 0; +} + +static DDS_Security_boolean check_create_participant( dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_Qos *participant_qos, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(domain_id); + DDSRT_UNUSED_ARG(participant_qos); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean check_create_datawriter( dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const char *topic_name, + const DDS_Security_Qos *writer_qos, + const DDS_Security_PartitionQosPolicy *partition, + const DDS_Security_DataTags *data_tag, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(domain_id); + DDSRT_UNUSED_ARG(topic_name); + DDSRT_UNUSED_ARG(writer_qos); + DDSRT_UNUSED_ARG(partition); + DDSRT_UNUSED_ARG(data_tag); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean check_create_datareader( dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const char *topic_name, + const DDS_Security_Qos *reader_qos, + const DDS_Security_PartitionQosPolicy *partition, + const DDS_Security_DataTags *data_tag, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(domain_id); + DDSRT_UNUSED_ARG(topic_name); + DDSRT_UNUSED_ARG(reader_qos); + DDSRT_UNUSED_ARG(partition); + DDSRT_UNUSED_ARG(data_tag); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean check_create_topic( dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const char *topic_name, + const DDS_Security_Qos *qos, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(domain_id); + DDSRT_UNUSED_ARG(topic_name); + DDSRT_UNUSED_ARG(qos); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean check_local_datawriter_register_instance( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_Entity *writer, + const DDS_Security_DynamicData *key, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(writer); + DDSRT_UNUSED_ARG(key); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean check_local_datawriter_dispose_instance( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_Entity *writer, + const DDS_Security_DynamicData key, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(writer); + DDSRT_UNUSED_ARG(key); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean check_remote_participant( dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_ParticipantBuiltinTopicDataSecure *participant_data, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(domain_id); + DDSRT_UNUSED_ARG(participant_data); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean check_remote_datawriter( dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(domain_id); + DDSRT_UNUSED_ARG(publication_data); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean check_remote_datareader( dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, + DDS_Security_boolean *relay_only, DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(domain_id); + DDSRT_UNUSED_ARG(subscription_data); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + *relay_only = false; + return true; +} + +static DDS_Security_boolean check_remote_topic( dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_TopicBuiltinTopicData *topic_data, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(domain_id); + DDSRT_UNUSED_ARG(topic_data); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean check_local_datawriter_match( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle writer_permissions_handle, + const DDS_Security_PermissionsHandle reader_permissions_handle, + const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, + const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(writer_permissions_handle); + DDSRT_UNUSED_ARG(reader_permissions_handle); + DDSRT_UNUSED_ARG(publication_data); + DDSRT_UNUSED_ARG(subscription_data); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean check_local_datareader_match( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle reader_permissions_handle, + const DDS_Security_PermissionsHandle writer_permissions_handle, + const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, + const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(reader_permissions_handle); + DDSRT_UNUSED_ARG(writer_permissions_handle); + DDSRT_UNUSED_ARG(subscription_data); + DDSRT_UNUSED_ARG(publication_data); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean check_remote_datawriter_register_instance( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_Entity *reader, + const DDS_Security_InstanceHandle publication_handle, + const DDS_Security_DynamicData key, + const DDS_Security_InstanceHandle instance_handle, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(reader); + DDSRT_UNUSED_ARG(publication_handle); + DDSRT_UNUSED_ARG(key); + DDSRT_UNUSED_ARG(instance_handle); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean check_remote_datawriter_dispose_instance( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_Entity *reader, + const DDS_Security_InstanceHandle publication_handle, + const DDS_Security_DynamicData key, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(reader); + DDSRT_UNUSED_ARG(publication_handle); + DDSRT_UNUSED_ARG(key); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean get_permissions_token( + dds_security_access_control *instance, + DDS_Security_PermissionsToken *permissions_token, + const DDS_Security_PermissionsHandle handle, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(handle); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + memset(permissions_token, 0, sizeof(*permissions_token)); + permissions_token->class_id = ddsrt_strdup(""); + return true; +} + +static DDS_Security_boolean get_permissions_credential_token( + dds_security_access_control *instance, + DDS_Security_PermissionsCredentialToken *permissions_credential_token, + const DDS_Security_PermissionsHandle handle, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_credential_token); + DDSRT_UNUSED_ARG(handle); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean set_listener( dds_security_access_control *instance, + const dds_security_access_control_listener *listener, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(listener); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean return_permissions_token( dds_security_access_control *instance, + const DDS_Security_PermissionsToken *token, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + ddsrt_free (token->class_id); + return true; +} + +static DDS_Security_boolean return_permissions_credential_token( + dds_security_access_control *instance, + const DDS_Security_PermissionsCredentialToken *permissions_credential_token, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_credential_token); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean get_participant_sec_attributes( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + DDS_Security_ParticipantSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(attributes); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean get_topic_sec_attributes( dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const char *topic_name, + DDS_Security_TopicSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(topic_name); + DDSRT_UNUSED_ARG(attributes); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean get_datawriter_sec_attributes( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const char *topic_name, + const DDS_Security_PartitionQosPolicy *partition, + const DDS_Security_DataTagQosPolicy *data_tag, + DDS_Security_EndpointSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(topic_name); + DDSRT_UNUSED_ARG(partition); + DDSRT_UNUSED_ARG(data_tag); + DDSRT_UNUSED_ARG(attributes); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean get_datareader_sec_attributes( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const char *topic_name, + const DDS_Security_PartitionQosPolicy *partition, + const DDS_Security_DataTagQosPolicy *data_tag, + DDS_Security_EndpointSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(topic_name); + DDSRT_UNUSED_ARG(partition); + DDSRT_UNUSED_ARG(data_tag); + DDSRT_UNUSED_ARG(attributes); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean return_participant_sec_attributes( + dds_security_access_control *instance, + const DDS_Security_ParticipantSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(attributes); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean return_topic_sec_attributes( + dds_security_access_control *instance, + const DDS_Security_TopicSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(attributes); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean return_datawriter_sec_attributes( + dds_security_access_control *instance, + const DDS_Security_EndpointSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(attributes); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean return_datareader_sec_attributes( + dds_security_access_control *instance, + const DDS_Security_EndpointSecurityAttributes *attributes, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(attributes); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +static DDS_Security_boolean return_permissions_handle( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(permissions_handle); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + + +static struct dds_security_access_control_impl * init_test_access_control_common() +{ + struct dds_security_access_control_impl *impl = ddsrt_malloc(sizeof(*impl)); + memset(impl, 0, sizeof(*impl)); + impl->base.validate_local_permissions = &validate_local_permissions; + impl->base.validate_remote_permissions = &validate_remote_permissions; + impl->base.check_create_participant = &check_create_participant; + impl->base.check_create_datawriter = &check_create_datawriter; + impl->base.check_create_datareader = &check_create_datareader; + impl->base.check_create_topic = &check_create_topic; + impl->base.check_local_datawriter_register_instance = &check_local_datawriter_register_instance; + impl->base.check_local_datawriter_dispose_instance = &check_local_datawriter_dispose_instance; + impl->base.check_remote_participant = &check_remote_participant; + impl->base.check_remote_datawriter = &check_remote_datawriter; + impl->base.check_remote_datareader = &check_remote_datareader; + impl->base.check_remote_topic = &check_remote_topic; + impl->base.check_local_datawriter_match = &check_local_datawriter_match; + impl->base.check_local_datareader_match = &check_local_datareader_match; + impl->base.check_remote_datawriter_register_instance = &check_remote_datawriter_register_instance; + impl->base.check_remote_datawriter_dispose_instance = &check_remote_datawriter_dispose_instance; + impl->base.get_permissions_token = &get_permissions_token; + impl->base.get_permissions_credential_token = &get_permissions_credential_token; + impl->base.set_listener = &set_listener; + impl->base.return_permissions_token = &return_permissions_token; + impl->base.return_permissions_credential_token = &return_permissions_credential_token; + impl->base.get_participant_sec_attributes = &get_participant_sec_attributes; + impl->base.get_topic_sec_attributes = &get_topic_sec_attributes; + impl->base.get_datawriter_sec_attributes = &get_datawriter_sec_attributes; + impl->base.get_datareader_sec_attributes = &get_datareader_sec_attributes; + impl->base.return_participant_sec_attributes = &return_participant_sec_attributes; + impl->base.return_topic_sec_attributes = &return_topic_sec_attributes; + impl->base.return_datawriter_sec_attributes = &return_datawriter_sec_attributes; + impl->base.return_datareader_sec_attributes = &return_datareader_sec_attributes; + impl->base.return_permissions_handle = &return_permissions_handle; + return impl; +} + +int32_t init_test_access_control_all_ok(const char *argument, void **context) +{ + DDSRT_UNUSED_ARG(argument); + DDSRT_UNUSED_ARG(context); + struct dds_security_access_control_impl *impl = init_test_access_control_common(); + impl->mode = PLUGIN_MODE_ALL_OK; + *context = impl; + return 0; +} + +int32_t finalize_test_access_control_all_ok(void *context) +{ + assert(((struct dds_security_access_control_impl *)context)->mode == PLUGIN_MODE_ALL_OK); + ddsrt_free(context); + return 0; +} + +int32_t init_test_access_control_missing_func(const char *argument, void **context) +{ + DDSRT_UNUSED_ARG(argument); + DDSRT_UNUSED_ARG(context); + struct dds_security_access_control_impl *impl = init_test_access_control_common(); + impl->base.check_create_datareader = NULL; + impl->mode = PLUGIN_MODE_MISSING_FUNC; + *context = impl; + return 0; +} + +int32_t finalize_test_access_control_missing_func(void *context) +{ + assert(((struct dds_security_access_control_impl *)context)->mode == PLUGIN_MODE_MISSING_FUNC); + ddsrt_free(context); + return 0; +} + diff --git a/src/security/core/tests/common/access_control_wrapper.h b/src/security/core/tests/common/access_control_wrapper.h new file mode 100644 index 0000000..70c9c2c --- /dev/null +++ b/src/security/core/tests/common/access_control_wrapper.h @@ -0,0 +1,26 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef SECURITY_CORE_TEST_ACCESS_CONTROL_WRAPPER_H_ +#define SECURITY_CORE_TEST_ACCESS_CONTROL_WRAPPER_H_ + +#include "dds/security/dds_security_api.h" +#include "dds/security/access_control_wrapper_export.h" + +/* Init in all-ok mode: all functions return success without calling the actual plugin */ +SECURITY_EXPORT int32_t init_test_access_control_all_ok(const char *argument, void **context); +SECURITY_EXPORT int32_t finalize_test_access_control_all_ok(void *context); + +/* Init in missing function mode: one of the function pointers is null */ +SECURITY_EXPORT int32_t init_test_access_control_missing_func(const char *argument, void **context); +SECURITY_EXPORT int32_t finalize_test_access_control_missing_func(void *context); + +#endif /* SECURITY_CORE_TEST_ACCESS_CONTROL_WRAPPER_H_ */ diff --git a/src/security/core/tests/common/authentication_wrapper.c b/src/security/core/tests/common/authentication_wrapper.c new file mode 100644 index 0000000..b794a3e --- /dev/null +++ b/src/security/core/tests/common/authentication_wrapper.c @@ -0,0 +1,566 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include "dds/dds.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsi/ddsi_domaingv.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/core/dds_security_utils.h" +#include "authentication_wrapper.h" +#include "test_identity.h" +#include "plugin_wrapper_msg_q.h" + +int32_t init_authentication(const char *argument, void **context); +int32_t finalize_authentication(void *context); + +enum auth_plugin_mode { + PLUGIN_MODE_ALL_OK, + PLUGIN_MODE_WRAPPED, + PLUGIN_MODE_MISSING_FUNC, + PLUGIN_MODE_INIT_FAIL +}; + +/** + * Implementation structure for storing encapsulated members of the instance + * while giving only the interface definition to user + */ +struct dds_security_authentication_impl +{ + dds_security_authentication base; + dds_security_authentication *instance; + struct message_queue msg_queue; + const struct ddsi_domaingv *gv; + enum auth_plugin_mode mode; +}; + +static struct dds_security_authentication_impl **auth_impl; +static size_t auth_impl_count = 0; + +static const char *test_identity_certificate = TEST_IDENTITY_CERTIFICATE_DUMMY; +static const char *test_private_key = TEST_IDENTITY_PRIVATE_KEY_DUMMY; +static const char *test_ca_certificate = TEST_IDENTITY_CA_CERTIFICATE_DUMMY; + +static DDS_Security_ValidationResult_t test_validate_local_identity_all_ok( + DDS_Security_GUID_t *adjusted_participant_guid, + const DDS_Security_Qos *participant_qos, + const DDS_Security_GUID_t *candidate_participant_guid) +{ + DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; + char *identity_ca = NULL; + char *identity_certificate = NULL; + char *private_key = NULL; + + memcpy(adjusted_participant_guid, candidate_participant_guid, sizeof(*adjusted_participant_guid)); + for (unsigned i = 0; i < participant_qos->property.value._length; i++) + { + printf("%s\n", participant_qos->property.value._buffer[i].name); + if (!strcmp(participant_qos->property.value._buffer[i].name, "dds.sec.auth.private_key")) + private_key = participant_qos->property.value._buffer[i].value; + else if (!strcmp(participant_qos->property.value._buffer[i].name, "dds.sec.auth.identity_ca")) + identity_ca = participant_qos->property.value._buffer[i].value; + else if (!strcmp(participant_qos->property.value._buffer[i].name, "dds.sec.auth.identity_certificate")) + identity_certificate = participant_qos->property.value._buffer[i].value; + } + + if (strcmp(identity_certificate, test_identity_certificate)) + { + printf("identity received=%s\n", identity_certificate); + printf("identity expected=%s\n", test_identity_certificate); + result = DDS_SECURITY_VALIDATION_FAILED; + printf("FAILED: Could not get identity_certificate value properly\n"); + } + else if (strcmp(identity_ca, test_ca_certificate)) + { + printf("ca received=%s\n", identity_ca); + printf("ca expected=%s\n", test_ca_certificate); + printf("FAILED: Could not get identity_ca value properly\n"); + result = DDS_SECURITY_VALIDATION_FAILED; + } + else if (strcmp(private_key, test_private_key)) + { + printf("FAILED: Could not get private_key value properly\n"); + result = DDS_SECURITY_VALIDATION_FAILED; + } + if (result == DDS_SECURITY_VALIDATION_OK) + printf("DDS_SECURITY_VALIDATION_OK\n"); + + return result; +} + +static DDS_Security_ValidationResult_t test_validate_local_identity( + dds_security_authentication *instance, + DDS_Security_IdentityHandle *local_identity_handle, + DDS_Security_GUID_t *adjusted_participant_guid, + const DDS_Security_DomainId domain_id, + const DDS_Security_Qos *participant_qos, + const DDS_Security_GUID_t *candidate_participant_guid, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + { + DDS_Security_ValidationResult_t result = impl->instance->validate_local_identity( + impl->instance, local_identity_handle, adjusted_participant_guid, domain_id, participant_qos, candidate_participant_guid, ex); + add_message(&impl->msg_queue, MESSAGE_KIND_VALIDATE_LOCAL_IDENTITY, *local_identity_handle, + 0, 0, adjusted_participant_guid, NULL, result, ex ? ex->message : "", NULL, instance); + return result; + } + case PLUGIN_MODE_ALL_OK: + default: + return test_validate_local_identity_all_ok(adjusted_participant_guid, participant_qos, candidate_participant_guid); + } +} + +static DDS_Security_boolean test_get_identity_token(dds_security_authentication *instance, + DDS_Security_IdentityToken *identity_token, + const DDS_Security_IdentityHandle handle, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->get_identity_token(impl->instance, identity_token, handle, ex); + + case PLUGIN_MODE_ALL_OK: + default: + { + memset(identity_token, 0, sizeof(*identity_token)); + identity_token->class_id = ddsrt_strdup(""); + return true; + } + } +} + +static DDS_Security_boolean test_get_identity_status_token( + dds_security_authentication *instance, + DDS_Security_IdentityStatusToken *identity_status_token, + const DDS_Security_IdentityHandle handle, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->get_identity_status_token(impl->instance, identity_status_token, handle, ex); + case PLUGIN_MODE_ALL_OK: + default: + return true; + } +} + +static DDS_Security_boolean test_set_permissions_credential_and_token( + dds_security_authentication *instance, + const DDS_Security_IdentityHandle handle, + const DDS_Security_PermissionsCredentialToken *permissions_credential, + const DDS_Security_PermissionsToken *permissions_token, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->set_permissions_credential_and_token(impl->instance, handle, permissions_credential, permissions_token, ex); + case PLUGIN_MODE_ALL_OK: + default: + return true; + } +} + +static DDS_Security_ValidationResult_t test_validate_remote_identity( + dds_security_authentication *instance, + DDS_Security_IdentityHandle *remote_identity_handle, + DDS_Security_AuthRequestMessageToken *local_auth_request_token, + const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, + const DDS_Security_IdentityHandle local_identity_handle, + const DDS_Security_IdentityToken *remote_identity_token, + const DDS_Security_GUID_t *remote_participant_guid, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + { + DDS_Security_ValidationResult_t result = impl->instance->validate_remote_identity( + impl->instance, remote_identity_handle, local_auth_request_token, remote_auth_request_token, + local_identity_handle, remote_identity_token, remote_participant_guid, ex); + add_message(&impl->msg_queue, MESSAGE_KIND_VALIDATE_REMOTE_IDENTITY, local_identity_handle, + *remote_identity_handle, 0, NULL, remote_participant_guid, result, ex ? ex->message : "", local_auth_request_token, instance); + return result; + } + + case PLUGIN_MODE_ALL_OK: + default: + return DDS_SECURITY_VALIDATION_OK; + } +} + +static DDS_Security_ValidationResult_t test_begin_handshake_request( + dds_security_authentication *instance, + DDS_Security_HandshakeHandle *handshake_handle, + DDS_Security_HandshakeMessageToken *handshake_message, + const DDS_Security_IdentityHandle initiator_identity_handle, + const DDS_Security_IdentityHandle replier_identity_handle, + const DDS_Security_OctetSeq *serialized_local_participant_data, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + { + DDS_Security_ValidationResult_t result = impl->instance->begin_handshake_request( + impl->instance, handshake_handle, handshake_message, initiator_identity_handle, + replier_identity_handle, serialized_local_participant_data, ex); + add_message(&impl->msg_queue, MESSAGE_KIND_BEGIN_HANDSHAKE_REQUEST, initiator_identity_handle, + replier_identity_handle, *handshake_handle, NULL, NULL, result, ex ? ex->message : "", handshake_message, instance); + return result; + } + + case PLUGIN_MODE_ALL_OK: + default: + return DDS_SECURITY_VALIDATION_OK; + } +} + +static DDS_Security_ValidationResult_t test_begin_handshake_reply( + dds_security_authentication *instance, + DDS_Security_HandshakeHandle *handshake_handle, + DDS_Security_HandshakeMessageToken *handshake_message_out, + const DDS_Security_HandshakeMessageToken *handshake_message_in, + const DDS_Security_IdentityHandle initiator_identity_handle, + const DDS_Security_IdentityHandle replier_identity_handle, + const DDS_Security_OctetSeq *serialized_local_participant_data, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + { + DDS_Security_ValidationResult_t result = impl->instance->begin_handshake_reply( + impl->instance, handshake_handle, handshake_message_out, handshake_message_in, + initiator_identity_handle, replier_identity_handle, serialized_local_participant_data, ex); + add_message(&impl->msg_queue, MESSAGE_KIND_BEGIN_HANDSHAKE_REPLY, replier_identity_handle, + initiator_identity_handle, *handshake_handle, NULL, NULL, result, ex ? ex->message : "", handshake_message_out, instance); + return result; + } + + case PLUGIN_MODE_ALL_OK: + default: + return DDS_SECURITY_VALIDATION_OK; + } +} + +static DDS_Security_ValidationResult_t test_process_handshake( + dds_security_authentication *instance, + DDS_Security_HandshakeMessageToken *handshake_message_out, + const DDS_Security_HandshakeMessageToken *handshake_message_in, + const DDS_Security_HandshakeHandle handshake_handle, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + { + DDS_Security_ValidationResult_t result = impl->instance->process_handshake(impl->instance, handshake_message_out, handshake_message_in, handshake_handle, ex); + add_message(&impl->msg_queue, MESSAGE_KIND_PROCESS_HANDSHAKE, 0, 0, handshake_handle, + NULL, NULL, result, ex ? ex->message : "", handshake_message_out, instance); + return result; + } + + case PLUGIN_MODE_ALL_OK: + default: + return DDS_SECURITY_VALIDATION_OK; + } +} + +static DDS_Security_SharedSecretHandle test_get_shared_secret( + dds_security_authentication *instance, + const DDS_Security_HandshakeHandle handshake_handle, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->get_shared_secret(impl->instance, handshake_handle, ex); + case PLUGIN_MODE_ALL_OK: + default: + return 0; + } +} + +static DDS_Security_boolean test_get_authenticated_peer_credential_token( + dds_security_authentication *instance, + DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, + const DDS_Security_HandshakeHandle handshake_handle, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->get_authenticated_peer_credential_token(impl->instance, peer_credential_token, handshake_handle, ex); + case PLUGIN_MODE_ALL_OK: + default: + return true; + } +} + +static DDS_Security_boolean test_set_listener(dds_security_authentication *instance, + const dds_security_authentication_listener *listener, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->set_listener(impl->instance, listener, ex); + case PLUGIN_MODE_ALL_OK: + default: + return true; + } +} + +static DDS_Security_boolean test_return_identity_token(dds_security_authentication *instance, + const DDS_Security_IdentityToken *token, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->return_identity_token(impl->instance, token, ex); + case PLUGIN_MODE_ALL_OK: + default: + if (token->class_id) + ddsrt_free (token->class_id); + return true; + } +} + +static DDS_Security_boolean test_return_identity_status_token( + dds_security_authentication *instance, + const DDS_Security_IdentityStatusToken *token, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->return_identity_status_token(impl->instance, token, ex); + case PLUGIN_MODE_ALL_OK: + default: + return true; + } +} + +static DDS_Security_boolean test_return_authenticated_peer_credential_token( + dds_security_authentication *instance, + const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->return_authenticated_peer_credential_token(impl->instance, peer_credential_token, ex); + case PLUGIN_MODE_ALL_OK: + default: + return true; + } +} + +static DDS_Security_boolean test_return_handshake_handle(dds_security_authentication *instance, + const DDS_Security_HandshakeHandle handshake_handle, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->return_handshake_handle(impl->instance, handshake_handle, ex); + case PLUGIN_MODE_ALL_OK: + default: + return true; + } +} + +static DDS_Security_boolean test_return_identity_handle( + dds_security_authentication *instance, + const DDS_Security_IdentityHandle identity_handle, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->return_identity_handle(impl->instance, identity_handle, ex); + default: + return true; + } +} + +static DDS_Security_boolean test_return_sharedsecret_handle( + dds_security_authentication *instance, + const DDS_Security_SharedSecretHandle sharedsecret_handle, + DDS_Security_SecurityException *ex) +{ + struct dds_security_authentication_impl *impl = (struct dds_security_authentication_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->return_sharedsecret_handle(impl->instance, sharedsecret_handle, ex); + case PLUGIN_MODE_ALL_OK: + default: + return true; + } +} + +static struct dds_security_authentication_impl * get_impl_for_domain(dds_domainid_t domain_id) +{ + for (size_t i = 0; i < auth_impl_count; i++) + { + if (auth_impl[i]->gv->config.domainId == domain_id) + { + assert(auth_impl[i]); + return auth_impl[i]; + } + } + return NULL; +} + +struct message * test_authentication_plugin_take_msg(dds_domainid_t domain_id, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, dds_duration_t timeout) +{ + struct dds_security_authentication_impl *impl = get_impl_for_domain(domain_id); + assert(impl); + return take_message(&impl->msg_queue, kind, lidHandle, ridHandle, hsHandle, timeout); +} + +void test_authentication_plugin_release_msg(struct message *msg) +{ + delete_message(msg); +} + +static struct dds_security_authentication_impl * init_test_authentication_common() +{ + struct dds_security_authentication_impl * impl = ddsrt_malloc(sizeof(*impl)); + memset(impl, 0, sizeof(*impl)); + impl->base.validate_local_identity = &test_validate_local_identity; + impl->base.get_identity_token = &test_get_identity_token; + impl->base.get_identity_status_token = &test_get_identity_status_token; + impl->base.set_permissions_credential_and_token = &test_set_permissions_credential_and_token; + impl->base.validate_remote_identity = &test_validate_remote_identity; + impl->base.begin_handshake_request = &test_begin_handshake_request; + impl->base.begin_handshake_reply = &test_begin_handshake_reply; + impl->base.process_handshake = &test_process_handshake; + impl->base.get_shared_secret = &test_get_shared_secret; + impl->base.get_authenticated_peer_credential_token = &test_get_authenticated_peer_credential_token; + impl->base.set_listener = &test_set_listener; + impl->base.return_identity_token = &test_return_identity_token; + impl->base.return_identity_status_token = &test_return_identity_status_token; + impl->base.return_authenticated_peer_credential_token = &test_return_authenticated_peer_credential_token; + impl->base.return_handshake_handle = &test_return_handshake_handle; + impl->base.return_identity_handle = &test_return_identity_handle; + impl->base.return_sharedsecret_handle = &test_return_sharedsecret_handle; + return impl; +} + +int32_t init_test_authentication_all_ok(const char *argument, void **context) +{ + DDSRT_UNUSED_ARG(argument); + DDSRT_UNUSED_ARG(context); + struct dds_security_authentication_impl *impl = init_test_authentication_common(); + impl->mode = PLUGIN_MODE_ALL_OK; + *context = impl; + return 0; +} + +int32_t finalize_test_authentication_all_ok(void *context) +{ + assert(((struct dds_security_authentication_impl *)context)->mode == PLUGIN_MODE_ALL_OK); + ddsrt_free(context); + return 0; +} + +int32_t init_test_authentication_missing_func(const char *argument, void **context) +{ + DDSRT_UNUSED_ARG(argument); + DDSRT_UNUSED_ARG(context); + struct dds_security_authentication_impl *impl = init_test_authentication_common(); + impl->base.get_shared_secret = NULL; + impl->mode = PLUGIN_MODE_MISSING_FUNC; + *context = impl; + return 0; +} + +int32_t finalize_test_authentication_missing_func(void *context) +{ + assert(((struct dds_security_authentication_impl *)context)->mode == PLUGIN_MODE_MISSING_FUNC); + ddsrt_free(context); + return 0; +} + +int32_t init_test_authentication_init_error(const char *argument, void **context) +{ + DDSRT_UNUSED_ARG(argument); + DDSRT_UNUSED_ARG(context); + return 1; +} + +int32_t finalize_test_authentication_init_error(void *context) +{ + DDSRT_UNUSED_ARG(context); + return 0; +} + +int32_t init_test_authentication_wrapped(const char *argument, void **context) +{ + int32_t ret; + struct dds_security_authentication_impl *impl = init_test_authentication_common(); + impl->mode = PLUGIN_MODE_WRAPPED; + + init_message_queue(&impl->msg_queue); + struct thread_state1 * const ts1 = lookup_thread_state (); + struct ddsi_domaingv const * const gv = ddsrt_atomic_ldvoidp (&ts1->gv); + impl->gv = gv; + + ret = init_authentication(argument, (void **)&impl->instance); + + auth_impl_count++; + auth_impl = ddsrt_realloc(auth_impl, auth_impl_count * sizeof(*auth_impl)); + auth_impl[auth_impl_count - 1] = impl; + + *context = impl; + return ret; +} + +int32_t finalize_test_authentication_wrapped(void *context) +{ + int32_t ret; + struct dds_security_authentication_impl *impl = context; + assert(impl->mode == PLUGIN_MODE_WRAPPED); + deinit_message_queue(&impl->msg_queue); + ret = finalize_authentication(impl->instance); + ddsrt_free(context); + auth_impl_count--; + return ret; +} + diff --git a/src/security/core/tests/common/authentication_wrapper.h b/src/security/core/tests/common/authentication_wrapper.h new file mode 100644 index 0000000..be4854a --- /dev/null +++ b/src/security/core/tests/common/authentication_wrapper.h @@ -0,0 +1,38 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef SECURITY_CORE_TEST_AUTHENTICATION_WRAPPER_H_ +#define SECURITY_CORE_TEST_AUTHENTICATION_WRAPPER_H_ + +#include "dds/security/dds_security_api.h" +#include "dds/security/authentication_wrapper_export.h" +#include "plugin_wrapper_msg_q.h" + +/* Init in wrapper mode */ +SECURITY_EXPORT int32_t init_test_authentication_wrapped(const char *argument, void **context); +SECURITY_EXPORT int32_t finalize_test_authentication_wrapped(void *context); + +/* Init in all-ok mode: all functions return success without calling the actual plugin */ +SECURITY_EXPORT int32_t init_test_authentication_all_ok(const char *argument, void **context); +SECURITY_EXPORT int32_t finalize_test_authentication_all_ok(void *context); + +/* Init in missing function mode: one of the function pointers is null */ +SECURITY_EXPORT int32_t init_test_authentication_missing_func(const char *argument, void **context); +SECURITY_EXPORT int32_t finalize_test_authentication_missing_func(void *context); + +/* Init function fails */ +SECURITY_EXPORT int32_t init_test_authentication_init_error(const char *argument, void **context); +SECURITY_EXPORT int32_t finalize_test_authentication_init_error(void *context); + +SECURITY_EXPORT struct message * test_authentication_plugin_take_msg(dds_domainid_t domain_id, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, dds_duration_t timeout); +SECURITY_EXPORT void test_authentication_plugin_release_msg(struct message *msg); + +#endif /* SECURITY_CORE_TEST_AUTHENTICATION_WRAPPER_H_ */ diff --git a/src/security/core/tests/common/config_env.h.in b/src/security/core/tests/common/config_env.h.in new file mode 100644 index 0000000..a3773f1 --- /dev/null +++ b/src/security/core/tests/common/config_env.h.in @@ -0,0 +1,27 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef CONFIG_ENV_H +#define CONFIG_ENV_H + +#define FILE_PATH_SEP "@file_path_sep@" +#define COMMON_ETC_DIR "@common_etc_dir@" +#define PLUGIN_WRAPPER_LIB_DIR "@plugin_wrapper_lib_dir@" +#define PLUGIN_WRAPPER_LIB_PREFIX "@CMAKE_SHARED_LIBRARY_PREFIX@" +#define PLUGIN_WRAPPER_LIB_SUFFIX "@CMAKE_SHARED_LIBRARY_SUFFIX@" + +#define WRAPPERLIB_PATH(name) \ + PLUGIN_WRAPPER_LIB_DIR FILE_PATH_SEP PLUGIN_WRAPPER_LIB_PREFIX name PLUGIN_WRAPPER_LIB_SUFFIX + +#define COMMON_ETC_PATH(name) \ + COMMON_ETC_DIR FILE_PATH_SEP name + +#endif /* CONFIG_ENV_H */ diff --git a/src/security/core/tests/common/cryptography_wrapper.c b/src/security/core/tests/common/cryptography_wrapper.c new file mode 100644 index 0000000..ad9346b --- /dev/null +++ b/src/security/core/tests/common/cryptography_wrapper.c @@ -0,0 +1,728 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include "dds/dds.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsi/ddsi_domaingv.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/dds_security_api_defs.h" +#include "dds/security/core/dds_security_utils.h" +#include "cryptography_wrapper.h" + +int32_t init_crypto(const char *argument, void **context); +int32_t finalize_crypto(void *context); + +enum crypto_plugin_mode { + PLUGIN_MODE_ALL_OK, + PLUGIN_MODE_MISSING_FUNC, + PLUGIN_MODE_WRAPPED +}; + +struct dds_security_crypto_key_exchange_impl { + struct dds_security_crypto_key_exchange base; + struct dds_security_crypto_key_exchange *instance; + struct dds_security_cryptography_impl *parent; +}; + +struct dds_security_crypto_key_factory_impl { + struct dds_security_crypto_key_factory base; + struct dds_security_crypto_key_factory *instance; + struct dds_security_cryptography_impl *parent; +}; + +struct dds_security_crypto_transform_impl { + struct dds_security_crypto_transform base; + struct dds_security_crypto_transform *instance; + struct dds_security_cryptography_impl *parent; +}; + +struct dds_security_cryptography_impl { + struct dds_security_cryptography base; + struct dds_security_cryptography *instance; + struct dds_security_crypto_transform_impl transform_wrap; + struct dds_security_crypto_key_factory_impl factory_wrap; + struct dds_security_crypto_key_exchange_impl exchange_wrap; + enum crypto_plugin_mode mode; + DDS_Security_ProtectionKind rtps_protection_kind; + DDS_Security_ProtectionKind metadata_protection_kind; + DDS_Security_BasicProtectionKind payload_protection_kind; +}; + +static DDS_Security_ParticipantCryptoHandle g_local_participant_handle = 0; + +void set_protection_kinds( + struct dds_security_cryptography_impl * impl, + DDS_Security_ProtectionKind rtps_protection_kind, + DDS_Security_ProtectionKind metadata_protection_kind, + DDS_Security_BasicProtectionKind payload_protection_kind) +{ + assert(impl); + impl->rtps_protection_kind = rtps_protection_kind; + impl->metadata_protection_kind = metadata_protection_kind; + impl->payload_protection_kind = payload_protection_kind; +} + +static unsigned char * find_buffer_match(unsigned char *input, size_t input_len, unsigned char *match, size_t match_len) +{ + if (match_len <= input_len && match_len > 0 && input_len > 0) + { + unsigned char *match_end = match + match_len; + unsigned char *i = input; + while (i <= input + input_len - match_len) + { + unsigned char *m = match, *j = i; + while (*m == *j && j < input + input_len) + { + j++; + if (++m == match_end) + return i; + } + i++; + } + } + return NULL; +} + +static bool check_buffers(const DDS_Security_OctetSeq *encoded_buffer, const DDS_Security_OctetSeq *plain_buffer, bool expect_encrypted, DDS_Security_SecurityException *ex) +{ + unsigned char *m = find_buffer_match (encoded_buffer->_buffer, encoded_buffer->_length, + plain_buffer->_buffer, plain_buffer->_length); + if ((m == NULL) != expect_encrypted) + { + ex->code = 1; + ex->message = ddsrt_strdup (expect_encrypted ? + "Expect encryption, but clear payload found after encoding." : "Expect only signature, but clear payload was not found in source after decoding."); + return false; + } + return true; +} + +static DDS_Security_long_long check_handle(DDS_Security_long_long handle) +{ + /* Assume that handle, which actually is a pointer, has a value that is likely to be + a valid memory address and not a value returned by the mock implementation. */ + assert (handle == 0 || handle > 4096); + return handle; +} + +static bool expect_encrypted_buffer (DDS_Security_ProtectionKind pk) +{ + return pk == DDS_SECURITY_PROTECTION_KIND_ENCRYPT || pk == DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION; +} + +/** + * Crypto key exchange + */ +static DDS_Security_boolean create_local_participant_crypto_tokens( + dds_security_crypto_key_exchange *instance, + DDS_Security_ParticipantCryptoTokenSeq *local_participant_crypto_tokens, + const DDS_Security_ParticipantCryptoHandle local_participant_crypto, + const DDS_Security_ParticipantCryptoHandle remote_participant_crypto, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_key_exchange_impl *impl = (struct dds_security_crypto_key_exchange_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->create_local_participant_crypto_tokens (impl->instance, local_participant_crypto_tokens, + local_participant_crypto, remote_participant_crypto, ex); + default: + return true; + } +} + +static DDS_Security_boolean set_remote_participant_crypto_tokens( + dds_security_crypto_key_exchange *instance, + const DDS_Security_ParticipantCryptoHandle local_participant_crypto, + const DDS_Security_ParticipantCryptoHandle remote_participant_crypto, + const DDS_Security_ParticipantCryptoTokenSeq *remote_participant_tokens, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_key_exchange_impl *impl = (struct dds_security_crypto_key_exchange_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->set_remote_participant_crypto_tokens (impl->instance, check_handle (local_participant_crypto), + check_handle (remote_participant_crypto), remote_participant_tokens, ex); + default: + return true; + } +} + +static DDS_Security_boolean create_local_datawriter_crypto_tokens( + dds_security_crypto_key_exchange *instance, + DDS_Security_DatawriterCryptoTokenSeq *local_datawriter_crypto_tokens, + const DDS_Security_DatawriterCryptoHandle local_datawriter_crypto, + const DDS_Security_DatareaderCryptoHandle remote_datareader_crypto, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_key_exchange_impl *impl = (struct dds_security_crypto_key_exchange_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->create_local_datawriter_crypto_tokens (impl->instance, local_datawriter_crypto_tokens, + check_handle (local_datawriter_crypto), check_handle (remote_datareader_crypto), ex); + default: + return true; + } +} + +static DDS_Security_boolean set_remote_datawriter_crypto_tokens( + dds_security_crypto_key_exchange *instance, + const DDS_Security_DatareaderCryptoHandle local_datareader_crypto, + const DDS_Security_DatawriterCryptoHandle remote_datawriter_crypto, + const DDS_Security_DatawriterCryptoTokenSeq *remote_datawriter_tokens, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_key_exchange_impl *impl = (struct dds_security_crypto_key_exchange_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->set_remote_datawriter_crypto_tokens (impl->instance, check_handle (local_datareader_crypto), + check_handle (remote_datawriter_crypto), remote_datawriter_tokens, ex); + default: + return true; + } +} + +static DDS_Security_boolean create_local_datareader_crypto_tokens( + dds_security_crypto_key_exchange *instance, + DDS_Security_DatareaderCryptoTokenSeq *local_datareader_cryto_tokens, + const DDS_Security_DatareaderCryptoHandle local_datareader_crypto, + const DDS_Security_DatawriterCryptoHandle remote_datawriter_crypto, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_key_exchange_impl *impl = (struct dds_security_crypto_key_exchange_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->create_local_datareader_crypto_tokens (impl->instance, local_datareader_cryto_tokens, + check_handle (local_datareader_crypto), check_handle (remote_datawriter_crypto), ex); + default: + return true; + } +} + +static DDS_Security_boolean set_remote_datareader_crypto_tokens( + dds_security_crypto_key_exchange *instance, + const DDS_Security_DatawriterCryptoHandle local_datawriter_crypto, + const DDS_Security_DatareaderCryptoHandle remote_datareader_crypto, + const DDS_Security_DatareaderCryptoTokenSeq *remote_datareader_tokens, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_key_exchange_impl *impl = (struct dds_security_crypto_key_exchange_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->set_remote_datareader_crypto_tokens (impl->instance, check_handle (local_datawriter_crypto), + check_handle (remote_datareader_crypto), remote_datareader_tokens, ex); + default: + return true; + } +} + +static DDS_Security_boolean return_crypto_tokens( + dds_security_crypto_key_exchange *instance, + DDS_Security_CryptoTokenSeq *crypto_tokens, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_key_exchange_impl *impl = (struct dds_security_crypto_key_exchange_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->return_crypto_tokens (impl->instance, crypto_tokens, ex); + default: + return true; + } +} + +/** + * Crypto key factory + */ +static DDS_Security_ParticipantCryptoHandle register_local_participant( + dds_security_crypto_key_factory *instance, + const DDS_Security_IdentityHandle participant_identity, + const DDS_Security_PermissionsHandle participant_permissions, + const DDS_Security_PropertySeq *participant_properties, + const DDS_Security_ParticipantSecurityAttributes *participant_security_attributes, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_key_factory_impl *impl = (struct dds_security_crypto_key_factory_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return check_handle (impl->instance->register_local_participant (impl->instance, check_handle (participant_identity), + check_handle (participant_permissions), participant_properties, participant_security_attributes, ex)); + default: + return ++g_local_participant_handle; + } +} + +static DDS_Security_ParticipantCryptoHandle register_matched_remote_participant( + dds_security_crypto_key_factory *instance, + const DDS_Security_ParticipantCryptoHandle local_participant_crypto_handle, + const DDS_Security_IdentityHandle remote_participant_identity, + const DDS_Security_PermissionsHandle remote_participant_permissions, + const DDS_Security_SharedSecretHandle shared_secret, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_key_factory_impl *impl = (struct dds_security_crypto_key_factory_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return check_handle (impl->instance->register_matched_remote_participant (impl->instance, local_participant_crypto_handle, + remote_participant_identity, remote_participant_permissions, shared_secret, ex)); + default: + return 0; + } +} + +static DDS_Security_DatawriterCryptoHandle register_local_datawriter( + dds_security_crypto_key_factory *instance, + const DDS_Security_ParticipantCryptoHandle participant_crypto, + const DDS_Security_PropertySeq *datawriter_properties, + const DDS_Security_EndpointSecurityAttributes *datawriter_security_attributes, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_key_factory_impl *impl = (struct dds_security_crypto_key_factory_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return check_handle (impl->instance->register_local_datawriter (impl->instance, check_handle (participant_crypto), + datawriter_properties, datawriter_security_attributes, ex)); + default: + return 0; + } +} + +static DDS_Security_DatareaderCryptoHandle register_matched_remote_datareader( + dds_security_crypto_key_factory *instance, + const DDS_Security_DatawriterCryptoHandle local_datawriter_crypto_handle, + const DDS_Security_ParticipantCryptoHandle remote_participant_crypto, + const DDS_Security_SharedSecretHandle shared_secret, + const DDS_Security_boolean relay_only, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_key_factory_impl *impl = (struct dds_security_crypto_key_factory_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return check_handle (impl->instance->register_matched_remote_datareader (impl->instance, check_handle (local_datawriter_crypto_handle), + check_handle (remote_participant_crypto), check_handle (shared_secret), relay_only, ex)); + default: + return 0; + } +} + +static DDS_Security_DatareaderCryptoHandle register_local_datareader( + dds_security_crypto_key_factory *instance, + const DDS_Security_ParticipantCryptoHandle participant_crypto, + const DDS_Security_PropertySeq *datareader_properties, + const DDS_Security_EndpointSecurityAttributes *datareader_security_attributes, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_key_factory_impl *impl = (struct dds_security_crypto_key_factory_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return check_handle (impl->instance->register_local_datareader (impl->instance, check_handle (participant_crypto), + datareader_properties, datareader_security_attributes, ex)); + default: + return 0; + } +} + +static DDS_Security_DatawriterCryptoHandle register_matched_remote_datawriter( + dds_security_crypto_key_factory *instance, + const DDS_Security_DatareaderCryptoHandle local_datareader_crypto_handle, + const DDS_Security_ParticipantCryptoHandle remote_participant_crypt, + const DDS_Security_SharedSecretHandle shared_secret, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_key_factory_impl *impl = (struct dds_security_crypto_key_factory_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return check_handle (impl->instance->register_matched_remote_datawriter (impl->instance, check_handle (local_datareader_crypto_handle), + check_handle (remote_participant_crypt), shared_secret, ex)); + default: + return 1; + } +} + +static DDS_Security_boolean unregister_participant( + dds_security_crypto_key_factory *instance, + const DDS_Security_ParticipantCryptoHandle participant_crypto_handle, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_key_factory_impl *impl = (struct dds_security_crypto_key_factory_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->unregister_participant (impl->instance, check_handle (participant_crypto_handle), ex); + default: + return true; + } +} + +static DDS_Security_boolean unregister_datawriter( + dds_security_crypto_key_factory *instance, + const DDS_Security_DatawriterCryptoHandle datawriter_crypto_handle, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_key_factory_impl *impl = (struct dds_security_crypto_key_factory_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->unregister_datawriter (impl->instance, check_handle (datawriter_crypto_handle), ex); + default: + return true; + } +} + +static DDS_Security_boolean unregister_datareader( + dds_security_crypto_key_factory *instance, + const DDS_Security_DatareaderCryptoHandle datareader_crypto_handle, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_key_factory_impl *impl = (struct dds_security_crypto_key_factory_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->unregister_datareader (impl->instance, check_handle (datareader_crypto_handle), ex); + default: + return true; + } +} + +/** + * Crypto transform + */ +static DDS_Security_boolean encode_serialized_payload( + dds_security_crypto_transform *instance, + DDS_Security_OctetSeq *encoded_buffer, + DDS_Security_OctetSeq *extra_inline_qos, + const DDS_Security_OctetSeq *plain_buffer, + const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_transform_impl *impl = (struct dds_security_crypto_transform_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + if (!impl->instance->encode_serialized_payload (impl->instance, encoded_buffer, + extra_inline_qos, plain_buffer, check_handle (sending_datawriter_crypto), ex)) + return false; + return check_buffers (encoded_buffer, plain_buffer, impl->parent->payload_protection_kind == DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT, ex); + default: + return true; + } +} + +static DDS_Security_boolean encode_datawriter_submessage( + dds_security_crypto_transform *instance, + DDS_Security_OctetSeq *encoded_rtps_submessage, + const DDS_Security_OctetSeq *plain_rtps_submessage, + const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, + const DDS_Security_DatareaderCryptoHandleSeq *receiving_datareader_crypto_list, + int32_t *receiving_datareader_crypto_list_index, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_transform_impl *impl = (struct dds_security_crypto_transform_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + if (!impl->instance->encode_datawriter_submessage (impl->instance, encoded_rtps_submessage, + plain_rtps_submessage, check_handle (sending_datawriter_crypto), receiving_datareader_crypto_list, receiving_datareader_crypto_list_index, ex)) + return false; + return expect_encrypted_buffer (impl->parent->metadata_protection_kind) ? + check_buffers (encoded_rtps_submessage, plain_rtps_submessage, true, ex) : true; + default: + return true; + } +} + +static DDS_Security_boolean encode_datareader_submessage( + dds_security_crypto_transform *instance, + DDS_Security_OctetSeq *encoded_rtps_submessage, + const DDS_Security_OctetSeq *plain_rtps_submessage, + const DDS_Security_DatareaderCryptoHandle sending_datareader_crypto, + const DDS_Security_DatawriterCryptoHandleSeq *receiving_datawriter_crypto_list, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_transform_impl *impl = (struct dds_security_crypto_transform_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + if (!impl->instance->encode_datareader_submessage (impl->instance, encoded_rtps_submessage, + plain_rtps_submessage, check_handle (sending_datareader_crypto), receiving_datawriter_crypto_list, ex)) + return false; + return expect_encrypted_buffer (impl->parent->metadata_protection_kind) ? + check_buffers (encoded_rtps_submessage, plain_rtps_submessage, true, ex) : true; + default: + return true; + } +} + +static DDS_Security_boolean encode_rtps_message( + dds_security_crypto_transform *instance, + DDS_Security_OctetSeq *encoded_rtps_message, + const DDS_Security_OctetSeq *plain_rtps_message, + const DDS_Security_ParticipantCryptoHandle sending_participant_crypto, + const DDS_Security_ParticipantCryptoHandleSeq *receiving_participant_crypto_list, + int32_t *receiving_participant_crypto_list_index, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_transform_impl *impl = (struct dds_security_crypto_transform_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + if (!impl->instance->encode_rtps_message (impl->instance, encoded_rtps_message, + plain_rtps_message, check_handle (sending_participant_crypto), receiving_participant_crypto_list, receiving_participant_crypto_list_index, ex)) + return false; + return expect_encrypted_buffer (impl->parent->rtps_protection_kind) ? + check_buffers (encoded_rtps_message, plain_rtps_message, true, ex) : true; + default: + return true; + } +} + +static DDS_Security_boolean decode_rtps_message( + dds_security_crypto_transform *instance, + DDS_Security_OctetSeq *plain_buffer, + const DDS_Security_OctetSeq *encoded_buffer, + const DDS_Security_ParticipantCryptoHandle receiving_participant_crypto, + const DDS_Security_ParticipantCryptoHandle sending_participant_crypto, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_transform_impl *impl = (struct dds_security_crypto_transform_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + if (!impl->instance->decode_rtps_message (impl->instance, plain_buffer, encoded_buffer, + check_handle (receiving_participant_crypto), check_handle (sending_participant_crypto), ex)) + return false; + return expect_encrypted_buffer (impl->parent->rtps_protection_kind) ? + check_buffers (encoded_buffer, plain_buffer, true, ex) : true; + default: + return true; + } +} + +static DDS_Security_boolean preprocess_secure_submsg( + dds_security_crypto_transform *instance, + DDS_Security_DatawriterCryptoHandle *datawriter_crypto, + DDS_Security_DatareaderCryptoHandle *datareader_crypto, + DDS_Security_SecureSubmessageCategory_t *secure_submessage_category, + const DDS_Security_OctetSeq *encoded_rtps_submessage, + const DDS_Security_ParticipantCryptoHandle receiving_participant_crypto, + const DDS_Security_ParticipantCryptoHandle sending_participant_crypto, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_transform_impl *impl = (struct dds_security_crypto_transform_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + return impl->instance->preprocess_secure_submsg (impl->instance, datawriter_crypto, datareader_crypto, + secure_submessage_category, encoded_rtps_submessage, check_handle (receiving_participant_crypto), check_handle (sending_participant_crypto), ex); + default: + return true; + } +} + +static DDS_Security_boolean decode_datawriter_submessage( + dds_security_crypto_transform *instance, + DDS_Security_OctetSeq *plain_rtps_submessage, + const DDS_Security_OctetSeq *encoded_rtps_submessage, + const DDS_Security_DatareaderCryptoHandle receiving_datareader_crypto, + const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_transform_impl *impl = (struct dds_security_crypto_transform_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + if (!impl->instance->decode_datawriter_submessage (impl->instance, plain_rtps_submessage, + encoded_rtps_submessage, check_handle (receiving_datareader_crypto), check_handle (sending_datawriter_crypto), ex)) + return false; + return expect_encrypted_buffer (impl->parent->metadata_protection_kind) ? + check_buffers (encoded_rtps_submessage, plain_rtps_submessage, true, ex) : true; + default: + return true; + } +} + +static DDS_Security_boolean decode_datareader_submessage( + dds_security_crypto_transform *instance, + DDS_Security_OctetSeq *plain_rtps_submessage, + const DDS_Security_OctetSeq *encoded_rtps_submessage, + const DDS_Security_DatawriterCryptoHandle receiving_datawriter_crypto, + const DDS_Security_DatareaderCryptoHandle sending_datareader_crypto, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_transform_impl *impl = (struct dds_security_crypto_transform_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + if (!impl->instance->decode_datareader_submessage (impl->instance, plain_rtps_submessage, + encoded_rtps_submessage, check_handle (receiving_datawriter_crypto), check_handle (sending_datareader_crypto), ex)) + return false; + return expect_encrypted_buffer (impl->parent->metadata_protection_kind) ? + check_buffers (encoded_rtps_submessage, plain_rtps_submessage, true, ex) : true; + default: + return true; + } +} + +static DDS_Security_boolean decode_serialized_payload( + dds_security_crypto_transform *instance, + DDS_Security_OctetSeq *plain_buffer, + const DDS_Security_OctetSeq *encoded_buffer, + const DDS_Security_OctetSeq *inline_qos, + const DDS_Security_DatareaderCryptoHandle receiving_datareader_crypto, + const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, + DDS_Security_SecurityException *ex) +{ + struct dds_security_crypto_transform_impl *impl = (struct dds_security_crypto_transform_impl *)instance; + switch (impl->parent->mode) + { + case PLUGIN_MODE_WRAPPED: + if (!impl->instance->decode_serialized_payload(impl->instance, plain_buffer, encoded_buffer, + inline_qos, check_handle (receiving_datareader_crypto), check_handle (sending_datawriter_crypto), ex)) + return false; + return check_buffers(encoded_buffer, plain_buffer, impl->parent->payload_protection_kind == DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT, ex); + default: + return true; + } +} + +/** + * Init and finalize functions + */ +static struct dds_security_cryptography_impl * init_test_cryptography_common(const char *argument, bool wrapped) +{ + struct dds_security_cryptography_impl *impl = (struct dds_security_cryptography_impl*) ddsrt_malloc(sizeof(*impl)); + memset(impl, 0, sizeof(*impl)); + + if (wrapped) + { + if (init_crypto(argument, (void **)&impl->instance) != DDS_SECURITY_SUCCESS) + return NULL; + + impl->transform_wrap.instance = impl->instance->crypto_transform; + impl->factory_wrap.instance = impl->instance->crypto_key_factory; + impl->exchange_wrap.instance = impl->instance->crypto_key_exchange; + } + + impl->base.crypto_transform = (dds_security_crypto_transform *)&impl->transform_wrap; + impl->base.crypto_key_factory = (dds_security_crypto_key_factory *)&impl->factory_wrap; + impl->base.crypto_key_exchange = (dds_security_crypto_key_exchange *)&impl->exchange_wrap; + + impl->transform_wrap.parent = impl; + impl->factory_wrap.parent = impl; + impl->exchange_wrap.parent = impl; + + impl->factory_wrap.base.register_local_participant = ®ister_local_participant; + impl->factory_wrap.base.register_matched_remote_participant = ®ister_matched_remote_participant; + impl->factory_wrap.base.register_local_datawriter = ®ister_local_datawriter; + impl->factory_wrap.base.register_matched_remote_datareader = ®ister_matched_remote_datareader; + impl->factory_wrap.base.register_local_datareader = ®ister_local_datareader; + impl->factory_wrap.base.register_matched_remote_datawriter = ®ister_matched_remote_datawriter; + impl->factory_wrap.base.unregister_participant = &unregister_participant; + impl->factory_wrap.base.unregister_datawriter = &unregister_datawriter; + impl->factory_wrap.base.unregister_datareader = &unregister_datareader; + + impl->exchange_wrap.base.create_local_participant_crypto_tokens = &create_local_participant_crypto_tokens; + impl->exchange_wrap.base.set_remote_participant_crypto_tokens = &set_remote_participant_crypto_tokens; + impl->exchange_wrap.base.create_local_datawriter_crypto_tokens = &create_local_datawriter_crypto_tokens; + impl->exchange_wrap.base.set_remote_datawriter_crypto_tokens = &set_remote_datawriter_crypto_tokens; + impl->exchange_wrap.base.create_local_datareader_crypto_tokens = &create_local_datareader_crypto_tokens; + impl->exchange_wrap.base.set_remote_datareader_crypto_tokens = &set_remote_datareader_crypto_tokens; + impl->exchange_wrap.base.return_crypto_tokens = &return_crypto_tokens; + + impl->transform_wrap.base.encode_datawriter_submessage = &encode_datawriter_submessage; + impl->transform_wrap.base.encode_datareader_submessage = &encode_datareader_submessage; + impl->transform_wrap.base.encode_rtps_message = &encode_rtps_message; + impl->transform_wrap.base.decode_rtps_message = &decode_rtps_message; + impl->transform_wrap.base.preprocess_secure_submsg = &preprocess_secure_submsg; + impl->transform_wrap.base.decode_datawriter_submessage = &decode_datawriter_submessage; + impl->transform_wrap.base.decode_datareader_submessage = &decode_datareader_submessage; + impl->transform_wrap.base.decode_serialized_payload = &decode_serialized_payload; + impl->transform_wrap.base.encode_serialized_payload = &encode_serialized_payload; + + return impl; +} + +static int32_t finalize_test_cryptography_common(struct dds_security_cryptography_impl * impl, bool wrapped) +{ + int32_t ret; + if (wrapped && (ret = finalize_crypto(impl->instance)) != DDS_SECURITY_SUCCESS) + return ret; + ddsrt_free(impl); + return DDS_SECURITY_SUCCESS; +} + +int32_t init_test_cryptography_all_ok(const char *argument, void **context) +{ + struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, false); + if (!impl) + return DDS_SECURITY_FAILED; + impl->mode = PLUGIN_MODE_ALL_OK; + *context = impl; + return DDS_SECURITY_SUCCESS; +} + +int32_t finalize_test_cryptography_all_ok(void *context) +{ + struct dds_security_cryptography_impl* impl = (struct dds_security_cryptography_impl*) context; + assert(impl->mode == PLUGIN_MODE_ALL_OK); + return finalize_test_cryptography_common(impl, false); +} + +int32_t init_test_cryptography_missing_func(const char *argument, void **context) +{ + struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, false); + if (!impl) + return DDS_SECURITY_FAILED; + impl->base.crypto_key_exchange->set_remote_participant_crypto_tokens = NULL; + impl->mode = PLUGIN_MODE_MISSING_FUNC; + *context = impl; + return DDS_SECURITY_SUCCESS; +} + +int32_t finalize_test_cryptography_missing_func(void *context) +{ + struct dds_security_cryptography_impl* impl = (struct dds_security_cryptography_impl*) context; + assert(impl->mode == PLUGIN_MODE_MISSING_FUNC); + return finalize_test_cryptography_common(impl, false); +} + +int32_t init_test_cryptography_wrapped(const char *argument, void **context) +{ + struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, true); + if (!impl) + return DDS_SECURITY_FAILED; + impl->mode = PLUGIN_MODE_WRAPPED; + *context = impl; + return DDS_SECURITY_SUCCESS; +} + +int32_t finalize_test_cryptography_wrapped(void *context) +{ + struct dds_security_cryptography_impl* impl = (struct dds_security_cryptography_impl*) context; + assert(impl->mode == PLUGIN_MODE_WRAPPED); + return finalize_test_cryptography_common(impl, true); +} + diff --git a/src/security/core/tests/common/cryptography_wrapper.h b/src/security/core/tests/common/cryptography_wrapper.h new file mode 100644 index 0000000..9fd17d1 --- /dev/null +++ b/src/security/core/tests/common/cryptography_wrapper.h @@ -0,0 +1,39 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef SECURITY_CORE_TEST_CRYPTO_WRAPPER_H_ +#define SECURITY_CORE_TEST_CRYPTO_WRAPPER_H_ + +#include "dds/security/dds_security_api.h" +#include "dds/security/dds_security_api_defs.h" +#include "dds/security/cryptography_wrapper_export.h" + +struct dds_security_cryptography_impl; + +SECURITY_EXPORT void set_protection_kinds( + struct dds_security_cryptography_impl * impl, + DDS_Security_ProtectionKind rtps_protection_kind, + DDS_Security_ProtectionKind metadata_protection_kind, + DDS_Security_BasicProtectionKind payload_protection_kind); + +/* Init in all-ok mode: all functions return success without calling the actual plugin */ +SECURITY_EXPORT int32_t init_test_cryptography_all_ok(const char *argument, void **context); +SECURITY_EXPORT int32_t finalize_test_cryptography_all_ok(void *context); + +/* Init in missing function mode: one of the function pointers is null */ +SECURITY_EXPORT int32_t init_test_cryptography_missing_func(const char *argument, void **context); +SECURITY_EXPORT int32_t finalize_test_cryptography_missing_func(void *context); + +/* Init in wrapper mode */ +SECURITY_EXPORT int32_t init_test_cryptography_wrapped(const char *argument, void **context); +SECURITY_EXPORT int32_t finalize_test_cryptography_wrapped(void *context); + +#endif /* SECURITY_CORE_TEST_CRYPTO_WRAPPER_H_ */ diff --git a/src/security/core/tests/common/etc/create_p7s b/src/security/core/tests/common/etc/create_p7s new file mode 100755 index 0000000..904e7bd --- /dev/null +++ b/src/security/core/tests/common/etc/create_p7s @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +# Argument +if [ -z "$1" ] +then + echo "This script can be used for signing Permissions and Governance file list. Can be called from any directory" + echo "Expected a filename list with or without the .xml extension" + echo "PERMISSION_CA_CERT and PERMISSION_CA_KEY environment variables are used for signing if they are set" + exit +fi + +# Location of the pem files is the same as this script location. +PEM_LOCATION="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" +if [ -v PERMISSION_CA_CERT ] && [ -v PERMISSION_CA_KEY ] ; then + echo "Using custom permission key and certificate" + echo "PERMISSION_CA_CERT: $PERMISSION_CA_CERT" + echo "PERMISSION_CA_KEY: $PERMISSION_CA_KEY" +else + PERMISSION_CA_CERT=${PEM_LOCATION}/default_permissions_ca.pem + PERMISSION_CA_KEY=${PEM_LOCATION}/default_permissions_ca_key.pem +fi + +# Do all given files. +for filename in "$@" +do + if [ ${filename:${#filename}-4:4} == ".xml" ] ; then + BASE_FILE_NAME=${filename:0:-4} + echo $BASE_FILE_NAME + else + BASE_FILE_NAME=$filename + fi + + # Create the p7s file(s) + openssl smime -sign -in "${BASE_FILE_NAME}.xml" -text -out "${BASE_FILE_NAME}.p7s" -signer "$PERMISSION_CA_CERT" -inkey "$PERMISSION_CA_KEY" +done + diff --git a/src/security/core/tests/common/etc/default_governance.p7s b/src/security/core/tests/common/etc/default_governance.p7s new file mode 100644 index 0000000..0fae1eb --- /dev/null +++ b/src/security/core/tests/common/etc/default_governance.p7s @@ -0,0 +1,120 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----53BB1E1533C543713994C321F5A9998F" + +This is an S/MIME signed message + +------53BB1E1533C543713994C321F5A9998F +Content-Type: text/plain + + + + + + + + + 0 + 230 + + + + + false + + + true + + + ENCRYPT + + + ENCRYPT + + + ENCRYPT + + + + + * + + + true + + + true + + + true + + + true + + + ENCRYPT + + + ENCRYPT + + + + + + +------53BB1E1533C543713994C321F5A9998F +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIHoQYJKoZIhvcNAQcCoIIHkjCCB44CAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggRzMIIEbzCCA1egAwIBAgIUfoby6818hlJQ+41KUHiM6BZll/0w +DQYJKoZIhvcNAQELBQAwgcYxCzAJBgNVBAYTAk5MMQswCQYDVQQIDAJPVjEWMBQG +A1UEBwwNTG9jYWxpdHkgTmFtZTETMBEGA1UECwwKRXhhbXBsZSBPVTEgMB4GA1UE +CgwXRXhhbXBsZSBDQSBPcmdhbml6YXRpb24xHzAdBgNVBAMMFkV4YW1wbGUgUGVy +bWlzc2lvbnMgQ0ExOjA4BgkqhkiG9w0BCQEWK2F1dGhvcml0eUBjeWNsb25lZGRz +c2VjdXJpdHkuYWRsaW5rdGVjaC5jb20wHhcNMjAwMjI3MTM0ODA5WhcNMzAwMjI0 +MTM0ODA5WjCBxjELMAkGA1UEBhMCTkwxCzAJBgNVBAgMAk9WMRYwFAYDVQQHDA1M +b2NhbGl0eSBOYW1lMRMwEQYDVQQLDApFeGFtcGxlIE9VMSAwHgYDVQQKDBdFeGFt +cGxlIENBIE9yZ2FuaXphdGlvbjEfMB0GA1UEAwwWRXhhbXBsZSBQZXJtaXNzaW9u +cyBDQTE6MDgGCSqGSIb3DQEJARYrYXV0aG9yaXR5QGN5Y2xvbmVkZHNzZWN1cml0 +eS5hZGxpbmt0ZWNoLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANNWwyrW3J+TCyaZH77q+29GGqFsYP5rv9cpcL/TMDNccsPYY+1RA1K+zMRYo1LG +8VdJNtJlhxE+tmEbKxsVUTtoj8zbLVU4P4g0gIh6U7LMv5lUEZ3XYKWvYrbZTFMo +f2rXQYGXPO7pFnvbNAbnMiLmagRKxKJ91kq4utuMG3U6rkCA7i2S8cEISNO3gIpF +a0IZJ8yS8wDlKa/LGxL90BYasLsSA6tw/69OIiUUYqpMRD+xxyyTkMO37VjmdiFL +Ha/dxO8HH0t3Q0U0AgZP9uwYTgZpN+2UEFnjv3BDIydc3Wa0UaSdxLtHXMPvg3sR +uH9CTqr4Le7/3uTYehYKgd0CAwEAAaNTMFEwHQYDVR0OBBYEFFi4pK986ZSB0BLi +Mm8ivu6AUxYPMB8GA1UdIwQYMBaAFFi4pK986ZSB0BLiMm8ivu6AUxYPMA8GA1Ud +EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHYLaJVWrLHg+62jC8yIz9db +ECIroX9Gb7Ll937HMum6Hj4wlImrifMVV3iORWBrBLvtTtn0Zno3mwfjLRQtkjOi +h71eJT+6//B7CT7noULJYVq8IRGErbKtmXULnxTajFApzO0v4hSu7rWj/Jfhil0T +X7QgKNpgKzjYodWz3oGGtchxvw3+v9wdIWD5Cj0bk/VMCQCaBV0anvyga7d4k8/z +PF7nW2Z9jNfKsVD1piFa+Yd4zN6XOPPKiFXfLD7ht9i2gG25iS+d95tKg1DfjnRD +7u0BJSOAPerxGtN/wf43qY1XzUoE2FBJ9QJGOA/02ffaUMOwSzICF/ShctH+Knkx +ggLyMIIC7gIBATCB3zCBxjELMAkGA1UEBhMCTkwxCzAJBgNVBAgMAk9WMRYwFAYD +VQQHDA1Mb2NhbGl0eSBOYW1lMRMwEQYDVQQLDApFeGFtcGxlIE9VMSAwHgYDVQQK +DBdFeGFtcGxlIENBIE9yZ2FuaXphdGlvbjEfMB0GA1UEAwwWRXhhbXBsZSBQZXJt +aXNzaW9ucyBDQTE6MDgGCSqGSIb3DQEJARYrYXV0aG9yaXR5QGN5Y2xvbmVkZHNz +ZWN1cml0eS5hZGxpbmt0ZWNoLmNvbQIUfoby6818hlJQ+41KUHiM6BZll/0wDQYJ +YIZIAWUDBAIBBQCggeQwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG +9w0BCQUxDxcNMjAwMjI3MTM0ODM0WjAvBgkqhkiG9w0BCQQxIgQgEOdJRhNPEiPV +hgGuWuTP8V074cDixAzQ31XymGEq0asweQYJKoZIhvcNAQkPMWwwajALBglghkgB +ZQMEASowCwYJYIZIAWUDBAEWMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAOBggq +hkiG9w0DAgICAIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwIC +ASgwDQYJKoZIhvcNAQEBBQAEggEAKGHnKKHlTdyGgbduE/dvtq4CteGtJJFE1z/Y +aG5xKd8NeInFIvMtGEoxp+hum1uh0819XRyHbOA5FUSB8y1HXNqqnfe6YwscD6Ds +Ux/nYtUrDuckZp+F1ulzsHe/lq7khtVaweck9YHt0iKUszn2fea774bR/ZjdZ0Fr ++6DBKLBR8XOlYK7m0HOjlOoN4O0qTCh100001884C0O75KXnOEGA6saf9epOwL0Z +LitRo9Evh20IvYlOzzDS5ddQqtOPgMDhq1dO8Mra4KKmYc6vj2gsNzQag0l0LkQa +lRQ/3YFTD0vAt09DzqUehNOZbr9pOYZYbP/z/Ov7zrb0+kPGzQ== + +------53BB1E1533C543713994C321F5A9998F-- + diff --git a/src/security/core/tests/common/etc/default_governance.xml b/src/security/core/tests/common/etc/default_governance.xml new file mode 100644 index 0000000..7d3e314 --- /dev/null +++ b/src/security/core/tests/common/etc/default_governance.xml @@ -0,0 +1,62 @@ + + + + + + + + 0 + 230 + + + + + false + + + true + + + ENCRYPT + + + ENCRYPT + + + ENCRYPT + + + + + * + + + true + + + true + + + true + + + true + + + ENCRYPT + + + ENCRYPT + + + + + diff --git a/src/security/core/tests/common/etc/default_permissions.p7s b/src/security/core/tests/common/etc/default_permissions.p7s new file mode 100644 index 0000000..3417eac --- /dev/null +++ b/src/security/core/tests/common/etc/default_permissions.p7s @@ -0,0 +1,97 @@ +MIME-Version: 1.0 +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----024D6D35BD8D71C15552DF3E23F615BB" + +This is an S/MIME signed message + +------024D6D35BD8D71C15552DF3E23F615BB +Content-Type: text/plain + + + + + + emailAddress=alice@cycloneddssecurity.adlinktech.com,CN=Alice Example,O=Example Organization,OU=Organizational Unit Name,L=Locality Name,ST=OV,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + * + + + + + * + + + * + + + + DENY + + + + +------024D6D35BD8D71C15552DF3E23F615BB +Content-Type: application/x-pkcs7-signature; name="smime.p7s" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="smime.p7s" + +MIIHoQYJKoZIhvcNAQcCoIIHkjCCB44CAQExDzANBglghkgBZQMEAgEFADALBgkq +hkiG9w0BBwGgggRzMIIEbzCCA1egAwIBAgIUfoby6818hlJQ+41KUHiM6BZll/0w +DQYJKoZIhvcNAQELBQAwgcYxCzAJBgNVBAYTAk5MMQswCQYDVQQIDAJPVjEWMBQG +A1UEBwwNTG9jYWxpdHkgTmFtZTETMBEGA1UECwwKRXhhbXBsZSBPVTEgMB4GA1UE +CgwXRXhhbXBsZSBDQSBPcmdhbml6YXRpb24xHzAdBgNVBAMMFkV4YW1wbGUgUGVy +bWlzc2lvbnMgQ0ExOjA4BgkqhkiG9w0BCQEWK2F1dGhvcml0eUBjeWNsb25lZGRz +c2VjdXJpdHkuYWRsaW5rdGVjaC5jb20wHhcNMjAwMjI3MTM0ODA5WhcNMzAwMjI0 +MTM0ODA5WjCBxjELMAkGA1UEBhMCTkwxCzAJBgNVBAgMAk9WMRYwFAYDVQQHDA1M +b2NhbGl0eSBOYW1lMRMwEQYDVQQLDApFeGFtcGxlIE9VMSAwHgYDVQQKDBdFeGFt +cGxlIENBIE9yZ2FuaXphdGlvbjEfMB0GA1UEAwwWRXhhbXBsZSBQZXJtaXNzaW9u +cyBDQTE6MDgGCSqGSIb3DQEJARYrYXV0aG9yaXR5QGN5Y2xvbmVkZHNzZWN1cml0 +eS5hZGxpbmt0ZWNoLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANNWwyrW3J+TCyaZH77q+29GGqFsYP5rv9cpcL/TMDNccsPYY+1RA1K+zMRYo1LG +8VdJNtJlhxE+tmEbKxsVUTtoj8zbLVU4P4g0gIh6U7LMv5lUEZ3XYKWvYrbZTFMo +f2rXQYGXPO7pFnvbNAbnMiLmagRKxKJ91kq4utuMG3U6rkCA7i2S8cEISNO3gIpF +a0IZJ8yS8wDlKa/LGxL90BYasLsSA6tw/69OIiUUYqpMRD+xxyyTkMO37VjmdiFL +Ha/dxO8HH0t3Q0U0AgZP9uwYTgZpN+2UEFnjv3BDIydc3Wa0UaSdxLtHXMPvg3sR +uH9CTqr4Le7/3uTYehYKgd0CAwEAAaNTMFEwHQYDVR0OBBYEFFi4pK986ZSB0BLi +Mm8ivu6AUxYPMB8GA1UdIwQYMBaAFFi4pK986ZSB0BLiMm8ivu6AUxYPMA8GA1Ud +EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAHYLaJVWrLHg+62jC8yIz9db +ECIroX9Gb7Ll937HMum6Hj4wlImrifMVV3iORWBrBLvtTtn0Zno3mwfjLRQtkjOi +h71eJT+6//B7CT7noULJYVq8IRGErbKtmXULnxTajFApzO0v4hSu7rWj/Jfhil0T +X7QgKNpgKzjYodWz3oGGtchxvw3+v9wdIWD5Cj0bk/VMCQCaBV0anvyga7d4k8/z +PF7nW2Z9jNfKsVD1piFa+Yd4zN6XOPPKiFXfLD7ht9i2gG25iS+d95tKg1DfjnRD +7u0BJSOAPerxGtN/wf43qY1XzUoE2FBJ9QJGOA/02ffaUMOwSzICF/ShctH+Knkx +ggLyMIIC7gIBATCB3zCBxjELMAkGA1UEBhMCTkwxCzAJBgNVBAgMAk9WMRYwFAYD +VQQHDA1Mb2NhbGl0eSBOYW1lMRMwEQYDVQQLDApFeGFtcGxlIE9VMSAwHgYDVQQK +DBdFeGFtcGxlIENBIE9yZ2FuaXphdGlvbjEfMB0GA1UEAwwWRXhhbXBsZSBQZXJt +aXNzaW9ucyBDQTE6MDgGCSqGSIb3DQEJARYrYXV0aG9yaXR5QGN5Y2xvbmVkZHNz +ZWN1cml0eS5hZGxpbmt0ZWNoLmNvbQIUfoby6818hlJQ+41KUHiM6BZll/0wDQYJ +YIZIAWUDBAIBBQCggeQwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG +9w0BCQUxDxcNMjAwMjI3MTM1MDU2WjAvBgkqhkiG9w0BCQQxIgQgLVEvOwNNW9+x ++KKNuY51LjFOBF441MR89lv8fK5pDKMweQYJKoZIhvcNAQkPMWwwajALBglghkgB +ZQMEASowCwYJYIZIAWUDBAEWMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAOBggq +hkiG9w0DAgICAIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwIC +ASgwDQYJKoZIhvcNAQEBBQAEggEAxDaQlT3KGO3Z69Dgh1JAnkR8fEW+SK/pRls0 +du8ZemKaeLAgwwS9rbMh+6YJqsYWrp1LWjxNI3oJqTp1RvcRzJJXF48nkP+Oe1jY +2KX9wx5LthmrT/573EvZHkXsx7mBu3Ar2etm4iE3lqkblEiynTNfy4XmJBNdB+u8 +cTzzm6J9372FK3iu5Od9yVDV33Ys/OHBI8GYcrK9RBKovkctr2fK+RJHaVqrDy3y +oE03GAaFr8brL2g9WlWRsE3nuRvPXppsz32kUWvHLUfEpGbq1K/9C137JSgVHNX2 +atfV404PDWdFqL/JMSdc8RIJTzY6I2Bwrg8z1912DkYD5KPuOA== + +------024D6D35BD8D71C15552DF3E23F615BB-- + diff --git a/src/security/core/tests/common/etc/default_permissions.xml b/src/security/core/tests/common/etc/default_permissions.xml new file mode 100644 index 0000000..74e3c9f --- /dev/null +++ b/src/security/core/tests/common/etc/default_permissions.xml @@ -0,0 +1,39 @@ + + + + + emailAddress=alice@cycloneddssecurity.adlinktech.com,CN=Alice Example,O=Example Organization,OU=Organizational Unit Name,L=Locality Name,ST=OV,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + * + + + + + * + + + * + + + + DENY + + + diff --git a/src/security/core/tests/common/etc/default_permissions_ca.pem b/src/security/core/tests/common/etc/default_permissions_ca.pem new file mode 100644 index 0000000..377a1e5 --- /dev/null +++ b/src/security/core/tests/common/etc/default_permissions_ca.pem @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEbzCCA1egAwIBAgIUfoby6818hlJQ+41KUHiM6BZll/0wDQYJKoZIhvcNAQEL +BQAwgcYxCzAJBgNVBAYTAk5MMQswCQYDVQQIDAJPVjEWMBQGA1UEBwwNTG9jYWxp +dHkgTmFtZTETMBEGA1UECwwKRXhhbXBsZSBPVTEgMB4GA1UECgwXRXhhbXBsZSBD +QSBPcmdhbml6YXRpb24xHzAdBgNVBAMMFkV4YW1wbGUgUGVybWlzc2lvbnMgQ0Ex +OjA4BgkqhkiG9w0BCQEWK2F1dGhvcml0eUBjeWNsb25lZGRzc2VjdXJpdHkuYWRs +aW5rdGVjaC5jb20wHhcNMjAwMjI3MTM0ODA5WhcNMzAwMjI0MTM0ODA5WjCBxjEL +MAkGA1UEBhMCTkwxCzAJBgNVBAgMAk9WMRYwFAYDVQQHDA1Mb2NhbGl0eSBOYW1l +MRMwEQYDVQQLDApFeGFtcGxlIE9VMSAwHgYDVQQKDBdFeGFtcGxlIENBIE9yZ2Fu +aXphdGlvbjEfMB0GA1UEAwwWRXhhbXBsZSBQZXJtaXNzaW9ucyBDQTE6MDgGCSqG +SIb3DQEJARYrYXV0aG9yaXR5QGN5Y2xvbmVkZHNzZWN1cml0eS5hZGxpbmt0ZWNo +LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNWwyrW3J+TCyaZ +H77q+29GGqFsYP5rv9cpcL/TMDNccsPYY+1RA1K+zMRYo1LG8VdJNtJlhxE+tmEb +KxsVUTtoj8zbLVU4P4g0gIh6U7LMv5lUEZ3XYKWvYrbZTFMof2rXQYGXPO7pFnvb +NAbnMiLmagRKxKJ91kq4utuMG3U6rkCA7i2S8cEISNO3gIpFa0IZJ8yS8wDlKa/L +GxL90BYasLsSA6tw/69OIiUUYqpMRD+xxyyTkMO37VjmdiFLHa/dxO8HH0t3Q0U0 +AgZP9uwYTgZpN+2UEFnjv3BDIydc3Wa0UaSdxLtHXMPvg3sRuH9CTqr4Le7/3uTY +ehYKgd0CAwEAAaNTMFEwHQYDVR0OBBYEFFi4pK986ZSB0BLiMm8ivu6AUxYPMB8G +A1UdIwQYMBaAFFi4pK986ZSB0BLiMm8ivu6AUxYPMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQELBQADggEBAHYLaJVWrLHg+62jC8yIz9dbECIroX9Gb7Ll937H +Mum6Hj4wlImrifMVV3iORWBrBLvtTtn0Zno3mwfjLRQtkjOih71eJT+6//B7CT7n +oULJYVq8IRGErbKtmXULnxTajFApzO0v4hSu7rWj/Jfhil0TX7QgKNpgKzjYodWz +3oGGtchxvw3+v9wdIWD5Cj0bk/VMCQCaBV0anvyga7d4k8/zPF7nW2Z9jNfKsVD1 +piFa+Yd4zN6XOPPKiFXfLD7ht9i2gG25iS+d95tKg1DfjnRD7u0BJSOAPerxGtN/ +wf43qY1XzUoE2FBJ9QJGOA/02ffaUMOwSzICF/ShctH+Knk= +-----END CERTIFICATE----- diff --git a/src/security/core/tests/common/etc/default_permissions_ca_key.pem b/src/security/core/tests/common/etc/default_permissions_ca_key.pem new file mode 100644 index 0000000..e68bae1 --- /dev/null +++ b/src/security/core/tests/common/etc/default_permissions_ca_key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA01bDKtbcn5MLJpkfvur7b0YaoWxg/mu/1ylwv9MwM1xyw9hj +7VEDUr7MxFijUsbxV0k20mWHET62YRsrGxVRO2iPzNstVTg/iDSAiHpTssy/mVQR +nddgpa9ittlMUyh/atdBgZc87ukWe9s0BucyIuZqBErEon3WSri624wbdTquQIDu +LZLxwQhI07eAikVrQhknzJLzAOUpr8sbEv3QFhqwuxIDq3D/r04iJRRiqkxEP7HH +LJOQw7ftWOZ2IUsdr93E7wcfS3dDRTQCBk/27BhOBmk37ZQQWeO/cEMjJ1zdZrRR +pJ3Eu0dcw++DexG4f0JOqvgt7v/e5Nh6FgqB3QIDAQABAoIBABFHMKGZ+2OYc/rt +3eiP8YqBYr/7ylpCmOaQXsVwEKrCTiew00qdqvXi337V+FRWK3kFZVQCNO61/9ck +j3uhXIjM3aTT7nrfJGKQWEnQJnOhxbBVbTNIXoBtPFbSoSjTUMd9Xb+oi7TEna/2 +leRSloi/6b78FeNrAlANlklIxR3qTjRSxjGYVfukCWsKq3uFfWM4Wp9N1B1gsyRo +/SH2jOu0XTLNdajggtBKcFoqxVIiaetERKVRRid7pW0zwuYS5Zwv5Wtl3XMbUuAn +VGesMeCKAGpwkLjmvXKBE5setnd7cWBKdVKddYDkzbDvU7X6QEHFnac6m6OQ2P62 +QfkO94ECgYEA70tV55AreDnPQEpf698ZjA8pYvF90GfGx/Y4oYWU/s0IlD6Pfbsr +qkRu+1I+SUNZWARhirXmJzuOmJYUQRteCEq+6RPJzn5Jl9MtipOBAjI0h589dbAB +8m/BRk+bEZKCXLgVa0TyZ/gd/wDBxB+qd+bPep8nAl4krMWK9W1+DLECgYEA4hfP +EwUPMwHrGlq0oRUA08ssQ8XxVCKWeS3cLAJjO6EdJyIUm/8S/UZPBPeSkGyZeld+ +fY7z9ZV0HA338p5BYYDCqgJC6b5Ud5UV0yLkq01v6b0H3nSjTPcbA61l9laN0vhm +QJ/xTiAHgsGBbOx2VtwDoE8T1AbAaamcapqNYu0CgYAXCiPdRc5JpxdDU2Xk6fgl +uhf8BNBeTn+fJR/SvW/ZEJiw3U0nh+vuWuRsokCJAUkK5nEVz+m3AU77dgfBNQda +uQeknVki3pnrWlPaMdWMBpV0MWrTd/zYANaVFHkTug1/K+I0D9FfHU6WDNabMYlS +PhDf947j9XiGggadFsu6IQKBgQC6dgpIVFbZqU5cuMvZQToicaA68Kd7zN6uZ7z5 +6qouRkyFtpyqnq3pha+rmAYe6AGXnUrrgBcAxdYxQO/o/s1K/WcN0LmgjmCZErIi +I9fU0xNmAIjZ1PXMhsqXuMyrYWyrvkKOL5pR5SZsluwHieh68A5pim3+4eaT/dbL +MFVEbQKBgQDfkeApSfKATXJpYIV/tiGjmRkkYoZ6NVar92npjlb72jaA4V0gHmuD +9ttypXOJPB/5zMa5uL6drp3CLv/GcWekUiUUXuyKQpcxZWqxf/leh9gTgGDAH/k4 +4+zX4HLEzTmoOc0cqzi4w6pTIj29BOV5QpnnyUGyvj8NGNSdFvZFSQ== +-----END RSA PRIVATE KEY----- diff --git a/src/security/core/tests/common/handshake_test_utils.c b/src/security/core/tests/common/handshake_test_utils.c new file mode 100644 index 0000000..5385fe5 --- /dev/null +++ b/src/security/core/tests/common/handshake_test_utils.c @@ -0,0 +1,232 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include + +#include "CUnit/Test.h" +#include "dds/dds.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/heap.h" +#include "dds/security/dds_security_api.h" +#include "authentication_wrapper.h" +#include "handshake_test_utils.h" + +#define TIMEOUT DDS_SECS(2) + +struct Identity localIdentityList[MAX_LOCAL_IDENTITIES]; +int numLocal = 0; + +struct Identity remoteIdentityList[MAX_REMOTE_IDENTITIES]; +int numRemote = 0; + +struct Handshake handshakeList[MAX_HANDSHAKES]; +int numHandshake = 0; + +static void add_local_identity(DDS_Security_IdentityHandle handle, DDS_Security_GUID_t *guid) +{ + printf("add local identity %"PRId64"\n", handle); + localIdentityList[numLocal].handle = handle; + memcpy(&localIdentityList[numLocal].guid, guid, sizeof(DDS_Security_GUID_t)); + numLocal++; +} + +static int find_local_identity(DDS_Security_IdentityHandle handle) +{ + for (int i = 0; i < (int)numLocal; i++) + { + if (localIdentityList[i].handle == handle) + return i; + } + return -1; +} + +static int find_remote_identity(DDS_Security_IdentityHandle handle) +{ + for (int i = 0; i < numRemote; i++) + { + if (remoteIdentityList[i].handle == handle) + return i; + } + return -1; +} + +static void add_remote_identity(DDS_Security_IdentityHandle handle, DDS_Security_GUID_t *guid) +{ + if (find_remote_identity(handle) < 0) + { + printf("add remote identity %"PRId64"\n", handle); + remoteIdentityList[numRemote].handle = handle; + memcpy(&remoteIdentityList[numRemote].guid, guid, sizeof(DDS_Security_GUID_t)); + numRemote++; + } +} + +static void clear_stores(void) +{ + numLocal = 0; + numRemote = 0; + numHandshake = 0; +} + +static void add_handshake(DDS_Security_HandshakeHandle handle, int isRequest, DDS_Security_IdentityHandle lHandle, DDS_Security_IdentityHandle rHandle, DDS_Security_ValidationResult_t result) +{ + printf("add handshake %"PRId64"\n", handle); + handshakeList[numHandshake].handle = handle; + handshakeList[numHandshake].isRequest = isRequest; + handshakeList[numHandshake].handshakeResult = result; + handshakeList[numHandshake].lidx = find_local_identity(lHandle); + handshakeList[numHandshake].ridx = find_remote_identity(rHandle); + handshakeList[numHandshake].finalResult = DDS_SECURITY_VALIDATION_FAILED; + numHandshake++; +} + +static int find_handshake(DDS_Security_HandshakeHandle handle) +{ + for (int i = 0; i < numHandshake; i++) + { + if (handshakeList[i].handle == handle) + return i; + } + return -1; +} + +static char * get_validation_result_str(DDS_Security_ValidationResult_t result) +{ + switch (result) + { + case DDS_SECURITY_VALIDATION_OK: + return "ok"; + case DDS_SECURITY_VALIDATION_PENDING_RETRY: + return "pending retry"; + case DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_REQUEST: + return "handshake request"; + case DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE: + return "handshake message"; + case DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE: + return "ok final"; + default: + case DDS_SECURITY_VALIDATION_FAILED: + return "failed"; + } +} + +static bool handle_process_message(dds_domainid_t domain_id, DDS_Security_IdentityHandle handshake) +{ + struct message *msg; + bool result = false; + if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_PROCESS_HANDSHAKE, 0, 0, handshake, TIMEOUT))) + { + int idx; + if ((idx = find_handshake(msg->hsHandle)) >= 0) + { + printf("set handshake %"PRId64" final result to '%s'\n", msg->hsHandle, get_validation_result_str(msg->result)); + handshakeList[idx].finalResult = msg->result; + result = true; + } + test_authentication_plugin_release_msg(msg); + } + return result; +} + +static bool handle_begin_handshake_request(dds_domainid_t domain_id, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid, char ** err_msg) +{ + struct message *msg; + bool result = false; + printf("handle begin handshake request %"PRId64"<->%"PRId64"\n", lid, rid); + if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REQUEST, lid, rid, 0, TIMEOUT))) + { + add_handshake(msg->hsHandle, 1, msg->lidHandle, msg->ridHandle, msg->result); + if (msg->result == DDS_SECURITY_VALIDATION_OK) + result = handle_process_message(domain_id, msg->hsHandle); + else if (msg->result == DDS_SECURITY_VALIDATION_FAILED && err_msg) + *err_msg = ddsrt_strdup (msg->err_msg); + test_authentication_plugin_release_msg(msg); + } + return result; +} + +static bool handle_begin_handshake_reply(dds_domainid_t domain_id, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid, char ** err_msg) +{ + struct message *msg; + bool result = false; + printf("handle begin handshake reply %"PRId64"<->%"PRId64"\n", lid, rid); + if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REPLY, lid, rid, 0, TIMEOUT))) + { + add_handshake(msg->hsHandle, 0, msg->lidHandle, msg->ridHandle, msg->result); + if (msg->result == DDS_SECURITY_VALIDATION_OK) + result = handle_process_message(domain_id, msg->hsHandle); + else if (msg->result == DDS_SECURITY_VALIDATION_FAILED && err_msg) + *err_msg = ddsrt_strdup (msg->err_msg); + test_authentication_plugin_release_msg(msg); + } + return result; +} + +static bool handle_validate_remote_identity(dds_domainid_t domain_id, DDS_Security_IdentityHandle lid, int count, bool * is_hs_requester, char ** err_msg_req, char ** err_msg_reply) +{ + bool result = true; + struct message *msg; + assert(is_hs_requester); + while (count-- > 0 && result && (msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_VALIDATE_REMOTE_IDENTITY, lid, 0, 0, TIMEOUT))) + { + add_remote_identity(msg->ridHandle, &msg->rguid); + if (msg->result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_REQUEST) + { + result = handle_begin_handshake_request(domain_id, lid, msg->ridHandle, err_msg_req); + *is_hs_requester = true; + } + else if (msg->result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE) + { + result = handle_begin_handshake_reply(domain_id, lid, msg->ridHandle, err_msg_reply); + *is_hs_requester = false; + } + else + result = false; + + test_authentication_plugin_release_msg(msg); + } + return result; +} + +void validate_handshake(dds_domainid_t domain_id, bool exp_req_fail, const char * exp_req_msg, bool exp_reply_fail, const char * exp_reply_msg) +{ + printf("validate handshake for domain %d\n", domain_id); + clear_stores(); + + struct message *msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_VALIDATE_LOCAL_IDENTITY, 0, 0, 0, TIMEOUT); + CU_ASSERT_FATAL (msg != NULL); + add_local_identity (msg->lidHandle, &msg->lguid); + test_authentication_plugin_release_msg (msg); + bool is_requester = false; + char * err_msg_req = NULL, *err_msg_reply = NULL; + bool ret = handle_validate_remote_identity (domain_id, localIdentityList[0].handle, 1, &is_requester, &err_msg_req, &err_msg_reply); + CU_ASSERT_FATAL ((is_requester && ret != exp_req_fail) || (!is_requester && ret != exp_reply_fail)); + if (ret) + { + DDS_Security_ValidationResult_t exp_result = is_requester ? DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE : DDS_SECURITY_VALIDATION_OK; + CU_ASSERT_EQUAL_FATAL (handshakeList[0].finalResult, exp_result); + } + else if (is_requester && exp_req_msg) + { + CU_ASSERT_FATAL (err_msg_req && strstr(err_msg_req, exp_req_msg) != NULL); + } + else if (!is_requester && exp_reply_msg) + { + CU_ASSERT_FATAL (err_msg_reply && strstr(err_msg_reply, exp_reply_msg) != NULL); + } + if (err_msg_req) + ddsrt_free (err_msg_req); + if (err_msg_reply) + ddsrt_free (err_msg_reply); + printf ("finished validate handshake for domain %d\n\n", domain_id); +} + diff --git a/src/security/core/tests/common/handshake_test_utils.h b/src/security/core/tests/common/handshake_test_utils.h new file mode 100644 index 0000000..9ca8afb --- /dev/null +++ b/src/security/core/tests/common/handshake_test_utils.h @@ -0,0 +1,48 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef SECURITY_CORE_HANDSHAKE_TEST_UTILS_H_ +#define SECURITY_CORE_HANDSHAKE_TEST_UTILS_H_ + +#include "dds/dds.h" +#include "dds/ddsrt/sync.h" + +#include "dds/security/dds_security_api.h" + +#define MAX_LOCAL_IDENTITIES 8 +#define MAX_REMOTE_IDENTITIES 8 +#define MAX_HANDSHAKES 32 +#define TIMEOUT DDS_SECS(2) + +union guid { + DDS_Security_GUID_t g; + unsigned u[4]; +}; + +struct Identity +{ + DDS_Security_IdentityHandle handle; + union guid guid; +}; + +struct Handshake +{ + DDS_Security_HandshakeHandle handle; + int isRequest; + int lidx; + int ridx; + DDS_Security_ValidationResult_t handshakeResult; + DDS_Security_ValidationResult_t finalResult; +}; + +void validate_handshake(dds_domainid_t domain_id, bool exp_req_fail, const char * exp_req_msg, bool exp_reply_fail, const char * exp_reply_msg); + +#endif /* SECURITY_CORE_HANDSHAKE_TEST_UTILS_H_ */ diff --git a/src/security/core/tests/common/plugin_wrapper_msg_q.c b/src/security/core/tests/common/plugin_wrapper_msg_q.c new file mode 100644 index 0000000..3ecad82 --- /dev/null +++ b/src/security/core/tests/common/plugin_wrapper_msg_q.c @@ -0,0 +1,134 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include "dds/dds.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsi/ddsi_domaingv.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/core/dds_security_utils.h" +#include "plugin_wrapper_msg_q.h" + +void insert_message(struct message_queue *queue, struct message *msg) +{ + ddsrt_mutex_lock(&queue->lock); + if (!queue->head) + queue->head = msg; + else + queue->tail->next = msg; + queue->tail = msg; + + ddsrt_cond_signal(&queue->cond); + ddsrt_mutex_unlock(&queue->lock); +} + +void add_message(struct message_queue *queue, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, + const DDS_Security_GUID_t *lguid, const DDS_Security_GUID_t *rguid, DDS_Security_ValidationResult_t result, const char * err_msg, + const DDS_Security_DataHolder *token, void *instance) +{ + struct message *msg = ddsrt_malloc(sizeof(*msg)); + memset(msg, 0, sizeof(*msg)); + msg->kind = kind; + msg->lidHandle = lidHandle; + msg->ridHandle = ridHandle; + msg->hsHandle = hsHandle; + msg->result = result; + msg->err_msg = ddsrt_strdup (err_msg ? err_msg : ""); + if (lguid) + memcpy(&msg->lguid, lguid, sizeof(msg->lguid)); + if (rguid) + memcpy(&msg->rguid, rguid, sizeof(msg->rguid)); + if (token) + DDS_Security_DataHolder_copy(&msg->token, token); + msg->instance = instance; + + insert_message(queue, msg); +} + +void delete_message(struct message *msg) +{ + if (msg) + { + DDS_Security_DataHolder_deinit(&msg->token); + ddsrt_free(msg->err_msg); + ddsrt_free(msg); + } +} + +void init_message_queue(struct message_queue *queue) +{ + queue->head = NULL; + queue->tail = NULL; + ddsrt_mutex_init(&queue->lock); + ddsrt_cond_init(&queue->cond); +} + +void deinit_message_queue(struct message_queue *queue) +{ + struct message *msg = queue->head; + while (msg) + { + queue->head = msg->next; + delete_message(msg); + msg = queue->head; + } + ddsrt_cond_destroy(&queue->cond); + ddsrt_mutex_destroy(&queue->lock); +} + +int message_matched(struct message *msg, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle) +{ + return msg->kind == kind && + (!lidHandle || msg->lidHandle == lidHandle) && + (!ridHandle || msg->ridHandle == ridHandle) && + (!hsHandle || msg->hsHandle == hsHandle); +} + +struct message * take_message(struct message_queue *queue, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, dds_duration_t timeout) +{ + struct message *msg = NULL, *cur, *prev; + int r = 1; + ddsrt_mutex_lock(&queue->lock); + do + { + cur = queue->head; + prev = NULL; + while (cur && !msg) + { + if (message_matched(cur, kind, lidHandle, ridHandle, hsHandle)) + { + msg = cur; + if (prev) + prev->next = msg->next; + else + queue->head = msg->next; + if (queue->tail == msg) + queue->tail = prev; + } + else + { + prev = cur; + cur = cur->next; + } + } + if (!msg) + { + if (!ddsrt_cond_waitfor(&queue->cond, &queue->lock, timeout)) + r = 0; + } + } while (r && !msg); + + ddsrt_mutex_unlock(&queue->lock); + return msg; +} diff --git a/src/security/core/tests/common/plugin_wrapper_msg_q.h b/src/security/core/tests/common/plugin_wrapper_msg_q.h new file mode 100644 index 0000000..32ec557 --- /dev/null +++ b/src/security/core/tests/common/plugin_wrapper_msg_q.h @@ -0,0 +1,62 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef SECURITY_CORE_PLUGIN_WRAPPER_MSG_Q_H_ +#define SECURITY_CORE_PLUGIN_WRAPPER_MSG_Q_H_ + +#include "dds/dds.h" +#include "dds/ddsrt/sync.h" + +#include "dds/security/dds_security_api.h" + +typedef enum { + MESSAGE_KIND_VALIDATE_LOCAL_IDENTITY, + MESSAGE_KIND_VALIDATE_REMOTE_IDENTITY, + MESSAGE_KIND_BEGIN_HANDSHAKE_REQUEST, + MESSAGE_KIND_BEGIN_HANDSHAKE_REPLY, + MESSAGE_KIND_PROCESS_HANDSHAKE +} message_kind_t; + +struct message { + message_kind_t kind; + DDS_Security_IdentityHandle lidHandle; + DDS_Security_IdentityHandle ridHandle; + DDS_Security_IdentityHandle hsHandle; + DDS_Security_GUID_t lguid; + DDS_Security_GUID_t rguid; + DDS_Security_ValidationResult_t result; + char * err_msg; + DDS_Security_DataHolder token; + void *instance; + struct message *next; +}; + +struct message_queue { + ddsrt_mutex_t lock; + ddsrt_cond_t cond; + struct message *head; + struct message *tail; +}; + +struct dds_security_authentication_impl; + +void insert_message(struct message_queue *queue, struct message *msg); +void add_message(struct message_queue *queue, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, + const DDS_Security_GUID_t *lguid, const DDS_Security_GUID_t *rguid, DDS_Security_ValidationResult_t result, const char * err_msg, + const DDS_Security_DataHolder *token, void *instance); +void delete_message(struct message *msg); +void init_message_queue(struct message_queue *queue); +void deinit_message_queue(struct message_queue *queue); +int message_matched(struct message *msg, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle); +struct message * take_message(struct message_queue *queue, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, dds_duration_t timeout); + + +#endif /* SECURITY_CORE_PLUGIN_WRAPPER_MSG_Q_H_ */ diff --git a/src/security/core/tests/common/security_config_test_utils.c b/src/security/core/tests/common/security_config_test_utils.c new file mode 100644 index 0000000..c67a4d8 --- /dev/null +++ b/src/security/core/tests/common/security_config_test_utils.c @@ -0,0 +1,156 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CUnit/Test.h" +#include "dds/dds.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/expand_vars.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/string.h" +#include "common/config_env.h" +#include "security_config_test_utils.h" + +static const char *governance_xml = + "" + "" + " " + " " + " " + " " + " 0" + " 230" + " " + " " + " ${ALLOW_UNAUTH_PP:-false}" + " ${ENABLE_JOIN_AC:-false}" + " ${DISCOVERY_PROTECTION_KIND:-NONE}" + " ${LIVELINESS_PROTECTION_KIND:-NONE}" + " ${RTPS_PROTECTION_KIND:-NONE}" + " " + " " + " *" + " ${ENABLE_DISC_PROTECTION:-false}" + " ${ENABLE_LIVELINESS_PROTECTION:-false}" + " ${ENABLE_READ_AC:-false}" + " ${ENABLE_WRITE_AC:-false}" + " ${METADATA_PROTECTION_KIND:-NONE}" + " ${DATA_PROTECTION_KIND:-NONE}" + " " + " " + " " + " " + ""; + +const char * expand_lookup_vars(const char *name, void * data) +{ + const struct kvp *vars = (struct kvp *)data; + for (uint32_t i = 0; vars[i].key != NULL; i++) + { + if (!strcmp(vars[i].key, name)) + return vars[i].value; + } + return NULL; +} + +const char * expand_lookup_vars_env(const char *name, void * data) +{ + const char *env; + if ((env = expand_lookup_vars (name, data))) + return env; + return ((ddsrt_getenv(name, &env)) == DDS_RETCODE_OK) ? env : NULL; +} + +static char * smime_sign(char * ca_cert_path, char * ca_priv_key_path, const char * data) +{ + // Read CA certificate + BIO *ca_cert_bio = BIO_new (BIO_s_file ()); + if (BIO_read_filename (ca_cert_bio, ca_cert_path) <= 0) + { + printf ("Error reading CA certificate file %s\n", ca_cert_path); + CU_ASSERT_FATAL (false); + } + + // Read CA private key + BIO *ca_priv_key_bio = BIO_new (BIO_s_file ()); + if (BIO_read_filename (ca_priv_key_bio, ca_priv_key_path) <= 0) + { + printf ("Error reading CA private key file %s\n", ca_priv_key_path); + CU_ASSERT_FATAL (false); + } + + // Create Openssl certificate and private key from the BIO's + X509 *ca_cert = PEM_read_bio_X509_AUX (ca_cert_bio, NULL, NULL, NULL); + EVP_PKEY* ca_priv_key = PEM_read_bio_PrivateKey (ca_priv_key_bio, NULL, 0, NULL); + + // Read the data + BIO *data_bio = BIO_new (BIO_s_mem ()); + if (BIO_puts (data_bio, data) <= 0) { + printf ("Error getting configuration data for signing\n"); + CU_ASSERT_FATAL (false); + } + + // Create the data signing object + PKCS7 *signed_data = PKCS7_sign (ca_cert, ca_priv_key, NULL, data_bio, PKCS7_DETACHED | PKCS7_STREAM | PKCS7_TEXT); + if (!signed_data) { + printf ("Error signing configuration data\n"); + CU_ASSERT_FATAL (false); + } + + // Create BIO for writing output + BIO *output_bio = BIO_new (BIO_s_mem ()); + if (!SMIME_write_PKCS7 (output_bio, signed_data, data_bio, PKCS7_DETACHED | PKCS7_STREAM | PKCS7_TEXT)) { + printf ("Error writing signed XML configuration\n"); + CU_ASSERT_FATAL (false); + } + + // Get string + char *output_tmp = NULL; + size_t output_sz = (size_t)BIO_get_mem_data (output_bio, &output_tmp); + char * output = ddsrt_malloc(output_sz + 1); + memcpy(output, output_tmp, output_sz); + output[output_sz] = 0; + + BIO_free (output_bio); + PKCS7_free (signed_data); + BIO_free (data_bio); + EVP_PKEY_free (ca_priv_key); + X509_free (ca_cert); + BIO_free (ca_priv_key_bio); + BIO_free (ca_cert_bio); + + return output; +} + +static char *get_signed_governance_data(const char *gov_xml) +{ + return smime_sign ( + COMMON_ETC_PATH("default_permissions_ca.pem"), + COMMON_ETC_PATH("default_permissions_ca_key.pem"), + gov_xml); +} + +char * get_governance_config(struct kvp *config_vars) +{ + char * config = ddsrt_expand_vars(governance_xml, &expand_lookup_vars, config_vars); + char * config_signed = get_signed_governance_data(config); + ddsrt_free (config); + return config_signed; +} diff --git a/src/security/core/tests/common/security_config_test_utils.h b/src/security/core/tests/common/security_config_test_utils.h new file mode 100644 index 0000000..d2c8635 --- /dev/null +++ b/src/security/core/tests/common/security_config_test_utils.h @@ -0,0 +1,28 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef SECURITY_CORE_TEST_SECURITY_CONFIG_TEST_UTILS_H_ +#define SECURITY_CORE_TEST_SECURITY_CONFIG_TEST_UTILS_H_ + +#include +#include "dds/ddsrt/environ.h" + +struct kvp { + const char *key; + const char *value; +}; + +const char * expand_lookup_vars (const char *name, void * data); +const char * expand_lookup_vars_env (const char *name, void * data); + +char * get_governance_config (struct kvp *config_vars); + +#endif /* SECURITY_CORE_TEST_SECURITY_CONFIG_TEST_UTILS_H_ */ diff --git a/src/security/core/tests/common/test_identity.h b/src/security/core/tests/common/test_identity.h new file mode 100644 index 0000000..2fbcd3b --- /dev/null +++ b/src/security/core/tests/common/test_identity.h @@ -0,0 +1,184 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#ifndef PLUGIN_SECURITY_CORE_TEST_IDENTITY_H_ +#define PLUGIN_SECURITY_CORE_TEST_IDENTITY_H_ + +#define TEST_IDENTITY_CERTIFICATE_DUMMY "testtext_IdentityCertificate_testtext" +#define TEST_IDENTITY_PRIVATE_KEY_DUMMY "testtext_PrivateKey_testtext" +#define TEST_IDENTITY_CA_CERTIFICATE_DUMMY "testtext_IdentityCA_testtext" + +#define TEST_IDENTITY_CERTIFICATE "data:,-----BEGIN CERTIFICATE-----\n\ +MIIEDTCCAvUCFHZ4yXyk/9yeMxgHs6Ib0bLKhXYuMA0GCSqGSIb3DQEBCwUAMIHA\n\ +MQswCQYDVQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2FsaXR5IE5h\n\ +bWUxEzARBgNVBAsMCkV4YW1wbGUgT1UxIzAhBgNVBAoMGkV4YW1wbGUgSUQgQ0Eg\n\ +T3JnYW5pemF0aW9uMRYwFAYDVQQDDA1FeGFtcGxlIElEIENBMTowOAYJKoZIhvcN\n\ +AQkBFithdXRob3JpdHlAY3ljbG9uZWRkc3NlY3VyaXR5LmFkbGlua3RlY2guY29t\n\ +MB4XDTIwMDIyNzE5MjQwMVoXDTMwMDIyNDE5MjQwMVowgcQxCzAJBgNVBAYTAk5M\n\ +MQswCQYDVQQIDAJPVjEWMBQGA1UEBwwNTG9jYWxpdHkgTmFtZTEhMB8GA1UECwwY\n\ +T3JnYW5pemF0aW9uYWwgVW5pdCBOYW1lMR0wGwYDVQQKDBRFeGFtcGxlIE9yZ2Fu\n\ +aXphdGlvbjEWMBQGA1UEAwwNQWxpY2UgRXhhbXBsZTE2MDQGCSqGSIb3DQEJARYn\n\ +YWxpY2VAY3ljbG9uZWRkc3NlY3VyaXR5LmFkbGlua3RlY2guY29tMIIBIjANBgkq\n\ +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5mEhLZIP2ko1bRJyJCwbnvhIpXFv6GOh\n\ +nvuS5v8tsTju40O62NNQmKT/my1QVKiUu7OoWZtLNBebgxgJ851eQ4TBRXy/f2jG\n\ +kLPYM22dohLTblVCpGutn+Itw3QRM3nkne7Sk8O6FP6NH6Y+7gkjxy5kI3GvhuIC\n\ +uBIzAV4dHK+hPlCn/Z+W33W71/ZAmnmI+2GaWiu5tjAQyFcmqWbi0BD7TWqBqidZ\n\ +2n7LTImUtp8NrYLfhzvgNLr9BZe7uf+T3mgdwcHtfi98GA94Lo6lqGeygiwig746\n\ +Y5uW4c6whsbd6riJ8FG1l8O86Ump4bSKChxjeoTLj4M4KX615kYa4QIDAQABMA0G\n\ +CSqGSIb3DQEBCwUAA4IBAQAM2g7v3FaA+d1zDkvDF5emCRL+R9H8pgimEOENrZTV\n\ +iK/kl8Hm7xkO7/LZ3y/kXpQpth8FtFS6LsZBAXPYabfADeDFVImnOD6UbWewwHQR\n\ +01gxkmYL/1nco/g3AsX/Ledh2ihwClGp+d6vNm5xF+Gw8Ux0YvH/aHy4RKg7mE/S\n\ +nonfHWRlT2tw1OtohTVhmBn00Jvj0IzSAiNvpmZHVRLYL9JRb5awYSX5XGetpoFM\n\ +VwzWIaZ06idvCtPKTfP71jJypV3+I2g5PNqranbuMv5nNAKZq1QlSB07f2Z1VIu6\n\ +6jeSZSADfm73qnE2Kj1PiZkPn0Wu+K24GXCvdILATcUS\n\ +-----END CERTIFICATE-----" + +#define TEST_IDENTITY_PRIVATE_KEY "data:,-----BEGIN RSA PRIVATE KEY-----\n\ +MIIEpQIBAAKCAQEA5mEhLZIP2ko1bRJyJCwbnvhIpXFv6GOhnvuS5v8tsTju40O6\n\ +2NNQmKT/my1QVKiUu7OoWZtLNBebgxgJ851eQ4TBRXy/f2jGkLPYM22dohLTblVC\n\ +pGutn+Itw3QRM3nkne7Sk8O6FP6NH6Y+7gkjxy5kI3GvhuICuBIzAV4dHK+hPlCn\n\ +/Z+W33W71/ZAmnmI+2GaWiu5tjAQyFcmqWbi0BD7TWqBqidZ2n7LTImUtp8NrYLf\n\ +hzvgNLr9BZe7uf+T3mgdwcHtfi98GA94Lo6lqGeygiwig746Y5uW4c6whsbd6riJ\n\ +8FG1l8O86Ump4bSKChxjeoTLj4M4KX615kYa4QIDAQABAoIBAAtNMoJ4ytxLjaln\n\ +IUBTBZvb1DyBfxroYFJbRw6b8BLklxuBBBaE70w9s+hZ5bnxdzJqEtUqgBrzGYbp\n\ +0/smeixXw99zyjUm367Tk8SaGQSNZd/gwN8uBRt1zgbrl7htv2BcCeqDzIohHq0x\n\ +y56DxkSMKw9uEU1NoxKCmgv0IPt6LlvjCwFhDv8iLu4lvu61F+ovVYIM6UXJJH0G\n\ +bHcJ1XnFBj5jCJFAWZRq7KxBgc4K3DlG+J7JcGEz89ZnZfGwcIiLqJ4rbU7E0ZE8\n\ +LslIHOwodtMDReIRWl6wEYmvd3mQizTXj2EWlRywQ/P3yFlxuHsGxPtRxdWoyXDc\n\ +Ii7GZK0CgYEA9KA+uEAMA5jZK0h1EMFoTiOIRe0x8CjlrHg4l0zU0ElcMeUXwoci\n\ +XqM0sjARiNgqkcMaONCb5bKgyxncWyWcamUxgp+bi2FUQIlBKHb56TCioPP0zzc6\n\ +yCiQ2cA8QW9PjL0WScJz3bCzeXrQceGZenDpPyphYE7SIUaRAOlMTMMCgYEA8RdP\n\ +QfYbOrcwgZB8ZycFE7lpZibe7Wh4UI1b/ipNZKcncr2pOZR+gVNv6eDQbV4z9xZY\n\ +5K6oU3rUcFHf0ZAi9xIpNzcq9q4+qOGO2OCEZX5tewXjKw9rwyDPUbv3yToFyZ9w\n\ +YwEKLfUgnYzpd5qn2NXa/pAZIoTh5ILF+EezD4sCgYEAr2lg0BoNA19NCn5wg01M\n\ +kAtmok3Nq1qIJr4mRkfvqlOQaq7N9M2V1arOFJ/nUus+yzrNyMO9pl4Kctjea/Vy\n\ +TdC2SeZNUQq/sW86a9u0pIQdebC1cQk3e2OrSplQG9PHhTHpk4Z+Mw+MAqYQZjjR\n\ +Jz1j48lt/fNHNlk1jSO9dKUCgYEAuYkJuqZuMBJ4Zs1Nn4ic1KAUp8N0Pdnu9XbD\n\ +++aMJtCogBnLWH+Zl2chsigL3o7niNiO0nZDHfNh94pap4i4D9HPHCn9i1du60Ki\n\ +Tu8BlKXmFQ3j0+iLMuBWC/2O5DId8BseP2K2dcW2MukVZrEDSNDTNqKoZTNEMDof\n\ +pkFvYJ8CgYEA6du9DFFZzIp5tuSIfVqCq5oxiNrRGJ/EpJEneBexrX56cC90sqLM\n\ +ecxDkgEVC592b004K1mjak3w6O0jYozQM1uvve38nZyMgtbMo3ORCtAO6Xszj8Oj\n\ +yNw1+km1Zy6EWdFEMciEFlbRwWVmDfE/um9LZsSWbmuWAOTww9GBDhc=\n\ +-----END RSA PRIVATE KEY-----" + + +#define TEST_IDENTITY_CA_CERTIFICATE "data:,-----BEGIN CERTIFICATE-----\n\ +MIIEYzCCA0ugAwIBAgIUOp5yaGGuh0vaQTZHVPkX5jHoc/4wDQYJKoZIhvcNAQEL\n\ +BQAwgcAxCzAJBgNVBAYTAk5MMQswCQYDVQQIDAJPVjEWMBQGA1UEBwwNTG9jYWxp\n\ +dHkgTmFtZTETMBEGA1UECwwKRXhhbXBsZSBPVTEjMCEGA1UECgwaRXhhbXBsZSBJ\n\ +RCBDQSBPcmdhbml6YXRpb24xFjAUBgNVBAMMDUV4YW1wbGUgSUQgQ0ExOjA4Bgkq\n\ +hkiG9w0BCQEWK2F1dGhvcml0eUBjeWNsb25lZGRzc2VjdXJpdHkuYWRsaW5rdGVj\n\ +aC5jb20wHhcNMjAwMjI3MTkyMjA1WhcNMzAwMjI0MTkyMjA1WjCBwDELMAkGA1UE\n\ +BhMCTkwxCzAJBgNVBAgMAk9WMRYwFAYDVQQHDA1Mb2NhbGl0eSBOYW1lMRMwEQYD\n\ +VQQLDApFeGFtcGxlIE9VMSMwIQYDVQQKDBpFeGFtcGxlIElEIENBIE9yZ2FuaXph\n\ +dGlvbjEWMBQGA1UEAwwNRXhhbXBsZSBJRCBDQTE6MDgGCSqGSIb3DQEJARYrYXV0\n\ +aG9yaXR5QGN5Y2xvbmVkZHNzZWN1cml0eS5hZGxpbmt0ZWNoLmNvbTCCASIwDQYJ\n\ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBALKhk7JXUpqJphyOC6oOI00LH49WTtO2\n\ +GCgDyJhcRYYAm7APMtmEDH+zptvd34N4eSu03Dc65cB/XN4Lbi2TjolVvKz0hHjz\n\ +tzmQT5jTgb1UkJX4NjKGw+RrYe9Ls0kfoAL2kvb12kmd1Oj4TIKMZP9TCrz7Vw8m\n\ +cZKQxZ56bLys6cU2XdiTp3v+Ef/vMll4+DINj4ZAMWL3CkT+q1G6ZxHRpFlsIyhc\n\ +Q1wX6gxUoY6cQdBA7TehKCCEWz4L1KM1A18ZmCHmjTniU0ssLoiAzsQs4b6Fnw8Z\n\ +MLFj8ocwzN5g66gJJWGofakXqX/V24KbGl54WX2X7FYU0tGzR234DXcCAwEAAaNT\n\ +MFEwHQYDVR0OBBYEFGeCcK8B74QWCuuCjlSUzOBBUTF5MB8GA1UdIwQYMBaAFGeC\n\ +cK8B74QWCuuCjlSUzOBBUTF5MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL\n\ +BQADggEBAJQeMc4XzMFnpQKCb58rzRs3Wt9FmZZS4O596sHxMEewTkEHm5gLYMzF\n\ +9JYEdUiLoTurQuIr0KgPi+Q3kliQdLfrVPbdWTmlUDZARR5ir5d1gGHST6qnb3Xi\n\ +mG+7nwle9R/hLrtPio+gYRgwJEiS55f6p0/E1wDcc+6numvjCRQ/CGIiJfwD/R+d\n\ +pv93YLEfuliZttfBc/apIu6OL4chxF+3QgSw1ltV5nXXqDTGHMRZENkp3Yiolumc\n\ +6smL4uA7Q812pVcENi3MLjdJgBS/8DcSBQHspVuXugaKKPDMkJnD0IyLWc8vLXh4\n\ +O7JdDrmusJAZA9RsTkinl3DuPfF34Sk=\n\ +-----END CERTIFICATE-----" + + +#define TEST_IDENTITY2_CERTIFICATE "data:,-----BEGIN CERTIFICATE-----\n\ +MIIEDjCCAvYCFDEZQzcfGKK8IKNyH+AdNSjdyVgnMA0GCSqGSIb3DQEBCwUAMIHF\n\ +MQswCQYDVQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2FsaXR5IE5h\n\ +bWUxEzARBgNVBAsMCkV4YW1wbGUgT1UxJTAjBgNVBAoMHEV4YW1wbGUgSUQgQ0Eg\n\ +MiBPcmdhbml6YXRpb24xGDAWBgNVBAMMD0V4YW1wbGUgSUQgQ0EgMjE7MDkGCSqG\n\ +SIb3DQEJARYsYXV0aG9yaXR5MkBjeWNsb25lZGRzc2VjdXJpdHkuYWRsaW5rdGVj\n\ +aC5jb20wHhcNMjAwMjI3MTkyNjIwWhcNMzAwMjI0MTkyNjIwWjCBwDELMAkGA1UE\n\ +BhMCTkwxCzAJBgNVBAgMAk9WMRYwFAYDVQQHDA1Mb2NhbGl0eSBOYW1lMSEwHwYD\n\ +VQQLDBhPcmdhbml6YXRpb25hbCBVbml0IE5hbWUxHTAbBgNVBAoMFEV4YW1wbGUg\n\ +T3JnYW5pemF0aW9uMRQwEgYDVQQDDAtCb2IgRXhhbXBsZTE0MDIGCSqGSIb3DQEJ\n\ +ARYlYm9iQGN5Y2xvbmVkZHNzZWN1cml0eS5hZGxpbmt0ZWNoLmNvbTCCASIwDQYJ\n\ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMAQM9eN0zjTTdZALCTijog0oqx/kqnW\n\ +VtVWjV/c34OyPvUuH/DNRH6Cr0fI76UiooLD9nfvHe52X8oZH8WqNW7m7g7dMliu\n\ +DJD3yVpdLRmTTgl40ES8MTqmdb2y8ut70MJf5nUz0EQs9lXvnT0ru0B2CfyubiPt\n\ +aLSfyDoVBkRLbfzeqaNEQe7Ta6mQKZOckb6BHcaInb9GYEsU+OyOHuf2tCVNnRIH\n\ +ALiTPbA7rRS/J7ICS904/qz7w6km9Ta/oYQI5n0np64L+HqgtYZgIlVURW9grg2p\n\ +BuaX+xnJdRZbLQ0YYs+Gpmc1Vnykd+c2b0KP7zyHf8WFk9vV5W1ah2sCAwEAATAN\n\ +BgkqhkiG9w0BAQsFAAOCAQEA1RHDhLZf/UOR+azuH2lvD7ioSGRtdaOdJchSPdMk\n\ +v1q74PsHgm4/QAadVPdzvaIVV9kDfo6kGMzh+dCtq69EqVOavw1WUDo/NfuVSbgA\n\ +W7yeA39o3ROMO9UgbE5T3BPLq/XSXdIisP9OA4uXCnt22JELJaSv4m59FHg5gnQ7\n\ +2qOWRM7hi/+cQwescE+lDRw7PUzW8SS1HkQA1DmdtIIpWVuvYj7EPUNQX3jIetn8\n\ +AuPUgPJObxJhxJSC4p5qy37pYZHiNH1wG/+BDHgZo3wNwFsWqxabKziGB8XU3INc\n\ +USI3GDWM2jjElMSnDCj4ChM5wFbwWrqwdOEzeGWBWbo3hQ==\n\ +-----END CERTIFICATE-----" + +#define TEST_IDENTITY2_PRIVATE_KEY "data:,-----BEGIN RSA PRIVATE KEY-----\n\ +MIIEpQIBAAKCAQEAwBAz143TONNN1kAsJOKOiDSirH+SqdZW1VaNX9zfg7I+9S4f\n\ +8M1EfoKvR8jvpSKigsP2d+8d7nZfyhkfxao1bubuDt0yWK4MkPfJWl0tGZNOCXjQ\n\ +RLwxOqZ1vbLy63vQwl/mdTPQRCz2Ve+dPSu7QHYJ/K5uI+1otJ/IOhUGREtt/N6p\n\ +o0RB7tNrqZApk5yRvoEdxoidv0ZgSxT47I4e5/a0JU2dEgcAuJM9sDutFL8nsgJL\n\ +3Tj+rPvDqSb1Nr+hhAjmfSenrgv4eqC1hmAiVVRFb2CuDakG5pf7Gcl1FlstDRhi\n\ +z4amZzVWfKR35zZvQo/vPId/xYWT29XlbVqHawIDAQABAoIBAFNm9cw15zI2+AcA\n\ +yOqfgzt8d+OmZl7gF8b+lde6B0meHp7Dj9U2nfa98zWd+QrhtmZIiH/eU0YZG1Gc\n\ +hWKFnjxxhZDo1xMRSZ2uLD7UVWBUyj9suiwO+OW6IUjmK3y8wJOXp3DftiHU0IfS\n\ +zJoiombEm2Ohr2xkjOJavE0UkisXQauc3K5AKv9coW9W6hzZf330Sm4sokmC5D3B\n\ +GcO/Keof2k2sFuv56wXPi9eGuXCEB2trhHhrxqncvb/fbRwpG1ELQsvZBnyuNNnY\n\ +FQcLYl52gkttP6EGvRPw1DFbQwsAJKnXBC7ddJaAl+JoKYAcGTt0+mRm0Z8ltzWl\n\ +c6uZQsECgYEA4NGiUMNq9kSn/6tQyPcsrphJ5uobu/svLaBipZ0vv2yQP3wQ5NPA\n\ +06KjwSm8gg8BLi0LCKplSxY09TwgUsc9unRkDTQ/eflgjdGA76lFKOjvLQdutxn7\n\ +eYNbx81WMY6E6n4y6K+2szpqW+Ds1At4ORRvweJWdFyc01bTqWNeuYsCgYEA2rOO\n\ +Ye6H2VixUfXzXwevBd4QyFJITW46WqnbYDFcUzf9pYBZfZoHU0YJqolDIhHhtHnG\n\ +soRi0Uk5P9D7Lvu+ZHAGQJrdmNELOMoqMNOqXcAdvK44qLLMwaLC8PS2zDIATrhZ\n\ +nc0TbeZJC8MynfIpxDsBVVMOa8u4eHRFdpk8ZaECgYEAlzuuCtJKQ7vPn2dpAqdz\n\ +gUekfxeA7KV+CR1Y/ruMgSLQrkQRQT1I+5Tuv2QKERty2dMnFv85AJfBrC50N/sb\n\ +hTAClfdNtAmTcBM8vvuJMInxSsMzMSzjQ8yfkvqIPvH2a5/VMz3wkwR6w6+84K+O\n\ +gidDPpO5QLGENY6097+G2x0CgYEAk7cdX0YGGaZPNiWiOLhu3c6slTEGRs5BucTq\n\ +OGF+k3LI7kTvrOchNXyjwLyvTE65nPV3YFIMkIEdmt3jGkvMv/fuMSqoq7PeGYBq\n\ +2MnOUz4Ul8Ew4bjKlasCck9HPEo1bPYVCYFfMyaMhdZU1NugnDqiXugXYHWb5jfa\n\ +Rw2e/qECgYEA3PvLLHklsRts6P37iSwUmDnkiopSSPfVdGXpDDGD/RbLpG6cSLRm\n\ +uh5n9+nxa2YXi0+LMLQvGpCSWk2k2qaRPpe2mahy9yAYrLhfDDcuGpSvw5BBJ3qw\n\ +mi1HgIUzXZTRBNamYCltJWYnN0hOlSL6vcHgeJ9y1gSDh0QqB2BG8HY=\n\ +-----END RSA PRIVATE KEY-----" + + +#define TEST_IDENTITY_CA2_CERTIFICATE "data:,-----BEGIN CERTIFICATE-----\n\ +MIIEbTCCA1WgAwIBAgIUL0mSpPRgzveYTJ8UHSmOIwkIjjYwDQYJKoZIhvcNAQEL\n\ +BQAwgcUxCzAJBgNVBAYTAk5MMQswCQYDVQQIDAJPVjEWMBQGA1UEBwwNTG9jYWxp\n\ +dHkgTmFtZTETMBEGA1UECwwKRXhhbXBsZSBPVTElMCMGA1UECgwcRXhhbXBsZSBJ\n\ +RCBDQSAyIE9yZ2FuaXphdGlvbjEYMBYGA1UEAwwPRXhhbXBsZSBJRCBDQSAyMTsw\n\ +OQYJKoZIhvcNAQkBFixhdXRob3JpdHkyQGN5Y2xvbmVkZHNzZWN1cml0eS5hZGxp\n\ +bmt0ZWNoLmNvbTAeFw0yMDAyMjcxNjI3MjRaFw0zMDAyMjQxNjI3MjRaMIHFMQsw\n\ +CQYDVQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2FsaXR5IE5hbWUx\n\ +EzARBgNVBAsMCkV4YW1wbGUgT1UxJTAjBgNVBAoMHEV4YW1wbGUgSUQgQ0EgMiBP\n\ +cmdhbml6YXRpb24xGDAWBgNVBAMMD0V4YW1wbGUgSUQgQ0EgMjE7MDkGCSqGSIb3\n\ +DQEJARYsYXV0aG9yaXR5MkBjeWNsb25lZGRzc2VjdXJpdHkuYWRsaW5rdGVjaC5j\n\ +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDk+ewDf871kPgBqXkm\n\ +UEXdf/vqWWoKx3KfJ4N3Gq4vt/cDOMs0xakpqr5uxm787AvbOui4P8QmT8naLhAA\n\ +TvHtNGg2LV0ZQtLcVVFsXXsBYDUEbLJYmCBtJU8zSfLLzgtN+z9nVqLthAcVyGhZ\n\ +iEkCfXKS4XzwjFUxgrXUM1VSiHHz8DbreQFDTF8mVavZ75HjieuHz1OcSaoIHCIF\n\ +mhPDlxRR/qZpc3Y52NZMNRHVPj4Tmc3N4H2eneeoG7nVn0MgNuqbssezeQtUOOoH\n\ +DgPGp3xzd8XQxaF5hVIM9E7aL77kw5v4gwccjL5xWC72zzxC3c1ltmbaEcwhHGsu\n\ +MR4lAgMBAAGjUzBRMB0GA1UdDgQWBBTTpmGTY5teWrZBA8Sd7kL5Lg/JmjAfBgNV\n\ +HSMEGDAWgBTTpmGTY5teWrZBA8Sd7kL5Lg/JmjAPBgNVHRMBAf8EBTADAQH/MA0G\n\ +CSqGSIb3DQEBCwUAA4IBAQCbelDJr9sVsYgQSp4yzSOSop5DSOWCweBF56NatcbY\n\ +3HUYc4iaH4NcB04WFkUl2XmqVCAM0zbmV0q4HoQikTK5PBHmwxuuD2HhPDWtMeFR\n\ +W96BjzGVpV27yaNIPvLwjTVV+A72r4vRvufiFhrMCovRwlWgHY6+gXKfrtyljTZ0\n\ +m1mENHOJOQWDXFAXP5yiehSMKy/izKvQ1G1hLErYMMc+sdgF/9X2KaudnTakTW0d\n\ +44kXUFKSU7mqV44D12unxCNODclznd31tiJ+70U39AXlR2BzwBzyFzPCh5JYtMog\n\ +TwbdLY3LN40gpkDUxIIH115D7ujUKNd8s2gmSHOCm1ar\n\ +-----END CERTIFICATE-----" + + +#endif /* PLUGIN_SECURITY_CORE_TEST_IDENTITY_H_ */ diff --git a/src/security/core/tests/config.c b/src/security/core/tests/config.c new file mode 100644 index 0000000..6bfc918 --- /dev/null +++ b/src/security/core/tests/config.c @@ -0,0 +1,631 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include + +#include "dds/dds.h" +#include "CUnit/Test.h" +#include "dds/version.h" +#include "dds/ddsrt/cdtors.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsi/q_misc.h" +#include "dds/ddsi/ddsi_xqos.h" +#include "dds/security/dds_security_api_defs.h" +#include "common/config_env.h" +#include "common/test_identity.h" + +#define PROPLIST(init_auth, fin_auth, init_crypto, fin_crypto, init_ac, fin_ac, perm_ca, gov, perm, pre_str, post_str, binprops) \ + "property_list={" pre_str \ + "0:\"dds.sec.auth.library.path\":\""WRAPPERLIB_PATH("dds_security_authentication_wrapper")"\"," \ + "0:\"dds.sec.auth.library.init\":\""init_auth"\"," \ + "0:\"dds.sec.auth.library.finalize\":\""fin_auth"\"," \ + "0:\"dds.sec.crypto.library.path\":\""WRAPPERLIB_PATH("dds_security_cryptography_wrapper")"\"," \ + "0:\"dds.sec.crypto.library.init\":\""init_crypto"\"," \ + "0:\"dds.sec.crypto.library.finalize\":\""fin_crypto"\"," \ + "0:\"dds.sec.access.library.path\":\""WRAPPERLIB_PATH("dds_security_access_control_wrapper")"\"," \ + "0:\"dds.sec.access.library.init\":\""init_ac"\"," \ + "0:\"dds.sec.access.library.finalize\":\""fin_ac"\"," \ + "0:\"dds.sec.auth.identity_ca\":\"" TEST_IDENTITY_CA_CERTIFICATE_DUMMY "\"," \ + "0:\"dds.sec.auth.private_key\":\"" TEST_IDENTITY_PRIVATE_KEY_DUMMY "\"," \ + "0:\"dds.sec.auth.identity_certificate\":\"" TEST_IDENTITY_CERTIFICATE_DUMMY "\"," \ + "0:\"dds.sec.access.permissions_ca\":\""perm_ca"\"," \ + "0:\"dds.sec.access.governance\":\""gov"\"," \ + "0:\"dds.sec.access.permissions\":\""perm"\"" \ + post_str "}:{" binprops "}" +#define PARTICIPANT_QOS(init_auth, fin_auth, init_crypto, fin_crypto, init_ac, fin_ac, perm_ca, gov, perm, pre_str, post_str, binprops) \ + "PARTICIPANT * QOS={*" PROPLIST (init_auth, fin_auth, init_crypto, fin_crypto, init_ac, fin_ac, perm_ca, gov, perm, pre_str, post_str, binprops) "*" +#define PARTICIPANT_QOS_ALL_OK(pre_str, post_str, binprops) \ + PARTICIPANT_QOS ("init_test_authentication_all_ok", "finalize_test_authentication_all_ok", \ + "init_test_cryptography_all_ok", "finalize_test_cryptography_all_ok", \ + "init_test_access_control_all_ok", "finalize_test_access_control_all_ok", \ + "file:Permissions_CA.pem", "file:Governance.p7s", "file:Permissions.p7s", \ + pre_str, post_str, binprops) + +/* + * The 'found' variable will contain flags related to the expected log + * messages that were received. + * Using flags will allow to show that when message isn't received, + * which one it was. + */ +static uint32_t found; + +static void logger(void *ptr, const dds_log_data_t *data) +{ + char **expected = (char**)ptr; + fputs (data->message, stdout); + for (uint32_t i = 0; expected[i] != NULL; i++) { + if (ddsi2_patmatch(expected[i], data->message)) { + found |= (uint32_t)(1 << i); + } + } +} + +static void set_logger_exp(const void * log_expected) +{ + found = 0; + dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG); + dds_set_log_sink(&logger, (void*)log_expected); + dds_set_trace_sink(&logger, (void*)log_expected); +} + +static void reset_logger() +{ + dds_set_log_sink(NULL, NULL); + dds_set_trace_sink(NULL, NULL); +} + +/* Expected traces when creating domain with an empty security element. We need to + test this one here to be sure that it refuses to start when security is configured + but the implementation doesn't include support for it. */ +CU_Test(ddssec_config, empty, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain; + const char *log_expected[] = { + "config: //CycloneDDS/Domain/DDSSecurity/Authentication/IdentityCertificate/#text: element missing in configuration*", + "config: //CycloneDDS/Domain/DDSSecurity/Authentication/IdentityCA/#text: element missing in configuration*", + "config: //CycloneDDS/Domain/DDSSecurity/Authentication/PrivateKey/#text: element missing in configuration*", + NULL + }; + + set_logger_exp(log_expected); + domain = dds_create_domain(0, ""); + CU_ASSERT_EQUAL_FATAL(domain, DDS_RETCODE_ERROR); + reset_logger(); + + /* All traces should have been provided. */ + CU_ASSERT_FATAL(found == 0x7); +} + +/* Create domain without security element, there shouldn't + be traces that mention security. */ +CU_Test(ddssec_config, non, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain; + const char *log_expected[] = { + "*Security*", + NULL + }; + + set_logger_exp(log_expected); + domain = dds_create_domain(0, "finest"); + CU_ASSERT_FATAL(domain > 0); + dds_delete(domain); + reset_logger(); + + /* No security traces should have been provided. */ + CU_ASSERT_FATAL(found == 0x0); +} + +/* Expected traces when creating domain with the security elements. */ +CU_Test(ddssec_config, missing, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain; + const char *log_expected[] = { + "config: //CycloneDDS/Domain/DDSSecurity/Authentication/IdentityCertificate/#text: element missing in configuration*", + "config: //CycloneDDS/Domain/DDSSecurity/Authentication/IdentityCA/#text: element missing in configuration*", + "config: //CycloneDDS/Domain/DDSSecurity/Authentication/PrivateKey/#text: element missing in configuration*", + NULL + }; + + /* IdentityCertificate, IdentityCA and PrivateKey values or elements are missing. */ + const char *sec_config = + "" + " finest" + " " + " " + " " + " " + " " + " testtext_Password_testtext" + " " + " " + ""; + + set_logger_exp(log_expected); + domain = dds_create_domain(0, sec_config); + CU_ASSERT_EQUAL_FATAL(domain, DDS_RETCODE_ERROR); + reset_logger(); + + /* All traces should have been provided. */ + CU_ASSERT_FATAL(found == 0x7); +} + +/* Expected traces when creating domain with the security elements. */ +CU_Test(ddssec_config, all, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + const char *log_expected[] = { + "config: Domain/DDSSecurity/Authentication/Library/#text: "WRAPPERLIB_PATH("dds_security_authentication_wrapper")"*", + "config: Domain/DDSSecurity/Authentication/Library[@path]: "WRAPPERLIB_PATH("dds_security_authentication_wrapper")"*", + "config: Domain/DDSSecurity/Authentication/Library[@initFunction]: init_test_authentication_all_ok*", + "config: Domain/DDSSecurity/Authentication/Library[@finalizeFunction]: finalize_test_authentication_all_ok*", + "config: Domain/DDSSecurity/Authentication/IdentityCertificate/#text: "TEST_IDENTITY_CERTIFICATE_DUMMY"*", + "config: Domain/DDSSecurity/Authentication/IdentityCA/#text: "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"*", + "config: Domain/DDSSecurity/Authentication/PrivateKey/#text: "TEST_IDENTITY_PRIVATE_KEY_DUMMY"*", + "config: Domain/DDSSecurity/Authentication/Password/#text: testtext_Password_testtext*", + "config: Domain/DDSSecurity/Authentication/TrustedCADirectory/#text: testtext_Dir_testtext*", + "config: Domain/DDSSecurity/AccessControl/Library/#text: "WRAPPERLIB_PATH("dds_security_access_control_wrapper")"*", + "config: Domain/DDSSecurity/AccessControl/Library[@path]: "WRAPPERLIB_PATH("dds_security_access_control_wrapper")"*", + "config: Domain/DDSSecurity/AccessControl/Library[@initFunction]: init_test_access_control_all_ok*", + "config: Domain/DDSSecurity/AccessControl/Library[@finalizeFunction]: finalize_test_access_control_all_ok*", + "config: Domain/DDSSecurity/AccessControl/PermissionsCA/#text: file:Permissions_CA.pem*", + "config: Domain/DDSSecurity/AccessControl/Governance/#text: file:Governance.p7s*", + "config: Domain/DDSSecurity/AccessControl/Permissions/#text: file:Permissions.p7s*", + "config: Domain/DDSSecurity/Cryptographic/Library/#text: "WRAPPERLIB_PATH("dds_security_cryptography_wrapper")"*", + "config: Domain/DDSSecurity/Cryptographic/Library[@path]: "WRAPPERLIB_PATH("dds_security_cryptography_wrapper")"*", + "config: Domain/DDSSecurity/Cryptographic/Library[@initFunction]: init_test_cryptography_all_ok*", + "config: Domain/DDSSecurity/Cryptographic/Library[@finalizeFunction]: finalize_test_cryptography_all_ok*", + /* The config should have been parsed into the participant QoS. */ + PARTICIPANT_QOS_ALL_OK ("", ",0:\"dds.sec.auth.password\":\"testtext_Password_testtext\",0:\"dds.sec.auth.trusted_ca_dir\":\"testtext_Dir_testtext\"", ""), + NULL + }; + + const char *sec_config = + "<"DDS_PROJECT_NAME">" + " " + " finest" + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " testtext_Password_testtext" + " testtext_Dir_testtext" + " " + " " + " " + " " + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + " " + ""; + + set_logger_exp(log_expected); + domain = dds_create_domain(0, sec_config); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, NULL, NULL); + CU_ASSERT_FATAL(participant > 0); + dds_delete(participant); + dds_delete(domain); + reset_logger(); + + /* All traces should have been provided. */ + printf("found: %x\n", found); + CU_ASSERT_FATAL(found == 0x1fffff); +} + +/* Expected traces when creating participant with the security elements. */ +CU_Test(ddssec_config, security, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + const char *log_expected[] = { + "config: Domain/DDSSecurity/Authentication/Library/#text: "WRAPPERLIB_PATH("dds_security_authentication_wrapper")"*", + "config: Domain/DDSSecurity/Authentication/Library[@path]: "WRAPPERLIB_PATH("dds_security_authentication_wrapper")"*", + "config: Domain/DDSSecurity/Authentication/Library[@initFunction]: init_test_authentication_all_ok*", + "config: Domain/DDSSecurity/Authentication/Library[@finalizeFunction]: finalize_test_authentication_all_ok*", + "config: Domain/DDSSecurity/Authentication/IdentityCertificate/#text: "TEST_IDENTITY_CERTIFICATE_DUMMY"*", + "config: Domain/DDSSecurity/Authentication/IdentityCA/#text: "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"*", + "config: Domain/DDSSecurity/Authentication/PrivateKey/#text: "TEST_IDENTITY_PRIVATE_KEY_DUMMY"*", + "config: Domain/DDSSecurity/Authentication/Password/#text: {}*", + "config: Domain/DDSSecurity/Authentication/TrustedCADirectory/#text: {}*", + "config: Domain/DDSSecurity/AccessControl/Library/#text: "WRAPPERLIB_PATH("dds_security_access_control_wrapper")"*", + "config: Domain/DDSSecurity/AccessControl/Library[@path]: "WRAPPERLIB_PATH("dds_security_access_control_wrapper")"*", + "config: Domain/DDSSecurity/AccessControl/Library[@initFunction]: init_test_access_control_all_ok*", + "config: Domain/DDSSecurity/AccessControl/Library[@finalizeFunction]: finalize_test_access_control_all_ok*", + "config: Domain/DDSSecurity/AccessControl/PermissionsCA/#text: file:Permissions_CA.pem*", + "config: Domain/DDSSecurity/AccessControl/Governance/#text: file:Governance.p7s*", + "config: Domain/DDSSecurity/AccessControl/Permissions/#text: file:Permissions.p7s*", + "config: Domain/DDSSecurity/Cryptographic/Library/#text: "WRAPPERLIB_PATH("dds_security_cryptography_wrapper")"*", + "config: Domain/DDSSecurity/Cryptographic/Library[@path]: "WRAPPERLIB_PATH("dds_security_cryptography_wrapper")"*", + "config: Domain/DDSSecurity/Cryptographic/Library[@initFunction]: init_test_cryptography_all_ok*", + "config: Domain/DDSSecurity/Cryptographic/Library[@finalizeFunction]: finalize_test_cryptography_all_ok*", + /* The config should have been parsed into the participant QoS. */ + PARTICIPANT_QOS_ALL_OK ("", ",0:\"dds.sec.auth.password\":\"\",0:\"dds.sec.auth.trusted_ca_dir\":\"\"", ""), + NULL + }; + + const char *sec_config = + "" + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " " + " " + " " + " " + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + " finest" + ""; + + set_logger_exp(log_expected); + domain = dds_create_domain(0, sec_config); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, NULL, NULL); + CU_ASSERT_FATAL(participant > 0); + dds_delete(participant); + dds_delete(domain); + reset_logger(); + + /* All traces should have been provided. */ + CU_ASSERT_FATAL(found == 0x1fffff); +} + +/* Expected traces when creating domain with the security elements. */ +CU_Test(ddssec_config, deprecated, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + const char *log_expected[] = { + "config: Domain/DDSSecurity/Authentication/Library/#text: "WRAPPERLIB_PATH("dds_security_authentication_wrapper")"*", + "config: Domain/DDSSecurity/Authentication/Library[@path]: "WRAPPERLIB_PATH("dds_security_authentication_wrapper")"*", + "config: Domain/DDSSecurity/Authentication/Library[@initFunction]: init_test_authentication_all_ok*", + "config: Domain/DDSSecurity/Authentication/Library[@finalizeFunction]: finalize_test_authentication_all_ok*", + "config: Domain/DDSSecurity/Authentication/IdentityCertificate/#text: "TEST_IDENTITY_CERTIFICATE_DUMMY"*", + "config: Domain/DDSSecurity/Authentication/IdentityCA/#text: "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"*", + "config: Domain/DDSSecurity/Authentication/PrivateKey/#text: "TEST_IDENTITY_PRIVATE_KEY_DUMMY"*", + "config: Domain/DDSSecurity/Authentication/Password/#text: testtext_Password_testtext*", + "config: Domain/DDSSecurity/Authentication/TrustedCADirectory/#text: testtext_Dir_testtext*", + "config: Domain/DDSSecurity/AccessControl/Library/#text: "WRAPPERLIB_PATH("dds_security_access_control_wrapper")"*", + "config: Domain/DDSSecurity/AccessControl/Library[@path]: "WRAPPERLIB_PATH("dds_security_access_control_wrapper")"*", + "config: Domain/DDSSecurity/AccessControl/Library[@initFunction]: init_test_access_control_all_ok*", + "config: Domain/DDSSecurity/AccessControl/Library[@finalizeFunction]: finalize_test_access_control_all_ok*", + "config: Domain/DDSSecurity/AccessControl/PermissionsCA/#text: file:Permissions_CA.pem*", + "config: Domain/DDSSecurity/AccessControl/Governance/#text: file:Governance.p7s*", + "config: Domain/DDSSecurity/AccessControl/Permissions/#text: file:Permissions.p7s*", + "config: Domain/DDSSecurity/Cryptographic/Library/#text: "WRAPPERLIB_PATH("dds_security_cryptography_wrapper")"*", + "config: Domain/DDSSecurity/Cryptographic/Library[@path]: "WRAPPERLIB_PATH("dds_security_cryptography_wrapper")"*", + "config: Domain/DDSSecurity/Cryptographic/Library[@initFunction]: init_test_cryptography_all_ok*", + "config: Domain/DDSSecurity/Cryptographic/Library[@finalizeFunction]: finalize_test_cryptography_all_ok*", + /* The config should have been parsed into the participant QoS. */ + PARTICIPANT_QOS_ALL_OK ("", ",0:\"dds.sec.auth.password\":\"testtext_Password_testtext\",0:\"dds.sec.auth.trusted_ca_dir\":\"testtext_Dir_testtext\"", ""), + NULL + }; + + const char *sec_config = + "<"DDS_PROJECT_NAME">" + " " + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " testtext_Password_testtext" + " testtext_Dir_testtext" + " " + " " + " " + " " + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + " finest" + " " + ""; + + set_logger_exp(log_expected); + domain = dds_create_domain(0, sec_config); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, NULL, NULL); + CU_ASSERT_FATAL(participant > 0); + dds_delete(participant); + dds_delete(domain); + reset_logger(); + + /* All traces should have been provided. */ + CU_ASSERT_FATAL(found == 0x1fffff); +} + +/* Expected traces when creating participant with the security elements. */ +CU_Test(ddssec_config, qos, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + dds_qos_t * qos; + const char *log_expected[] = { + /* The config should have been parsed into the participant QoS. */ + PARTICIPANT_QOS_ALL_OK ("", ",0:\"dds.sec.auth.password\":\"testtext_Password_testtext\",0:\"dds.sec.auth.trusted_ca_dir\":\"file:/test/dir\"", ""), + NULL + }; + + /* Create the qos */ + CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); + dds_qset_prop(qos, "dds.sec.auth.library.path", ""WRAPPERLIB_PATH("dds_security_authentication_wrapper")""); + dds_qset_prop(qos, "dds.sec.auth.library.init", "init_test_authentication_all_ok"); + dds_qset_prop(qos, "dds.sec.auth.library.finalize", "finalize_test_authentication_all_ok"); + dds_qset_prop(qos, "dds.sec.crypto.library.path", ""WRAPPERLIB_PATH("dds_security_cryptography_wrapper")""); + dds_qset_prop(qos, "dds.sec.crypto.library.init", "init_test_cryptography_all_ok"); + dds_qset_prop(qos, "dds.sec.crypto.library.finalize", "finalize_test_cryptography_all_ok"); + dds_qset_prop(qos, "dds.sec.access.library.path", ""WRAPPERLIB_PATH("dds_security_access_control_wrapper")""); + dds_qset_prop(qos, "dds.sec.access.library.init", "init_test_access_control_all_ok"); + dds_qset_prop(qos, "dds.sec.access.library.finalize", "finalize_test_access_control_all_ok"); + dds_qset_prop(qos, "dds.sec.auth.identity_ca", ""TEST_IDENTITY_CA_CERTIFICATE_DUMMY""); + dds_qset_prop(qos, "dds.sec.auth.private_key", ""TEST_IDENTITY_PRIVATE_KEY_DUMMY""); + dds_qset_prop(qos, "dds.sec.auth.identity_certificate", ""TEST_IDENTITY_CERTIFICATE_DUMMY""); + dds_qset_prop(qos, "dds.sec.access.permissions_ca", "file:Permissions_CA.pem"); + dds_qset_prop(qos, "dds.sec.access.governance", "file:Governance.p7s"); + dds_qset_prop(qos, "dds.sec.access.permissions", "file:Permissions.p7s"); + dds_qset_prop(qos, "dds.sec.auth.password", "testtext_Password_testtext"); + dds_qset_prop(qos, "dds.sec.auth.trusted_ca_dir", "file:/test/dir"); + + set_logger_exp(log_expected); + domain = dds_create_domain(0, "finest"); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, qos, NULL); + CU_ASSERT_FATAL(participant > 0); + dds_delete(participant); + dds_delete_qos(qos); + dds_delete(domain); + reset_logger(); + + /* All traces should have been provided. */ + CU_ASSERT_FATAL(found == 0x1); +} + +/* Expected traces when creating participant with the security elements. */ +CU_Test(ddssec_config, qos_props, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + dds_qos_t * qos; + const char *log_expected[] = { + /* The config should have been parsed into the participant QoS. */ + PARTICIPANT_QOS_ALL_OK ("", ",0:\"dds.sec.auth.password\":\"testtext_Password_testtext\",0:\"dds.sec.auth.trusted_ca_dir\":\"file:/test/dir\",0:\"test.prop1\":\"testtext_value1_testtext\",0:\"test.prop2\":\"testtext_value2_testtext\"", + "0:\"test.bprop1\":3<1,2,3>"), + NULL + }; + + /* Create the qos */ + unsigned char bvalue[3] = { 0x01, 0x02, 0x03 }; + CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); + dds_qset_prop(qos, "dds.sec.auth.library.path", ""WRAPPERLIB_PATH("dds_security_authentication_wrapper")""); + dds_qset_prop(qos, "dds.sec.auth.library.init", "init_test_authentication_all_ok"); + dds_qset_prop(qos, "dds.sec.auth.library.finalize", "finalize_test_authentication_all_ok"); + dds_qset_prop(qos, "dds.sec.crypto.library.path", ""WRAPPERLIB_PATH("dds_security_cryptography_wrapper")""); + dds_qset_prop(qos, "dds.sec.crypto.library.init", "init_test_cryptography_all_ok"); + dds_qset_prop(qos, "dds.sec.crypto.library.finalize", "finalize_test_cryptography_all_ok"); + dds_qset_prop(qos, "dds.sec.access.library.path", ""WRAPPERLIB_PATH("dds_security_access_control_wrapper")""); + dds_qset_prop(qos, "dds.sec.access.library.init", "init_test_access_control_all_ok"); + dds_qset_prop(qos, "dds.sec.access.library.finalize", "finalize_test_access_control_all_ok"); + dds_qset_prop(qos, "dds.sec.auth.identity_ca", TEST_IDENTITY_CA_CERTIFICATE_DUMMY); + dds_qset_prop(qos, "dds.sec.auth.private_key", TEST_IDENTITY_PRIVATE_KEY_DUMMY); + dds_qset_prop(qos, "dds.sec.auth.identity_certificate", TEST_IDENTITY_CERTIFICATE_DUMMY); + dds_qset_prop(qos, "dds.sec.access.permissions_ca", "file:Permissions_CA.pem"); + dds_qset_prop(qos, "dds.sec.access.governance", "file:Governance.p7s"); + dds_qset_prop(qos, "dds.sec.access.permissions", "file:Permissions.p7s"); + dds_qset_prop(qos, "dds.sec.auth.password", "testtext_Password_testtext"); + dds_qset_prop(qos, "dds.sec.auth.trusted_ca_dir", "file:/test/dir"); + dds_qset_prop(qos, "test.prop1", "testtext_value1_testtext"); + dds_qset_prop(qos, "test.prop2", "testtext_value2_testtext"); + dds_qset_bprop(qos, "test.bprop1", bvalue, 3); + + set_logger_exp(log_expected); + domain = dds_create_domain(0, "finest"); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, qos, NULL); + CU_ASSERT_FATAL(participant > 0); + dds_delete(participant); + dds_delete_qos(qos); + dds_delete(domain); + reset_logger(); + + /* All traces should have been provided. */ + CU_ASSERT_FATAL(found == 0x1); +} + +/* Expect qos settings used when creating participant with config security elements and qos. */ +CU_Test(ddssec_config, config_qos, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + dds_qos_t * qos; + const char *log_expected[] = { + /* The security settings from qos properties should have been parsed into the participant QoS. */ + "new_participant(*): using security settings from QoS*", + PARTICIPANT_QOS ("init_test_authentication_all_ok", "finalize_test_authentication_all_ok", \ + "init_test_cryptography_all_ok", "finalize_test_cryptography_all_ok", \ + "init_test_access_control_all_ok", "finalize_test_access_control_all_ok", \ + "file:QOS_Permissions_CA.pem", "file:QOS_Governance.p7s", "file:QOS_Permissions.p7s", \ + "", "", ""), + NULL + }; + + const char *sec_config = + "finest" + "" + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + ""; + + CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_PATH, WRAPPERLIB_PATH("dds_security_authentication_wrapper")); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_INIT, "init_test_authentication_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE, "finalize_test_authentication_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_PATH, WRAPPERLIB_PATH("dds_security_cryptography_wrapper")); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_INIT, "init_test_cryptography_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE, "finalize_test_cryptography_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_PATH, WRAPPERLIB_PATH("dds_security_access_control_wrapper")); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_INIT, "init_test_access_control_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE, "finalize_test_access_control_all_ok"); + dds_qset_prop(qos, "dds.sec.auth.identity_ca", TEST_IDENTITY_CA_CERTIFICATE_DUMMY); + dds_qset_prop(qos, "dds.sec.auth.private_key", TEST_IDENTITY_PRIVATE_KEY_DUMMY); + dds_qset_prop(qos, "dds.sec.auth.identity_certificate", TEST_IDENTITY_CERTIFICATE_DUMMY); + dds_qset_prop(qos, "dds.sec.access.permissions_ca", "file:QOS_Permissions_CA.pem"); + dds_qset_prop(qos, "dds.sec.access.governance", "file:QOS_Governance.p7s"); + dds_qset_prop(qos, "dds.sec.access.permissions", "file:QOS_Permissions.p7s"); + + set_logger_exp(log_expected); + domain = dds_create_domain(0, sec_config); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, qos, NULL); + CU_ASSERT_FATAL (participant > 0); + dds_delete(participant); + dds_delete_qos(qos); + dds_delete(domain); + reset_logger(); + + /* All traces should have been provided. */ + CU_ASSERT_FATAL(found == 0x3); +} + +/* Expect config used when creating participant with config security elements and + qos containing only non-security properties. */ +CU_Test(ddssec_config, other_prop, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + dds_qos_t * qos; + const char *log_expected[] = { + /* The security settings from config should have been parsed into the participant QoS. */ + PARTICIPANT_QOS_ALL_OK ("0:\"test.dds.sec.prop1\":\"testtext_value1_testtext\",", ",0:\"dds.sec.auth.password\":\"testtext_Password_testtext\",0:\"dds.sec.auth.trusted_ca_dir\":\"testtext_Dir_testtext\"", ""), + NULL + }; + + const char *sec_config = + "finest" + "" + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " testtext_Password_testtext" + " testtext_Dir_testtext" + " " + " " + " " + " " + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + ""; + + CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); + dds_qset_prop(qos, "test.dds.sec.prop1", "testtext_value1_testtext"); + + set_logger_exp(log_expected); + domain = dds_create_domain(0, sec_config); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, qos, NULL); + CU_ASSERT_FATAL (participant > 0); + dds_delete(participant); + dds_delete_qos(qos); + dds_delete(domain); + reset_logger(); + + /* All traces should have been provided. */ + CU_ASSERT_FATAL(found == 0x1); +} + +/* Expected traces when creating participant with the security elements. */ +CU_Test(ddssec_config, qos_invalid, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + dds_qos_t * qos; + const char *log_expected[] = { + /* The config should have been parsed into the participant QoS. */ + "new_participant(*): using security settings from QoS*", + "new_participant(*): required security property dds.sec.auth.identity_ca missing in Property QoS*", + "new_participant(*): required security property dds.sec.auth.private_key missing in Property QoS*", + "new_participant(*): required security property dds.sec.auth.identity_certificate missing in Property QoS*", + "new_participant(*): required security property dds.sec.access.permissions_ca missing in Property QoS*", + "new_participant(*): required security property dds.sec.access.governance missing in Property QoS*", + "new_participant(*): required security property dds.sec.access.permissions missing in Property QoS*", + "new_participant(*): required security property dds.sec.auth.library.path missing in Property QoS*", + "new_participant(*): required security property dds.sec.auth.library.init missing in Property QoS*", + "new_participant(*): required security property dds.sec.auth.library.finalize missing in Property QoS*", + "new_participant(*): required security property dds.sec.crypto.library.path missing in Property QoS*", + "new_participant(*): required security property dds.sec.crypto.library.init missing in Property QoS*", + "new_participant(*): required security property dds.sec.crypto.library.finalize missing in Property QoS*", + "new_participant(*): required security property dds.sec.access.library.path missing in Property QoS*", + "new_participant(*): required security property dds.sec.access.library.init missing in Property QoS*", + "new_participant(*): required security property dds.sec.access.library.finalize missing in Property QoS*", + NULL + }; + + const char *sec_config = + "finest" + "" + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + ""; + + set_logger_exp(log_expected); + + CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); + dds_qset_prop(qos, "dds.sec.dummy", "testtext_dummy_testtext"); + + /* Create participant with security config in qos. */ + domain = dds_create_domain(0, sec_config); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, qos, NULL); + CU_ASSERT_EQUAL_FATAL(participant, DDS_RETCODE_ERROR); + dds_delete_qos(qos); + dds_delete(domain); + reset_logger(); + + /* All traces should have been provided. */ + CU_ASSERT_FATAL(found == 0xffff); +} diff --git a/src/security/core/tests/dds_security_core.c b/src/security/core/tests/dds_security_core.c index ac494c2..aef1e4f 100644 --- a/src/security/core/tests/dds_security_core.c +++ b/src/security/core/tests/dds_security_core.c @@ -291,7 +291,7 @@ CU_Test(dds_security_timed_cb, test_create_dispatcher) /************************************************************************* * Check if adding callbacks succeeds *************************************************************************/ - + /* The last argument is a sequence number in which * the callbacks are expected to be called. */ /* We can only really check if it crashes or not... */ @@ -299,7 +299,7 @@ CU_Test(dds_security_timed_cb, test_create_dispatcher) dds_security_timed_dispatcher_add(tcb, d2, tc__callback, past, (void*)0); dds_security_timed_dispatcher_add(tcb, d2, tc__callback, present, (void*)2); dds_security_timed_dispatcher_add(tcb, d1, tc__callback, future, (void*)7); - + CU_PASS("Added callbacks") /************************************************************************* @@ -308,7 +308,7 @@ CU_Test(dds_security_timed_cb, test_create_dispatcher) d3 = dds_security_timed_dispatcher_new(tcb); d4 = dds_security_timed_dispatcher_new(tcb); d5 = dds_security_timed_dispatcher_new(tcb); - + CU_ASSERT_PTR_NOT_NULL_FATAL(d3); CU_ASSERT_PTR_NOT_NULL_FATAL(d4); CU_ASSERT_PTR_NOT_NULL_FATAL(d5); @@ -351,7 +351,7 @@ CU_Test(dds_security_timed_cb, test_create_dispatcher) /************************************************************************* * Check if timeout callbacks are triggered in the right sequence *************************************************************************/ - + int idx; int timeout = 200; /* 2 seconds */ diff --git a/src/security/core/tests/handshake.c b/src/security/core/tests/handshake.c new file mode 100644 index 0000000..6de2876 --- /dev/null +++ b/src/security/core/tests/handshake.c @@ -0,0 +1,99 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include + +#include "dds/dds.h" +#include "CUnit/Test.h" + +#include "dds/version.h" +#include "dds/ddsrt/cdtors.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsi/q_config.h" +#include "dds/ddsi/ddsi_domaingv.h" +#include "dds/ddsi/q_misc.h" +#include "dds/ddsi/ddsi_xqos.h" + +#include "dds/security/dds_security_api.h" + +#include "common/config_env.h" +#include "common/authentication_wrapper.h" +#include "common/plugin_wrapper_msg_q.h" +#include "common/handshake_test_utils.h" +#include "common/test_identity.h" + +static const char *config = + "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" + "0" + "" + " finest" + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE"" + " "TEST_IDENTITY_PRIVATE_KEY"" + " "TEST_IDENTITY_CA_CERTIFICATE"" + " testtext_Password_testtext" + " ." + " " + " " + " " + " file:" COMMON_ETC_PATH("default_governance.p7s") "" + " file:" COMMON_ETC_PATH("default_permissions_ca.pem") "" + " file:" COMMON_ETC_PATH("default_permissions.p7s") "" + " " + " " + " " + " " + " " + ""; + +#define DDS_DOMAINID_PART1 0 +#define DDS_DOMAINID_PART2 1 + +static dds_entity_t g_part1_domain = 0; +static dds_entity_t g_part1_participant = 0; + +static dds_entity_t g_part2_domain = 0; +static dds_entity_t g_part2_participant = 0; + +static void handshake_init(void) +{ + /* Domains for pub and sub use a different domain id, but the portgain setting + * in configuration is 0, so that both domains will map to the same port number. + * This allows to create two domains in a single test process. */ + char *conf_part1 = ddsrt_expand_envvars(config, DDS_DOMAINID_PART1); + char *conf_part2 = ddsrt_expand_envvars(config, DDS_DOMAINID_PART2); + g_part1_domain = dds_create_domain(DDS_DOMAINID_PART1, conf_part1); + g_part2_domain = dds_create_domain(DDS_DOMAINID_PART2, conf_part2); + dds_free(conf_part1); + dds_free(conf_part2); + + CU_ASSERT_FATAL((g_part1_participant = dds_create_participant(DDS_DOMAINID_PART1, NULL, NULL)) > 0); + CU_ASSERT_FATAL((g_part2_participant = dds_create_participant(DDS_DOMAINID_PART2, NULL, NULL)) > 0); +} + +static void handshake_fini(void) +{ + CU_ASSERT_EQUAL_FATAL(dds_delete(g_part1_participant), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(dds_delete(g_part2_participant), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(dds_delete(g_part1_domain), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL(dds_delete(g_part2_domain), DDS_RETCODE_OK); +} + +CU_Test(ddssec_handshake, happy_day, .init = handshake_init, .fini = handshake_fini) +{ + validate_handshake(DDS_DOMAINID_PART1, false, NULL, false, NULL); + validate_handshake(DDS_DOMAINID_PART2, false, NULL, false, NULL); +} diff --git a/src/security/core/tests/plugin_loading.c b/src/security/core/tests/plugin_loading.c new file mode 100644 index 0000000..f6aa141 --- /dev/null +++ b/src/security/core/tests/plugin_loading.c @@ -0,0 +1,646 @@ +/* + * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include "CUnit/Test.h" +#include "dds/dds.h" +#include "dds/ddsrt/cdtors.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsi/q_misc.h" +#include "dds/security/dds_security_api_defs.h" +#include "common/config_env.h" +#include "common/test_identity.h" + +#define MAX_PARTICIPANTS_VARIABLE "MAX_PARTICIPANTS" + +static uint32_t found; + +static void logger(void *ptr, const dds_log_data_t *data) +{ + char **expected = (char **)ptr; + fputs(data->message, stdout); + for (uint32_t i = 0; expected[i] != NULL; i++) + { + if (ddsi2_patmatch(expected[i], data->message)) + { + found |= (uint32_t)(1 << i); + } + } +} + +static void set_logger_exp(const void *log_expected) +{ + found = 0; + dds_set_log_mask(DDS_LC_FATAL | DDS_LC_ERROR | DDS_LC_WARNING | DDS_LC_CONFIG); + dds_set_log_sink(&logger, (void *)log_expected); + dds_set_trace_sink(&logger, (void *)log_expected); +} + +static void reset_logger() +{ + dds_set_log_sink(NULL, NULL); + dds_set_trace_sink(NULL, NULL); +} + +CU_Test(ddssec_security_plugin_loading, all_ok, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + const char *log_expected[] = { + "DDS Security plugins have been loaded*", + NULL}; + + const char *sec_config = + "" + " finest" + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " testtext_Password_testtext" + " testtext_Dir_testtext" + " " + " " + " " + " " + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + ""; + + set_logger_exp(log_expected); + domain = dds_create_domain(0, sec_config); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, NULL, NULL); + CU_ASSERT_FATAL(participant > 0); + dds_delete(participant); + dds_delete(domain); + reset_logger(); + + CU_ASSERT_FATAL(found == 0x1); +} + +CU_Test(ddssec_security_plugin_loading, missing_finalize, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + const char *log_expected[] = { + "Could not find the function: finalize_test_authentication_NON_EXISTING_FUNC*", + "Could not load Authentication plugin*", + NULL}; + + const char *sec_config = + "" + " finest" + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " testtext_Password_testtext" + " testtext_Dir_testtext" + " " + " " + " " + " " + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + ""; + + set_logger_exp(log_expected); + domain = dds_create_domain(0, sec_config); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, NULL, NULL); + CU_ASSERT_EQUAL_FATAL(participant, DDS_RETCODE_ERROR); + dds_delete(domain); + reset_logger(); + + CU_ASSERT_FATAL(found == 0x3); +} + +CU_Test(ddssec_security_plugin_loading, authentication_missing_function, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + const char *log_expected[] = { + "Could not find the function for Authentication: get_shared_secret*", + "Could not load security*", + NULL}; + + const char *sec_config = + "" + " finest" + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " testtext_Password_testtext" + " testtext_Dir_testtext" + " " + " " + " " + " " + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + ""; + + set_logger_exp(log_expected); + domain = dds_create_domain(0, sec_config); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, NULL, NULL); + CU_ASSERT_EQUAL_FATAL(participant, DDS_RETCODE_ERROR); + dds_delete(domain); + reset_logger(); + + CU_ASSERT_FATAL(found == 0x3); +} + +CU_Test(ddssec_security_plugin_loading, access_control_missing_function, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + const char *log_expected[] = { + "Could not find the function for Access Control: check_create_datareader*", + "Could not load security*", + NULL}; + + const char *sec_config = + "" + " finest" + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " testtext_Password_testtext" + " testtext_Dir_testtext" + " " + " " + " " + " " + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + ""; + + set_logger_exp(log_expected); + domain = dds_create_domain(0, sec_config); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, NULL, NULL); + CU_ASSERT_EQUAL_FATAL(participant, DDS_RETCODE_ERROR); + dds_delete(domain); + reset_logger(); + + CU_ASSERT_FATAL(found == 0x3); +} + +CU_Test(ddssec_security_plugin_loading, cryptography_missing_function, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + const char *log_expected[] = { + "Could not find the function for Cryptographic: set_remote_participant_crypto_tokens*", + "Could not load security*", + NULL}; + + const char *sec_config = + "" + " finest" + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " testtext_Password_testtext" + " testtext_Dir_testtext" + " " + " " + " " + " " + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + ""; + + set_logger_exp(log_expected); + domain = dds_create_domain(0, sec_config); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, NULL, NULL); + CU_ASSERT_EQUAL_FATAL(participant, DDS_RETCODE_ERROR); + dds_delete(domain); + reset_logger(); + + CU_ASSERT_FATAL(found == 0x3); +} + +CU_Test(ddssec_security_plugin_loading, no_library_in_path, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + const char *log_expected[] = { + "Could not load Authentication library: " WRAPPERLIB_PATH("dds_security_authentication_wrapper_INVALID") ": cannot open shared object file: No such file or directory*", + "Could not load Authentication library: dlopen(" WRAPPERLIB_PATH("dds_security_authentication_wrapper_INVALID") "*", + "Could not load Authentication library: The specified module could not be found.*", + "Could not load Authentication plugin*", + "Could not load security*", + NULL}; + + const char *sec_config = + "" + " finest" + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " testtext_Password_testtext" + " testtext_Dir_testtext" + " " + " " + " " + " " + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + ""; + + set_logger_exp(log_expected); + domain = dds_create_domain(0, sec_config); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, NULL, NULL); + CU_ASSERT_EQUAL_FATAL(participant, DDS_RETCODE_ERROR); + dds_delete(domain); + reset_logger(); + + CU_ASSERT_FATAL(found == 0x19 || found == 0x1a || found == 0x1c); +} + +CU_Test(ddssec_security_plugin_loading, init_error, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + const char *log_expected[] = { + "Error occured while initializing Authentication plugin*", + "Could not load Authentication plugin*", + "Could not load security*", + NULL}; + + const char *sec_config = + "" + " finest" + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " testtext_Password_testtext" + " testtext_Dir_testtext" + " " + " " + " " + " " + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + ""; + + set_logger_exp(log_expected); + domain = dds_create_domain(0, sec_config); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, NULL, NULL); + CU_ASSERT_EQUAL_FATAL(participant, DDS_RETCODE_ERROR); + dds_delete(domain); + reset_logger(); + + CU_ASSERT_FATAL(found == 0x7); +} + +CU_Test(ddssec_security_plugin_loading, all_ok_with_props, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + dds_qos_t *qos; + const char *log_expected[] = { + "DDS Security plugins have been loaded*", + NULL}; + + unsigned char bvalue[3] = {0x01, 0x02, 0x03}; + CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); + dds_qset_prop(qos, "test.prop1", "testtext_value1_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PRIV_KEY, "testtext_PrivateKey_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CERT, "testtext_IdentityCertificate_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:Permissions_CA.pem"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:Governance.p7s"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:Permissions.p7s"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PASSWORD, "testtext_Password_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR, "file:/test/dir"); + + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_PATH, WRAPPERLIB_PATH("dds_security_authentication_wrapper")); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_INIT, "init_test_authentication_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE, "finalize_test_authentication_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_PATH, WRAPPERLIB_PATH("dds_security_cryptography_wrapper")); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_INIT, "init_test_cryptography_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE, "finalize_test_cryptography_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_PATH, WRAPPERLIB_PATH("dds_security_access_control_wrapper")); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_INIT, "init_test_access_control_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE, "finalize_test_access_control_all_ok"); + + dds_qset_prop(qos, "test.prop2", "testtext_value2_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); + dds_qset_bprop(qos, "test.bprop1", bvalue, 3); + + set_logger_exp(log_expected); + domain = dds_create_domain(0, "finest"); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, qos, NULL); + CU_ASSERT_FATAL(participant > 0); + dds_delete(participant); + dds_delete(domain); + dds_delete_qos(qos); + reset_logger(); + + CU_ASSERT_FATAL(found == 0x1); +} + +CU_Test(ddssec_security_plugin_loading, missing_plugin_property_with_props, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + dds_qos_t *qos; + const char *log_expected[] = { + "*using security settings from QoS*", + "*required security property dds.sec.auth.library.init missing in Property QoS*", + NULL}; + + unsigned char bvalue[3] = {0x01, 0x02, 0x03}; + CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); + dds_qset_prop(qos, "test.prop1", "testtext_value1_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PRIV_KEY, "testtext_PrivateKey_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CERT, "testtext_IdentityCertificate_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:Permissions_CA.pem"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:Governance.p7s"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:Permissions.p7s"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PASSWORD, "testtext_Password_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR, "file:/test/dir"); + + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_PATH, "dds_security_authentication_all_ok"); + // missing: dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_INIT, "init_authentication"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE, "finalize_authentication"); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_PATH, "dds_security_cryptography_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_INIT, "init_crypto"); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE, "finalize_crypto"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_PATH, "dds_security_access_control_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_INIT, "init_access_control"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE, "finalize_access_control"); + + dds_qset_prop(qos, "test.prop2", "testtext_value2_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); + dds_qset_bprop(qos, "test.bprop1", bvalue, 3); + + set_logger_exp(log_expected); + domain = dds_create_domain(0, "finest"); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(0, qos, NULL); + CU_ASSERT_EQUAL_FATAL(participant, DDS_RETCODE_ERROR); + dds_delete_qos(qos); + dds_delete(domain); + reset_logger(); + + CU_ASSERT_FATAL(found == 0x3); +} + +CU_Test(ddssec_security_plugin_loading, empty_plugin_property_with_props, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + dds_qos_t *qos; + const char *log_expected[] = { + "*using security settings from QoS*", + "*required security property dds.sec.auth.library.finalize missing in Property QoS*", + NULL}; + + unsigned char bvalue[3] = {0x01, 0x02, 0x03}; + CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); + dds_qset_prop(qos, "test.prop1", "testtext_value1_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PRIV_KEY, "testtext_PrivateKey_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CERT, "testtext_IdentityCertificate_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:Permissions_CA.pem"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:Governance.p7s"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:Permissions.p7s"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PASSWORD, "testtext_Password_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR, "file:/test/dir"); + + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_PATH, "dds_security_authentication_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_INIT, "init_authentication"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE, ""); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_PATH, "dds_security_cryptography_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_INIT, "init_crypto"); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE, "finalize_crypto"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_PATH, "dds_security_access_control_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_INIT, "init_access_control"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE, "finalize_access_control"); + + dds_qset_prop(qos, "test.prop2", "testtext_value2_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); + dds_qset_bprop(qos, "test.bprop1", bvalue, 3); + + set_logger_exp(log_expected); + domain = dds_create_domain(0, "finest"); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(DDS_DOMAIN_DEFAULT, qos, NULL); + CU_ASSERT_EQUAL_FATAL(participant, DDS_RETCODE_ERROR); + dds_delete_qos(qos); + dds_delete(domain); + reset_logger(); + + CU_ASSERT_FATAL(found == 0x3); +} + +CU_Test(ddssec_security_plugin_loading, missing_security_property_with_props, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain, participant; + dds_qos_t *qos; + const char *log_expected[] = { + "*using security settings from QoS*", + "*required security property dds.sec.access.permissions missing in Property QoS*", + NULL}; + + unsigned char bvalue[3] = {0x01, 0x02, 0x03}; + CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); + dds_qset_prop(qos, "test.prop1", "testtext_value1_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PRIV_KEY, "testtext_PrivateKey_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CERT, "testtext_IdentityCertificate_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:Permissions_CA.pem"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:Governance.p7s"); + /* we ignore permissions for testing + //dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:Permissions.p7s"); */ + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PASSWORD, "testtext_Password_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR, "file:/test/dir"); + + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_PATH, "dds_security_authentication_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_INIT, "init_authentication"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE, "finalize_authentication"); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_PATH, "dds_security_cryptography_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_INIT, "init_crypto"); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE, "finalize_crypto"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_PATH, "dds_security_access_control_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_INIT, "init_access_control"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE, "finalize_access_control"); + + dds_qset_prop(qos, "test.prop2", "testtext_value2_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); + dds_qset_bprop(qos, "test.bprop1", bvalue, 3); + + set_logger_exp(log_expected); + domain = dds_create_domain(0, "finest"); + CU_ASSERT_FATAL(domain > 0); + participant = dds_create_participant(DDS_DOMAIN_DEFAULT, qos, NULL); + CU_ASSERT_EQUAL_FATAL(participant, DDS_RETCODE_ERROR); + dds_delete_qos(qos); + dds_delete(domain); + reset_logger(); + + CU_ASSERT_FATAL(found == 0x3); +} + +CU_Test(ddssec_security_plugin_loading, multiple_domains_different_config, .init = ddsrt_init, .fini = ddsrt_fini) +{ + dds_entity_t domain1, domain2, participant1, participant2, participant3; + dds_qos_t *qos; + const char *log_expected[] = { + "*using security settings from configuration*", + "*using security settings from QoS*", + "DDS Security plugins have been loaded*", + "*security is already loaded for this domain*", + NULL}; + + const char *sec_config = + "" + " finest" + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " testtext_Password_testtext" + " testtext_Dir_testtext" + " " + " " + " " + " " + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + "" + "" + " finest" + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " testtext_Password_testtext" + " testtext_Dir_testtext" + " " + " " + " " + " " + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + ""; + + set_logger_exp(log_expected); + + domain1 = dds_create_domain(1, sec_config); + CU_ASSERT_FATAL(domain1 > 0); + domain2 = dds_create_domain(2, sec_config); + CU_ASSERT_FATAL(domain2 > 0); + + /* Create the qos */ + CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PRIV_KEY, "testtext_PrivateKey_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CERT, "testtext_IdentityCertificate_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:Permissions_CA.pem"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:Governance.p7s"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:Permissions.p7s"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PASSWORD, "testtext_Password_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR, "file:/test/dir"); + + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_PATH, WRAPPERLIB_PATH("dds_security_authentication_wrapper")); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_INIT, "init_test_authentication_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE, "finalize_test_authentication_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_PATH, WRAPPERLIB_PATH("dds_security_cryptography_wrapper")); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_INIT, "init_test_cryptography_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE, "finalize_test_cryptography_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_PATH, WRAPPERLIB_PATH("dds_security_access_control_wrapper")); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_INIT, "init_test_access_control_all_ok"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE, "finalize_test_access_control_all_ok"); + + participant1 = dds_create_participant(1, NULL, NULL); + participant2 = dds_create_participant(2, NULL, NULL); + participant3 = dds_create_participant(2, qos, NULL); + CU_ASSERT_FATAL(participant1 > 0); + CU_ASSERT_FATAL(participant2 > 0); + CU_ASSERT_FATAL(participant3 > 0); + dds_delete_qos(qos); + dds_delete(domain1); + dds_delete(domain2); + reset_logger(); + + CU_ASSERT_FATAL(found == 0xf); +} diff --git a/src/security/core/tests/plugin_loading/CMakeLists.txt b/src/security/core/tests/plugin_loading/CMakeLists.txt deleted file mode 100644 index 0eda38b..0000000 --- a/src/security/core/tests/plugin_loading/CMakeLists.txt +++ /dev/null @@ -1,85 +0,0 @@ - # -# Copyright(c) 2006 to 2019 ADLINK Technology Limited and others -# -# This program and the accompanying materials are made available under the -# terms of the Eclipse Public License v. 2.0 which is available at -# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License -# v. 1.0 which is available at -# http://www.eclipse.org/org/documents/edl-v10.php. -# -# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause -# -include(GenerateExportHeader) -include(CUnit) - -set(security_plugin_loading_test_sources - "security_config.c" - "plugin_loading.c") - -add_cunit_executable(cunit_security_plugin_loading ${security_plugin_loading_test_sources}) -target_include_directories( - cunit_security_plugin_loading PRIVATE - "$" - "$>" - "$>" - "$" - "$" - "$") - -target_link_libraries(cunit_security_plugin_loading PRIVATE ddsc security_api) -target_include_directories(cunit_security_plugin_loading PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") - -set(CUnit_plugin_mock_dir ".") - -# Let the cunit application know the location and name of the library. -configure_file("config_env.h.in" "config_env.h") - -function(add_mock libname casename) - PREPEND(srcs_mock_authentication_all_ok "${CMAKE_CURRENT_LIST_DIR}/plugin_mock/${casename}" - "mock_${libname}.c") - add_library("dds_security_${casename}" SHARED "") - - generate_export_header( - "dds_security_${casename}" - BASE_NAME SECURITY - EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/dds/security/${casename}_export.h") - - set_target_properties( - "dds_security_${casename}" - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR} - RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR} - RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR} - RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR} - LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR} - LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR} - LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR}) - - #find_package(OpenSSL ) - #target_link_libraries("dds_security_${casename}" PUBLIC OpenSSL::SSL) - target_link_libraries("dds_security_${casename}" PUBLIC ddsc) - - target_sources("dds_security_${casename}" - PRIVATE - ${srcs_mock_authentication_all_ok}) - target_include_directories("dds_security_${casename}" - PUBLIC - "$>" - "$>" - "$>" - "$") -endfunction() - -#PLUGIN MOCKS -add_mock(authentication authentication_all_ok) -add_mock(authentication authentication_all_ok_other) -add_mock(authentication authentication_missing_function) -add_mock(authentication authentication_finalize_error) -add_mock(access_control access_control_all_ok) -add_mock(access_control access_control_missing_function) -add_mock(cryptography cryptography_all_ok) -add_mock(cryptography cryptography_missing_function) -add_mock(authentication authentication_init_error) diff --git a/src/security/core/tests/plugin_loading/config_env.h.in b/src/security/core/tests/plugin_loading/config_env.h.in deleted file mode 100644 index 6d05734..0000000 --- a/src/security/core/tests/plugin_loading/config_env.h.in +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef CONFIG_ENV_H -#define CONFIG_ENV_H - -#define CONFIG_ENV_PLUGIN_MOCK_DIR "@CUnit_plugin_mock_dir@" -#define TEST_LIB_DIR "@test_lib_dir@" -#define TEST_LIB_SEP "@test_lib_sep@" -#define TEST_LIB_SUFFIX "@CMAKE_SHARED_LIBRARY_SUFFIX@" -#define TEST_LIB_PREFIX "@CMAKE_SHARED_LIBRARY_PREFIX@" -#define CONFIG_PLUGIN_MOCK_DIR "@test_lib_dir@" -#define CONFIG_LIB_SUFFIX "@CMAKE_SHARED_LIBRARY_SUFFIX@" -#define CONFIG_LIB_PREFIX "@CMAKE_SHARED_LIBRARY_PREFIX@" -#define CONFIG_LIB_SEP "@test_lib_sep@" - -#endif /* CONFIG_ENV_H */ diff --git a/src/security/core/tests/plugin_loading/plugin_loading.c b/src/security/core/tests/plugin_loading/plugin_loading.c deleted file mode 100644 index 09c6c0b..0000000 --- a/src/security/core/tests/plugin_loading/plugin_loading.c +++ /dev/null @@ -1,911 +0,0 @@ -/* - * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include -#include - -#include "dds/dds.h" -#include "CUnit/Test.h" -#include "config_env.h" - -#include "dds/version.h" -#include "dds/ddsrt/cdtors.h" -#include "dds/ddsrt/environ.h" -#include "dds/ddsrt/heap.h" -#include "plugin_mock_common.h" -//#include "dds/ddsi/ddsi_security_omg.h" - -#define FORCE_ENV - -#define URI_VARIABLE DDS_PROJECT_NAME_NOSPACE_CAPS"_URI" -#define MAX_PARTICIPANTS_VARIABLE "MAX_PARTICIPANTS" -static bool print_log=true; - -static int patmatch (const char *pat, const char *str) -{ - while (*pat) - { - if (*pat == '?') - { - /* any character will do */ - if (*str++ == 0) - { - return 0; - } - pat++; - } - else if (*pat == '*') - { - /* collapse a sequence of wildcards, requiring as many - characters in str as there are ?s in the sequence */ - while (*pat == '*' || *pat == '?') - { - if (*pat == '?' && *str++ == 0) - { - return 0; - } - pat++; - } - /* try matching on all positions where str matches pat */ - while (*str) - { - if (*str == *pat && patmatch (pat+1, str+1)) - { - return 1; - } - str++; - } - return *pat == 0; - } - else - { - /* only an exact match */ - if (*str++ != *pat++) - { - return 0; - } - } - } - return *str == 0; -} - - -/* - * The 'found' variable will contain flags related to the expected log - * messages that were received. - * Using flags will allow to show that when message isn't received, - * which one it was. - */ -static uint32_t found; -static void logger(void *ptr, const dds_log_data_t *data) { - char **expected = (char **) ptr; - if (print_log) { - fputs(data->message, stdout); - } - for (uint32_t i = 0; expected[i] != NULL; i++) { - if (patmatch(expected[i], data->message)) { - found |= (uint32_t)(1 << i); - } - } -} - - -CU_Test(ddssec_security_plugin_loading, all_ok, .init = ddsrt_init, .fini = ddsrt_fini) { - - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - "DDS Security plugins have been loaded*", - NULL - }; - - const char *sec_config = - "<"DDS_PROJECT_NAME">" - "" - "finest" - "" - "" - "" - ""TEST_IDENTITY_CERTIFICATE_ALL_OK"" - ""TEST_CA_CERTIFICATE_ALL_OK"" - ""TEST_PRIVATE_KEY_ALL_OK"" - "testtext_Password_testtext" - "testtext_Dir_testtext" - "" - "" - "" - "" - "" - "" - "file:Governance.p7s" - "file:Permissions_CA.pem" - "file:Permissions.p7s" - "" - "" - "" - ""; - - - dds_entity_t participant; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_INFO| DDS_LC_TRACE); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create participant with security elements. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, sec_config); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - dds_set_log_sink(NULL,NULL); - dds_set_trace_sink(NULL,NULL); - ddsrt_setenv(URI_VARIABLE, ""); - CU_ASSERT_FATAL(found == 0x1); - - - dds_delete(participant); - -} - -CU_Test(ddssec_security_plugin_loading, missing_finalize, .init = ddsrt_init, .fini = ddsrt_fini) { - - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - "Could not find the function: finalize_authentication*", - "Could not load Authentication plugin*", - NULL - }; - - const char *sec_config = - "<"DDS_PROJECT_NAME">" - "" - "finest" - "" - "" - "" - "testtext_IdentityCertificate_testtext" - "testtext_IdentityCA_testtext" - "testtext_PrivateKey_testtext" - "testtext_Password_testtext" - "testtext_Dir_testtext" - "" - "" - "" - "" - "" - "" - "file:Governance.p7s" - "file:Permissions_CA.pem" - "file:Permissions.p7s" - "" - "" - "" - ""; - - - dds_entity_t participant; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create participant with security elements. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, sec_config); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - dds_set_log_sink( NULL, NULL ); - dds_set_trace_sink(NULL, NULL); - ddsrt_setenv(URI_VARIABLE, ""); -#ifdef PR304_MERGED - /* It is better dds to return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY instead of DDS_RETCODE_ERROR - CU_ASSERT_FATAL( participant == DDS_RETCODE_NOT_ALLOWED_BY_SECURITY ); */ - CU_ASSERT_FATAL( participant == DDS_RETCODE_ERROR ); -#else - dds_delete(participant); -#endif - CU_ASSERT_FATAL(found == 0x3); - -} - - -CU_Test(ddssec_security_plugin_loading, authentication_missing_function, .init = ddsrt_init, .fini = ddsrt_fini) { - - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - "Could not find the function for Authentication: get_shared_secret*", - "Could not load security*", - NULL - }; - - const char *sec_config = - "<"DDS_PROJECT_NAME">" - "" - "finest" - "" - "" - "" - "testtext_IdentityCertificate_testtext" - "testtext_IdentityCA_testtext" - "testtext_PrivateKey_testtext" - "testtext_Password_testtext" - "testtext_Dir_testtext" - "" - "" - "" - "" - "" - "" - "file:Governance.p7s" - "file:Permissions_CA.pem" - "file:Permissions.p7s" - "" - "" - "" - ""; - - - dds_entity_t participant; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_ERROR); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create participant with security elements. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, sec_config); - print_log = true; - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - ddsrt_setenv(URI_VARIABLE, ""); -#ifdef PR304_MERGED - /* It is better dds to return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY instead of DDS_RETCODE_ERROR - CU_ASSERT_FATAL( participant == DDS_RETCODE_NOT_ALLOWED_BY_SECURITY ); */ - CU_ASSERT_FATAL( participant == DDS_RETCODE_ERROR ); -#else - dds_delete(participant); -#endif - CU_ASSERT_FATAL(found == 0x3); - - -} - - -CU_Test(ddssec_security_plugin_loading, access_control_missing_function, .init = ddsrt_init, .fini = ddsrt_fini) { - - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - "Could not find the function for Access Control: check_create_datareader*", - "Could not load security*", - NULL - }; - - const char *sec_config = - "<"DDS_PROJECT_NAME">" - "" - "finest" - "" - "" - "" - "testtext_IdentityCertificate_testtext" - "testtext_IdentityCA_testtext" - "testtext_PrivateKey_testtext" - "testtext_Password_testtext" - "testtext_Dir_testtext" - "" - "" - "" - "" - "" - "" - "file:Governance.p7s" - "file:Permissions_CA.pem" - "file:Permissions.p7s" - "" - "" - "" - ""; - - - dds_entity_t participant; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create participant with security elements. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, sec_config); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - ddsrt_setenv(URI_VARIABLE, ""); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - -#ifdef PR304_MERGED - /* It is better dds to return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY instead of DDS_RETCODE_ERROR - CU_ASSERT_FATAL( participant == DDS_RETCODE_NOT_ALLOWED_BY_SECURITY ); */ - CU_ASSERT_FATAL( participant == DDS_RETCODE_ERROR ); -#else - dds_delete(participant); -#endif - CU_ASSERT_FATAL(found == 0x3); - - - -} - - -CU_Test(ddssec_security_plugin_loading, cryptography_missing_function, .init = ddsrt_init, .fini = ddsrt_fini) { - - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - "Could not find the function for Cryptographic: set_remote_participant_crypto_tokens*", - "Could not load security*", - NULL - }; - - const char *sec_config = - "<"DDS_PROJECT_NAME">" - "" - "finest" - "" - "" - "" - "testtext_IdentityCertificate_testtext" - "testtext_IdentityCA_testtext" - "testtext_PrivateKey_testtext" - "testtext_Password_testtext" - "testtext_Dir_testtext" - "" - "" - "" - "" - "" - "" - "file:Governance.p7s" - "file:Permissions_CA.pem" - "file:Permissions.p7s" - "" - "" - "" - ""; - - - dds_entity_t participant; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create participant with security elements. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, sec_config); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - ddsrt_setenv(URI_VARIABLE, ""); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - -#ifdef PR304_MERGED - /* It is better dds to return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY instead of DDS_RETCODE_ERROR - CU_ASSERT_FATAL( participant == DDS_RETCODE_NOT_ALLOWED_BY_SECURITY ); */ - CU_ASSERT_FATAL( participant == DDS_RETCODE_ERROR ); -#else - dds_delete(participant); -#endif - CU_ASSERT_FATAL(found == 0x3); - - - -} - - -CU_Test(ddssec_security_plugin_loading, no_library_in_path, .init = ddsrt_init, .fini = ddsrt_fini) { - - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - "Could not load Authentication library: no_library_in_path: cannot open shared object file: No such file or directory*", - "Could not load Authentication library: *not*found*", - "Could not load Authentication plugin*", - "Could not load security*", - NULL - }; - - const char *sec_config = - "<"DDS_PROJECT_NAME">" - "" - "finest" - "" - "" - "" - "testtext_IdentityCertificate_testtext" - "testtext_IdentityCA_testtext" - "testtext_PrivateKey_testtext" - "testtext_Password_testtext" - "testtext_Dir_testtext" - "" - "" - "" - "" - "" - "" - "file:Governance.p7s" - "file:Permissions_CA.pem" - "file:Permissions.p7s" - "" - "" - "" - ""; - - - dds_entity_t participant; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_INFO| DDS_LC_TRACE); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create participant with security elements. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, sec_config); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - ddsrt_setenv(URI_VARIABLE, ""); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - -#ifdef PR304_MERGED - /* It is better dds to return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY instead of DDS_RETCODE_ERROR - CU_ASSERT_FATAL( participant == DDS_RETCODE_NOT_ALLOWED_BY_SECURITY ); */ - CU_ASSERT_FATAL( participant == DDS_RETCODE_ERROR ); -#else - dds_delete(participant); -#endif - - CU_ASSERT_FATAL(found == 0xd || found == 0xe); - - dds_delete(participant); - -} - - -CU_Test(ddssec_security_plugin_loading, init_error, .init = ddsrt_init, .fini = ddsrt_fini) { - - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - "Error occured while initializing Authentication plugin*", - "Could not load Authentication plugin*", - "Could not load security*", - NULL - }; - - const char *sec_config = - "<"DDS_PROJECT_NAME">" - "" - "finest" - "" - "" - "" - "testtext_IdentityCertificate_testtext" - "testtext_IdentityCA_testtext" - "testtext_PrivateKey_testtext" - "testtext_Password_testtext" - "testtext_Dir_testtext" - "" - "" - "" - "" - "" - "" - "file:Governance.p7s" - "file:Permissions_CA.pem" - "file:Permissions.p7s" - "" - "" - "" - ""; - - - dds_entity_t participant; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_INFO| DDS_LC_TRACE); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create participant with security elements. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, sec_config); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - ddsrt_setenv(URI_VARIABLE, ""); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - -#ifdef PR304_MERGED - /* It is better dds to return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY instead of DDS_RETCODE_ERROR - CU_ASSERT_FATAL( participant == DDS_RETCODE_NOT_ALLOWED_BY_SECURITY ); */ - CU_ASSERT_FATAL( participant == DDS_RETCODE_ERROR ); -#else - dds_delete(participant); -#endif - CU_ASSERT_FATAL(found == 0x7); - - - dds_delete(participant); - -} -CU_Test(ddssec_security_plugin_loading, all_ok_with_props, .init = ddsrt_init, .fini = ddsrt_fini) { - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - "DDS Security plugins have been loaded*", - NULL - }; - - dds_entity_t participant; - dds_qos_t * qos; - - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_INFO); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create the qos */ - unsigned char bvalue[3] = { 0x01, 0x02, 0x03 }; - CU_ASSERT_FATAL ((qos = dds_create_qos()) != NULL); - dds_qset_prop (qos, "test.prop1", "testtext_value1_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_PRIV_KEY, "testtext_PrivateKey_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_IDENTITY_CERT, "testtext_IdentityCertificate_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:Permissions_CA.pem"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:Governance.p7s"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:Permissions.p7s"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_PASSWORD, "testtext_Password_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR, "file:/test/dir"); - - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_LIBRARY_PATH, "dds_security_authentication_all_ok"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_LIBRARY_INIT, "init_authentication"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE, "finalize_authentication"); - dds_qset_prop (qos, DDS_SEC_PROP_CRYPTO_LIBRARY_PATH, "dds_security_cryptography_all_ok"); - dds_qset_prop (qos, DDS_SEC_PROP_CRYPTO_LIBRARY_INIT, "init_crypto"); - dds_qset_prop (qos, DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE, "finalize_crypto"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_LIBRARY_PATH, "dds_security_access_control_all_ok"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_LIBRARY_INIT, "init_access_control"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE, "finalize_access_control"); - - dds_qset_prop (qos, "test.prop2", "testtext_value2_testtext"); - - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); - - dds_qset_bprop (qos, "test.bprop1", bvalue, 3); - - /* Create participant with security config in qos. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, "finest"); - CU_ASSERT_FATAL ((participant = dds_create_participant(DDS_DOMAIN_DEFAULT, qos, NULL)) > 0); - ddsrt_setenv(URI_VARIABLE, ""); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - - dds_delete(participant); - dds_delete_qos(qos); - CU_ASSERT_FATAL(found == 0x1); -} - - - -CU_Test(ddssec_security_plugin_loading, missing_plugin_property_with_props, .init = ddsrt_init, .fini = ddsrt_fini) { - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - "*using security settings from QoS*", - "*required security property dds.sec.auth.library.init missing in Property QoS*", - NULL - }; - - dds_entity_t participant; - dds_qos_t * qos; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_INFO|DDS_LC_ERROR); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create the qos */ - unsigned char bvalue[3] = { 0x01, 0x02, 0x03 }; - CU_ASSERT_FATAL ((qos = dds_create_qos()) != NULL); - dds_qset_prop (qos, "test.prop1", "testtext_value1_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_PRIV_KEY, "testtext_PrivateKey_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_IDENTITY_CERT, "testtext_IdentityCertificate_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:Permissions_CA.pem"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:Governance.p7s"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:Permissions.p7s"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_PASSWORD, "testtext_Password_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR, "file:/test/dir"); - - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_LIBRARY_PATH, "dds_security_authentication_all_ok"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE, "finalize_authentication"); - dds_qset_prop (qos, DDS_SEC_PROP_CRYPTO_LIBRARY_PATH, "dds_security_cryptography_all_ok"); - dds_qset_prop (qos, DDS_SEC_PROP_CRYPTO_LIBRARY_INIT, "init_crypto"); - dds_qset_prop (qos, DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE, "finalize_crypto"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_LIBRARY_PATH, "dds_security_access_control_all_ok"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_LIBRARY_INIT, "init_access_control"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE, "finalize_access_control"); - - dds_qset_prop (qos, "test.prop2", "testtext_value2_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); - dds_qset_bprop (qos, "test.bprop1", bvalue, 3); - - /* Create participant with security config in qos. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, "finest"); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, qos, NULL); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - ddsrt_setenv(URI_VARIABLE, ""); -#ifdef PR304_MERGED - /* It is better dds to return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY instead of DDS_RETCODE_ERROR - CU_ASSERT_FATAL( participant == DDS_RETCODE_NOT_ALLOWED_BY_SECURITY ); */ - CU_ASSERT_FATAL( participant == DDS_RETCODE_ERROR ); -#else - dds_delete(participant); -#endif - CU_ASSERT_FATAL(found == 0x3); - dds_delete_qos(qos); -} - - - -CU_Test(ddssec_security_plugin_loading, empty_plugin_property_with_props, .init = ddsrt_init, .fini = ddsrt_fini) { - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - "*using security settings from QoS*", - "*required security property dds.sec.auth.library.finalize missing in Property QoS*", - NULL - }; - - dds_entity_t participant; - dds_qos_t * qos; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_INFO|DDS_LC_ERROR); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create the qos */ - unsigned char bvalue[3] = { 0x01, 0x02, 0x03 }; - CU_ASSERT_FATAL ((qos = dds_create_qos()) != NULL); - dds_qset_prop (qos, "test.prop1", "testtext_value1_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_PRIV_KEY, "testtext_PrivateKey_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_IDENTITY_CERT, "testtext_IdentityCertificate_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:Permissions_CA.pem"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:Governance.p7s"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:Permissions.p7s"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_PASSWORD, "testtext_Password_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR, "file:/test/dir"); - - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_LIBRARY_PATH, "dds_security_authentication_all_ok"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_LIBRARY_INIT, "init_authentication"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE, ""); - dds_qset_prop (qos, DDS_SEC_PROP_CRYPTO_LIBRARY_PATH, "dds_security_cryptography_all_ok"); - dds_qset_prop (qos, DDS_SEC_PROP_CRYPTO_LIBRARY_INIT, "init_crypto"); - dds_qset_prop (qos, DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE, "finalize_crypto"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_LIBRARY_PATH, "dds_security_access_control_all_ok"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_LIBRARY_INIT, "init_access_control"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE, "finalize_access_control"); - - dds_qset_prop (qos, "test.prop2", "testtext_value2_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); - dds_qset_bprop (qos, "test.bprop1", bvalue, 3); - - /* Create participant with security config in qos. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, "finest"); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, qos, NULL); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - ddsrt_setenv(URI_VARIABLE, ""); -#ifdef PR304_MERGED - /* It is better dds to return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY instead of DDS_RETCODE_ERROR - CU_ASSERT_FATAL( participant == DDS_RETCODE_NOT_ALLOWED_BY_SECURITY ); */ - CU_ASSERT_FATAL( participant == DDS_RETCODE_ERROR ); -#else - dds_delete(participant); -#endif - CU_ASSERT_FATAL(found == 0x3); - dds_delete_qos(qos); -} - - -CU_Test(ddssec_security_plugin_loading, missing_security_property_with_props, .init = ddsrt_init, .fini = ddsrt_fini) { - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - "*using security settings from QoS*", - "*required security property dds.sec.access.permissions missing in Property QoS*", - NULL - }; - - - dds_entity_t participant; - dds_qos_t * qos; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_INFO|DDS_LC_ERROR); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create the qos */ - unsigned char bvalue[3] = { 0x01, 0x02, 0x03 }; - CU_ASSERT_FATAL ((qos = dds_create_qos()) != NULL); - dds_qset_prop (qos, "test.prop1", "testtext_value1_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_PRIV_KEY, "testtext_PrivateKey_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_IDENTITY_CERT, "testtext_IdentityCertificate_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:Permissions_CA.pem"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:Governance.p7s"); - /* we ignore permissions for testing - //dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:Permissions.p7s"); */ - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_PASSWORD, "testtext_Password_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR, "file:/test/dir"); - - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_LIBRARY_PATH, "dds_security_authentication_all_ok"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_LIBRARY_INIT, "init_authentication"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE, "finalize_authentication"); - dds_qset_prop (qos, DDS_SEC_PROP_CRYPTO_LIBRARY_PATH, "dds_security_cryptography_all_ok"); - dds_qset_prop (qos, DDS_SEC_PROP_CRYPTO_LIBRARY_INIT, "init_crypto"); - dds_qset_prop (qos, DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE, "finalize_crypto"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_LIBRARY_PATH, "dds_security_access_control_all_ok"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_LIBRARY_INIT, "init_access_control"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE, "finalize_access_control"); - - dds_qset_prop (qos, "test.prop2", "testtext_value2_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); - dds_qset_bprop (qos, "test.bprop1", bvalue, 3); - - /* Create participant with security config in qos. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, "finest"); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, qos, NULL); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - ddsrt_setenv(URI_VARIABLE, ""); -#ifdef PR304_MERGED - /* It is better dds to return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY instead of DDS_RETCODE_ERROR - CU_ASSERT_FATAL( participant == DDS_RETCODE_NOT_ALLOWED_BY_SECURITY ); */ - CU_ASSERT_FATAL( participant == DDS_RETCODE_ERROR ); -#else - dds_delete(participant); -#endif - CU_ASSERT_FATAL(found == 0x3); - dds_delete_qos(qos); -} - - - - -CU_Test(ddssec_security_plugin_loading, multiple_domains_different_config, .init = ddsrt_init, .fini = ddsrt_fini) { - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - "*using security settings from configuration*", - "*using security settings from QoS*", - "DDS Security plugins have been loaded*", - "*security is already loaded for this domain*", - NULL - }; - - const char *sec_config = - "<"DDS_PROJECT_NAME">" - "" - "finest" - "" - "" - "" - "testtext_IdentityCertificate_testtext" - "testtext_IdentityCA_testtext" - "testtext_PrivateKey_testtext" - "testtext_Password_testtext" - "testtext_Dir_testtext" - "" - "" - "" - "" - "" - "" - "file:Governance.p7s" - "file:Permissions_CA.pem" - "file:Permissions.p7s" - "" - "" - "" - "" - "finest" - "" - "" - "" - "testtext_IdentityCertificate_testtext" - "testtext_IdentityCA_testtext" - "testtext_PrivateKey_testtext" - "testtext_Password_testtext" - "testtext_Dir_testtext" - "" - "" - "" - "" - "" - "" - "file:Governance.p7s" - "file:Permissions_CA.pem" - "file:Permissions.p7s" - "" - "" - "" - ""; - - - dds_entity_t participant1, participant2, participant3; - dds_qos_t * qos; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_INFO|DDS_LC_ERROR); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create the qos */ - unsigned char bvalue[3] = { 0x01, 0x02, 0x03 }; - CU_ASSERT_FATAL ((qos = dds_create_qos()) != NULL); - dds_qset_prop (qos, "test.prop1", "testtext_value1_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_PRIV_KEY, "testtext_PrivateKey_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_IDENTITY_CERT, "testtext_IdentityCertificate_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:Permissions_CA.pem"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:Governance.p7s"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:Permissions.p7s"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_PASSWORD, "testtext_Password_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR, "file:/test/dir"); - - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_LIBRARY_PATH, "dds_security_authentication_all_ok_other"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_LIBRARY_INIT, "init_authentication"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE, "finalize_authentication"); - dds_qset_prop (qos, DDS_SEC_PROP_CRYPTO_LIBRARY_PATH, "dds_security_cryptography_all_ok"); - dds_qset_prop (qos, DDS_SEC_PROP_CRYPTO_LIBRARY_INIT, "init_crypto"); - dds_qset_prop (qos, DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE, "finalize_crypto"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_LIBRARY_PATH, "dds_security_access_control_all_ok"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_LIBRARY_INIT, "init_access_control"); - dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE, "finalize_access_control"); - - dds_qset_prop (qos, "test.prop2", "testtext_value2_testtext"); - dds_qset_prop (qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); - dds_qset_bprop (qos, "test.bprop1", bvalue, 3); - - /* Create participant with security config in qos. */ - found = 0; - print_log = true; - ddsrt_setenv(URI_VARIABLE, sec_config); - participant1 = dds_create_participant(1, NULL, NULL); - participant2 = dds_create_participant(2, qos, NULL); - participant3 = dds_create_participant(2, NULL, NULL); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - ddsrt_setenv(URI_VARIABLE, ""); -#ifdef PR304_MERGED - /* It is better dds to return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY instead of DDS_RETCODE_ERROR - CU_ASSERT_FATAL( participant1 == DDS_RETCODE_NOT_ALLOWED_BY_SECURITY ); */ - CU_ASSERT_FATAL( participant1 == DDS_RETCODE_ERROR ); -#else - dds_delete(participant1); - dds_delete(participant2); - dds_delete(participant3); -#endif - CU_ASSERT_FATAL(found == 0xf); - dds_delete_qos(qos); -} diff --git a/src/security/core/tests/plugin_loading/plugin_mock/access_control_all_ok/mock_access_control.c b/src/security/core/tests/plugin_loading/plugin_mock/access_control_all_ok/mock_access_control.c deleted file mode 100644 index 322c465..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/access_control_all_ok/mock_access_control.c +++ /dev/null @@ -1,597 +0,0 @@ -/* - * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include "dds/security/dds_security_api.h" -#include "dds/ddsrt/heap.h" -#include "dds/ddsrt/misc.h" -#include "mock_access_control.h" -#include -#include -#include - -/** - * Implementation structure for storing encapsulated members of the instance - * while giving only the interface definition to user - */ - -typedef struct dds_security_access_control_impl { - dds_security_access_control base; - int member; -} dds_security_access_control_impl; - -/** - * Function implementations - */ - -DDS_Security_PermissionsHandle validate_local_permissions( - dds_security_access_control *instance, - const dds_security_authentication *auth_plugin, - const DDS_Security_IdentityHandle identity, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(auth_plugin); - DDSRT_UNUSED_ARG(auth_plugin); - DDSRT_UNUSED_ARG(identity); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(participant_qos); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return 1; -} - -DDS_Security_PermissionsHandle validate_remote_permissions( - dds_security_access_control *instance, - const dds_security_authentication *auth_plugin, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityHandle remote_identity_handle, - const DDS_Security_PermissionsToken *remote_permissions_token, - const DDS_Security_AuthenticatedPeerCredentialToken *remote_credential_token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(auth_plugin); - DDSRT_UNUSED_ARG(local_identity_handle); - DDSRT_UNUSED_ARG(remote_identity_handle); - DDSRT_UNUSED_ARG(remote_permissions_token); - DDSRT_UNUSED_ARG(remote_credential_token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return 0; -} - -DDS_Security_boolean check_create_participant( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, const DDS_Security_Qos *participant_qos, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(participant_qos); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_create_datawriter( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, const char *topic_name, - const DDS_Security_Qos *writer_qos, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTags *data_tag, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(writer_qos); - DDSRT_UNUSED_ARG(partition); - DDSRT_UNUSED_ARG(data_tag); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_create_datareader( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, const char *topic_name, - const DDS_Security_Qos *reader_qos, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTags *data_tag, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(reader_qos); - DDSRT_UNUSED_ARG(partition); - DDSRT_UNUSED_ARG(data_tag); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_create_topic( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, const char *topic_name, - const DDS_Security_Qos *qos, DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(qos); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_local_datawriter_register_instance( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *writer, const DDS_Security_DynamicData *key, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(writer); - DDSRT_UNUSED_ARG(key); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_local_datawriter_dispose_instance( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *writer, const DDS_Security_DynamicData key, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(writer); - DDSRT_UNUSED_ARG(key); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_remote_participant( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_ParticipantBuiltinTopicDataSecure *participant_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(participant_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_remote_datawriter( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(publication_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_remote_datareader( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, - DDS_Security_boolean *relay_only, DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(subscription_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - *relay_only = false; - - return true; -} - -DDS_Security_boolean check_remote_topic( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_TopicBuiltinTopicData *topic_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(topic_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_local_datawriter_match( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle writer_permissions_handle, - const DDS_Security_PermissionsHandle reader_permissions_handle, - const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, - const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(writer_permissions_handle); - DDSRT_UNUSED_ARG(reader_permissions_handle); - DDSRT_UNUSED_ARG(publication_data); - DDSRT_UNUSED_ARG(subscription_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_local_datareader_match( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle reader_permissions_handle, - const DDS_Security_PermissionsHandle writer_permissions_handle, - const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, - const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(reader_permissions_handle); - DDSRT_UNUSED_ARG(writer_permissions_handle); - DDSRT_UNUSED_ARG(subscription_data); - DDSRT_UNUSED_ARG(publication_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_remote_datawriter_register_instance( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *reader, - const DDS_Security_InstanceHandle publication_handle, - const DDS_Security_DynamicData key, - const DDS_Security_InstanceHandle instance_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(reader); - DDSRT_UNUSED_ARG(publication_handle); - DDSRT_UNUSED_ARG(key); - DDSRT_UNUSED_ARG(instance_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_remote_datawriter_dispose_instance( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *reader, - const DDS_Security_InstanceHandle publication_handle, - const DDS_Security_DynamicData key, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(reader); - DDSRT_UNUSED_ARG(publication_handle); - DDSRT_UNUSED_ARG(key); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean get_permissions_token( dds_security_access_control *instance, - DDS_Security_PermissionsToken *permissions_token, - const DDS_Security_PermissionsHandle handle, - DDS_Security_SecurityException *ex) -{ - - DDSRT_UNUSED_ARG(permissions_token); - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean get_permissions_credential_token( - dds_security_access_control *instance, - DDS_Security_PermissionsCredentialToken *permissions_credential_token, - const DDS_Security_PermissionsHandle handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_credential_token); - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean set_listener( dds_security_access_control *instance, - const dds_security_access_control_listener *listener, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(listener); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_permissions_token( dds_security_access_control *instance, - const DDS_Security_PermissionsToken *token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_permissions_credential_token( - dds_security_access_control *instance, - const DDS_Security_PermissionsCredentialToken *permissions_credential_token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_credential_token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean get_participant_sec_attributes( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - DDS_Security_ParticipantSecurityAttributes *attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean get_topic_sec_attributes( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const char *topic_name, - DDS_Security_TopicSecurityAttributes *attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean get_datawriter_sec_attributes( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const char *topic_name, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTagQosPolicy *data_tag, - DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(partition); - DDSRT_UNUSED_ARG(data_tag); - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean get_datareader_sec_attributes( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const char *topic_name, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTagQosPolicy *data_tag, - DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(partition); - DDSRT_UNUSED_ARG(data_tag); - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_participant_sec_attributes( - dds_security_access_control *instance, - const DDS_Security_ParticipantSecurityAttributes *attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_topic_sec_attributes( - dds_security_access_control *instance, - const DDS_Security_TopicSecurityAttributes *attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_datawriter_sec_attributes( - dds_security_access_control *instance, - const DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_datareader_sec_attributes( - dds_security_access_control *instance, - const DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_permissions_handle( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - - int32_t init_access_control( const char *argument, void **context) -{ - - dds_security_access_control *access_control; - - DDSRT_UNUSED_ARG(argument); - - //allocate new instance - access_control = ddsrt_malloc(sizeof(dds_security_access_control)); - memset(access_control, 0, sizeof(dds_security_access_control)); - - //assign the interface functions - access_control->validate_local_permissions = &validate_local_permissions; - - access_control->validate_remote_permissions = &validate_remote_permissions; - - access_control->check_create_participant = &check_create_participant; - - access_control->check_create_datawriter = &check_create_datawriter; - - access_control->check_create_datareader = &check_create_datareader; - - access_control->check_create_topic = &check_create_topic; - - access_control->check_local_datawriter_register_instance = - &check_local_datawriter_register_instance; - - access_control->check_local_datawriter_dispose_instance = - &check_local_datawriter_dispose_instance; - - access_control->check_remote_participant = &check_remote_participant; - - access_control->check_remote_datawriter = &check_remote_datawriter; - - access_control->check_remote_datareader = &check_remote_datareader; - - access_control->check_remote_topic = &check_remote_topic; - - access_control->check_local_datawriter_match = &check_local_datawriter_match; - - access_control->check_local_datareader_match = &check_local_datareader_match; - - access_control->check_remote_datawriter_register_instance = - &check_remote_datawriter_register_instance; - - access_control->check_remote_datawriter_dispose_instance = - &check_remote_datawriter_dispose_instance; - - access_control->get_permissions_token = &get_permissions_token; - - access_control->get_permissions_credential_token = - &get_permissions_credential_token; - - access_control->set_listener = &set_listener; - - access_control->return_permissions_token = &return_permissions_token; - - access_control->return_permissions_credential_token = - &return_permissions_credential_token; - - access_control->get_participant_sec_attributes = - &get_participant_sec_attributes; - - access_control->get_topic_sec_attributes = &get_topic_sec_attributes; - - access_control->get_datawriter_sec_attributes = - &get_datawriter_sec_attributes; - - access_control->get_datareader_sec_attributes = - &get_datareader_sec_attributes; - - access_control->return_participant_sec_attributes = - &return_participant_sec_attributes; - - access_control->return_topic_sec_attributes = - &return_topic_sec_attributes; - - access_control->return_datawriter_sec_attributes = - &return_datawriter_sec_attributes; - - access_control->return_datareader_sec_attributes = - &return_datareader_sec_attributes; - - access_control->return_permissions_handle = - &return_permissions_handle; - - //return the instance - *context = access_control; - return 0; -} - - int32_t finalize_access_control( void *context) -{ - - DDSRT_UNUSED_ARG(context); - - ddsrt_free((dds_security_access_control*) context); - return 0; -} diff --git a/src/security/core/tests/plugin_loading/plugin_mock/access_control_all_ok/mock_access_control.h b/src/security/core/tests/plugin_loading/plugin_mock/access_control_all_ok/mock_access_control.h deleted file mode 100644 index 07eb595..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/access_control_all_ok/mock_access_control.h +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -#ifndef SECURITY_ACCESS_CONTROL_ALLOK_H_ -#define SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ - -#include "dds/security/access_control_all_ok_export.h" -#include "dds/security/dds_security_api.h" - -SECURITY_EXPORT int32_t -init_access_control(const char *argument, void **context); - -SECURITY_EXPORT int32_t -finalize_access_control(void *context); - - -/** - * AccessControl Interface - */ - -DDS_Security_PermissionsHandle -validate_local_permissions - ( dds_security_access_control *instance, - const dds_security_authentication *auth_plugin, - const DDS_Security_IdentityHandle identity, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - DDS_Security_SecurityException *ex); - -DDS_Security_PermissionsHandle -validate_remote_permissions - ( dds_security_access_control *instance, - const dds_security_authentication *auth_plugin, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityHandle remote_identity_handle, - const DDS_Security_PermissionsToken *remote_permissions_token, - const DDS_Security_AuthenticatedPeerCredentialToken *remote_credential_token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_create_participant - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_create_datawriter - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_char *topic_name, - const DDS_Security_Qos *writer_qos, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTags *data_tag, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_create_datareader - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_char *topic_name, - const DDS_Security_Qos *reader_qos, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTags *data_tag, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean -check_create_topic - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_char *topic_name, - const DDS_Security_Qos *topic_qos, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_local_datawriter_register_instance - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *writer, - const DDS_Security_DynamicData *key, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_local_datawriter_dispose_instance - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *writer, - const DDS_Security_DynamicData key, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_remote_participant - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_ParticipantBuiltinTopicDataSecure *participant_data, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_remote_datawriter - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_remote_datareader - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, - DDS_Security_boolean *relay_only, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_remote_topic - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_TopicBuiltinTopicData *topic_data, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean -check_local_datawriter_match - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle writer_permissions_handle, - const DDS_Security_PermissionsHandle reader_permissions_handle, - const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, - const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean -check_local_datareader_match - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle reader_permissions_handle, - const DDS_Security_PermissionsHandle writer_permissions_handle, - const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, - const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_remote_datawriter_register_instance - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *reader, - const DDS_Security_InstanceHandle publication_handle, - const DDS_Security_DynamicData key, - const DDS_Security_InstanceHandle instance_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_remote_datawriter_dispose_instance - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *reader, - const DDS_Security_InstanceHandle publication_handle, - const DDS_Security_DynamicData key, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -get_permissions_token - ( dds_security_access_control *instance, - DDS_Security_PermissionsToken *permissions_token, - const DDS_Security_PermissionsHandle handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -get_permissions_credential_token - ( dds_security_access_control *instance, - DDS_Security_PermissionsCredentialToken *permissions_credential_token, - const DDS_Security_PermissionsHandle handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -set_listener - ( dds_security_access_control *instance, - const dds_security_access_control_listener *listener, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -return_permissions_token - ( dds_security_access_control *instance, - const DDS_Security_PermissionsToken *token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -return_permissions_credential_token - ( dds_security_access_control *instance, - const DDS_Security_PermissionsCredentialToken *permissions_credential_token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -get_participant_sec_attributes - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - DDS_Security_ParticipantSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean -get_topic_sec_attributes - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_char *topic_name, - DDS_Security_TopicSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean -get_datawriter_sec_attributes - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_char *topic_name, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTagQosPolicy *data_tag, - DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean -get_datareader_sec_attributes - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_char *topic_name, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTagQosPolicy *data_tag, - DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean -return_participant_sec_attributes - ( dds_security_access_control *instance, - const DDS_Security_ParticipantSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -return_topic_sec_attributes - ( dds_security_access_control *instance, - const DDS_Security_TopicSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -return_datawriter_sec_attributes - ( dds_security_access_control *instance, - const DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean -return_datareader_sec_attributes - ( dds_security_access_control *instance, - const DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -return_permissions_handle - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - DDS_Security_SecurityException *ex); - - - -#endif /* SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ */ diff --git a/src/security/core/tests/plugin_loading/plugin_mock/access_control_missing_function/mock_access_control.c b/src/security/core/tests/plugin_loading/plugin_mock/access_control_missing_function/mock_access_control.c deleted file mode 100644 index a28e7e7..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/access_control_missing_function/mock_access_control.c +++ /dev/null @@ -1,600 +0,0 @@ -/* - * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include "dds/security/dds_security_api.h" -#include "dds/ddsrt/heap.h" -#include "dds/ddsrt/misc.h" -#include "mock_access_control.h" -#include -#include -#include - -/** - * Implementation structure for storing encapsulated members of the instance - * while giving only the interface definition to user - */ - -typedef struct dds_security_access_control_impl { - dds_security_access_control base; - int member; -} dds_security_access_control_impl; - -/** - * Function implementations - */ - -DDS_Security_PermissionsHandle validate_local_permissions( - dds_security_access_control *instance, - const dds_security_authentication *auth_plugin, - const DDS_Security_IdentityHandle identity, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(auth_plugin); - DDSRT_UNUSED_ARG(auth_plugin); - DDSRT_UNUSED_ARG(identity); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(participant_qos); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return 1; -} - -DDS_Security_PermissionsHandle validate_remote_permissions( - dds_security_access_control *instance, - const dds_security_authentication *auth_plugin, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityHandle remote_identity_handle, - const DDS_Security_PermissionsToken *remote_permissions_token, - const DDS_Security_AuthenticatedPeerCredentialToken *remote_credential_token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(auth_plugin); - DDSRT_UNUSED_ARG(local_identity_handle); - DDSRT_UNUSED_ARG(remote_identity_handle); - DDSRT_UNUSED_ARG(remote_permissions_token); - DDSRT_UNUSED_ARG(remote_credential_token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return 0; -} - -DDS_Security_boolean check_create_participant( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, const DDS_Security_Qos *participant_qos, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(participant_qos); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_create_datawriter( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, const char *topic_name, - const DDS_Security_Qos *writer_qos, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTags *data_tag, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(writer_qos); - DDSRT_UNUSED_ARG(partition); - DDSRT_UNUSED_ARG(data_tag); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_create_datareader( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, const char *topic_name, - const DDS_Security_Qos *reader_qos, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTags *data_tag, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(reader_qos); - DDSRT_UNUSED_ARG(partition); - DDSRT_UNUSED_ARG(data_tag); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_create_topic( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, const char *topic_name, - const DDS_Security_Qos *qos, DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(qos); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_local_datawriter_register_instance( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *writer, const DDS_Security_DynamicData *key, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(writer); - DDSRT_UNUSED_ARG(key); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_local_datawriter_dispose_instance( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *writer, const DDS_Security_DynamicData key, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(writer); - DDSRT_UNUSED_ARG(key); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_remote_participant( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_ParticipantBuiltinTopicDataSecure *participant_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(participant_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_remote_datawriter( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(publication_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_remote_datareader( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, - DDS_Security_boolean *relay_only, DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(subscription_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - *relay_only = false; - - return true; -} - -DDS_Security_boolean check_remote_topic( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_TopicBuiltinTopicData *topic_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(topic_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_local_datawriter_match( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle writer_permissions_handle, - const DDS_Security_PermissionsHandle reader_permissions_handle, - const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, - const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(writer_permissions_handle); - DDSRT_UNUSED_ARG(reader_permissions_handle); - DDSRT_UNUSED_ARG(publication_data); - DDSRT_UNUSED_ARG(subscription_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_local_datareader_match( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle reader_permissions_handle, - const DDS_Security_PermissionsHandle writer_permissions_handle, - const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, - const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(reader_permissions_handle); - DDSRT_UNUSED_ARG(writer_permissions_handle); - DDSRT_UNUSED_ARG(subscription_data); - DDSRT_UNUSED_ARG(publication_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_remote_datawriter_register_instance( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *reader, - const DDS_Security_InstanceHandle publication_handle, - const DDS_Security_DynamicData key, - const DDS_Security_InstanceHandle instance_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(reader); - DDSRT_UNUSED_ARG(publication_handle); - DDSRT_UNUSED_ARG(key); - DDSRT_UNUSED_ARG(instance_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean check_remote_datawriter_dispose_instance( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *reader, - const DDS_Security_InstanceHandle publication_handle, - const DDS_Security_DynamicData key, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(reader); - DDSRT_UNUSED_ARG(publication_handle); - DDSRT_UNUSED_ARG(key); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean get_permissions_token( dds_security_access_control *instance, - DDS_Security_PermissionsToken *permissions_token, - const DDS_Security_PermissionsHandle handle, - DDS_Security_SecurityException *ex) -{ - - DDSRT_UNUSED_ARG(permissions_token); - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean get_permissions_credential_token( - dds_security_access_control *instance, - DDS_Security_PermissionsCredentialToken *permissions_credential_token, - const DDS_Security_PermissionsHandle handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_credential_token); - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean set_listener( dds_security_access_control *instance, - const dds_security_access_control_listener *listener, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(listener); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_permissions_token( dds_security_access_control *instance, - const DDS_Security_PermissionsToken *token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_permissions_credential_token( - dds_security_access_control *instance, - const DDS_Security_PermissionsCredentialToken *permissions_credential_token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_credential_token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean get_participant_sec_attributes( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - DDS_Security_ParticipantSecurityAttributes *attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean get_topic_sec_attributes( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const char *topic_name, - DDS_Security_TopicSecurityAttributes *attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean get_datawriter_sec_attributes( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const char *topic_name, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTagQosPolicy *data_tag, - DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(partition); - DDSRT_UNUSED_ARG(data_tag); - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean get_datareader_sec_attributes( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const char *topic_name, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTagQosPolicy *data_tag, - DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(partition); - DDSRT_UNUSED_ARG(data_tag); - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_participant_sec_attributes( - dds_security_access_control *instance, - const DDS_Security_ParticipantSecurityAttributes *attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_topic_sec_attributes( - dds_security_access_control *instance, - const DDS_Security_TopicSecurityAttributes *attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_datawriter_sec_attributes( - dds_security_access_control *instance, - const DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_datareader_sec_attributes( - dds_security_access_control *instance, - const DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_permissions_handle( - dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -int32_t init_access_control( const char *argument, void **context) -{ - - dds_security_access_control *access_control; - - DDSRT_UNUSED_ARG(argument); - - //allocate new instance - access_control = ddsrt_malloc(sizeof(dds_security_access_control)); - memset(access_control, 0, sizeof(dds_security_access_control)); - - //assign the interface functions - access_control->validate_local_permissions = &validate_local_permissions; - - access_control->validate_remote_permissions = &validate_remote_permissions; - - access_control->check_create_participant = &check_create_participant; - - access_control->check_create_datawriter = &check_create_datawriter; - - /* removed the function assignment - access_control->check_create_datareader = &check_create_datareader; - - */ - - access_control->check_create_topic = &check_create_topic; - - access_control->check_local_datawriter_register_instance = - &check_local_datawriter_register_instance; - - access_control->check_local_datawriter_dispose_instance = - &check_local_datawriter_dispose_instance; - - access_control->check_remote_participant = &check_remote_participant; - - access_control->check_remote_datawriter = &check_remote_datawriter; - - access_control->check_remote_datareader = &check_remote_datareader; - - access_control->check_remote_topic = &check_remote_topic; - - access_control->check_local_datawriter_match = &check_local_datawriter_match; - - access_control->check_local_datareader_match = &check_local_datareader_match; - - access_control->check_remote_datawriter_register_instance = - &check_remote_datawriter_register_instance; - - access_control->check_remote_datawriter_dispose_instance = - &check_remote_datawriter_dispose_instance; - - access_control->get_permissions_token = &get_permissions_token; - - access_control->get_permissions_credential_token = - &get_permissions_credential_token; - - access_control->set_listener = &set_listener; - - access_control->return_permissions_token = &return_permissions_token; - - access_control->return_permissions_credential_token = - &return_permissions_credential_token; - - access_control->get_participant_sec_attributes = - &get_participant_sec_attributes; - - access_control->get_topic_sec_attributes = &get_topic_sec_attributes; - - access_control->get_datawriter_sec_attributes = - &get_datawriter_sec_attributes; - - access_control->get_datareader_sec_attributes = - &get_datareader_sec_attributes; - - access_control->return_participant_sec_attributes = - &return_participant_sec_attributes; - - access_control->return_topic_sec_attributes = - &return_topic_sec_attributes; - - access_control->return_datawriter_sec_attributes = - &return_datawriter_sec_attributes; - - access_control->return_datareader_sec_attributes = - &return_datareader_sec_attributes; - - access_control->return_permissions_handle = - &return_permissions_handle; - - //return the instance - *context = access_control; - return 0; -} - - int32_t finalize_access_control( void *context) -{ - - DDSRT_UNUSED_ARG(context); - - ddsrt_free((dds_security_access_control*) context); - return 0; -} diff --git a/src/security/core/tests/plugin_loading/plugin_mock/access_control_missing_function/mock_access_control.h b/src/security/core/tests/plugin_loading/plugin_mock/access_control_missing_function/mock_access_control.h deleted file mode 100644 index 89d87c0..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/access_control_missing_function/mock_access_control.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef SECURITY_ACCESS_CONTROL_ALLOK_H_ -#define SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ - -#include "dds/security/access_control_missing_function_export.h" -#include "dds/security/dds_security_api.h" - -SECURITY_EXPORT int32_t -init_access_control(const char *argument, void **context); - -SECURITY_EXPORT int32_t -finalize_access_control(void *context); - - -/** - * AccessControl Interface - */ - -DDS_Security_PermissionsHandle -validate_local_permissions - ( dds_security_access_control *instance, - const dds_security_authentication *auth_plugin, - const DDS_Security_IdentityHandle identity, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - DDS_Security_SecurityException *ex); - -DDS_Security_PermissionsHandle -validate_remote_permissions - ( dds_security_access_control *instance, - const dds_security_authentication *auth_plugin, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityHandle remote_identity_handle, - const DDS_Security_PermissionsToken *remote_permissions_token, - const DDS_Security_AuthenticatedPeerCredentialToken *remote_credential_token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_create_participant - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_create_datawriter - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_char *topic_name, - const DDS_Security_Qos *writer_qos, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTags *data_tag, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_create_datareader - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_char *topic_name, - const DDS_Security_Qos *reader_qos, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTags *data_tag, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean -check_create_topic - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_char *topic_name, - const DDS_Security_Qos *topic_qos, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_local_datawriter_register_instance - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *writer, - const DDS_Security_DynamicData *key, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_local_datawriter_dispose_instance - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *writer, - const DDS_Security_DynamicData key, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_remote_participant - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_ParticipantBuiltinTopicDataSecure *participant_data, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_remote_datawriter - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_remote_datareader - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, - DDS_Security_boolean *relay_only, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_remote_topic - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_TopicBuiltinTopicData *topic_data, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean -check_local_datawriter_match - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle writer_permissions_handle, - const DDS_Security_PermissionsHandle reader_permissions_handle, - const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, - const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean -check_local_datareader_match - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle reader_permissions_handle, - const DDS_Security_PermissionsHandle writer_permissions_handle, - const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, - const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_remote_datawriter_register_instance - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *reader, - const DDS_Security_InstanceHandle publication_handle, - const DDS_Security_DynamicData key, - const DDS_Security_InstanceHandle instance_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -check_remote_datawriter_dispose_instance - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *reader, - const DDS_Security_InstanceHandle publication_handle, - const DDS_Security_DynamicData key, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -get_permissions_token - ( dds_security_access_control *instance, - DDS_Security_PermissionsToken *permissions_token, - const DDS_Security_PermissionsHandle handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -get_permissions_credential_token - ( dds_security_access_control *instance, - DDS_Security_PermissionsCredentialToken *permissions_credential_token, - const DDS_Security_PermissionsHandle handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -set_listener - ( dds_security_access_control *instance, - const dds_security_access_control_listener *listener, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -return_permissions_token - ( dds_security_access_control *instance, - const DDS_Security_PermissionsToken *token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -return_permissions_credential_token - ( dds_security_access_control *instance, - const DDS_Security_PermissionsCredentialToken *permissions_credential_token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -get_participant_sec_attributes - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - DDS_Security_ParticipantSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean -get_topic_sec_attributes - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_char *topic_name, - DDS_Security_TopicSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean -get_datawriter_sec_attributes - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_char *topic_name, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTagQosPolicy *data_tag, - DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean -get_datareader_sec_attributes - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_char *topic_name, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTagQosPolicy *data_tag, - DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean -return_participant_sec_attributes - ( dds_security_access_control *instance, - const DDS_Security_ParticipantSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -return_topic_sec_attributes - ( dds_security_access_control *instance, - const DDS_Security_TopicSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -return_datawriter_sec_attributes - ( dds_security_access_control *instance, - const DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean -return_datareader_sec_attributes - ( dds_security_access_control *instance, - const DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -return_permissions_handle - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - DDS_Security_SecurityException *ex); - - - -#endif /* SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ */ diff --git a/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok/mock_authentication.c b/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok/mock_authentication.c deleted file mode 100644 index 03f9666..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok/mock_authentication.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -#include "dds/security/dds_security_api.h" -#include "dds/ddsrt/heap.h" -#include "dds/ddsrt/misc.h" -#include "mock_authentication.h" -#include -#include -#include - -/** - * Implementation structure for storing encapsulated members of the instance - * while giving only the interface definition to user - */ - -typedef struct dds_security_authentication_impl { - dds_security_authentication base; - int id; //sample internal member -} dds_security_authentication_impl; - - -static const char *test_identity_certificate = TEST_IDENTITY_CERTIFICATE_ALL_OK; -static const char *test_ca_certificate = TEST_CA_CERTIFICATE_ALL_OK; -static const char *test_private_key = TEST_PRIVATE_KEY_ALL_OK; - -DDS_Security_ValidationResult_t validate_local_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *local_identity_handle, - DDS_Security_GUID_t *adjusted_participant_guid, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - const DDS_Security_GUID_t *candidate_participant_guid, - DDS_Security_SecurityException *ex) -{ - - unsigned i; - DDS_Security_ValidationResult_t result=DDS_SECURITY_VALIDATION_OK; - dds_security_authentication_impl *implementation = - (dds_security_authentication_impl *) instance; - char *identity_ca = NULL; - char *identity_certificate = NULL; - char *private_key = NULL; - - DDSRT_UNUSED_ARG(local_identity_handle); - DDSRT_UNUSED_ARG(adjusted_participant_guid); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(participant_qos); - DDSRT_UNUSED_ARG(candidate_participant_guid); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - implementation->id = 2; - - memcpy(adjusted_participant_guid, candidate_participant_guid, sizeof(DDS_Security_GUID_t)); - - for( i=0; i< participant_qos->property.value._length; i++) - { - - //printf("%s: %s",participant_qos->property.value._buffer[i].name, participant_qos->property.value._buffer[i].value); - printf("%s\n",participant_qos->property.value._buffer[i].name); - if( strcmp(participant_qos->property.value._buffer[i].name, "dds.sec.auth.private_key") == 0) - { - private_key = participant_qos->property.value._buffer[i].value; - } else if( strcmp(participant_qos->property.value._buffer[i].name, "dds.sec.auth.identity_ca") == 0) - { - identity_ca = participant_qos->property.value._buffer[i].value; - } else if( strcmp(participant_qos->property.value._buffer[i].name, "dds.sec.auth.identity_certificate") == 0) - { - identity_certificate = participant_qos->property.value._buffer[i].value; - } - } - - if( strcmp(identity_certificate, test_identity_certificate) != 0){ - printf("identity received=%s\n", identity_certificate); - printf("identity expected=%s\n", test_identity_certificate); - result = DDS_SECURITY_VALIDATION_FAILED; - printf("FAILED: Could not get identity_certificate value properly\n"); - } - else if( strcmp(identity_ca, test_ca_certificate) != 0){ - printf("ca received=%s\n", identity_ca); - printf("ca expected=%s\n", test_ca_certificate); - printf("FAILED: Could not get identity_ca value properly\n"); - result = DDS_SECURITY_VALIDATION_FAILED; - }else if( strcmp(private_key, test_private_key) != 0){ - printf("FAILED: Could not get private_key value properly\n"); - result = DDS_SECURITY_VALIDATION_FAILED; - } - - if( result == DDS_SECURITY_VALIDATION_OK ) - { - printf("DDS_SECURITY_VALIDATION_OK\n"); - } - - - return result; -} - -DDS_Security_boolean get_identity_token(dds_security_authentication *instance, - DDS_Security_IdentityToken *identity_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(identity_token); - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - memset(identity_token, 0, sizeof(*identity_token)); - - return true; -} - -DDS_Security_boolean get_identity_status_token( - dds_security_authentication *instance, - DDS_Security_IdentityStatusToken *identity_status_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(identity_status_token); - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean set_permissions_credential_and_token( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle handle, - const DDS_Security_PermissionsCredentialToken *permissions_credential, - const DDS_Security_PermissionsToken *permissions_token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(permissions_credential); - DDSRT_UNUSED_ARG(permissions_token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_ValidationResult_t validate_remote_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *remote_identity_handle, - DDS_Security_AuthRequestMessageToken *local_auth_request_token, - const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityToken *remote_identity_token, - const DDS_Security_GUID_t *remote_participant_guid, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(remote_identity_handle); - DDSRT_UNUSED_ARG(local_auth_request_token); - DDSRT_UNUSED_ARG(remote_auth_request_token); - DDSRT_UNUSED_ARG(local_identity_handle); - DDSRT_UNUSED_ARG(remote_identity_token); - DDSRT_UNUSED_ARG(remote_participant_guid); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_ValidationResult_t begin_handshake_request( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(handshake_message); - DDSRT_UNUSED_ARG(initiator_identity_handle); - DDSRT_UNUSED_ARG(replier_identity_handle); - DDSRT_UNUSED_ARG(serialized_local_participant_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_ValidationResult_t begin_handshake_reply( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(handshake_message_out); - DDSRT_UNUSED_ARG(handshake_message_in); - DDSRT_UNUSED_ARG(initiator_identity_handle); - DDSRT_UNUSED_ARG(replier_identity_handle); - DDSRT_UNUSED_ARG(serialized_local_participant_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_ValidationResult_t process_handshake( - dds_security_authentication *instance, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_message_out); - DDSRT_UNUSED_ARG(handshake_message_in); - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_SharedSecretHandle get_shared_secret( - dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return 0; -} - -DDS_Security_boolean get_authenticated_peer_credential_token( - dds_security_authentication *instance, - DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(peer_credential_token); - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean set_listener(dds_security_authentication *instance, - const dds_security_authentication_listener *listener, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(listener); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_identity_token(dds_security_authentication *instance, - const DDS_Security_IdentityToken *token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_identity_status_token( - dds_security_authentication *instance, - const DDS_Security_IdentityStatusToken *token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_authenticated_peer_credential_token( - dds_security_authentication *instance, - const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(peer_credential_token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_handshake_handle(dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_identity_handle(dds_security_authentication *instance, - const DDS_Security_IdentityHandle identity_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(identity_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_sharedsecret_handle( - dds_security_authentication *instance, - const DDS_Security_SharedSecretHandle sharedsecret_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(sharedsecret_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -int32_t init_authentication( const char *argument, void **context) -{ - - dds_security_authentication_impl *authentication; - - DDSRT_UNUSED_ARG(argument); - - //allocate implementation wrapper - authentication = (dds_security_authentication_impl*) ddsrt_malloc( - sizeof(dds_security_authentication_impl)); - memset(authentication, 0, sizeof(dds_security_authentication_impl)); - - //assign the interface functions - authentication->base.validate_local_identity = &validate_local_identity; - - authentication->base.get_identity_token = &get_identity_token; - - authentication->base.get_identity_status_token = &get_identity_status_token; - - authentication->base.set_permissions_credential_and_token = - &set_permissions_credential_and_token; - - authentication->base.validate_remote_identity = &validate_remote_identity; - - authentication->base.begin_handshake_request = &begin_handshake_request; - - authentication->base.begin_handshake_reply = &begin_handshake_reply; - - authentication->base.process_handshake = &process_handshake; - - authentication->base.get_shared_secret = &get_shared_secret; - - authentication->base.get_authenticated_peer_credential_token = - &get_authenticated_peer_credential_token; - - authentication->base.set_listener = &set_listener; - - authentication->base.return_identity_token = &return_identity_token; - - authentication->base.return_identity_status_token = - &return_identity_status_token; - - authentication->base.return_authenticated_peer_credential_token = - &return_authenticated_peer_credential_token; - - authentication->base.return_handshake_handle = &return_handshake_handle; - - authentication->base.return_identity_handle = &return_identity_handle; - - authentication->base.return_sharedsecret_handle = &return_sharedsecret_handle; - - //prepare implementation wrapper - authentication->id = 1; - - //return the instance - *context = authentication; - return 0; -} - -int32_t finalize_authentication(void *instance) -{ - - ddsrt_free((dds_security_authentication_impl*) instance); - - return 0; -} diff --git a/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok/mock_authentication.h b/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok/mock_authentication.h deleted file mode 100644 index bb4479f..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok/mock_authentication.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * authentication.h - * - * Created on: Jan 15, 2018 - * Author: kurtulus oksuztepe - */ - -#ifndef SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ -#define SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ - -#include "dds/security/authentication_all_ok_export.h" -#include "../../plugin_mock_common.h" - -SECURITY_EXPORT int32_t -init_authentication(const char *argument, void **context); - -SECURITY_EXPORT int32_t -finalize_authentication(void *context); - -DDS_Security_ValidationResult_t -validate_local_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *local_identity_handle, - DDS_Security_GUID_t *adjusted_participant_guid, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - const DDS_Security_GUID_t *candidate_participant_guid, - - DDS_Security_SecurityException *ex); -DDS_Security_boolean -get_identity_token(dds_security_authentication *instance, - DDS_Security_IdentityToken *identity_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex); -DDS_Security_boolean -set_permissions_credential_and_token( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle handle, - const DDS_Security_PermissionsCredentialToken *permissions_credential, - const DDS_Security_PermissionsToken *permissions_token, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -validate_remote_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *remote_identity_handle, - DDS_Security_AuthRequestMessageToken *local_auth_request_token, - const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityToken *remote_identity_token, - const DDS_Security_GUID_t *remote_participant_guid, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -begin_handshake_request( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -begin_handshake_reply( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -process_handshake( - dds_security_authentication *instance, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_SharedSecretHandle get_shared_secret( - dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -get_authenticated_peer_credential_token( - dds_security_authentication *instance, - DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean get_identity_status_token( - dds_security_authentication *instance, - DDS_Security_IdentityStatusToken *identity_status_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean set_listener(dds_security_authentication *instance, - const dds_security_authentication_listener *listener, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_identity_token(dds_security_authentication *instance, - const DDS_Security_IdentityToken *token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_identity_status_token( - dds_security_authentication *instance, - const DDS_Security_IdentityStatusToken *token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_authenticated_peer_credential_token( - dds_security_authentication *instance, - const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -return_handshake_handle(dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); -DDS_Security_boolean -return_identity_handle( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle identity_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_sharedsecret_handle( - dds_security_authentication *instance, - const DDS_Security_SharedSecretHandle sharedsecret_handle, - DDS_Security_SecurityException *ex); - - - -#endif /* SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ */ diff --git a/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok_other/mock_authentication.c b/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok_other/mock_authentication.c deleted file mode 100644 index ff367c5..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok_other/mock_authentication.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -#include "dds/security/dds_security_api.h" -#include "dds/ddsrt/heap.h" -#include "dds/ddsrt/misc.h" -#include "dds/ddsrt/string.h" -#include "mock_authentication.h" -#include -#include -#include - -/** - * Implementation structure for storing encapsulated members of the instance - * while giving only the interface definition to user - */ - -typedef struct dds_security_authentication_impl { - dds_security_authentication base; - int id; //sample internal member -} dds_security_authentication_impl; - -DDS_Security_ValidationResult_t validate_local_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *local_identity_handle, - DDS_Security_GUID_t *adjusted_participant_guid, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - const DDS_Security_GUID_t *candidate_participant_guid, - DDS_Security_SecurityException *ex) -{ - - DDSRT_UNUSED_ARG(local_identity_handle); - DDSRT_UNUSED_ARG(adjusted_participant_guid); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(participant_qos); - DDSRT_UNUSED_ARG(candidate_participant_guid); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - ex->message = ddsrt_strdup("Certificate expired"); - ex->code = DDS_SECURITY_ERR_CERT_EXPIRED_CODE; - ex->minor_code = 0; - - return DDS_SECURITY_VALIDATION_FAILED; -} - -DDS_Security_boolean get_identity_token(dds_security_authentication *instance, - DDS_Security_IdentityToken *identity_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(identity_token); - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - memset(identity_token, 0, sizeof(*identity_token)); - - return true; -} - -DDS_Security_boolean get_identity_status_token( - dds_security_authentication *instance, - DDS_Security_IdentityStatusToken *identity_status_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(identity_status_token); - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean set_permissions_credential_and_token( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle handle, - const DDS_Security_PermissionsCredentialToken *permissions_credential, - const DDS_Security_PermissionsToken *permissions_token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(permissions_credential); - DDSRT_UNUSED_ARG(permissions_token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_ValidationResult_t validate_remote_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *remote_identity_handle, - DDS_Security_AuthRequestMessageToken *local_auth_request_token, - const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityToken *remote_identity_token, - const DDS_Security_GUID_t *remote_participant_guid, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(remote_identity_handle); - DDSRT_UNUSED_ARG(local_auth_request_token); - DDSRT_UNUSED_ARG(remote_auth_request_token); - DDSRT_UNUSED_ARG(local_identity_handle); - DDSRT_UNUSED_ARG(remote_identity_token); - DDSRT_UNUSED_ARG(remote_participant_guid); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_ValidationResult_t begin_handshake_request( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(handshake_message); - DDSRT_UNUSED_ARG(initiator_identity_handle); - DDSRT_UNUSED_ARG(replier_identity_handle); - DDSRT_UNUSED_ARG(serialized_local_participant_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_ValidationResult_t begin_handshake_reply( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(handshake_message_out); - DDSRT_UNUSED_ARG(handshake_message_in); - DDSRT_UNUSED_ARG(initiator_identity_handle); - DDSRT_UNUSED_ARG(replier_identity_handle); - DDSRT_UNUSED_ARG(serialized_local_participant_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_ValidationResult_t process_handshake( - dds_security_authentication *instance, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_message_out); - DDSRT_UNUSED_ARG(handshake_message_in); - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_SharedSecretHandle get_shared_secret( - dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return 0; -} - -DDS_Security_boolean get_authenticated_peer_credential_token( - dds_security_authentication *instance, - DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(peer_credential_token); - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean set_listener(dds_security_authentication *instance, - const dds_security_authentication_listener *listener, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(listener); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_identity_token(dds_security_authentication *instance, - const DDS_Security_IdentityToken *token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_identity_status_token( - dds_security_authentication *instance, - const DDS_Security_IdentityStatusToken *token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_authenticated_peer_credential_token( - dds_security_authentication *instance, - const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(peer_credential_token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_handshake_handle(dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_identity_handle(dds_security_authentication *instance, - const DDS_Security_IdentityHandle identity_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(identity_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_sharedsecret_handle( - dds_security_authentication *instance, - const DDS_Security_SharedSecretHandle sharedsecret_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(sharedsecret_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -int32_t init_authentication( const char *argument, void **context) -{ - - dds_security_authentication_impl *authentication; - - DDSRT_UNUSED_ARG(argument); - - //allocate implementation wrapper - authentication = (dds_security_authentication_impl*) ddsrt_malloc( - sizeof(dds_security_authentication_impl)); - memset(authentication, 0, sizeof(dds_security_authentication_impl)); - - //assign the interface functions - authentication->base.validate_local_identity = &validate_local_identity; - - authentication->base.get_identity_token = &get_identity_token; - - authentication->base.get_identity_status_token = &get_identity_status_token; - - authentication->base.set_permissions_credential_and_token = - &set_permissions_credential_and_token; - - authentication->base.validate_remote_identity = &validate_remote_identity; - - authentication->base.begin_handshake_request = &begin_handshake_request; - - authentication->base.begin_handshake_reply = &begin_handshake_reply; - - authentication->base.process_handshake = &process_handshake; - - authentication->base.get_shared_secret = &get_shared_secret; - - authentication->base.get_authenticated_peer_credential_token = - &get_authenticated_peer_credential_token; - - authentication->base.set_listener = &set_listener; - - authentication->base.return_identity_token = &return_identity_token; - - authentication->base.return_identity_status_token = - &return_identity_status_token; - - authentication->base.return_authenticated_peer_credential_token = - &return_authenticated_peer_credential_token; - - authentication->base.return_handshake_handle = &return_handshake_handle; - - authentication->base.return_identity_handle = &return_identity_handle; - - authentication->base.return_sharedsecret_handle = &return_sharedsecret_handle; - - //prepare implementation wrapper - authentication->id = 1; - - //return the instance - *context = authentication; - return 0; -} - -int32_t finalize_authentication(void *instance) -{ - - ddsrt_free((dds_security_authentication_impl*) instance); - - return 0; -} diff --git a/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok_other/mock_authentication.h b/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok_other/mock_authentication.h deleted file mode 100644 index c6a416f..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/authentication_all_ok_other/mock_authentication.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * authentication.h - * - * Created on: Jan 15, 2018 - * Author: kurtulus oksuztepe - */ - -#ifndef SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ -#define SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ - -#include "dds/security/authentication_all_ok_other_export.h" - -SECURITY_EXPORT int32_t -init_authentication(const char *argument, void **context); - -SECURITY_EXPORT int32_t -finalize_authentication(void *context); - -DDS_Security_ValidationResult_t -validate_local_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *local_identity_handle, - DDS_Security_GUID_t *adjusted_participant_guid, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - const DDS_Security_GUID_t *candidate_participant_guid, - - DDS_Security_SecurityException *ex); -DDS_Security_boolean -get_identity_token(dds_security_authentication *instance, - DDS_Security_IdentityToken *identity_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex); -DDS_Security_boolean -set_permissions_credential_and_token( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle handle, - const DDS_Security_PermissionsCredentialToken *permissions_credential, - const DDS_Security_PermissionsToken *permissions_token, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -validate_remote_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *remote_identity_handle, - DDS_Security_AuthRequestMessageToken *local_auth_request_token, - const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityToken *remote_identity_token, - const DDS_Security_GUID_t *remote_participant_guid, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -begin_handshake_request( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -begin_handshake_reply( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -process_handshake( - dds_security_authentication *instance, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_SharedSecretHandle get_shared_secret( - dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -get_authenticated_peer_credential_token( - dds_security_authentication *instance, - DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean get_identity_status_token( - dds_security_authentication *instance, - DDS_Security_IdentityStatusToken *identity_status_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean set_listener(dds_security_authentication *instance, - const dds_security_authentication_listener *listener, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_identity_token(dds_security_authentication *instance, - const DDS_Security_IdentityToken *token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_identity_status_token( - dds_security_authentication *instance, - const DDS_Security_IdentityStatusToken *token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_authenticated_peer_credential_token( - dds_security_authentication *instance, - const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -return_handshake_handle(dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); -DDS_Security_boolean -return_identity_handle( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle identity_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_sharedsecret_handle( - dds_security_authentication *instance, - const DDS_Security_SharedSecretHandle sharedsecret_handle, - DDS_Security_SecurityException *ex); - - - -#endif /* SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ */ diff --git a/src/security/core/tests/plugin_loading/plugin_mock/authentication_finalize_error/mock_authentication.c b/src/security/core/tests/plugin_loading/plugin_mock/authentication_finalize_error/mock_authentication.c deleted file mode 100644 index 68f53ad..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/authentication_finalize_error/mock_authentication.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -#include "dds/security/dds_security_api.h" -#include "dds/ddsrt/heap.h" -#include "dds/ddsrt/misc.h" -#include "mock_authentication.h" -#include -#include -#include -#include - -/** - * Implementation structure for storing encapsulated members of the instance - * while giving only the interface definition to user - */ - -typedef struct dds_security_authentication_impl { - dds_security_authentication base; - int id; //sample internal member -} dds_security_authentication_impl; - -DDS_Security_ValidationResult_t validate_local_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *local_identity_handle, - DDS_Security_GUID_t *adjusted_participant_guid, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - const DDS_Security_GUID_t *candidate_participant_guid, - DDS_Security_SecurityException *ex) -{ - - unsigned i; - DDS_Security_ValidationResult_t result=DDS_SECURITY_VALIDATION_OK; - dds_security_authentication_impl *implementation = - (dds_security_authentication_impl *) instance; - char *identity_ca=NULL; - char *identity_certificate=NULL; - char *private_key=NULL; - - DDSRT_UNUSED_ARG(local_identity_handle); - DDSRT_UNUSED_ARG(adjusted_participant_guid); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(participant_qos); - DDSRT_UNUSED_ARG(candidate_participant_guid); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - implementation->id = 2; - - for( i=0; i< participant_qos->property.value._length; i++) - { - - printf("%s: %s",participant_qos->property.value._buffer[i].name, participant_qos->property.value._buffer[i].value); - if( strcmp(participant_qos->property.value._buffer[i].name, "dds.sec.auth.private_key") == 0) - { - private_key = participant_qos->property.value._buffer[i].value; - } else if( strcmp(participant_qos->property.value._buffer[i].name, "dds.sec.auth.identity_ca") == 0) - { - identity_ca = participant_qos->property.value._buffer[i].value; - } else if( strcmp(participant_qos->property.value._buffer[i].name, "dds.sec.auth.identity_certificate") == 0) - { - identity_certificate = participant_qos->property.value._buffer[i].value; - } - } - - /* for Clang's static analyzer */ - assert(identity_certificate != NULL); - assert(identity_ca != NULL); - assert(private_key != NULL); - - if( strcmp(identity_certificate, test_identity_certificate) != 0){ - - result = DDS_SECURITY_VALIDATION_FAILED; - printf("FAILED: Could not get identity_certificate value properly\n"); - } - else if( strcmp(identity_ca, test_ca_certificate) != 0){ - printf("FAILED: Could not get identity_ca value properly\n"); - result = DDS_SECURITY_VALIDATION_FAILED; - }else if( strcmp(private_key, test_privatekey) != 0){ - printf("FAILED: Could not get private_key value properly\n"); - result = DDS_SECURITY_VALIDATION_FAILED; - } - - - return result; -} - -DDS_Security_boolean get_identity_token( dds_security_authentication *instance, - DDS_Security_IdentityToken *identity_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(identity_token); - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - memset(identity_token, 0, sizeof(*identity_token)); - - return true; -} - -DDS_Security_boolean get_identity_status_token( - dds_security_authentication *instance, - DDS_Security_IdentityStatusToken *identity_status_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(identity_status_token); - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean set_permissions_credential_and_token( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle handle, - const DDS_Security_PermissionsCredentialToken *permissions_credential, - const DDS_Security_PermissionsToken *permissions_token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(permissions_credential); - DDSRT_UNUSED_ARG(permissions_token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_ValidationResult_t validate_remote_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *remote_identity_handle, - DDS_Security_AuthRequestMessageToken *local_auth_request_token, - const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityToken *remote_identity_token, - const DDS_Security_GUID_t *remote_participant_guid, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(remote_identity_handle); - DDSRT_UNUSED_ARG(local_auth_request_token); - DDSRT_UNUSED_ARG(remote_auth_request_token); - DDSRT_UNUSED_ARG(local_identity_handle); - DDSRT_UNUSED_ARG(remote_identity_token); - DDSRT_UNUSED_ARG(remote_participant_guid); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_ValidationResult_t begin_handshake_request( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(handshake_message); - DDSRT_UNUSED_ARG(initiator_identity_handle); - DDSRT_UNUSED_ARG(replier_identity_handle); - DDSRT_UNUSED_ARG(serialized_local_participant_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_ValidationResult_t begin_handshake_reply( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(handshake_message_out); - DDSRT_UNUSED_ARG(handshake_message_in); - DDSRT_UNUSED_ARG(initiator_identity_handle); - DDSRT_UNUSED_ARG(replier_identity_handle); - DDSRT_UNUSED_ARG(serialized_local_participant_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_ValidationResult_t process_handshake( - dds_security_authentication *instance, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_message_out); - DDSRT_UNUSED_ARG(handshake_message_in); - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_SharedSecretHandle get_shared_secret( - dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return 0; -} - -DDS_Security_boolean get_authenticated_peer_credential_token( - dds_security_authentication *instance, - DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(peer_credential_token); - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean set_listener( dds_security_authentication *instance, - const dds_security_authentication_listener *listener, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(listener); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_identity_token( dds_security_authentication *instance, - const DDS_Security_IdentityToken *token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_identity_status_token( - dds_security_authentication *instance, - const DDS_Security_IdentityStatusToken *token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_authenticated_peer_credential_token( - dds_security_authentication *instance, - const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(peer_credential_token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_handshake_handle( dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_identity_handle( dds_security_authentication *instance, - const DDS_Security_IdentityHandle identity_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(identity_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_sharedsecret_handle( - dds_security_authentication *instance, - const DDS_Security_SharedSecretHandle sharedsecret_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(sharedsecret_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -int32_t init_authentication( const char *argument, void **context) -{ - - dds_security_authentication_impl *authentication; - DDSRT_UNUSED_ARG(argument); - - //allocate implementation wrapper - authentication = (dds_security_authentication_impl*) ddsrt_malloc( - sizeof(dds_security_authentication_impl)); - memset(authentication, 0, sizeof(dds_security_authentication_impl)); - - //assign the interface functions - authentication->base.validate_local_identity = &validate_local_identity; - - authentication->base.get_identity_token = &get_identity_token; - - authentication->base.get_identity_status_token = &get_identity_status_token; - - authentication->base.set_permissions_credential_and_token = - &set_permissions_credential_and_token; - - authentication->base.validate_remote_identity = &validate_remote_identity; - - authentication->base.begin_handshake_request = &begin_handshake_request; - - authentication->base.begin_handshake_reply = &begin_handshake_reply; - - authentication->base.process_handshake = &process_handshake; - - authentication->base.get_shared_secret = &get_shared_secret; - - authentication->base.get_authenticated_peer_credential_token = - &get_authenticated_peer_credential_token; - - authentication->base.set_listener = &set_listener; - - authentication->base.return_identity_token = &return_identity_token; - - authentication->base.return_identity_status_token = - &return_identity_status_token; - - authentication->base.return_authenticated_peer_credential_token = - &return_authenticated_peer_credential_token; - - authentication->base.return_handshake_handle = &return_handshake_handle; - - authentication->base.return_identity_handle = &return_identity_handle; - - authentication->base.return_sharedsecret_handle = &return_sharedsecret_handle; - - //prepare implementation wrapper - authentication->id = 1; - - //return the instance - *context = authentication; - return 0; -} - -/* wrong finalize function name for test purposes */ -int32_t finalize_authentication_WRONG_NAME( void *instance) -{ - - ddsrt_free((dds_security_authentication_impl*) instance); - - return 0; -} diff --git a/src/security/core/tests/plugin_loading/plugin_mock/authentication_finalize_error/mock_authentication.h b/src/security/core/tests/plugin_loading/plugin_mock/authentication_finalize_error/mock_authentication.h deleted file mode 100644 index d7c0e09..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/authentication_finalize_error/mock_authentication.h +++ /dev/null @@ -1,264 +0,0 @@ -/* - * authentication.h - * - * Created on: Jan 15, 2018 - * Author: kurtulus oksuztepe - */ - -#ifndef SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ -#define SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ - - -#include "dds/security/authentication_finalize_error_export.h" - -SECURITY_EXPORT int32_t -init_authentication(const char *argument, void **context); - -SECURITY_EXPORT int32_t -finalize_authentication_WRONG_NAME(void *context); - -char *test_identity_certificate="data:,-----BEGIN CERTIFICATE-----\n\ -MIIGJzCCBA+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBsjELMAkGA1UEBhMCRlIx\n\ -DzANBgNVBAgMBkFsc2FjZTETMBEGA1UEBwwKU3RyYXNib3VyZzEYMBYGA1UECgwP\n\ -d3d3LmZyZWVsYW4ub3JnMRAwDgYDVQQLDAdmcmVlbGFuMS0wKwYDVQQDDCRGcmVl\n\ -bGFuIFNhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIjAgBgkqhkiG9w0BCQEW\n\ -E2NvbnRhY3RAZnJlZWxhbi5vcmcwHhcNMTIwNDI3MTAzMTE4WhcNMjIwNDI1MTAz\n\ -MTE4WjB+MQswCQYDVQQGEwJGUjEPMA0GA1UECAwGQWxzYWNlMRgwFgYDVQQKDA93\n\ -d3cuZnJlZWxhbi5vcmcxEDAOBgNVBAsMB2ZyZWVsYW4xDjAMBgNVBAMMBWFsaWNl\n\ -MSIwIAYJKoZIhvcNAQkBFhNjb250YWN0QGZyZWVsYW4ub3JnMIICIjANBgkqhkiG\n\ -9w0BAQEFAAOCAg8AMIICCgKCAgEA3W29+ID6194bH6ejLrIC4hb2Ugo8v6ZC+Mrc\n\ -k2dNYMNPjcOKABvxxEtBamnSaeU/IY7FC/giN622LEtV/3oDcrua0+yWuVafyxmZ\n\ -yTKUb4/GUgafRQPf/eiX9urWurtIK7XgNGFNUjYPq4dSJQPPhwCHE/LKAykWnZBX\n\ -RrX0Dq4XyApNku0IpjIjEXH+8ixE12wH8wt7DEvdO7T3N3CfUbaITl1qBX+Nm2Z6\n\ -q4Ag/u5rl8NJfXg71ZmXA3XOj7zFvpyapRIZcPmkvZYn7SMCp8dXyXHPdpSiIWL2\n\ -uB3KiO4JrUYvt2GzLBUThp+lNSZaZ/Q3yOaAAUkOx+1h08285Pi+P8lO+H2Xic4S\n\ -vMq1xtLg2bNoPC5KnbRfuFPuUD2/3dSiiragJ6uYDLOyWJDivKGt/72OVTEPAL9o\n\ -6T2pGZrwbQuiFGrGTMZOvWMSpQtNl+tCCXlT4mWqJDRwuMGrI4DnnGzt3IKqNwS4\n\ -Qyo9KqjMIPwnXZAmWPm3FOKe4sFwc5fpawKO01JZewDsYTDxVj+cwXwFxbE2yBiF\n\ -z2FAHwfopwaH35p3C6lkcgP2k/zgAlnBluzACUI+MKJ/G0gv/uAhj1OHJQ3L6kn1\n\ -SpvQ41/ueBjlunExqQSYD7GtZ1Kg8uOcq2r+WISE3Qc9MpQFFkUVllmgWGwYDuN3\n\ -Zsez95kCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT\n\ -TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFFlfyRO6G8y5qEFKikl5\n\ -ajb2fT7XMB8GA1UdIwQYMBaAFCNsLT0+KV14uGw+quK7Lh5sh/JTMA0GCSqGSIb3\n\ -DQEBBQUAA4ICAQAT5wJFPqervbja5+90iKxi1d0QVtVGB+z6aoAMuWK+qgi0vgvr\n\ -mu9ot2lvTSCSnRhjeiP0SIdqFMORmBtOCFk/kYDp9M/91b+vS+S9eAlxrNCB5VOf\n\ -PqxEPp/wv1rBcE4GBO/c6HcFon3F+oBYCsUQbZDKSSZxhDm3mj7pb67FNbZbJIzJ\n\ -70HDsRe2O04oiTx+h6g6pW3cOQMgIAvFgKN5Ex727K4230B0NIdGkzuj4KSML0NM\n\ -slSAcXZ41OoSKNjy44BVEZv0ZdxTDrRM4EwJtNyggFzmtTuV02nkUj1bYYYC5f0L\n\ -ADr6s0XMyaNk8twlWYlYDZ5uKDpVRVBfiGcq0uJIzIvemhuTrofh8pBQQNkPRDFT\n\ -Rq1iTo1Ihhl3/Fl1kXk1WR3jTjNb4jHX7lIoXwpwp767HAPKGhjQ9cFbnHMEtkro\n\ -RlJYdtRq5mccDtwT0GFyoJLLBZdHHMHJz0F9H7FNk2tTQQMhK5MVYwg+LIaee586\n\ -CQVqfbscp7evlgjLW98H+5zylRHAgoH2G79aHljNKMp9BOuq6SnEglEsiWGVtu2l\n\ -hnx8SB3sVJZHeer8f/UQQwqbAO+Kdy70NmbSaqaVtp8jOxLiidWkwSyRTsuU6D8i\n\ -DiH5uEqBXExjrj0FslxcVKdVj5glVcSmkLwZKbEU1OKwleT/iXFhvooWhQ==\n\ ------END CERTIFICATE-----"; - -char *test_ca_certificate="data:,-----BEGIN CERTIFICATE-----\n\ -MIIGOTCCBCGgAwIBAgIJAOE/vJd8EB24MA0GCSqGSIb3DQEBBQUAMIGyMQswCQYD\n\ -VQQGEwJGUjEPMA0GA1UECAwGQWxzYWNlMRMwEQYDVQQHDApTdHJhc2JvdXJnMRgw\n\ -FgYDVQQKDA93d3cuZnJlZWxhbi5vcmcxEDAOBgNVBAsMB2ZyZWVsYW4xLTArBgNV\n\ -BAMMJEZyZWVsYW4gU2FtcGxlIENlcnRpZmljYXRlIEF1dGhvcml0eTEiMCAGCSqG\n\ -SIb3DQEJARYTY29udGFjdEBmcmVlbGFuLm9yZzAeFw0xMjA0MjcxMDE3NDRaFw0x\n\ -MjA1MjcxMDE3NDRaMIGyMQswCQYDVQQGEwJGUjEPMA0GA1UECAwGQWxzYWNlMRMw\n\ -EQYDVQQHDApTdHJhc2JvdXJnMRgwFgYDVQQKDA93d3cuZnJlZWxhbi5vcmcxEDAO\n\ -BgNVBAsMB2ZyZWVsYW4xLTArBgNVBAMMJEZyZWVsYW4gU2FtcGxlIENlcnRpZmlj\n\ -YXRlIEF1dGhvcml0eTEiMCAGCSqGSIb3DQEJARYTY29udGFjdEBmcmVlbGFuLm9y\n\ -ZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAODp+8oQcK+MTuWPZVxJ\n\ -ZR75paK4zcUngupYXWSGWFXPTV7vssFk6vInePArTL+T9KwHfiZ29Pp3UbzDlysY\n\ -Kz9f9Ae50jGD6xVPwXgQ/VI979GyFXzhiEMtSYykF04tBJiDl2/FZxbHPpNxC39t\n\ -14kwuDqBin9N/ZbT5+45tbbS8ziXS+QgL5hD2q2eYCWayrGEt1Y+jDAdHDHmGnZ8\n\ -d4hbgILJAs3IInOCDjC4c1gwHFb8G4QHHTwVhjhqpkq2hQHgzWBC1l2Dku/oDYev\n\ -Zu/pfpTo3z6+NOYBrUWseQmIuG+DGMQA9KOuSQveyTywBm4G4vZKn0sCu1/v2+9T\n\ -BGv41tgS/Yf6oeeQVrbS4RFY1r9qTK6DW9wkTTesa4xoDKQrWjSJ7+aa8tvBXLGX\n\ -x2xdRNWLeRMuGBSOihwXmDr+rCJRauT7pItN5X+uWNTX1ofNksQSUMaFJ5K7L0LU\n\ -iQqU2Yyt/8UphdVZL4EFkGSA13UDWtb9mM1hY0h65LlSYwCchEphrtI9cuV+ITrS\n\ -NcN6cP/dqDx1/jWd6dqjNu7+dugwX5elQS9uUYCFmugR5s1m2eeBg3QuC7gZLE0N\n\ -NbgS7oSxKJe9KeOcw68jHWfBKsCfBfQ4fU2t/ntMybT3hCdEMQu4dgM5Tyw/UeFq\n\ -0SaJyTl+G1bTzS0FW6uUp6NLAgMBAAGjUDBOMB0GA1UdDgQWBBQjbC09PildeLhs\n\ -Pqriuy4ebIfyUzAfBgNVHSMEGDAWgBQjbC09PildeLhsPqriuy4ebIfyUzAMBgNV\n\ -HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQCwRJpJCgp7S+k9BT6X3kBefonE\n\ -EOYtyWXBPpuyG3Qlm1rdhc66DCGForDmTxjMmHYtNmAVnM37ILW7MoflWrAkaY19\n\ -gv88Fzwa5e6rWK4fTSpiEOc5WB2A3HPN9wJnhQXt1WWMDD7jJSLxLIwFqkzpDbDE\n\ -9122TtnIbmKNv0UQpzPV3Ygbqojy6eZHUOT05NaOT7vviv5QwMAH5WeRfiCys8CG\n\ -Sno/o830OniEHvePTYswLlX22LyfSHeoTQCCI8pocytl7IwARKCvBgeFqvPrMiqP\n\ -ch16FiU9II8KaMgpebrUSz3J1BApOOd1LBd42BeTAkNSxjRvbh8/lDWfnE7ODbKc\n\ -b6Ad3V9flFb5OBZH4aTi6QfrDnBmbLgLL8o/MLM+d3Kg94XRU9LjC2rjivQ6MC53\n\ -EnWNobcJFY+soXsJokGtFxKgIx8XrhF5GOsT2f1pmMlYL4cjlU0uWkPOOkhq8tIp\n\ -R8cBYphzXu1v6h2AaZLRq184e30ZO98omKyQoQ2KAm5AZayRrZZtjvEZPNamSuVQ\n\ -iPe3o/4tyQGq+jEMAEjLlDECu0dEa6RFntcbBPMBP3wZwE2bI9GYgvyaZd63DNdm\n\ -Xd65m0mmfOWYttfrDT3Q95YP54nHpIxKBw1eFOzrnXOqbKVmJ/1FDP2yWeooKVLf\n\ -KvbxUcDaVvXB0EU0bg==\n\ ------END CERTIFICATE-----"; - -char *test_privatekey = "data:,-----BEGIN RSA PRIVATE KEY-----\n\ -MIIJKQIBAAKCAgEA3W29+ID6194bH6ejLrIC4hb2Ugo8v6ZC+Mrck2dNYMNPjcOK\n\ -ABvxxEtBamnSaeU/IY7FC/giN622LEtV/3oDcrua0+yWuVafyxmZyTKUb4/GUgaf\n\ -RQPf/eiX9urWurtIK7XgNGFNUjYPq4dSJQPPhwCHE/LKAykWnZBXRrX0Dq4XyApN\n\ -ku0IpjIjEXH+8ixE12wH8wt7DEvdO7T3N3CfUbaITl1qBX+Nm2Z6q4Ag/u5rl8NJ\n\ -fXg71ZmXA3XOj7zFvpyapRIZcPmkvZYn7SMCp8dXyXHPdpSiIWL2uB3KiO4JrUYv\n\ -t2GzLBUThp+lNSZaZ/Q3yOaAAUkOx+1h08285Pi+P8lO+H2Xic4SvMq1xtLg2bNo\n\ -PC5KnbRfuFPuUD2/3dSiiragJ6uYDLOyWJDivKGt/72OVTEPAL9o6T2pGZrwbQui\n\ -FGrGTMZOvWMSpQtNl+tCCXlT4mWqJDRwuMGrI4DnnGzt3IKqNwS4Qyo9KqjMIPwn\n\ -XZAmWPm3FOKe4sFwc5fpawKO01JZewDsYTDxVj+cwXwFxbE2yBiFz2FAHwfopwaH\n\ -35p3C6lkcgP2k/zgAlnBluzACUI+MKJ/G0gv/uAhj1OHJQ3L6kn1SpvQ41/ueBjl\n\ -unExqQSYD7GtZ1Kg8uOcq2r+WISE3Qc9MpQFFkUVllmgWGwYDuN3Zsez95kCAwEA\n\ -AQKCAgBymEHxouau4z6MUlisaOn/Ej0mVi/8S1JrqakgDB1Kj6nTRzhbOBsWKJBR\n\ -PzTrIv5aIqYtvJwQzrDyGYcHMaEpNpg5Rz716jPGi5hAPRH+7pyHhO/Watv4bvB+\n\ -lCjO+O+v12+SDC1U96+CaQUFLQSw7H/7vfH4UsJmhvX0HWSSWFzsZRCiklOgl1/4\n\ -vlNgB7MU/c7bZLyor3ZuWQh8Q6fgRSQj0kp1T/78RrwDl8r7xG4gW6vj6F6m+9bg\n\ -ro5Zayu3qxqJhWVvR3OPvm8pVa4hIJR5J5Jj3yZNOwdOX/Saiv6tEx7MvB5bGQlC\n\ -6co5SIEPPZ/FNC1Y/PNOWrb/Q4GW1AScdICZu7wIkKzWAJCo59A8Luv5FV8vm4R2\n\ -4JkyB6kXcVfowrjYXqDF/UX0ddDLLGF96ZStte3PXX8PQWY89FZuBkGw6NRZInHi\n\ -xinN2V8cm7Cw85d9Ez2zEGB4KC7LI+JgLQtdg3XvbdfhOi06eGjgK2mwfOqT8Sq+\n\ -v9POIJXTNEI3fi3dB86af/8OXRtOrAa1mik2msDI1Goi7cKQbC3fz/p1ISQCptvs\n\ -YvNwstDDutkA9o9araQy5b0LC6w5k+CSdVNbd8O2EUd0OBOUjblHKvdZ3Voz8EDF\n\ -ywYimmNGje1lK8nh2ndpja5q3ipDs1hKg5UujoGfei2gn0ch5QKCAQEA8O+IHOOu\n\ -T/lUgWspophE0Y1aUJQPqgK3EiKB84apwLfz2eAPSBff2dCN7Xp6s//u0fo41LE5\n\ -P0ds/5eu9PDlNF6HH5H3OYpV/57v5O2OSBQdB/+3TmNmQGYJCSzouIS3YNOUPQ1z\n\ -FFvRateN91BW7wKFHr0+M4zG6ezfutAQywWNoce7oGaYTT8z/yWXqmFidDqng5w5\n\ -6d8t40ScozIVacGug+lRi8lbTC+3Tp0r+la66h49upged3hFOvGXIOybvYcE98K2\n\ -GpNl9cc4q6O1WLdR7QC91ZNflKOKE8fALLZ/stEXL0p2bixbSnbIdxOEUch/iQhM\n\ -chxlsRFLjxV1dwKCAQEA60X6LyefIlXzU3PA+gIRYV0g8FOxzxXfvqvYeyOGwDaa\n\ -p/Ex50z76jIJK8wlW5Ei7U6xsxxw3E9DLH7Sf3H4KiGouBVIdcv9+IR0LcdYPR9V\n\ -oCQ1Mm5a7fjnm/FJwTokdgWGSwmFTH7/jGcNHZ8lumlRFCj6VcLT/nRxM6dgIXSo\n\ -w1D9QGC9V+e6KOZ6VR5xK0h8pOtkqoGrbFLu26GPBSuguPJXt0fwJt9PAG+6VvxJ\n\ -89NLML/n+g2/jVKXhfTT1Mbb3Fx4lnbLnkP+JrvYIaoQ1PZNggILYCUGJJTLtqOT\n\ -gkg1S41/X8EFg671kAB6ZYPbd5WnL14Xp0a9MOB/bwKCAQEA6WVAl6u/al1/jTdA\n\ -R+/1ioHB4Zjsa6bhrUGcXUowGy6XnJG+e/oUsS2kr04cm03sDaC1eOSNLk2Euzw3\n\ -EbRidI61mtGNikIF+PAAN+YgFJbXYK5I5jjIDs5JJohIkKaP9c5AJbxnpGslvLg/\n\ -IDrFXBc22YY9QTa4YldCi/eOrP0eLIANs95u3zXAqwPBnh1kgG9pYsbuGy5Fh4kp\n\ -q7WSpLYo1kQo6J8QQAdhLVh4B7QIsU7GQYGm0djCR81Mt2o9nCW1nEUUnz32YVay\n\ -ASM/Q0eip1I2kzSGPLkHww2XjjjkD1cZfIhHnYZ+kO3sV92iKo9tbFOLqmbz48l7\n\ -RoplFQKCAQEA6i+DcoCL5A+N3tlvkuuQBUw/xzhn2uu5BP/kwd2A+b7gfp6Uv9lf\n\ -P6SCgHf6D4UOMQyN0O1UYdb71ESAnp8BGF7cpC97KtXcfQzK3+53JJAWGQsxcHts\n\ -Q0foss6gTZfkRx4EqJhXeOdI06aX5Y5ObZj7PYf0dn0xqyyYqYPHKkYG3jO1gelJ\n\ -T0C3ipKv3h4pI55Jg5dTYm0kBvUeELxlsg3VM4L2UNdocikBaDvOTVte+Taut12u\n\ -OLaKns9BR/OFD1zJ6DSbS5n/4A9p4YBFCG1Rx8lLKUeDrzXrQWpiw+9amunpMsUr\n\ -rlJhfMwgXjA7pOR1BjmOapXMEZNWKlqsPQKCAQByVDxIwMQczUFwQMXcu2IbA3Z8\n\ -Czhf66+vQWh+hLRzQOY4hPBNceUiekpHRLwdHaxSlDTqB7VPq+2gSkVrCX8/XTFb\n\ -SeVHTYE7iy0Ckyme+2xcmsl/DiUHfEy+XNcDgOutS5MnWXANqMQEoaLW+NPLI3Lu\n\ -V1sCMYTd7HN9tw7whqLg18wB1zomSMVGT4DkkmAzq4zSKI1FNYp8KA3OE1Emwq+0\n\ -wRsQuawQVLCUEP3To6kYOwTzJq7jhiUK6FnjLjeTrNQSVdoqwoJrlTAHgXVV3q7q\n\ -v3TGd3xXD9yQIjmugNgxNiwAZzhJs/ZJy++fPSJ1XQxbd9qPghgGoe/ff6G7\n\ ------END RSA PRIVATE KEY-----"; - - - -DDS_Security_ValidationResult_t -validate_local_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *local_identity_handle, - DDS_Security_GUID_t *adjusted_participant_guid, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - const DDS_Security_GUID_t *candidate_participant_guid, - - DDS_Security_SecurityException *ex); -DDS_Security_boolean -get_identity_token(dds_security_authentication *instance, - DDS_Security_IdentityToken *identity_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex); -DDS_Security_boolean -set_permissions_credential_and_token( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle handle, - const DDS_Security_PermissionsCredentialToken *permissions_credential, - const DDS_Security_PermissionsToken *permissions_token, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -validate_remote_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *remote_identity_handle, - DDS_Security_AuthRequestMessageToken *local_auth_request_token, - const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityToken *remote_identity_token, - const DDS_Security_GUID_t *remote_participant_guid, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -begin_handshake_request( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -begin_handshake_reply( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -process_handshake( - dds_security_authentication *instance, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_SharedSecretHandle get_shared_secret( - dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -get_authenticated_peer_credential_token( - dds_security_authentication *instance, - DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean get_identity_status_token( - dds_security_authentication *instance, - DDS_Security_IdentityStatusToken *identity_status_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean set_listener(dds_security_authentication *instance, - const dds_security_authentication_listener *listener, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_identity_token(dds_security_authentication *instance, - const DDS_Security_IdentityToken *token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_identity_status_token( - dds_security_authentication *instance, - const DDS_Security_IdentityStatusToken *token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_authenticated_peer_credential_token( - dds_security_authentication *instance, - const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -return_handshake_handle(dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); -DDS_Security_boolean -return_identity_handle( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle identity_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_sharedsecret_handle( - dds_security_authentication *instance, - const DDS_Security_SharedSecretHandle sharedsecret_handle, - DDS_Security_SecurityException *ex); - - - -#endif /* SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ */ diff --git a/src/security/core/tests/plugin_loading/plugin_mock/authentication_init_error/mock_authentication.c b/src/security/core/tests/plugin_loading/plugin_mock/authentication_init_error/mock_authentication.c deleted file mode 100644 index d42e4f5..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/authentication_init_error/mock_authentication.c +++ /dev/null @@ -1,347 +0,0 @@ -/* - * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -#include "dds/security/dds_security_api.h" -#include "dds/ddsrt/heap.h" -#include "dds/ddsrt/misc.h" -#include "mock_authentication.h" -#include -#include -#include - -/** - * Implementation structure for storing encapsulated members of the instance - * while giving only the interface definition to user - */ - -typedef struct dds_security_authentication_impl { - dds_security_authentication base; - int id; //sample internal member -} dds_security_authentication_impl; - -DDS_Security_ValidationResult_t validate_local_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *local_identity_handle, - DDS_Security_GUID_t *adjusted_participant_guid, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - const DDS_Security_GUID_t *candidate_participant_guid, - DDS_Security_SecurityException *ex) -{ - - unsigned i; - DDS_Security_ValidationResult_t result=DDS_SECURITY_VALIDATION_OK; - dds_security_authentication_impl *implementation = - (dds_security_authentication_impl *) instance; - char *identity_ca = NULL; - char *identity_certificate = NULL; - char *private_key = NULL; - - DDSRT_UNUSED_ARG(local_identity_handle); - DDSRT_UNUSED_ARG(adjusted_participant_guid); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(participant_qos); - DDSRT_UNUSED_ARG(candidate_participant_guid); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - implementation->id = 2; - - memcpy(adjusted_participant_guid, candidate_participant_guid, sizeof(DDS_Security_GUID_t)); - - for( i=0; i< participant_qos->property.value._length; i++) - { - - //printf("%s: %s",participant_qos->property.value._buffer[i].name, participant_qos->property.value._buffer[i].value); - printf("%s\n",participant_qos->property.value._buffer[i].name); - if( strcmp(participant_qos->property.value._buffer[i].name, "dds.sec.auth.private_key") == 0) - { - private_key = participant_qos->property.value._buffer[i].value; - } else if( strcmp(participant_qos->property.value._buffer[i].name, "dds.sec.auth.identity_ca") == 0) - { - identity_ca = participant_qos->property.value._buffer[i].value; - } else if( strcmp(participant_qos->property.value._buffer[i].name, "dds.sec.auth.identity_certificate") == 0) - { - identity_certificate = participant_qos->property.value._buffer[i].value; - } - } - - if( strcmp(identity_certificate, test_identity_certificate) != 0){ - - result = DDS_SECURITY_VALIDATION_FAILED; - printf("FAILED: Could not get identity_certificate value properly\n"); - } - else if( strcmp(identity_ca, test_ca_certificate) != 0){ - printf("FAILED: Could not get identity_ca value properly\n"); - result = DDS_SECURITY_VALIDATION_FAILED; - }else if( strcmp(private_key, test_privatekey) != 0){ - printf("FAILED: Could not get private_key value properly\n"); - result = DDS_SECURITY_VALIDATION_FAILED; - } - - if( result == DDS_SECURITY_VALIDATION_OK ) - { - printf("DDS_SECURITY_VALIDATION_OK\n"); - } - - - return result; -} - -DDS_Security_boolean get_identity_token(dds_security_authentication *instance, - DDS_Security_IdentityToken *identity_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(identity_token); - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - memset(identity_token, 0, sizeof(*identity_token)); - - return true; -} - -DDS_Security_boolean get_identity_status_token( - dds_security_authentication *instance, - DDS_Security_IdentityStatusToken *identity_status_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(identity_status_token); - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean set_permissions_credential_and_token( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle handle, - const DDS_Security_PermissionsCredentialToken *permissions_credential, - const DDS_Security_PermissionsToken *permissions_token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(permissions_credential); - DDSRT_UNUSED_ARG(permissions_token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_ValidationResult_t validate_remote_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *remote_identity_handle, - DDS_Security_AuthRequestMessageToken *local_auth_request_token, - const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityToken *remote_identity_token, - const DDS_Security_GUID_t *remote_participant_guid, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(remote_identity_handle); - DDSRT_UNUSED_ARG(local_auth_request_token); - DDSRT_UNUSED_ARG(remote_auth_request_token); - DDSRT_UNUSED_ARG(local_identity_handle); - DDSRT_UNUSED_ARG(remote_identity_token); - DDSRT_UNUSED_ARG(remote_participant_guid); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_ValidationResult_t begin_handshake_request( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(handshake_message); - DDSRT_UNUSED_ARG(initiator_identity_handle); - DDSRT_UNUSED_ARG(replier_identity_handle); - DDSRT_UNUSED_ARG(serialized_local_participant_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_ValidationResult_t begin_handshake_reply( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(handshake_message_out); - DDSRT_UNUSED_ARG(handshake_message_in); - DDSRT_UNUSED_ARG(initiator_identity_handle); - DDSRT_UNUSED_ARG(replier_identity_handle); - DDSRT_UNUSED_ARG(serialized_local_participant_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_ValidationResult_t process_handshake( - dds_security_authentication *instance, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_message_out); - DDSRT_UNUSED_ARG(handshake_message_in); - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_SharedSecretHandle get_shared_secret( - dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return 0; -} - -DDS_Security_boolean get_authenticated_peer_credential_token( - dds_security_authentication *instance, - DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(peer_credential_token); - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean set_listener(dds_security_authentication *instance, - const dds_security_authentication_listener *listener, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(listener); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_identity_token(dds_security_authentication *instance, - const DDS_Security_IdentityToken *token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_identity_status_token( - dds_security_authentication *instance, - const DDS_Security_IdentityStatusToken *token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_authenticated_peer_credential_token( - dds_security_authentication *instance, - const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(peer_credential_token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_handshake_handle(dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_identity_handle(dds_security_authentication *instance, - const DDS_Security_IdentityHandle identity_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(identity_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_sharedsecret_handle( - dds_security_authentication *instance, - const DDS_Security_SharedSecretHandle sharedsecret_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(sharedsecret_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -int32_t init_authentication( const char *argument, void **context) -{ - - DDSRT_UNUSED_ARG(argument); - DDSRT_UNUSED_ARG(context); - - /* return error code for test purposes */ - return 1; -} - -int32_t finalize_authentication(void *instance) -{ - - ddsrt_free((dds_security_authentication_impl*) instance); - - return 0; -} diff --git a/src/security/core/tests/plugin_loading/plugin_mock/authentication_init_error/mock_authentication.h b/src/security/core/tests/plugin_loading/plugin_mock/authentication_init_error/mock_authentication.h deleted file mode 100644 index faceace..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/authentication_init_error/mock_authentication.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#ifndef SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ -#define SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ - -#include "dds/security/authentication_init_error_export.h" - -SECURITY_EXPORT int32_t -init_authentication(const char *argument, void **context); - -SECURITY_EXPORT int32_t -finalize_authentication(void *context); - -char *test_identity_certificate="data:,-----BEGIN CERTIFICATE-----\n\ -MIIDYDCCAkigAwIBAgIBBDANBgkqhkiG9w0BAQsFADByMQswCQYDVQQGEwJOTDEL\n\ -MAkGA1UECBMCT1YxEzARBgNVBAoTCkFETGluayBJU1QxGTAXBgNVBAMTEElkZW50\n\ -aXR5IENBIFRlc3QxJjAkBgkqhkiG9w0BCQEWF2luZm9AaXN0LmFkbGlua3RlY2gu\n\ -Y29tMB4XDTE4MDMxMjAwMDAwMFoXDTI3MDMxMTIzNTk1OVowdTELMAkGA1UEBhMC\n\ -TkwxCzAJBgNVBAgTAk9WMRAwDgYDVQQKEwdBRExpbmsgMREwDwYDVQQLEwhJU1Qg\n\ -VGVzdDETMBEGA1UEAxMKQWxpY2UgVGVzdDEfMB0GCSqGSIb3DQEJARYQYWxpY2VA\n\ -YWRsaW5rLmlzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANBW+tEZ\n\ -Baw7EQCEXyzH9n7IkZ8PQIKe8hG1LAOGYOF/oUYQZJO/HxbWoC4rFqOC20+A6is6\n\ -kFwr1Zzp/Wurk9CrFXo5Nomi6ActH6LUM57nYqN68w6U38z/XkQxVY/ESZ5dySfD\n\ -9Q1C8R+zdE8gwbimdYmwX7ioz336nghM2CoAHPDRthQeJupl8x4V7isOltr9CGx8\n\ -+imJXbGr39OK6u87cNLeu23sUkOIC0lSRMIqIQK3oJtHS70J2qecXdqp9MhE7Xky\n\ -/GPlI8ptQ1gJ8A3cAOvtI9mtMJMszs2EKWTLfeTcmfJHKKhKjvCgDdh3Jan4x5YP\n\ -Yg7HG6H+ceOUkMMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAkvuqZzyJ3Nu4/Eo5\n\ -kD0nVgYGBUl7cspu+636q39zPSrxLEDMUWz+u8oXLpyGcgiZ8lZulPTV8dmOn+3C\n\ -Vg55c5C+gbnbX3MDyb3wB17296RmxYf6YNul4sFOmj6+g2i+Dw9WH0PBCVKbA84F\n\ -jR3Gx2Pfoifor3DvT0YFSsjNIRt090u4dQglbIb6cWEafC7O24t5jFhGPvJ7L9SE\n\ -gB0Drh/HmKTVuaqaRkoOKkKaKuWoXsszK1ZFda1DHommnR5LpYPsDRQ2fVM4EuBF\n\ -By03727uneuG8HLuNcLEV9H0i7LxtyfFkyCPUQvWG5jehb7xPOz/Ml26NAwwjlTJ\n\ -xEEFrw==\n\ ------END CERTIFICATE-----"; - -char *test_ca_certificate="data:,-----BEGIN CERTIFICATE-----\n\ -MIIEKTCCAxGgAwIBAgIBATANBgkqhkiG9w0BAQsFADByMQswCQYDVQQGEwJOTDEL\n\ -MAkGA1UECBMCT1YxEzARBgNVBAoTCkFETGluayBJU1QxGTAXBgNVBAMTEElkZW50\n\ -aXR5IENBIFRlc3QxJjAkBgkqhkiG9w0BCQEWF2luZm9AaXN0LmFkbGlua3RlY2gu\n\ -Y29tMB4XDTE4MDMxMjAwMDAwMFoXDTI3MDMxMTIzNTk1OVowcjELMAkGA1UEBhMC\n\ -TkwxCzAJBgNVBAgTAk9WMRMwEQYDVQQKEwpBRExpbmsgSVNUMRkwFwYDVQQDExBJ\n\ -ZGVudGl0eSBDQSBUZXN0MSYwJAYJKoZIhvcNAQkBFhdpbmZvQGlzdC5hZGxpbmt0\n\ -ZWNoLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANa/ENFfGVXg\n\ -bPLTzBdDfiZQcp5dWZ//Pb8ErFOJu8uosVHFv8t69dgjHgNHB4OsjmjnR7GfKUZT\n\ -0cMvWJnjsC7DDlBwFET9rj4k40n96bbVCH9I7+tNhsoqzc6Eu+5h4sk7VfNGTM2Z\n\ -SyCd4GiSZRuA44rRbhXI7/LDpr4hY5J9ZDo5AM9ZyoLAoh774H3CZWD67S35XvUs\n\ -72dzE6uKG/vxBbvZ7eW2GLO6ewa9UxlnLVMPfJdpkp/xYXwwcPW2+2YXCge1ujxs\n\ -tjrOQJ5HUySh6DkE/kZpx8zwYWm9AaCrsvCIX1thsqgvKy+U5v1FS1L58eGc6s//\n\ -9yMgNhU29R0CAwEAAaOByTCBxjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRNVUJN\n\ -FzhJPReYT4QSx6dK53CXCTAfBgNVHSMEGDAWgBRNVUJNFzhJPReYT4QSx6dK53CX\n\ -CTAPBgNVHQ8BAf8EBQMDB/+AMGUGA1UdJQEB/wRbMFkGCCsGAQUFBwMBBggrBgEF\n\ -BQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkGCCsG\n\ -AQUFBwMNBggrBgEFBQcDDgYHKwYBBQIDBTANBgkqhkiG9w0BAQsFAAOCAQEAcOLF\n\ -ZYdJguj0uxeXB8v3xnUr1AWz9+gwg0URdfNLU2KvF2lsb/uznv6168b3/FcPgezN\n\ -Ihl9GqB+RvGwgXS/1UelCGbQiIUdsNxk246P4uOGPIyW32RoJcYPWZcpY+cw11tQ\n\ -NOnk994Y5/8ad1DmcxVLLqq5kwpXGWQufV1zOONq8B+mCvcVAmM4vkyF/de56Lwa\n\ -sAMpk1p77uhaDnuq2lIR4q3QHX2wGctFid5Q375DRscFQteY01r/dtwBBrMn0wuL\n\ -AMNx9ZGD+zAoOUaslpIlEQ+keAxk3jgGMWFMxF81YfhEnXzevSQXWpyek86XUyFL\n\ -O9IAQi5pa15gXjSbUg==\n\ ------END CERTIFICATE-----"; - -char *test_privatekey = "data:,-----BEGIN RSA PRIVATE KEY-----\n\ -MIIEowIBAAKCAQEA0Fb60RkFrDsRAIRfLMf2fsiRnw9Agp7yEbUsA4Zg4X+hRhBk\n\ -k78fFtagLisWo4LbT4DqKzqQXCvVnOn9a6uT0KsVejk2iaLoBy0fotQznudio3rz\n\ -DpTfzP9eRDFVj8RJnl3JJ8P1DULxH7N0TyDBuKZ1ibBfuKjPffqeCEzYKgAc8NG2\n\ -FB4m6mXzHhXuKw6W2v0IbHz6KYldsavf04rq7ztw0t67bexSQ4gLSVJEwiohAreg\n\ -m0dLvQnap5xd2qn0yETteTL8Y+Ujym1DWAnwDdwA6+0j2a0wkyzOzYQpZMt95NyZ\n\ -8kcoqEqO8KAN2HclqfjHlg9iDscbof5x45SQwwIDAQABAoIBAG0dYPeqd0IhHWJ7\n\ -8azufbchLMN1pX/D51xG2uptssfnpHuhkkufSZUYi4QipRS2ME6PYhWJ8pmTi6lH\n\ -E6cUkbI0KGd/F4U2gPdhNrR9Fxwea5bbifkVF7Gx/ZkRjZJiZ3w9+mCNTQbJDKhh\n\ -wITAzzT6WYznhvqbzzBX1fTa6kv0GAQtX7aHKM+XIwkhX2gzU5TU80bvH8aMrT05\n\ -tAMGQqkUeRnpo0yucBl4VmTZzd/+X/d2UyXR0my15jE5iH5o+p+E6qTRE9D+MGUd\n\ -MQ6Ftj0Untqy1lcog1ZLL6zPlnwcD4jgY5VCYDgvabnrSwymOJapPLsAEdWdq+U5\n\ -ec44BMECgYEA/+3qPUrd4XxA517qO3fCGBvf2Gkr7w5ZDeATOTHGuD8QZeK0nxPl\n\ -CWhRjdgkqo0fyf1cjczL5XgYayo+YxkO1Z4RUU+8lJAHlVx9izOQo+MTQfkwH4BK\n\ -LYlHxMoHJwAOXXoE+dmBaDh5xT0mDUGU750r763L6EFovE4qRBn9hxkCgYEA0GWz\n\ -rpOPNxb419WxG9npoQYdCZ5IbmEOGDH3ReggVzWHmW8sqtkqTZm5srcyDpqAc1Gu\n\ -paUveMblEBbU+NFJjLWOfwB5PCp8jsrqRgCQSxolShiVkc3Vu3oyzMus9PDge1eo\n\ -9mwVGO7ojQKWRu/WVAakENPaAjeyyhv4dqSNnjsCgYEAlwe8yszqoY1k8+U0T0G+\n\ -HeIdOCXgkmOiNCj+zyrLvaEhuS6PLq1b5TBVqGJcSPWdQ+MrglbQIKu9pUg5ptt7\n\ -wJ5WU+i9PeK9Ruxc/g/BFKYFkFJQjtZzb+nqm3wpul8zGwDN/O/ZiTqCyd3rHbmM\n\ -/dZ/viKPCZHIEBAEq0m3LskCgYBndzcAo+5k8ZjWwBfQth5SfhCIp/daJgGzbYtR\n\ -P/BenAsY2KOap3tjT8Fsw5usuHSxzIojX6H0Gvu7Qzq11mLn43Q+BeQrRQTWeFRc\n\ -MQdy4iZFZXNNEp7dF8yE9VKHwdgSJPGUdxD6chMvf2tRCN6mlS171VLV6wVvZvez\n\ -H/vX5QKBgD2Dq/NHpjCpAsECP9awmNF5Akn5WJbRGmegwXIih2mOtgtYYDeuQyxY\n\ -ZCrdJFfIUjUVPagshEmUklKhkYMYpzy2PQDVtaVcm6UNFroxT5h+J+KDs1LN1H8G\n\ -LsASrzyAg8EpRulwXEfLrWKiu9DKv8bMEgO4Ovgz8zTKJZIFhcac\n\ ------END RSA PRIVATE KEY-----"; - - -DDS_Security_ValidationResult_t -validate_local_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *local_identity_handle, - DDS_Security_GUID_t *adjusted_participant_guid, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - const DDS_Security_GUID_t *candidate_participant_guid, - - DDS_Security_SecurityException *ex); -DDS_Security_boolean -get_identity_token(dds_security_authentication *instance, - DDS_Security_IdentityToken *identity_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex); -DDS_Security_boolean -set_permissions_credential_and_token( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle handle, - const DDS_Security_PermissionsCredentialToken *permissions_credential, - const DDS_Security_PermissionsToken *permissions_token, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -validate_remote_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *remote_identity_handle, - DDS_Security_AuthRequestMessageToken *local_auth_request_token, - const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityToken *remote_identity_token, - const DDS_Security_GUID_t *remote_participant_guid, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -begin_handshake_request( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -begin_handshake_reply( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -process_handshake( - dds_security_authentication *instance, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_SharedSecretHandle get_shared_secret( - dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -get_authenticated_peer_credential_token( - dds_security_authentication *instance, - DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean get_identity_status_token( - dds_security_authentication *instance, - DDS_Security_IdentityStatusToken *identity_status_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean set_listener(dds_security_authentication *instance, - const dds_security_authentication_listener *listener, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_identity_token(dds_security_authentication *instance, - const DDS_Security_IdentityToken *token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_identity_status_token( - dds_security_authentication *instance, - const DDS_Security_IdentityStatusToken *token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_authenticated_peer_credential_token( - dds_security_authentication *instance, - const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -return_handshake_handle(dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); -DDS_Security_boolean -return_identity_handle( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle identity_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_sharedsecret_handle( - dds_security_authentication *instance, - const DDS_Security_SharedSecretHandle sharedsecret_handle, - DDS_Security_SecurityException *ex); - - - -#endif /* SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ */ diff --git a/src/security/core/tests/plugin_loading/plugin_mock/authentication_missing_function/mock_authentication.c b/src/security/core/tests/plugin_loading/plugin_mock/authentication_missing_function/mock_authentication.c deleted file mode 100644 index c80c8d1..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/authentication_missing_function/mock_authentication.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * authentication.c - * - * Created on: Jan 12, 2018 - * Author: kurtulus oksuztepe - * - * Description: This file implements the Authentication interface for DDS Security 1.2 - * - */ - -#include "dds/security/dds_security_api.h" -#include "dds/ddsrt/heap.h" -#include "dds/ddsrt/misc.h" -#include "mock_authentication.h" -#include -#include -#include -#include - -/** - * Implementation structure for storing encapsulated members of the instance - * while giving only the interface definition to user - */ - -typedef struct dds_security_authentication_impl { - dds_security_authentication base; - int id; //sample internal member -} dds_security_authentication_impl; - -DDS_Security_ValidationResult_t validate_local_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *local_identity_handle, - DDS_Security_GUID_t *adjusted_participant_guid, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - const DDS_Security_GUID_t *candidate_participant_guid, - DDS_Security_SecurityException *ex) -{ - - unsigned i; - DDS_Security_ValidationResult_t result=DDS_SECURITY_VALIDATION_OK; - dds_security_authentication_impl *implementation = - (dds_security_authentication_impl *) instance; - char *identity_ca = NULL; - char *identity_certificate = NULL; - char *private_key = NULL; - - DDSRT_UNUSED_ARG(local_identity_handle); - DDSRT_UNUSED_ARG(adjusted_participant_guid); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(participant_qos); - DDSRT_UNUSED_ARG(candidate_participant_guid); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - implementation->id = 2; - - memcpy(adjusted_participant_guid, candidate_participant_guid, sizeof(DDS_Security_GUID_t)); - - for( i=0; i< participant_qos->property.value._length; i++) - { - - //printf("%s: %s",participant_qos->property.value._buffer[i].name, participant_qos->property.value._buffer[i].value); - printf("%s\n",participant_qos->property.value._buffer[i].name); - if( strcmp(participant_qos->property.value._buffer[i].name, "dds.sec.auth.private_key") == 0) - { - private_key = participant_qos->property.value._buffer[i].value; - } else if( strcmp(participant_qos->property.value._buffer[i].name, "dds.sec.auth.identity_ca") == 0) - { - identity_ca = participant_qos->property.value._buffer[i].value; - } else if( strcmp(participant_qos->property.value._buffer[i].name, "dds.sec.auth.identity_certificate") == 0) - { - identity_certificate = participant_qos->property.value._buffer[i].value; - } - } - - /* for Clang's static analyzer */ - assert(identity_certificate != NULL); - assert(identity_ca != NULL); - assert(private_key != NULL); - - if( strcmp(identity_certificate, test_identity_certificate) != 0){ - - result = DDS_SECURITY_VALIDATION_FAILED; - printf("FAILED: Could not get identity_certificate value properly\n"); - } - else if( strcmp(identity_ca, test_ca_certificate) != 0){ - printf("FAILED: Could not get identity_ca value properly\n"); - result = DDS_SECURITY_VALIDATION_FAILED; - }else if( strcmp(private_key, test_privatekey) != 0){ - printf("FAILED: Could not get private_key value properly\n"); - result = DDS_SECURITY_VALIDATION_FAILED; - } - - if( result == DDS_SECURITY_VALIDATION_OK ) - { - printf("DDS_SECURITY_VALIDATION_OK\n"); - } - - - return result; -} - -DDS_Security_boolean get_identity_token(dds_security_authentication *instance, - DDS_Security_IdentityToken *identity_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(identity_token); - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - memset(identity_token, 0, sizeof(*identity_token)); - - return true; -} - -DDS_Security_boolean get_identity_status_token( - dds_security_authentication *instance, - DDS_Security_IdentityStatusToken *identity_status_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(identity_status_token); - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean set_permissions_credential_and_token( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle handle, - const DDS_Security_PermissionsCredentialToken *permissions_credential, - const DDS_Security_PermissionsToken *permissions_token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(permissions_credential); - DDSRT_UNUSED_ARG(permissions_token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_ValidationResult_t validate_remote_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *remote_identity_handle, - DDS_Security_AuthRequestMessageToken *local_auth_request_token, - const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityToken *remote_identity_token, - const DDS_Security_GUID_t *remote_participant_guid, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(remote_identity_handle); - DDSRT_UNUSED_ARG(local_auth_request_token); - DDSRT_UNUSED_ARG(remote_auth_request_token); - DDSRT_UNUSED_ARG(local_identity_handle); - DDSRT_UNUSED_ARG(remote_identity_token); - DDSRT_UNUSED_ARG(remote_participant_guid); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_ValidationResult_t begin_handshake_request( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(handshake_message); - DDSRT_UNUSED_ARG(initiator_identity_handle); - DDSRT_UNUSED_ARG(replier_identity_handle); - DDSRT_UNUSED_ARG(serialized_local_participant_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_ValidationResult_t begin_handshake_reply( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(handshake_message_out); - DDSRT_UNUSED_ARG(handshake_message_in); - DDSRT_UNUSED_ARG(initiator_identity_handle); - DDSRT_UNUSED_ARG(replier_identity_handle); - DDSRT_UNUSED_ARG(serialized_local_participant_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_ValidationResult_t process_handshake( - dds_security_authentication *instance, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_message_out); - DDSRT_UNUSED_ARG(handshake_message_in); - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return DDS_SECURITY_VALIDATION_OK; -} - -DDS_Security_SharedSecretHandle get_shared_secret( - dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return 0; -} - -DDS_Security_boolean get_authenticated_peer_credential_token( - dds_security_authentication *instance, - DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(peer_credential_token); - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean set_listener(dds_security_authentication *instance, - const dds_security_authentication_listener *listener, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(listener); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_identity_token(dds_security_authentication *instance, - const DDS_Security_IdentityToken *token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_identity_status_token( - dds_security_authentication *instance, - const DDS_Security_IdentityStatusToken *token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_authenticated_peer_credential_token( - dds_security_authentication *instance, - const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(peer_credential_token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_handshake_handle(dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(handshake_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_identity_handle(dds_security_authentication *instance, - const DDS_Security_IdentityHandle identity_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(identity_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_sharedsecret_handle( - dds_security_authentication *instance, - const DDS_Security_SharedSecretHandle sharedsecret_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(sharedsecret_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -int32_t init_authentication( const char *argument, void **context) -{ - - dds_security_authentication_impl *authentication; - - DDSRT_UNUSED_ARG(argument); - - //allocate implementation wrapper - authentication = (dds_security_authentication_impl*) ddsrt_malloc( - sizeof(dds_security_authentication_impl)); - memset(authentication, 0, sizeof(dds_security_authentication_impl)); - - //assign the interface functions - authentication->base.validate_local_identity = &validate_local_identity; - - authentication->base.get_identity_token = &get_identity_token; - - authentication->base.get_identity_status_token = &get_identity_status_token; - - authentication->base.set_permissions_credential_and_token = - &set_permissions_credential_and_token; - - authentication->base.validate_remote_identity = &validate_remote_identity; - - authentication->base.begin_handshake_request = &begin_handshake_request; - - authentication->base.begin_handshake_reply = &begin_handshake_reply; - - authentication->base.process_handshake = &process_handshake; - - /* missing function - authentication->base.get_shared_secret = &get_shared_secret; - */ - - authentication->base.get_authenticated_peer_credential_token = - &get_authenticated_peer_credential_token; - - authentication->base.set_listener = &set_listener; - - authentication->base.return_identity_token = &return_identity_token; - - authentication->base.return_identity_status_token = - &return_identity_status_token; - - authentication->base.return_authenticated_peer_credential_token = - &return_authenticated_peer_credential_token; - - authentication->base.return_handshake_handle = &return_handshake_handle; - - authentication->base.return_identity_handle = &return_identity_handle; - - authentication->base.return_sharedsecret_handle = &return_sharedsecret_handle; - - //prepare implementation wrapper - authentication->id = 1; - - //return the instance - *context = authentication; - return 0; -} - -int32_t finalize_authentication(void *instance) -{ - - ddsrt_free((dds_security_authentication_impl*) instance); - - return 0; -} diff --git a/src/security/core/tests/plugin_loading/plugin_mock/authentication_missing_function/mock_authentication.h b/src/security/core/tests/plugin_loading/plugin_mock/authentication_missing_function/mock_authentication.h deleted file mode 100644 index d3854b1..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/authentication_missing_function/mock_authentication.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -#ifndef SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ -#define SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ - -#include "dds/security/authentication_missing_function_export.h" - -SECURITY_EXPORT int32_t -init_authentication(const char *argument, void **context); - -SECURITY_EXPORT int32_t -finalize_authentication(void *context); - -char *test_identity_certificate="data:,-----BEGIN CERTIFICATE-----\n\ -MIIDYDCCAkigAwIBAgIBBDANBgkqhkiG9w0BAQsFADByMQswCQYDVQQGEwJOTDEL\n\ -MAkGA1UECBMCT1YxEzARBgNVBAoTCkFETGluayBJU1QxGTAXBgNVBAMTEElkZW50\n\ -aXR5IENBIFRlc3QxJjAkBgkqhkiG9w0BCQEWF2luZm9AaXN0LmFkbGlua3RlY2gu\n\ -Y29tMB4XDTE4MDMxMjAwMDAwMFoXDTI3MDMxMTIzNTk1OVowdTELMAkGA1UEBhMC\n\ -TkwxCzAJBgNVBAgTAk9WMRAwDgYDVQQKEwdBRExpbmsgMREwDwYDVQQLEwhJU1Qg\n\ -VGVzdDETMBEGA1UEAxMKQWxpY2UgVGVzdDEfMB0GCSqGSIb3DQEJARYQYWxpY2VA\n\ -YWRsaW5rLmlzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANBW+tEZ\n\ -Baw7EQCEXyzH9n7IkZ8PQIKe8hG1LAOGYOF/oUYQZJO/HxbWoC4rFqOC20+A6is6\n\ -kFwr1Zzp/Wurk9CrFXo5Nomi6ActH6LUM57nYqN68w6U38z/XkQxVY/ESZ5dySfD\n\ -9Q1C8R+zdE8gwbimdYmwX7ioz336nghM2CoAHPDRthQeJupl8x4V7isOltr9CGx8\n\ -+imJXbGr39OK6u87cNLeu23sUkOIC0lSRMIqIQK3oJtHS70J2qecXdqp9MhE7Xky\n\ -/GPlI8ptQ1gJ8A3cAOvtI9mtMJMszs2EKWTLfeTcmfJHKKhKjvCgDdh3Jan4x5YP\n\ -Yg7HG6H+ceOUkMMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAkvuqZzyJ3Nu4/Eo5\n\ -kD0nVgYGBUl7cspu+636q39zPSrxLEDMUWz+u8oXLpyGcgiZ8lZulPTV8dmOn+3C\n\ -Vg55c5C+gbnbX3MDyb3wB17296RmxYf6YNul4sFOmj6+g2i+Dw9WH0PBCVKbA84F\n\ -jR3Gx2Pfoifor3DvT0YFSsjNIRt090u4dQglbIb6cWEafC7O24t5jFhGPvJ7L9SE\n\ -gB0Drh/HmKTVuaqaRkoOKkKaKuWoXsszK1ZFda1DHommnR5LpYPsDRQ2fVM4EuBF\n\ -By03727uneuG8HLuNcLEV9H0i7LxtyfFkyCPUQvWG5jehb7xPOz/Ml26NAwwjlTJ\n\ -xEEFrw==\n\ ------END CERTIFICATE-----"; - -char *test_ca_certificate="data:,-----BEGIN CERTIFICATE-----\n\ -MIIEKTCCAxGgAwIBAgIBATANBgkqhkiG9w0BAQsFADByMQswCQYDVQQGEwJOTDEL\n\ -MAkGA1UECBMCT1YxEzARBgNVBAoTCkFETGluayBJU1QxGTAXBgNVBAMTEElkZW50\n\ -aXR5IENBIFRlc3QxJjAkBgkqhkiG9w0BCQEWF2luZm9AaXN0LmFkbGlua3RlY2gu\n\ -Y29tMB4XDTE4MDMxMjAwMDAwMFoXDTI3MDMxMTIzNTk1OVowcjELMAkGA1UEBhMC\n\ -TkwxCzAJBgNVBAgTAk9WMRMwEQYDVQQKEwpBRExpbmsgSVNUMRkwFwYDVQQDExBJ\n\ -ZGVudGl0eSBDQSBUZXN0MSYwJAYJKoZIhvcNAQkBFhdpbmZvQGlzdC5hZGxpbmt0\n\ -ZWNoLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANa/ENFfGVXg\n\ -bPLTzBdDfiZQcp5dWZ//Pb8ErFOJu8uosVHFv8t69dgjHgNHB4OsjmjnR7GfKUZT\n\ -0cMvWJnjsC7DDlBwFET9rj4k40n96bbVCH9I7+tNhsoqzc6Eu+5h4sk7VfNGTM2Z\n\ -SyCd4GiSZRuA44rRbhXI7/LDpr4hY5J9ZDo5AM9ZyoLAoh774H3CZWD67S35XvUs\n\ -72dzE6uKG/vxBbvZ7eW2GLO6ewa9UxlnLVMPfJdpkp/xYXwwcPW2+2YXCge1ujxs\n\ -tjrOQJ5HUySh6DkE/kZpx8zwYWm9AaCrsvCIX1thsqgvKy+U5v1FS1L58eGc6s//\n\ -9yMgNhU29R0CAwEAAaOByTCBxjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRNVUJN\n\ -FzhJPReYT4QSx6dK53CXCTAfBgNVHSMEGDAWgBRNVUJNFzhJPReYT4QSx6dK53CX\n\ -CTAPBgNVHQ8BAf8EBQMDB/+AMGUGA1UdJQEB/wRbMFkGCCsGAQUFBwMBBggrBgEF\n\ -BQcDAgYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkGCCsG\n\ -AQUFBwMNBggrBgEFBQcDDgYHKwYBBQIDBTANBgkqhkiG9w0BAQsFAAOCAQEAcOLF\n\ -ZYdJguj0uxeXB8v3xnUr1AWz9+gwg0URdfNLU2KvF2lsb/uznv6168b3/FcPgezN\n\ -Ihl9GqB+RvGwgXS/1UelCGbQiIUdsNxk246P4uOGPIyW32RoJcYPWZcpY+cw11tQ\n\ -NOnk994Y5/8ad1DmcxVLLqq5kwpXGWQufV1zOONq8B+mCvcVAmM4vkyF/de56Lwa\n\ -sAMpk1p77uhaDnuq2lIR4q3QHX2wGctFid5Q375DRscFQteY01r/dtwBBrMn0wuL\n\ -AMNx9ZGD+zAoOUaslpIlEQ+keAxk3jgGMWFMxF81YfhEnXzevSQXWpyek86XUyFL\n\ -O9IAQi5pa15gXjSbUg==\n\ ------END CERTIFICATE-----"; - -char *test_privatekey = "data:,-----BEGIN RSA PRIVATE KEY-----\n\ -MIIEowIBAAKCAQEA0Fb60RkFrDsRAIRfLMf2fsiRnw9Agp7yEbUsA4Zg4X+hRhBk\n\ -k78fFtagLisWo4LbT4DqKzqQXCvVnOn9a6uT0KsVejk2iaLoBy0fotQznudio3rz\n\ -DpTfzP9eRDFVj8RJnl3JJ8P1DULxH7N0TyDBuKZ1ibBfuKjPffqeCEzYKgAc8NG2\n\ -FB4m6mXzHhXuKw6W2v0IbHz6KYldsavf04rq7ztw0t67bexSQ4gLSVJEwiohAreg\n\ -m0dLvQnap5xd2qn0yETteTL8Y+Ujym1DWAnwDdwA6+0j2a0wkyzOzYQpZMt95NyZ\n\ -8kcoqEqO8KAN2HclqfjHlg9iDscbof5x45SQwwIDAQABAoIBAG0dYPeqd0IhHWJ7\n\ -8azufbchLMN1pX/D51xG2uptssfnpHuhkkufSZUYi4QipRS2ME6PYhWJ8pmTi6lH\n\ -E6cUkbI0KGd/F4U2gPdhNrR9Fxwea5bbifkVF7Gx/ZkRjZJiZ3w9+mCNTQbJDKhh\n\ -wITAzzT6WYznhvqbzzBX1fTa6kv0GAQtX7aHKM+XIwkhX2gzU5TU80bvH8aMrT05\n\ -tAMGQqkUeRnpo0yucBl4VmTZzd/+X/d2UyXR0my15jE5iH5o+p+E6qTRE9D+MGUd\n\ -MQ6Ftj0Untqy1lcog1ZLL6zPlnwcD4jgY5VCYDgvabnrSwymOJapPLsAEdWdq+U5\n\ -ec44BMECgYEA/+3qPUrd4XxA517qO3fCGBvf2Gkr7w5ZDeATOTHGuD8QZeK0nxPl\n\ -CWhRjdgkqo0fyf1cjczL5XgYayo+YxkO1Z4RUU+8lJAHlVx9izOQo+MTQfkwH4BK\n\ -LYlHxMoHJwAOXXoE+dmBaDh5xT0mDUGU750r763L6EFovE4qRBn9hxkCgYEA0GWz\n\ -rpOPNxb419WxG9npoQYdCZ5IbmEOGDH3ReggVzWHmW8sqtkqTZm5srcyDpqAc1Gu\n\ -paUveMblEBbU+NFJjLWOfwB5PCp8jsrqRgCQSxolShiVkc3Vu3oyzMus9PDge1eo\n\ -9mwVGO7ojQKWRu/WVAakENPaAjeyyhv4dqSNnjsCgYEAlwe8yszqoY1k8+U0T0G+\n\ -HeIdOCXgkmOiNCj+zyrLvaEhuS6PLq1b5TBVqGJcSPWdQ+MrglbQIKu9pUg5ptt7\n\ -wJ5WU+i9PeK9Ruxc/g/BFKYFkFJQjtZzb+nqm3wpul8zGwDN/O/ZiTqCyd3rHbmM\n\ -/dZ/viKPCZHIEBAEq0m3LskCgYBndzcAo+5k8ZjWwBfQth5SfhCIp/daJgGzbYtR\n\ -P/BenAsY2KOap3tjT8Fsw5usuHSxzIojX6H0Gvu7Qzq11mLn43Q+BeQrRQTWeFRc\n\ -MQdy4iZFZXNNEp7dF8yE9VKHwdgSJPGUdxD6chMvf2tRCN6mlS171VLV6wVvZvez\n\ -H/vX5QKBgD2Dq/NHpjCpAsECP9awmNF5Akn5WJbRGmegwXIih2mOtgtYYDeuQyxY\n\ -ZCrdJFfIUjUVPagshEmUklKhkYMYpzy2PQDVtaVcm6UNFroxT5h+J+KDs1LN1H8G\n\ -LsASrzyAg8EpRulwXEfLrWKiu9DKv8bMEgO4Ovgz8zTKJZIFhcac\n\ ------END RSA PRIVATE KEY-----"; - - -DDS_Security_ValidationResult_t -validate_local_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *local_identity_handle, - DDS_Security_GUID_t *adjusted_participant_guid, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - const DDS_Security_GUID_t *candidate_participant_guid, - - DDS_Security_SecurityException *ex); -DDS_Security_boolean -get_identity_token(dds_security_authentication *instance, - DDS_Security_IdentityToken *identity_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex); -DDS_Security_boolean -set_permissions_credential_and_token( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle handle, - const DDS_Security_PermissionsCredentialToken *permissions_credential, - const DDS_Security_PermissionsToken *permissions_token, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -validate_remote_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *remote_identity_handle, - DDS_Security_AuthRequestMessageToken *local_auth_request_token, - const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityToken *remote_identity_token, - const DDS_Security_GUID_t *remote_participant_guid, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -begin_handshake_request( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -begin_handshake_reply( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -process_handshake( - dds_security_authentication *instance, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_SharedSecretHandle get_shared_secret( - dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -get_authenticated_peer_credential_token( - dds_security_authentication *instance, - DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean get_identity_status_token( - dds_security_authentication *instance, - DDS_Security_IdentityStatusToken *identity_status_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean set_listener(dds_security_authentication *instance, - const dds_security_authentication_listener *listener, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_identity_token(dds_security_authentication *instance, - const DDS_Security_IdentityToken *token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_identity_status_token( - dds_security_authentication *instance, - const DDS_Security_IdentityStatusToken *token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_authenticated_peer_credential_token( - dds_security_authentication *instance, - const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -return_handshake_handle(dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); -DDS_Security_boolean -return_identity_handle( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle identity_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_sharedsecret_handle( - dds_security_authentication *instance, - const DDS_Security_SharedSecretHandle sharedsecret_handle, - DDS_Security_SecurityException *ex); - - - -#endif /* SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ */ diff --git a/src/security/core/tests/plugin_loading/plugin_mock/cryptography_all_ok/mock_cryptography.c b/src/security/core/tests/plugin_loading/plugin_mock/cryptography_all_ok/mock_cryptography.c deleted file mode 100644 index 7f664bf..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/cryptography_all_ok/mock_cryptography.c +++ /dev/null @@ -1,667 +0,0 @@ -/* - * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -#include "dds/security/dds_security_api.h" -#include "dds/ddsrt/heap.h" -#include "dds/ddsrt/misc.h" -#include -#include -#include -#include "mock_cryptography.h" -/** - * Implementation structure for storing encapsulated members of the instance - * while giving only the interface definition to user - */ - -typedef struct dds_security_cryptography_impl { - dds_security_cryptography base; - int member; -} dds_security_cryptography_impl; - - -dds_security_crypto_key_exchange* dds_security_crypto_key_exchange__alloc(void); -void dds_security_crypto_key_exchange__dealloc( - dds_security_crypto_key_exchange* instance); - -dds_security_crypto_key_factory* dds_security_crypto_key_factory__alloc(void); -void dds_security_crypto_key_factory__dealloc( - dds_security_crypto_key_factory* instance); - -/** - * CryptoTransform Interface - */ - -/* - * Allocation function for implementer structure (with internal variables) transparently. - * - */ - -dds_security_crypto_transform* dds_security_crypto_transform__alloc(void); -void dds_security_crypto_transform__dealloc( - dds_security_crypto_transform* instance); - - -int32_t init_crypto( const char *argument, void **context) -{ - - dds_security_cryptography_impl *cryptography; - - dds_security_crypto_key_exchange *crypto_key_exchange; - dds_security_crypto_key_factory *crypto_key_factory; - dds_security_crypto_transform *crypto_transform; - - - DDSRT_UNUSED_ARG(argument); - - //allocate new instance - cryptography = (dds_security_cryptography_impl*) ddsrt_malloc( - sizeof(dds_security_cryptography_impl)); - - //assign the sub components - crypto_key_exchange = dds_security_crypto_key_exchange__alloc(); - crypto_key_factory = dds_security_crypto_key_factory__alloc(); - crypto_transform = dds_security_crypto_transform__alloc(); - - - cryptography->base.crypto_key_exchange = crypto_key_exchange; - cryptography->base.crypto_key_factory = crypto_key_factory; - cryptography->base.crypto_transform = crypto_transform; - - //return the instance - *context = cryptography; - return 0; -} - -int32_t finalize_crypto( void *instance) -{ - - dds_security_cryptography_impl* instance_impl = - (dds_security_cryptography_impl*) instance; - - //deallocate components - dds_security_crypto_key_exchange__dealloc( - instance_impl->base.crypto_key_exchange); - dds_security_crypto_key_factory__dealloc( - instance_impl->base.crypto_key_factory); - dds_security_crypto_transform__dealloc(instance_impl->base.crypto_transform); - //deallocate cryptography - ddsrt_free(instance_impl); - - return 0; -} - - - - - - -/** - * Implementation structure for storing encapsulated members of the instance - * while giving only the interface definition to user - */ - -typedef struct dds_security_crypto_key_exchange_impl { - dds_security_crypto_key_exchange base; - int member; -} dds_security_crypto_key_exchange_impl; - -/** - * Function implementations - */ -static DDS_Security_boolean create_local_participant_crypto_tokens( - dds_security_crypto_key_exchange *instance, - DDS_Security_ParticipantCryptoTokenSeq *local_participant_crypto_tokens, - const DDS_Security_ParticipantCryptoHandle local_participant_crypto, - const DDS_Security_ParticipantCryptoHandle remote_participant_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_participant_crypto_tokens); - DDSRT_UNUSED_ARG(local_participant_crypto); - DDSRT_UNUSED_ARG(remote_participant_crypto); - DDSRT_UNUSED_ARG(ex); - return true; - -} - -static DDS_Security_boolean set_remote_participant_crypto_tokens( - dds_security_crypto_key_exchange *instance, - const DDS_Security_ParticipantCryptoHandle local_participant_crypto, - const DDS_Security_ParticipantCryptoHandle remote_participant_crypto, - const DDS_Security_ParticipantCryptoTokenSeq *remote_participant_tokens, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_participant_crypto); - DDSRT_UNUSED_ARG(remote_participant_crypto); - DDSRT_UNUSED_ARG(remote_participant_tokens); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean create_local_datawriter_crypto_tokens( - dds_security_crypto_key_exchange *instance, - DDS_Security_DatawriterCryptoTokenSeq *local_datawriter_crypto_tokens, - const DDS_Security_DatawriterCryptoHandle local_datawriter_crypto, - const DDS_Security_DatareaderCryptoHandle remote_datareader_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_datawriter_crypto_tokens); - DDSRT_UNUSED_ARG(local_datawriter_crypto); - DDSRT_UNUSED_ARG(remote_datareader_crypto); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean set_remote_datawriter_crypto_tokens( - dds_security_crypto_key_exchange *instance, - const DDS_Security_DatareaderCryptoHandle local_datareader_crypto, - const DDS_Security_DatawriterCryptoHandle remote_datawriter_crypto, - const DDS_Security_DatawriterCryptoTokenSeq *remote_datawriter_tokens, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_datareader_crypto); - DDSRT_UNUSED_ARG(remote_datawriter_crypto); - DDSRT_UNUSED_ARG(remote_datawriter_tokens); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean create_local_datareader_crypto_tokens( - dds_security_crypto_key_exchange *instance, - DDS_Security_DatareaderCryptoTokenSeq *local_datareader_cryto_tokens, - const DDS_Security_DatareaderCryptoHandle local_datareader_crypto, - const DDS_Security_DatawriterCryptoHandle remote_datawriter_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_datareader_cryto_tokens); - DDSRT_UNUSED_ARG(local_datareader_crypto); - DDSRT_UNUSED_ARG(remote_datawriter_crypto); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean set_remote_datareader_crypto_tokens( - dds_security_crypto_key_exchange *instance, - const DDS_Security_DatawriterCryptoHandle local_datawriter_crypto, - const DDS_Security_DatareaderCryptoHandle remote_datareader_crypto, - const DDS_Security_DatareaderCryptoTokenSeq *remote_datareader_tokens, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_datawriter_crypto); - DDSRT_UNUSED_ARG(remote_datareader_crypto); - DDSRT_UNUSED_ARG(remote_datareader_tokens); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean return_crypto_tokens( - dds_security_crypto_key_exchange *instance, - DDS_Security_CryptoTokenSeq *crypto_tokens, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(crypto_tokens); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -dds_security_crypto_key_exchange* dds_security_crypto_key_exchange__alloc(void) -{ - dds_security_crypto_key_exchange_impl *instance; - instance = (dds_security_crypto_key_exchange_impl*) ddsrt_malloc( - sizeof(dds_security_crypto_key_exchange_impl)); - - instance->base.create_local_participant_crypto_tokens = - &create_local_participant_crypto_tokens; - - instance->base.set_remote_participant_crypto_tokens = - &set_remote_participant_crypto_tokens; - - instance->base.create_local_datawriter_crypto_tokens = - &create_local_datawriter_crypto_tokens; - - instance->base.set_remote_datawriter_crypto_tokens = - &set_remote_datawriter_crypto_tokens; - - instance->base.create_local_datareader_crypto_tokens = - &create_local_datareader_crypto_tokens; - - instance->base.set_remote_datareader_crypto_tokens = - &set_remote_datareader_crypto_tokens; - - instance->base.return_crypto_tokens = &return_crypto_tokens; - - return (dds_security_crypto_key_exchange*) instance; -} - -void dds_security_crypto_key_exchange__dealloc( - dds_security_crypto_key_exchange* instance) -{ - - ddsrt_free((dds_security_crypto_key_exchange_impl*) instance); -} - - - -/** - * Implementation structure for storing encapsulated members of the instance - * while giving only the interface definition to user - */ - -typedef struct dds_security_crypto_key_factory_impl { - dds_security_crypto_key_factory base; - int member; -} dds_security_crypto_key_factory_impl; - -/** - * Function implementations - */ - -static DDS_Security_ParticipantCryptoHandle register_local_participant( - dds_security_crypto_key_factory *instance, - const DDS_Security_IdentityHandle participant_identity, - const DDS_Security_PermissionsHandle participant_permissions, - const DDS_Security_PropertySeq *participant_properties, - const DDS_Security_ParticipantSecurityAttributes *participant_security_attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(participant_identity); - DDSRT_UNUSED_ARG(participant_permissions); - DDSRT_UNUSED_ARG(participant_properties); - DDSRT_UNUSED_ARG(participant_security_attributes); - DDSRT_UNUSED_ARG(ex); - return 0; -} - -static DDS_Security_ParticipantCryptoHandle register_matched_remote_participant( - dds_security_crypto_key_factory *instance, - const DDS_Security_ParticipantCryptoHandle local_participant_crypto_handle, - const DDS_Security_IdentityHandle remote_participant_identity, - const DDS_Security_PermissionsHandle remote_participant_permissions, - const DDS_Security_SharedSecretHandle shared_secret, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_participant_crypto_handle); - DDSRT_UNUSED_ARG(remote_participant_identity); - DDSRT_UNUSED_ARG(remote_participant_permissions); - DDSRT_UNUSED_ARG(shared_secret); - DDSRT_UNUSED_ARG(ex); - return 0; -} - -static DDS_Security_DatawriterCryptoHandle register_local_datawriter( - dds_security_crypto_key_factory *instance, - const DDS_Security_ParticipantCryptoHandle participant_crypto, - const DDS_Security_PropertySeq *datawriter_properties, - const DDS_Security_EndpointSecurityAttributes *datawriter_security_attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(participant_crypto); - DDSRT_UNUSED_ARG(datawriter_properties); - DDSRT_UNUSED_ARG(datawriter_security_attributes); - DDSRT_UNUSED_ARG(ex); - return 0; -} - -static DDS_Security_DatareaderCryptoHandle register_matched_remote_datareader( - dds_security_crypto_key_factory *instance, - const DDS_Security_DatawriterCryptoHandle local_datawritert_crypto_handle, - const DDS_Security_ParticipantCryptoHandle remote_participant_crypto, - const DDS_Security_SharedSecretHandle shared_secret, - const DDS_Security_boolean relay_only, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_datawritert_crypto_handle); - DDSRT_UNUSED_ARG(remote_participant_crypto); - DDSRT_UNUSED_ARG(shared_secret); - DDSRT_UNUSED_ARG(relay_only); - DDSRT_UNUSED_ARG(ex); - return 0; -} - -static DDS_Security_DatareaderCryptoHandle register_local_datareader( - dds_security_crypto_key_factory *instance, - const DDS_Security_ParticipantCryptoHandle participant_crypto, - const DDS_Security_PropertySeq *datareader_properties, - const DDS_Security_EndpointSecurityAttributes *datareader_security_attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(participant_crypto); - DDSRT_UNUSED_ARG(datareader_properties); - DDSRT_UNUSED_ARG(datareader_security_attributes); - DDSRT_UNUSED_ARG(ex); - - return 0; -} - -static DDS_Security_DatawriterCryptoHandle register_matched_remote_datawriter( - dds_security_crypto_key_factory *instance, - const DDS_Security_DatareaderCryptoHandle local_datareader_crypto_handle, - const DDS_Security_ParticipantCryptoHandle remote_participant_crypt, - const DDS_Security_SharedSecretHandle shared_secret, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_datareader_crypto_handle); - DDSRT_UNUSED_ARG(remote_participant_crypt); - DDSRT_UNUSED_ARG(shared_secret); - DDSRT_UNUSED_ARG(ex); - return true; -} - -static DDS_Security_boolean unregister_participant( - dds_security_crypto_key_factory *instance, - const DDS_Security_ParticipantCryptoHandle participant_crypto_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(participant_crypto_handle); - DDSRT_UNUSED_ARG(ex); - return true; -} - -static DDS_Security_boolean unregister_datawriter( - dds_security_crypto_key_factory *instance, - const DDS_Security_DatawriterCryptoHandle datawriter_crypto_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(datawriter_crypto_handle); - DDSRT_UNUSED_ARG(ex); - return true; -} - -static DDS_Security_boolean unregister_datareader( - dds_security_crypto_key_factory *instance, - const DDS_Security_DatareaderCryptoHandle datareader_crypto_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(datareader_crypto_handle); - DDSRT_UNUSED_ARG(ex); - return true; -} - -dds_security_crypto_key_factory* dds_security_crypto_key_factory__alloc(void) -{ - dds_security_crypto_key_factory_impl *instance; - instance = (dds_security_crypto_key_factory_impl*) ddsrt_malloc( - sizeof(dds_security_crypto_key_factory_impl)); - - instance->base.register_local_participant = ®ister_local_participant; - - instance->base.register_matched_remote_participant = - ®ister_matched_remote_participant; - - instance->base.register_local_datawriter = ®ister_local_datawriter; - - instance->base.register_matched_remote_datareader = - ®ister_matched_remote_datareader; - - instance->base.register_local_datareader = ®ister_local_datareader; - - instance->base.register_matched_remote_datawriter = - ®ister_matched_remote_datawriter; - - instance->base.unregister_participant = &unregister_participant; - - instance->base.unregister_datawriter = &unregister_datawriter; - - instance->base.unregister_datareader = &unregister_datareader; - - return (dds_security_crypto_key_factory*) instance; -} - -void dds_security_crypto_key_factory__dealloc( - dds_security_crypto_key_factory* instance) -{ - - ddsrt_free((dds_security_crypto_key_factory_impl*) instance); -} - - - -/** - * Implementation structure for storing encapsulated members of the instance - * while giving only the interface definition to user - */ - -typedef struct dds_security_crypto_transform_impl { - dds_security_crypto_transform base; - int member; -} dds_security_crypto_transform_impl; - -/** - * Function implementations - */ -static DDS_Security_boolean encode_serialized_payload( - dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *encoded_buffer, - DDS_Security_OctetSeq *extra_inline_qos, - const DDS_Security_OctetSeq *plain_buffer, - const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(encoded_buffer); - DDSRT_UNUSED_ARG(extra_inline_qos); - DDSRT_UNUSED_ARG(plain_buffer); - DDSRT_UNUSED_ARG(sending_datawriter_crypto); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean encode_datawriter_submessage( - dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *encoded_rtps_submessage, - const DDS_Security_OctetSeq *plain_rtps_submessage, - const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, - const DDS_Security_DatareaderCryptoHandleSeq *receiving_datareader_crypto_list, - int32_t *receiving_datareader_crypto_list_index, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(encoded_rtps_submessage); - DDSRT_UNUSED_ARG(plain_rtps_submessage); - DDSRT_UNUSED_ARG(sending_datawriter_crypto); - DDSRT_UNUSED_ARG(receiving_datareader_crypto_list); - DDSRT_UNUSED_ARG(receiving_datareader_crypto_list_index); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean encode_datareader_submessage( - dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *encoded_rtps_submessage, - const DDS_Security_OctetSeq *plain_rtps_submessage, - const DDS_Security_DatareaderCryptoHandle sending_datareader_crypto, - const DDS_Security_DatawriterCryptoHandleSeq *receiving_datawriter_crypto_list, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(encoded_rtps_submessage); - DDSRT_UNUSED_ARG(plain_rtps_submessage); - DDSRT_UNUSED_ARG(sending_datareader_crypto); - DDSRT_UNUSED_ARG(receiving_datawriter_crypto_list); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean encode_rtps_message( dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *encoded_rtps_message, - const DDS_Security_OctetSeq *plain_rtps_message, - const DDS_Security_ParticipantCryptoHandle sending_participant_crypto, - const DDS_Security_ParticipantCryptoHandleSeq *receiving_participant_crypto_list, - int32_t *receiving_participant_crypto_list_index, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(encoded_rtps_message); - DDSRT_UNUSED_ARG(plain_rtps_message); - DDSRT_UNUSED_ARG(sending_participant_crypto); - DDSRT_UNUSED_ARG(receiving_participant_crypto_list); - DDSRT_UNUSED_ARG(receiving_participant_crypto_list_index); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean decode_rtps_message( dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *plain_buffer, const DDS_Security_OctetSeq *encoded_buffer, - const DDS_Security_ParticipantCryptoHandle receiving_participant_crypto, - const DDS_Security_ParticipantCryptoHandle sending_participant_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(plain_buffer); - DDSRT_UNUSED_ARG(encoded_buffer); - DDSRT_UNUSED_ARG(receiving_participant_crypto); - DDSRT_UNUSED_ARG(sending_participant_crypto); - DDSRT_UNUSED_ARG(ex); - - return true; -} - - -static DDS_Security_boolean preprocess_secure_submsg( - dds_security_crypto_transform *instance, - DDS_Security_DatawriterCryptoHandle *datawriter_crypto, - DDS_Security_DatareaderCryptoHandle *datareader_crypto, - DDS_Security_SecureSubmessageCategory_t *secure_submessage_category, - const DDS_Security_OctetSeq *encoded_rtps_submessage, - const DDS_Security_ParticipantCryptoHandle receiving_participant_crypto, - const DDS_Security_ParticipantCryptoHandle sending_participant_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(datawriter_crypto); - DDSRT_UNUSED_ARG(datareader_crypto); - DDSRT_UNUSED_ARG(secure_submessage_category); - DDSRT_UNUSED_ARG(encoded_rtps_submessage); - DDSRT_UNUSED_ARG(receiving_participant_crypto); - DDSRT_UNUSED_ARG(sending_participant_crypto); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean decode_datawriter_submessage( - dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *plain_rtps_submessage, - const DDS_Security_OctetSeq *encoded_rtps_submessage, - const DDS_Security_DatareaderCryptoHandle receiving_datareader_crypto, - const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(plain_rtps_submessage); - DDSRT_UNUSED_ARG(encoded_rtps_submessage); - DDSRT_UNUSED_ARG(receiving_datareader_crypto); - DDSRT_UNUSED_ARG(sending_datawriter_crypto); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean decode_datareader_submessage( - dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *plain_rtps_message, - const DDS_Security_OctetSeq *encoded_rtps_message, - const DDS_Security_DatawriterCryptoHandle receiving_datawriter_crypto, - const DDS_Security_DatareaderCryptoHandle sending_datareader_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(plain_rtps_message); - DDSRT_UNUSED_ARG(encoded_rtps_message); - DDSRT_UNUSED_ARG(receiving_datawriter_crypto); - DDSRT_UNUSED_ARG(sending_datareader_crypto); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean decode_serialized_payload( - dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *plain_buffer, const DDS_Security_OctetSeq *encoded_buffer, - const DDS_Security_OctetSeq *inline_qos, - const DDS_Security_DatareaderCryptoHandle receiving_datareader_crypto, - const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(plain_buffer); - DDSRT_UNUSED_ARG(encoded_buffer); - DDSRT_UNUSED_ARG(inline_qos); - DDSRT_UNUSED_ARG(receiving_datareader_crypto); - DDSRT_UNUSED_ARG(sending_datawriter_crypto); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -dds_security_crypto_transform* dds_security_crypto_transform__alloc(void) -{ - dds_security_crypto_transform_impl *instance; - instance = (dds_security_crypto_transform_impl*) ddsrt_malloc( - sizeof(dds_security_crypto_transform_impl)); - - memset( instance, 0, sizeof(dds_security_crypto_transform_impl)); - - instance->base.encode_datawriter_submessage = &encode_datawriter_submessage; - - instance->base.encode_datareader_submessage = &encode_datareader_submessage; - - instance->base.encode_rtps_message = &encode_rtps_message; - - instance->base.decode_rtps_message = &decode_rtps_message; - - instance->base.preprocess_secure_submsg = &preprocess_secure_submsg; - - instance->base.decode_datawriter_submessage = &decode_datawriter_submessage; - - instance->base.decode_datareader_submessage = &decode_datareader_submessage; - - instance->base.decode_serialized_payload = &decode_serialized_payload; - - instance->base.encode_serialized_payload = &encode_serialized_payload; - - return (dds_security_crypto_transform*) instance; -} - -void dds_security_crypto_transform__dealloc( - dds_security_crypto_transform* instance) -{ - - ddsrt_free((dds_security_crypto_transform_impl*) instance); -} - - diff --git a/src/security/core/tests/plugin_loading/plugin_mock/cryptography_all_ok/mock_cryptography.h b/src/security/core/tests/plugin_loading/plugin_mock/cryptography_all_ok/mock_cryptography.h deleted file mode 100644 index e532a94..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/cryptography_all_ok/mock_cryptography.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * authentication.h - * - * Created on: Jan 15, 2018 - * Author: kurtulus oksuztepe - */ - -#ifndef SECURITY_CRYPTO_OK_H_ -#define SECURITY_CRYPTO_OK_H_ - -#include "dds/security/cryptography_all_ok_export.h" -#include "dds/security/dds_security_api.h" - -SECURITY_EXPORT int32_t -init_crypto(const char *argument, void **context); - -SECURITY_EXPORT int32_t -finalize_crypto(void *context); - - -#endif /* SECURITY_CRYPTO_OK_H_ */ diff --git a/src/security/core/tests/plugin_loading/plugin_mock/cryptography_missing_function/mock_cryptography.c b/src/security/core/tests/plugin_loading/plugin_mock/cryptography_missing_function/mock_cryptography.c deleted file mode 100644 index 3a72441..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/cryptography_missing_function/mock_cryptography.c +++ /dev/null @@ -1,656 +0,0 @@ -/* - * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -#include "dds/security/dds_security_api.h" -#include "dds/ddsrt/heap.h" -#include "dds/ddsrt/misc.h" -#include -#include -#include -#include "mock_cryptography.h" -/** - * Implementation structure for storing encapsulated members of the instance - * while giving only the interface definition to user - */ - -typedef struct dds_security_cryptography_impl { - dds_security_cryptography base; - int member; -} dds_security_cryptography_impl; - - -dds_security_crypto_key_exchange* dds_security_crypto_key_exchange__alloc(void); -void dds_security_crypto_key_exchange__dealloc( - dds_security_crypto_key_exchange* instance); - -dds_security_crypto_key_factory* dds_security_crypto_key_factory__alloc(void); -void dds_security_crypto_key_factory__dealloc( - dds_security_crypto_key_factory* instance); - -/** - * CryptoTransform Interface - */ - -/* - * Allocation function for implementer structure (with internal variables) transparently. - * - */ - -dds_security_crypto_transform* dds_security_crypto_transform__alloc(void); -void dds_security_crypto_transform__dealloc( - dds_security_crypto_transform* instance); - - -int32_t init_crypto( const char *argument, void **context) -{ - - dds_security_cryptography_impl *cryptography; - - dds_security_crypto_key_exchange *crypto_key_exchange; - dds_security_crypto_key_factory *crypto_key_factory; - dds_security_crypto_transform *crypto_transform; - - - DDSRT_UNUSED_ARG(argument); - - //allocate new instance - cryptography = (dds_security_cryptography_impl*) ddsrt_malloc( - sizeof(dds_security_cryptography_impl)); - - memset( cryptography, 0, sizeof(dds_security_cryptography_impl)); - //assign the sub components - crypto_key_exchange = dds_security_crypto_key_exchange__alloc(); - crypto_key_factory = dds_security_crypto_key_factory__alloc(); - crypto_transform = dds_security_crypto_transform__alloc(); - - - cryptography->base.crypto_key_exchange = crypto_key_exchange; - cryptography->base.crypto_key_factory = crypto_key_factory; - cryptography->base.crypto_transform = crypto_transform; - - //return the instance - *context = cryptography; - return 0; -} - -int32_t finalize_crypto( void *instance) -{ - - dds_security_cryptography_impl* instance_impl = - (dds_security_cryptography_impl*) instance; - - //deallocate components - dds_security_crypto_key_exchange__dealloc( - instance_impl->base.crypto_key_exchange); - dds_security_crypto_key_factory__dealloc( - instance_impl->base.crypto_key_factory); - dds_security_crypto_transform__dealloc(instance_impl->base.crypto_transform); - //deallocate cryptography - ddsrt_free(instance_impl); - - return 0; -} - - - - - - -/** - * Implementation structure for storing encapsulated members of the instance - * while giving only the interface definition to user - */ - -typedef struct dds_security_crypto_key_exchange_impl { - dds_security_crypto_key_exchange base; - int member; -} dds_security_crypto_key_exchange_impl; - -/** - * Function implementations - */ -static DDS_Security_boolean create_local_participant_crypto_tokens( - dds_security_crypto_key_exchange *instance, - DDS_Security_ParticipantCryptoTokenSeq *local_participant_crypto_tokens, - const DDS_Security_ParticipantCryptoHandle local_participant_crypto, - const DDS_Security_ParticipantCryptoHandle remote_participant_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_participant_crypto_tokens); - DDSRT_UNUSED_ARG(local_participant_crypto); - DDSRT_UNUSED_ARG(remote_participant_crypto); - DDSRT_UNUSED_ARG(ex); - return true; - -} - -static DDS_Security_boolean create_local_datawriter_crypto_tokens( - dds_security_crypto_key_exchange *instance, - DDS_Security_DatawriterCryptoTokenSeq *local_datawriter_crypto_tokens, - const DDS_Security_DatawriterCryptoHandle local_datawriter_crypto, - const DDS_Security_DatareaderCryptoHandle remote_datareader_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_datawriter_crypto_tokens); - DDSRT_UNUSED_ARG(local_datawriter_crypto); - DDSRT_UNUSED_ARG(remote_datareader_crypto); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean set_remote_datawriter_crypto_tokens( - dds_security_crypto_key_exchange *instance, - const DDS_Security_DatareaderCryptoHandle local_datareader_crypto, - const DDS_Security_DatawriterCryptoHandle remote_datawriter_crypto, - const DDS_Security_DatawriterCryptoTokenSeq *remote_datawriter_tokens, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_datareader_crypto); - DDSRT_UNUSED_ARG(remote_datawriter_crypto); - DDSRT_UNUSED_ARG(remote_datawriter_tokens); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean create_local_datareader_crypto_tokens( - dds_security_crypto_key_exchange *instance, - DDS_Security_DatareaderCryptoTokenSeq *local_datareader_cryto_tokens, - const DDS_Security_DatareaderCryptoHandle local_datareader_crypto, - const DDS_Security_DatawriterCryptoHandle remote_datawriter_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_datareader_cryto_tokens); - DDSRT_UNUSED_ARG(local_datareader_crypto); - DDSRT_UNUSED_ARG(remote_datawriter_crypto); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean set_remote_datareader_crypto_tokens( - dds_security_crypto_key_exchange *instance, - const DDS_Security_DatawriterCryptoHandle local_datawriter_crypto, - const DDS_Security_DatareaderCryptoHandle remote_datareader_crypto, - const DDS_Security_DatareaderCryptoTokenSeq *remote_datareader_tokens, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_datawriter_crypto); - DDSRT_UNUSED_ARG(remote_datareader_crypto); - DDSRT_UNUSED_ARG(remote_datareader_tokens); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean return_crypto_tokens( - dds_security_crypto_key_exchange *instance, - DDS_Security_CryptoTokenSeq *crypto_tokens, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(crypto_tokens); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -dds_security_crypto_key_exchange* dds_security_crypto_key_exchange__alloc(void) -{ - dds_security_crypto_key_exchange_impl *instance; - instance = (dds_security_crypto_key_exchange_impl*) ddsrt_malloc( - sizeof(dds_security_crypto_key_exchange_impl)); - - memset( instance, 0, sizeof(dds_security_crypto_key_exchange_impl)); - - instance->base.create_local_participant_crypto_tokens = - &create_local_participant_crypto_tokens; - - /* Do not assign it for testing purposes - instance->base.set_remote_participant_crypto_tokens = - &set_remote_participant_crypto_tokens; - */ - - instance->base.create_local_datawriter_crypto_tokens = - &create_local_datawriter_crypto_tokens; - - instance->base.set_remote_datawriter_crypto_tokens = - &set_remote_datawriter_crypto_tokens; - - instance->base.create_local_datareader_crypto_tokens = - &create_local_datareader_crypto_tokens; - - instance->base.set_remote_datareader_crypto_tokens = - &set_remote_datareader_crypto_tokens; - - instance->base.return_crypto_tokens = &return_crypto_tokens; - - return (dds_security_crypto_key_exchange*) instance; -} - -void dds_security_crypto_key_exchange__dealloc( - dds_security_crypto_key_exchange* instance) -{ - - ddsrt_free((dds_security_crypto_key_exchange_impl*) instance); -} - - - -/** - * Implementation structure for storing encapsulated members of the instance - * while giving only the interface definition to user - */ - -typedef struct dds_security_crypto_key_factory_impl { - dds_security_crypto_key_factory base; - int member; -} dds_security_crypto_key_factory_impl; - -/** - * Function implementations - */ - -static DDS_Security_ParticipantCryptoHandle register_local_participant( - dds_security_crypto_key_factory *instance, - const DDS_Security_IdentityHandle participant_identity, - const DDS_Security_PermissionsHandle participant_permissions, - const DDS_Security_PropertySeq *participant_properties, - const DDS_Security_ParticipantSecurityAttributes *participant_security_attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(participant_identity); - DDSRT_UNUSED_ARG(participant_permissions); - DDSRT_UNUSED_ARG(participant_properties); - DDSRT_UNUSED_ARG(participant_security_attributes); - DDSRT_UNUSED_ARG(ex); - return 0; -} - -static DDS_Security_ParticipantCryptoHandle register_matched_remote_participant( - dds_security_crypto_key_factory *instance, - const DDS_Security_ParticipantCryptoHandle local_participant_crypto_handle, - const DDS_Security_IdentityHandle remote_participant_identity, - const DDS_Security_PermissionsHandle remote_participant_permissions, - const DDS_Security_SharedSecretHandle shared_secret, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_participant_crypto_handle); - DDSRT_UNUSED_ARG(remote_participant_identity); - DDSRT_UNUSED_ARG(remote_participant_permissions); - DDSRT_UNUSED_ARG(shared_secret); - DDSRT_UNUSED_ARG(ex); - return 0; -} - -static DDS_Security_DatawriterCryptoHandle register_local_datawriter( - dds_security_crypto_key_factory *instance, - const DDS_Security_ParticipantCryptoHandle participant_crypto, - const DDS_Security_PropertySeq *datawriter_properties, - const DDS_Security_EndpointSecurityAttributes *datawriter_security_attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(participant_crypto); - DDSRT_UNUSED_ARG(datawriter_properties); - DDSRT_UNUSED_ARG(datawriter_security_attributes); - DDSRT_UNUSED_ARG(ex); - return 0; -} - -static DDS_Security_DatareaderCryptoHandle register_matched_remote_datareader( - dds_security_crypto_key_factory *instance, - const DDS_Security_DatawriterCryptoHandle local_datawritert_crypto_handle, - const DDS_Security_ParticipantCryptoHandle remote_participant_crypto, - const DDS_Security_SharedSecretHandle shared_secret, - const DDS_Security_boolean relay_only, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_datawritert_crypto_handle); - DDSRT_UNUSED_ARG(remote_participant_crypto); - DDSRT_UNUSED_ARG(shared_secret); - DDSRT_UNUSED_ARG(relay_only); - DDSRT_UNUSED_ARG(ex); - return 0; -} - -static DDS_Security_DatareaderCryptoHandle register_local_datareader( - dds_security_crypto_key_factory *instance, - const DDS_Security_ParticipantCryptoHandle participant_crypto, - const DDS_Security_PropertySeq *datareader_properties, - const DDS_Security_EndpointSecurityAttributes *datareader_security_attributes, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(participant_crypto); - DDSRT_UNUSED_ARG(datareader_properties); - DDSRT_UNUSED_ARG(datareader_security_attributes); - DDSRT_UNUSED_ARG(ex); - - return 0; -} - -static DDS_Security_DatawriterCryptoHandle register_matched_remote_datawriter( - dds_security_crypto_key_factory *instance, - const DDS_Security_DatareaderCryptoHandle local_datareader_crypto_handle, - const DDS_Security_ParticipantCryptoHandle remote_participant_crypt, - const DDS_Security_SharedSecretHandle shared_secret, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(local_datareader_crypto_handle); - DDSRT_UNUSED_ARG(remote_participant_crypt); - DDSRT_UNUSED_ARG(shared_secret); - DDSRT_UNUSED_ARG(ex); - return true; -} - -static DDS_Security_boolean unregister_participant( - dds_security_crypto_key_factory *instance, - const DDS_Security_ParticipantCryptoHandle participant_crypto_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(participant_crypto_handle); - DDSRT_UNUSED_ARG(ex); - return true; -} - -static DDS_Security_boolean unregister_datawriter( - dds_security_crypto_key_factory *instance, - const DDS_Security_DatawriterCryptoHandle datawriter_crypto_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(datawriter_crypto_handle); - DDSRT_UNUSED_ARG(ex); - return true; -} - -static DDS_Security_boolean unregister_datareader( - dds_security_crypto_key_factory *instance, - const DDS_Security_DatareaderCryptoHandle datareader_crypto_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(datareader_crypto_handle); - DDSRT_UNUSED_ARG(ex); - return true; -} - -dds_security_crypto_key_factory* dds_security_crypto_key_factory__alloc(void) -{ - dds_security_crypto_key_factory_impl *instance; - instance = (dds_security_crypto_key_factory_impl*) ddsrt_malloc( - sizeof(dds_security_crypto_key_factory_impl)); - - memset( instance, 0, sizeof(dds_security_crypto_key_factory_impl)); - instance->base.register_local_participant = ®ister_local_participant; - - instance->base.register_matched_remote_participant = - ®ister_matched_remote_participant; - - instance->base.register_local_datawriter = ®ister_local_datawriter; - - instance->base.register_matched_remote_datareader = - ®ister_matched_remote_datareader; - - instance->base.register_local_datareader = ®ister_local_datareader; - - instance->base.register_matched_remote_datawriter = - ®ister_matched_remote_datawriter; - - instance->base.unregister_participant = &unregister_participant; - - instance->base.unregister_datawriter = &unregister_datawriter; - - instance->base.unregister_datareader = &unregister_datareader; - - return (dds_security_crypto_key_factory*) instance; -} - -void dds_security_crypto_key_factory__dealloc( - dds_security_crypto_key_factory* instance) -{ - - ddsrt_free((dds_security_crypto_key_factory_impl*) instance); -} - - - -/** - * Implementation structure for storing encapsulated members of the instance - * while giving only the interface definition to user - */ - -typedef struct dds_security_crypto_transform_impl { - dds_security_crypto_transform base; - int member; -} dds_security_crypto_transform_impl; - -/** - * Function implementations - */ -static DDS_Security_boolean encode_serialized_payload( - dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *encoded_buffer, - DDS_Security_OctetSeq *extra_inline_qos, - const DDS_Security_OctetSeq *plain_buffer, - const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(encoded_buffer); - DDSRT_UNUSED_ARG(extra_inline_qos); - DDSRT_UNUSED_ARG(plain_buffer); - DDSRT_UNUSED_ARG(sending_datawriter_crypto); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean encode_datawriter_submessage( - dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *encoded_rtps_submessage, - const DDS_Security_OctetSeq *plain_rtps_submessage, - const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, - const DDS_Security_DatareaderCryptoHandleSeq *receiving_datareader_crypto_list, - int32_t *receiving_datareader_crypto_list_index, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(encoded_rtps_submessage); - DDSRT_UNUSED_ARG(plain_rtps_submessage); - DDSRT_UNUSED_ARG(sending_datawriter_crypto); - DDSRT_UNUSED_ARG(receiving_datareader_crypto_list); - DDSRT_UNUSED_ARG(receiving_datareader_crypto_list_index); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean encode_datareader_submessage( - dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *encoded_rtps_submessage, - const DDS_Security_OctetSeq *plain_rtps_submessage, - const DDS_Security_DatareaderCryptoHandle sending_datareader_crypto, - const DDS_Security_DatawriterCryptoHandleSeq *receiving_datawriter_crypto_list, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(encoded_rtps_submessage); - DDSRT_UNUSED_ARG(plain_rtps_submessage); - DDSRT_UNUSED_ARG(sending_datareader_crypto); - DDSRT_UNUSED_ARG(receiving_datawriter_crypto_list); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean encode_rtps_message( dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *encoded_rtps_message, - const DDS_Security_OctetSeq *plain_rtps_message, - const DDS_Security_ParticipantCryptoHandle sending_participant_crypto, - const DDS_Security_ParticipantCryptoHandleSeq *receiving_participant_crypto_list, - int32_t *receiving_participant_crypto_list_index, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(encoded_rtps_message); - DDSRT_UNUSED_ARG(plain_rtps_message); - DDSRT_UNUSED_ARG(sending_participant_crypto); - DDSRT_UNUSED_ARG(receiving_participant_crypto_list); - DDSRT_UNUSED_ARG(receiving_participant_crypto_list_index); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean decode_rtps_message( dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *plain_buffer, const DDS_Security_OctetSeq *encoded_buffer, - const DDS_Security_ParticipantCryptoHandle receiving_participant_crypto, - const DDS_Security_ParticipantCryptoHandle sending_participant_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(plain_buffer); - DDSRT_UNUSED_ARG(encoded_buffer); - DDSRT_UNUSED_ARG(receiving_participant_crypto); - DDSRT_UNUSED_ARG(sending_participant_crypto); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean preprocess_secure_submsg( - dds_security_crypto_transform *instance, - DDS_Security_DatawriterCryptoHandle *datawriter_crypto, - DDS_Security_DatareaderCryptoHandle *datareader_crypto, - DDS_Security_SecureSubmessageCategory_t *secure_submessage_category, - const DDS_Security_OctetSeq *encoded_rtps_submessage, - const DDS_Security_ParticipantCryptoHandle receiving_participant_crypto, - const DDS_Security_ParticipantCryptoHandle sending_participant_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(datawriter_crypto); - DDSRT_UNUSED_ARG(datareader_crypto); - DDSRT_UNUSED_ARG(secure_submessage_category); - DDSRT_UNUSED_ARG(encoded_rtps_submessage); - DDSRT_UNUSED_ARG(receiving_participant_crypto); - DDSRT_UNUSED_ARG(sending_participant_crypto); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean decode_datawriter_submessage( - dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *plain_rtps_submessage, - const DDS_Security_OctetSeq *encoded_rtps_submessage, - const DDS_Security_DatareaderCryptoHandle receiving_datareader_crypto, - const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(plain_rtps_submessage); - DDSRT_UNUSED_ARG(encoded_rtps_submessage); - DDSRT_UNUSED_ARG(receiving_datareader_crypto); - DDSRT_UNUSED_ARG(sending_datawriter_crypto); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean decode_datareader_submessage( - dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *plain_rtps_message, - const DDS_Security_OctetSeq *encoded_rtps_message, - const DDS_Security_DatawriterCryptoHandle receiving_datawriter_crypto, - const DDS_Security_DatareaderCryptoHandle sending_datareader_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(plain_rtps_message); - DDSRT_UNUSED_ARG(encoded_rtps_message); - DDSRT_UNUSED_ARG(receiving_datawriter_crypto); - DDSRT_UNUSED_ARG(sending_datareader_crypto); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -static DDS_Security_boolean decode_serialized_payload( - dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *plain_buffer, const DDS_Security_OctetSeq *encoded_buffer, - const DDS_Security_OctetSeq *inline_qos, - const DDS_Security_DatareaderCryptoHandle receiving_datareader_crypto, - const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(instance); - DDSRT_UNUSED_ARG(plain_buffer); - DDSRT_UNUSED_ARG(encoded_buffer); - DDSRT_UNUSED_ARG(inline_qos); - DDSRT_UNUSED_ARG(receiving_datareader_crypto); - DDSRT_UNUSED_ARG(sending_datawriter_crypto); - DDSRT_UNUSED_ARG(ex); - - return true; -} - -dds_security_crypto_transform* dds_security_crypto_transform__alloc(void) -{ - dds_security_crypto_transform_impl *instance; - instance = (dds_security_crypto_transform_impl*) ddsrt_malloc( - sizeof(dds_security_crypto_transform_impl)); - - - - instance->base.encode_datawriter_submessage = &encode_datawriter_submessage; - - instance->base.encode_datareader_submessage = &encode_datareader_submessage; - - instance->base.encode_rtps_message = &encode_rtps_message; - - instance->base.decode_rtps_message = &decode_rtps_message; - - instance->base.preprocess_secure_submsg = &preprocess_secure_submsg; - - instance->base.decode_datawriter_submessage = &decode_datawriter_submessage; - - instance->base.decode_datareader_submessage = &decode_datareader_submessage; - - instance->base.decode_serialized_payload = &decode_serialized_payload; - - instance->base.encode_serialized_payload = &encode_serialized_payload; - - return (dds_security_crypto_transform*) instance; -} - -void dds_security_crypto_transform__dealloc( - dds_security_crypto_transform* instance) -{ - - ddsrt_free((dds_security_crypto_transform_impl*) instance); -} - - diff --git a/src/security/core/tests/plugin_loading/plugin_mock/cryptography_missing_function/mock_cryptography.h b/src/security/core/tests/plugin_loading/plugin_mock/cryptography_missing_function/mock_cryptography.h deleted file mode 100644 index 2908eeb..0000000 --- a/src/security/core/tests/plugin_loading/plugin_mock/cryptography_missing_function/mock_cryptography.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright(c) 2006 to 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -#ifndef SECURITY_CRYPTO_MISSING_H_ -#define SECURITY_CRYPTO_MISSING_H_ - -#include "dds/security/cryptography_missing_function_export.h" -#include "dds/security/dds_security_api.h" - -SECURITY_EXPORT int32_t -init_crypto(const char *argument, void **context); - -SECURITY_EXPORT int32_t -finalize_crypto(void *context); - - -#endif /* SECURITY_CRYPTO_MISSING_H_ */ diff --git a/src/security/core/tests/plugin_loading/security_config.c b/src/security/core/tests/plugin_loading/security_config.c deleted file mode 100644 index dbd0806..0000000 --- a/src/security/core/tests/plugin_loading/security_config.c +++ /dev/null @@ -1,724 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include - -#include "dds/dds.h" -#include "CUnit/Test.h" -#include "config_env.h" - -#include "dds/version.h" -#include "dds/ddsrt/cdtors.h" -#include "dds/ddsrt/environ.h" -#include "dds/ddsrt/heap.h" -#include "dds/ddsi/q_misc.h" -#include "dds/ddsi/ddsi_xqos.h" -#include "plugin_mock_common.h" - -#include "dds/security/dds_security_api_defs.h" - -#define MOCKLIB_PATH(name) \ - CONFIG_PLUGIN_MOCK_DIR CONFIG_LIB_SEP CONFIG_LIB_PREFIX name CONFIG_LIB_SUFFIX -#define MOCKLIB_ELEM_AUTH(name) \ - "" -#define MOCKLIB_ELEM_CRYPTO(name) \ - "" -#define MOCKLIB_ELEM_ACCESS_CONTROL(name) \ - "" - -#define PROPLIST(auth, crypto, ac, pre_str, post_str, binprops) \ - "property_list={" pre_str \ - "0:\"dds.sec.auth.library.path\":\""auth"\"," \ - "0:\"dds.sec.auth.library.init\":\"init_authentication\"," \ - "0:\"dds.sec.auth.library.finalize\":\"finalize_authentication\"," \ - "0:\"dds.sec.crypto.library.path\":\""crypto"\"," \ - "0:\"dds.sec.crypto.library.init\":\"init_crypto\"," \ - "0:\"dds.sec.crypto.library.finalize\":\"finalize_crypto\"," \ - "0:\"dds.sec.access.library.path\":\""ac"\"," \ - "0:\"dds.sec.access.library.init\":\"init_access_control\"," \ - "0:\"dds.sec.access.library.finalize\":\"finalize_access_control\"," \ - "0:\"dds.sec.auth.identity_ca\":\"" TEST_CA_CERTIFICATE_ALL_OK "\"," \ - "0:\"dds.sec.auth.private_key\":\"" TEST_PRIVATE_KEY_ALL_OK "\"," \ - "0:\"dds.sec.auth.identity_certificate\":\"" TEST_IDENTITY_CERTIFICATE_ALL_OK "\"," \ - "0:\"dds.sec.access.permissions_ca\":\"file:Permissions_CA.pem\"," \ - "0:\"dds.sec.access.governance\":\"file:Governance.p7s\"," \ - "0:\"dds.sec.access.permissions\":\"file:Permissions.p7s\"" \ - post_str "}:{" binprops "}" -#define PARTICIPANT_QOS(auth, crypto, ac, pre_str, post_str, binprops) \ - "PARTICIPANT * QOS={*" PROPLIST (auth, crypto, ac, pre_str, post_str, binprops) "*" -#define PARTICIPANT_QOS_ALL_OK(pre_str, post_str, binprops) \ - PARTICIPANT_QOS (MOCKLIB_PATH ("dds_security_authentication_all_ok"), \ - MOCKLIB_PATH ("dds_security_cryptography_all_ok"), \ - MOCKLIB_PATH ("dds_security_access_control_all_ok"), \ - pre_str, post_str, binprops) - -#define URI_VARIABLE DDS_PROJECT_NAME_NOSPACE_CAPS"_URI" - -/* - * The 'found' variable will contain flags related to the expected log - * messages that were received. - * Using flags will allow to show that when message isn't received, - * which one it was. - */ -static uint32_t found; - -static void logger(void *ptr, const dds_log_data_t *data) -{ - char **expected = (char**)ptr; - fputs (data->message, stdout); - for (uint32_t i = 0; expected[i] != NULL; i++) { - if (ddsi2_patmatch(expected[i], data->message)) { - found |= (uint32_t)(1 << i); - } - } -} - - -CU_Test(ddsc_security_config, empty, .init = ddsrt_init, .fini = ddsrt_fini) -{ - /* Expected traces when creating participant with an empty security element. We need to - test this one here to be sure that it refuses to start when security is configured - but the implementation doesn't include support for it. */ - const char *log_expected[] = { - "config: //CycloneDDS/Domain/DDSSecurity/Authentication/IdentityCertificate/#text: element missing in configuration*", - "config: //CycloneDDS/Domain/DDSSecurity/Authentication/IdentityCA/#text: element missing in configuration*", - "config: //CycloneDDS/Domain/DDSSecurity/Authentication/PrivateKey/#text: element missing in configuration*", - NULL - }; - - dds_entity_t participant; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create participant with an empty security element. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, ""); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - ddsrt_setenv(URI_VARIABLE, ""); - CU_ASSERT_FATAL(participant < 0); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - - /* All traces should have been provided. */ - CU_ASSERT_FATAL(found == 0x7); -} - -CU_Test(ddsc_security_config, non, .init = ddsrt_init, .fini = ddsrt_fini) -{ - /* There shouldn't be traces that mention security. */ - const char *log_expected[] = { - "*Security*", - NULL - }; - - dds_entity_t participant; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create participant with an empty security element. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, "finest"); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - ddsrt_setenv(URI_VARIABLE, ""); - CU_ASSERT_FATAL(participant > 0); - dds_delete(participant); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - - /* No security traces should have been provided. */ - CU_ASSERT_FATAL(found == 0x0); -} - -CU_Test(ddsc_security_config, missing, .init = ddsrt_init, .fini = ddsrt_fini) -{ - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - "config: //CycloneDDS/Domain/DDSSecurity/Authentication/IdentityCertificate/#text: element missing in configuration*", - "config: //CycloneDDS/Domain/DDSSecurity/Authentication/IdentityCA/#text: element missing in configuration*", - "config: //CycloneDDS/Domain/DDSSecurity/Authentication/PrivateKey/#text: element missing in configuration*", - NULL - }; - - /* IdentityCertificate, IdentityCA and PrivateKey values or elements are missing. */ - const char *sec_config = - "finest" - "" - " " - " "MOCKLIB_ELEM_AUTH("dds_security_authentication_all_ok") - " " - " " - " testtext_Password_testtext" - " " - " " - " "MOCKLIB_ELEM_CRYPTO("dds_security_cryptography_all_ok") - " " - " " - " "MOCKLIB_ELEM_ACCESS_CONTROL("dds_security_access_control_all_ok") - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" - " " - ""; - - dds_entity_t participant; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create participant with an empty security element. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, sec_config); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - ddsrt_setenv(URI_VARIABLE, ""); - CU_ASSERT_FATAL(participant < 0); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - /* All traces should have been provided. */ - CU_ASSERT_FATAL(found == 0x7); -} - -CU_Test(ddsc_security_config, all, .init = ddsrt_init, .fini = ddsrt_fini) -{ - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - "config: Domain/DDSSecurity/Authentication/Library/#text: "MOCKLIB_PATH("dds_security_authentication_all_ok")"*", - "config: Domain/DDSSecurity/Authentication/Library[@path]: "MOCKLIB_PATH("dds_security_authentication_all_ok")"*", - "config: Domain/DDSSecurity/Authentication/Library[@initFunction]: init_authentication*", - "config: Domain/DDSSecurity/Authentication/Library[@finalizeFunction]: finalize_authentication*", - "config: Domain/DDSSecurity/Authentication/IdentityCertificate/#text: "TEST_IDENTITY_CERTIFICATE_ALL_OK"*", - "config: Domain/DDSSecurity/Authentication/IdentityCA/#text: "TEST_CA_CERTIFICATE_ALL_OK"*", - "config: Domain/DDSSecurity/Authentication/PrivateKey/#text: "TEST_PRIVATE_KEY_ALL_OK"*", - "config: Domain/DDSSecurity/Authentication/Password/#text: testtext_Password_testtext*", - "config: Domain/DDSSecurity/Authentication/TrustedCADirectory/#text: testtext_Dir_testtext*", - "config: Domain/DDSSecurity/AccessControl/Library/#text: "MOCKLIB_PATH("dds_security_access_control_all_ok")"*", - "config: Domain/DDSSecurity/AccessControl/Library[@path]: "MOCKLIB_PATH("dds_security_access_control_all_ok")"*", - "config: Domain/DDSSecurity/AccessControl/Library[@initFunction]: init_access_control*", - "config: Domain/DDSSecurity/AccessControl/Library[@finalizeFunction]: finalize_access_control*", - "config: Domain/DDSSecurity/AccessControl/PermissionsCA/#text: file:Permissions_CA.pem*", - "config: Domain/DDSSecurity/AccessControl/Governance/#text: file:Governance.p7s*", - "config: Domain/DDSSecurity/AccessControl/Permissions/#text: file:Permissions.p7s*", - "config: Domain/DDSSecurity/Cryptographic/Library/#text: "MOCKLIB_PATH("dds_security_cryptography_all_ok")"*", - "config: Domain/DDSSecurity/Cryptographic/Library[@path]: "MOCKLIB_PATH("dds_security_cryptography_all_ok")"*", - "config: Domain/DDSSecurity/Cryptographic/Library[@initFunction]: init_crypto*", - "config: Domain/DDSSecurity/Cryptographic/Library[@finalizeFunction]: finalize_crypto*", - /* The config should have been parsed into the participant QoS. */ - PARTICIPANT_QOS_ALL_OK ("", ",0:\"dds.sec.auth.password\":\"testtext_Password_testtext\",0:\"dds.sec.auth.trusted_ca_dir\":\"testtext_Dir_testtext\"", ""), - NULL - }; - const char *sec_config = - "<"DDS_PROJECT_NAME">" - " " - " finest" - " " - " " - " "MOCKLIB_ELEM_AUTH("dds_security_authentication_all_ok") - " "TEST_IDENTITY_CERTIFICATE_ALL_OK"" - " "TEST_CA_CERTIFICATE_ALL_OK"" - " "TEST_PRIVATE_KEY_ALL_OK"" - " testtext_Password_testtext" - " testtext_Dir_testtext" - " " - " " - " "MOCKLIB_ELEM_CRYPTO("dds_security_cryptography_all_ok") - " " - " " - " "MOCKLIB_ELEM_ACCESS_CONTROL("dds_security_access_control_all_ok") - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" - " " - " " - " " - ""; - - dds_entity_t participant; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create participant with security elements. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, sec_config); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - CU_ASSERT_FATAL(participant > 0); - ddsrt_setenv(URI_VARIABLE, ""); - dds_delete(participant); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - - /* All traces should have been provided. */ - CU_ASSERT_FATAL(found == 0x1fffff); -} - -CU_Test(ddsc_security_config, security, .init = ddsrt_init, .fini = ddsrt_fini) -{ - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - "config: Domain/DDSSecurity/Authentication/Library/#text: "MOCKLIB_PATH("dds_security_authentication_all_ok")"*", - "config: Domain/DDSSecurity/Authentication/Library[@path]: "MOCKLIB_PATH("dds_security_authentication_all_ok")"*", - "config: Domain/DDSSecurity/Authentication/Library[@initFunction]: init_authentication*", - "config: Domain/DDSSecurity/Authentication/Library[@finalizeFunction]: finalize_authentication*", - "config: Domain/DDSSecurity/Authentication/IdentityCertificate/#text: "TEST_IDENTITY_CERTIFICATE_ALL_OK"*", - "config: Domain/DDSSecurity/Authentication/IdentityCA/#text: "TEST_CA_CERTIFICATE_ALL_OK"*", - "config: Domain/DDSSecurity/Authentication/PrivateKey/#text: "TEST_PRIVATE_KEY_ALL_OK"*", - "config: Domain/DDSSecurity/Authentication/Password/#text: {}*", - "config: Domain/DDSSecurity/Authentication/TrustedCADirectory/#text: {}*", - "config: Domain/DDSSecurity/AccessControl/Library/#text: "MOCKLIB_PATH("dds_security_access_control_all_ok")"*", - "config: Domain/DDSSecurity/AccessControl/Library[@path]: "MOCKLIB_PATH("dds_security_access_control_all_ok")"*", - "config: Domain/DDSSecurity/AccessControl/Library[@initFunction]: init_access_control*", - "config: Domain/DDSSecurity/AccessControl/Library[@finalizeFunction]: finalize_access_control*", - "config: Domain/DDSSecurity/AccessControl/PermissionsCA/#text: file:Permissions_CA.pem*", - "config: Domain/DDSSecurity/AccessControl/Governance/#text: file:Governance.p7s*", - "config: Domain/DDSSecurity/AccessControl/Permissions/#text: file:Permissions.p7s*", - "config: Domain/DDSSecurity/Cryptographic/Library/#text: "MOCKLIB_PATH("dds_security_cryptography_all_ok")"*", - "config: Domain/DDSSecurity/Cryptographic/Library[@path]: "MOCKLIB_PATH("dds_security_cryptography_all_ok")"*", - "config: Domain/DDSSecurity/Cryptographic/Library[@initFunction]: init_crypto*", - "config: Domain/DDSSecurity/Cryptographic/Library[@finalizeFunction]: finalize_crypto*", - /* The config should have been parsed into the participant QoS. */ - PARTICIPANT_QOS_ALL_OK ("", ",0:\"dds.sec.auth.password\":\"\",0:\"dds.sec.auth.trusted_ca_dir\":\"\"", ""), - NULL - }; - - const char *sec_config = - "finest" - "" - " " - " "MOCKLIB_ELEM_AUTH("dds_security_authentication_all_ok") - " "TEST_IDENTITY_CERTIFICATE_ALL_OK"" - " "TEST_CA_CERTIFICATE_ALL_OK"" - " "TEST_PRIVATE_KEY_ALL_OK"" - " " - " " - " "MOCKLIB_ELEM_CRYPTO("dds_security_cryptography_all_ok") - " " - " " - " "MOCKLIB_ELEM_ACCESS_CONTROL("dds_security_access_control_all_ok") - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" - " " - ""; - - dds_entity_t participant; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create participant with security elements. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, sec_config); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - CU_ASSERT_FATAL(participant > 0); - ddsrt_setenv(URI_VARIABLE, ""); - dds_delete(participant); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - - /* All traces should have been provided. */ - CU_ASSERT_FATAL(found == 0x1fffff); -} - -CU_Test(ddsc_security_config, deprecated, .init = ddsrt_init, .fini = ddsrt_fini) -{ - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - "config: Domain/DDSSecurity/Authentication/Library/#text: "MOCKLIB_PATH("dds_security_authentication_all_ok")"*", - "config: Domain/DDSSecurity/Authentication/Library[@path]: "MOCKLIB_PATH("dds_security_authentication_all_ok")"*", - "config: Domain/DDSSecurity/Authentication/Library[@initFunction]: init_authentication*", - "config: Domain/DDSSecurity/Authentication/Library[@finalizeFunction]: finalize_authentication*", - "config: Domain/DDSSecurity/Authentication/IdentityCertificate/#text: "TEST_IDENTITY_CERTIFICATE_ALL_OK"*", - "config: Domain/DDSSecurity/Authentication/IdentityCA/#text: "TEST_CA_CERTIFICATE_ALL_OK"*", - "config: Domain/DDSSecurity/Authentication/PrivateKey/#text: "TEST_PRIVATE_KEY_ALL_OK"*", - "config: Domain/DDSSecurity/Authentication/Password/#text: testtext_Password_testtext*", - "config: Domain/DDSSecurity/Authentication/TrustedCADirectory/#text: testtext_Dir_testtext*", - "config: Domain/DDSSecurity/AccessControl/Library/#text: "MOCKLIB_PATH("dds_security_access_control_all_ok")"*", - "config: Domain/DDSSecurity/AccessControl/Library[@path]: "MOCKLIB_PATH("dds_security_access_control_all_ok")"*", - "config: Domain/DDSSecurity/AccessControl/Library[@initFunction]: init_access_control*", - "config: Domain/DDSSecurity/AccessControl/Library[@finalizeFunction]: finalize_access_control*", - "config: Domain/DDSSecurity/AccessControl/PermissionsCA/#text: file:Permissions_CA.pem*", - "config: Domain/DDSSecurity/AccessControl/Governance/#text: file:Governance.p7s*", - "config: Domain/DDSSecurity/AccessControl/Permissions/#text: file:Permissions.p7s*", - "config: Domain/DDSSecurity/Cryptographic/Library/#text: "MOCKLIB_PATH("dds_security_cryptography_all_ok")"*", - "config: Domain/DDSSecurity/Cryptographic/Library[@path]: "MOCKLIB_PATH("dds_security_cryptography_all_ok")"*", - "config: Domain/DDSSecurity/Cryptographic/Library[@initFunction]: init_crypto*", - "config: Domain/DDSSecurity/Cryptographic/Library[@finalizeFunction]: finalize_crypto*", - /* The config should have been parsed into the participant QoS. */ - PARTICIPANT_QOS_ALL_OK ("", ",0:\"dds.sec.auth.password\":\"testtext_Password_testtext\",0:\"dds.sec.auth.trusted_ca_dir\":\"testtext_Dir_testtext\"", ""), - NULL - }; - - const char *sec_config = - "<"DDS_PROJECT_NAME">" - " " - " " - " " - " "MOCKLIB_ELEM_AUTH("dds_security_authentication_all_ok") - " "TEST_IDENTITY_CERTIFICATE_ALL_OK"" - " "TEST_CA_CERTIFICATE_ALL_OK"" - " "TEST_PRIVATE_KEY_ALL_OK"" - " testtext_Password_testtext" - " testtext_Dir_testtext" - " " - " " - " "MOCKLIB_ELEM_CRYPTO("dds_security_cryptography_all_ok") - " " - " " - " "MOCKLIB_ELEM_ACCESS_CONTROL("dds_security_access_control_all_ok") - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" - " " - " " - " finest" - " " - ""; - - dds_entity_t participant; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create participant with security elements. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, sec_config); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - CU_ASSERT_FATAL(participant > 0); - ddsrt_setenv(URI_VARIABLE, ""); - dds_delete(participant); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - - /* All traces should have been provided. */ - CU_ASSERT_FATAL(found == 0x1fffff); -} - -CU_Test(ddsc_security_config, qos, .init = ddsrt_init, .fini = ddsrt_fini) -{ - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - /* The config should have been parsed into the participant QoS. */ - PARTICIPANT_QOS_ALL_OK ("", ",0:\"dds.sec.auth.password\":\"testtext_Password_testtext\",0:\"dds.sec.auth.trusted_ca_dir\":\"file:/test/dir\"", ""), - NULL - }; - - dds_entity_t participant; - dds_qos_t * qos; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create the qos -- the properties are dumped in the order in which they are set, so for - PARTICIPANT_QOS_ALL_OK to work, the order must match that one */ - CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); - dds_qset_prop(qos, "dds.sec.auth.library.path", ""MOCKLIB_PATH("dds_security_authentication_all_ok")""); - dds_qset_prop(qos, "dds.sec.auth.library.init", "init_authentication"); - dds_qset_prop(qos, "dds.sec.auth.library.finalize", "finalize_authentication"); - dds_qset_prop(qos, "dds.sec.crypto.library.path", ""MOCKLIB_PATH("dds_security_cryptography_all_ok")""); - dds_qset_prop(qos, "dds.sec.crypto.library.init", "init_crypto"); - dds_qset_prop(qos, "dds.sec.crypto.library.finalize", "finalize_crypto"); - dds_qset_prop(qos, "dds.sec.access.library.path", ""MOCKLIB_PATH("dds_security_access_control_all_ok")""); - dds_qset_prop(qos, "dds.sec.access.library.init", "init_access_control"); - dds_qset_prop(qos, "dds.sec.access.library.finalize", "finalize_access_control"); - dds_qset_prop(qos, "dds.sec.auth.identity_ca", TEST_CA_CERTIFICATE_ALL_OK); - dds_qset_prop(qos, "dds.sec.auth.private_key", TEST_PRIVATE_KEY_ALL_OK); - dds_qset_prop(qos, "dds.sec.auth.identity_certificate", TEST_IDENTITY_CERTIFICATE_ALL_OK); - dds_qset_prop(qos, "dds.sec.access.permissions_ca", "file:Permissions_CA.pem"); - dds_qset_prop(qos, "dds.sec.access.governance", "file:Governance.p7s"); - dds_qset_prop(qos, "dds.sec.access.permissions", "file:Permissions.p7s"); - dds_qset_prop(qos, "dds.sec.auth.password", "testtext_Password_testtext"); - dds_qset_prop(qos, "dds.sec.auth.trusted_ca_dir", "file:/test/dir"); - - /* Create participant with security config in qos. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, "finest"); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, qos, NULL); - CU_ASSERT_FATAL(participant > 0); - ddsrt_setenv(URI_VARIABLE, ""); - dds_delete(participant); - dds_delete_qos(qos); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - - /* All traces should have been provided. */ - CU_ASSERT_FATAL(found == 0x1); -} - -CU_Test(ddsc_security_config, qos_props, .init = ddsrt_init, .fini = ddsrt_fini) -{ - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - /* The config should have been parsed into the participant QoS. */ - PARTICIPANT_QOS_ALL_OK ("", ",0:\"dds.sec.auth.password\":\"testtext_Password_testtext\",0:\"dds.sec.auth.trusted_ca_dir\":\"file:/test/dir\",0:\"test.prop1\":\"testtext_value1_testtext\",0:\"test.prop2\":\"testtext_value2_testtext\"", - "0:\"test.bprop1\":3<1,2,3>"), - NULL - }; - - dds_entity_t participant; - dds_qos_t * qos; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL | DDS_LC_ERROR | DDS_LC_WARNING | DDS_LC_CONFIG); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create the qos -- the properties are dumped in the order in which they are set, so for - PARTICIPANT_QOS_ALL_OK to work, the order must match that one */ - unsigned char bvalue[3] = { 0x01, 0x02, 0x03 }; - CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); - - dds_qset_prop(qos, "dds.sec.auth.library.path", ""MOCKLIB_PATH("dds_security_authentication_all_ok")""); - dds_qset_prop(qos, "dds.sec.auth.library.init", "init_authentication"); - dds_qset_prop(qos, "dds.sec.auth.library.finalize", "finalize_authentication"); - dds_qset_prop(qos, "dds.sec.crypto.library.path", ""MOCKLIB_PATH("dds_security_cryptography_all_ok")""); - dds_qset_prop(qos, "dds.sec.crypto.library.init", "init_crypto"); - dds_qset_prop(qos, "dds.sec.crypto.library.finalize", "finalize_crypto"); - dds_qset_prop(qos, "dds.sec.access.library.path", ""MOCKLIB_PATH("dds_security_access_control_all_ok")""); - dds_qset_prop(qos, "dds.sec.access.library.init", "init_access_control"); - dds_qset_prop(qos, "dds.sec.access.library.finalize", "finalize_access_control"); - dds_qset_prop(qos, "dds.sec.auth.identity_ca", TEST_CA_CERTIFICATE_ALL_OK); - dds_qset_prop(qos, "dds.sec.auth.private_key", TEST_PRIVATE_KEY_ALL_OK); - dds_qset_prop(qos, "dds.sec.auth.identity_certificate", TEST_IDENTITY_CERTIFICATE_ALL_OK); - dds_qset_prop(qos, "dds.sec.access.permissions_ca", "file:Permissions_CA.pem"); - dds_qset_prop(qos, "dds.sec.access.governance", "file:Governance.p7s"); - dds_qset_prop(qos, "dds.sec.access.permissions", "file:Permissions.p7s"); - dds_qset_prop(qos, "dds.sec.auth.password", "testtext_Password_testtext"); - dds_qset_prop(qos, "dds.sec.auth.trusted_ca_dir", "file:/test/dir"); - - dds_qset_prop(qos, "test.prop1", "testtext_value1_testtext"); - dds_qset_prop(qos, "test.prop2", "testtext_value2_testtext"); - dds_qset_bprop(qos, "test.bprop1", bvalue, 3); - - /* Create participant with security config in qos. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, "finest"); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, qos, NULL); - CU_ASSERT_FATAL(participant > 0); - ddsrt_setenv(URI_VARIABLE, ""); - dds_delete(participant); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - dds_delete_qos(qos); - - /* All traces should have been provided. */ - CU_ASSERT_FATAL(found == 0x1); -} - -CU_Test(ddsc_security_config, config_qos, .init = ddsrt_init, .fini = ddsrt_fini) -{ - /* Expect qos settings used when creating participant with config security elements and qos. */ - const char *log_expected[] = { - /* The security settings from qos properties should have been parsed into the participant QoS. */ - "new_participant(*): using security settings from QoS*", - PARTICIPANT_QOS_ALL_OK ("", "", ""), - NULL - }; - - const char *sec_config = - "finest" - "" - " " - " "TEST_IDENTITY_CERTIFICATE_ALL_OK"" - " "TEST_CA_CERTIFICATE_ALL_OK"" - " "TEST_PRIVATE_KEY_ALL_OK"" - " " - " " - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" - " " - ""; - - dds_entity_t participant; - dds_qos_t * qos; - - /* Create the qos -- the properties are dumped in the order in which they are set, so for - PARTICIPANT_QOS_ALL_OK to work, the order must match that one */ - CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); - dds_qset_prop(qos, "dds.sec.auth.library.path", ""MOCKLIB_PATH("dds_security_authentication_all_ok")""); - dds_qset_prop(qos, "dds.sec.auth.library.init", "init_authentication"); - dds_qset_prop(qos, "dds.sec.auth.library.finalize", "finalize_authentication"); - dds_qset_prop(qos, "dds.sec.crypto.library.path", ""MOCKLIB_PATH("dds_security_cryptography_all_ok")""); - dds_qset_prop(qos, "dds.sec.crypto.library.init", "init_crypto"); - dds_qset_prop(qos, "dds.sec.crypto.library.finalize", "finalize_crypto"); - dds_qset_prop(qos, "dds.sec.access.library.path", ""MOCKLIB_PATH("dds_security_access_control_all_ok")""); - dds_qset_prop(qos, "dds.sec.access.library.init", "init_access_control"); - dds_qset_prop(qos, "dds.sec.access.library.finalize", "finalize_access_control"); - dds_qset_prop(qos, "dds.sec.auth.identity_ca", TEST_CA_CERTIFICATE_ALL_OK); - dds_qset_prop(qos, "dds.sec.auth.private_key", TEST_PRIVATE_KEY_ALL_OK); - dds_qset_prop(qos, "dds.sec.auth.identity_certificate", TEST_IDENTITY_CERTIFICATE_ALL_OK); - dds_qset_prop(qos, "dds.sec.access.permissions_ca", "file:Permissions_CA.pem"); - dds_qset_prop(qos, "dds.sec.access.governance", "file:Governance.p7s"); - dds_qset_prop(qos, "dds.sec.access.permissions", "file:Permissions.p7s"); - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL | DDS_LC_ERROR | DDS_LC_WARNING | DDS_LC_CONFIG); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create participant with security elements. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, sec_config); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, qos, NULL); - CU_ASSERT_FATAL (participant > 0); - ddsrt_setenv(URI_VARIABLE, ""); - dds_delete(participant); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - dds_delete_qos(qos); - - /* All traces should have been provided. */ - CU_ASSERT_FATAL(found == 0x3); -} - -CU_Test(ddsc_security_config, other_prop, .init = ddsrt_init, .fini = ddsrt_fini) -{ - /* Expect config used when creating participant with config security elements and - * qos containing only non-security properties. */ - const char *log_expected[] = { - /* The security settings from config should have been parsed into the participant QoS. */ - PARTICIPANT_QOS_ALL_OK ("0:\"test.dds.sec.prop1\":\"testtext_value1_testtext\",", ",0:\"dds.sec.auth.password\":\"testtext_Password_testtext\",0:\"dds.sec.auth.trusted_ca_dir\":\"testtext_Dir_testtext\"", ""), - NULL - }; - - const char *sec_config = - "finest" - "" - " " - " "MOCKLIB_ELEM_AUTH("dds_security_authentication_all_ok") - " "TEST_IDENTITY_CERTIFICATE_ALL_OK"" - " "TEST_CA_CERTIFICATE_ALL_OK"" - " "TEST_PRIVATE_KEY_ALL_OK"" - " testtext_Password_testtext" - " testtext_Dir_testtext" - " " - " " - " "MOCKLIB_ELEM_CRYPTO("dds_security_cryptography_all_ok") - " " - " " - " "MOCKLIB_ELEM_ACCESS_CONTROL("dds_security_access_control_all_ok") - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" - " " - ""; - - dds_entity_t participant; - dds_qos_t * qos; - - CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); - dds_qset_prop(qos, "test.dds.sec.prop1", "testtext_value1_testtext"); - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL | DDS_LC_ERROR | DDS_LC_WARNING | DDS_LC_CONFIG); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create participant with security elements. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, sec_config); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, qos, NULL); - CU_ASSERT_FATAL (participant > 0); - ddsrt_setenv(URI_VARIABLE, ""); - dds_delete(participant); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); - dds_delete_qos(qos); - - /* All traces should have been provided. */ - CU_ASSERT_FATAL(found == 0x1); -} - -CU_Test(ddsc_security_config, qos_invalid, .init = ddsrt_init, .fini = ddsrt_fini) -{ - /* Expected traces when creating participant with the security elements. */ - const char *log_expected[] = { - /* The config should have been parsed into the participant QoS. */ - "new_participant(*): using security settings from QoS*", - "new_participant(*): required security property dds.sec.auth.identity_ca missing in Property QoS*", - "new_participant(*): required security property dds.sec.auth.private_key missing in Property QoS*", - "new_participant(*): required security property dds.sec.auth.identity_certificate missing in Property QoS*", - "new_participant(*): required security property dds.sec.access.permissions_ca missing in Property QoS*", - "new_participant(*): required security property dds.sec.access.governance missing in Property QoS*", - "new_participant(*): required security property dds.sec.access.permissions missing in Property QoS*", - "new_participant(*): required security property dds.sec.auth.library.path missing in Property QoS*", - "new_participant(*): required security property dds.sec.auth.library.init missing in Property QoS*", - "new_participant(*): required security property dds.sec.auth.library.finalize missing in Property QoS*", - "new_participant(*): required security property dds.sec.crypto.library.path missing in Property QoS*", - "new_participant(*): required security property dds.sec.crypto.library.init missing in Property QoS*", - "new_participant(*): required security property dds.sec.crypto.library.finalize missing in Property QoS*", - "new_participant(*): required security property dds.sec.access.library.path missing in Property QoS*", - "new_participant(*): required security property dds.sec.access.library.init missing in Property QoS*", - "new_participant(*): required security property dds.sec.access.library.finalize missing in Property QoS*", - NULL - }; - - const char *sec_config = - "finest" - "" - " " - " "TEST_IDENTITY_CERTIFICATE_ALL_OK"" - " "TEST_CA_CERTIFICATE_ALL_OK"" - " "TEST_PRIVATE_KEY_ALL_OK"" - " " - " " - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" - " " - ""; - - dds_entity_t participant; - dds_qos_t * qos; - - /* Set up the trace sinks to detect the config parsing. */ - dds_set_log_mask(DDS_LC_FATAL | DDS_LC_ERROR | DDS_LC_WARNING | DDS_LC_CONFIG); - dds_set_log_sink(&logger, (void*)log_expected); - dds_set_trace_sink(&logger, (void*)log_expected); - - /* Create the qos */ - CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); - dds_qset_prop(qos, "dds.sec.dummy", "testtext_dummy_testtext"); - - /* Create participant with security config in qos. */ - found = 0; - ddsrt_setenv(URI_VARIABLE, sec_config); - participant = dds_create_participant(DDS_DOMAIN_DEFAULT, qos, NULL); - dds_delete_qos(qos); - CU_ASSERT_EQUAL_FATAL(participant, DDS_RETCODE_ERROR); - ddsrt_setenv(URI_VARIABLE, ""); - - /* All traces should have been provided. */ - CU_ASSERT_FATAL(found == 0xffff); - dds_set_log_sink(NULL, NULL); - dds_set_trace_sink(NULL, NULL); -} diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c new file mode 100644 index 0000000..c8ac8df --- /dev/null +++ b/src/security/core/tests/secure_communication.c @@ -0,0 +1,481 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include + +#include "dds/dds.h" +#include "CUnit/Test.h" +#include "CUnit/Theory.h" + +#include "dds/version.h" +#include "dds/ddsrt/cdtors.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/threads.h" +#include "dds/ddsrt/process.h" +#include "dds/ddsi/q_config.h" +#include "dds/ddsi/ddsi_domaingv.h" +#include "dds/ddsi/q_misc.h" +#include "dds/ddsi/ddsi_xqos.h" +#include "dds/ddsi/q_entity.h" +#include "dds/ddsi/ddsi_entity_index.h" +#include "dds/ddsi/ddsi_security_omg.h" +#include "dds__entity.h" +#include "dds/security/dds_security_api.h" + +#include "common/config_env.h" +#include "common/test_identity.h" +#include "common/security_config_test_utils.h" +#include "common/cryptography_wrapper.h" + +#include "SecurityCoreTests.h" + +#define PK_N DDS_SECURITY_PROTECTION_KIND_NONE +#define PK_S DDS_SECURITY_PROTECTION_KIND_SIGN +#define PK_SOA DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION +#define PK_E DDS_SECURITY_PROTECTION_KIND_ENCRYPT +#define PK_EOA DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION +#define BPK_N DDS_SECURITY_BASICPROTECTION_KIND_NONE +#define BPK_S DDS_SECURITY_BASICPROTECTION_KIND_SIGN +#define BPK_E DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT + +static const char *config = + "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" + "0" + "" + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE"" + " "TEST_IDENTITY_PRIVATE_KEY"" + " "TEST_IDENTITY_CA_CERTIFICATE"" + " " + " ." + " " + " " + " " + " " + " file:" COMMON_ETC_PATH("default_permissions_ca.pem") "" + " file:" COMMON_ETC_PATH("default_permissions.p7s") "" + " " + " " + " " + " " + " " + ""; + +#define DDS_DOMAINID_PUB 0 +#define DDS_DOMAINID_SUB 10 + +#define MAX_DOMAINS 10 +#define MAX_PARTICIPANTS 10 + +const char * g_pk_none = "NONE"; +const char * g_pk_sign = "SIGN"; +const char * g_pk_encrypt = "ENCRYPT"; +const char * g_pk_sign_oa = "SIGN_WITH_ORIGIN_AUTHENTICATION"; +const char * g_pk_encrypt_oa = "ENCRYPT_WITH_ORIGIN_AUTHENTICATION"; + +uint32_t g_topic_nr = 0; + +static dds_entity_t g_pub_domains[MAX_DOMAINS]; +static dds_entity_t g_pub_participants[MAX_DOMAINS * MAX_PARTICIPANTS]; +static dds_entity_t g_pub_publishers[MAX_DOMAINS * MAX_PARTICIPANTS]; + +static dds_entity_t g_sub_domains[MAX_DOMAINS]; +static dds_entity_t g_sub_participants[MAX_DOMAINS * MAX_PARTICIPANTS]; +static dds_entity_t g_sub_subscribers[MAX_DOMAINS * MAX_PARTICIPANTS]; + +struct domain_sec_config { + DDS_Security_ProtectionKind discovery_pk; + DDS_Security_ProtectionKind liveliness_pk; + DDS_Security_ProtectionKind rtps_pk; + DDS_Security_ProtectionKind metadata_pk; + DDS_Security_BasicProtectionKind payload_pk; +}; + + +static struct dds_security_cryptography_impl * get_crypto_context(dds_entity_t participant) +{ + struct dds_entity *pp_entity = NULL; + struct participant *pp; + struct dds_security_cryptography_impl *context; + dds_return_t ret; + + ret = dds_entity_lock (participant, DDS_KIND_PARTICIPANT, &pp_entity); + CU_ASSERT_EQUAL_FATAL (ret, 0); + thread_state_awake (lookup_thread_state(), &pp_entity->m_domain->gv); + pp = entidx_lookup_participant_guid (pp_entity->m_domain->gv.entity_index, &pp_entity->m_guid); + CU_ASSERT_FATAL (pp != NULL); + context = (struct dds_security_cryptography_impl *) q_omg_participant_get_cryptography (pp); + thread_state_asleep (lookup_thread_state ()); + dds_entity_unlock (pp_entity); + return context; +} + +static const char * pk_to_str(DDS_Security_ProtectionKind pk) +{ + switch (pk) + { + case DDS_SECURITY_PROTECTION_KIND_NONE: return g_pk_none; + case DDS_SECURITY_PROTECTION_KIND_SIGN: return g_pk_sign; + case DDS_SECURITY_PROTECTION_KIND_ENCRYPT: return g_pk_encrypt; + case DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION: return g_pk_sign_oa; + case DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION: return g_pk_encrypt_oa; + } + assert (false); + return NULL; +} + +static const char * bpk_to_str(DDS_Security_BasicProtectionKind bpk) +{ + switch (bpk) + { + case DDS_SECURITY_BASICPROTECTION_KIND_NONE: return g_pk_none; + case DDS_SECURITY_BASICPROTECTION_KIND_SIGN: return g_pk_sign; + case DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT: return g_pk_encrypt; + } + assert (false); + return NULL; +} + +static void print_config_vars(struct kvp *vars) +{ + for (uint32_t i = 0; vars[i].key != NULL; i++) + printf("%s=%s; ", vars[i].key, vars[i].value); +} + +static char *create_topic_name(const char *prefix, uint32_t nr, char *name, size_t size) +{ + ddsrt_pid_t pid = ddsrt_getpid (); + ddsrt_tid_t tid = ddsrt_gettid (); + (void)snprintf(name, size, "%s%d_pid%" PRIdPID "_tid%" PRIdTID "", prefix, nr, pid, tid); + return name; +} + +static dds_entity_t create_pp (dds_domainid_t domain_id, const struct domain_sec_config * domain_config) +{ + dds_entity_t pp = dds_create_participant (domain_id, NULL, NULL); + CU_ASSERT_FATAL (pp > 0); + struct dds_security_cryptography_impl * crypto_context = get_crypto_context (pp); + CU_ASSERT_FATAL (crypto_context != NULL); + set_protection_kinds (crypto_context, domain_config->rtps_pk, domain_config->metadata_pk, domain_config->payload_pk); + return pp; +} + +typedef dds_entity_t (*pubsub_create_fn)(dds_entity_t, const dds_qos_t *qos, const dds_listener_t *listener); + +static void create_dom_pp_pubsub(dds_domainid_t domain_id_base, const char * domain_conf, const struct domain_sec_config * domain_sec_config, + size_t n_dom, size_t n_pp, dds_entity_t * doms, dds_entity_t * pps, dds_entity_t * pubsubs, pubsub_create_fn pubsub_create) +{ + for (size_t d = 0; d < n_dom; d++) + { + doms[d] = dds_create_domain (domain_id_base + (uint32_t)d, domain_conf); + CU_ASSERT_FATAL (doms[d] > 0); + for (size_t p = 0; p < n_pp; p++) + { + size_t pp_index = d * n_pp + p; + pps[pp_index] = create_pp (domain_id_base + (uint32_t)d, domain_sec_config); + pubsubs[pp_index] = pubsub_create (pps[pp_index], NULL, NULL); + CU_ASSERT_FATAL (pubsubs[pp_index] > 0); + } + } +} + +static void test_init(const struct domain_sec_config * domain_config, size_t n_sub_domains, size_t n_sub_participants, size_t n_pub_domains, size_t n_pub_participants) +{ + assert (n_sub_domains < MAX_DOMAINS); + assert (n_sub_participants < MAX_PARTICIPANTS); + assert (n_pub_domains < MAX_DOMAINS); + assert (n_pub_participants < MAX_PARTICIPANTS); + + struct kvp governance_vars[] = { + { "DISCOVERY_PROTECTION_KIND", pk_to_str (domain_config->discovery_pk) }, + { "LIVELINESS_PROTECTION_KIND", pk_to_str (domain_config->liveliness_pk) }, + { "RTPS_PROTECTION_KIND", pk_to_str (domain_config->rtps_pk) }, + { "METADATA_PROTECTION_KIND", pk_to_str (domain_config->metadata_pk) }, + { "DATA_PROTECTION_KIND", bpk_to_str (domain_config->payload_pk) }, + { NULL, NULL } + }; + + printf("Governance configuration: "); + print_config_vars(governance_vars); + printf("\n"); + + char * gov_config_signed = get_governance_config (governance_vars); + + struct kvp config_vars[] = { + { "GOVERNANCE_DATA", gov_config_signed }, + { "CRYPTO_INIT", "init_test_cryptography_wrapped" }, + { "CRYPTO_FINI", "finalize_test_cryptography_wrapped" }, + { NULL, NULL } + }; + + char *conf_pub = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars); + create_dom_pp_pubsub (DDS_DOMAINID_PUB, conf_pub, domain_config, n_pub_domains, n_pub_participants, + g_pub_domains, g_pub_participants, g_pub_publishers, &dds_create_publisher); + dds_free (conf_pub); + + char *conf_sub = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars); + create_dom_pp_pubsub (DDS_DOMAINID_SUB, conf_sub, domain_config, n_sub_domains, n_sub_participants, + g_sub_domains, g_sub_participants, g_sub_subscribers, &dds_create_subscriber); + dds_free (conf_sub); + + dds_free (gov_config_signed); +} + +static void test_fini(size_t n_sub_domain, size_t n_pub_domain) +{ + dds_return_t ret; + for (size_t d = 0; d < n_pub_domain; d++) + { + ret = dds_delete (g_pub_domains[d]); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + } + for (size_t d = 0; d < n_sub_domain; d++) + { + ret = dds_delete (g_sub_domains[d]); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + } + printf("Test finished\n"); +} + +static void sync_writer_to_readers(dds_entity_t pub_participant, dds_entity_t writer, size_t n_exp_rd) +{ + size_t found = 0; + dds_attach_t triggered; + dds_return_t ret; + dds_entity_t waitset_wr = dds_create_waitset (pub_participant); + CU_ASSERT_FATAL (waitset_wr > 0); + + /* Sync writer to reader. */ + ret = dds_waitset_attach (waitset_wr, writer, writer); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + while (true) + { + ret = dds_waitset_wait (waitset_wr, &triggered, 1, DDS_SECS(5)); + CU_ASSERT_FATAL(ret >= 1); + CU_ASSERT_EQUAL_FATAL (writer, (dds_entity_t)(intptr_t) triggered); + if ((found += (size_t)ret) >= n_exp_rd) + break; + }; + dds_delete (waitset_wr); +} + +static void reader_wait_for_data(dds_entity_t sub_participant, dds_entity_t reader) +{ + dds_attach_t triggered; + dds_return_t ret; + dds_entity_t waitset_rd = dds_create_waitset (sub_participant); + CU_ASSERT_FATAL (waitset_rd > 0); + + ret = dds_waitset_attach (waitset_rd, reader, reader); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + ret = dds_waitset_wait (waitset_rd, &triggered, 1, DDS_SECS(5)); + CU_ASSERT_EQUAL_FATAL (ret, 1); + CU_ASSERT_EQUAL_FATAL (reader, (dds_entity_t)(intptr_t)triggered); + dds_delete (waitset_rd); +} + +typedef dds_entity_t (*ep_create_fn)(dds_entity_t, dds_entity_t, const dds_qos_t *qos, const dds_listener_t *listener); + +static void create_eps (dds_entity_t **endpoints, dds_entity_t **topics, size_t n_dom, size_t n_pp, size_t n_eps, const char * topic_name, const dds_entity_t * pps, const dds_qos_t * qos, ep_create_fn ep_create, unsigned status_mask) +{ + *topics = ddsrt_malloc (n_dom * n_pp * sizeof (dds_entity_t)); + *endpoints = ddsrt_malloc (n_dom * n_pp * n_eps * sizeof (dds_entity_t)); + for (size_t d = 0; d < n_dom; d++) + { + for (size_t p = 0; p < n_pp; p++) + { + size_t pp_index = d * n_pp + p; + (*topics)[pp_index] = dds_create_topic (pps[pp_index], &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL); + CU_ASSERT_FATAL ((*topics)[pp_index] > 0); + for (size_t e = 0; e < n_eps; e++) + { + size_t ep_index = pp_index * n_eps + e; + (*endpoints)[ep_index] = ep_create (pps[pp_index], (*topics)[pp_index], qos, NULL); + CU_ASSERT_FATAL ((*endpoints)[ep_index] > 0); + dds_return_t ret = dds_set_status_mask ((*endpoints)[ep_index], status_mask); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + } + } + } +} + +static void test_write_read(struct domain_sec_config *domain_config, + size_t n_sub_domains, size_t n_sub_participants, size_t n_readers, + size_t n_pub_domains, size_t n_pub_participants, size_t n_writers) +{ + dds_entity_t *writers, *readers, *writer_topics, *reader_topics; + dds_qos_t *qos; + SecurityCoreTests_Type1 sample = { 0, 1 }; + SecurityCoreTests_Type1 rd_sample; + void * samples[] = { &rd_sample }; + dds_sample_info_t info[1]; + dds_return_t ret; + char name[100]; + + printf("Testing: %"PRIuSIZE" subscriber domains, %"PRIuSIZE" pp per domain, %"PRIuSIZE" rd per pp; %"PRIuSIZE" publishing domains, %"PRIuSIZE" pp per domain, %"PRIuSIZE" wr per pp\n", + n_sub_domains, n_sub_participants, n_readers, n_pub_domains, n_pub_participants, n_writers); + test_init(domain_config, n_sub_domains, n_sub_participants, n_pub_domains, n_pub_participants); + + create_topic_name("ddssec_secure_communication_", g_topic_nr++, name, sizeof name); + + qos = dds_create_qos (); + CU_ASSERT_FATAL (qos != NULL); + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, -1); + dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL); + dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); + + create_eps (&writers, &writer_topics, n_pub_domains, n_pub_participants, n_writers, name, g_pub_participants, qos, &dds_create_writer, DDS_PUBLICATION_MATCHED_STATUS); + create_eps (&readers, &reader_topics, n_sub_domains, n_sub_participants, n_readers, name, g_sub_participants, qos, &dds_create_reader, DDS_DATA_AVAILABLE_STATUS); + + for (size_t d = 0; d < n_pub_domains; d++) + { + for (size_t p = 0; p < n_pub_participants; p++) + { + size_t pp_index = d * n_pub_participants + p; + for (size_t w = 0; w < n_writers; w++) + { + size_t wr_index = pp_index * n_writers + w; + sync_writer_to_readers (g_pub_participants[pp_index], writers[wr_index], n_sub_domains * n_sub_participants * n_readers); + sample.id = (int32_t) wr_index; + printf("writer %"PRId32" writing sample %d\n", writers[wr_index], sample.id); + ret = dds_write (writers[wr_index], &sample); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + } + } + } + + for (size_t d = 0; d < n_sub_domains; d++) + { + for (size_t p = 0; p < n_sub_participants; p++) + { + size_t pp_index = d * n_sub_participants + p; + for (size_t r = 0; r < n_readers; r++) + { + size_t rd_index = pp_index * n_readers + r; + size_t n_samples = n_pub_domains * n_pub_participants * n_writers; + while (n_samples > 0) + { + ret = dds_take (readers[rd_index], samples, info, 1, 1); + if (ret == 0) + { + reader_wait_for_data (g_sub_participants[pp_index], readers[rd_index]); + continue; + } + printf("reader %"PRId32" received sample %d\n", readers[rd_index], rd_sample.id); + CU_ASSERT_EQUAL_FATAL (ret, 1); + CU_ASSERT_EQUAL_FATAL (rd_sample.value, 1); + n_samples--; + } + } + } + } + + /* Cleanup */ + dds_delete_qos (qos); + test_fini (n_sub_domains, n_pub_domains); + ddsrt_free (readers); + ddsrt_free (writers); + ddsrt_free (reader_topics); + ddsrt_free (writer_topics); +} + +static void test_discovery_liveliness_protection(DDS_Security_ProtectionKind discovery_pk, DDS_Security_ProtectionKind liveliness_pk) +{ + struct domain_sec_config domain_config = { discovery_pk, liveliness_pk, PK_N, PK_N, BPK_N }; + /* FIXME: add more asserts in wrapper or test instead of just testing communication */ + test_write_read (&domain_config, 1, 1, 1, 1, 1, 1); +} + +static void test_data_protection_kind(DDS_Security_ProtectionKind rtps_pk, DDS_Security_ProtectionKind metadata_pk, DDS_Security_BasicProtectionKind payload_pk) +{ + struct domain_sec_config domain_config = { PK_N, PK_N, rtps_pk, metadata_pk, payload_pk }; + test_write_read (&domain_config, 1, 1, 1, 1, 1, 1); +} + +static void test_multiple_readers(size_t n_dom, size_t n_pp, size_t n_rd, DDS_Security_ProtectionKind metadata_pk, DDS_Security_BasicProtectionKind payload_pk) +{ + struct domain_sec_config domain_config = { PK_N, PK_N, PK_N, metadata_pk, payload_pk }; + test_write_read (&domain_config, n_dom, n_pp, n_rd, 1, 1, 1); +} + +static void test_multiple_writers(size_t n_rd_dom, size_t n_rd, size_t n_wr_dom, size_t n_wr, DDS_Security_ProtectionKind metadata_pk) +{ + struct domain_sec_config domain_config = { PK_N, PK_N, PK_N, metadata_pk, BPK_N }; + test_write_read (&domain_config, n_rd_dom, 1, n_rd, n_wr_dom, 1, n_wr); +} + +CU_Test(ddssec_secure_communication, protection_kinds, .timeout = 120) +{ + DDS_Security_ProtectionKind rtps_pk[] = { PK_N, PK_S, PK_E }; + DDS_Security_ProtectionKind metadata_pk[] = { PK_N, PK_S, PK_E }; + DDS_Security_BasicProtectionKind payload_pk[] = { BPK_N, BPK_S, BPK_E }; + for (size_t rtps = 0; rtps < sizeof (rtps_pk) / sizeof (rtps_pk[0]); rtps++) + { + for (size_t metadata = 0; metadata < sizeof (metadata_pk) / sizeof (metadata_pk[0]); metadata++) + { + for (size_t payload = 0; payload < sizeof (payload_pk) / sizeof (payload_pk[0]); payload++) + { + test_data_protection_kind (rtps_pk[rtps], metadata_pk[metadata], payload_pk[payload]); + } + } + } +} + +CU_Test(ddssec_secure_communication, discovery_liveliness_protection, .timeout = 60) +{ + DDS_Security_ProtectionKind discovery_pk[] = { PK_N, PK_S, PK_E }; + DDS_Security_ProtectionKind liveliness_pk[] = { PK_N, PK_S, PK_E }; + for (size_t disc = 0; disc < sizeof (discovery_pk) / sizeof (discovery_pk[0]); disc++) + { + for (size_t liveliness = 0; liveliness < sizeof (liveliness_pk) / sizeof (liveliness_pk[0]); liveliness++) + { + test_discovery_liveliness_protection (discovery_pk[disc], liveliness_pk[liveliness]); + } + } +} + +CU_TheoryDataPoints(ddssec_secure_communication, multiple_readers) = { + CU_DataPoints(size_t, 1, 1, 1, 3), /* number of domains */ + CU_DataPoints(size_t, 1, 3, 1, 3), /* number of participants per domain */ + CU_DataPoints(size_t, 3, 1, 3, 3), /* number of readers per participant */ +}; +CU_Theory((size_t n_dom, size_t n_pp, size_t n_rd), ddssec_secure_communication, multiple_readers, .timeout = 60) +{ + DDS_Security_ProtectionKind metadata_pk[] = { PK_N, PK_SOA, PK_EOA }; + DDS_Security_BasicProtectionKind payload_pk[] = { BPK_N, BPK_S, BPK_E }; + for (size_t metadata = 0; metadata < sizeof (metadata_pk) / sizeof (metadata_pk[0]); metadata++) + { + for (size_t payload = 0; payload < sizeof (payload_pk) / sizeof (payload_pk[0]); payload++) + { + test_multiple_readers (n_dom, n_pp, n_rd, metadata_pk[metadata], payload_pk[payload]); + } + } +} + +CU_TheoryDataPoints(ddssec_secure_communication, multiple_readers_writers) = { + CU_DataPoints(size_t, 1, 1, 2), /* number of reader domains */ + CU_DataPoints(size_t, 1, 3, 3), /* number of readers per domain */ + CU_DataPoints(size_t, 1, 1, 2), /* number of writer domains */ + CU_DataPoints(size_t, 1, 3, 3), /* number of writers per domain */ +}; +CU_Theory((size_t n_rd_dom, size_t n_rd, size_t n_wr_dom, size_t n_wr), ddssec_secure_communication, multiple_readers_writers, .timeout = 60) +{ + DDS_Security_ProtectionKind metadata_pk[] = { PK_SOA, PK_EOA }; + for (size_t metadata = 0; metadata < sizeof (metadata_pk) / sizeof (metadata_pk[0]); metadata++) + { + test_multiple_writers (n_rd_dom, n_rd, n_wr_dom, n_wr, metadata_pk[metadata]); + } +} From 6c9e50cf3ae7c3a7aa5ffef3fc042da67d000d71 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Mon, 2 Mar 2020 10:55:19 +0100 Subject: [PATCH 112/238] Fix for empty trusted CA dir Trusted CA dir in security configuration is optional, but participant creation currently fails if no or empty dir is provided. This commit fixes this issue and adds some tests for various trusted_ca_dir values. Signed-off-by: Dennis Potman --- src/ddsrt/src/filesystem/posix/filesystem.c | 7 +-- .../authentication/src/authentication.c | 10 +--- src/security/core/tests/authentication.c | 57 +++++++++++++++---- src/security/core/tests/handshake.c | 2 - 4 files changed, 53 insertions(+), 23 deletions(-) diff --git a/src/ddsrt/src/filesystem/posix/filesystem.c b/src/ddsrt/src/filesystem/posix/filesystem.c index 11b57ce..1db647c 100644 --- a/src/ddsrt/src/filesystem/posix/filesystem.c +++ b/src/ddsrt/src/filesystem/posix/filesystem.c @@ -87,14 +87,14 @@ char * ddsrt_file_normalize(const char *filepath) char *normPtr; norm = NULL; - if ((filepath != NULL) && (*filepath != '\0')) { - norm = ddsrt_malloc(strlen(filepath) + 1); + if (filepath != NULL) { + norm = ddsrt_malloc (strlen (filepath) + 1); /* replace any / or \ by DDSRT_FILESEPCHAR */ fpPtr = (char *) filepath; normPtr = norm; while (*fpPtr != '\0') { *normPtr = *fpPtr; - if ((*fpPtr == '/') || (*fpPtr == '\\')) { + if (*fpPtr == '/' || *fpPtr == '\\') { *normPtr = DDSRT_FILESEPCHAR; normPtr++; } else { @@ -106,7 +106,6 @@ char * ddsrt_file_normalize(const char *filepath) } *normPtr = '\0'; } - return norm; } diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index d6139d9..4d317d7 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -980,17 +980,13 @@ validate_local_identity( password = DDS_Security_Property_get_value(&participant_qos->property.value, PROPERTY_PASSWORD); - trusted_ca_dir = DDS_Security_Property_get_value(&participant_qos->property.value, PROPERTY_TRUSTED_CA_DIR); - - if( trusted_ca_dir ){ - result = get_trusted_ca_list(trusted_ca_dir, &(implementation->trustedCAList), ex ); - if (result != DDS_SECURITY_VALIDATION_OK) { + if (trusted_ca_dir && *trusted_ca_dir != '\0') + { + if ((result = get_trusted_ca_list (trusted_ca_dir, &(implementation->trustedCAList), ex)) != DDS_SECURITY_VALIDATION_OK) goto err_inv_trusted_ca_dir; - } } - result = load_X509_certificate(identityCaPEM, &identityCA, ex); if (result != DDS_SECURITY_VALIDATION_OK) { goto err_inv_identity_ca; diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index e981648..c1e022d 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -14,6 +14,7 @@ #include "dds/dds.h" #include "CUnit/Test.h" +#include "CUnit/Theory.h" #include "dds/version.h" #include "dds/ddsrt/cdtors.h" @@ -44,8 +45,7 @@ static const char *config = " ${TEST_IDENTITY_CERTIFICATE}" " ${TEST_IDENTITY_PRIVATE_KEY}" " ${TEST_IDENTITY_CA_CERTIFICATE}" - " testtext_Password_testtext" - " ." + " ${TRUSTED_CA_DIR:+}${TRUSTED_CA_DIR}${TRUSTED_CA_DIR:+}" " " " " " " @@ -61,6 +61,7 @@ static const char *config = #define DDS_DOMAINID1 0 #define DDS_DOMAINID2 1 +#define MAX_ADDITIONAL_CONF 255 static dds_entity_t g_domain1 = 0; static dds_entity_t g_participant1 = 0; @@ -68,7 +69,7 @@ static dds_entity_t g_participant1 = 0; static dds_entity_t g_domain2 = 0; static dds_entity_t g_participant2 = 0; -static void authentication_init(void) +static void authentication_init(bool different_ca, const char * trusted_ca_dir, bool exp_pp_fail) { struct kvp governance_vars[] = { { "ALLOW_UNAUTH_PP", "false" }, @@ -82,38 +83,74 @@ static void authentication_init(void) { "TEST_IDENTITY_CERTIFICATE", TEST_IDENTITY_CERTIFICATE }, { "TEST_IDENTITY_PRIVATE_KEY", TEST_IDENTITY_PRIVATE_KEY }, { "TEST_IDENTITY_CA_CERTIFICATE", TEST_IDENTITY_CA_CERTIFICATE }, + { "TRUSTED_CA_DIR", trusted_ca_dir }, { NULL, NULL } }; + struct kvp config_vars2[] = { { "GOVERNANCE_DATA", gov_config_signed }, { "TEST_IDENTITY_CERTIFICATE", TEST_IDENTITY2_CERTIFICATE }, { "TEST_IDENTITY_PRIVATE_KEY", TEST_IDENTITY2_PRIVATE_KEY }, { "TEST_IDENTITY_CA_CERTIFICATE", TEST_IDENTITY_CA2_CERTIFICATE }, + { "TRUSTED_CA_DIR", trusted_ca_dir }, { NULL, NULL } }; char *conf1 = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars1); char *conf2 = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars2); g_domain1 = dds_create_domain (DDS_DOMAINID1, conf1); - g_domain2 = dds_create_domain (DDS_DOMAINID2, conf2); + g_domain2 = dds_create_domain (DDS_DOMAINID2, different_ca ? conf2 : conf1); dds_free (conf1); dds_free (conf2); ddsrt_free (gov_config_signed); - CU_ASSERT_FATAL ((g_participant1 = dds_create_participant (DDS_DOMAINID1, NULL, NULL)) > 0); - CU_ASSERT_FATAL ((g_participant2 = dds_create_participant (DDS_DOMAINID2, NULL, NULL)) > 0); + g_participant1 = dds_create_participant (DDS_DOMAINID1, NULL, NULL); + g_participant2 = dds_create_participant (DDS_DOMAINID2, NULL, NULL); + if (exp_pp_fail) + { + CU_ASSERT_FATAL (g_participant1 <= 0); + CU_ASSERT_FATAL (g_participant2 <= 0); + } + else + { + CU_ASSERT_FATAL (g_participant1 > 0); + CU_ASSERT_FATAL (g_participant2 > 0); + } } -static void authentication_fini(void) +static void authentication_fini(bool delete_pp) { - CU_ASSERT_EQUAL_FATAL (dds_delete (g_participant1), DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL (dds_delete (g_participant2), DDS_RETCODE_OK); + if (delete_pp) + { + CU_ASSERT_EQUAL_FATAL (dds_delete (g_participant1), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL (dds_delete (g_participant2), DDS_RETCODE_OK); + } CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain1), DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain2), DDS_RETCODE_OK); } -CU_Test(ddssec_authentication, different_ca, .init = authentication_init, .fini = authentication_fini) +CU_Test(ddssec_authentication, different_ca) { + authentication_init (true, NULL, false); validate_handshake (DDS_DOMAINID1, true, NULL, true, "error: unable to get local issuer certificate"); validate_handshake (DDS_DOMAINID2, true, NULL, true, "error: unable to get local issuer certificate"); + authentication_fini (true); +} + + +CU_TheoryDataPoints(ddssec_authentication, trusted_ca_dir) = { + CU_DataPoints(const char *, "", ".", "/nonexisting", NULL), + CU_DataPoints(bool, false, false, true, false) +}; + +CU_Theory((const char * ca_dir, bool exp_fail), ddssec_authentication, trusted_ca_dir) +{ + printf("Testing custom CA dir: %s\n", ca_dir); + authentication_init (false, ca_dir, exp_fail); + if (!exp_fail) + { + validate_handshake (DDS_DOMAINID1, false, NULL, false, NULL); + validate_handshake (DDS_DOMAINID2, false, NULL, false, NULL); + } + authentication_fini (!exp_fail); } diff --git a/src/security/core/tests/handshake.c b/src/security/core/tests/handshake.c index 6de2876..2eb52fc 100644 --- a/src/security/core/tests/handshake.c +++ b/src/security/core/tests/handshake.c @@ -44,8 +44,6 @@ static const char *config = " "TEST_IDENTITY_CERTIFICATE"" " "TEST_IDENTITY_PRIVATE_KEY"" " "TEST_IDENTITY_CA_CERTIFICATE"" - " testtext_Password_testtext" - " ." " " " " " " From 28aa06915e11f17c8e29f39df25cd7793460d88b Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Mon, 2 Mar 2020 13:05:05 +0100 Subject: [PATCH 113/238] Fixed bug in handshake happy-day test Signed-off-by: Dennis Potman --- src/security/core/tests/common/handshake_test_utils.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/security/core/tests/common/handshake_test_utils.c b/src/security/core/tests/common/handshake_test_utils.c index 5385fe5..6d2e494 100644 --- a/src/security/core/tests/common/handshake_test_utils.c +++ b/src/security/core/tests/common/handshake_test_utils.c @@ -145,9 +145,9 @@ static bool handle_begin_handshake_request(dds_domainid_t domain_id, DDS_Securit if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REQUEST, lid, rid, 0, TIMEOUT))) { add_handshake(msg->hsHandle, 1, msg->lidHandle, msg->ridHandle, msg->result); - if (msg->result == DDS_SECURITY_VALIDATION_OK) + if (msg->result != DDS_SECURITY_VALIDATION_FAILED) result = handle_process_message(domain_id, msg->hsHandle); - else if (msg->result == DDS_SECURITY_VALIDATION_FAILED && err_msg) + else if (err_msg) *err_msg = ddsrt_strdup (msg->err_msg); test_authentication_plugin_release_msg(msg); } @@ -162,9 +162,9 @@ static bool handle_begin_handshake_reply(dds_domainid_t domain_id, DDS_Security_ if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REPLY, lid, rid, 0, TIMEOUT))) { add_handshake(msg->hsHandle, 0, msg->lidHandle, msg->ridHandle, msg->result); - if (msg->result == DDS_SECURITY_VALIDATION_OK) + if (msg->result != DDS_SECURITY_VALIDATION_FAILED) result = handle_process_message(domain_id, msg->hsHandle); - else if (msg->result == DDS_SECURITY_VALIDATION_FAILED && err_msg) + else if (err_msg) *err_msg = ddsrt_strdup (msg->err_msg); test_authentication_plugin_release_msg(msg); } From 8f464e0c99ddea7c13d6f6ff7ca7c2b0a71a76fb Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Mon, 2 Mar 2020 14:58:31 +0100 Subject: [PATCH 114/238] Fix writer-reader sync in secure_communication tests Signed-off-by: Dennis Potman --- src/security/core/tests/secure_communication.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index c8ac8df..54882e4 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -252,11 +252,11 @@ static void test_fini(size_t n_sub_domain, size_t n_pub_domain) static void sync_writer_to_readers(dds_entity_t pub_participant, dds_entity_t writer, size_t n_exp_rd) { - size_t found = 0; dds_attach_t triggered; dds_return_t ret; dds_entity_t waitset_wr = dds_create_waitset (pub_participant); CU_ASSERT_FATAL (waitset_wr > 0); + dds_publication_matched_status_t pub_matched; /* Sync writer to reader. */ ret = dds_waitset_attach (waitset_wr, writer, writer); @@ -264,9 +264,11 @@ static void sync_writer_to_readers(dds_entity_t pub_participant, dds_entity_t wr while (true) { ret = dds_waitset_wait (waitset_wr, &triggered, 1, DDS_SECS(5)); - CU_ASSERT_FATAL(ret >= 1); + CU_ASSERT_FATAL (ret >= 1); CU_ASSERT_EQUAL_FATAL (writer, (dds_entity_t)(intptr_t) triggered); - if ((found += (size_t)ret) >= n_exp_rd) + ret = dds_get_publication_matched_status(writer, &pub_matched); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + if (pub_matched.total_count >= n_exp_rd) break; }; dds_delete (waitset_wr); From ea10dbd8e162c95aa96a56298837d75c789839ba Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 3 Mar 2020 12:14:39 +0100 Subject: [PATCH 115/238] Fixes in security core tests: add check that all provided vars are used in variable expansion for test configs, add note on concurrency in authentication wrapper, replace assert by cunit assert in crypto wrapper Signed-off-by: Dennis Potman --- src/security/core/tests/CMakeLists.txt | 5 ++- src/security/core/tests/authentication.c | 34 +++++++---------- .../tests/common/authentication_wrapper.c | 37 ++++++++++++++----- .../core/tests/common/cryptography_wrapper.c | 11 +++--- .../tests/common/security_config_test_utils.c | 20 +++++++++- .../tests/common/security_config_test_utils.h | 2 + .../core/tests/secure_communication.c | 24 ++++++------ 7 files changed, 83 insertions(+), 50 deletions(-) diff --git a/src/security/core/tests/CMakeLists.txt b/src/security/core/tests/CMakeLists.txt index 9fcc0c0..af2b446 100644 --- a/src/security/core/tests/CMakeLists.txt +++ b/src/security/core/tests/CMakeLists.txt @@ -46,6 +46,9 @@ function(add_wrapper libname linklibs) set_target_properties("dds_security_${libname}_wrapper" PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") endif() + target_link_libraries("dds_security_${libname}_wrapper" PRIVATE CUnit) + target_include_directories("dds_security_${libname}_wrapper" PRIVATE "${CUNIT_DIR}/include") + target_link_libraries("dds_security_${libname}_wrapper" PUBLIC ddsc ${linklibs}) target_sources("dds_security_${libname}_wrapper" PRIVATE ${srcs_wrapper}) target_include_directories("dds_security_${libname}_wrapper" @@ -87,7 +90,7 @@ endif() target_include_directories( cunit_security_core PRIVATE - "$" + "$" "$>" "$>" "$>" diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index c1e022d..1ed8ce6 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -38,7 +38,7 @@ static const char *config = "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" "0" "" - " finest" + " config" " " " " " " @@ -71,38 +71,30 @@ static dds_entity_t g_participant2 = 0; static void authentication_init(bool different_ca, const char * trusted_ca_dir, bool exp_pp_fail) { - struct kvp governance_vars[] = { - { "ALLOW_UNAUTH_PP", "false" }, - { "ENABLE_JOIN_AC", "true" }, - { NULL, NULL } - }; - char * gov_config_signed = get_governance_config (governance_vars); - struct kvp config_vars1[] = { - { "GOVERNANCE_DATA", gov_config_signed }, - { "TEST_IDENTITY_CERTIFICATE", TEST_IDENTITY_CERTIFICATE }, - { "TEST_IDENTITY_PRIVATE_KEY", TEST_IDENTITY_PRIVATE_KEY }, - { "TEST_IDENTITY_CA_CERTIFICATE", TEST_IDENTITY_CA_CERTIFICATE }, - { "TRUSTED_CA_DIR", trusted_ca_dir }, - { NULL, NULL } + { "TEST_IDENTITY_CERTIFICATE", TEST_IDENTITY_CERTIFICATE, 1 }, + { "TEST_IDENTITY_PRIVATE_KEY", TEST_IDENTITY_PRIVATE_KEY, 1 }, + { "TEST_IDENTITY_CA_CERTIFICATE", TEST_IDENTITY_CA_CERTIFICATE, 1 }, + { "TRUSTED_CA_DIR", trusted_ca_dir, 3 }, + { NULL, NULL, 0 } }; struct kvp config_vars2[] = { - { "GOVERNANCE_DATA", gov_config_signed }, - { "TEST_IDENTITY_CERTIFICATE", TEST_IDENTITY2_CERTIFICATE }, - { "TEST_IDENTITY_PRIVATE_KEY", TEST_IDENTITY2_PRIVATE_KEY }, - { "TEST_IDENTITY_CA_CERTIFICATE", TEST_IDENTITY_CA2_CERTIFICATE }, - { "TRUSTED_CA_DIR", trusted_ca_dir }, - { NULL, NULL } + { "TEST_IDENTITY_CERTIFICATE", TEST_IDENTITY2_CERTIFICATE, 1 }, + { "TEST_IDENTITY_PRIVATE_KEY", TEST_IDENTITY2_PRIVATE_KEY, 1 }, + { "TEST_IDENTITY_CA_CERTIFICATE", TEST_IDENTITY_CA2_CERTIFICATE, 1 }, + { "TRUSTED_CA_DIR", trusted_ca_dir, 3 }, + { NULL, NULL, 0 } }; char *conf1 = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars1); char *conf2 = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars2); + CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars1), 0); + CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars2), 0); g_domain1 = dds_create_domain (DDS_DOMAINID1, conf1); g_domain2 = dds_create_domain (DDS_DOMAINID2, different_ca ? conf2 : conf1); dds_free (conf1); dds_free (conf2); - ddsrt_free (gov_config_signed); g_participant1 = dds_create_participant (DDS_DOMAINID1, NULL, NULL); g_participant2 = dds_create_participant (DDS_DOMAINID2, NULL, NULL); diff --git a/src/security/core/tests/common/authentication_wrapper.c b/src/security/core/tests/common/authentication_wrapper.c index b794a3e..0ab9882 100644 --- a/src/security/core/tests/common/authentication_wrapper.c +++ b/src/security/core/tests/common/authentication_wrapper.c @@ -46,7 +46,8 @@ struct dds_security_authentication_impl }; static struct dds_security_authentication_impl **auth_impl; -static size_t auth_impl_count = 0; +static size_t auth_impl_idx = 0; +static size_t auth_impl_use = 0; static const char *test_identity_certificate = TEST_IDENTITY_CERTIFICATE_DUMMY; static const char *test_private_key = TEST_IDENTITY_PRIVATE_KEY_DUMMY; @@ -436,11 +437,10 @@ static DDS_Security_boolean test_return_sharedsecret_handle( static struct dds_security_authentication_impl * get_impl_for_domain(dds_domainid_t domain_id) { - for (size_t i = 0; i < auth_impl_count; i++) + for (size_t i = 0; i < auth_impl_idx; i++) { - if (auth_impl[i]->gv->config.domainId == domain_id) + if (auth_impl[i] && auth_impl[i]->gv->config.domainId == domain_id) { - assert(auth_impl[i]); return auth_impl[i]; } } @@ -531,6 +531,10 @@ int32_t finalize_test_authentication_init_error(void *context) return 0; } +/** + * Init and fini functions for using wrapped mode for the authentication plugin. + * These functions assumes that there are no concurrent calls, as the static + * variables used here are not protected by a lock. */ int32_t init_test_authentication_wrapped(const char *argument, void **context) { int32_t ret; @@ -544,10 +548,10 @@ int32_t init_test_authentication_wrapped(const char *argument, void **context) ret = init_authentication(argument, (void **)&impl->instance); - auth_impl_count++; - auth_impl = ddsrt_realloc(auth_impl, auth_impl_count * sizeof(*auth_impl)); - auth_impl[auth_impl_count - 1] = impl; - + auth_impl_idx++; + auth_impl = ddsrt_realloc(auth_impl, auth_impl_idx * sizeof(*auth_impl)); + auth_impl[auth_impl_idx - 1] = impl; + auth_impl_use++; *context = impl; return ret; } @@ -559,8 +563,23 @@ int32_t finalize_test_authentication_wrapped(void *context) assert(impl->mode == PLUGIN_MODE_WRAPPED); deinit_message_queue(&impl->msg_queue); ret = finalize_authentication(impl->instance); + + size_t idx; + for (idx = 0; idx < auth_impl_idx; idx++) + if (auth_impl[idx] == impl) + break; + assert (idx < auth_impl_idx); + auth_impl[idx] = NULL; + ddsrt_free(context); - auth_impl_count--; + + if (--auth_impl_use == 0) + { + ddsrt_free (auth_impl); + auth_impl = NULL; + auth_impl_idx = 0; + } + return ret; } diff --git a/src/security/core/tests/common/cryptography_wrapper.c b/src/security/core/tests/common/cryptography_wrapper.c index ad9346b..f220c5c 100644 --- a/src/security/core/tests/common/cryptography_wrapper.c +++ b/src/security/core/tests/common/cryptography_wrapper.c @@ -11,6 +11,7 @@ */ #include #include +#include "CUnit/Test.h" #include "dds/dds.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" @@ -74,15 +75,15 @@ void set_protection_kinds( impl->payload_protection_kind = payload_protection_kind; } -static unsigned char * find_buffer_match(unsigned char *input, size_t input_len, unsigned char *match, size_t match_len) +static unsigned char * find_buffer_match(const unsigned char *input, size_t input_len, const unsigned char *match, size_t match_len) { if (match_len <= input_len && match_len > 0 && input_len > 0) { - unsigned char *match_end = match + match_len; - unsigned char *i = input; + const unsigned char *match_end = match + match_len; + unsigned char *i = (unsigned char *) input; while (i <= input + input_len - match_len) { - unsigned char *m = match, *j = i; + unsigned char *m = (unsigned char *) match, *j = i; while (*m == *j && j < input + input_len) { j++; @@ -113,7 +114,7 @@ static DDS_Security_long_long check_handle(DDS_Security_long_long handle) { /* Assume that handle, which actually is a pointer, has a value that is likely to be a valid memory address and not a value returned by the mock implementation. */ - assert (handle == 0 || handle > 4096); + CU_ASSERT_FATAL (handle == 0 || handle > 4096); return handle; } diff --git a/src/security/core/tests/common/security_config_test_utils.c b/src/security/core/tests/common/security_config_test_utils.c index c67a4d8..c6e939b 100644 --- a/src/security/core/tests/common/security_config_test_utils.c +++ b/src/security/core/tests/common/security_config_test_utils.c @@ -61,11 +61,14 @@ static const char *governance_xml = const char * expand_lookup_vars(const char *name, void * data) { - const struct kvp *vars = (struct kvp *)data; + struct kvp *vars = (struct kvp *)data; for (uint32_t i = 0; vars[i].key != NULL; i++) { if (!strcmp(vars[i].key, name)) + { + vars[i].count--; return vars[i].value; + } } return NULL; } @@ -78,6 +81,21 @@ const char * expand_lookup_vars_env(const char *name, void * data) return ((ddsrt_getenv(name, &env)) == DDS_RETCODE_OK) ? env : NULL; } +int32_t expand_lookup_unmatched (const struct kvp * lookup_table) +{ + int32_t unmatched = 0; + for (uint32_t i = 0; lookup_table[i].key != NULL; i++) + { + int32_t c = lookup_table[i].count; + if (c > 0 && unmatched >= INT32_MAX - c) + return INT32_MAX; + if (c < 0 && unmatched <= INT32_MIN - c) + return INT32_MIN; + unmatched += c; + } + return unmatched; +} + static char * smime_sign(char * ca_cert_path, char * ca_priv_key_path, const char * data) { // Read CA certificate diff --git a/src/security/core/tests/common/security_config_test_utils.h b/src/security/core/tests/common/security_config_test_utils.h index d2c8635..ab14b7f 100644 --- a/src/security/core/tests/common/security_config_test_utils.h +++ b/src/security/core/tests/common/security_config_test_utils.h @@ -18,10 +18,12 @@ struct kvp { const char *key; const char *value; + int32_t count; }; const char * expand_lookup_vars (const char *name, void * data); const char * expand_lookup_vars_env (const char *name, void * data); +int32_t expand_lookup_unmatched (const struct kvp * lookup_table); char * get_governance_config (struct kvp *config_vars); diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index 54882e4..9270a57 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -69,7 +69,7 @@ static const char *config = " file:" COMMON_ETC_PATH("default_permissions.p7s") "" " " " " - " " + " " " " " " ""; @@ -200,12 +200,12 @@ static void test_init(const struct domain_sec_config * domain_config, size_t n_s assert (n_pub_participants < MAX_PARTICIPANTS); struct kvp governance_vars[] = { - { "DISCOVERY_PROTECTION_KIND", pk_to_str (domain_config->discovery_pk) }, - { "LIVELINESS_PROTECTION_KIND", pk_to_str (domain_config->liveliness_pk) }, - { "RTPS_PROTECTION_KIND", pk_to_str (domain_config->rtps_pk) }, - { "METADATA_PROTECTION_KIND", pk_to_str (domain_config->metadata_pk) }, - { "DATA_PROTECTION_KIND", bpk_to_str (domain_config->payload_pk) }, - { NULL, NULL } + { "DISCOVERY_PROTECTION_KIND", pk_to_str (domain_config->discovery_pk), 1 }, + { "LIVELINESS_PROTECTION_KIND", pk_to_str (domain_config->liveliness_pk), 1 }, + { "RTPS_PROTECTION_KIND", pk_to_str (domain_config->rtps_pk), 1 }, + { "METADATA_PROTECTION_KIND", pk_to_str (domain_config->metadata_pk), 1 }, + { "DATA_PROTECTION_KIND", bpk_to_str (domain_config->payload_pk), 1 }, + { NULL, NULL, 0 } }; printf("Governance configuration: "); @@ -215,10 +215,8 @@ static void test_init(const struct domain_sec_config * domain_config, size_t n_s char * gov_config_signed = get_governance_config (governance_vars); struct kvp config_vars[] = { - { "GOVERNANCE_DATA", gov_config_signed }, - { "CRYPTO_INIT", "init_test_cryptography_wrapped" }, - { "CRYPTO_FINI", "finalize_test_cryptography_wrapped" }, - { NULL, NULL } + { "GOVERNANCE_DATA", gov_config_signed, 1 }, + { NULL, NULL, 0 } }; char *conf_pub = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars); @@ -454,7 +452,7 @@ CU_TheoryDataPoints(ddssec_secure_communication, multiple_readers) = { CU_DataPoints(size_t, 1, 3, 1, 3), /* number of participants per domain */ CU_DataPoints(size_t, 3, 1, 3, 3), /* number of readers per participant */ }; -CU_Theory((size_t n_dom, size_t n_pp, size_t n_rd), ddssec_secure_communication, multiple_readers, .timeout = 60) +CU_Theory((size_t n_dom, size_t n_pp, size_t n_rd), ddssec_secure_communication, multiple_readers, .timeout = 60, .disabled = true) { DDS_Security_ProtectionKind metadata_pk[] = { PK_N, PK_SOA, PK_EOA }; DDS_Security_BasicProtectionKind payload_pk[] = { BPK_N, BPK_S, BPK_E }; @@ -473,7 +471,7 @@ CU_TheoryDataPoints(ddssec_secure_communication, multiple_readers_writers) = { CU_DataPoints(size_t, 1, 1, 2), /* number of writer domains */ CU_DataPoints(size_t, 1, 3, 3), /* number of writers per domain */ }; -CU_Theory((size_t n_rd_dom, size_t n_rd, size_t n_wr_dom, size_t n_wr), ddssec_secure_communication, multiple_readers_writers, .timeout = 60) +CU_Theory((size_t n_rd_dom, size_t n_rd, size_t n_wr_dom, size_t n_wr), ddssec_secure_communication, multiple_readers_writers, .timeout = 60, .disabled = true) { DDS_Security_ProtectionKind metadata_pk[] = { PK_SOA, PK_EOA }; for (size_t metadata = 0; metadata < sizeof (metadata_pk) / sizeof (metadata_pk[0]); metadata++) From e7f5ae354c425199135deb71e5b9e2f129267378 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Wed, 4 Mar 2020 11:14:51 +0100 Subject: [PATCH 116/238] Fix security handshake test Isolate domains by using unique tags when running tests that are using security handshake. And updated coding style and some minor refactoring in fsm and timed_cb tests. Signed-off-by: Dennis Potman --- src/security/core/tests/CMakeLists.txt | 6 +- src/security/core/tests/authentication.c | 10 +- .../core/tests/common/config_env.h.in | 2 +- src/security/core/tests/dds_security_core.c | 546 ------------- src/security/core/tests/fsm.c | 581 ++++++++++++++ src/security/core/tests/handshake.c | 38 +- .../core/tests/secure_communication.c | 9 +- src/security/core/tests/tc_fsm.c | 757 ------------------ src/security/core/tests/timed_cb.c | 374 +++++++++ 9 files changed, 990 insertions(+), 1333 deletions(-) delete mode 100644 src/security/core/tests/dds_security_core.c create mode 100644 src/security/core/tests/fsm.c delete mode 100644 src/security/core/tests/tc_fsm.c create mode 100644 src/security/core/tests/timed_cb.c diff --git a/src/security/core/tests/CMakeLists.txt b/src/security/core/tests/CMakeLists.txt index af2b446..5618269 100644 --- a/src/security/core/tests/CMakeLists.txt +++ b/src/security/core/tests/CMakeLists.txt @@ -62,8 +62,8 @@ function(add_wrapper libname linklibs) endfunction() set(security_core_test_sources - "tc_fsm.c" - "dds_security_core.c" + "fsm.c" + "timed_cb.c" "security_utils.c" ) @@ -102,8 +102,6 @@ target_include_directories( set(common_etc_dir "${CMAKE_CURRENT_SOURCE_DIR}/common/etc") set(plugin_wrapper_lib_dir "${CMAKE_CURRENT_BINARY_DIR}") -file(TO_NATIVE_PATH "/" file_path_sep) -string(REPLACE "\\" "\\\\" file_path_sep ${file_path_sep}) configure_file("common/config_env.h.in" "common/config_env.h") target_link_libraries(cunit_security_core PRIVATE ddsc security_api SecurityCoreTests) diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index 1ed8ce6..2d13079 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -19,6 +19,7 @@ #include "dds/version.h" #include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/environ.h" +#include "dds/ddsrt/process.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsi/q_config.h" @@ -36,8 +37,11 @@ static const char *config = "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" - "0" "" + " " + " 0" + " \\${CYCLONEDDS_PID}" + " " " config" " " " " @@ -87,8 +91,8 @@ static void authentication_init(bool different_ca, const char * trusted_ca_dir, { NULL, NULL, 0 } }; - char *conf1 = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars1); - char *conf2 = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars2); + char *conf1 = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars1); + char *conf2 = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars2); CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars1), 0); CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars2), 0); g_domain1 = dds_create_domain (DDS_DOMAINID1, conf1); diff --git a/src/security/core/tests/common/config_env.h.in b/src/security/core/tests/common/config_env.h.in index a3773f1..d4811fc 100644 --- a/src/security/core/tests/common/config_env.h.in +++ b/src/security/core/tests/common/config_env.h.in @@ -12,7 +12,7 @@ #ifndef CONFIG_ENV_H #define CONFIG_ENV_H -#define FILE_PATH_SEP "@file_path_sep@" +#define FILE_PATH_SEP "/" #define COMMON_ETC_DIR "@common_etc_dir@" #define PLUGIN_WRAPPER_LIB_DIR "@plugin_wrapper_lib_dir@" #define PLUGIN_WRAPPER_LIB_PREFIX "@CMAKE_SHARED_LIBRARY_PREFIX@" diff --git a/src/security/core/tests/dds_security_core.c b/src/security/core/tests/dds_security_core.c deleted file mode 100644 index aef1e4f..0000000 --- a/src/security/core/tests/dds_security_core.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - * Copyright(c) 2019 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ - -#include -#include "CUnit/Test.h" - -#include "dds/security/core/dds_security_timed_cb.h" -#include "dds/ddsrt/misc.h" - -#define SEQ_SIZE (16) - -typedef struct { - struct dds_security_timed_dispatcher_t *d; - dds_security_timed_cb_kind kind; - void *listener; - void *arg; - dds_time_t time; -} tc__sequence_data; - -static int g_sequence_idx = 0; -static tc__sequence_data g_sequence_array[SEQ_SIZE]; - -static void simple_callback(struct dds_security_timed_dispatcher_t *d, - dds_security_timed_cb_kind kind, - void *listener, - void *arg) -{ - DDSRT_UNUSED_ARG(d); - DDSRT_UNUSED_ARG(kind); - DDSRT_UNUSED_ARG(listener); - - if (*((bool *)arg) == false) - { - *((bool *)arg) = true; - } - else - { - *((bool *)arg) = false; - } -} - -static int g_order_callback_idx = 0; -static void* g_order_callback[2] = {(void*)NULL, (void*)NULL}; -static void order_callback(struct dds_security_timed_dispatcher_t *d, - dds_security_timed_cb_kind kind, - void *listener, - void *arg) -{ - DDSRT_UNUSED_ARG(d); - DDSRT_UNUSED_ARG(kind); - DDSRT_UNUSED_ARG(listener); - - g_order_callback[g_order_callback_idx] = arg; - g_order_callback_idx++; -} - -static void -tc__callback( - struct dds_security_timed_dispatcher_t *d, - dds_security_timed_cb_kind kind, - void *listener, - void *arg) -{ - if (g_sequence_idx < SEQ_SIZE) { - g_sequence_array[g_sequence_idx].d = d; - g_sequence_array[g_sequence_idx].arg = arg; - g_sequence_array[g_sequence_idx].kind = kind; - g_sequence_array[g_sequence_idx].listener = listener; - g_sequence_array[g_sequence_idx].time = dds_time(); - } - g_sequence_idx++; -} - -CU_Test(dds_security_timed_cb, simple_test) -{ - struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); - struct dds_security_timed_dispatcher_t *d1 = NULL; - static bool test_var = false; - - dds_time_t now = dds_time(); - dds_time_t future = now + DDS_SECS(2); - - d1 = dds_security_timed_dispatcher_new(tcb); - - CU_ASSERT_PTR_NOT_NULL_FATAL(d1); - - dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void*)&test_var); - - dds_security_timed_dispatcher_enable(tcb, d1, (void*)NULL); - - CU_ASSERT_FALSE_FATAL(test_var); - - dds_sleepfor(DDS_MSECS(500)); - - CU_ASSERT_FALSE_FATAL(test_var); - - dds_sleepfor(DDS_SECS(2)); - - CU_ASSERT_TRUE_FATAL(test_var); - - dds_security_timed_dispatcher_free(tcb, d1); - - dds_security_timed_cb_free(tcb); -} - -CU_Test(dds_security_timed_cb, simple_order) -{ - struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); - struct dds_security_timed_dispatcher_t *d1 = NULL; - dds_time_t future; - dds_time_t future2; - - d1 = dds_security_timed_dispatcher_new(tcb); - CU_ASSERT_PTR_NOT_NULL_FATAL(d1); - future = dds_time() + DDS_MSECS(20); - future2 = future; - dds_security_timed_dispatcher_add(tcb, d1, order_callback, future, (void*)1); - dds_security_timed_dispatcher_add(tcb, d1, order_callback, future2, (void*)2); - dds_security_timed_dispatcher_enable(tcb, d1, (void*)&g_order_callback); - dds_sleepfor(DDS_MSECS(10)); - - dds_security_timed_dispatcher_free(tcb, d1); - - CU_ASSERT_EQUAL_FATAL(g_order_callback[0], (void*)1); - CU_ASSERT_EQUAL_FATAL(g_order_callback[1], (void*)2); - - dds_security_timed_cb_free(tcb); -} - -CU_Test(dds_security_timed_cb, test_enabled_and_disabled) -{ - struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); - struct dds_security_timed_dispatcher_t *d1 = NULL; - static bool test_var = false; - - dds_time_t now = dds_time(); - dds_time_t future = now + DDS_SECS(2); - - d1 = dds_security_timed_dispatcher_new(tcb); - - CU_ASSERT_PTR_NOT_NULL_FATAL(d1); - - dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void*)&test_var); - - dds_security_timed_dispatcher_enable(tcb, d1, (void*)NULL); - - CU_ASSERT_FALSE(test_var); - - dds_security_timed_dispatcher_disable(tcb, d1); - - dds_sleepfor(DDS_MSECS(500)); - - CU_ASSERT_FALSE(test_var); - - dds_sleepfor(DDS_SECS(2)); - - CU_ASSERT_FALSE(test_var); - - dds_security_timed_dispatcher_free(tcb, d1); - - dds_security_timed_cb_free(tcb); -} - -CU_Test(dds_security_timed_cb, simple_test_with_future) -{ - struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); - struct dds_security_timed_dispatcher_t *d1 = NULL; - static bool test_var = false; - - dds_time_t now = dds_time(); - dds_time_t future = now + DDS_SECS(2); - dds_time_t far_future = now + DDS_SECS(10); - - d1 = dds_security_timed_dispatcher_new(tcb); - - CU_ASSERT_PTR_NOT_NULL_FATAL(d1); - - dds_security_timed_dispatcher_enable(tcb, d1, (void*)NULL); - - dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void*)&test_var); - dds_security_timed_dispatcher_add(tcb, d1, simple_callback, far_future, (void*)&test_var); - - CU_ASSERT_FALSE_FATAL(test_var); - - dds_sleepfor(DDS_MSECS(500)); - - CU_ASSERT_FALSE_FATAL(test_var); - - dds_sleepfor(DDS_SECS(2)); - - CU_ASSERT_TRUE_FATAL(test_var); - - dds_security_timed_dispatcher_free(tcb, d1); - - dds_security_timed_cb_free(tcb); -} - -CU_Test(dds_security_timed_cb, test_multiple_dispatchers) -{ - struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); - struct dds_security_timed_dispatcher_t *d1 = NULL; - struct dds_security_timed_dispatcher_t *d2 = NULL; - static bool test_var = false; - - dds_time_t now = dds_time(); - dds_time_t future = now + DDS_SECS(2); - dds_time_t far_future = now + DDS_SECS(10); - - d1 = dds_security_timed_dispatcher_new(tcb); - d2 = dds_security_timed_dispatcher_new(tcb); - - CU_ASSERT_PTR_NOT_NULL_FATAL(d1); - - dds_security_timed_dispatcher_enable(tcb, d1, (void*)NULL); - dds_security_timed_dispatcher_enable(tcb, d2, (void*)NULL); - - dds_security_timed_dispatcher_free(tcb, d2); - - dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void*)&test_var); - dds_security_timed_dispatcher_add(tcb, d1, simple_callback, far_future, (void*)&test_var); - - CU_ASSERT_FALSE_FATAL(test_var); - - dds_sleepfor(DDS_MSECS(500)); - - CU_ASSERT_FALSE_FATAL(test_var); - - dds_sleepfor(DDS_SECS(2)); - - CU_ASSERT_TRUE_FATAL(test_var); - - dds_security_timed_dispatcher_free(tcb, d1); - - dds_security_timed_cb_free(tcb); -} - -CU_Test(dds_security_timed_cb, test_not_enabled_multiple_dispatchers) -{ - struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); - struct dds_security_timed_dispatcher_t *d1 = NULL; - struct dds_security_timed_dispatcher_t *d2 = NULL; - - d1 = dds_security_timed_dispatcher_new(tcb); - d2 = dds_security_timed_dispatcher_new(tcb); - - CU_ASSERT_PTR_NOT_NULL_FATAL(d1); - CU_ASSERT_PTR_NOT_NULL_FATAL(d2); - - dds_security_timed_dispatcher_free(tcb, d2); - - dds_security_timed_dispatcher_free(tcb, d1); - - dds_security_timed_cb_free(tcb); - - CU_PASS("Timed callbacks enabled and disabled without add"); -} - -CU_Test(dds_security_timed_cb, test_create_dispatcher) -{ - struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); - struct dds_security_timed_dispatcher_t *d1 = NULL; - struct dds_security_timed_dispatcher_t *d2 = NULL; - struct dds_security_timed_dispatcher_t *d3 = NULL; - struct dds_security_timed_dispatcher_t *d4 = NULL; - struct dds_security_timed_dispatcher_t *d5 = NULL; - bool ok = false; - - dds_time_t now = dds_time(); - dds_time_t past = now - DDS_SECS(1); - dds_time_t present = now + DDS_SECS(1); - dds_time_t future = present + DDS_SECS(1); - dds_time_t future2 = future + DDS_SECS(10); - - /************************************************************************* - * Check if dispatchers can be created - *************************************************************************/ - d1 = dds_security_timed_dispatcher_new(tcb); - d2 = dds_security_timed_dispatcher_new(tcb); - CU_ASSERT_PTR_NOT_NULL_FATAL(d1); - CU_ASSERT_PTR_NOT_NULL_FATAL(d2); - - /************************************************************************* - * Check if adding callbacks succeeds - *************************************************************************/ - - /* The last argument is a sequence number in which - * the callbacks are expected to be called. */ - /* We can only really check if it crashes or not... */ - dds_security_timed_dispatcher_add(tcb, d1, tc__callback, present, (void*)1); - dds_security_timed_dispatcher_add(tcb, d2, tc__callback, past, (void*)0); - dds_security_timed_dispatcher_add(tcb, d2, tc__callback, present, (void*)2); - dds_security_timed_dispatcher_add(tcb, d1, tc__callback, future, (void*)7); - - CU_PASS("Added callbacks") - - /************************************************************************* - * Check if dispatchers can be created - *************************************************************************/ - d3 = dds_security_timed_dispatcher_new(tcb); - d4 = dds_security_timed_dispatcher_new(tcb); - d5 = dds_security_timed_dispatcher_new(tcb); - - CU_ASSERT_PTR_NOT_NULL_FATAL(d3); - CU_ASSERT_PTR_NOT_NULL_FATAL(d4); - CU_ASSERT_PTR_NOT_NULL_FATAL(d5); - - - /************************************************************************* - * Check if enabling dispatchers succeeds - *************************************************************************/ - - /* The sleeps are added to get the timing between - * 'present' and 'past' callbacks right. */ - /* We can only really check if it crashes or not... */ - dds_sleepfor(DDS_MSECS(600)); - dds_security_timed_dispatcher_enable(tcb, d1, (void*)NULL); - dds_security_timed_dispatcher_enable(tcb, d2, (void*) d2); - dds_security_timed_dispatcher_enable(tcb, d3, (void*)NULL); - /* Specifically not enabling d4 and d5. */ - dds_sleepfor(DDS_MSECS(600)); - CU_PASS("Enabled dds_security_timed_dispatchers."); - - /************************************************************************* - * Check if adding callbacks succeeds - *************************************************************************/ - - /* The last argument is a sequence number in which - * the callbacks are expected to be called. */ - /* We can only really check if it crashes or not... */ - dds_security_timed_dispatcher_add(tcb, d4, tc__callback, past, (void*)99); - dds_security_timed_dispatcher_add(tcb, d2, tc__callback, future, (void*) 8); - dds_security_timed_dispatcher_add(tcb, d3, tc__callback, future2, (void*) 9); - dds_security_timed_dispatcher_add(tcb, d1, tc__callback, past, (void*) 3); - dds_security_timed_dispatcher_add(tcb, d1, tc__callback, future2, (void*)10); - dds_security_timed_dispatcher_add(tcb, d1, tc__callback, present, (void*) 4); - dds_security_timed_dispatcher_add(tcb, d2, tc__callback, present, (void*) 5); - dds_security_timed_dispatcher_add(tcb, d1, tc__callback, future, (void*) 6); - dds_security_timed_dispatcher_add(tcb, d3, tc__callback, future2, (void*)11); - CU_PASS("Added callbacks."); - - - /************************************************************************* - * Check if timeout callbacks are triggered in the right sequence - *************************************************************************/ - - int idx; - int timeout = 200; /* 2 seconds */ - - /* Wait for the callbacks to have been triggered. - * Ignore the ones in the far future. */ - while ((g_sequence_idx < 8) && (timeout > 0)) { - dds_sleepfor(DDS_MSECS(10)); - timeout--; - } - - /* Print and check sequence of triggered callbacks. */ - for (idx = 0; (idx < g_sequence_idx) && (idx < SEQ_SIZE); idx++) { - int seq = (int)(long long)(g_sequence_array[idx].arg); - struct dds_security_timed_dispatcher_t *expected_d; - void *expected_l; - - /* - * Sequence checks. - */ - if ((seq == 1) || (seq == 6) || (seq == 3) || (seq == 10) || (seq == 4) || (seq == 7)) { - expected_d = d1; - expected_l = NULL; - } else if ((seq == 0) || (seq == 2) || (seq == 8) || (seq == 5)) { - expected_d = d2; - expected_l = d2; - } else if (seq == 9) { - expected_d = d3; - expected_l = NULL; - } else if (seq == 99) { - expected_d = d4; - expected_l = NULL; - CU_FAIL("Unexpected callback on a disabled dispatcher"); - ok = false; - } else { - expected_d = NULL; - expected_l = NULL; - CU_FAIL(sprintf("Unknown sequence idx received %d", seq)); - ok = false; - } - - if (seq != idx) { - /* 6 and 7 order may be mixed since the order is not defined for same time stamp */ - if (!((seq == 6 && idx == 7) || (seq == 7 && idx == 6))) - { - printf("Unexpected sequence ordering %d vs %d\n", seq, idx); - CU_FAIL("Unexpected sequence ordering"); - ok = false; - } - } - if (seq > 8) { - CU_FAIL(sprintf("Unexpected sequence idx %d of the far future", seq)); - ok = false; - } - if (idx > 8) { - CU_FAIL(sprintf("Too many callbacks %d", idx)); - ok = false; - } - - /* - * Callback contents checks. - */ - if (expected_d != NULL) { - if (g_sequence_array[idx].d != expected_d) { - printf("Unexpected dispatcher %p vs %p\n", g_sequence_array[idx].d, expected_d); - CU_FAIL("Unexpected dispatcher"); - ok = false; - } - if (g_sequence_array[idx].listener != expected_l) { - CU_FAIL(sprintf("Unexpected listener %p vs %p", g_sequence_array[idx].listener, expected_l)); - ok = false; - } - } - - /* - * Callback kind check. - */ - if (g_sequence_array[idx].kind != DDS_SECURITY_TIMED_CB_KIND_TIMEOUT) { - CU_FAIL(sprintf("Unexpected kind %d vs %d", (int)g_sequence_array[idx].kind, (int)DDS_SECURITY_TIMED_CB_KIND_TIMEOUT)); - ok = false; - } - } - if (g_sequence_idx < 8) { - CU_FAIL(sprintf("Received %d callbacks, while 9 are expected", - g_sequence_idx + 1)); - ok = false; - } - if (ok) { - CU_FAIL(sprintf("Received timeout callbacks.")); - } - - /* Reset callback index to catch the deletion ones. */ - g_sequence_idx = 0; - - - /************************************************************************* - * Check if deleting succeeds with dispatchers in different states - *************************************************************************/ - /* We can only really check if it crashes or not... */ - if (d1) { - dds_security_timed_dispatcher_free(tcb, d1); - } - if (d2) { - dds_security_timed_dispatcher_free(tcb, d2); - } - if (d3) { - dds_security_timed_dispatcher_free(tcb, d3); - } - if (d4) { - dds_security_timed_dispatcher_free(tcb, d4); - } - if (d5) { - dds_security_timed_dispatcher_free(tcb, d5); - } - CU_PASS("Deleted dispatchers."); - - - /************************************************************************* - * Check if deletion callbacks are triggered - *************************************************************************/ - if (ok) { - timeout = 200; /* 2 seconds */ - - /* Wait for the callbacks to have been triggered. - * Ignore the ones in the far future. */ - while ((g_sequence_idx < 4) && (timeout > 0)) { - dds_sleepfor(DDS_MSECS(10)); - timeout--; - } - - /* Print and check sequence of triggered callbacks. */ - for (idx = 0; (idx < g_sequence_idx) && (idx < SEQ_SIZE); idx++) { - int seq = (int)(long long)(g_sequence_array[idx].arg); - struct dds_security_timed_dispatcher_t *expected_d; - - /* - * Human (somewhat) readable format. - */ - // tc__sequence_data_print(&(g_sequence_array[idx])); - - /* - * Sequence checks. - */ - if (seq == 99) { - expected_d = d4; - } else if ((seq == 9) || (seq == 11)) { - expected_d = d3; - } else if (seq == 10) { - expected_d = d1; - } else { - expected_d = NULL; - CU_FAIL(sprintf("Unexpected sequence idx received %d", seq)); - ok = false; - } - if (idx > 4) { - CU_FAIL(sprintf("Too many callbacks %d", idx)); - ok = false; - } - - /* - * Callback contents checks. - */ - if (expected_d != NULL) { - if (g_sequence_array[idx].d != expected_d) { - CU_FAIL(sprintf("Unexpected dispatcher %p vs %p", g_sequence_array[idx].d, expected_d)); - ok = false; - } - if (g_sequence_array[idx].listener != NULL) { - CU_FAIL(sprintf("Unexpected listener %p vs NULL", g_sequence_array[idx].listener)); - ok = false; - } - } - - /* - * Callback kind check. - */ - if (g_sequence_array[idx].kind != DDS_SECURITY_TIMED_CB_KIND_DELETE) { - CU_FAIL(sprintf("Unexpected kind %d vs %d", (int)g_sequence_array[idx].kind, (int)DDS_SECURITY_TIMED_CB_KIND_TIMEOUT)); - ok = false; - } - } - if (g_sequence_idx < 4) { - CU_FAIL(sprintf("Received %d callbacks, while 3 are expected", - g_sequence_idx + 1)); - ok = false; - } - if (ok) { - CU_PASS("Received deletion callbacks."); - } - } - - dds_security_timed_cb_free(tcb); -} diff --git a/src/security/core/tests/fsm.c b/src/security/core/tests/fsm.c new file mode 100644 index 0000000..e947dfe --- /dev/null +++ b/src/security/core/tests/fsm.c @@ -0,0 +1,581 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include "CUnit/CUnit.h" +#include "CUnit/Test.h" + +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/misc.h" +#include "dds/dds.h" +#include "dds__types.h" +#include "dds__entity.h" +#include "dds/security/core/dds_security_fsm.h" + +#define CHECK_BIT(var, pos) ((var) & (1<<(pos))) +#define FSM_AUTH_ARG 10 + +static dds_entity_t g_participant = 0; +static ddsrt_mutex_t g_lock; +static struct dds_security_fsm_control *g_fsm_control = NULL; + +#define DO_SIMPLE(name, var, bit) static void name(struct dds_security_fsm *fsm, void *arg) { \ + DDSRT_UNUSED_ARG(fsm); \ + DDSRT_UNUSED_ARG(arg); \ + printf("Transition %s\n", __FUNCTION__); \ + ddsrt_mutex_lock(&g_lock); \ + visited_##var |= 1u << (bit); \ + ddsrt_mutex_unlock(&g_lock); \ +} + +typedef enum { + VALIDATION_PENDING_RETRY, + VALIDATION_FAILED, + VALIDATION_OK, + VALIDATION_OK_FINAL_MESSAGE, + VALIDATION_PENDING_HANDSHAKE_MESSAGE, + VALIDATION_PENDING_HANDSHAKE_REQUEST, + plugin_ret_MAX +} plugin_ret; + +static struct dds_security_fsm *fsm_auth; +static uint32_t visited_auth = 0; +static uint32_t correct_fsm = 0; +static uint32_t correct_arg = 0; +static int validate_remote_identity_first = 1; +static int begin_handshake_reply_first = 1; + + +static plugin_ret validate_remote_identity(void) +{ + printf("validate_remote_identity - %d\n", validate_remote_identity_first); + if (validate_remote_identity_first) + { + validate_remote_identity_first = 0; + return VALIDATION_PENDING_RETRY; + } + return VALIDATION_PENDING_HANDSHAKE_MESSAGE; +} + +static plugin_ret begin_handshake_reply(void) +{ + printf("begin_handshake_reply - %d\n", begin_handshake_reply_first); + if (begin_handshake_reply_first) + { + begin_handshake_reply_first = 0; + return VALIDATION_PENDING_RETRY; + } + return VALIDATION_OK_FINAL_MESSAGE; +} + +static plugin_ret get_shared_secret(void) +{ + return VALIDATION_OK; +} + +/* State actions */ +static void fsm_validate_remote_identity(struct dds_security_fsm *fsm, void *arg) +{ + DDSRT_UNUSED_ARG(arg); + plugin_ret ret = validate_remote_identity(); + printf("[%p] State %s (ret %d)\n", fsm, __FUNCTION__, (int) ret); + dds_security_fsm_dispatch(fsm, (int32_t) ret, false); +} + +static void fsm_begin_handshake_reply(struct dds_security_fsm *fsm, void *arg) +{ + DDSRT_UNUSED_ARG(arg); + plugin_ret ret = begin_handshake_reply(); + if (ret == VALIDATION_OK_FINAL_MESSAGE) + ret = get_shared_secret(); + printf("[%p] State %s (ret %d)\n", fsm, __FUNCTION__, (int) ret); + dds_security_fsm_dispatch(fsm, (int32_t) ret, false); +} + +/* A few states from the handshake state-machine. */ +static dds_security_fsm_state StateValidateRemoteIdentity = {fsm_validate_remote_identity, 0}; +static dds_security_fsm_state StateValRemIdentityRetryWait = {NULL, 100000000}; +static dds_security_fsm_state StateHandshakeInitMessageWait = {NULL, 0}; +static dds_security_fsm_state state_beginHandshakeReply = {fsm_begin_handshake_reply, 0}; +static dds_security_fsm_state state_beginHsReplyWait = {NULL, 100000000}; + +static void a(struct dds_security_fsm *fsm, void *arg) +{ + printf("[%p] Transition %s\n", fsm, __FUNCTION__); + ddsrt_mutex_lock (&g_lock); + if (arg != NULL) + correct_arg = *((int *)arg) == FSM_AUTH_ARG ? 1 : 0; + correct_fsm = (fsm == fsm_auth) ? 1 : 0; + visited_auth |= 1u << 0; + ddsrt_mutex_unlock (&g_lock); +} + +DO_SIMPLE(b, auth, 1) +DO_SIMPLE(c, auth, 2) +DO_SIMPLE(d, auth, 3) +DO_SIMPLE(e, auth, 4) +DO_SIMPLE(f, auth, 5) +DO_SIMPLE(g, auth, 6) +DO_SIMPLE(h, auth, 7) + +#define SHM_MSG_RECEIVED (plugin_ret_MAX + 1) + +/* + * .--. + * |##|--------------------------------------. + * '--' a() v + * .----------------------------------------------------. + * | StateValidateRemoteIdentity | + * |----------------------------------------------------| + * .------>| fsm_validate_remote_identity() | + * | | - dispatch VALIDATION_PENDING_RETRY | + * 100ms| | - dispatch VALIDATION_PENDING_HANDSHAKE_MESSAGE | + * d() | '----------------------------------------------------' + * | VALIDATION_PENDING_RETRY| | VALIDATION_PENDING_HANDSHAKE_MESSAGE + * | b() | | c() + * | | | + * .------------------------------. | | .-------------------------------. + * | StateValRemIdentityRetryWait | | | | StateHandshakeInitMessageWait | + * |------------------------------|<----------' '------>|-------------------------------| + * '------------------------------' '-------------------------------' + * SHM_MSG_RECEIVED | + * e() | + * v + * .----------------------------------------. + * VALIDATION_PENDING_RETRY | state_beginHandshakeReply | + * f() |----------------------------------------| + * .-------------------------| fsm_begin_handshake_reply() | + * | | - dispatch VALIDATION_PENDING_RETRY | + * v | - dispatch VALIDATION_OK | + * .-----------------------. 100ms '----------------------------------------' + * | state_beginHsReplyWait | h() ^ VALIDATION_OK | + * |-----------------------|-----------------------' g() | + * '-----------------------' v + * .-. + * '-' + */ +static dds_security_fsm_transition HandshakeTransistions[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, a, &StateValidateRemoteIdentity}, // NULL state is the start state + {&StateValidateRemoteIdentity, VALIDATION_PENDING_RETRY, b, &StateValRemIdentityRetryWait}, + {&StateValidateRemoteIdentity, VALIDATION_PENDING_HANDSHAKE_MESSAGE, c, &StateHandshakeInitMessageWait}, + {&StateValRemIdentityRetryWait, DDS_SECURITY_FSM_EVENT_TIMEOUT, d, &StateValidateRemoteIdentity}, + {&StateHandshakeInitMessageWait, SHM_MSG_RECEIVED, e, &state_beginHandshakeReply}, + {&state_beginHandshakeReply, VALIDATION_PENDING_RETRY, f, &state_beginHsReplyWait}, + {&state_beginHandshakeReply, VALIDATION_OK, g, NULL}, // Reaching NULL means end of state-diagram + {&state_beginHsReplyWait, DDS_SECURITY_FSM_EVENT_TIMEOUT, h, &state_beginHandshakeReply} +}; +static const uint32_t HandshakeTransistionsSize = sizeof(HandshakeTransistions)/sizeof(HandshakeTransistions[0]); + + +/* Example State Machine properties and methods */ +typedef enum { + eventX, eventY, eventZ, +} test_events; + +static struct dds_security_fsm *fsm_test; +static uint32_t visited_test = 0; +static int do_stuff_counter = 0; +static int do_other_stuff_counter = 0; + +DO_SIMPLE(do_start, test, 0) +DO_SIMPLE(do_restart, test, 1) +DO_SIMPLE(do_event_stuff, test, 4) + +static void do_stuff(struct dds_security_fsm *fsm, void *arg) +{ + DDSRT_UNUSED_ARG(fsm); + DDSRT_UNUSED_ARG(arg); + printf("Transition %s - %d\n", __FUNCTION__, do_stuff_counter); + ddsrt_mutex_lock (&g_lock); + visited_test |= 1u << 2; + ddsrt_mutex_unlock (&g_lock); + if (do_stuff_counter < 2) + dds_security_fsm_dispatch(fsm, eventZ, false); + else if (do_stuff_counter == 2) + dds_security_fsm_dispatch(fsm, eventY, false); + ++do_stuff_counter; +} + +static void do_other_stuff(struct dds_security_fsm *fsm, void *arg) +{ + DDSRT_UNUSED_ARG(fsm); + DDSRT_UNUSED_ARG(arg); + printf("Transition %s - %d\n", __FUNCTION__, do_other_stuff_counter); + ddsrt_mutex_lock (&g_lock); + visited_test |= 1u << 3; + ddsrt_mutex_unlock (&g_lock); + if (do_other_stuff_counter == 0) + dds_security_fsm_dispatch(fsm, DDS_SECURITY_FSM_EVENT_AUTO, false); + else if (do_other_stuff_counter == 1) + dds_security_fsm_dispatch(fsm, eventY, false); + else if (do_other_stuff_counter == 2) + dds_security_fsm_dispatch(fsm, eventX, false); + ++do_other_stuff_counter; +} + +static dds_security_fsm_state state_a = {do_stuff, 0}; +static dds_security_fsm_state state_b = {do_stuff, 100000000}; +static dds_security_fsm_state state_c = {NULL, 0}; +static dds_security_fsm_state state_d = {do_other_stuff, 0}; + +static dds_security_fsm_transition Transitions[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, do_start, &state_a}, // NULL state is the start state + {&state_a, eventZ, NULL, &state_b}, + {&state_a, eventY, do_other_stuff, &state_c}, + {&state_b, eventX, NULL, NULL}, // Reaching NULL means end of state-diagram + {&state_b, eventZ, do_restart, &state_a}, + {&state_c, DDS_SECURITY_FSM_EVENT_AUTO, do_event_stuff, &state_d}, + {&state_d, eventY, do_event_stuff, &state_d}, + {&state_d, eventX, do_stuff, NULL}, // Reaching NULL means end of sttimeoutate-diagram +}; +static const uint32_t TransitionsSize = sizeof(Transitions)/sizeof(Transitions[0]); + + +/* Timeout State Machine properties and methods */ +typedef enum { + event_to_timeout, event_to_interrupt, event_to_end, +} timeout_events; + +struct fsm_timeout_arg { + int id; +}; + +static struct dds_security_fsm *fsm_timeout; +static uint32_t visited_timeout = 0; +static uint32_t correct_fsm_timeout = 0; +static uint32_t correct_arg_timeout = 0; +static struct fsm_timeout_arg fsm_arg = { .id = FSM_AUTH_ARG }; + +DO_SIMPLE(do_interrupt, timeout, 0) +DO_SIMPLE(timeout_cb2, timeout, 3) + +static void do_timeout(struct dds_security_fsm *fsm, void *arg) +{ + DDSRT_UNUSED_ARG(arg); + printf("Transition >>>> %s\n", __FUNCTION__); + ddsrt_mutex_lock (&g_lock); + visited_timeout |= 1u << 1; + ddsrt_mutex_unlock (&g_lock); + printf("Transition <<<< %s\n", __FUNCTION__); + dds_security_fsm_dispatch(fsm, event_to_timeout, false); +} + +static void timeout_cb(struct dds_security_fsm *fsm, void *arg) +{ + struct fsm_timeout_arg *farg = arg; + printf("timeout_cb\n"); + ddsrt_mutex_lock (&g_lock); + visited_timeout |= 1u << 2; + if (farg != NULL) + correct_arg_timeout = farg->id == FSM_AUTH_ARG ? 1 : 0; + correct_fsm_timeout = fsm == fsm_timeout ? 1 : 0; + ddsrt_mutex_unlock (&g_lock); +} + +static dds_security_fsm_state state_initial = {do_timeout, 0}; +static dds_security_fsm_state state_wait_timeout = {NULL, DDS_SECS(4)}; +static dds_security_fsm_state state_interrupt = {do_interrupt, 0}; + +static const dds_security_fsm_transition timeout_transitions[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &state_initial}, // NULL state is the start state + {&state_initial, event_to_timeout, NULL, &state_wait_timeout}, + {&state_wait_timeout, DDS_SECURITY_FSM_EVENT_TIMEOUT, NULL, &state_interrupt}, + {&state_wait_timeout, event_to_interrupt, NULL, &state_interrupt}, + {&state_interrupt, event_to_end, NULL, NULL}, // Reaching NULL means end of state-diagram +}; +static const uint32_t timeout_transitionsSize = sizeof(timeout_transitions)/sizeof(timeout_transitions[0]); + +/* Parallel Timeout State Machines properties and methods */ +static struct dds_security_fsm *fsm_timeout1; +static struct dds_security_fsm *fsm_timeout2; +static struct dds_security_fsm *fsm_timeout3; + +static dds_time_t time0 = 0; +static dds_time_t time1 = 0; +static dds_time_t time2 = 0; +static dds_time_t time3 = 0; + +static void state_par_time1(struct dds_security_fsm *fsm, void *arg) +{ + DDSRT_UNUSED_ARG(fsm); + DDSRT_UNUSED_ARG(arg); + time1 = dds_time(); +} + +static void state_par_time2(struct dds_security_fsm *fsm, void *arg) +{ + DDSRT_UNUSED_ARG(fsm); + DDSRT_UNUSED_ARG(arg); + time2 = dds_time(); +} + +static void state_par_time3(struct dds_security_fsm *fsm, void *arg) +{ + DDSRT_UNUSED_ARG(fsm); + DDSRT_UNUSED_ARG(arg); + time3 = dds_time(); +} + +static dds_security_fsm_state state_par_timeout1 = {NULL, DDS_SECS(1)}; +static dds_security_fsm_state state_par_timeout2 = {NULL, DDS_SECS(2)}; +static dds_security_fsm_state state_par_timeout3 = {NULL, DDS_SECS(1)}; + +static dds_security_fsm_transition parallel_timeout_transitions_1[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &state_par_timeout1}, // NULL state is the startfsm_control_thread state + {&state_par_timeout1, DDS_SECURITY_FSM_EVENT_TIMEOUT, &state_par_time1, NULL}, // Reaching NULL means end of state-diagram +}; +static const uint32_t parallel_timeout_transitionsSize_1 = sizeof(parallel_timeout_transitions_1) / sizeof(parallel_timeout_transitions_1[0]); + +static dds_security_fsm_transition parallel_timeout_transitions_2[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &state_par_timeout2}, // NULL state is the start state + {&state_par_timeout2, DDS_SECURITY_FSM_EVENT_TIMEOUT, &state_par_time2, NULL}, // Reaching NULL means end of state-diagram +}; +static const uint32_t parallel_timeout_transitionsSize_2 = sizeof(parallel_timeout_transitions_2) / sizeof(parallel_timeout_transitions_2[0]); + +static dds_security_fsm_transition parallel_timeout_transitions_3[] = { + {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &state_par_timeout3}, // NULL state is the start state + {&state_par_timeout3, DDS_SECURITY_FSM_EVENT_TIMEOUT, &state_par_time3, NULL}, // Reaching NULL means end of state-diagram +}; +static const uint32_t parallel_timeout_transitionsSize_3 = sizeof(parallel_timeout_transitions_3) / sizeof(parallel_timeout_transitions_3[0]); + +static void fsm_control_init(void) +{ + struct dds_entity *e; + g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); + CU_ASSERT_FATAL(g_participant > 0); + ddsrt_mutex_init(&g_lock); + dds_return_t rc = dds_entity_pin(g_participant, &e); + CU_ASSERT_FATAL(rc == 0); + g_fsm_control = dds_security_fsm_control_create(&e->m_domain->gv); + CU_ASSERT_FATAL(g_fsm_control != NULL); + dds_entity_unpin(e); + rc = dds_security_fsm_control_start(g_fsm_control, NULL); + CU_ASSERT_EQUAL_FATAL(rc, 0); +} + +static void fsm_control_fini(void) +{ + dds_security_fsm_control_stop(g_fsm_control); + dds_security_fsm_control_free(g_fsm_control); + ddsrt_mutex_destroy (&g_lock); + dds_delete(g_participant); +} + +CU_Test(ddssec_fsm, create, .init = fsm_control_init, .fini = fsm_control_fini) +{ + /* Test single running state machine. Check creation of a single State Machine */ + fsm_auth = dds_security_fsm_create(g_fsm_control, HandshakeTransistions, HandshakeTransistionsSize, &fsm_arg); + CU_ASSERT_FATAL(fsm_auth != NULL) + + /* set a delay that doesn't expire. Should be terminate when fsm is freed. */ + dds_security_fsm_set_timeout(fsm_auth, timeout_cb, DDS_SECS(30)); + dds_security_fsm_start(fsm_auth); + + int n = 100; + while (dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait && n-- > 0) + dds_sleepfor(DDS_MSECS(100)); + CU_ASSERT(n > 0); + dds_security_fsm_dispatch(fsm_auth, SHM_MSG_RECEIVED, false); + + n = 100; + while (dds_security_fsm_current_state(fsm_auth) != NULL && n-- > 0) + dds_sleepfor(DDS_MSECS(100)); + CU_ASSERT(n > 0); + + ddsrt_mutex_lock (&g_lock); + CU_ASSERT(visited_auth == 0xff); + ddsrt_mutex_unlock (&g_lock); + + /* Check correct callback parameter passing (from fsm to user defined methods) */ + CU_ASSERT(correct_arg && correct_fsm); + dds_security_fsm_free(fsm_auth); + + /* Check whether timeout callback has NOT been invoked */ + ddsrt_mutex_lock (&g_lock); + CU_ASSERT(visited_timeout == 0); + ddsrt_mutex_unlock (&g_lock); +} + +/* Test multiple (2) running state machines */ +CU_Test(ddssec_fsm, multiple, .init = fsm_control_init, .fini = fsm_control_fini) +{ + validate_remote_identity_first = 0; + begin_handshake_reply_first = 0; + visited_auth = 0; + visited_test = 0; + + fsm_auth = dds_security_fsm_create(g_fsm_control, HandshakeTransistions, HandshakeTransistionsSize, NULL); + CU_ASSERT_FATAL(fsm_auth != NULL); + + fsm_test = dds_security_fsm_create(g_fsm_control, Transitions, TransitionsSize, NULL); + CU_ASSERT_FATAL(fsm_test != NULL); + + dds_security_fsm_start(fsm_auth); + dds_security_fsm_start(fsm_test); + + /* Check the results of multiple running State Machines */ + int n = 100; /* 10 sec */ + while (dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait && n-- > 0) + dds_sleepfor(DDS_MSECS(100)); + CU_ASSERT_FATAL(n > 0); + + n = 100; /* 10 sec */ + dds_security_fsm_dispatch(fsm_auth, SHM_MSG_RECEIVED, false); + while (dds_security_fsm_current_state(fsm_auth) != NULL && n-- > 0) + dds_sleepfor(DDS_MSECS(100)); + CU_ASSERT_FATAL(n > 0); + + // not all bits are set since we're running the state machine a second time + ddsrt_mutex_lock (&g_lock); + CU_ASSERT_FATAL(visited_auth == 0x55); + ddsrt_mutex_unlock (&g_lock); + + /* Wait for the last state to occur */ + n = 100; /* 10 sec */ + while (dds_security_fsm_current_state(fsm_test) != NULL && n-- > 0) + dds_sleepfor(DDS_MSECS(100)); + CU_ASSERT_FATAL(n > 0); + + ddsrt_mutex_lock (&g_lock); + CU_ASSERT(visited_test == 0x1f); + ddsrt_mutex_unlock (&g_lock); + + dds_security_fsm_free(fsm_auth); + dds_security_fsm_free(fsm_test); + +} + +/** + * Check creation of State Machine for timeout purposes + */ +CU_Test(ddssec_fsm, timeout, .init = fsm_control_init, .fini = fsm_control_fini) +{ + visited_timeout = 0; + /* Test timeout monitoring of state machines */ + fsm_timeout = dds_security_fsm_create(g_fsm_control, timeout_transitions, timeout_transitionsSize, &fsm_arg); + CU_ASSERT(fsm_timeout != NULL); + dds_security_fsm_set_timeout(fsm_timeout, timeout_cb, DDS_SECS(1)); + dds_security_fsm_start(fsm_timeout); + + int n = 100; /* 10 sec */ + ddsrt_mutex_lock (&g_lock); + while (visited_timeout != 0x7 && n-- > 0) + { + ddsrt_mutex_unlock (&g_lock); + dds_sleepfor(DDS_MSECS(100)); + ddsrt_mutex_lock (&g_lock); + } + CU_ASSERT(n > 0); + CU_ASSERT(visited_timeout == 0x7); + CU_ASSERT(correct_arg_timeout && correct_fsm_timeout); + ddsrt_mutex_unlock (&g_lock); + dds_security_fsm_free(fsm_timeout); +} + +/* Check the double global timeout */ +CU_Test(ddssec_fsm, double_timeout, .init = fsm_control_init, .fini = fsm_control_fini) +{ + visited_timeout = 0; + fsm_timeout = dds_security_fsm_create(g_fsm_control, timeout_transitions, timeout_transitionsSize, &fsm_arg); + CU_ASSERT(fsm_timeout != NULL); + + fsm_timeout2 = dds_security_fsm_create(g_fsm_control, timeout_transitions, timeout_transitionsSize, &fsm_arg); + CU_ASSERT(fsm_timeout2 != NULL); + + dds_security_fsm_set_timeout(fsm_timeout, timeout_cb, DDS_SECS(1)); + dds_security_fsm_set_timeout(fsm_timeout2, timeout_cb2, DDS_SECS(2)); + dds_security_fsm_start(fsm_timeout); + dds_security_fsm_start(fsm_timeout2); + int n = 100; + ddsrt_mutex_lock (&g_lock); + while (visited_timeout != 0xf && n-- > 0) + { + ddsrt_mutex_unlock (&g_lock); + dds_sleepfor(DDS_MSECS(100)); + ddsrt_mutex_lock (&g_lock); + } + CU_ASSERT(visited_timeout == 0xf); + ddsrt_mutex_unlock (&g_lock); + dds_security_fsm_free(fsm_timeout); + dds_security_fsm_free(fsm_timeout2); +} + +/* Check parallel state timeouts */ +CU_Test(ddssec_fsm, parallel_timeout, .init = fsm_control_init, .fini = fsm_control_fini) +{ + visited_timeout = 0; + + fsm_timeout1 = dds_security_fsm_create(g_fsm_control, parallel_timeout_transitions_1, parallel_timeout_transitionsSize_1, &fsm_arg); + CU_ASSERT_FATAL(fsm_timeout1 != NULL); + fsm_timeout2 = dds_security_fsm_create(g_fsm_control, parallel_timeout_transitions_2, parallel_timeout_transitionsSize_2, &fsm_arg); + CU_ASSERT_FATAL(fsm_timeout2 != NULL); + fsm_timeout3 = dds_security_fsm_create(g_fsm_control, parallel_timeout_transitions_3, parallel_timeout_transitionsSize_3, &fsm_arg); + CU_ASSERT_FATAL(fsm_timeout3 != NULL); + + time0 = dds_time(); + dds_security_fsm_start(fsm_timeout1); + dds_security_fsm_start(fsm_timeout2); + dds_security_fsm_start(fsm_timeout3); + + int n = 300; + while (((dds_security_fsm_current_state(fsm_timeout1) == NULL) + || (dds_security_fsm_current_state(fsm_timeout2) == NULL) + || (dds_security_fsm_current_state(fsm_timeout3) == NULL)) && n-- > 0) + { + dds_sleepfor(DDS_MSECS(100)); + } + while (((dds_security_fsm_current_state(fsm_timeout1) != NULL) + || (dds_security_fsm_current_state(fsm_timeout2) != NULL) + || (dds_security_fsm_current_state(fsm_timeout3) != NULL)) && n-- > 0) + { + dds_sleepfor(DDS_MSECS(100)); + } + + dds_duration_t delta1 = time1 - time0; + dds_duration_t delta2 = time2 - time0; + dds_duration_t delta3 = time3 - time0; + printf("time0 %"PRId64"\n", time0); + printf("time1 %"PRId64", delta1 %"PRId64"\n", time1, delta1); + printf("time2 %"PRId64", delta2 %"PRId64"\n", time2, delta2); + printf("time3 %"PRId64", delta3 %"PRId64"\n", time3, delta3); + CU_ASSERT(delta1 > DDS_MSECS(750)); + CU_ASSERT(delta1 < DDS_MSECS(1250)); + CU_ASSERT(delta2 > DDS_MSECS(1750)); + CU_ASSERT(delta2 < DDS_MSECS(2250)); + CU_ASSERT(delta3 > DDS_MSECS(750)); + CU_ASSERT(delta3 < DDS_MSECS(1250)); + + dds_security_fsm_free(fsm_timeout1); + dds_security_fsm_free(fsm_timeout2); + dds_security_fsm_free(fsm_timeout3); +} + +/* Delete with event timeout */ +CU_Test(ddssec_fsm, delete_with_timeout, .init = fsm_control_init, .fini = fsm_control_fini) +{ + fsm_timeout = dds_security_fsm_create(g_fsm_control, timeout_transitions, timeout_transitionsSize, &fsm_arg); + CU_ASSERT (fsm_timeout != NULL) + visited_timeout = 0; + dds_security_fsm_start(fsm_timeout); + + int n = 100; + ddsrt_mutex_lock (&g_lock); + while (visited_timeout == 0 && n-- > 0) + { + ddsrt_mutex_unlock (&g_lock); + dds_sleepfor(DDS_MSECS(100)); + ddsrt_mutex_lock (&g_lock); + } + ddsrt_mutex_unlock (&g_lock); + dds_security_fsm_free(fsm_timeout); +} + diff --git a/src/security/core/tests/handshake.c b/src/security/core/tests/handshake.c index 2eb52fc..0408bb9 100644 --- a/src/security/core/tests/handshake.c +++ b/src/security/core/tests/handshake.c @@ -35,9 +35,12 @@ static const char *config = "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" - "0" "" - " finest" + " " + " 0" + " \\${CYCLONEDDS_PID}" + " " + " config" " " " " " " @@ -68,30 +71,27 @@ static dds_entity_t g_part2_participant = 0; static void handshake_init(void) { - /* Domains for pub and sub use a different domain id, but the portgain setting - * in configuration is 0, so that both domains will map to the same port number. - * This allows to create two domains in a single test process. */ - char *conf_part1 = ddsrt_expand_envvars(config, DDS_DOMAINID_PART1); - char *conf_part2 = ddsrt_expand_envvars(config, DDS_DOMAINID_PART2); - g_part1_domain = dds_create_domain(DDS_DOMAINID_PART1, conf_part1); - g_part2_domain = dds_create_domain(DDS_DOMAINID_PART2, conf_part2); - dds_free(conf_part1); - dds_free(conf_part2); + char *conf_part1 = ddsrt_expand_envvars_sh (config, DDS_DOMAINID_PART1); + char *conf_part2 = ddsrt_expand_envvars_sh (config, DDS_DOMAINID_PART2); + g_part1_domain = dds_create_domain (DDS_DOMAINID_PART1, conf_part1); + g_part2_domain = dds_create_domain (DDS_DOMAINID_PART2, conf_part2); + dds_free (conf_part1); + dds_free (conf_part2); - CU_ASSERT_FATAL((g_part1_participant = dds_create_participant(DDS_DOMAINID_PART1, NULL, NULL)) > 0); - CU_ASSERT_FATAL((g_part2_participant = dds_create_participant(DDS_DOMAINID_PART2, NULL, NULL)) > 0); + CU_ASSERT_FATAL ((g_part1_participant = dds_create_participant (DDS_DOMAINID_PART1, NULL, NULL)) > 0); + CU_ASSERT_FATAL ((g_part2_participant = dds_create_participant (DDS_DOMAINID_PART2, NULL, NULL)) > 0); } static void handshake_fini(void) { - CU_ASSERT_EQUAL_FATAL(dds_delete(g_part1_participant), DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(dds_delete(g_part2_participant), DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(dds_delete(g_part1_domain), DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(dds_delete(g_part2_domain), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL (dds_delete (g_part1_participant), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL (dds_delete (g_part2_participant), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL (dds_delete (g_part1_domain), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL (dds_delete (g_part2_domain), DDS_RETCODE_OK); } CU_Test(ddssec_handshake, happy_day, .init = handshake_init, .fini = handshake_fini) { - validate_handshake(DDS_DOMAINID_PART1, false, NULL, false, NULL); - validate_handshake(DDS_DOMAINID_PART2, false, NULL, false, NULL); + validate_handshake (DDS_DOMAINID_PART1, false, NULL, false, NULL); + validate_handshake (DDS_DOMAINID_PART2, false, NULL, false, NULL); } diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index 9270a57..978aa62 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -51,8 +51,11 @@ static const char *config = "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" - "0" "" + " " + " 0" + " \\${CYCLONEDDS_PID}" + " " " " " " " " @@ -219,12 +222,12 @@ static void test_init(const struct domain_sec_config * domain_config, size_t n_s { NULL, NULL, 0 } }; - char *conf_pub = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars); + char *conf_pub = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars); create_dom_pp_pubsub (DDS_DOMAINID_PUB, conf_pub, domain_config, n_pub_domains, n_pub_participants, g_pub_domains, g_pub_participants, g_pub_publishers, &dds_create_publisher); dds_free (conf_pub); - char *conf_sub = ddsrt_expand_vars (config, &expand_lookup_vars_env, config_vars); + char *conf_sub = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars); create_dom_pp_pubsub (DDS_DOMAINID_SUB, conf_sub, domain_config, n_sub_domains, n_sub_participants, g_sub_domains, g_sub_participants, g_sub_subscribers, &dds_create_subscriber); dds_free (conf_sub); diff --git a/src/security/core/tests/tc_fsm.c b/src/security/core/tests/tc_fsm.c deleted file mode 100644 index 666a641..0000000 --- a/src/security/core/tests/tc_fsm.c +++ /dev/null @@ -1,757 +0,0 @@ -/* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License - * v. 1.0 which is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause - */ -#include -#include - -#include "dds/ddsrt/sync.h" -#include "dds/ddsrt/misc.h" - -#include "CUnit/CUnit.h" -#include "CUnit/Test.h" -#include "dds/dds.h" -#include "dds__types.h" -#include "dds__entity.h" -#include "dds/security/core/dds_security_fsm.h" - -#define CHECK_BIT(var, pos) ((var) & (1<<(pos))) - -#define FSM_AUTH_ARG 10 - -#define DB_TC_PRINT_DEBUG (true) - -static dds_entity_t g_participant = 0; -static ddsrt_mutex_t g_lock; -static struct dds_security_fsm_control *g_fsm_control = NULL; -static const dds_duration_t msec100 = DDS_MSECS(100); - -//static int fsm_arg = FSM_AUTH_ARG; - -#define DO_SIMPLE(name, var, bit) static void name(struct dds_security_fsm *fsm, void *arg) { \ - DDSRT_UNUSED_ARG(fsm); \ - DDSRT_UNUSED_ARG(arg); \ - if (DB_TC_PRINT_DEBUG) \ - printf("Transition %s\n", __FUNCTION__); \ - ddsrt_mutex_lock(&g_lock); \ - visited_##var |= 1u << (bit); \ - ddsrt_mutex_unlock(&g_lock); \ -} - - -/********************************************************************** - * Authentication State Machine properties and methods - **********************************************************************/ - -typedef enum { - VALIDATION_PENDING_RETRY, - VALIDATION_FAILED, - VALIDATION_OK, - VALIDATION_OK_FINAL_MESSAGE, - VALIDATION_PENDING_HANDSHAKE_MESSAGE, - VALIDATION_PENDING_HANDSHAKE_REQUEST, - PluginReturn_MAX -} PluginReturn; - -static struct dds_security_fsm *fsm_auth; -static uint32_t visited_auth = 0; -static uint32_t correct_fsm = 0; -static uint32_t correct_arg = 0; -static int validate_remote_identity_first = 1; -static int begin_handshake_reply_first = 1; - - -static PluginReturn validate_remote_identity(void) -{ - if (DB_TC_PRINT_DEBUG) { - printf("validate_remote_identity - %d\n", validate_remote_identity_first); - } - if (validate_remote_identity_first) { - validate_remote_identity_first = 0; - return VALIDATION_PENDING_RETRY; - } - return VALIDATION_PENDING_HANDSHAKE_MESSAGE; -} - -static PluginReturn begin_handshake_reply(void) -{ - if (DB_TC_PRINT_DEBUG) { - printf("begin_handshake_reply - %d\n", begin_handshake_reply_first); - } - if (begin_handshake_reply_first) { - begin_handshake_reply_first = 0; - return VALIDATION_PENDING_RETRY; - } - return VALIDATION_OK_FINAL_MESSAGE; -} - -static PluginReturn get_shared_secret(void) -{ - return VALIDATION_OK; -} - -/* State actions. */ -static void fsm_validate_remote_identity(struct dds_security_fsm *fsm, void *arg) -{ - PluginReturn ret; - - DDSRT_UNUSED_ARG(arg); - - ret = validate_remote_identity(); - - if (DB_TC_PRINT_DEBUG) { - printf("[%p] State %s (ret %d)\n", fsm, __FUNCTION__, (int) ret); - } - - dds_security_fsm_dispatch(fsm, (int32_t) ret, false); -} - -static void fsm_begin_handshake_reply(struct dds_security_fsm *fsm, void *arg) -{ - PluginReturn ret; - - DDSRT_UNUSED_ARG(arg); - - ret = begin_handshake_reply(); - if (ret == VALIDATION_OK_FINAL_MESSAGE) { - ret = get_shared_secret(); - } - - if (DB_TC_PRINT_DEBUG) { - printf("[%p] State %s (ret %d)\n", fsm, __FUNCTION__, (int) ret); - } - - dds_security_fsm_dispatch(fsm, (int32_t) ret, false); -} - -/* A few states from the handshake state-machine. */ -static dds_security_fsm_state StateValidateRemoteIdentity = {fsm_validate_remote_identity, 0}; -static dds_security_fsm_state StateValRemIdentityRetryWait = {NULL, 100000000}; -static dds_security_fsm_state StateHandshakeInitMessageWait = {NULL, 0}; -static dds_security_fsm_state StateBeginHandshakeReply = {fsm_begin_handshake_reply, 0}; -static dds_security_fsm_state StateBeginHsReplyWait = {NULL, 100000000}; - -static void a(struct dds_security_fsm *fsm, void *arg) -{ - int *fsm_arg; - - if (DB_TC_PRINT_DEBUG) { - printf("[%p] Transition %s\n", fsm, __FUNCTION__); - } - - ddsrt_mutex_lock (&g_lock); - if (arg != NULL) { - fsm_arg = (int *) arg; - - if (*fsm_arg == FSM_AUTH_ARG) { - correct_arg = 1; - } else { - correct_arg = 0; - } - } - - if (fsm == fsm_auth) { - correct_fsm = 1; - } else { - correct_fsm = 0; - } - visited_auth |= 1u << 0; - ddsrt_mutex_unlock (&g_lock); -} - -DO_SIMPLE(b, auth, 1) -DO_SIMPLE(c, auth, 2) -DO_SIMPLE(d, auth, 3) -DO_SIMPLE(e, auth, 4) -DO_SIMPLE(f, auth, 5) -DO_SIMPLE(g, auth, 6) -DO_SIMPLE(h, auth, 7) - -#define SHM_MSG_RECEIVED (PluginReturn_MAX + 1) - -/* - * .--. - * |##|--------------------------------------. - * '--' a() v - * .----------------------------------------------------. - * | StateValidateRemoteIdentity | - * |----------------------------------------------------| - * .------>| fsm_validate_remote_identity() | - * | | - dispatch VALIDATION_PENDING_RETRY | - * 100ms| | - dispatch VALIDATION_PENDING_HANDSHAKE_MESSAGE | - * d() | '----------------------------------------------------' - * | VALIDATION_PENDING_RETRY| | VALIDATION_PENDING_HANDSHAKE_MESSAGE - * | b() | | c() - * | | | - * .------------------------------. | | .-------------------------------. - * | StateValRemIdentityRetryWait | | | | StateHandshakeInitMessageWait | - * |------------------------------|<----------' '------>|-------------------------------| - * '------------------------------' '-------------------------------' - * SHM_MSG_RECEIVED | - * e() | - * v - * .----------------------------------------. - * VALIDATION_PENDING_RETRY | StateBeginHandshakeReply | - * f() |----------------------------------------| - * .-------------------------| fsm_begin_handshake_reply() | - * | | - dispatch VALIDATION_PENDING_RETRY | - * v | - dispatch VALIDATION_OK | - * .-----------------------. 100ms '----------------------------------------' - * | StateBeginHsReplyWait | h() ^ VALIDATION_OK | - * |-----------------------|-----------------------' g() | - * '-----------------------' v - * .-. - * '-' - */ -static dds_security_fsm_transition HandshakeTransistions[] = { - {NULL, DDS_SECURITY_FSM_EVENT_AUTO, a, &StateValidateRemoteIdentity}, // NULL state is the start state - {&StateValidateRemoteIdentity, VALIDATION_PENDING_RETRY, b, &StateValRemIdentityRetryWait}, - {&StateValidateRemoteIdentity, VALIDATION_PENDING_HANDSHAKE_MESSAGE, c, &StateHandshakeInitMessageWait}, - {&StateValRemIdentityRetryWait, DDS_SECURITY_FSM_EVENT_TIMEOUT, d, &StateValidateRemoteIdentity}, - {&StateHandshakeInitMessageWait, SHM_MSG_RECEIVED, e, &StateBeginHandshakeReply}, - {&StateBeginHandshakeReply, VALIDATION_PENDING_RETRY, f, &StateBeginHsReplyWait}, - {&StateBeginHandshakeReply, VALIDATION_OK, g, NULL}, // Reaching NULL means end of state-diagram - {&StateBeginHsReplyWait, DDS_SECURITY_FSM_EVENT_TIMEOUT, h, &StateBeginHandshakeReply} -}; -static const uint32_t HandshakeTransistionsSize = sizeof(HandshakeTransistions)/sizeof(HandshakeTransistions[0]); - - -/********************************************************************** - * Example State Machine properties and methods - **********************************************************************/ - -typedef enum { - eventX, eventY, eventZ, -} test_events; - -static struct dds_security_fsm *fsm_test; -static uint32_t visited_test = 0; -static int do_stuff_counter = 0; -static int do_other_stuff_counter = 0; - -DO_SIMPLE(doStart, test, 0) -DO_SIMPLE(doRestart, test, 1) -DO_SIMPLE(doEventStuff, test, 4) - -static void doStuff(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - - if (DB_TC_PRINT_DEBUG) { - printf("Transition %s - %d\n", __FUNCTION__, do_stuff_counter); - } - ddsrt_mutex_lock (&g_lock); - visited_test |= 1u << 2; - ddsrt_mutex_unlock (&g_lock); - - if (do_stuff_counter < 2) { - dds_security_fsm_dispatch(fsm, eventZ, false); - } else if (do_stuff_counter == 2) { - dds_security_fsm_dispatch(fsm, eventY, false); - } - ++do_stuff_counter; -} - -static void doOtherStuff(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - - if (DB_TC_PRINT_DEBUG) { - printf("Transition %s - %d\n", __FUNCTION__, do_other_stuff_counter); - } - ddsrt_mutex_lock (&g_lock); - visited_test |= 1u << 3; - ddsrt_mutex_unlock (&g_lock); - - if (do_other_stuff_counter == 0) { - dds_security_fsm_dispatch(fsm, DDS_SECURITY_FSM_EVENT_AUTO, false); - } - - if (do_other_stuff_counter == 1) { - dds_security_fsm_dispatch(fsm, eventY, false); - } else if (do_other_stuff_counter == 2) { - dds_security_fsm_dispatch(fsm, eventX, false); - } - ++do_other_stuff_counter; -} - -static dds_security_fsm_state StateA = {doStuff, 0}; -static dds_security_fsm_state StateB = {doStuff, 100000000}; -static dds_security_fsm_state StateC = {NULL, 0}; -static dds_security_fsm_state StateD = {doOtherStuff, 0}; - -static dds_security_fsm_transition Transitions[] = { - {NULL, DDS_SECURITY_FSM_EVENT_AUTO, doStart, &StateA}, // NULL state is the start state - {&StateA, eventZ, NULL, &StateB}, - {&StateA, eventY, doOtherStuff, &StateC}, - {&StateB, eventX, NULL, NULL}, // Reaching NULL means end of state-diagram - {&StateB, eventZ, doRestart, &StateA}, - {&StateC, DDS_SECURITY_FSM_EVENT_AUTO, doEventStuff, &StateD}, - {&StateD, eventY, doEventStuff, &StateD}, - {&StateD, eventX, doStuff, NULL}, // Reaching NULL means end of sttimeoutate-diagram -}; -static const uint32_t TransitionsSize = sizeof(Transitions)/sizeof(Transitions[0]); - - -/********************************************************************** - * Timeout State Machine properties and methods - **********************************************************************/ - -typedef enum { - eventToTimeout, eventToInterupt, eventToEnd, -} timeout_events; - -struct fsm_timeout_arg { - int id; -}; - -static struct dds_security_fsm *fsm_timeout; -static uint32_t visited_timeout = 0; -static uint32_t correct_fsm_timeout = 0; -static uint32_t correct_arg_timeout = 0; -static struct fsm_timeout_arg fsm_arg = { .id = FSM_AUTH_ARG }; - -DO_SIMPLE(doInterrupt, timeout, 0) -DO_SIMPLE(TimeoutCallback2, timeout, 3) - -static void doTimeout(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(arg); - - if (DB_TC_PRINT_DEBUG) { - printf("Transition >>>> %s\n", __FUNCTION__); - } - ddsrt_mutex_lock (&g_lock); - visited_timeout |= 1u << 1; - ddsrt_mutex_unlock (&g_lock); - - if (DB_TC_PRINT_DEBUG) { - printf("Transition <<<< %s\n", __FUNCTION__); - } - - dds_security_fsm_dispatch(fsm, eventToTimeout, false); -} - -static void TimeoutCallback(struct dds_security_fsm *fsm, void *arg) -{ - struct fsm_timeout_arg *farg = arg; - - if (DB_TC_PRINT_DEBUG) { - printf("TimeoutCallback\n"); - } - - ddsrt_mutex_lock (&g_lock); - visited_timeout |= 1u << 2; - - if (farg != NULL) { - if (farg->id == FSM_AUTH_ARG) { - correct_arg_timeout = 1; - } else { - correct_arg_timeout = 0; - } - } - if (fsm == fsm_timeout) { - correct_fsm_timeout = 1; - } else { - correct_fsm_timeout = 0; - } - ddsrt_mutex_unlock (&g_lock); -} - -static dds_security_fsm_state StateInitial = {doTimeout, 0}; -static dds_security_fsm_state StateWaitTimeout = {NULL, DDS_SECS(4)}; -static dds_security_fsm_state StateInterupt = {doInterrupt, 0}; - - -static const dds_security_fsm_transition TimeoutTransitions[] = { - {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateInitial}, // NULL state is the start state - {&StateInitial, eventToTimeout, NULL, &StateWaitTimeout}, - {&StateWaitTimeout, DDS_SECURITY_FSM_EVENT_TIMEOUT, NULL, &StateInterupt}, - {&StateWaitTimeout, eventToInterupt, NULL, &StateInterupt}, - {&StateInterupt, eventToEnd, NULL, NULL}, // Reaching NULL means end of state-diagram -}; -static const uint32_t TimeoutTransitionsSize = sizeof(TimeoutTransitions)/sizeof(TimeoutTransitions[0]); - - -/********************************************************************** - * Parallel Timeout State Machines properties and methods - **********************************************************************/ - -static struct dds_security_fsm *fsm_timeout1; -static struct dds_security_fsm *fsm_timeout2; -static struct dds_security_fsm *fsm_timeout3; - -static dds_time_t time0 = 0; -static dds_time_t time1 = 0; -static dds_time_t time2 = 0; -static dds_time_t time3 = 0; - -static void StateParTime1(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - time1 = dds_time(); -} - -static void StateParTime2(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - time2 = dds_time(); -} - -static void StateParTime3(struct dds_security_fsm *fsm, void *arg) -{ - DDSRT_UNUSED_ARG(fsm); - DDSRT_UNUSED_ARG(arg); - time3 = dds_time(); -} - -static dds_security_fsm_state StateParTimeout1 = {NULL, DDS_SECS(1)}; -static dds_security_fsm_state StateParTimeout2 = {NULL, DDS_SECS(2)}; -static dds_security_fsm_state StateParTimeout3 = {NULL, DDS_SECS(1)}; - -static dds_security_fsm_transition ParallelTimeoutTransitions_1[] = { - {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateParTimeout1}, // NULL state is the startfsm_control_thread state - {&StateParTimeout1, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime1, NULL}, // Reaching NULL means end of state-diagram -}; -static const uint32_t ParallelTimeoutTransitionsSize_1 = sizeof(ParallelTimeoutTransitions_1) / sizeof(ParallelTimeoutTransitions_1[0]); - -static dds_security_fsm_transition ParallelTimeoutTransitions_2[] = { - {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateParTimeout2}, // NULL state is the start state - {&StateParTimeout2, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime2, NULL}, // Reaching NULL means end of state-diagram -}; -static const uint32_t ParallelTimeoutTransitionsSize_2 = sizeof(ParallelTimeoutTransitions_2) / sizeof(ParallelTimeoutTransitions_2[0]); - -static dds_security_fsm_transition ParallelTimeoutTransitions_3[] = { - {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateParTimeout3}, // NULL state is the start state - {&StateParTimeout3, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime3, NULL}, // Reaching NULL means end of state-diagram -}; -static const uint32_t ParallelTimeoutTransitionsSize_3 = sizeof(ParallelTimeoutTransitions_3) / sizeof(ParallelTimeoutTransitions_3[0]); - -static void fsm_control_init(void) -{ - dds_return_t rc; - struct dds_entity *e; - - g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - CU_ASSERT_FATAL(g_participant > 0); - - ddsrt_mutex_init (&g_lock); - - rc = dds_entity_pin(g_participant, &e); - CU_ASSERT_FATAL(rc == 0); - - g_fsm_control = dds_security_fsm_control_create (&e->m_domain->gv); - CU_ASSERT_FATAL (g_fsm_control != NULL); - - dds_entity_unpin (e); - - rc = dds_security_fsm_control_start (g_fsm_control, NULL); - CU_ASSERT_FATAL(rc == 0); -} - -static void fsm_control_fini(void) -{ - dds_security_fsm_control_stop(g_fsm_control); - dds_security_fsm_control_free(g_fsm_control); - ddsrt_mutex_destroy (&g_lock); - - dds_delete(g_participant); -} - -CU_Test(ddssec_fsm, create, .init = fsm_control_init, .fini = fsm_control_fini) -{ - dds_time_t delay30 = DDS_SECS(30); - int timeout; - - /* - * Test single running state machine - * Check creation of a single State Machine - */ - fsm_auth = dds_security_fsm_create(g_fsm_control, HandshakeTransistions, HandshakeTransistionsSize, &fsm_arg); - CU_ASSERT_FATAL(fsm_auth != NULL) - - // set a delay that doesn't expire. Should be terminate when fsm is freed. - dds_security_fsm_set_timeout(fsm_auth, TimeoutCallback, delay30); - dds_security_fsm_start(fsm_auth); - - /** - * Check the result of one running State Machine - */ - - // Wait for the last state to occur - timeout = 100; /* 10 sec */ - while ((dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait) && (timeout > 0)) { - dds_sleepfor(msec100); - timeout--; - } - CU_ASSERT(timeout > 0); - dds_security_fsm_dispatch(fsm_auth, SHM_MSG_RECEIVED, false); - - timeout = 100; /* 10 sec */ - while ((dds_security_fsm_current_state(fsm_auth) != NULL) && (timeout > 0)) { - dds_sleepfor(msec100); - timeout--; - } - CU_ASSERT(timeout > 0); - - ddsrt_mutex_lock (&g_lock); - CU_ASSERT(visited_auth == 0xff); - ddsrt_mutex_unlock (&g_lock); - - /* - * "Check correct callback parameter passing (from fsm to user defined methods) "); - */ - CU_ASSERT(correct_arg && correct_fsm); - dds_security_fsm_free(fsm_auth); - - /* Check whether timeout callback has NOT been invoked */ - ddsrt_mutex_lock (&g_lock); - CU_ASSERT(visited_timeout == 0); - ddsrt_mutex_unlock (&g_lock); -} - -/* - * Test multiple (2) running state machines - */ -CU_Test(ddssec_fsm, multiple, .init = fsm_control_init, .fini = fsm_control_fini) -{ - int timeout; - - /*Check creation of multiple (2) State Machines*/ - validate_remote_identity_first = 0; - begin_handshake_reply_first = 0; - visited_auth = 0; - visited_test = 0; - - fsm_auth = dds_security_fsm_create(g_fsm_control, HandshakeTransistions, HandshakeTransistionsSize, NULL); - CU_ASSERT_FATAL(fsm_auth != NULL); - - fsm_test = dds_security_fsm_create(g_fsm_control, Transitions, TransitionsSize, NULL); - CU_ASSERT_FATAL(fsm_test != NULL); - - dds_security_fsm_start(fsm_auth); - dds_security_fsm_start(fsm_test); - - /* Check the results of multiple running State Machines */ - - /* Wait for the last state to occur */ - timeout = 100; /* 10 sec */ - while ((dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait) && (timeout > 0)) { - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - } - CU_ASSERT_FATAL(timeout > 0); - - timeout = 100; /* 10 sec */ - dds_security_fsm_dispatch(fsm_auth, SHM_MSG_RECEIVED, false); - while ((dds_security_fsm_current_state(fsm_auth) != NULL) && (timeout > 0)) { - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - } - CU_ASSERT_FATAL(timeout > 0); - - // not all bits are set since we're running the state machine a second time - ddsrt_mutex_lock (&g_lock); - CU_ASSERT_FATAL(visited_auth == 0x55); - ddsrt_mutex_unlock (&g_lock); - - /* Wait for the last state to occur */ - timeout = 100; /* 10 sec */ - while ((dds_security_fsm_current_state(fsm_test) != NULL) && timeout > 0) { - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - } - CU_ASSERT_FATAL(timeout > 0); - - ddsrt_mutex_lock (&g_lock); - CU_ASSERT(visited_test == 0x1f); - ddsrt_mutex_unlock (&g_lock); - - dds_security_fsm_free(fsm_auth); - dds_security_fsm_free(fsm_test); - -} - -/** - * Check creation of State Machine for timeout purposes - */ -CU_Test(ddssec_fsm, timeout, .init = fsm_control_init, .fini = fsm_control_fini) -{ - dds_time_t delay1 = DDS_SECS(1); - int timeout; - - visited_timeout = 0; - - /* - * Test timeout monitoring of state machines - */ - fsm_timeout = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg); - CU_ASSERT(fsm_timeout != NULL); - - dds_security_fsm_set_timeout(fsm_timeout, TimeoutCallback, delay1); - dds_security_fsm_start(fsm_timeout); - - /*Check the result of the running State Machine for timeout purposes*/ - - // Wait for the last state to occur - timeout = 100; /* 10 sec */ - ddsrt_mutex_lock (&g_lock); - while (visited_timeout != 0x7 && (timeout > 0)) { - ddsrt_mutex_unlock (&g_lock); - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - ddsrt_mutex_lock (&g_lock); - } - CU_ASSERT(timeout > 0); - CU_ASSERT(visited_timeout == 0x7); - CU_ASSERT(correct_arg_timeout && correct_fsm_timeout); - ddsrt_mutex_unlock (&g_lock); - - dds_security_fsm_free(fsm_timeout); -} - -/** - * Check the double global timeout - */ -CU_Test(ddssec_fsm, double_timeout, .init = fsm_control_init, .fini = fsm_control_fini) -{ - dds_time_t delay1 = DDS_SECS(1); - dds_time_t delay2 = DDS_SECS(2); - int timeout; - - visited_timeout = 0; - fsm_timeout = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg); - CU_ASSERT(fsm_timeout != NULL); - - fsm_timeout2 = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg); - CU_ASSERT(fsm_timeout2 != NULL); - - dds_security_fsm_set_timeout(fsm_timeout, TimeoutCallback, delay1); - dds_security_fsm_set_timeout(fsm_timeout2, TimeoutCallback2, delay2); - dds_security_fsm_start(fsm_timeout); - dds_security_fsm_start(fsm_timeout2); - timeout = 100; /* 10 sec */ - ddsrt_mutex_lock (&g_lock); - while (visited_timeout != 0xf && (timeout > 0)) { - ddsrt_mutex_unlock (&g_lock); - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - ddsrt_mutex_lock (&g_lock); - } - CU_ASSERT(visited_timeout == 0xf); - ddsrt_mutex_unlock (&g_lock); - dds_security_fsm_free(fsm_timeout); - dds_security_fsm_free(fsm_timeout2); -} - -/** - * Check parallel state timeouts - */ -CU_Test(ddssec_fsm, parallel_timeout, .init = fsm_control_init, .fini = fsm_control_fini) -{ - dds_duration_t delta1; - dds_duration_t delta2; - dds_duration_t delta3; - int timeout; - - visited_timeout = 0; - - fsm_timeout1 = dds_security_fsm_create(g_fsm_control, ParallelTimeoutTransitions_1, ParallelTimeoutTransitionsSize_1, &fsm_arg); - CU_ASSERT_FATAL(fsm_timeout1 != NULL); - - fsm_timeout2 = dds_security_fsm_create(g_fsm_control, ParallelTimeoutTransitions_2, ParallelTimeoutTransitionsSize_2, &fsm_arg); - CU_ASSERT_FATAL(fsm_timeout2 != NULL); - - fsm_timeout3 = dds_security_fsm_create(g_fsm_control, ParallelTimeoutTransitions_3, ParallelTimeoutTransitionsSize_3, &fsm_arg); - CU_ASSERT_FATAL(fsm_timeout3 != NULL); - - time0 = dds_time(); - dds_security_fsm_start(fsm_timeout1); - dds_security_fsm_start(fsm_timeout2); - dds_security_fsm_start(fsm_timeout3); - - /* Wait for both to end. */ - timeout = 300; /* 10 sec */ - /* First, they have to be started. */ - while (((dds_security_fsm_current_state(fsm_timeout1) == NULL) - || (dds_security_fsm_current_state(fsm_timeout2) == NULL) - || (dds_security_fsm_current_state(fsm_timeout3) == NULL)) && (timeout > 0)) { - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - } - - /* Then, they have to have ended. */ - while (((dds_security_fsm_current_state(fsm_timeout1) != NULL) - || (dds_security_fsm_current_state(fsm_timeout2) != NULL) - || (dds_security_fsm_current_state(fsm_timeout3) != NULL)) && (timeout > 0)) { - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - } - - /* - * There should be about 1 second difference between all times: - * time1 = time0 + 1 - * time2 = time0 + 2 - * time3 = time0 + 1 - */ - delta1 = time1 - time0; - delta2 = time2 - time0; - delta3 = time3 - time0; - printf("Time0 %" PRId64 "\n", time0); - printf("Time1 %" PRId64 "\n", time1); - printf("Time2 %" PRId64 "\n", time2); - printf("Time3 %" PRId64 "\n", time3); - printf("Delta1 %" PRId64 "\n", delta1); - printf("Delta2 %" PRId64 "\n", delta2); - printf("Delta3 %" PRId64 "\n", delta3); - CU_ASSERT(delta1 > 750 * DDS_NSECS_IN_MSEC); - CU_ASSERT(delta1 < 1250 * DDS_NSECS_IN_MSEC); - CU_ASSERT(delta2 > 1750 * DDS_NSECS_IN_MSEC); - CU_ASSERT(delta2 < 2250 * DDS_NSECS_IN_MSEC); - CU_ASSERT(delta3 > 750 * DDS_NSECS_IN_MSEC); - CU_ASSERT(delta3 < 1250 * DDS_NSECS_IN_MSEC); - - dds_security_fsm_free(fsm_timeout1); - dds_security_fsm_free(fsm_timeout2); - dds_security_fsm_free(fsm_timeout3); - -} - -/** - * Delete with event timeout - */ -CU_Test(ddssec_fsm, delete_with_timeout, .init = fsm_control_init, .fini = fsm_control_fini) -{ - int timeout; - - fsm_timeout = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg); - CU_ASSERT (fsm_timeout != NULL) - - visited_timeout = 0; - dds_security_fsm_start(fsm_timeout); - - /* Wait until we're in the timeout function. */ - timeout = 100; /* 10 sec */ - ddsrt_mutex_lock (&g_lock); - while ((visited_timeout == 0) && (timeout > 0)) { - ddsrt_mutex_unlock (&g_lock); - dds_sleepfor(100 * DDS_NSECS_IN_MSEC); - timeout--; - ddsrt_mutex_lock (&g_lock); - } - ddsrt_mutex_unlock (&g_lock); - - dds_security_fsm_free(fsm_timeout); -} - diff --git a/src/security/core/tests/timed_cb.c b/src/security/core/tests/timed_cb.c new file mode 100644 index 0000000..6b01a9e --- /dev/null +++ b/src/security/core/tests/timed_cb.c @@ -0,0 +1,374 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#include +#include "CUnit/Test.h" + +#include "dds/security/core/dds_security_timed_cb.h" +#include "dds/ddsrt/misc.h" + +#define SEQ_SIZE (16) + +typedef struct +{ + struct dds_security_timed_dispatcher_t *d; + dds_security_timed_cb_kind kind; + void *listener; + void *arg; + dds_time_t time; +} test_sequence_data; + +static int g_sequence_idx = 0; +static test_sequence_data g_sequence_array[SEQ_SIZE]; + +static void simple_callback(struct dds_security_timed_dispatcher_t *d, dds_security_timed_cb_kind kind, void *listener, void *arg) +{ + DDSRT_UNUSED_ARG(d); + DDSRT_UNUSED_ARG(kind); + DDSRT_UNUSED_ARG(listener); + *((bool *)arg) = !(*((bool *)arg)); +} + +static int g_order_callback_idx = 0; +static void *g_order_callback[2] = {(void *)NULL, (void *)NULL}; +static void order_callback(struct dds_security_timed_dispatcher_t *d, dds_security_timed_cb_kind kind, void *listener, void *arg) +{ + DDSRT_UNUSED_ARG(d); + DDSRT_UNUSED_ARG(kind); + DDSRT_UNUSED_ARG(listener); + g_order_callback[g_order_callback_idx] = arg; + g_order_callback_idx++; +} + +static void test_callback(struct dds_security_timed_dispatcher_t *d, dds_security_timed_cb_kind kind, void *listener, void *arg) +{ + if (g_sequence_idx < SEQ_SIZE) + { + g_sequence_array[g_sequence_idx].d = d; + g_sequence_array[g_sequence_idx].arg = arg; + g_sequence_array[g_sequence_idx].kind = kind; + g_sequence_array[g_sequence_idx].listener = listener; + g_sequence_array[g_sequence_idx].time = dds_time(); + } + g_sequence_idx++; +} + +CU_Test(ddssec_timed_cb, simple_test) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + static bool test_var = false; + dds_time_t future = dds_time() + DDS_SECS(2); + struct dds_security_timed_dispatcher_t *d1 = dds_security_timed_dispatcher_new(tcb); + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void *)&test_var); + dds_security_timed_dispatcher_enable(tcb, d1, (void *)NULL); + CU_ASSERT_FALSE_FATAL(test_var); + dds_sleepfor(DDS_MSECS(500)); + CU_ASSERT_FALSE_FATAL(test_var); + dds_sleepfor(DDS_SECS(2)); + CU_ASSERT_TRUE_FATAL(test_var); + dds_security_timed_dispatcher_free(tcb, d1); + dds_security_timed_cb_free(tcb); +} + +CU_Test(ddssec_timed_cb, simple_order) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + struct dds_security_timed_dispatcher_t *d1 = dds_security_timed_dispatcher_new(tcb); + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + dds_time_t future = dds_time() + DDS_MSECS(20), future2 = future; + dds_security_timed_dispatcher_add(tcb, d1, order_callback, future, (void *)1); + dds_security_timed_dispatcher_add(tcb, d1, order_callback, future2, (void *)2); + dds_security_timed_dispatcher_enable(tcb, d1, (void *)&g_order_callback); + dds_sleepfor(DDS_MSECS(10)); + dds_security_timed_dispatcher_free(tcb, d1); + CU_ASSERT_EQUAL_FATAL(g_order_callback[0], (void *)1); + CU_ASSERT_EQUAL_FATAL(g_order_callback[1], (void *)2); + dds_security_timed_cb_free(tcb); +} + +CU_Test(ddssec_timed_cb, test_enabled_and_disabled) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + static bool test_var = false; + dds_time_t future = dds_time() + DDS_SECS(2); + struct dds_security_timed_dispatcher_t *d1 = dds_security_timed_dispatcher_new(tcb); + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void *)&test_var); + dds_security_timed_dispatcher_enable(tcb, d1, (void *)NULL); + CU_ASSERT_FALSE(test_var); + dds_security_timed_dispatcher_disable(tcb, d1); + dds_sleepfor(DDS_MSECS(500)); + CU_ASSERT_FALSE(test_var); + dds_sleepfor(DDS_SECS(2)); + CU_ASSERT_FALSE(test_var); + dds_security_timed_dispatcher_free(tcb, d1); + dds_security_timed_cb_free(tcb); +} + +CU_Test(ddssec_timed_cb, simple_test_with_future) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + static bool test_var = false; + dds_time_t now = dds_time(), future = now + DDS_SECS(2), far_future = now + DDS_SECS(10); + struct dds_security_timed_dispatcher_t *d1 = dds_security_timed_dispatcher_new(tcb); + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + dds_security_timed_dispatcher_enable(tcb, d1, (void *)NULL); + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void *)&test_var); + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, far_future, (void *)&test_var); + CU_ASSERT_FALSE_FATAL(test_var); + dds_sleepfor(DDS_MSECS(500)); + CU_ASSERT_FALSE_FATAL(test_var); + dds_sleepfor(DDS_SECS(2)); + CU_ASSERT_TRUE_FATAL(test_var); + dds_security_timed_dispatcher_free(tcb, d1); + dds_security_timed_cb_free(tcb); +} + +CU_Test(ddssec_timed_cb, test_multiple_dispatchers) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + static bool test_var = false; + dds_time_t now = dds_time(), future = now + DDS_SECS(2), far_future = now + DDS_SECS(10); + struct dds_security_timed_dispatcher_t *d1 = dds_security_timed_dispatcher_new(tcb); + struct dds_security_timed_dispatcher_t *d2 = dds_security_timed_dispatcher_new(tcb); + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + dds_security_timed_dispatcher_enable(tcb, d1, (void *)NULL); + dds_security_timed_dispatcher_enable(tcb, d2, (void *)NULL); + dds_security_timed_dispatcher_free(tcb, d2); + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, future, (void *)&test_var); + dds_security_timed_dispatcher_add(tcb, d1, simple_callback, far_future, (void *)&test_var); + CU_ASSERT_FALSE_FATAL(test_var); + dds_sleepfor(DDS_MSECS(500)); + CU_ASSERT_FALSE_FATAL(test_var); + dds_sleepfor(DDS_SECS(2)); + CU_ASSERT_TRUE_FATAL(test_var); + dds_security_timed_dispatcher_free(tcb, d1); + dds_security_timed_cb_free(tcb); +} + +CU_Test(ddssec_timed_cb, test_not_enabled_multiple_dispatchers) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + struct dds_security_timed_dispatcher_t *d1 = dds_security_timed_dispatcher_new(tcb); + struct dds_security_timed_dispatcher_t *d2 = dds_security_timed_dispatcher_new(tcb); + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + CU_ASSERT_PTR_NOT_NULL_FATAL(d2); + dds_security_timed_dispatcher_free(tcb, d2); + dds_security_timed_dispatcher_free(tcb, d1); + dds_security_timed_cb_free(tcb); +} + +CU_Test(ddssec_timed_cb, test_create_dispatcher) +{ + struct dds_security_timed_cb_data *tcb = dds_security_timed_cb_new(); + struct dds_security_timed_dispatcher_t *d1 = NULL; + struct dds_security_timed_dispatcher_t *d2 = NULL; + struct dds_security_timed_dispatcher_t *d3 = NULL; + struct dds_security_timed_dispatcher_t *d4 = NULL; + struct dds_security_timed_dispatcher_t *d5 = NULL; + + dds_time_t now = dds_time(); + dds_time_t past = now - DDS_SECS(1); + dds_time_t present = now + DDS_SECS(1); + dds_time_t future = present + DDS_SECS(1); + dds_time_t future2 = future + DDS_SECS(10); + + d1 = dds_security_timed_dispatcher_new(tcb); + d2 = dds_security_timed_dispatcher_new(tcb); + CU_ASSERT_PTR_NOT_NULL_FATAL(d1); + CU_ASSERT_PTR_NOT_NULL_FATAL(d2); + + /* The last argument is a sequence number in which + the callbacks are expected to be called. */ + dds_security_timed_dispatcher_add(tcb, d1, test_callback, present, (void *)1); + dds_security_timed_dispatcher_add(tcb, d2, test_callback, past, (void *)0); + dds_security_timed_dispatcher_add(tcb, d2, test_callback, present, (void *)2); + dds_security_timed_dispatcher_add(tcb, d1, test_callback, future, (void *)7); + + d3 = dds_security_timed_dispatcher_new(tcb); + d4 = dds_security_timed_dispatcher_new(tcb); + d5 = dds_security_timed_dispatcher_new(tcb); + + CU_ASSERT_PTR_NOT_NULL_FATAL(d3); + CU_ASSERT_PTR_NOT_NULL_FATAL(d4); + CU_ASSERT_PTR_NOT_NULL_FATAL(d5); + + /* The sleeps are added to get the timing between 'present' and 'past' callbacks right. */ + dds_sleepfor(DDS_MSECS(600)); + dds_security_timed_dispatcher_enable(tcb, d1, (void *)NULL); + dds_security_timed_dispatcher_enable(tcb, d2, (void *)d2); + dds_security_timed_dispatcher_enable(tcb, d3, (void *)NULL); + /* Specifically not enabling d4 and d5. */ + dds_sleepfor(DDS_MSECS(600)); + + /* The last argument is a sequence number in which the callbacks are expected to be called. */ + dds_security_timed_dispatcher_add(tcb, d4, test_callback, past, (void *)99); + dds_security_timed_dispatcher_add(tcb, d2, test_callback, future, (void *)8); + dds_security_timed_dispatcher_add(tcb, d3, test_callback, future2, (void *)9); + dds_security_timed_dispatcher_add(tcb, d1, test_callback, past, (void *)3); + dds_security_timed_dispatcher_add(tcb, d1, test_callback, future2, (void *)10); + dds_security_timed_dispatcher_add(tcb, d1, test_callback, present, (void *)4); + dds_security_timed_dispatcher_add(tcb, d2, test_callback, present, (void *)5); + dds_security_timed_dispatcher_add(tcb, d1, test_callback, future, (void *)6); + dds_security_timed_dispatcher_add(tcb, d3, test_callback, future2, (void *)11); + + int idx; + int n = 200; + + /* Wait for the callbacks to have been triggered. Ignore the ones in the far future. */ + while (g_sequence_idx < 8 && n-- > 0) + dds_sleepfor(DDS_MSECS(10)); + + /* Print and check sequence of triggered callbacks. */ + for (idx = 0; idx < g_sequence_idx && idx < SEQ_SIZE; idx++) + { + int seq = (int)(long long)(g_sequence_array[idx].arg); + struct dds_security_timed_dispatcher_t *expected_d; + void *expected_l; + + if (seq == 1 || seq == 6 || seq == 3 || seq == 10 || seq == 4 || seq == 7) + { + expected_d = d1; + expected_l = NULL; + } + else if (seq == 0 || seq == 2 || seq == 8 || seq == 5) + { + expected_d = d2; + expected_l = d2; + } + else if (seq == 9) + { + expected_d = d3; + expected_l = NULL; + } + else if (seq == 99) + { + expected_d = d4; + expected_l = NULL; + CU_FAIL_FATAL("Unexpected callback on a disabled dispatcher"); + } + else + { + expected_d = NULL; + expected_l = NULL; + CU_FAIL_FATAL(sprintf("Unknown sequence idx received %d", seq)); + } + + if (seq != idx) + { + /* 6 and 7 order may be mixed since the order is not defined for same time stamp */ + if (!((seq == 6 && idx == 7) || (seq == 7 && idx == 6))) + { + CU_FAIL_FATAL(sprintf("Unexpected sequence ordering %d vs %d\n", seq, idx)); + } + } + if (seq > 8) + { + CU_FAIL_FATAL(sprintf("Unexpected sequence idx %d of the far future", seq)); + } + if (idx > 8) + { + CU_FAIL_FATAL(sprintf("Too many callbacks %d", idx)); + } + + /* Callback contents checks. */ + if (expected_d != NULL) + { + if (g_sequence_array[idx].d != expected_d) + { + CU_FAIL_FATAL(sprintf("Unexpected dispatcher %p vs %p\n", g_sequence_array[idx].d, expected_d)); + } + if (g_sequence_array[idx].listener != expected_l) + { + CU_FAIL_FATAL(sprintf("Unexpected listener %p vs %p", g_sequence_array[idx].listener, expected_l)); + } + } + + /* Callback kind check. */ + if (g_sequence_array[idx].kind != DDS_SECURITY_TIMED_CB_KIND_TIMEOUT) + { + CU_FAIL_FATAL(sprintf("Unexpected kind %d vs %d", (int)g_sequence_array[idx].kind, (int)DDS_SECURITY_TIMED_CB_KIND_TIMEOUT)); + } + } + if (g_sequence_idx < 8) + { + CU_FAIL_FATAL(sprintf("Received %d callbacks, while 9 are expected", g_sequence_idx + 1)); + } + + /* Reset callback index to catch the deletion ones. */ + g_sequence_idx = 0; + + /* Check if deleting succeeds with dispatchers in different states */ + if (d1) + dds_security_timed_dispatcher_free(tcb, d1); + if (d2) + dds_security_timed_dispatcher_free(tcb, d2); + if (d3) + dds_security_timed_dispatcher_free(tcb, d3); + if (d4) + dds_security_timed_dispatcher_free(tcb, d4); + if (d5) + dds_security_timed_dispatcher_free(tcb, d5); + + /* Wait for the callbacks to have been triggered. Ignore the ones in the far future. */ + n = 200; + while (g_sequence_idx < 4 && n-- > 0) + dds_sleepfor(DDS_MSECS(10)); + + /* Print and check sequence of triggered callbacks. */ + for (idx = 0; (idx < g_sequence_idx) && (idx < SEQ_SIZE); idx++) + { + int seq = (int)(long long)(g_sequence_array[idx].arg); + struct dds_security_timed_dispatcher_t *expected_d; + if (seq == 99) + expected_d = d4; + else if (seq == 9 || seq == 11) + expected_d = d3; + else if (seq == 10) + expected_d = d1; + else + { + expected_d = NULL; + CU_FAIL_FATAL(sprintf("Unexpected sequence idx received %d", seq)); + } + if (idx > 4) + { + CU_FAIL_FATAL(sprintf("Too many callbacks %d", idx)); + } + + /* Callback contents checks. */ + if (expected_d != NULL) + { + if (g_sequence_array[idx].d != expected_d) + { + CU_FAIL_FATAL(sprintf("Unexpected dispatcher %p vs %p", g_sequence_array[idx].d, expected_d)); + } + if (g_sequence_array[idx].listener != NULL) + { + CU_FAIL_FATAL(sprintf("Unexpected listener %p vs NULL", g_sequence_array[idx].listener)); + } + } + + /* Callback kind check. */ + if (g_sequence_array[idx].kind != DDS_SECURITY_TIMED_CB_KIND_DELETE) + { + CU_FAIL_FATAL(sprintf("Unexpected kind %d vs %d", (int)g_sequence_array[idx].kind, (int)DDS_SECURITY_TIMED_CB_KIND_TIMEOUT)); + } + } + if (g_sequence_idx < 4) + { + CU_FAIL_FATAL(sprintf("Received %d callbacks, while 3 are expected", g_sequence_idx + 1)); + } + + dds_security_timed_cb_free(tcb); +} From 9cc128c2951b2523dd12f7d36acd15ba0dcd7da6 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Thu, 5 Mar 2020 11:12:40 +0100 Subject: [PATCH 117/238] Remove setting the tracing verbosity in tests and make configs in security core tests more consistent Signed-off-by: Dennis Potman --- src/security/core/tests/authentication.c | 1 - src/security/core/tests/config.c | 239 +++++++++++++---------- src/security/core/tests/handshake.c | 1 - src/security/core/tests/plugin_loading.c | 138 ++++++++----- 4 files changed, 226 insertions(+), 153 deletions(-) diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index 2d13079..afab49b 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -42,7 +42,6 @@ static const char *config = " 0" " \\${CYCLONEDDS_PID}" " " - " config" " " " " " " diff --git a/src/security/core/tests/config.c b/src/security/core/tests/config.c index 6bfc918..6cb404d 100644 --- a/src/security/core/tests/config.c +++ b/src/security/core/tests/config.c @@ -50,6 +50,15 @@ "file:Permissions_CA.pem", "file:Governance.p7s", "file:Permissions.p7s", \ pre_str, post_str, binprops) +static const char *default_config = + "" + " " + " ${CYCLONEDDS_PID}" + " " + " finest" + ""; + + /* * The 'found' variable will contain flags related to the expected log * messages that were received. @@ -96,8 +105,17 @@ CU_Test(ddssec_config, empty, .init = ddsrt_init, .fini = ddsrt_fini) NULL }; + const char *sec_config = + "" + " " + " ${CYCLONEDDS_PID}" + " " + " config" + " " + ""; + set_logger_exp(log_expected); - domain = dds_create_domain(0, ""); + domain = dds_create_domain(0, sec_config); CU_ASSERT_EQUAL_FATAL(domain, DDS_RETCODE_ERROR); reset_logger(); @@ -116,7 +134,7 @@ CU_Test(ddssec_config, non, .init = ddsrt_init, .fini = ddsrt_fini) }; set_logger_exp(log_expected); - domain = dds_create_domain(0, "finest"); + domain = dds_create_domain(0, default_config); CU_ASSERT_FATAL(domain > 0); dds_delete(domain); reset_logger(); @@ -139,6 +157,9 @@ CU_Test(ddssec_config, missing, .init = ddsrt_init, .fini = ddsrt_fini) /* IdentityCertificate, IdentityCA and PrivateKey values or elements are missing. */ const char *sec_config = "" + " " + " ${CYCLONEDDS_PID}" + " " " finest" " " " " @@ -190,30 +211,31 @@ CU_Test(ddssec_config, all, .init = ddsrt_init, .fini = ddsrt_fini) }; const char *sec_config = - "<"DDS_PROJECT_NAME">" - " " - " finest" - " " - " " - " " - " "TEST_IDENTITY_CERTIFICATE_DUMMY"" - " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" - " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" - " testtext_Password_testtext" - " testtext_Dir_testtext" - " " - " " - " " - " " - " " - " " - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" - " " - " " - " " - ""; + "" + " " + " ${CYCLONEDDS_PID}" + " " + " finest" + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " testtext_Password_testtext" + " testtext_Dir_testtext" + " " + " " + " " + " " + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + ""; set_logger_exp(log_expected); domain = dds_create_domain(0, sec_config); @@ -261,6 +283,10 @@ CU_Test(ddssec_config, security, .init = ddsrt_init, .fini = ddsrt_fini) const char *sec_config = "" + " " + " ${CYCLONEDDS_PID}" + " " + " finest" " " " " " " @@ -278,7 +304,6 @@ CU_Test(ddssec_config, security, .init = ddsrt_init, .fini = ddsrt_fini) " file:Permissions.p7s" " " " " - " finest" ""; set_logger_exp(log_expected); @@ -325,30 +350,31 @@ CU_Test(ddssec_config, deprecated, .init = ddsrt_init, .fini = ddsrt_fini) }; const char *sec_config = - "<"DDS_PROJECT_NAME">" - " " - " " - " " - " " - " "TEST_IDENTITY_CERTIFICATE_DUMMY"" - " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" - " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" - " testtext_Password_testtext" - " testtext_Dir_testtext" - " " - " " - " " - " " - " " - " " - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" - " " - " " - " finest" - " " - ""; + "" + " " + " ${CYCLONEDDS_PID}" + " " + " finest" + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " testtext_Password_testtext" + " testtext_Dir_testtext" + " " + " " + " " + " " + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + ""; set_logger_exp(log_expected); domain = dds_create_domain(0, sec_config); @@ -395,7 +421,7 @@ CU_Test(ddssec_config, qos, .init = ddsrt_init, .fini = ddsrt_fini) dds_qset_prop(qos, "dds.sec.auth.trusted_ca_dir", "file:/test/dir"); set_logger_exp(log_expected); - domain = dds_create_domain(0, "finest"); + domain = dds_create_domain(0, default_config); CU_ASSERT_FATAL(domain > 0); participant = dds_create_participant(0, qos, NULL); CU_ASSERT_FATAL(participant > 0); @@ -445,7 +471,7 @@ CU_Test(ddssec_config, qos_props, .init = ddsrt_init, .fini = ddsrt_fini) dds_qset_bprop(qos, "test.bprop1", bvalue, 3); set_logger_exp(log_expected); - domain = dds_create_domain(0, "finest"); + domain = dds_create_domain(0, default_config); CU_ASSERT_FATAL(domain > 0); participant = dds_create_participant(0, qos, NULL); CU_ASSERT_FATAL(participant > 0); @@ -475,19 +501,24 @@ CU_Test(ddssec_config, config_qos, .init = ddsrt_init, .fini = ddsrt_fini) }; const char *sec_config = - "finest" - "" - " " - " "TEST_IDENTITY_CERTIFICATE_DUMMY"" - " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" - " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" - " " - " " - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" - " " - ""; + "" + " " + " ${CYCLONEDDS_PID}" + " " + " finest" + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + ""; CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); dds_qset_prop(qos, DDS_SEC_PROP_AUTH_LIBRARY_PATH, WRAPPERLIB_PATH("dds_security_authentication_wrapper")); @@ -533,26 +564,31 @@ CU_Test(ddssec_config, other_prop, .init = ddsrt_init, .fini = ddsrt_fini) }; const char *sec_config = - "finest" - "" - " " - " " - " "TEST_IDENTITY_CERTIFICATE_DUMMY"" - " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" - " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" - " testtext_Password_testtext" - " testtext_Dir_testtext" - " " - " " - " " - " " - " " - " " - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" - " " - ""; + "" + " " + " ${CYCLONEDDS_PID}" + " " + " finest" + " " + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " testtext_Password_testtext" + " testtext_Dir_testtext" + " " + " " + " " + " " + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + ""; CU_ASSERT_FATAL((qos = dds_create_qos()) != NULL); dds_qset_prop(qos, "test.dds.sec.prop1", "testtext_value1_testtext"); @@ -598,19 +634,24 @@ CU_Test(ddssec_config, qos_invalid, .init = ddsrt_init, .fini = ddsrt_fini) }; const char *sec_config = - "finest" - "" - " " - " "TEST_IDENTITY_CERTIFICATE_DUMMY"" - " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" - " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" - " " - " " - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" - " " - ""; + "" + " " + " ${CYCLONEDDS_PID}" + " " + " finest" + " " + " " + " "TEST_IDENTITY_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_CA_CERTIFICATE_DUMMY"" + " "TEST_IDENTITY_PRIVATE_KEY_DUMMY"" + " " + " " + " file:Governance.p7s" + " file:Permissions_CA.pem" + " file:Permissions.p7s" + " " + " " + ""; set_logger_exp(log_expected); diff --git a/src/security/core/tests/handshake.c b/src/security/core/tests/handshake.c index 0408bb9..5534434 100644 --- a/src/security/core/tests/handshake.c +++ b/src/security/core/tests/handshake.c @@ -40,7 +40,6 @@ static const char *config = " 0" " \\${CYCLONEDDS_PID}" " " - " config" " " " " " " diff --git a/src/security/core/tests/plugin_loading.c b/src/security/core/tests/plugin_loading.c index f6aa141..8e09cc5 100644 --- a/src/security/core/tests/plugin_loading.c +++ b/src/security/core/tests/plugin_loading.c @@ -24,6 +24,14 @@ static uint32_t found; +static const char *default_config = + "" + " " + " ${CYCLONEDDS_PID}" + " " + " finest" + ""; + static void logger(void *ptr, const dds_log_data_t *data) { char **expected = (char **)ptr; @@ -60,6 +68,9 @@ CU_Test(ddssec_security_plugin_loading, all_ok, .init = ddsrt_init, .fini = ddsr const char *sec_config = "" + " " + " ${CYCLONEDDS_PID}" + " " " finest" " " " " @@ -75,9 +86,9 @@ CU_Test(ddssec_security_plugin_loading, all_ok, .init = ddsrt_init, .fini = ddsr " " " " " " - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" + " " + " " + " " " " " " ""; @@ -104,7 +115,10 @@ CU_Test(ddssec_security_plugin_loading, missing_finalize, .init = ddsrt_init, .f const char *sec_config = "" - " finest" + " " + " ${CYCLONEDDS_PID}" + " " + " warning" " " " " " " @@ -119,9 +133,9 @@ CU_Test(ddssec_security_plugin_loading, missing_finalize, .init = ddsrt_init, .f " " " " " " - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" + " " + " " + " " " " " " ""; @@ -147,7 +161,10 @@ CU_Test(ddssec_security_plugin_loading, authentication_missing_function, .init = const char *sec_config = "" - " finest" + " " + " ${CYCLONEDDS_PID}" + " " + " warning" " " " " " " @@ -162,9 +179,9 @@ CU_Test(ddssec_security_plugin_loading, authentication_missing_function, .init = " " " " " " - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" + " " + " " + " " " " " " ""; @@ -190,7 +207,10 @@ CU_Test(ddssec_security_plugin_loading, access_control_missing_function, .init = const char *sec_config = "" - " finest" + " " + " ${CYCLONEDDS_PID}" + " " + " warning" " " " " " " @@ -205,9 +225,9 @@ CU_Test(ddssec_security_plugin_loading, access_control_missing_function, .init = " " " " " " - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" + " " + " " + " " " " " " ""; @@ -233,7 +253,10 @@ CU_Test(ddssec_security_plugin_loading, cryptography_missing_function, .init = d const char *sec_config = "" - " finest" + " " + " ${CYCLONEDDS_PID}" + " " + " warning" " " " " " " @@ -248,9 +271,9 @@ CU_Test(ddssec_security_plugin_loading, cryptography_missing_function, .init = d " " " " " " - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" + " " + " " + " " " " " " ""; @@ -279,7 +302,10 @@ CU_Test(ddssec_security_plugin_loading, no_library_in_path, .init = ddsrt_init, const char *sec_config = "" - " finest" + " " + " ${CYCLONEDDS_PID}" + " " + " warning" " " " " " " @@ -294,9 +320,9 @@ CU_Test(ddssec_security_plugin_loading, no_library_in_path, .init = ddsrt_init, " " " " " " - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" + " " + " " + " " " " " " ""; @@ -323,7 +349,10 @@ CU_Test(ddssec_security_plugin_loading, init_error, .init = ddsrt_init, .fini = const char *sec_config = "" - " finest" + " " + " ${CYCLONEDDS_PID}" + " " + " warning" " " " " " " @@ -338,9 +367,9 @@ CU_Test(ddssec_security_plugin_loading, init_error, .init = ddsrt_init, .fini = " " " " " " - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" + " " + " " + " " " " " " ""; @@ -370,9 +399,9 @@ CU_Test(ddssec_security_plugin_loading, all_ok_with_props, .init = ddsrt_init, . dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PRIV_KEY, "testtext_PrivateKey_testtext"); dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CERT, "testtext_IdentityCertificate_testtext"); - dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:Permissions_CA.pem"); - dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:Governance.p7s"); - dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:Permissions.p7s"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:"); dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PASSWORD, "testtext_Password_testtext"); dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR, "file:/test/dir"); @@ -391,7 +420,7 @@ CU_Test(ddssec_security_plugin_loading, all_ok_with_props, .init = ddsrt_init, . dds_qset_bprop(qos, "test.bprop1", bvalue, 3); set_logger_exp(log_expected); - domain = dds_create_domain(0, "finest"); + domain = dds_create_domain(0, default_config); CU_ASSERT_FATAL(domain > 0); participant = dds_create_participant(0, qos, NULL); CU_ASSERT_FATAL(participant > 0); @@ -418,9 +447,9 @@ CU_Test(ddssec_security_plugin_loading, missing_plugin_property_with_props, .ini dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PRIV_KEY, "testtext_PrivateKey_testtext"); dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CERT, "testtext_IdentityCertificate_testtext"); - dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:Permissions_CA.pem"); - dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:Governance.p7s"); - dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:Permissions.p7s"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:"); dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PASSWORD, "testtext_Password_testtext"); dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR, "file:/test/dir"); @@ -439,7 +468,7 @@ CU_Test(ddssec_security_plugin_loading, missing_plugin_property_with_props, .ini dds_qset_bprop(qos, "test.bprop1", bvalue, 3); set_logger_exp(log_expected); - domain = dds_create_domain(0, "finest"); + domain = dds_create_domain(0, default_config); CU_ASSERT_FATAL(domain > 0); participant = dds_create_participant(0, qos, NULL); CU_ASSERT_EQUAL_FATAL(participant, DDS_RETCODE_ERROR); @@ -466,8 +495,8 @@ CU_Test(ddssec_security_plugin_loading, empty_plugin_property_with_props, .init dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PRIV_KEY, "testtext_PrivateKey_testtext"); dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CERT, "testtext_IdentityCertificate_testtext"); dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:Permissions_CA.pem"); - dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:Governance.p7s"); - dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:Permissions.p7s"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:"); dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PASSWORD, "testtext_Password_testtext"); dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR, "file:/test/dir"); @@ -486,7 +515,7 @@ CU_Test(ddssec_security_plugin_loading, empty_plugin_property_with_props, .init dds_qset_bprop(qos, "test.bprop1", bvalue, 3); set_logger_exp(log_expected); - domain = dds_create_domain(0, "finest"); + domain = dds_create_domain(0, default_config); CU_ASSERT_FATAL(domain > 0); participant = dds_create_participant(DDS_DOMAIN_DEFAULT, qos, NULL); CU_ASSERT_EQUAL_FATAL(participant, DDS_RETCODE_ERROR); @@ -512,10 +541,9 @@ CU_Test(ddssec_security_plugin_loading, missing_security_property_with_props, .i dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PRIV_KEY, "testtext_PrivateKey_testtext"); dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CERT, "testtext_IdentityCertificate_testtext"); - dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:Permissions_CA.pem"); - dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:Governance.p7s"); - /* we ignore permissions for testing - //dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:Permissions.p7s"); */ + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:"); + //dds_qset_prop (qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:"); dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PASSWORD, "testtext_Password_testtext"); dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR, "file:/test/dir"); @@ -534,7 +562,7 @@ CU_Test(ddssec_security_plugin_loading, missing_security_property_with_props, .i dds_qset_bprop(qos, "test.bprop1", bvalue, 3); set_logger_exp(log_expected); - domain = dds_create_domain(0, "finest"); + domain = dds_create_domain(0, default_config); CU_ASSERT_FATAL(domain > 0); participant = dds_create_participant(DDS_DOMAIN_DEFAULT, qos, NULL); CU_ASSERT_EQUAL_FATAL(participant, DDS_RETCODE_ERROR); @@ -558,6 +586,9 @@ CU_Test(ddssec_security_plugin_loading, multiple_domains_different_config, .init const char *sec_config = "" + " " + " ${CYCLONEDDS_PID}" + " " " finest" " " " " @@ -573,14 +604,17 @@ CU_Test(ddssec_security_plugin_loading, multiple_domains_different_config, .init " " " " " " - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" + " " + " " + " " " " " " "" "" " finest" + " " + " ${CYCLONEDDS_PID}" + " " " " " " " " @@ -595,9 +629,9 @@ CU_Test(ddssec_security_plugin_loading, multiple_domains_different_config, .init " " " " " " - " file:Governance.p7s" - " file:Permissions_CA.pem" - " file:Permissions.p7s" + " " + " " + " " " " " " ""; @@ -614,9 +648,9 @@ CU_Test(ddssec_security_plugin_loading, multiple_domains_different_config, .init dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CA, "testtext_IdentityCA_testtext"); dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PRIV_KEY, "testtext_PrivateKey_testtext"); dds_qset_prop(qos, DDS_SEC_PROP_AUTH_IDENTITY_CERT, "testtext_IdentityCertificate_testtext"); - dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:Permissions_CA.pem"); - dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:Governance.p7s"); - dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:Permissions.p7s"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, "file:"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_GOVERNANCE, "file:"); + dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_PERMISSIONS, "file:"); dds_qset_prop(qos, DDS_SEC_PROP_AUTH_PASSWORD, "testtext_Password_testtext"); dds_qset_prop(qos, DDS_SEC_PROP_ACCESS_TRUSTED_CA_DIR, "file:/test/dir"); From b8537c0d0993ed5b011e8110afadeffac5eba513 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Thu, 5 Mar 2020 11:14:46 +0100 Subject: [PATCH 118/238] Add test in secure_communication suite to validate that payload/submsg/rtps-msg does not contain secret when using encryption protection kind Signed-off-by: Dennis Potman --- src/security/core/tests/SecurityCoreTests.idl | 6 + .../core/tests/common/cryptography_wrapper.c | 79 ++++++--- .../core/tests/common/cryptography_wrapper.h | 2 + .../core/tests/secure_communication.c | 157 ++++++++++++++---- 4 files changed, 187 insertions(+), 57 deletions(-) diff --git a/src/security/core/tests/SecurityCoreTests.idl b/src/security/core/tests/SecurityCoreTests.idl index 1eb6700..8e2290c 100644 --- a/src/security/core/tests/SecurityCoreTests.idl +++ b/src/security/core/tests/SecurityCoreTests.idl @@ -15,4 +15,10 @@ module SecurityCoreTests { long value; }; #pragma keylist Type1 id + + struct Type2 { + long id; //@Key + string text; + }; +#pragma keylist Type2 id }; diff --git a/src/security/core/tests/common/cryptography_wrapper.c b/src/security/core/tests/common/cryptography_wrapper.c index f220c5c..fcb3ed9 100644 --- a/src/security/core/tests/common/cryptography_wrapper.c +++ b/src/security/core/tests/common/cryptography_wrapper.c @@ -59,6 +59,7 @@ struct dds_security_cryptography_impl { DDS_Security_ProtectionKind rtps_protection_kind; DDS_Security_ProtectionKind metadata_protection_kind; DDS_Security_BasicProtectionKind payload_protection_kind; + const char * encrypted_secret; }; static DDS_Security_ParticipantCryptoHandle g_local_participant_handle = 0; @@ -75,6 +76,12 @@ void set_protection_kinds( impl->payload_protection_kind = payload_protection_kind; } +void set_encrypted_secret(struct dds_security_cryptography_impl * impl, const char * secret) +{ + assert(impl); + impl->encrypted_secret = secret; +} + static unsigned char * find_buffer_match(const unsigned char *input, size_t input_len, const unsigned char *match, size_t match_len) { if (match_len <= input_len && match_len > 0 && input_len > 0) @@ -423,15 +430,46 @@ static DDS_Security_boolean encode_serialized_payload( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + { if (!impl->instance->encode_serialized_payload (impl->instance, encoded_buffer, extra_inline_qos, plain_buffer, check_handle (sending_datawriter_crypto), ex)) return false; + if (impl->parent->encrypted_secret && (impl->parent->payload_protection_kind == DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT + || expect_encrypted_buffer (impl->parent->metadata_protection_kind) + || expect_encrypted_buffer (impl->parent->rtps_protection_kind))) + { + if (find_buffer_match (encoded_buffer->_buffer, encoded_buffer->_length, (const unsigned char *) impl->parent->encrypted_secret, strlen (impl->parent->encrypted_secret)) != NULL) + { + ex->code = 1; + ex->message = ddsrt_strdup ("Expect encryption, but found secret in payload after encoding"); + return false; + } + } return check_buffers (encoded_buffer, plain_buffer, impl->parent->payload_protection_kind == DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT, ex); + } default: return true; } } +static DDS_Security_boolean check_buffer_submsg( + struct dds_security_crypto_transform_impl *impl, + DDS_Security_OctetSeq *encoded_rtps_submessage, + const DDS_Security_OctetSeq *plain_rtps_submessage, + DDS_Security_SecurityException *ex) +{ + bool exp_enc = expect_encrypted_buffer (impl->parent->metadata_protection_kind) || expect_encrypted_buffer (impl->parent->rtps_protection_kind); + if (exp_enc + && impl->parent->encrypted_secret + && find_buffer_match (encoded_rtps_submessage->_buffer, encoded_rtps_submessage->_length, (const unsigned char *) impl->parent->encrypted_secret, strlen (impl->parent->encrypted_secret)) != NULL) + { + ex->code = 1; + ex->message = ddsrt_strdup ("Expect encryption, but found secret in submessage after encoding"); + return false; + } + return expect_encrypted_buffer (impl->parent->metadata_protection_kind) ? check_buffers (encoded_rtps_submessage, plain_rtps_submessage, true, ex) : true; +} + static DDS_Security_boolean encode_datawriter_submessage( dds_security_crypto_transform *instance, DDS_Security_OctetSeq *encoded_rtps_submessage, @@ -448,8 +486,7 @@ static DDS_Security_boolean encode_datawriter_submessage( if (!impl->instance->encode_datawriter_submessage (impl->instance, encoded_rtps_submessage, plain_rtps_submessage, check_handle (sending_datawriter_crypto), receiving_datareader_crypto_list, receiving_datareader_crypto_list_index, ex)) return false; - return expect_encrypted_buffer (impl->parent->metadata_protection_kind) ? - check_buffers (encoded_rtps_submessage, plain_rtps_submessage, true, ex) : true; + return check_buffer_submsg(impl, encoded_rtps_submessage, plain_rtps_submessage, ex); default: return true; } @@ -470,8 +507,7 @@ static DDS_Security_boolean encode_datareader_submessage( if (!impl->instance->encode_datareader_submessage (impl->instance, encoded_rtps_submessage, plain_rtps_submessage, check_handle (sending_datareader_crypto), receiving_datawriter_crypto_list, ex)) return false; - return expect_encrypted_buffer (impl->parent->metadata_protection_kind) ? - check_buffers (encoded_rtps_submessage, plain_rtps_submessage, true, ex) : true; + return check_buffer_submsg(impl, encoded_rtps_submessage, plain_rtps_submessage, ex); default: return true; } @@ -493,6 +529,14 @@ static DDS_Security_boolean encode_rtps_message( if (!impl->instance->encode_rtps_message (impl->instance, encoded_rtps_message, plain_rtps_message, check_handle (sending_participant_crypto), receiving_participant_crypto_list, receiving_participant_crypto_list_index, ex)) return false; + if (impl->parent->encrypted_secret + && expect_encrypted_buffer (impl->parent->rtps_protection_kind) + && find_buffer_match (encoded_rtps_message->_buffer, encoded_rtps_message->_length, (const unsigned char *) impl->parent->encrypted_secret, strlen (impl->parent->encrypted_secret)) != NULL) + { + ex->code = 1; + ex->message = ddsrt_strdup ("Expect encryption, but found secret in RTPS message after encoding"); + return false; + } return expect_encrypted_buffer (impl->parent->rtps_protection_kind) ? check_buffers (encoded_rtps_message, plain_rtps_message, true, ex) : true; default: @@ -512,11 +556,8 @@ static DDS_Security_boolean decode_rtps_message( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: - if (!impl->instance->decode_rtps_message (impl->instance, plain_buffer, encoded_buffer, - check_handle (receiving_participant_crypto), check_handle (sending_participant_crypto), ex)) - return false; - return expect_encrypted_buffer (impl->parent->rtps_protection_kind) ? - check_buffers (encoded_buffer, plain_buffer, true, ex) : true; + return impl->instance->decode_rtps_message (impl->instance, plain_buffer, encoded_buffer, + check_handle (receiving_participant_crypto), check_handle (sending_participant_crypto), ex); default: return true; } @@ -555,11 +596,8 @@ static DDS_Security_boolean decode_datawriter_submessage( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: - if (!impl->instance->decode_datawriter_submessage (impl->instance, plain_rtps_submessage, - encoded_rtps_submessage, check_handle (receiving_datareader_crypto), check_handle (sending_datawriter_crypto), ex)) - return false; - return expect_encrypted_buffer (impl->parent->metadata_protection_kind) ? - check_buffers (encoded_rtps_submessage, plain_rtps_submessage, true, ex) : true; + return impl->instance->decode_datawriter_submessage (impl->instance, plain_rtps_submessage, + encoded_rtps_submessage, check_handle (receiving_datareader_crypto), check_handle (sending_datawriter_crypto), ex); default: return true; } @@ -577,11 +615,8 @@ static DDS_Security_boolean decode_datareader_submessage( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: - if (!impl->instance->decode_datareader_submessage (impl->instance, plain_rtps_submessage, - encoded_rtps_submessage, check_handle (receiving_datawriter_crypto), check_handle (sending_datareader_crypto), ex)) - return false; - return expect_encrypted_buffer (impl->parent->metadata_protection_kind) ? - check_buffers (encoded_rtps_submessage, plain_rtps_submessage, true, ex) : true; + return impl->instance->decode_datareader_submessage (impl->instance, plain_rtps_submessage, + encoded_rtps_submessage, check_handle (receiving_datawriter_crypto), check_handle (sending_datareader_crypto), ex); default: return true; } @@ -600,10 +635,8 @@ static DDS_Security_boolean decode_serialized_payload( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: - if (!impl->instance->decode_serialized_payload(impl->instance, plain_buffer, encoded_buffer, - inline_qos, check_handle (receiving_datareader_crypto), check_handle (sending_datawriter_crypto), ex)) - return false; - return check_buffers(encoded_buffer, plain_buffer, impl->parent->payload_protection_kind == DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT, ex); + return impl->instance->decode_serialized_payload(impl->instance, plain_buffer, encoded_buffer, + inline_qos, check_handle (receiving_datareader_crypto), check_handle (sending_datawriter_crypto), ex); default: return true; } diff --git a/src/security/core/tests/common/cryptography_wrapper.h b/src/security/core/tests/common/cryptography_wrapper.h index 9fd17d1..42ed1ef 100644 --- a/src/security/core/tests/common/cryptography_wrapper.h +++ b/src/security/core/tests/common/cryptography_wrapper.h @@ -24,6 +24,8 @@ SECURITY_EXPORT void set_protection_kinds( DDS_Security_ProtectionKind metadata_protection_kind, DDS_Security_BasicProtectionKind payload_protection_kind); +SECURITY_EXPORT void set_encrypted_secret(struct dds_security_cryptography_impl * impl, const char * secret); + /* Init in all-ok mode: all functions return success without calling the actual plugin */ SECURITY_EXPORT int32_t init_test_cryptography_all_ok(const char *argument, void **context); SECURITY_EXPORT int32_t finalize_test_cryptography_all_ok(void *context); diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index 978aa62..039174a 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -105,8 +105,13 @@ struct domain_sec_config { DDS_Security_ProtectionKind rtps_pk; DDS_Security_ProtectionKind metadata_pk; DDS_Security_BasicProtectionKind payload_pk; + const char * payload_secret; }; +typedef void (*set_crypto_params_fn)(struct dds_security_cryptography_impl *, const struct domain_sec_config *); +typedef dds_entity_t (*pubsub_create_fn)(dds_entity_t, const dds_qos_t *qos, const dds_listener_t *listener); +typedef dds_entity_t (*ep_create_fn)(dds_entity_t, dds_entity_t, const dds_qos_t *qos, const dds_listener_t *listener); + static struct dds_security_cryptography_impl * get_crypto_context(dds_entity_t participant) { @@ -158,6 +163,16 @@ static void print_config_vars(struct kvp *vars) printf("%s=%s; ", vars[i].key, vars[i].value); } +static dds_qos_t *get_qos() +{ + dds_qos_t * qos = dds_create_qos (); + CU_ASSERT_FATAL (qos != NULL); + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, -1); + dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL); + dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); + return qos; +} + static char *create_topic_name(const char *prefix, uint32_t nr, char *name, size_t size) { ddsrt_pid_t pid = ddsrt_getpid (); @@ -166,20 +181,20 @@ static char *create_topic_name(const char *prefix, uint32_t nr, char *name, size return name; } -static dds_entity_t create_pp (dds_domainid_t domain_id, const struct domain_sec_config * domain_config) +static dds_entity_t create_pp (dds_domainid_t domain_id, const struct domain_sec_config * domain_config, set_crypto_params_fn set_crypto_params) { dds_entity_t pp = dds_create_participant (domain_id, NULL, NULL); CU_ASSERT_FATAL (pp > 0); struct dds_security_cryptography_impl * crypto_context = get_crypto_context (pp); CU_ASSERT_FATAL (crypto_context != NULL); - set_protection_kinds (crypto_context, domain_config->rtps_pk, domain_config->metadata_pk, domain_config->payload_pk); + if (set_crypto_params) + set_crypto_params (crypto_context, domain_config); return pp; } -typedef dds_entity_t (*pubsub_create_fn)(dds_entity_t, const dds_qos_t *qos, const dds_listener_t *listener); static void create_dom_pp_pubsub(dds_domainid_t domain_id_base, const char * domain_conf, const struct domain_sec_config * domain_sec_config, - size_t n_dom, size_t n_pp, dds_entity_t * doms, dds_entity_t * pps, dds_entity_t * pubsubs, pubsub_create_fn pubsub_create) + size_t n_dom, size_t n_pp, dds_entity_t * doms, dds_entity_t * pps, dds_entity_t * pubsubs, pubsub_create_fn pubsub_create, set_crypto_params_fn set_crypto_params) { for (size_t d = 0; d < n_dom; d++) { @@ -188,14 +203,14 @@ static void create_dom_pp_pubsub(dds_domainid_t domain_id_base, const char * dom for (size_t p = 0; p < n_pp; p++) { size_t pp_index = d * n_pp + p; - pps[pp_index] = create_pp (domain_id_base + (uint32_t)d, domain_sec_config); + pps[pp_index] = create_pp (domain_id_base + (uint32_t)d, domain_sec_config, set_crypto_params); pubsubs[pp_index] = pubsub_create (pps[pp_index], NULL, NULL); CU_ASSERT_FATAL (pubsubs[pp_index] > 0); } } } -static void test_init(const struct domain_sec_config * domain_config, size_t n_sub_domains, size_t n_sub_participants, size_t n_pub_domains, size_t n_pub_participants) +static void test_init(const struct domain_sec_config * domain_config, size_t n_sub_domains, size_t n_sub_participants, size_t n_pub_domains, size_t n_pub_participants, set_crypto_params_fn set_crypto_params) { assert (n_sub_domains < MAX_DOMAINS); assert (n_sub_participants < MAX_PARTICIPANTS); @@ -224,12 +239,12 @@ static void test_init(const struct domain_sec_config * domain_config, size_t n_s char *conf_pub = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars); create_dom_pp_pubsub (DDS_DOMAINID_PUB, conf_pub, domain_config, n_pub_domains, n_pub_participants, - g_pub_domains, g_pub_participants, g_pub_publishers, &dds_create_publisher); + g_pub_domains, g_pub_participants, g_pub_publishers, &dds_create_publisher, set_crypto_params); dds_free (conf_pub); char *conf_sub = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars); create_dom_pp_pubsub (DDS_DOMAINID_SUB, conf_sub, domain_config, n_sub_domains, n_sub_participants, - g_sub_domains, g_sub_participants, g_sub_subscribers, &dds_create_subscriber); + g_sub_domains, g_sub_participants, g_sub_subscribers, &dds_create_subscriber, set_crypto_params); dds_free (conf_sub); dds_free (gov_config_signed); @@ -290,9 +305,8 @@ static void reader_wait_for_data(dds_entity_t sub_participant, dds_entity_t read dds_delete (waitset_rd); } -typedef dds_entity_t (*ep_create_fn)(dds_entity_t, dds_entity_t, const dds_qos_t *qos, const dds_listener_t *listener); - -static void create_eps (dds_entity_t **endpoints, dds_entity_t **topics, size_t n_dom, size_t n_pp, size_t n_eps, const char * topic_name, const dds_entity_t * pps, const dds_qos_t * qos, ep_create_fn ep_create, unsigned status_mask) +static void create_eps (dds_entity_t **endpoints, dds_entity_t **topics, size_t n_dom, size_t n_pp, size_t n_eps, const char * topic_name, const dds_topic_descriptor_t *topic_descriptor, + const dds_entity_t * pps, const dds_qos_t * qos, ep_create_fn ep_create, unsigned status_mask) { *topics = ddsrt_malloc (n_dom * n_pp * sizeof (dds_entity_t)); *endpoints = ddsrt_malloc (n_dom * n_pp * n_eps * sizeof (dds_entity_t)); @@ -301,7 +315,7 @@ static void create_eps (dds_entity_t **endpoints, dds_entity_t **topics, size_t for (size_t p = 0; p < n_pp; p++) { size_t pp_index = d * n_pp + p; - (*topics)[pp_index] = dds_create_topic (pps[pp_index], &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL); + (*topics)[pp_index] = dds_create_topic (pps[pp_index], topic_descriptor, topic_name, NULL, NULL); CU_ASSERT_FATAL ((*topics)[pp_index] > 0); for (size_t e = 0; e < n_eps; e++) { @@ -315,9 +329,16 @@ static void create_eps (dds_entity_t **endpoints, dds_entity_t **topics, size_t } } +static void free_eps(dds_entity_t *endpoints, dds_entity_t *topics) +{ + ddsrt_free (endpoints); + ddsrt_free (topics); +} + static void test_write_read(struct domain_sec_config *domain_config, size_t n_sub_domains, size_t n_sub_participants, size_t n_readers, - size_t n_pub_domains, size_t n_pub_participants, size_t n_writers) + size_t n_pub_domains, size_t n_pub_participants, size_t n_writers, + set_crypto_params_fn set_crypto_params) { dds_entity_t *writers, *readers, *writer_topics, *reader_topics; dds_qos_t *qos; @@ -330,18 +351,13 @@ static void test_write_read(struct domain_sec_config *domain_config, printf("Testing: %"PRIuSIZE" subscriber domains, %"PRIuSIZE" pp per domain, %"PRIuSIZE" rd per pp; %"PRIuSIZE" publishing domains, %"PRIuSIZE" pp per domain, %"PRIuSIZE" wr per pp\n", n_sub_domains, n_sub_participants, n_readers, n_pub_domains, n_pub_participants, n_writers); - test_init(domain_config, n_sub_domains, n_sub_participants, n_pub_domains, n_pub_participants); + test_init(domain_config, n_sub_domains, n_sub_participants, n_pub_domains, n_pub_participants, set_crypto_params); create_topic_name("ddssec_secure_communication_", g_topic_nr++, name, sizeof name); - qos = dds_create_qos (); - CU_ASSERT_FATAL (qos != NULL); - dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, -1); - dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL); - dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); - - create_eps (&writers, &writer_topics, n_pub_domains, n_pub_participants, n_writers, name, g_pub_participants, qos, &dds_create_writer, DDS_PUBLICATION_MATCHED_STATUS); - create_eps (&readers, &reader_topics, n_sub_domains, n_sub_participants, n_readers, name, g_sub_participants, qos, &dds_create_reader, DDS_DATA_AVAILABLE_STATUS); + qos = get_qos (); + create_eps (&writers, &writer_topics, n_pub_domains, n_pub_participants, n_writers, name, &SecurityCoreTests_Type1_desc, g_pub_participants, qos, &dds_create_writer, DDS_PUBLICATION_MATCHED_STATUS); + create_eps (&readers, &reader_topics, n_sub_domains, n_sub_participants, n_readers, name, &SecurityCoreTests_Type1_desc, g_sub_participants, qos, &dds_create_reader, DDS_DATA_AVAILABLE_STATUS); for (size_t d = 0; d < n_pub_domains; d++) { @@ -389,35 +405,91 @@ static void test_write_read(struct domain_sec_config *domain_config, /* Cleanup */ dds_delete_qos (qos); test_fini (n_sub_domains, n_pub_domains); - ddsrt_free (readers); - ddsrt_free (writers); - ddsrt_free (reader_topics); - ddsrt_free (writer_topics); + free_eps (readers, reader_topics); + free_eps (writers, writer_topics); +} + +static void set_encryption_parameters_basic(struct dds_security_cryptography_impl * crypto_context, const struct domain_sec_config *domain_config) +{ + set_protection_kinds (crypto_context, domain_config->rtps_pk, domain_config->metadata_pk, domain_config->payload_pk); +} + +static void set_encryption_parameters_secret(struct dds_security_cryptography_impl * crypto_context, const struct domain_sec_config *domain_config) +{ + set_encrypted_secret (crypto_context, domain_config->payload_secret); } static void test_discovery_liveliness_protection(DDS_Security_ProtectionKind discovery_pk, DDS_Security_ProtectionKind liveliness_pk) { - struct domain_sec_config domain_config = { discovery_pk, liveliness_pk, PK_N, PK_N, BPK_N }; + struct domain_sec_config domain_config = { discovery_pk, liveliness_pk, PK_N, PK_N, BPK_N, NULL }; /* FIXME: add more asserts in wrapper or test instead of just testing communication */ - test_write_read (&domain_config, 1, 1, 1, 1, 1, 1); + test_write_read (&domain_config, 1, 1, 1, 1, 1, 1, NULL); } static void test_data_protection_kind(DDS_Security_ProtectionKind rtps_pk, DDS_Security_ProtectionKind metadata_pk, DDS_Security_BasicProtectionKind payload_pk) { - struct domain_sec_config domain_config = { PK_N, PK_N, rtps_pk, metadata_pk, payload_pk }; - test_write_read (&domain_config, 1, 1, 1, 1, 1, 1); + struct domain_sec_config domain_config = { PK_N, PK_N, rtps_pk, metadata_pk, payload_pk, NULL }; + test_write_read (&domain_config, 1, 1, 1, 1, 1, 1, &set_encryption_parameters_basic); } static void test_multiple_readers(size_t n_dom, size_t n_pp, size_t n_rd, DDS_Security_ProtectionKind metadata_pk, DDS_Security_BasicProtectionKind payload_pk) { - struct domain_sec_config domain_config = { PK_N, PK_N, PK_N, metadata_pk, payload_pk }; - test_write_read (&domain_config, n_dom, n_pp, n_rd, 1, 1, 1); + struct domain_sec_config domain_config = { PK_N, PK_N, PK_N, metadata_pk, payload_pk, NULL }; + test_write_read (&domain_config, n_dom, n_pp, n_rd, 1, 1, 1, NULL); } static void test_multiple_writers(size_t n_rd_dom, size_t n_rd, size_t n_wr_dom, size_t n_wr, DDS_Security_ProtectionKind metadata_pk) { - struct domain_sec_config domain_config = { PK_N, PK_N, PK_N, metadata_pk, BPK_N }; - test_write_read (&domain_config, n_rd_dom, 1, n_rd, n_wr_dom, 1, n_wr); + struct domain_sec_config domain_config = { PK_N, PK_N, PK_N, metadata_pk, BPK_N, NULL }; + test_write_read (&domain_config, n_rd_dom, 1, n_rd, n_wr_dom, 1, n_wr, NULL); +} + +static void test_payload_secret(DDS_Security_ProtectionKind rtps_pk, DDS_Security_ProtectionKind metadata_pk, DDS_Security_BasicProtectionKind payload_pk) +{ + dds_entity_t *writers, *readers, *writer_topics, *reader_topics; + const char * secret = "my_test_secret"; + dds_qos_t *qos; + SecurityCoreTests_Type2 sample; + SecurityCoreTests_Type2 rd_sample = {0, NULL}; + void * samples[] = { &rd_sample }; + dds_sample_info_t info[1]; + dds_return_t ret; + char name[100]; + struct domain_sec_config domain_config = { PK_N, PK_N, rtps_pk, metadata_pk, payload_pk, secret }; + + size_t payload_sz = 100 * strlen (secret) + 1; + sample.id = 1; + sample.text = ddsrt_malloc (payload_sz); + for (size_t n = 0; n < 100; n++) + memcpy (sample.text + n * strlen (secret), secret, strlen (secret)); + sample.text[payload_sz - 1] = '\0'; + + test_init (&domain_config, 1, 1, 1, 1, &set_encryption_parameters_secret); + create_topic_name ("ddssec_secure_communication_", g_topic_nr++, name, sizeof name); + qos = get_qos (); + create_eps (&writers, &writer_topics, 1, 1, 1, name, &SecurityCoreTests_Type2_desc, g_pub_participants, qos, &dds_create_writer, DDS_PUBLICATION_MATCHED_STATUS); + create_eps (&readers, &reader_topics, 1, 1, 1, name, &SecurityCoreTests_Type2_desc, g_sub_participants, qos, &dds_create_reader, DDS_DATA_AVAILABLE_STATUS); + dds_delete_qos (qos); + sync_writer_to_readers (g_pub_participants[0], writers[0], 1); + ret = dds_write (writers[0], &sample); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + + while (true) + { + if ((ret = dds_take (readers[0], samples, info, 1, 1)) == 0) + { + reader_wait_for_data (g_sub_participants[0], readers[0]); + continue; + } + CU_ASSERT_EQUAL_FATAL (ret, 1); + break; + } + + test_fini (1, 1); + free_eps (readers, reader_topics); + free_eps (writers, writer_topics); + ddsrt_free (rd_sample.text); + ddsrt_free (sample.text); } CU_Test(ddssec_secure_communication, protection_kinds, .timeout = 120) @@ -450,6 +522,23 @@ CU_Test(ddssec_secure_communication, discovery_liveliness_protection, .timeout = } } +CU_Test(ddssec_secure_communication, check_encrypted_secret, .timeout = 60) +{ + DDS_Security_ProtectionKind rtps_pk[] = { PK_N, PK_E, PK_EOA }; + DDS_Security_ProtectionKind metadata_pk[] = { PK_N, PK_E, PK_EOA }; + DDS_Security_BasicProtectionKind payload_pk[] = { BPK_N, BPK_E }; + for (size_t rtps = 0; rtps < sizeof (rtps_pk) / sizeof (rtps_pk[0]); rtps++) + { + for (size_t metadata = 0; metadata < sizeof (metadata_pk) / sizeof (metadata_pk[0]); metadata++) + { + for (size_t payload = 0; payload < sizeof (payload_pk) / sizeof (payload_pk[0]); payload++) + { + test_payload_secret (rtps_pk[rtps], metadata_pk[metadata], payload_pk[payload]); + } + } + } +} + CU_TheoryDataPoints(ddssec_secure_communication, multiple_readers) = { CU_DataPoints(size_t, 1, 1, 1, 3), /* number of domains */ CU_DataPoints(size_t, 1, 3, 1, 3), /* number of participants per domain */ From 8ca17805380787aff9bff6deb2b3196f0baaabff Mon Sep 17 00:00:00 2001 From: Marcel Jordense Date: Wed, 4 Mar 2020 18:34:30 +0100 Subject: [PATCH 119/238] Correct problem with cleanup of security handshake Signed-off-by: Marcel Jordense --- .../ddsi/include/dds/ddsi/ddsi_handshake.h | 3 +- src/core/ddsi/src/ddsi_handshake.c | 23 ++++++++---- src/core/ddsi/src/q_entity.c | 30 ++++++++-------- src/core/ddsi/src/q_transmit.c | 7 +++- .../dds/security/core/dds_security_fsm.h | 18 ++++++++++ src/security/core/src/dds_security_fsm.c | 35 +++++++++---------- 6 files changed, 74 insertions(+), 42 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_handshake.h b/src/core/ddsi/include/dds/ddsi/ddsi_handshake.h index f473d0f..307eb72 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_handshake.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_handshake.h @@ -131,10 +131,9 @@ void ddsi_handshake_register(struct participant *pp, struct proxy_participant *p * * @param[in] pp The local participant. * @param[in] proxypp The remote participant. - * @param[in] handshake The handshake. * */ -void ddsi_handshake_remove(struct participant *pp, struct proxy_participant *proxypp, struct ddsi_handshake *handshake); +void ddsi_handshake_remove(struct participant *pp, struct proxy_participant *proxypp); /** * @brief Searches for the handshake associated with the specified participants diff --git a/src/core/ddsi/src/ddsi_handshake.c b/src/core/ddsi/src/ddsi_handshake.c index 5d1b967..847c796 100644 --- a/src/core/ddsi/src/ddsi_handshake.c +++ b/src/core/ddsi/src/ddsi_handshake.c @@ -21,6 +21,7 @@ #include "dds/ddsi/ddsi_entity_index.h" #include "dds/ddsi/ddsi_plist.h" #include "dds/ddsi/q_entity.h" +#include "dds/ddsi/q_gc.h" #include "dds/security/dds_security_api_types.h" #include "dds/security/dds_security_api.h" #include "dds/ddsi/ddsi_security_omg.h" @@ -991,6 +992,7 @@ void ddsi_handshake_release(struct ddsi_handshake *handshake) DDS_Security_DataHolder_free(handshake->handshake_message_out); DDS_Security_DataHolder_free(handshake->remote_auth_request_token); DDS_Security_OctetSeq_deinit(&handshake->pdata); + dds_security_fsm_free(handshake->fsm); ddsrt_mutex_destroy(&handshake->lock); ddsrt_free(handshake); } @@ -1146,22 +1148,31 @@ static struct ddsi_handshake * ddsi_handshake_find_locked( return ddsrt_avl_lookup(&handshake_treedef, &hsadmin->handshakes, &handles); } -void ddsi_handshake_remove(struct participant *pp, struct proxy_participant *proxypp, struct ddsi_handshake *handshake) +static void gc_delete_handshale (struct gcreq *gcreq) +{ + struct ddsi_handshake *handshake = gcreq->arg; + + ddsi_handshake_release(handshake); + gcreq_free(gcreq); +} + +void ddsi_handshake_remove(struct participant *pp, struct proxy_participant *proxypp) { struct ddsi_hsadmin *hsadmin = pp->e.gv->hsadmin; + struct ddsi_handshake *handshake = NULL; ddsrt_mutex_lock(&hsadmin->lock); - if (!handshake) - handshake = ddsi_handshake_find_locked(hsadmin, pp, proxypp); + handshake = ddsi_handshake_find_locked(hsadmin, pp, proxypp); if (handshake) { + struct gcreq *gcreq = gcreq_new (pp->e.gv->gcreq_queue, gc_delete_handshale); ddsrt_avl_delete(&handshake_treedef, &hsadmin->handshakes, handshake); ddsrt_atomic_st32(&handshake->deleting, 1); + dds_security_fsm_stop(handshake->fsm); + gcreq->arg = handshake; + gcreq_enqueue (gcreq); } ddsrt_mutex_unlock(&hsadmin->lock); - if (handshake && handshake->fsm) - dds_security_fsm_free(handshake->fsm); - ddsi_handshake_release(handshake); } struct ddsi_handshake * ddsi_handshake_find(struct participant *pp, struct proxy_participant *proxypp) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index ab60485..69b75b5 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -668,7 +668,7 @@ static void disconnect_participant_secure(struct participant *pp) entidx_enum_proxy_participant_init (&it, gv->entity_index); while ((proxypp = entidx_enum_proxy_participant_next (&it)) != NULL) { - ddsi_handshake_remove(pp, proxypp, NULL); + ddsi_handshake_remove(pp, proxypp); } entidx_enum_proxy_participant_fini (&it); } @@ -3102,19 +3102,21 @@ static void match_volatile_secure_endpoints (struct participant *pp, struct prox guid = pp->e.guid; guid.entityid.u = NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER; - rd = entidx_lookup_reader_guid (pp->e.gv->entity_index, &guid); - assert(rd); + if ((rd = entidx_lookup_reader_guid (pp->e.gv->entity_index, &guid)) == NULL) + return; + guid.entityid.u = NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER; - wr = entidx_lookup_writer_guid (pp->e.gv->entity_index, &guid); - assert(wr); + if ((wr = entidx_lookup_writer_guid (pp->e.gv->entity_index, &guid)) == NULL) + return; guid = proxypp->e.guid; guid.entityid.u = NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER; - prd = entidx_lookup_proxy_reader_guid (pp->e.gv->entity_index, &guid); - assert(rd); + if ((prd = entidx_lookup_proxy_reader_guid (pp->e.gv->entity_index, &guid)) == NULL) + return; + guid.entityid.u = NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER; - pwr = entidx_lookup_proxy_writer_guid (pp->e.gv->entity_index, &guid); - assert(wr); + if ((pwr = entidx_lookup_proxy_writer_guid (pp->e.gv->entity_index, &guid)) == NULL) + return; connect_proxy_writer_with_reader_wrapper(&pwr->e, &rd->e, tnow); connect_writer_with_proxy_reader_wrapper(&wr->e, &prd->e, tnow); @@ -4771,7 +4773,7 @@ void handshake_end_cb(struct ddsi_handshake *handshake, struct participant *pp, case STATE_HANDSHAKE_OK: DDS_CLOG (DDS_LC_DISCOVERY, &gv->logconfig, "handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") succeeded\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid)); update_proxy_participant_endpoint_matching(proxypp, pp); - ddsi_handshake_remove(pp, proxypp, handshake); + ddsi_handshake_remove(pp, proxypp); break; case STATE_HANDSHAKE_TIMED_OUT: @@ -4780,7 +4782,7 @@ void handshake_end_cb(struct ddsi_handshake *handshake, struct participant *pp, downgrade_to_nonsecure(proxypp); update_proxy_participant_endpoint_matching(proxypp, pp); } - ddsi_handshake_remove(pp, proxypp, handshake); + ddsi_handshake_remove(pp, proxypp); break; case STATE_HANDSHAKE_FAILED: DDS_CERROR (&gv->logconfig, "handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") failed: (%d) Failed\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid), (int)result); @@ -4788,11 +4790,11 @@ void handshake_end_cb(struct ddsi_handshake *handshake, struct participant *pp, downgrade_to_nonsecure(proxypp); update_proxy_participant_endpoint_matching(proxypp, pp); } - ddsi_handshake_remove(pp, proxypp, handshake); + ddsi_handshake_remove(pp, proxypp); break; default: DDS_CERROR (&gv->logconfig, "handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") failed: (%d) Unknown failure\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid), (int)result); - ddsi_handshake_remove(pp, proxypp, handshake); + ddsi_handshake_remove(pp, proxypp); break; } } @@ -4840,7 +4842,7 @@ static void disconnect_proxy_participant_secure(struct proxy_participant *proxyp entidx_enum_participant_init (&it, gv->entity_index); while ((pp = entidx_enum_participant_next (&it)) != NULL) { - ddsi_handshake_remove(pp, proxypp, NULL); + ddsi_handshake_remove(pp, proxypp); } entidx_enum_participant_fini (&it); } diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index cdc7485..774e4f8 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -1159,7 +1159,7 @@ static int maybe_grow_whc (struct writer *wr) int write_sample_p2p_wrlock_held(struct writer *wr, seqno_t seq, struct ddsi_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk, struct proxy_reader *prd) { struct ddsi_domaingv * const gv = wr->e.gv; - int r; + int r = 0; nn_mtime_t tnow; int rexmit = 1; struct wr_prd_match *wprd = NULL; @@ -1170,10 +1170,14 @@ int write_sample_p2p_wrlock_held(struct writer *wr, seqno_t seq, struct ddsi_pli serdata->twrite = tnow; serdata->timestamp = now(); + if (prd->filter) { if ((wprd = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &prd->e.guid)) != NULL) { + if (wprd->seq == MAX_SEQ_NUMBER) + goto prd_is_deleting; + rexmit = prd->filter(wr, prd, serdata); /* determine if gap has to added */ if (rexmit) @@ -1212,6 +1216,7 @@ int write_sample_p2p_wrlock_held(struct writer *wr, seqno_t seq, struct ddsi_pli writer_hbcontrol_note_asyncwrite(wr, tnow); } +prd_is_deleting: return r; } diff --git a/src/security/core/include/dds/security/core/dds_security_fsm.h b/src/security/core/include/dds/security/core/dds_security_fsm.h index 503c5f6..96f24d9 100644 --- a/src/security/core/include/dds/security/core/dds_security_fsm.h +++ b/src/security/core/include/dds/security/core/dds_security_fsm.h @@ -147,6 +147,24 @@ dds_security_fsm_dispatch(struct dds_security_fsm *fsm, int32_t event_id, bool p DDS_EXPORT const dds_security_fsm_state* dds_security_fsm_current_state(struct dds_security_fsm *fsm); +/** + * Stops the state machine. + * Stops all running timeouts and events and cleaning all memory + * related to this machine. + * + * When calling this from another thread, then it may block until + * a possible concurrent event has finished. After this call, the + * fsm may not be used anymore. + * + * When in the fsm action callback function context, this will + * not block. It will garbage collect when the event has been + * handled. + * + * @param fsm The state machine to b stopped + */ +DDS_EXPORT void +dds_security_fsm_stop(struct dds_security_fsm *fsm); + /** * Free the state machine. * Stops all running timeouts and events and cleaning all memory diff --git a/src/security/core/src/dds_security_fsm.c b/src/security/core/src/dds_security_fsm.c index 8685ed0..e2b9436 100644 --- a/src/security/core/src/dds_security_fsm.c +++ b/src/security/core/src/dds_security_fsm.c @@ -49,7 +49,6 @@ struct dds_security_fsm { struct dds_security_fsm *next_fsm; struct dds_security_fsm *prev_fsm; - bool busy; bool deleting; struct dds_security_fsm_control *control; const dds_security_fsm_transition *transitions; @@ -73,7 +72,6 @@ struct dds_security_fsm_control struct fsm_event *first_event; struct fsm_event *last_event; ddsrt_fibheap_t timers; - ddsrt_thread_t tid; bool running; }; @@ -230,7 +228,7 @@ static void fsm_check_auto_state_change (struct dds_security_fsm *fsm) } } -static void fsm_state_change (struct thread_state1 *ts1, struct dds_security_fsm_control *control, struct fsm_event *event) +static void fsm_state_change (struct dds_security_fsm_control *control, struct fsm_event *event) { struct dds_security_fsm *fsm = event->fsm; int event_id = event->event_id; @@ -246,19 +244,15 @@ static void fsm_state_change (struct thread_state1 *ts1, struct dds_security_fsm clear_state_timer (fsm); fsm->current = fsm->transitions[i].end; set_state_timer (fsm); - fsm->busy = true; ddsrt_mutex_unlock (&control->lock); - thread_state_awake (ts1, control->gv); if (fsm->transitions[i].func) fsm->transitions[i].func (fsm, fsm->arg); if (fsm->current && fsm->current->func) fsm->current->func (fsm, fsm->arg); - thread_state_asleep (ts1); ddsrt_mutex_lock (&control->lock); - fsm->busy = false; if (!fsm->deleting) fsm_check_auto_state_change (fsm); else @@ -278,12 +272,10 @@ static void fsm_handle_timeout (struct dds_security_fsm_control *control, struct fsm_dispatch (fsm, DDS_SECURITY_FSM_EVENT_TIMEOUT, true); break; case FSM_TIMEOUT_OVERALL: - fsm->busy = true; ddsrt_mutex_unlock (&control->lock); if (fsm->overall_timeout_action) fsm->overall_timeout_action (fsm, fsm->arg); ddsrt_mutex_lock (&control->lock); - fsm->busy = false; if (fsm->deleting) ddsrt_cond_broadcast(&control->cond); break; @@ -298,15 +290,13 @@ static uint32_t handle_events (struct dds_security_fsm_control *control) struct thread_state1 * const ts1 = lookup_thread_state (); struct fsm_event *event; - control->tid = ddsrt_thread_self(); - thread_state_awake (ts1, control->gv); ddsrt_mutex_lock (&control->lock); while (control->running) { if ((event = get_event(control)) != NULL) { - fsm_state_change (ts1, control, event); + fsm_state_change (control, event); ddsrt_free (event); } else @@ -456,7 +446,6 @@ struct dds_security_fsm * dds_security_fsm_create (struct dds_security_fsm_contr fsm->overall_timeout_event.kind = FSM_TIMEOUT_OVERALL; fsm->overall_timeout_event.endtime = DDS_NEVER; fsm->overall_timeout_event.fsm = fsm; - fsm->busy = false; fsm->deleting = false; fsm->next_fsm = NULL; fsm->prev_fsm = NULL; @@ -482,14 +471,9 @@ static void fsm_deactivate (struct dds_security_fsm_control *control, struct dds clear_state_timer (fsm); clear_overall_timer (fsm); fsm->current = NULL; - if (!ddsrt_thread_equal(control->tid, ddsrt_thread_self())) - { - while (fsm->busy) - ddsrt_cond_wait(&control->cond, &control->lock); - } } -void dds_security_fsm_free (struct dds_security_fsm *fsm) +void dds_security_fsm_stop (struct dds_security_fsm *fsm) { struct dds_security_fsm_control *control; @@ -509,6 +493,19 @@ static void fsm_delete (struct dds_security_fsm_control *control, struct dds_sec ddsrt_free(fsm); } +void dds_security_fsm_free (struct dds_security_fsm *fsm) +{ + struct dds_security_fsm_control *control; + + assert(fsm); + assert(fsm->control); + + control = fsm->control; + ddsrt_mutex_lock (&control->lock); + fsm_delete (control, fsm); + ddsrt_mutex_unlock (&control->lock); +} + struct dds_security_fsm_control * dds_security_fsm_control_create (struct ddsi_domaingv *gv) { struct dds_security_fsm_control *control; From 0a9d391c64640c8e616c1887ce695dec4e4b3b1d Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Thu, 5 Mar 2020 13:13:24 +0100 Subject: [PATCH 120/238] Fixed logging in find_own_ip Signed-off-by: Dennis Potman --- src/core/ddsi/src/q_nwif.c | 4 +- src/security/core/tests/access_control.c | 136 +++++++++++++++++++++++ 2 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 src/security/core/tests/access_control.c diff --git a/src/core/ddsi/src/q_nwif.c b/src/core/ddsi/src/q_nwif.c index 7b96a2f..5ee10a1 100644 --- a/src/core/ddsi/src/q_nwif.c +++ b/src/core/ddsi/src/q_nwif.c @@ -482,10 +482,10 @@ int find_own_ip (struct ddsi_domaingv *gv, const char *requested_address) switch (ifa->type) { case DDSRT_IFTYPE_WIFI: - DDS_LOG(DDS_LC_CONFIG, " wireless"); + GVLOG (DDS_LC_CONFIG, " wireless"); break; case DDSRT_IFTYPE_WIRED: - DDS_LOG(DDS_LC_CONFIG, " wired"); + GVLOG (DDS_LC_CONFIG, " wired"); break; case DDSRT_IFTYPE_UNKNOWN: break; diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c new file mode 100644 index 0000000..0b25a90 --- /dev/null +++ b/src/security/core/tests/access_control.c @@ -0,0 +1,136 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include + +#include "dds/dds.h" +#include "CUnit/Test.h" +#include "CUnit/Theory.h" + +#include "dds/version.h" +#include "dds/ddsrt/cdtors.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/process.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsi/q_config.h" +#include "dds/ddsi/ddsi_domaingv.h" +#include "dds/ddsi/q_misc.h" +#include "dds/ddsi/ddsi_xqos.h" + +#include "dds/security/dds_security_api.h" + +#include "common/config_env.h" +#include "common/access_control_wrapper.h" +#include "common/security_config_test_utils.h" +#include "common/test_identity.h" + +static const char *config = + "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" + "" + " " + " 0" + " \\${CYCLONEDDS_PID}" + " " + " " + " " + " " + " " TEST_IDENTITY_CERTIFICATE "" + " " TEST_IDENTITY_PRIVATE_KEY "" + " " TEST_IDENTITY_CA_CERTIFICATE "" + " " + " " + " " + " ${TEST_GOVERNANCE}" + " ${TEST_PERMISSIONS_CA}" + " ${TEST_PERMISSIONS}" + " " + " " + " " + " " + " " + ""; + +#define DDS_DOMAINID1 0 +#define DDS_DOMAINID2 1 + +static dds_entity_t g_domain1 = 0; +static dds_entity_t g_participant1 = 0; + +static dds_entity_t g_domain2 = 0; +static dds_entity_t g_participant2 = 0; + +static void access_control_init(const char * gov, const char * perm, const char * ca, bool exp_pp_fail) +{ + struct kvp config_vars[] = { + { "TEST_GOVERNANCE", gov, 1 }, + { "TEST_PERMISSIONS", perm, 1 }, + { "TEST_PERMISSIONS_CA", ca, 1 }, + { NULL, NULL, 0 } + }; + + char *conf = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars); + CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars), 0); + g_domain1 = dds_create_domain (DDS_DOMAINID1, conf); + g_domain2 = dds_create_domain (DDS_DOMAINID2, conf); + dds_free (conf); + + g_participant1 = dds_create_participant (DDS_DOMAINID1, NULL, NULL); + g_participant2 = dds_create_participant (DDS_DOMAINID2, NULL, NULL); + if (exp_pp_fail) + { + CU_ASSERT_FATAL (g_participant1 <= 0); + CU_ASSERT_FATAL (g_participant2 <= 0); + } + else + { + CU_ASSERT_FATAL (g_participant1 > 0); + CU_ASSERT_FATAL (g_participant2 > 0); + } +} + +static void access_control_fini(bool delete_pp) +{ + if (delete_pp) + { + CU_ASSERT_EQUAL_FATAL (dds_delete (g_participant1), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL (dds_delete (g_participant2), DDS_RETCODE_OK); + } + CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain1), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain2), DDS_RETCODE_OK); +} + + +#define PF_F "file:" +#define PF_D "data:," +#define GOV_F PF_F COMMON_ETC_PATH("default_governance.p7s") +#define GOV_FNE PF_F COMMON_ETC_PATH("default_governance_non_existing.p7s") +#define GOV_DI PF_D COMMON_ETC_PATH("default_governance.p7s") +#define PERM_F PF_F COMMON_ETC_PATH("default_permissions.p7s") +#define PERM_FNE PF_F COMMON_ETC_PATH("default_permissions_non_existing.p7s") +#define PERM_DI PF_D COMMON_ETC_PATH("default_permissions.p7s") +#define CA_F PF_F COMMON_ETC_PATH("default_permissions_ca.pem") +#define CA_FNE PF_F COMMON_ETC_PATH("default_permissions_ca_non_existing.pem") +#define CA_DI PF_D COMMON_ETC_PATH("default_permissions_ca.pem") +#define CA_D TEST_PERMISSIONS_CA_CERTIFICATE + +CU_TheoryDataPoints(ddssec_access_control, config_parameters) = { + CU_DataPoints(const char *, GOV_F, GOV_FNE, GOV_FNE, GOV_F, GOV_F, "", GOV_F, GOV_F, GOV_DI, GOV_F), + CU_DataPoints(const char *, PERM_F, PERM_FNE, PERM_F, PERM_FNE, PERM_F, PERM_F, "", PERM_F, PERM_F, PERM_F), + CU_DataPoints(const char *, CA_F, CA_FNE, CA_F, CA_F, CA_FNE, CA_F, CA_F, "", CA_F, CA_D), + CU_DataPoints(bool, false, true, true, true, true, true, true, true, true, false) +}; +CU_Theory((const char * gov, const char * perm, const char * ca, bool exp_fail), ddssec_access_control, config_parameters) +{ + access_control_init (gov, perm, ca, exp_fail); + access_control_fini (!exp_fail); +} From ea91e17a62342bc6902b04a627e4aca3d2a806cf Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 29 Feb 2020 17:18:47 +0100 Subject: [PATCH 121/238] Rename nn_keyhash to ddsi_keyhash Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_builtin.c | 4 +-- src/core/ddsc/src/dds_serdata_builtintopic.c | 2 +- src/core/ddsi/CMakeLists.txt | 1 + src/core/ddsi/include/dds/ddsi/ddsi_keyhash.h | 27 +++++++++++++++++++ src/core/ddsi/include/dds/ddsi/ddsi_plist.h | 7 ++--- src/core/ddsi/include/dds/ddsi/ddsi_serdata.h | 10 +++---- src/core/ddsi/src/ddsi_plist.c | 20 +++++++------- src/core/ddsi/src/ddsi_serdata.c | 4 +-- src/core/ddsi/src/ddsi_serdata_default.c | 6 ++--- src/core/ddsi/src/q_ddsi_discovery.c | 2 +- src/core/ddsi/src/q_xmsg.c | 2 +- 11 files changed, 55 insertions(+), 30 deletions(-) create mode 100644 src/core/ddsi/include/dds/ddsi/ddsi_keyhash.h diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index b7068c4..f4a52af 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -176,7 +176,7 @@ static struct ddsi_tkmap_instance *dds__builtin_get_tkmap_entry (const struct dd struct dds_domain *domain = vdomain; struct ddsi_tkmap_instance *tk; struct ddsi_serdata *sd; - struct nn_keyhash kh; + struct ddsi_keyhash kh; memcpy (&kh, guid, sizeof (kh)); /* any random builtin topic will do (provided it has a GUID for a key), because what matters is the "class" of the topic, not the actual topic; also, this is called early in the initialisation of the entity with this GUID, which simply causes serdata_from_keyhash to create a key-only serdata because the key lookup fails. */ sd = ddsi_serdata_from_keyhash (domain->builtin_participant_topic, &kh); @@ -191,7 +191,7 @@ struct ddsi_serdata *dds__builtin_make_sample (const struct entity_common *e, nn struct dds_domain *dom = e->gv->builtin_topic_interface->arg; struct ddsi_sertopic *topic = NULL; struct ddsi_serdata *serdata; - struct nn_keyhash keyhash; + struct ddsi_keyhash keyhash; switch (e->kind) { case EK_PARTICIPANT: diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index 84063f0..12af5e0 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -126,7 +126,7 @@ static void from_entity_pwr (struct ddsi_serdata_builtintopic *d, const struct p assert (d->xqos.present & QP_TYPE_NAME); } -static struct ddsi_serdata *ddsi_serdata_builtin_from_keyhash (const struct ddsi_sertopic *tpcmn, const nn_keyhash_t *keyhash) +static struct ddsi_serdata *ddsi_serdata_builtin_from_keyhash (const struct ddsi_sertopic *tpcmn, const ddsi_keyhash_t *keyhash) { /* FIXME: not quite elegant to manage the creation of a serdata for a built-in topic via this function, but I also find it quite unelegant to let from_sample read straight from the underlying internal entity, and to_sample convert to the external format ... I could claim the internal entity is the "serialised form", but that forces wrapping it in a fragchain in one way or another, which, though possible, is also a bit lacking in elegance. */ const struct ddsi_sertopic_builtintopic *tp = (const struct ddsi_sertopic_builtintopic *)tpcmn; diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 4c466bd..ab200f3 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -98,6 +98,7 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" ddsi_builtin_topic_if.h ddsi_rhc.h ddsi_guid.h + ddsi_keyhash.h ddsi_entity_index.h ddsi_deadline.h ddsi_deliver_locally.h diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_keyhash.h b/src/core/ddsi/include/dds/ddsi/ddsi_keyhash.h new file mode 100644 index 0000000..bbb60a1 --- /dev/null +++ b/src/core/ddsi/include/dds/ddsi/ddsi_keyhash.h @@ -0,0 +1,27 @@ +/* + * Copyright(c) 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSI_KEYHASH_H +#define DDSI_KEYHASH_H + +#if defined (__cplusplus) +extern "C" { +#endif + +typedef struct ddsi_keyhash { + unsigned char value[16]; +} ddsi_keyhash_t; + +#if defined (__cplusplus) +} +#endif + +#endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_plist.h b/src/core/ddsi/include/dds/ddsi/ddsi_plist.h index 4f8b07f..227067a 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_plist.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_plist.h @@ -14,6 +14,7 @@ #include "dds/ddsi/q_feature_check.h" #include "dds/ddsi/ddsi_xqos.h" +#include "dds/ddsi/ddsi_keyhash.h" #include "dds/ddsi/ddsi_tran.h" /* FIXME: eliminate */ #if defined (__cplusplus) @@ -97,10 +98,6 @@ typedef uint32_t nn_ipv4address_t; typedef uint32_t nn_port_t; -typedef struct nn_keyhash { - unsigned char value[16]; -} nn_keyhash_t; - #ifdef DDSI_INCLUDE_SECURITY typedef struct nn_tag { char *name; @@ -218,7 +215,7 @@ typedef struct ddsi_plist { uint32_t builtin_endpoint_set; /* int type_max_size_serialized; */ char *entity_name; - nn_keyhash_t keyhash; + ddsi_keyhash_t keyhash; uint32_t statusinfo; nn_prismtech_participant_version_info_t prismtech_participant_version_info; char *type_description; diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h index 4ff9ff0..db3b87a 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h @@ -15,13 +15,13 @@ #include "dds/ddsrt/sockets.h" #include "dds/ddsi/q_time.h" #include "dds/ddsi/ddsi_sertopic.h" +#include "dds/ddsi/ddsi_keyhash.h" #if defined (__cplusplus) extern "C" { #endif struct nn_rdata; -struct nn_keyhash; enum ddsi_serdata_kind { SDK_EMPTY, @@ -65,7 +65,7 @@ typedef struct ddsi_serdata * (*ddsi_serdata_from_ser_t) (const struct ddsi_sert typedef struct ddsi_serdata * (*ddsi_serdata_from_ser_iov_t) (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size); /* Construct a serdata from a keyhash (an SDK_KEY by definition) */ -typedef struct ddsi_serdata * (*ddsi_serdata_from_keyhash_t) (const struct ddsi_sertopic *topic, const struct nn_keyhash *keyhash); +typedef struct ddsi_serdata * (*ddsi_serdata_from_keyhash_t) (const struct ddsi_sertopic *topic, const struct ddsi_keyhash *keyhash); /* Construct a serdata from an application sample - "kind" is KEY or DATA depending on the operation invoked by the application; @@ -138,7 +138,7 @@ typedef size_t (*ddsi_serdata_print_t) (const struct ddsi_sertopic *topic, const /* Add keyhash (from serdata) to buffer (forcing md5 when necessary). - key needs to be set within serdata (can already be md5) - buf needs to be at least 16 bytes large */ -typedef void (*ddsi_serdata_get_keyhash_t) (const struct ddsi_serdata *d, struct nn_keyhash *buf, bool force_md5); +typedef void (*ddsi_serdata_get_keyhash_t) (const struct ddsi_serdata *d, struct ddsi_keyhash *buf, bool force_md5); struct ddsi_serdata_ops { ddsi_serdata_eqkey_t eqkey; @@ -187,7 +187,7 @@ DDS_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_ser_iov (const struct d return topic->serdata_ops->from_ser_iov (topic, kind, niov, iov, size); } -DDS_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_keyhash (const struct ddsi_sertopic *topic, const struct nn_keyhash *keyhash) { +DDS_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_keyhash (const struct ddsi_sertopic *topic, const struct ddsi_keyhash *keyhash) { return topic->serdata_ops->from_keyhash (topic, keyhash); } @@ -237,7 +237,7 @@ DDS_EXPORT inline bool ddsi_serdata_print_topicless (const struct ddsi_sertopic } } -DDS_EXPORT inline void ddsi_serdata_get_keyhash (const struct ddsi_serdata *d, struct nn_keyhash *buf, bool force_md5) { +DDS_EXPORT inline void ddsi_serdata_get_keyhash (const struct ddsi_serdata *d, struct ddsi_keyhash *buf, bool force_md5) { d->ops->get_keyhash (d, buf, force_md5); } diff --git a/src/core/ddsi/src/ddsi_plist.c b/src/core/ddsi/src/ddsi_plist.c index 9722e02..a421e4c 100644 --- a/src/core/ddsi/src/ddsi_plist.c +++ b/src/core/ddsi/src/ddsi_plist.c @@ -487,7 +487,7 @@ static size_t ser_generic_srcsize (const enum pserop * __restrict desc) case Xb: case Xbx2: SIMPLE (Xb, unsigned char); break; case XbCOND: SIMPLE (XbCOND, unsigned char); break; case XG: SIMPLE (XG, ddsi_guid_t); break; - case XK: SIMPLE (XK, nn_keyhash_t); break; + case XK: SIMPLE (XK, ddsi_keyhash_t); break; case XbPROP: SIMPLE (XbPROP, unsigned char); break; case XQ: SIMPLE (XQ, ddsi_octetseq_t); break; case Xopt: break; @@ -531,7 +531,7 @@ static bool fini_generic_embeddable (void * __restrict dst, size_t * __restrict case Xb: case Xbx2: SIMPLE (Xb, unsigned char); break; case XbCOND: SIMPLE (XbCOND, unsigned char); break; case XG: SIMPLE (XG, ddsi_guid_t); break; - case XK: SIMPLE (XK, nn_keyhash_t); break; + case XK: SIMPLE (XK, ddsi_keyhash_t); break; case XbPROP: SIMPLE (XbPROP, unsigned char); break; case XQ: { @@ -564,7 +564,7 @@ static size_t pserop_memalign (enum pserop op) case XO: case XQ: return alignof (ddsi_octetseq_t); case XS: return alignof (char *); case XG: return alignof (ddsi_guid_t); - case XK: return alignof (nn_keyhash_t); + case XK: return alignof (ddsi_keyhash_t); case Xb: case Xbx2: return 1; case Xo: case Xox2: return 1; case XbCOND: case XbPROP: return 1; @@ -705,7 +705,7 @@ static dds_return_t deser_generic_r (void * __restrict dst, size_t * __restrict break; } case XK: { /* keyhash */ - nn_keyhash_t * const x = deser_generic_dst (dst, dstoff, alignof (nn_keyhash_t)); + ddsi_keyhash_t * const x = deser_generic_dst (dst, dstoff, alignof (ddsi_keyhash_t)); if (dd->bufsz - *srcoff < sizeof (*x)) goto fail; memcpy (x, dd->buf + *srcoff, sizeof (*x)); @@ -817,7 +817,7 @@ static void ser_generic_size_embeddable (size_t *dstoff, const void *src, size_t case Xb: case Xbx2: SIMPLE1 (Xb, unsigned char); break; case XbCOND: SIMPLE1 (XbCOND, unsigned char); break; case XG: SIMPLE1 (XG, ddsi_guid_t); break; - case XK: SIMPLE1 (XK, nn_keyhash_t); break; + case XK: SIMPLE1 (XK, ddsi_keyhash_t); break; case XbPROP: /* "propagate" boolean: when 'false'; no serialisation; no size; force early out */ COMPLEX (XbPROP, unsigned char, if (! *x) return); break; case XQ: COMPLEX (XQ, ddsi_octetseq_t, { @@ -973,7 +973,7 @@ static dds_return_t ser_generic_embeddable (char * const data, size_t *dstoff, c break; } case XK: { /* keyhash */ - nn_keyhash_t const * const x = deser_generic_src (src, &srcoff, alignof (nn_keyhash_t)); + ddsi_keyhash_t const * const x = deser_generic_src (src, &srcoff, alignof (ddsi_keyhash_t)); char * const p = data + *dstoff; memcpy (p, x, sizeof (*x)); *dstoff += sizeof (*x); @@ -1055,7 +1055,7 @@ static dds_return_t unalias_generic (void * __restrict dst, size_t * __restrict case XbCOND: SIMPLE (XbCOND, unsigned char); break; case XbPROP: SIMPLE (XbPROP, unsigned char); break; case XG: SIMPLE (XG, ddsi_guid_t); break; - case XK: SIMPLE (XK, nn_keyhash_t); break; + case XK: SIMPLE (XK, ddsi_keyhash_t); break; case XQ: COMPLEX (XQ, ddsi_octetseq_t, if (x->length) { const size_t elem_size = ser_generic_srcsize (desc + 1); if (gen_seq_aliased) @@ -1149,7 +1149,7 @@ static dds_return_t valid_generic (const void *src, size_t srcoff, const enum ps case XbCOND: SIMPLE (XbCOND, unsigned char, *x == 0 || *x == 1); break; case XbPROP: SIMPLE (XbPROP, unsigned char, *x == 0 || *x == 1); break; case XG: TRIVIAL (XG, ddsi_guid_t); break; - case XK: TRIVIAL (XK, nn_keyhash_t); break; + case XK: TRIVIAL (XK, ddsi_keyhash_t); break; case XQ: COMPLEX (XQ, ddsi_octetseq_t, { if ((x->length == 0) != (x->value == NULL)) return DDS_RETCODE_BAD_PARAMETER; @@ -1213,7 +1213,7 @@ static bool equal_generic (const void *srcx, const void *srcy, size_t srcoff, co break; case XbPROP: TRIVIAL (XbPROP, unsigned char); break; case XG: SIMPLE (XG, ddsi_guid_t, memcmp (x, y, sizeof (*x)) == 0); break; - case XK: SIMPLE (XK, nn_keyhash_t, memcmp (x, y, sizeof (*x)) == 0); break; + case XK: SIMPLE (XK, ddsi_keyhash_t, memcmp (x, y, sizeof (*x)) == 0); break; case XQ: COMPLEX (XQ, ddsi_octetseq_t, { if (x->length != y->length) return false; @@ -1393,7 +1393,7 @@ static bool print_generic1 (char * __restrict *buf, size_t * __restrict bufsize, break; } case XK: { /* keyhash */ - nn_keyhash_t const * const x = deser_generic_src (src, &srcoff, alignof (nn_keyhash_t)); + ddsi_keyhash_t const * const x = deser_generic_src (src, &srcoff, alignof (ddsi_keyhash_t)); if (!prtf (buf, bufsize, "%s{%02x%02x%02x%02x:%02x%02x%02x%02x:%02x%02x%02x%02x:%02x%02x%02x%02x}", sep, x->value[0], x->value[1], x->value[2], x->value[3], x->value[4], x->value[5], x->value[6], x->value[7], x->value[8], x->value[9], x->value[10], x->value[11], x->value[12], x->value[13], x->value[14], x->value[15])) diff --git a/src/core/ddsi/src/ddsi_serdata.c b/src/core/ddsi/src/ddsi_serdata.c index 97e43c2..d1f5fa6 100644 --- a/src/core/ddsi/src/ddsi_serdata.c +++ b/src/core/ddsi/src/ddsi_serdata.c @@ -37,7 +37,7 @@ extern inline void ddsi_serdata_unref (struct ddsi_serdata *serdata); extern inline uint32_t ddsi_serdata_size (const struct ddsi_serdata *d); extern inline struct ddsi_serdata *ddsi_serdata_from_ser (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, const struct nn_rdata *fragchain, size_t size); extern inline struct ddsi_serdata *ddsi_serdata_from_ser_iov (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size); -extern inline struct ddsi_serdata *ddsi_serdata_from_keyhash (const struct ddsi_sertopic *topic, const struct nn_keyhash *keyhash); +extern inline struct ddsi_serdata *ddsi_serdata_from_keyhash (const struct ddsi_sertopic *topic, const struct ddsi_keyhash *keyhash); extern inline struct ddsi_serdata *ddsi_serdata_from_sample (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, const void *sample); extern inline struct ddsi_serdata *ddsi_serdata_to_topicless (const struct ddsi_serdata *d); extern inline void ddsi_serdata_to_ser (const struct ddsi_serdata *d, size_t off, size_t sz, void *buf); @@ -48,4 +48,4 @@ extern inline bool ddsi_serdata_topicless_to_sample (const struct ddsi_sertopic extern inline bool ddsi_serdata_eqkey (const struct ddsi_serdata *a, const struct ddsi_serdata *b); extern inline bool ddsi_serdata_print (const struct ddsi_serdata *d, char *buf, size_t size); extern inline bool ddsi_serdata_print_topicless (const struct ddsi_sertopic *topic, const struct ddsi_serdata *d, char *buf, size_t size); -extern inline void ddsi_serdata_get_keyhash (const struct ddsi_serdata *d, struct nn_keyhash *buf, bool force_md5); +extern inline void ddsi_serdata_get_keyhash (const struct ddsi_serdata *d, struct ddsi_keyhash *buf, bool force_md5); diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index f89e30c..bd49d4b 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -346,7 +346,7 @@ static struct ddsi_serdata *serdata_default_from_ser_iov_nokey (const struct dds return fix_serdata_default_nokey (d, tpcmn->serdata_basehash); } -static struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr (const struct ddsi_sertopic *tpcmn, const nn_keyhash_t *keyhash) +static struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr (const struct ddsi_sertopic *tpcmn, const ddsi_keyhash_t *keyhash) { /* FIXME: not quite sure this is correct, though a check against a specially hacked OpenSplice suggests it is */ const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)tpcmn; @@ -374,7 +374,7 @@ static struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr (const struct ddsi_ser } } -static struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr_nokey (const struct ddsi_sertopic *tpcmn, const nn_keyhash_t *keyhash) +static struct ddsi_serdata *ddsi_serdata_from_keyhash_cdr_nokey (const struct ddsi_sertopic *tpcmn, const ddsi_keyhash_t *keyhash) { const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)tpcmn; struct ddsi_serdata_default *d = serdata_default_new(tp, SDK_KEY); @@ -700,7 +700,7 @@ static size_t serdata_default_print_raw (const struct ddsi_sertopic *sertopic_co return (size_t) snprintf (buf, size, "(blob)"); } -static void serdata_default_get_keyhash (const struct ddsi_serdata *serdata_common, struct nn_keyhash *buf, bool force_md5) +static void serdata_default_get_keyhash (const struct ddsi_serdata *serdata_common, struct ddsi_keyhash *buf, bool force_md5) { const struct ddsi_serdata_default *d = (const struct ddsi_serdata_default *)serdata_common; assert(buf); diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 589276a..04f2660 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -1874,7 +1874,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str break; } keyhash_payload.p_endpoint_guid.parameterid = pid; - keyhash_payload.p_endpoint_guid.length = sizeof (nn_keyhash_t); + keyhash_payload.p_endpoint_guid.length = sizeof (ddsi_keyhash_t); memcpy (keyhash_payload.kh, &qos.keyhash, sizeof (qos.keyhash)); keyhash_payload.p_sentinel.parameterid = PID_SENTINEL; keyhash_payload.p_sentinel.length = 0; diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index 93a70a2..5d90709 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -952,7 +952,7 @@ void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serda if (serdata->kind != SDK_EMPTY) { char *p = nn_xmsg_addpar (m, PID_KEYHASH, 16); - ddsi_serdata_get_keyhash(serdata, (struct nn_keyhash*)p, force_md5); + ddsi_serdata_get_keyhash(serdata, (struct ddsi_keyhash*)p, force_md5); } } From e58f4dc344bc0c656ab2a95eb163876433c581b1 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 29 Feb 2020 17:19:01 +0100 Subject: [PATCH 122/238] Fix macro for checking serdata has get_keyhash Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/ddsi_serdata.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h index db3b87a..ce65c6e 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h @@ -160,7 +160,7 @@ struct ddsi_serdata_ops { #define DDSI_SERDATA_HAS_PRINT 1 #define DDSI_SERDATA_HAS_FROM_SER_IOV 1 -#define DDSI_SERDATA_HAS_ADD_KEYHASH 1 +#define DDSI_SERDATA_HAS_GET_KEYHASH 1 DDS_EXPORT void ddsi_serdata_init (struct ddsi_serdata *d, const struct ddsi_sertopic *tp, enum ddsi_serdata_kind kind); From 9fe51ef3fb795d798f57c0f79569b29ed55a623a Mon Sep 17 00:00:00 2001 From: Sid Faber Date: Tue, 10 Mar 2020 13:55:03 +0000 Subject: [PATCH 123/238] Install security plugins Security plugins are built but not installed. Add target to CMakeLists.txt for three security plugins. Signed-off-by: Sid Faber --- src/security/builtin_plugins/access_control/CMakeLists.txt | 2 +- src/security/builtin_plugins/authentication/CMakeLists.txt | 2 +- src/security/builtin_plugins/cryptographic/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/security/builtin_plugins/access_control/CMakeLists.txt b/src/security/builtin_plugins/access_control/CMakeLists.txt index e0ffc78..e7bf471 100644 --- a/src/security/builtin_plugins/access_control/CMakeLists.txt +++ b/src/security/builtin_plugins/access_control/CMakeLists.txt @@ -41,7 +41,7 @@ target_include_directories(dds_security_ac ) install( - TARGETS + TARGETS dds_security_ac EXPORT "${PROJECT_NAME}" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT lib LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib diff --git a/src/security/builtin_plugins/authentication/CMakeLists.txt b/src/security/builtin_plugins/authentication/CMakeLists.txt index 91455c5..d6cb40c 100644 --- a/src/security/builtin_plugins/authentication/CMakeLists.txt +++ b/src/security/builtin_plugins/authentication/CMakeLists.txt @@ -46,7 +46,7 @@ target_include_directories(dds_security_auth ) install( - TARGETS + TARGETS dds_security_auth EXPORT "${PROJECT_NAME}" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT lib LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib diff --git a/src/security/builtin_plugins/cryptographic/CMakeLists.txt b/src/security/builtin_plugins/cryptographic/CMakeLists.txt index 3cae998..e7d97f5 100644 --- a/src/security/builtin_plugins/cryptographic/CMakeLists.txt +++ b/src/security/builtin_plugins/cryptographic/CMakeLists.txt @@ -45,7 +45,7 @@ target_include_directories(dds_security_crypto ) install( - TARGETS + TARGETS dds_security_crypto EXPORT "${PROJECT_NAME}" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT lib LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib From f11dd50810f4f48e2dac9ebe871dbccf67607540 Mon Sep 17 00:00:00 2001 From: Marcel Jordense Date: Tue, 10 Mar 2020 15:54:10 +0100 Subject: [PATCH 124/238] Set volatile secure reader initially out-of-sync Signed-off-by: Marcel Jordense --- src/core/ddsi/src/ddsi_security_exchange.c | 2 ++ src/core/ddsi/src/q_entity.c | 2 +- src/core/ddsi/src/q_receive.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/ddsi/src/ddsi_security_exchange.c b/src/core/ddsi/src/ddsi_security_exchange.c index e510e2c..b475ad4 100644 --- a/src/core/ddsi/src/ddsi_security_exchange.c +++ b/src/core/ddsi/src/ddsi_security_exchange.c @@ -280,6 +280,8 @@ static bool write_crypto_exchange_message(const struct participant *pp, const dd nn_participant_generic_message_init(&pmg, &wr->e.guid, seq, dst_pguid, dst_eguid, src_eguid, classid, tokens, NULL); nn_participant_generic_message_serialize(&pmg, &data, &len); + nn_participant_generic_message_log(gv, &pmg, 0); + /* Get the key value. */ ddsrt_md5_state_t md5st; ddsrt_md5_byte_t digest[16]; diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 69b75b5..d7b5c46 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -2480,7 +2480,7 @@ static void proxy_writer_add_connection (struct proxy_writer *pwr, struct reader /* These can change as a consequence of handling data and/or discovery activities. The safe way of dealing with them is to lock the proxy writer */ - if (is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE) && !ddsrt_avl_is_empty (&pwr->readers)) + if (is_builtin_entityid (rd->e.guid.entityid, NN_VENDORID_ECLIPSE) && !ddsrt_avl_is_empty (&pwr->readers) && !pwr->filtered) { /* builtins really don't care about multiple copies or anything */ m->in_sync = PRMSS_SYNC; diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 7a5f9a7..cdf7e2d 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -2300,7 +2300,7 @@ static void handle_regular (struct receiver_state *rst, nn_etime_t tnow, struct if (rres2 > 0) { if (!pwr->deliver_synchronously) - nn_dqueue_enqueue (pwr->dqueue, &sc, rres2); + nn_dqueue_enqueue1 (pwr->dqueue, &wn->rd_guid, &sc, rres2); else deliver_user_data_synchronously (&sc, &wn->rd_guid); } From 6507859f36db25af1c56ad7d1aa3296860084eec Mon Sep 17 00:00:00 2001 From: Marcel Jordense Date: Fri, 13 Mar 2020 17:49:59 +0100 Subject: [PATCH 125/238] Correct handling of identity certificates with EC key Signed-off-by: Marcel Jordense --- .../authentication/src/auth_utils.c | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/security/builtin_plugins/authentication/src/auth_utils.c b/src/security/builtin_plugins/authentication/src/auth_utils.c index d2ec77a..ef9d768 100644 --- a/src/security/builtin_plugins/authentication/src/auth_utils.c +++ b/src/security/builtin_plugins/authentication/src/auth_utils.c @@ -1288,10 +1288,12 @@ create_asymmetrical_signature( goto err_sign; } - if (EVP_PKEY_CTX_set_rsa_padding(kctx, RSA_PKCS1_PSS_PADDING) < 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to initialize signing context: "); - goto err_sign; + if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { + if (EVP_PKEY_CTX_set_rsa_padding(kctx, RSA_PKCS1_PSS_PADDING) < 1) { + result = DDS_SECURITY_VALIDATION_FAILED; + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to initialize signing context: "); + goto err_sign; + } } if (EVP_DigestSignUpdate(mdctx, data, dataLen) != 1) { @@ -1345,11 +1347,13 @@ validate_asymmetrical_signature( goto err_verify; } - if (EVP_PKEY_CTX_set_rsa_padding(kctx, RSA_PKCS1_PSS_PADDING) < 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to initialize signing context: "); - goto err_verify; - } + if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { + if (EVP_PKEY_CTX_set_rsa_padding(kctx, RSA_PKCS1_PSS_PADDING) < 1) { + result = DDS_SECURITY_VALIDATION_FAILED; + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to initialize signing context: "); + goto err_verify; + } + } if (EVP_DigestVerifyUpdate(mdctx, data, dataLen) != 1) { result = DDS_SECURITY_VALIDATION_FAILED; From 4a6b13412609ba910cb3978539c8e4839ba7af8f Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 14 Mar 2020 10:16:25 +0100 Subject: [PATCH 126/238] Fix passing of "relay_only" in check/register reader * access-control check_remote_datareader has "relay_only" as an out parameter, so should pass in an address instead of "false"; * value of "relay_only" returned by check_remote_datareader must be passed to crypto register_matched_remote_datareader Signed-off-by: Erik Boasson --- .../ddsi/include/dds/ddsi/ddsi_security_omg.h | 20 +++++++++------- src/core/ddsi/src/ddsi_security_omg.c | 24 ++++++++++++------- src/core/ddsi/src/q_entity.c | 5 ++-- 3 files changed, 30 insertions(+), 19 deletions(-) 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 674cd3f..30e2c4a 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h @@ -768,15 +768,17 @@ bool q_omg_reader_is_submessage_protected(const struct reader *rd); * This function will check with the access control plugin if the remote reader * is allowed to communicate with this participant. * - * @param[in] prd The remote reader. - * @param[in] domain_id The domain id. - * @param[in] pp The local participant. + * @param[in] prd The remote reader. + * @param[in] domain_id The domain id. + * @param[in] pp The local participant. + * @param[out] relay_only The "relay_only" value returned by the access control + * operation check_remote_datareader() * * @returns bool * @retval true The remote reader is allowed to communicate. - * @retval false Otherwise. + * @retval false Otherwise; relay_only is unspecified. */ -bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *prd, uint32_t domain_id, struct participant *pp); +bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *prd, uint32_t domain_id, struct participant *pp, bool *relay_only); /** * @brief Check it the local writer is allowed to communicate with the remote reader. @@ -793,13 +795,15 @@ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *p * * @param[in] wr The local writer. * @param[in] prd The remote reader. + * @param[in] relay_only The "relay_only" returned by access control + * operation check_remote_datareader() * @param[out] crypto_handle The crypto handle associated with the match. * * @returns bool * @retval true The local writer and remote reader are allowed to communicate. * @retval false Otherwise. */ -bool q_omg_security_match_remote_reader_enabled(struct writer *wr, struct proxy_reader *prd, int64_t *crypto_handle); +bool q_omg_security_match_remote_reader_enabled(struct writer *wr, struct proxy_reader *prd, bool relay_only, int64_t *crypto_handle); /** * @brief Release the security information associated with the match between a writer and @@ -1226,7 +1230,7 @@ inline bool q_omg_security_match_remote_writer_enabled(UNUSED_ARG(struct reader return true; } -inline bool q_omg_security_match_remote_reader_enabled(UNUSED_ARG(struct writer *wr), UNUSED_ARG(struct proxy_reader *prd), UNUSED_ARG(int64_t *crypto_handle)) +inline bool q_omg_security_match_remote_reader_enabled(UNUSED_ARG(struct writer *wr), UNUSED_ARG(struct proxy_reader *prd), UNUSED_ARG(bool relay_only), UNUSED_ARG(int64_t *crypto_handle)) { return true; } @@ -1274,7 +1278,7 @@ inline bool q_omg_reader_is_submessage_protected(UNUSED_ARG(const struct reader } -inline bool q_omg_security_check_remote_reader_permissions(UNUSED_ARG(const struct proxy_reader *prd), UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(struct participant *pp)) +inline bool q_omg_security_check_remote_reader_permissions(UNUSED_ARG(const struct proxy_reader *prd), UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(struct participant *pp), UNUSED_ARG(bool *relay_only)) { return true; } diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 16da442..7539ea5 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -2149,13 +2149,16 @@ void q_omg_security_deregister_remote_writer_match(const struct ddsi_domaingv *g } } -bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *prd, uint32_t domain_id, struct participant *pp) +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; struct dds_security_context *sc = q_omg_security_get_secure_context(pp); DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; bool ok = true; + /* relay_only is meaningless in all cases except the one where the access control plugin says otherwise */ + *relay_only = false; + if (!sc) return true; @@ -2185,11 +2188,14 @@ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *p else { DDS_Security_SubscriptionBuiltinTopicDataSecure subscription_data; + DDS_Security_boolean sec_relay_only; q_omg_shallow_copy_SubscriptionBuiltinTopicDataSecure(&subscription_data, &prd->e.guid, prd->c.xqos, &prd->security_info); - ok = sc->access_control_context->check_remote_datareader(sc->access_control_context, permissions_handle, (int)domain_id, &subscription_data, false, &exception); + ok = sc->access_control_context->check_remote_datareader(sc->access_control_context, permissions_handle, (int)domain_id, &subscription_data, &sec_relay_only, &exception); q_omg_shallow_free_SubscriptionBuiltinTopicDataSecure(&subscription_data); - if (!ok) + if (ok) + *relay_only = !!sec_relay_only; + else { if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, subscription_data.topic_name)) EXCEPTION_ERROR(sc, &exception, "Access control does not allow remote reader "PGUIDFMT": %s", PGUID(prd->e.guid)); @@ -2349,7 +2355,7 @@ static void send_writer_crypto_tokens(struct writer *wr, struct proxy_reader *pr } } -static bool q_omg_security_register_remote_reader_match(struct proxy_reader *prd, struct writer *wr, int64_t *crypto_handle) +static bool q_omg_security_register_remote_reader_match(struct proxy_reader *prd, struct writer *wr, int64_t *crypto_handle, bool relay_only) { struct participant *pp = wr->c.pp; struct proxy_participant *proxypp = prd->c.proxypp; @@ -2380,7 +2386,7 @@ static bool q_omg_security_register_remote_reader_match(struct proxy_reader *prd { /* 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, false, &exception); + sc->crypto_context->crypto_key_factory, wr->sec_attr->crypto_handle, proxypp->sec_attr->crypto_handle, pm->shared_secret, relay_only, &exception); *crypto_handle = match->crypto_handle; @@ -2421,7 +2427,7 @@ static bool q_omg_security_register_remote_reader_match(struct proxy_reader *prd return match->matched; } -bool q_omg_security_match_remote_reader_enabled(struct writer *wr, struct proxy_reader *prd, int64_t *crypto_handle) +bool q_omg_security_match_remote_reader_enabled(struct writer *wr, struct proxy_reader *prd, bool relay_only, int64_t *crypto_handle) { struct ddsi_domaingv *gv = wr->e.gv; nn_security_info_t info; @@ -2474,7 +2480,7 @@ bool q_omg_security_match_remote_reader_enabled(struct writer *wr, struct proxy_ prd->security_info.plugin_security_attributes = info.plugin_security_attributes; } - return q_omg_security_register_remote_reader_match(prd, wr, crypto_handle); + return q_omg_security_register_remote_reader_match(prd, wr, crypto_handle, relay_only); } void q_omg_security_set_remote_writer_crypto_tokens(struct reader *rd, const ddsi_guid_t *pwr_guid, const nn_dataholderseq_t *tokens) @@ -3673,7 +3679,7 @@ extern inline bool q_omg_proxy_participant_is_secure(UNUSED_ARG(const struct pro extern inline unsigned determine_subscription_writer(UNUSED_ARG(const struct reader *rd)); extern inline bool q_omg_security_match_remote_writer_enabled(UNUSED_ARG(struct reader *rd), UNUSED_ARG(struct proxy_writer *pwr), UNUSED_ARG(int64_t *crypto_handle)); -extern inline bool q_omg_security_match_remote_reader_enabled(UNUSED_ARG(struct writer *wr), UNUSED_ARG(struct proxy_reader *prd), UNUSED_ARG(int64_t *crypto_handle)); +extern inline bool q_omg_security_match_remote_reader_enabled(UNUSED_ARG(struct writer *wr), UNUSED_ARG(struct proxy_reader *prd), UNUSED_ARG(bool relay_only), UNUSED_ARG(int64_t *crypto_handle)); extern inline bool q_omg_writer_is_discovery_protected(UNUSED_ARG(const struct writer *wr)); extern inline bool q_omg_writer_is_submessage_protected(UNUSED_ARG(const struct writer *wr)); @@ -3683,7 +3689,7 @@ extern inline void q_omg_get_proxy_writer_security_info(UNUSED_ARG(struct proxy_ extern inline bool q_omg_security_check_remote_writer_permissions(UNUSED_ARG(const struct proxy_writer *pwr), UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(struct participant *pp)); extern inline void q_omg_security_deregister_remote_writer_match(UNUSED_ARG(const struct proxy_writer *pwr), UNUSED_ARG(const struct reader *rd), UNUSED_ARG(struct rd_pwr_match *match)); extern inline void q_omg_get_proxy_reader_security_info(UNUSED_ARG(struct proxy_reader *prd), UNUSED_ARG(const ddsi_plist_t *plist), UNUSED_ARG(nn_security_info_t *info)); -extern inline bool q_omg_security_check_remote_reader_permissions(UNUSED_ARG(const struct proxy_reader *prd), UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(struct participant *par)); +extern inline bool q_omg_security_check_remote_reader_permissions(UNUSED_ARG(const struct proxy_reader *prd), UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(struct participant *par), UNUSED_ARG(bool *relay_only)); extern inline void q_omg_security_deregister_remote_reader_match(UNUSED_ARG(const struct proxy_reader *prd), UNUSED_ARG(const struct writer *wr), UNUSED_ARG(struct wr_prd_match *match)); extern inline unsigned determine_publication_writer(UNUSED_ARG(const struct writer *wr)); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index d7b5c46..474b8a5 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -2767,6 +2767,7 @@ static void connect_writer_with_proxy_reader (struct writer *wr, struct proxy_re const int isb1 = (is_builtin_entityid (prd->e.guid.entityid, prd->c.vendor) != 0); dds_qos_policy_id_t reason; int64_t crypto_handle; + bool relay_only; DDSRT_UNUSED_ARG(tnow); if (isb0 != isb1) @@ -2779,12 +2780,12 @@ static void connect_writer_with_proxy_reader (struct writer *wr, struct proxy_re return; } - if (!q_omg_security_check_remote_reader_permissions (prd, wr->e.gv->config.domainId, wr->c.pp)) + if (!q_omg_security_check_remote_reader_permissions (prd, wr->e.gv->config.domainId, wr->c.pp, &relay_only)) { EELOGDISC (&wr->e, "connect_writer_with_proxy_reader (wr "PGUIDFMT") with (prd "PGUIDFMT") not allowed by security\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); } - else if (!q_omg_security_match_remote_reader_enabled (wr, prd, &crypto_handle)) + else if (!q_omg_security_match_remote_reader_enabled (wr, prd, relay_only, &crypto_handle)) { EELOGDISC (&wr->e, "connect_writer_with_proxy_reader (wr "PGUIDFMT") with (prd "PGUIDFMT") waiting for approval by security\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); From 0354b42cdcacd26b25405099fcb8426a5c05fa67 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 14 Mar 2020 10:19:55 +0100 Subject: [PATCH 127/238] Check for permissions handle by testing for != 0 The test gates access-control plugin invocation and with the inverted condition all remote readers/writers requiring access control are blocked eiter because of the permissions handle, or because a NIL handle is passed to the access control plugin. Signed-off-by: Erik Boasson --- src/core/ddsi/src/ddsi_security_omg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 7539ea5..06b6dab 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -1956,7 +1956,7 @@ bool q_omg_security_check_remote_writer_permissions(const struct proxy_writer *p { DDS_Security_PermissionsHandle permissions_handle; - if ((permissions_handle = get_permissions_handle(pp, pwr->c.proxypp)) != 0) + if ((permissions_handle = get_permissions_handle(pp, pwr->c.proxypp)) == 0) { GVTRACE("Secure remote writer "PGUIDFMT" proxypp does not have permissions handle yet\n", PGUID(pwr->e.guid)); return false; @@ -2180,7 +2180,7 @@ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *p { DDS_Security_PermissionsHandle permissions_handle; - if ((permissions_handle = get_permissions_handle(pp, prd->c.proxypp)) != 0) + if ((permissions_handle = get_permissions_handle(pp, prd->c.proxypp)) == 0) { GVTRACE("Secure remote reader "PGUIDFMT" proxypp does not have permissions handle yet\n", PGUID(prd->e.guid)); return false; From 3ea2cea318d760aebaf43b99b73b441955fb91b5 Mon Sep 17 00:00:00 2001 From: Dennis Potman <45659984+dennis-adlink@users.noreply.github.com> Date: Wed, 18 Mar 2020 10:01:20 +0100 Subject: [PATCH 128/238] Code formatting fixes and clean-up authentication plugin (#439) * Fix code formatting, fix for memory leak in validate_handshake_reply_token and make error handling and return values more consistent with the other two plugins. Signed-off-by: Dennis Potman * Processed review comments: fixed memory leaks and more consistent error handling and function returns Signed-off-by: Dennis Potman * Fix trusted ca dir max exceeded Signed-off-by: Dennis Potman --- docs/manual/security.rst | 2 + .../dds/security/dds_security_api_err.h | 2 + .../authentication/src/auth_utils.c | 1961 +++---- .../authentication/src/auth_utils.h | 186 +- .../authentication/src/authentication.c | 5021 +++++++---------- .../authentication/src/authentication.h | 152 +- 6 files changed, 2914 insertions(+), 4410 deletions(-) diff --git a/docs/manual/security.rst b/docs/manual/security.rst index 078a013..725de07 100644 --- a/docs/manual/security.rst +++ b/docs/manual/security.rst @@ -793,6 +793,8 @@ dds_security_api_err.h header file contains the code and message constants. +-------+----------------------------------------------------------------+ | 151 | The payload is not aligned at 4 bytes | +-------+----------------------------------------------------------------+ +| 152 | Cannot open trusted CA directory: maximum number exceeded | ++-------+----------------------------------------------------------------+ | 200 | Undefined Error Message | +-------+----------------------------------------------------------------+ diff --git a/src/security/api/include/dds/security/dds_security_api_err.h b/src/security/api/include/dds/security/dds_security_api_err.h index 9246ba5..b93cc62 100644 --- a/src/security/api/include/dds/security/dds_security_api_err.h +++ b/src/security/api/include/dds/security/dds_security_api_err.h @@ -106,6 +106,8 @@ extern "C" { #define DDS_SECURITY_ERR_URI_TYPE_NOT_SUPPORTED_MESSAGE "Unsupported URI type: %s" #define DDS_SECURITY_ERR_INVALID_CRYPTO_DATA_NOT_ALIGNED_CODE 151 #define DDS_SECURITY_ERR_INVALID_CRYPTO_DATA_NOT_ALIGNED_MESSAGE "The payload is not aligned at 4 bytes" +#define DDS_SECURITY_ERR_TRUSTED_CA_DIR_MAX_EXCEEDED_CODE 152 +#define DDS_SECURITY_ERR_TRUSTED_CA_DIR_MAX_EXCEEDED_MESSAGE "Cannot open trusted CA directory: maximum number of CA directories (%d) exceeded" #define DDS_SECURITY_ERR_UNDEFINED_CODE 200 #define DDS_SECURITY_ERR_UNDEFINED_MESSAGE "Undefined Error Message" diff --git a/src/security/builtin_plugins/authentication/src/auth_utils.c b/src/security/builtin_plugins/authentication/src/auth_utils.c index ef9d768..54e94b2 100644 --- a/src/security/builtin_plugins/authentication/src/auth_utils.c +++ b/src/security/builtin_plugins/authentication/src/auth_utils.c @@ -10,6 +10,8 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ +#include +#include #include #include #include @@ -18,6 +20,7 @@ #include #include #include +#include #if OPENSSL_VERSION_NUMBER >= 0x1000200fL #define AUTH_INCLUDE_EC #include @@ -27,15 +30,17 @@ #else #error "OpenSSL version is not supported" #endif -#include #include "dds/ddsrt/time.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/filesystem.h" #include "dds/ddsrt/retcode.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/atomics.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/io.h" #include "dds/security/dds_security_api_defs.h" #include "dds/security/core/dds_security_utils.h" -#include - +#include "auth_utils.h" /* There is a problem when compiling on windows w.r.t. X509_NAME. * The windows api already defines the type X509_NAME which @@ -46,1329 +51,999 @@ #undef X509_NAME #endif -#include "dds/ddsrt/heap.h" -#include "dds/ddsrt/atomics.h" -#include "dds/ddsrt/string.h" -#include "dds/ddsrt/io.h" -#include "dds/security/core/dds_security_utils.h" -#include -#include "auth_utils.h" - #define MAX_TRUSTED_CA 100 -char * -get_openssl_error_message( - void) +char *get_openssl_error_message(void) { - BIO *bio = BIO_new(BIO_s_mem()); - char *msg; - char *buf = NULL; - size_t len; /*BIO_get_mem_data requires long int */ + char *msg, *buf = NULL; + size_t len; + BIO *bio = BIO_new(BIO_s_mem()); + if (!bio) + return ddsrt_strdup("BIO_new failed"); - if (bio) { - ERR_print_errors(bio); - len = (size_t)BIO_get_mem_data (bio, &buf); - msg = ddsrt_malloc(len + 1); - memcpy(msg, buf, len); - msg[len] = '\0'; - BIO_free(bio); - } else { - msg = ddsrt_strdup("BIO_new failed"); - } - - return msg; + ERR_print_errors(bio); + len = (size_t)BIO_get_mem_data(bio, &buf); + msg = ddsrt_malloc(len + 1); + memcpy(msg, buf, len); + msg[len] = '\0'; + BIO_free(bio); + return msg; } -char * -get_certificate_subject_name( - X509 *cert, - DDS_Security_SecurityException *ex) +char *get_certificate_subject_name(X509 *cert, DDS_Security_SecurityException *ex) { - X509_NAME *name; - char *subject = NULL; - char *subject_openssl = NULL; - - assert(cert); - - name = X509_get_subject_name(cert); - if (!name) { - goto err_get_subject; - } - - subject_openssl = X509_NAME_oneline( name, NULL, 0 ); - subject = ddsrt_strdup( subject_openssl ); - OPENSSL_free( subject_openssl ); - - return subject; - -err_get_subject: + X509_NAME *name; + assert(cert); + if (!(name = X509_get_subject_name(cert))) + { DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "X509_get_subject_name failed : "); return NULL; + } + char *subject_openssl = X509_NAME_oneline(name, NULL, 0); + char *subject = ddsrt_strdup(subject_openssl); + OPENSSL_free(subject_openssl); + return subject; } -dds_time_t -get_certificate_expiry( - const X509 *cert) +dds_time_t get_certificate_expiry(const X509 *cert) { - dds_time_t expiry = DDS_TIME_INVALID; - ASN1_TIME *asn1; - - assert(cert); - - asn1 = X509_get_notAfter(cert); - if (asn1 != NULL) { - int days; - int seconds; - if (ASN1_TIME_diff(&days, &seconds, NULL, asn1) == 1 ) { - static const dds_duration_t secs_in_day = 86400; - const dds_time_t now = dds_time(); - const int64_t max_valid_days_to_wait = (INT64_MAX - now) / DDS_NSECS_IN_SEC / secs_in_day; - - if ( days < max_valid_days_to_wait ){ - dds_duration_t delta = ((dds_duration_t)seconds + ((dds_duration_t)days * secs_in_day)) * DDS_NSECS_IN_SEC; - expiry = now + delta; - } else { - return DDS_NEVER; - } - } + assert(cert); + ASN1_TIME *asn1 = X509_get_notAfter(cert); + if (asn1 != NULL) + { + int days, seconds; + if (ASN1_TIME_diff(&days, &seconds, NULL, asn1) == 1) + { + static const dds_duration_t secs_in_day = 86400; + const dds_time_t now = dds_time(); + const int64_t max_valid_days_to_wait = (INT64_MAX - now) / DDS_NSECS_IN_SEC / secs_in_day; + if (days < max_valid_days_to_wait) + { + dds_duration_t delta = ((dds_duration_t)seconds + ((dds_duration_t)days * secs_in_day)) * DDS_NSECS_IN_SEC; + return now + delta; + } + return DDS_NEVER; } - - return expiry; + } + return DDS_TIME_INVALID; } -DDS_Security_ValidationResult_t -get_subject_name_DER_encoded( - const X509 *cert, - unsigned char **buffer, - size_t *size, - DDS_Security_SecurityException *ex) +DDS_Security_ValidationResult_t get_subject_name_DER_encoded(const X509 *cert, unsigned char **buffer, size_t *size, DDS_Security_SecurityException *ex) { - unsigned char *tmp = NULL; - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_FAILED; - int32_t sz; - X509_NAME *name; + unsigned char *tmp = NULL; + int32_t sz; + X509_NAME *name; - assert(cert); - assert(buffer); - assert(size); + assert(cert); + assert(buffer); + assert(size); - *size = 0; + *size = 0; + if (!(name = X509_get_subject_name((X509 *)cert))) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "X509_get_subject_name failed : "); + return DDS_SECURITY_VALIDATION_FAILED; + } + if ((sz = i2d_X509_NAME(name, &tmp)) <= 0) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "i2d_X509_NAME failed : "); + return DDS_SECURITY_VALIDATION_FAILED; + } - name = X509_get_subject_name((X509 *)cert); - if (name) { - sz = i2d_X509_NAME(name, &tmp); - if (sz > 0) { - *size = (size_t)sz; - *buffer = ddsrt_malloc(*size); - memcpy(*buffer, tmp, *size); - OPENSSL_free(tmp); - result = DDS_SECURITY_VALIDATION_OK; - } else if (sz < 0) { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "i2d_X509_NAME failed : "); - } - } else { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "X509_get_subject_name failed : "); - } - - return result; + *size = (size_t)sz; + *buffer = ddsrt_malloc(*size); + memcpy(*buffer, tmp, *size); + OPENSSL_free(tmp); + return DDS_SECURITY_VALIDATION_OK; } - -static DDS_Security_ValidationResult_t -check_key_type_and_size( - EVP_PKEY *key, - int isPrivate, - DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t check_key_type_and_size(EVP_PKEY *key, int isPrivate, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - const char *sub = isPrivate ? "private key" : "certificate"; - - assert(key); - - switch (EVP_PKEY_id(key)) { - case EVP_PKEY_RSA: - if (EVP_PKEY_bits(key) != 2048) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "RSA %s has unsupported key size (%d)", sub, EVP_PKEY_bits(key)); - } else if (isPrivate) { - RSA *rsaKey = EVP_PKEY_get1_RSA(key); - if (rsaKey) { - if (RSA_check_key(rsaKey) != 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "RSA key not correct : "); - } - } - RSA_free(rsaKey); - } - break; - case EVP_PKEY_EC: - if (EVP_PKEY_bits(key) != 256) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "EC %s has unsupported key size (%d)", sub, EVP_PKEY_bits(key)); - } else { - EC_KEY *ecKey = EVP_PKEY_get1_EC_KEY(key); - if (ecKey) { - if (EC_KEY_check_key(ecKey) != 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "EC key not correct : "); - } - } - EC_KEY_free(ecKey); - } - break; - default: - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "%s has not supported type", sub); - break; + const char *sub = isPrivate ? "private key" : "certificate"; + assert(key); + switch (EVP_PKEY_id(key)) + { + case EVP_PKEY_RSA: + if (EVP_PKEY_bits(key) != 2048) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "RSA %s has unsupported key size (%d)", sub, EVP_PKEY_bits(key)); + return DDS_SECURITY_VALIDATION_FAILED; } + if (isPrivate) + { + RSA *rsaKey = EVP_PKEY_get0_RSA(key); + if (rsaKey && RSA_check_key(rsaKey) != 1) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "RSA key not correct : "); + return DDS_SECURITY_VALIDATION_FAILED; + } + } + return DDS_SECURITY_VALIDATION_OK; - return result; + case EVP_PKEY_EC: + if (EVP_PKEY_bits(key) != 256) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "EC %s has unsupported key size (%d)", sub, EVP_PKEY_bits(key)); + return DDS_SECURITY_VALIDATION_FAILED; + } + EC_KEY *ecKey = EVP_PKEY_get0_EC_KEY(key); + if (ecKey && EC_KEY_check_key(ecKey) != 1) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "EC key not correct : "); + return DDS_SECURITY_VALIDATION_FAILED; + } + return DDS_SECURITY_VALIDATION_OK; + + default: + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "%s has not supported type", sub); + return DDS_SECURITY_VALIDATION_FAILED; + } } -static DDS_Security_ValidationResult_t -check_certificate_type_and_size( - X509 *cert, - DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t check_certificate_type_and_size(X509 *cert, DDS_Security_SecurityException *ex) { - EVP_PKEY *pkey; - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - - assert(cert); - - pkey = X509_get_pubkey(cert); - if (pkey) { - result = check_key_type_and_size(pkey, false, ex); - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "X509_get_pubkey failed"); - } - EVP_PKEY_free(pkey); - - return result; + assert(cert); + EVP_PKEY *pkey = X509_get_pubkey(cert); + if (!pkey) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "X509_get_pubkey failed"); + return DDS_SECURITY_VALIDATION_FAILED; + } + DDS_Security_ValidationResult_t result = check_key_type_and_size(pkey, false, ex); + EVP_PKEY_free(pkey); + return result; } -DDS_Security_ValidationResult_t -check_certificate_expiry( - const X509 *cert, - DDS_Security_SecurityException *ex) +DDS_Security_ValidationResult_t check_certificate_expiry(const X509 *cert, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - - assert(cert); - - if( X509_cmp_current_time(X509_get_notBefore( cert )) == 0 ){ - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CERT_STARTDATE_IN_FUTURE_CODE, (int)result, DDS_SECURITY_ERR_CERT_STARTDATE_IN_FUTURE_MESSAGE); - - } - if( X509_cmp_current_time(X509_get_notAfter( cert )) == 0 ){ - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CERT_EXPIRED_CODE, (int)result, DDS_SECURITY_ERR_CERT_EXPIRED_MESSAGE); - - } - - return result; + assert(cert); + if (X509_cmp_current_time(X509_get_notBefore(cert)) == 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CERT_STARTDATE_IN_FUTURE_CODE, DDS_SECURITY_VALIDATION_FAILED, DDS_SECURITY_ERR_CERT_STARTDATE_IN_FUTURE_MESSAGE); + return DDS_SECURITY_VALIDATION_FAILED; + } + if (X509_cmp_current_time(X509_get_notAfter(cert)) == 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CERT_EXPIRED_CODE, DDS_SECURITY_VALIDATION_FAILED, DDS_SECURITY_ERR_CERT_EXPIRED_MESSAGE); + return DDS_SECURITY_VALIDATION_FAILED; + } + return DDS_SECURITY_VALIDATION_OK; } - -DDS_Security_ValidationResult_t -load_X509_certificate_from_data( - const char *data, - int len, - X509 **x509Cert, - DDS_Security_SecurityException *ex) +DDS_Security_ValidationResult_t load_X509_certificate_from_data(const char *data, int len, X509 **x509Cert, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - BIO *bio; + BIO *bio; + assert(data); + assert(len >= 0); + assert(x509Cert); - assert(data); - assert(len >= 0); - assert(x509Cert); - - /* load certificate in buffer */ - bio = BIO_new_mem_buf((void *) data, len); - if (!bio) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "BIO_new_mem_buf failed"); - goto err_bio_alloc; - } - - *x509Cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); - if (!(*x509Cert)) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to parse certificate: "); - goto err_cert_read; - } - - /* check authentication algorithm */ - if( get_auhentication_algo_kind( *x509Cert ) == AUTH_ALGO_KIND_UNKNOWN ){ - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CERT_AUTH_ALGO_KIND_UNKNOWN_CODE, (int)result, - DDS_SECURITY_ERR_CERT_AUTH_ALGO_KIND_UNKNOWN_MESSAGE); - X509_free(*x509Cert); - goto err_cert_read; - } - -err_cert_read: + if (!(bio = BIO_new_mem_buf((void *)data, len))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "BIO_new_mem_buf failed"); + return DDS_SECURITY_VALIDATION_FAILED; + } + if (!(*x509Cert = PEM_read_bio_X509(bio, NULL, NULL, NULL))) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to parse certificate: "); BIO_free(bio); -err_bio_alloc: - return result; + return DDS_SECURITY_VALIDATION_FAILED; + } + BIO_free(bio); + + if (get_authentication_algo_kind(*x509Cert) == AUTH_ALGO_KIND_UNKNOWN) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CERT_AUTH_ALGO_KIND_UNKNOWN_CODE, DDS_SECURITY_VALIDATION_FAILED, DDS_SECURITY_ERR_CERT_AUTH_ALGO_KIND_UNKNOWN_MESSAGE); + X509_free(*x509Cert); + return DDS_SECURITY_VALIDATION_FAILED; + } + + return DDS_SECURITY_VALIDATION_OK; } - - -DDS_Security_ValidationResult_t -load_X509_certificate_from_file( - const char *filename, - X509 **x509Cert, - DDS_Security_SecurityException *ex) +DDS_Security_ValidationResult_t load_X509_certificate_from_file(const char *filename, X509 **x509Cert, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - FILE *file_ptr; + assert(filename); + assert(x509Cert); - assert(filename); - assert(x509Cert); - - /*check the file*/ DDSRT_WARNING_MSVC_OFF(4996); - file_ptr = fopen( filename, "r"); + FILE *file_ptr = fopen(filename, "r"); DDSRT_WARNING_MSVC_ON(4996); - if( file_ptr == NULL ){ - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE, (int)result, DDS_SECURITY_ERR_INVALID_FILE_PATH_MESSAGE, filename); - goto err_invalid_path; - } + if (file_ptr == NULL) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE, DDS_SECURITY_VALIDATION_FAILED, DDS_SECURITY_ERR_INVALID_FILE_PATH_MESSAGE, filename); + return DDS_SECURITY_VALIDATION_FAILED; + } + if (!(*x509Cert = PEM_read_X509(file_ptr, NULL, NULL, NULL))) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to parse certificate: "); + (void)fclose(file_ptr); + return DDS_SECURITY_VALIDATION_FAILED; + } + (void)fclose(file_ptr); - /*load certificate from file*/ - *x509Cert = PEM_read_X509(file_ptr,NULL,NULL,NULL); - if (!(*x509Cert)) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to parse certificate: "); - goto err_invalid_content; - } + if (get_authentication_algo_kind(*x509Cert) == AUTH_ALGO_KIND_UNKNOWN) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CERT_AUTH_ALGO_KIND_UNKNOWN_CODE, DDS_SECURITY_VALIDATION_FAILED, DDS_SECURITY_ERR_CERT_AUTH_ALGO_KIND_UNKNOWN_MESSAGE); + X509_free(*x509Cert); + return DDS_SECURITY_VALIDATION_FAILED; + } - /* check authentication algorithm */ - if( get_auhentication_algo_kind( *x509Cert ) == AUTH_ALGO_KIND_UNKNOWN ){ - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CERT_AUTH_ALGO_KIND_UNKNOWN_CODE, (int)result, - DDS_SECURITY_ERR_CERT_AUTH_ALGO_KIND_UNKNOWN_MESSAGE); - X509_free(*x509Cert); - goto err_invalid_content; - } - - -err_invalid_content: - (void)fclose( file_ptr ); -err_invalid_path: - - return result; + return DDS_SECURITY_VALIDATION_OK; } -static DDS_Security_ValidationResult_t -load_private_key_from_data( - const char *data, - const char *password, - EVP_PKEY **privateKey, - DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t load_private_key_from_data(const char *data, const char *password, EVP_PKEY **privateKey, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - BIO *bio; - const char *pw = (password ? password : ""); + BIO *bio; + assert(data); + assert(privateKey); - assert(data); - assert(privateKey); - - /* load certificate in buffer */ - bio = BIO_new_mem_buf((void *) data, -1); - if (!bio) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "BIO_new_mem_buf failed"); - goto err_bio_alloc; - } - - *privateKey = PEM_read_bio_PrivateKey(bio, NULL, NULL, (void *)pw); - if (!(*privateKey)) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to parse private key: "); - goto err_key_read; - } - -err_key_read: + if (!(bio = BIO_new_mem_buf((void *)data, -1))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "BIO_new_mem_buf failed"); + return DDS_SECURITY_VALIDATION_FAILED; + } + if (!(*privateKey = PEM_read_bio_PrivateKey(bio, NULL, NULL, (void *)(password ? password : "")))) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to parse private key: "); BIO_free(bio); -err_bio_alloc: - return result; + return DDS_SECURITY_VALIDATION_FAILED; + } + + BIO_free(bio); + return DDS_SECURITY_VALIDATION_OK; } - -static DDS_Security_ValidationResult_t -load_private_key_from_file( - const char *filepath, - const char *password, - EVP_PKEY **privateKey, - DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t load_private_key_from_file(const char *filepath, const char *password, EVP_PKEY **privateKey, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - const char *pw = (password ? password : ""); - FILE *file_ptr; + FILE *file_ptr; + assert(filepath); + assert(privateKey); - assert(filepath); - assert(privateKey); - - /*check the file*/ DDSRT_WARNING_MSVC_OFF(4996); - file_ptr = fopen( filepath, "r"); + file_ptr = fopen(filepath, "r"); DDSRT_WARNING_MSVC_ON(4996); + if (file_ptr == NULL) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE, DDS_SECURITY_VALIDATION_FAILED, DDS_SECURITY_ERR_INVALID_FILE_PATH_MESSAGE, filepath); + return DDS_SECURITY_VALIDATION_FAILED; + } + if (!(*privateKey = PEM_read_PrivateKey(file_ptr, NULL, NULL, (void *)(password ? password : "")))) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to parse certificate: "); + (void)fclose(file_ptr); + return DDS_SECURITY_VALIDATION_FAILED; + } - if( file_ptr == NULL ){ - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_FILE_PATH_CODE, (int)result, DDS_SECURITY_ERR_INVALID_FILE_PATH_MESSAGE, filepath); - goto err_invalid_path; - } - - /*load private key from file*/ - *privateKey = PEM_read_PrivateKey(file_ptr, NULL, NULL, (void *)pw); - if (!(*privateKey)) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to parse certificate: "); - goto err_invalid_content; - } - -err_invalid_content: - (void)fclose( file_ptr ); -err_invalid_path: - - return result; + (void)fclose(file_ptr); + return DDS_SECURITY_VALIDATION_OK; } - /* * Gets the URI string (as referred in DDS Security spec) and returns the URI type * data: data part of the URI. Typically It contains different format according to URI type. */ -AuthConfItemPrefix_t -get_conf_item_type( - const char *str, - char **data) +AuthConfItemPrefix_t get_conf_item_type(const char *str, char **data) { - AuthConfItemPrefix_t kind = AUTH_CONF_ITEM_PREFIX_UNKNOWN; - const char *AUTH_CONF_FILE_PREFIX = "file:"; - const char *AUTH_CONF_DATA_PREFIX = "data:,"; - const char *AUTH_CONF_PKCS11_PREFIX = "pkcs11:"; - size_t AUTH_CONF_FILE_PREFIX_LEN = strlen(AUTH_CONF_FILE_PREFIX); - size_t AUTH_CONF_DATA_PREFIX_LEN = strlen(AUTH_CONF_DATA_PREFIX); - size_t AUTH_CONF_PKCS11_PREFIX_LEN = strlen(AUTH_CONF_PKCS11_PREFIX); - char *ptr; + const char *f = "file:", *d = "data:,", *p = "pkcs11:"; + size_t sf = strlen(f), sd = strlen(d), sp = strlen(p); + assert(str); + assert(data); - assert(str); - assert(data); + char *ptr = ddssec_strchrs(str, " \t", false); + if (strncmp(ptr, f, sf) == 0) + { + size_t e = strncmp(ptr + sf, "//", 2) == 0 ? 2 : 0; + *data = ddsrt_strdup(ptr + sf + e); + return AUTH_CONF_ITEM_PREFIX_FILE; + } + if (strncmp(ptr, d, sd) == 0) + { + *data = ddsrt_strdup(ptr + sd); + return AUTH_CONF_ITEM_PREFIX_DATA; + } + if (strncmp(ptr, p, sp) == 0) + { + *data = ddsrt_strdup(ptr + sp); + return AUTH_CONF_ITEM_PREFIX_PKCS11; + } - ptr = ddssec_strchrs(str, " \t", false); - - if (strncmp(ptr, AUTH_CONF_FILE_PREFIX, AUTH_CONF_FILE_PREFIX_LEN) == 0) { - const char *DOUBLE_SLASH = "//"; - size_t DOUBLE_SLASH_LEN = 2; - if (strncmp(&(ptr[AUTH_CONF_FILE_PREFIX_LEN]), DOUBLE_SLASH, DOUBLE_SLASH_LEN) == 0) { - *data = ddsrt_strdup(&(ptr[AUTH_CONF_FILE_PREFIX_LEN + DOUBLE_SLASH_LEN])); - } else { - *data = ddsrt_strdup(&(ptr[AUTH_CONF_FILE_PREFIX_LEN])); - } - kind = AUTH_CONF_ITEM_PREFIX_FILE; - } else if (strncmp(ptr, AUTH_CONF_DATA_PREFIX, AUTH_CONF_DATA_PREFIX_LEN) == 0) { - kind = AUTH_CONF_ITEM_PREFIX_DATA; - *data = ddsrt_strdup(&(ptr[AUTH_CONF_DATA_PREFIX_LEN])); - } else if (strncmp(ptr, AUTH_CONF_PKCS11_PREFIX, AUTH_CONF_PKCS11_PREFIX_LEN) == 0) { - kind = AUTH_CONF_ITEM_PREFIX_PKCS11; - *data = ddsrt_strdup(&(ptr[AUTH_CONF_PKCS11_PREFIX_LEN])); - } - - return kind; + return AUTH_CONF_ITEM_PREFIX_UNKNOWN; } -DDS_Security_ValidationResult_t -load_X509_certificate( - const char *data, - X509 **x509Cert, - DDS_Security_SecurityException *ex) +DDS_Security_ValidationResult_t load_X509_certificate(const char *data, X509 **x509Cert, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - char *contents = NULL; + DDS_Security_ValidationResult_t result; + char *contents = NULL; + assert(data); + assert(x509Cert); - assert(data); - assert(x509Cert); + switch (get_conf_item_type(data, &contents)) + { + case AUTH_CONF_ITEM_PREFIX_FILE: + result = load_X509_certificate_from_file(contents, x509Cert, ex); + break; + case AUTH_CONF_ITEM_PREFIX_DATA: + result = load_X509_certificate_from_data(contents, (int)strlen(contents), x509Cert, ex); + break; + case AUTH_CONF_ITEM_PREFIX_PKCS11: + result = DDS_SECURITY_VALIDATION_FAILED; + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Certificate pkcs11 format currently not supported:\n%s", data); + break; + default: + result = DDS_SECURITY_VALIDATION_FAILED; + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Specified certificate has wrong format:\n%s", data); + break; + } + ddsrt_free(contents); - switch (get_conf_item_type(data, &contents)) { - case AUTH_CONF_ITEM_PREFIX_FILE: - result = load_X509_certificate_from_file(contents, x509Cert, ex); - break; - case AUTH_CONF_ITEM_PREFIX_DATA: - result = load_X509_certificate_from_data(contents, (int)strlen(contents), x509Cert, ex); - break; - case AUTH_CONF_ITEM_PREFIX_PKCS11: - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Certificate pkcs11 format currently not supported:\n%s", data); - break; - default: - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Specified certificate has wrong format:\n%s", data); - break; + if (result == DDS_SECURITY_VALIDATION_OK) + { + if (check_certificate_type_and_size(*x509Cert, ex) != DDS_SECURITY_VALIDATION_OK || + check_certificate_expiry(*x509Cert, ex) != DDS_SECURITY_VALIDATION_OK) + { + result = DDS_SECURITY_VALIDATION_FAILED; + X509_free(*x509Cert); } - ddsrt_free(contents); - - if (result == DDS_SECURITY_VALIDATION_OK) { - if ( check_certificate_type_and_size(*x509Cert, ex) != DDS_SECURITY_VALIDATION_OK || - check_certificate_expiry(*x509Cert, ex) != DDS_SECURITY_VALIDATION_OK - ) { - result = DDS_SECURITY_VALIDATION_FAILED; - X509_free(*x509Cert); - } - } - return result; + } + return result; } -DDS_Security_ValidationResult_t -load_X509_private_key( - const char *data, - const char *password, - EVP_PKEY **privateKey, - DDS_Security_SecurityException *ex) +DDS_Security_ValidationResult_t load_X509_private_key(const char *data, const char *password, EVP_PKEY **privateKey, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - char *contents = NULL; + DDS_Security_ValidationResult_t result; + char *contents = NULL; + assert(data); + assert(privateKey); - assert(data); - assert(privateKey); + switch (get_conf_item_type(data, &contents)) + { + case AUTH_CONF_ITEM_PREFIX_FILE: + result = load_private_key_from_file(contents, password, privateKey, ex); + break; + case AUTH_CONF_ITEM_PREFIX_DATA: + result = load_private_key_from_data(contents, password, privateKey, ex); + break; + case AUTH_CONF_ITEM_PREFIX_PKCS11: + result = DDS_SECURITY_VALIDATION_FAILED; + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "PrivateKey pkcs11 format currently not supported:\n%s", data); + break; + default: + result = DDS_SECURITY_VALIDATION_FAILED; + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Specified PrivateKey has wrong format:\n%s", data); + break; + } + ddsrt_free(contents); - switch (get_conf_item_type(data, &contents)) { - case AUTH_CONF_ITEM_PREFIX_FILE: - result = load_private_key_from_file(contents, password, privateKey, ex); - break; - case AUTH_CONF_ITEM_PREFIX_DATA: - result = load_private_key_from_data(contents, password, privateKey, ex); - break; - case AUTH_CONF_ITEM_PREFIX_PKCS11: - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "PrivateKey pkcs11 format currently not supported:\n%s", data); - break; - default: - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Specified PrivateKey has wrong format:\n%s", data); - break; + if (result == DDS_SECURITY_VALIDATION_OK) + { + if (check_key_type_and_size(*privateKey, true, ex) != DDS_SECURITY_VALIDATION_OK) + { + result = DDS_SECURITY_VALIDATION_FAILED; + EVP_PKEY_free(*privateKey); } - ddsrt_free(contents); + } - if (result == DDS_SECURITY_VALIDATION_OK) { - if ((result = check_key_type_and_size(*privateKey, true, ex)) != DDS_SECURITY_VALIDATION_OK) { - EVP_PKEY_free(*privateKey); - } - } - - return result; + return result; } -DDS_Security_ValidationResult_t -verify_certificate( - X509 *identityCert, - X509 *identityCa, - DDS_Security_SecurityException *ex) +DDS_Security_ValidationResult_t verify_certificate(X509 *identityCert, X509 *identityCa, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - int r; - X509_STORE *store; - X509_STORE_CTX *ctx; + X509_STORE_CTX *ctx; + X509_STORE *store; + assert(identityCert); + assert(identityCa); + /* Currently only a self signed indentiyCa is supported. Verification of against a certificate chain is not yet supported */ + /* Verification of the certificate expiry using a CRL is not yet supported */ - - assert(identityCert); - assert(identityCa); - - /* Currently only a self signed indentiyCa is supported */ - /* Verification of against a certificate chain is not yet supported */ - /* Verification of the certificate expiry using a CRL is not yet supported */ - - store = X509_STORE_new(); - - - if (!store) { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "X509_STORE_new failed : "); - goto err_store_new; - } - - if (X509_STORE_add_cert(store, identityCa) != 1) { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "X509_STORE_add_cert failed : "); - goto err_add_cert; - } - - ctx = X509_STORE_CTX_new(); - if (!ctx) { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "X509_STORE_CTX_new failed : "); - goto err_ctx_new; - } - - if (X509_STORE_CTX_init(ctx, store, identityCert, NULL) != 1) { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "X509_STORE_CTX_init failed : "); - goto err_ctx_init; - } - - r = X509_verify_cert(ctx); - if (r != 1) { - const char *msg = X509_verify_cert_error_string(X509_STORE_CTX_get_error(ctx)); - char *subject = NULL; - - result = DDS_SECURITY_VALIDATION_FAILED; - subject = get_certificate_subject_name(identityCert, NULL); - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "Certificate not valid: error: %s subject: %s", msg, subject ? subject : "not found"); - ddsrt_free(subject); - } + if (!(store = X509_STORE_new())) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "X509_STORE_new failed : "); + goto err_store_new; + } + if (X509_STORE_add_cert(store, identityCa) != 1) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "X509_STORE_add_cert failed : "); + goto err_add_cert; + } + if (!(ctx = X509_STORE_CTX_new())) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "X509_STORE_CTX_new failed : "); + goto err_ctx_new; + } + if (X509_STORE_CTX_init(ctx, store, identityCert, NULL) != 1) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "X509_STORE_CTX_init failed : "); + goto err_ctx_init; + } + if (X509_verify_cert(ctx) != 1) + { + const char *msg = X509_verify_cert_error_string(X509_STORE_CTX_get_error(ctx)); + char *subject = get_certificate_subject_name(identityCert, NULL); + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Certificate not valid: error: %s; subject: %s", msg, subject ? subject : "[not found]"); + ddsrt_free(subject); + goto err_ctx_init; + } + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + return DDS_SECURITY_VALIDATION_OK; err_ctx_init: - X509_STORE_CTX_free(ctx); + X509_STORE_CTX_free(ctx); err_ctx_new: err_add_cert: - X509_STORE_free(store); + X509_STORE_free(store); err_store_new: - return result; + return DDS_SECURITY_VALIDATION_FAILED; } -AuthenticationAlgoKind_t -get_auhentication_algo_kind( - X509 *cert) +AuthenticationAlgoKind_t get_authentication_algo_kind(X509 *cert) { - AuthenticationAlgoKind_t kind = AUTH_ALGO_KIND_UNKNOWN; - EVP_PKEY *pkey; - - assert(cert); - - pkey = X509_get_pubkey(cert); - - if (pkey) { - switch (EVP_PKEY_id(pkey)) { - case EVP_PKEY_RSA: - if (EVP_PKEY_bits(pkey) == 2048) { - kind = AUTH_ALGO_KIND_RSA_2048; - } - break; - case EVP_PKEY_EC: - if (EVP_PKEY_bits(pkey) == 256) { - kind = AUTH_ALGO_KIND_EC_PRIME256V1; - } - break; - default: - break; - } - EVP_PKEY_free(pkey); + AuthenticationAlgoKind_t kind = AUTH_ALGO_KIND_UNKNOWN; + assert(cert); + EVP_PKEY *pkey = X509_get_pubkey(cert); + if (pkey) + { + switch (EVP_PKEY_id(pkey)) + { + case EVP_PKEY_RSA: + if (EVP_PKEY_bits(pkey) == 2048) + kind = AUTH_ALGO_KIND_RSA_2048; + break; + case EVP_PKEY_EC: + if (EVP_PKEY_bits(pkey) == 256) + kind = AUTH_ALGO_KIND_EC_PRIME256V1; + break; } - - return kind; + EVP_PKEY_free(pkey); + } + return kind; } -AuthenticationChallenge * -generate_challenge( - DDS_Security_SecurityException *ex) +AuthenticationChallenge * generate_challenge(DDS_Security_SecurityException *ex) { - AuthenticationChallenge *result; - - result = ddsrt_malloc(sizeof(*result)); - if (RAND_bytes(result->value, sizeof(result->value)) < 0 ) { - - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "Failed to generate a 256 bit random number "); - ddsrt_free(result); - result = NULL; - } - - return result; + AuthenticationChallenge *result = ddsrt_malloc(sizeof(*result)); + if (RAND_bytes(result->value, sizeof(result->value)) < 0) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to generate a 256 bit random number "); + ddsrt_free(result); + return NULL; + } + return result; } -DDS_Security_ValidationResult_t -get_certificate_contents( - X509 *cert, - unsigned char **data, - uint32_t *size, - DDS_Security_SecurityException *ex) +DDS_Security_ValidationResult_t get_certificate_contents(X509 *cert, unsigned char **data, uint32_t *size, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - BIO *bio = NULL; - size_t sz; - char *ptr; + BIO *bio = NULL; + char *ptr; + if ((bio = BIO_new(BIO_s_mem())) == NULL) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "BIO_new_mem_buf failed"); + return DDS_SECURITY_VALIDATION_FAILED; + } + if (!PEM_write_bio_X509(bio, cert)) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "PEM_write_bio_X509 failed: "); + BIO_free(bio); + return DDS_SECURITY_VALIDATION_FAILED; + } - if ((bio = BIO_new(BIO_s_mem())) == NULL) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "BIO_new_mem_buf failed"); - } else if (!PEM_write_bio_X509(bio, cert)) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "PEM_write_bio_X509 failed: "); - } else { - sz = (size_t)BIO_get_mem_data(bio, &ptr); - *data = ddsrt_malloc(sz +1); - memcpy(*data, ptr, sz); - (*data)[sz] = '\0'; - *size = (uint32_t)sz; - } - - if (bio) BIO_free(bio); - - return result; + size_t sz = (size_t)BIO_get_mem_data(bio, &ptr); + *data = ddsrt_malloc(sz + 1); + memcpy(*data, ptr, sz); + (*data)[sz] = '\0'; + *size = (uint32_t)sz; + BIO_free(bio); + return DDS_SECURITY_VALIDATION_OK; } -static DDS_Security_ValidationResult_t -get_rsa_dh_parameters( - EVP_PKEY **params, - DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t get_rsa_dh_parameters(EVP_PKEY **params, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - DH *dh = NULL; + DH *dh = NULL; + *params = NULL; + if ((*params = EVP_PKEY_new()) == NULL) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to allocate DH generation parameters: "); + return DDS_SECURITY_VALIDATION_FAILED; + } + if ((dh = DH_get_2048_256()) == NULL) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to allocate DH parameter using DH_get_2048_256: "); + EVP_PKEY_free(*params); + return DDS_SECURITY_VALIDATION_FAILED; + } + if (EVP_PKEY_set1_DH(*params, dh) <= 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to set DH generation parameters using EVP_PKEY_set1_DH: "); + EVP_PKEY_free(*params); + DH_free(dh); + return DDS_SECURITY_VALIDATION_FAILED; + } - *params = NULL; - - if ((*params = EVP_PKEY_new()) == NULL) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "Failed to allocate DH generation parameters: "); - } else if ((dh = DH_get_2048_256()) == NULL) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "Failed to allocate DH parameter using DH_get_2048_256: "); - } else if (EVP_PKEY_set1_DH(*params, dh) <= 0) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "Failed to set DH generation parameters using EVP_PKEY_set1_DH: "); - EVP_PKEY_free(*params); - } - - if (dh) DH_free(dh); - - return result; + DH_free(dh); + return DDS_SECURITY_VALIDATION_OK; } -static DDS_Security_ValidationResult_t -get_ec_dh_parameters( - EVP_PKEY **params, - DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t get_ec_dh_parameters(EVP_PKEY **params, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY_CTX *pctx = NULL; + if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to allocate DH parameter context: "); + return DDS_SECURITY_VALIDATION_FAILED; + } + if (EVP_PKEY_paramgen_init(pctx) <= 0) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to initialize DH generation context: "); + EVP_PKEY_CTX_free(pctx); + return DDS_SECURITY_VALIDATION_FAILED; + } + if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1) <= 0) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to set DH generation parameter generation method: "); + EVP_PKEY_CTX_free(pctx); + return DDS_SECURITY_VALIDATION_FAILED; + } + if (EVP_PKEY_paramgen(pctx, params) <= 0) + { + char *msg = get_openssl_error_message(); + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to generate DH parameters: "); + ddsrt_free(msg); + EVP_PKEY_CTX_free(pctx); + return DDS_SECURITY_VALIDATION_FAILED; + } - if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "Failed to allocate DH parameter context: "); - } else if (EVP_PKEY_paramgen_init(pctx) <= 0) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "Failed to initialize DH generation context: "); - } else if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1) <= 0) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "Failed to set DH generation parameter generation method: "); - } else if (EVP_PKEY_paramgen(pctx, params) <= 0) { - char *msg = get_openssl_error_message(); - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "Failed to generate DH parameters: "); - ddsrt_free(msg); - } - - if (pctx) EVP_PKEY_CTX_free(pctx); - - return result; + EVP_PKEY_CTX_free(pctx); + return DDS_SECURITY_VALIDATION_OK; } - -DDS_Security_ValidationResult_t -generate_dh_keys( - EVP_PKEY **dhkey, - AuthenticationAlgoKind_t authKind, - DDS_Security_SecurityException *ex) +DDS_Security_ValidationResult_t generate_dh_keys(EVP_PKEY **dhkey, AuthenticationAlgoKind_t authKind, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_FAILED; - EVP_PKEY *params = NULL; - EVP_PKEY_CTX *kctx = NULL; + EVP_PKEY *params = NULL; + EVP_PKEY_CTX *kctx = NULL; + *dhkey = NULL; + switch (authKind) + { + case AUTH_ALGO_KIND_RSA_2048: + if (get_rsa_dh_parameters(¶ms, ex) != DDS_SECURITY_VALIDATION_OK) + goto failed; + break; + case AUTH_ALGO_KIND_EC_PRIME256V1: + if (get_ec_dh_parameters(¶ms, ex) != DDS_SECURITY_VALIDATION_OK) + goto failed; + break; + default: + assert(0); + goto failed; + } - *dhkey = NULL; + if ((kctx = EVP_PKEY_CTX_new(params, NULL)) == NULL) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to allocate DH generation context: "); + goto failed_params; + } + if (EVP_PKEY_keygen_init(kctx) <= 0) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to initialize DH generation context: "); + goto failed_kctx; + } + if (EVP_PKEY_keygen(kctx, dhkey) <= 0) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to generate DH key pair: "); + goto failed_kctx; + } + EVP_PKEY_CTX_free(kctx); + EVP_PKEY_free(params); + return DDS_SECURITY_VALIDATION_OK; - switch(authKind) { - case AUTH_ALGO_KIND_RSA_2048: - result = get_rsa_dh_parameters(¶ms, ex); - break; - case AUTH_ALGO_KIND_EC_PRIME256V1: - result = get_ec_dh_parameters(¶ms, ex); - break; - default: - assert(0); - break; - } - - if (result != DDS_SECURITY_VALIDATION_OK) { - return result; - } else if ((kctx = EVP_PKEY_CTX_new(params, NULL)) == NULL) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "Failed to allocate DH generation context: "); - } else if (EVP_PKEY_keygen_init(kctx) <= 0) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "Failed to initialize DH generation context: "); - } else if (EVP_PKEY_keygen(kctx, dhkey) <= 0) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "Failed to generate DH key pair: "); - } - - if (kctx) EVP_PKEY_CTX_free(kctx); - if (params) EVP_PKEY_free(params); - - return result; +failed_kctx: + EVP_PKEY_CTX_free(kctx); +failed_params: + EVP_PKEY_free(params); +failed: + return DDS_SECURITY_VALIDATION_FAILED; } -static const BIGNUM * -dh_get_public_key( - DH *dhkey) +static const BIGNUM *dh_get_public_key(DH *dhkey) { #ifdef AUTH_INCLUDE_DH_ACCESSORS - const BIGNUM *pubkey, *privkey; - DH_get0_key(dhkey, &pubkey, &privkey); - return pubkey; + const BIGNUM *pubkey, *privkey; + DH_get0_key(dhkey, &pubkey, &privkey); + return pubkey; #else - return dhkey->pub_key; + return dhkey->pub_key; #endif } -static int -dh_set_public_key( - DH *dhkey, - BIGNUM *pubkey) +static int dh_set_public_key(DH *dhkey, BIGNUM *pubkey) { #ifdef AUTH_INCLUDE_DH_ACCESSORS - return DH_set0_key(dhkey, pubkey, NULL); + return DH_set0_key(dhkey, pubkey, NULL); #else - dhkey->pub_key = pubkey; + dhkey->pub_key = pubkey; #endif - return 1; + return 1; } -static DDS_Security_ValidationResult_t -dh_public_key_to_oct_modp( - EVP_PKEY *pkey, - unsigned char **buffer, - uint32_t *length, - DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t dh_public_key_to_oct_modp(EVP_PKEY *pkey, unsigned char **buffer, uint32_t *length, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - DH *dhkey; - ASN1_INTEGER *asn1int; - - *buffer = NULL; - - dhkey = EVP_PKEY_get1_DH(pkey); - if (!dhkey) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to get DH key from PKEY: "); - goto fail_get_dhkey; - } - - asn1int = BN_to_ASN1_INTEGER(dh_get_public_key(dhkey), NULL); - if (!asn1int) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to convert DH key to ASN1 integer: "); - goto fail_get_asn1int; - } - - *length = (uint32_t) i2d_ASN1_INTEGER(asn1int, buffer); - - ASN1_INTEGER_free(asn1int); - -fail_get_asn1int: + DH *dhkey; + ASN1_INTEGER *asn1int; + *buffer = NULL; + if (!(dhkey = EVP_PKEY_get1_DH(pkey))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to get DH key from PKEY: "); + return DDS_SECURITY_VALIDATION_FAILED; + } + if (!(asn1int = BN_to_ASN1_INTEGER(dh_get_public_key(dhkey), NULL))) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to convert DH key to ASN1 integer: "); DH_free(dhkey); -fail_get_dhkey: - return result; + return DDS_SECURITY_VALIDATION_FAILED; + } + *length = (uint32_t)i2d_ASN1_INTEGER(asn1int, buffer); + ASN1_INTEGER_free(asn1int); + DH_free(dhkey); + return DDS_SECURITY_VALIDATION_OK; } -static DDS_Security_ValidationResult_t -dh_public_key_to_oct_ecdh( - EVP_PKEY *pkey, - unsigned char **buffer, - uint32_t *length, - DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t dh_public_key_to_oct_ecdh(EVP_PKEY *pkey, unsigned char **buffer, uint32_t *length, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - EC_KEY *eckey; - const EC_GROUP *group; - const EC_POINT *point; - size_t sz; + EC_KEY *eckey; + const EC_GROUP *group; + const EC_POINT *point; + size_t sz; - eckey = EVP_PKEY_get1_EC_KEY(pkey); - if (!eckey) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to get EC key from PKEY: "); - goto fail_get_eckey; - } - - point = EC_KEY_get0_public_key(eckey); - if (!point) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to get public key from ECKEY: "); - goto fail_get_point; - } - - group = EC_KEY_get0_group(eckey); - if (!group) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to get group from ECKEY: "); - goto fail_get_group; - } - - sz = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); - if (sz == 0) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to serialize public EC key: "); - goto fail_point2oct1; - } - - *buffer = ddsrt_malloc(sz); - - *length = (uint32_t)EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, *buffer, sz, NULL); - if (*length == 0) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to serialize public EC key: "); - goto fail_point2oct2; - } - - EC_KEY_free(eckey); - - return result; - -fail_point2oct2: + if (!(eckey = EVP_PKEY_get1_EC_KEY(pkey))) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to get EC key from PKEY: "); + goto failed_key; + } + if (!(point = EC_KEY_get0_public_key(eckey))) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to get public key from ECKEY: "); + goto failed; + } + if (!(group = EC_KEY_get0_group(eckey))) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to get group from ECKEY: "); + goto failed; + } + if ((sz = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL)) == 0) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to serialize public EC key: "); + goto failed; + } + *buffer = ddsrt_malloc(sz); + if ((*length = (uint32_t)EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, *buffer, sz, NULL)) == 0) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to serialize public EC key: "); ddsrt_free(*buffer); -fail_point2oct1: -fail_get_group: -fail_get_point: -fail_get_eckey: - EC_KEY_free(eckey); - return result; + goto failed; + } + EC_KEY_free(eckey); + return DDS_SECURITY_VALIDATION_OK; + +failed: + EC_KEY_free(eckey); +failed_key: + return DDS_SECURITY_VALIDATION_FAILED; } -DDS_Security_ValidationResult_t -dh_public_key_to_oct( - EVP_PKEY *pkey, - AuthenticationAlgoKind_t algo, - unsigned char **buffer, - uint32_t *length, - DDS_Security_SecurityException *ex) +DDS_Security_ValidationResult_t dh_public_key_to_oct(EVP_PKEY *pkey, AuthenticationAlgoKind_t algo, unsigned char **buffer, uint32_t *length, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - - assert(pkey); - assert(buffer); - assert(length); - - switch (algo) { - case AUTH_ALGO_KIND_RSA_2048: - result = dh_public_key_to_oct_modp(pkey, buffer, length, ex); - break; - case AUTH_ALGO_KIND_EC_PRIME256V1: - result = dh_public_key_to_oct_ecdh(pkey, buffer, length, ex); - break; - default: - assert(0); - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Invalid key algorithm specified"); - break; - } - - return result; + assert(pkey); + assert(buffer); + assert(length); + switch (algo) + { + case AUTH_ALGO_KIND_RSA_2048: + return dh_public_key_to_oct_modp(pkey, buffer, length, ex); + case AUTH_ALGO_KIND_EC_PRIME256V1: + return dh_public_key_to_oct_ecdh(pkey, buffer, length, ex); + default: + assert(0); + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Invalid key algorithm specified"); + return DDS_SECURITY_VALIDATION_FAILED; + } } -static DDS_Security_ValidationResult_t -dh_oct_to_public_key_modp( - EVP_PKEY **pkey, - const unsigned char *keystr, - uint32_t size, - DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t dh_oct_to_public_key_modp(EVP_PKEY **pkey, const unsigned char *keystr, uint32_t size, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - DH *dhkey; - ASN1_INTEGER *asn1int; - BIGNUM *pubkey; + DH *dhkey; + ASN1_INTEGER *asn1int; + BIGNUM *pubkey; - *pkey = EVP_PKEY_new(); - if (!(*pkey)) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to convert octet sequence to ASN1 integer: "); - goto fail_alloc_pkey; - } + if (!(*pkey = EVP_PKEY_new())) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to convert octet sequence to ASN1 integer: "); + goto fail_alloc_pkey; + } + if (!(asn1int = d2i_ASN1_INTEGER(NULL, (const unsigned char **)&keystr, size))) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to convert octet sequence to ASN1 integer: "); + goto fail_get_asn1int; + } + if (!(pubkey = ASN1_INTEGER_to_BN(asn1int, NULL))) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to convert ASN1 integer to BIGNUM: "); + goto fail_get_pubkey; + } - asn1int = d2i_ASN1_INTEGER(NULL, (const unsigned char **)&keystr, size); - if (!asn1int) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to convert octet sequence to ASN1 integer: "); - goto fail_get_asn1int; - } - - pubkey = ASN1_INTEGER_to_BN(asn1int, NULL); - if (!pubkey) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to convert ASN1 integer to BIGNUM: "); - goto fail_get_pubkey; - } - - dhkey = DH_get_2048_256(); - - if (dh_set_public_key(dhkey, pubkey) == 0) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to set DH public key: "); - } else if (EVP_PKEY_set1_DH(*pkey, dhkey) == 0) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to convert DH to PKEY: "); - } - - ASN1_INTEGER_free(asn1int); + dhkey = DH_get_2048_256(); + if (dh_set_public_key(dhkey, pubkey) == 0) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to set DH public key: "); + goto fail_get_pubkey; + } + if (EVP_PKEY_set1_DH(*pkey, dhkey) == 0) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to convert DH to PKEY: "); DH_free(dhkey); - - return result; + goto fail_get_pubkey; + } + ASN1_INTEGER_free(asn1int); + DH_free(dhkey); + return DDS_SECURITY_VALIDATION_OK; fail_get_pubkey: - ASN1_INTEGER_free(asn1int); + ASN1_INTEGER_free(asn1int); fail_get_asn1int: - EVP_PKEY_free(*pkey); + EVP_PKEY_free(*pkey); fail_alloc_pkey: - return result; + return DDS_SECURITY_VALIDATION_FAILED; } -static DDS_Security_ValidationResult_t -dh_oct_to_public_key_ecdh( - EVP_PKEY **pkey, - const unsigned char *keystr, - uint32_t size, - DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t dh_oct_to_public_key_ecdh(EVP_PKEY **pkey, const unsigned char *keystr, uint32_t size, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - EC_KEY *eckey; - EC_GROUP *group; - EC_POINT *point; - - group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); - if (!group) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to allocate EC group: "); - goto fail_alloc_group; - } - - point = EC_POINT_new(group); - if (!point) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to allocate EC point: "); - goto fail_alloc_point; - } - - - if (EC_POINT_oct2point(group, point, keystr, size, NULL) != 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to deserialize EC public key to EC point: "); - goto fail_oct2point; - } - - eckey = EC_KEY_new(); - if (!eckey) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to allocate EC KEY: "); - goto fail_alloc_eckey; - } - - if (EC_KEY_set_group(eckey, group) != 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to convert octet sequence to ASN1 integer: "); - goto fail_eckey_set_group; - } - - if (EC_KEY_set_public_key(eckey, point) != 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to set EC public key: "); - goto fail_eckey_set_pubkey; - } - - *pkey = EVP_PKEY_new(); - if (!(*pkey)) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to allocate EVP key: "); - goto fail_alloc_pkey; - } - - if (EVP_PKEY_set1_EC_KEY(*pkey, eckey) != 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to set EVP key to EC public key: "); - goto fail_pkey_set_eckey; - } - - EC_KEY_free(eckey); - EC_POINT_free(point); - EC_GROUP_free(group); - - return result; + EC_KEY *eckey; + EC_GROUP *group; + EC_POINT *point; + if (!(group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1))) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to allocate EC group: "); + goto fail_alloc_group; + } + if (!(point = EC_POINT_new(group))) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to allocate EC point: "); + goto fail_alloc_point; + } + if (EC_POINT_oct2point(group, point, keystr, size, NULL) != 1) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to deserialize EC public key to EC point: "); + goto fail_oct2point; + } + if (!(eckey = EC_KEY_new())) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to allocate EC KEY: "); + goto fail_alloc_eckey; + } + if (EC_KEY_set_group(eckey, group) != 1) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to set EC group: "); + goto fail_eckey_set; + } + if (EC_KEY_set_public_key(eckey, point) != 1) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to set EC public key: "); + goto fail_eckey_set; + } + if (!(*pkey = EVP_PKEY_new())) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to allocate EVP key: "); + goto fail_alloc_pkey; + } + if (EVP_PKEY_set1_EC_KEY(*pkey, eckey) != 1) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to set EVP key to EC public key: "); + goto fail_pkey_set_eckey; + } + EC_KEY_free(eckey); + EC_POINT_free(point); + EC_GROUP_free(group); + return DDS_SECURITY_VALIDATION_OK; fail_pkey_set_eckey: - EVP_PKEY_free(*pkey); + EVP_PKEY_free(*pkey); fail_alloc_pkey: -fail_eckey_set_pubkey: -fail_eckey_set_group: - EC_KEY_free(eckey); +fail_eckey_set: + EC_KEY_free(eckey); fail_alloc_eckey: fail_oct2point: - EC_POINT_free(point); + EC_POINT_free(point); fail_alloc_point: - EC_GROUP_free(group); + EC_GROUP_free(group); fail_alloc_group: - return result; + return DDS_SECURITY_VALIDATION_FAILED; } -DDS_Security_ValidationResult_t -dh_oct_to_public_key( - EVP_PKEY **data, - AuthenticationAlgoKind_t algo, - const unsigned char *str, - uint32_t size, - DDS_Security_SecurityException *ex) +DDS_Security_ValidationResult_t dh_oct_to_public_key(EVP_PKEY **data, AuthenticationAlgoKind_t algo, const unsigned char *str, uint32_t size, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - - assert(data); - assert(str); - - switch (algo) { - case AUTH_ALGO_KIND_RSA_2048: - result = dh_oct_to_public_key_modp(data, str, size, ex); - break; - case AUTH_ALGO_KIND_EC_PRIME256V1: - result = dh_oct_to_public_key_ecdh(data, str, size, ex); - break; - default: - assert(0); - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Invalid key algorithm specified"); - break; - } - - return result; + assert(data); + assert(str); + switch (algo) + { + case AUTH_ALGO_KIND_RSA_2048: + return dh_oct_to_public_key_modp(data, str, size, ex); + case AUTH_ALGO_KIND_EC_PRIME256V1: + return dh_oct_to_public_key_ecdh(data, str, size, ex); + default: + assert(0); + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Invalid key algorithm specified"); + return DDS_SECURITY_VALIDATION_FAILED; + } } -/* - * Allocates and return a NULL terminated string from given char array with the given size. - */ -char * -string_from_data( - const unsigned char *data, - uint32_t size) +char *string_from_data(const unsigned char *data, uint32_t size) { - char *str = NULL; - - if (size > 0 && data) { - str = ddsrt_malloc(size+1); - memcpy(str, data, size); - str[size] = '\0'; - } - - return str; + char *str = NULL; + if (size > 0 && data) + { + str = ddsrt_malloc(size + 1); + memcpy(str, data, size); + str[size] = '\0'; + } + return str; } -void -free_ca_list_contents( X509Seq *ca_list) +void free_ca_list_contents(X509Seq *ca_list) { - unsigned i; - if( ca_list->buffer != NULL && ca_list->length > 0){ - for (i = 0; i < ca_list->length; ++i) { - X509_free(ca_list->buffer[i]); - } - ddsrt_free ( ca_list->buffer ); - } - ca_list->buffer = NULL; - ca_list->length = 0; + unsigned i; + if (ca_list->buffer != NULL && ca_list->length > 0) + { + for (i = 0; i < ca_list->length; ++i) + X509_free(ca_list->buffer[i]); + ddsrt_free(ca_list->buffer); + } + ca_list->buffer = NULL; + ca_list->length = 0; } -DDS_Security_ValidationResult_t -get_trusted_ca_list ( const char* trusted_ca_dir, - X509Seq *ca_list, - DDS_Security_SecurityException *ex){ - - - DDS_Security_ValidationResult_t loading_result = DDS_RETCODE_OK; - - dds_return_t r; - ddsrt_dir_handle_t d_descr; - struct ddsrt_dirent d_entry; - struct ddsrt_stat status; - char *full_file_path; - char *trusted_ca_dir_normalized; - - X509 *ca_buffer_array[MAX_TRUSTED_CA]; /*max trusted CA size */ - unsigned ca_buffer_array_size=0; - unsigned i; - trusted_ca_dir_normalized = ddsrt_file_normalize(trusted_ca_dir); - - r = ddsrt_opendir(trusted_ca_dir_normalized, &d_descr); - ddsrt_free ( trusted_ca_dir_normalized ); - if (r == DDS_RETCODE_OK && ca_buffer_array_size < MAX_TRUSTED_CA) { /* accessable */ - r = ddsrt_readdir(d_descr, &d_entry); - while (r == DDS_RETCODE_OK) { - ddsrt_asprintf(&full_file_path, "%s%s%s", trusted_ca_dir, ddsrt_file_sep(), d_entry.d_name); - if (ddsrt_stat (full_file_path, &status) == DDS_RETCODE_OK) { /* accessable */ - if ((strcmp(d_entry.d_name, ".") != 0) && - (strcmp(d_entry.d_name, "..") != 0)) { - char * filename = ddsrt_file_normalize(full_file_path); - - if(filename){ - X509 *identityCA; - loading_result = load_X509_certificate_from_file( filename, &identityCA, ex); - - ddsrt_free(filename); - - if( loading_result == DDS_SECURITY_VALIDATION_OK ){ - ca_buffer_array[ca_buffer_array_size] = identityCA; - ca_buffer_array_size++; - } else { - DDS_Security_Exception_reset(ex); - } - } - } - } - r = ddsrt_readdir(d_descr, &d_entry); - - ddsrt_free(full_file_path); - } - - ddsrt_closedir (d_descr); - - /* deallocate given ca_list if it is not NULL */ - free_ca_list_contents(ca_list); - - /*copy CAs to out parameter as HASH*/ - if( ca_buffer_array_size > 0 ){ - ca_list->buffer = ddsrt_malloc( ca_buffer_array_size * sizeof(X509 * ) ); - for (i = 0; i < ca_buffer_array_size; ++i) { - ca_list->buffer[i] = ca_buffer_array[i]; - - } - - } - ca_list->length = ca_buffer_array_size; - - return DDS_SECURITY_VALIDATION_OK; - - } - else{ - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_TRUSTED_CA_DIR_CODE, 0, DDS_SECURITY_ERR_INVALID_TRUSTED_CA_DIR_MESSAGE); - return DDS_SECURITY_VALIDATION_FAILED; - } - - return loading_result; -} - -DDS_Security_ValidationResult_t -create_asymmetrical_signature( - EVP_PKEY *pkey, - const unsigned char *data, - const size_t dataLen, - unsigned char **signature, - size_t *signatureLen, - DDS_Security_SecurityException *ex) +DDS_Security_ValidationResult_t get_trusted_ca_list(const char *trusted_ca_dir, X509Seq *ca_list, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - EVP_MD_CTX *mdctx = NULL; - EVP_PKEY_CTX *kctx = NULL; + ddsrt_dir_handle_t d_descr; + struct ddsrt_dirent d_entry; + struct ddsrt_stat status; + X509 *ca_buf[MAX_TRUSTED_CA]; + unsigned ca_cnt = 0; + char *tca_dir_norm = ddsrt_file_normalize(trusted_ca_dir); + dds_return_t ret = ddsrt_opendir(tca_dir_norm, &d_descr); + ddsrt_free(tca_dir_norm); + if (ret != DDS_RETCODE_OK) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_TRUSTED_CA_DIR_CODE, 0, DDS_SECURITY_ERR_INVALID_TRUSTED_CA_DIR_MESSAGE); + return DDS_SECURITY_VALIDATION_FAILED; + } - if (!(mdctx = EVP_MD_CTX_create())) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to create signing context: "); - goto err_create_ctx; + char *fpath, *fname; + X509 *ca; + bool failed = false; + while (!failed && ddsrt_readdir(d_descr, &d_entry) == DDS_RETCODE_OK) + { + ddsrt_asprintf(&fpath, "%s%s%s", trusted_ca_dir, ddsrt_file_sep(), d_entry.d_name); + if (ddsrt_stat(fpath, &status) == DDS_RETCODE_OK + && strcmp(d_entry.d_name, ".") != 0 && strcmp(d_entry.d_name, "..") != 0 + && (fname = ddsrt_file_normalize(fpath)) != NULL) + { + if (ca_cnt >= MAX_TRUSTED_CA) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_TRUSTED_CA_DIR_MAX_EXCEEDED_CODE, 0, DDS_SECURITY_ERR_TRUSTED_CA_DIR_MAX_EXCEEDED_MESSAGE, MAX_TRUSTED_CA); + failed = true; + } + else if (load_X509_certificate_from_file(fname, &ca, ex) == DDS_SECURITY_VALIDATION_OK) + ca_buf[ca_cnt++] = ca; + else + DDS_Security_Exception_reset(ex); + ddsrt_free(fname); } + ddsrt_free(fpath); + } + ddsrt_closedir(d_descr); - if (EVP_DigestSignInit(mdctx, &kctx, EVP_sha256(), NULL, pkey) != 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to initialize signing context: "); - goto err_sign; + if (!failed) + { + free_ca_list_contents(ca_list); + if (ca_cnt > 0) + { + ca_list->buffer = ddsrt_malloc(ca_cnt * sizeof(X509 *)); + for (unsigned i = 0; i < ca_cnt; ++i) + ca_list->buffer[i] = ca_buf[i]; } + ca_list->length = ca_cnt; + } + return failed ? DDS_SECURITY_VALIDATION_FAILED : DDS_SECURITY_VALIDATION_OK; +} - if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { - if (EVP_PKEY_CTX_set_rsa_padding(kctx, RSA_PKCS1_PSS_PADDING) < 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to initialize signing context: "); - goto err_sign; - } - } +DDS_Security_ValidationResult_t create_asymmetrical_signature(EVP_PKEY *pkey, const unsigned char *data, const size_t dataLen, + unsigned char **signature, size_t *signatureLen, DDS_Security_SecurityException *ex) +{ + EVP_MD_CTX *mdctx = NULL; + EVP_PKEY_CTX *kctx = NULL; - if (EVP_DigestSignUpdate(mdctx, data, dataLen) != 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to update signing context: "); - goto err_sign; - } - - if (EVP_DigestSignFinal(mdctx, NULL, signatureLen) != 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to finalize signing context: "); - goto err_sign; - } - - *signature = ddsrt_malloc(sizeof(unsigned char) * (*signatureLen)); - assert(*signature != NULL); - if (EVP_DigestSignFinal(mdctx, *signature, signatureLen) != 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to finalize signing context: "); - ddsrt_free(*signature); + if (!(mdctx = EVP_MD_CTX_create())) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to create signing context: "); + goto err_create_ctx; + } + if (EVP_DigestSignInit(mdctx, &kctx, EVP_sha256(), NULL, pkey) != 1) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to initialize signing context: "); + goto err_sign; + } + if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) + { + if (EVP_PKEY_CTX_set_rsa_padding(kctx, RSA_PKCS1_PSS_PADDING) < 1) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to initialize signing context: "); + goto err_sign; } + } + if (EVP_DigestSignUpdate(mdctx, data, dataLen) != 1) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to update signing context: "); + goto err_sign; + } + if (EVP_DigestSignFinal(mdctx, NULL, signatureLen) != 1) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to finalize signing context: "); + goto err_sign; + } + *signature = ddsrt_malloc(sizeof(unsigned char) * (*signatureLen)); + if (EVP_DigestSignFinal(mdctx, *signature, signatureLen) != 1) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to finalize signing context: "); + ddsrt_free(*signature); + goto err_sign; + } + EVP_MD_CTX_destroy(mdctx); + return DDS_SECURITY_VALIDATION_OK; err_sign: - EVP_MD_CTX_destroy(mdctx); + EVP_MD_CTX_destroy(mdctx); err_create_ctx: - return result; + return DDS_SECURITY_VALIDATION_FAILED; } -DDS_Security_ValidationResult_t -validate_asymmetrical_signature( - EVP_PKEY *pkey, - const unsigned char *data, - const size_t dataLen, - const unsigned char *signature, - const size_t signatureLen, - DDS_Security_SecurityException *ex) +DDS_Security_ValidationResult_t validate_asymmetrical_signature(EVP_PKEY *pkey, const unsigned char *data, const size_t dataLen, + const unsigned char *signature, const size_t signatureLen, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - EVP_MD_CTX *mdctx = NULL; - EVP_PKEY_CTX *kctx = NULL; - - if (!(mdctx = EVP_MD_CTX_create())) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to create verify context: "); - goto err_create_ctx; - } - - if (EVP_DigestVerifyInit(mdctx, &kctx, EVP_sha256(), NULL, pkey) != 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to initialize verify context: "); - goto err_verify; - } - - if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { - if (EVP_PKEY_CTX_set_rsa_padding(kctx, RSA_PKCS1_PSS_PADDING) < 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to initialize signing context: "); - goto err_verify; - } - } - - if (EVP_DigestVerifyUpdate(mdctx, data, dataLen) != 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to update verify context: "); - goto err_verify; - } - - if (EVP_DigestVerifyFinal(mdctx, signature, signatureLen) != 1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Failed to finalize verify context: "); - goto err_verify; + EVP_MD_CTX *mdctx = NULL; + EVP_PKEY_CTX *kctx = NULL; + if (!(mdctx = EVP_MD_CTX_create())) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to create verify context: "); + goto err_create_ctx; + } + if (EVP_DigestVerifyInit(mdctx, &kctx, EVP_sha256(), NULL, pkey) != 1) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to initialize verify context: "); + goto err_verify; + } + if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) + { + if (EVP_PKEY_CTX_set_rsa_padding(kctx, RSA_PKCS1_PSS_PADDING) < 1) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to initialize signing context: "); + goto err_verify; } + } + if (EVP_DigestVerifyUpdate(mdctx, data, dataLen) != 1) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to update verify context: "); + goto err_verify; + } + if (EVP_DigestVerifyFinal(mdctx, signature, signatureLen) != 1) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to finalize verify context: "); + goto err_verify; + } + EVP_MD_CTX_destroy(mdctx); + return DDS_SECURITY_VALIDATION_OK; err_verify: - EVP_MD_CTX_destroy(mdctx); + EVP_MD_CTX_destroy(mdctx); err_create_ctx: - return result; + return DDS_SECURITY_VALIDATION_FAILED; } diff --git a/src/security/builtin_plugins/authentication/src/auth_utils.h b/src/security/builtin_plugins/authentication/src/auth_utils.h index b08df38..bbde1ba 100644 --- a/src/security/builtin_plugins/authentication/src/auth_utils.h +++ b/src/security/builtin_plugins/authentication/src/auth_utils.h @@ -42,34 +42,21 @@ typedef struct { } X509Seq; typedef unsigned char HashValue_t[SHA256_DIGEST_LENGTH]; -/*typedef struct HashValue { - unsigned char value[SHA256_DIGEST_LENGTH]; -} HashValue_t; -*/ /* Return a string that contains an openssl error description * When a openssl function returns an error this function can be * used to retrieve a descriptive error string. * Note that the returned string should be freed. */ -char * -get_openssl_error_message( - void); +char * get_openssl_error_message(void); /* Return the subject name of contained in a X509 certificate * Note that the returned string should be freed. */ -char* -get_certificate_subject_name( - X509 *cert, - DDS_Security_SecurityException *ex); +char * get_certificate_subject_name(X509 *cert, DDS_Security_SecurityException *ex); -/* Return the expiry date of contained in a X509 certificate - * - */ -dds_time_t -get_certificate_expiry( - const X509 *cert); +/* Return the expiry date of contained in a X509 certificate */ +dds_time_t get_certificate_expiry(const X509 *cert); /* Return the subject name of a X509 certificate DER * encoded. The DER encoded subject name is returned in @@ -78,63 +65,19 @@ get_certificate_expiry( * * return length of allocated buffer or -1 on error */ -DDS_Security_ValidationResult_t -get_subject_name_DER_encoded( - const X509 *cert, - unsigned char **buffer, - size_t *size, - DDS_Security_SecurityException *ex); +DDS_Security_ValidationResult_t get_subject_name_DER_encoded(const X509 *cert, unsigned char **buffer, size_t *size, DDS_Security_SecurityException *ex); +/* Load a X509 certificate for the provided data (PEM format) */ +DDS_Security_ValidationResult_t load_X509_certificate_from_data(const char *data, int len, X509 **x509Cert, DDS_Security_SecurityException *ex); -/* Load a X509 certificate for the provided data. - * - * data : certificate in PEM format - * x509Cert : the openssl X509 return value - */ -DDS_Security_ValidationResult_t -load_X509_certificate_from_data( - const char *data, - int len, - X509 **x509Cert, - DDS_Security_SecurityException *ex); +/* Load a X509 certificate for the provided data (certificate uri) */ +DDS_Security_ValidationResult_t load_X509_certificate(const char *data, X509 **x509Cert, DDS_Security_SecurityException *ex); +/* Load a X509 certificate for the provided file */ +DDS_Security_ValidationResult_t load_X509_certificate_from_file(const char *filename, X509 **x509Cert, DDS_Security_SecurityException *ex); -/* Load a X509 certificate for the provided data. - * - * data : URI of the certificate. URI format is defined in DDS Security spec 9.3.1 - - * x509Cert : the openssl X509 return value - */ -DDS_Security_ValidationResult_t -load_X509_certificate( - const char *data, - X509 **x509Cert, - DDS_Security_SecurityException *ex); - - -/* Load a X509 certificate for the provided file. - * - * filename : path of the file that contains PEM formatted certificate - * x509Cert : the openssl X509 return value - */ -DDS_Security_ValidationResult_t -load_X509_certificate_from_file( - const char *filename, - X509 **x509Cert, - DDS_Security_SecurityException *ex); - -/* Load a Private Key for the provided data. - * - * data : URI of the private key. URI format is defined in DDS Security spec 9.3.1 - * privateKey : the openssl EVP_PKEY return value - */ -DDS_Security_ValidationResult_t -load_X509_private_key( - const char *data, - const char *password, - EVP_PKEY **privateKey, - DDS_Security_SecurityException *ex); - +/* Load a Private Key for the provided data (private key uri) */ +DDS_Security_ValidationResult_t load_X509_private_key(const char *data, const char *password, EVP_PKEY **privateKey, DDS_Security_SecurityException *ex); /* Validate an identity certificate against the identityCA * The provided identity certificate is checked if it is @@ -144,95 +87,20 @@ load_X509_private_key( * The function does not yet check a CLR or ocsp * for expiry of identity certificate. */ -DDS_Security_ValidationResult_t -verify_certificate( - X509 *identityCert, - X509 *identityCa, - DDS_Security_SecurityException *ex); +DDS_Security_ValidationResult_t verify_certificate(X509 *identityCert, X509 *identityCa, DDS_Security_SecurityException *ex); -DDS_Security_ValidationResult_t -check_certificate_expiry( - const X509 *cert, - DDS_Security_SecurityException *ex); - -AuthenticationAlgoKind_t -get_auhentication_algo_kind( - X509 *cert); - -AuthenticationChallenge * -generate_challenge( - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -get_certificate_contents( - X509 *cert, - unsigned char **data, - uint32_t *size, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -generate_dh_keys( - EVP_PKEY **dhkey, - AuthenticationAlgoKind_t authKind, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -dh_public_key_to_oct( - EVP_PKEY *pkey, - AuthenticationAlgoKind_t algo, - unsigned char **buffer, - uint32_t *length, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -dh_oct_to_public_key( - EVP_PKEY **data, - AuthenticationAlgoKind_t algo, - const unsigned char *str, - uint32_t size, - DDS_Security_SecurityException *ex); - - -AuthConfItemPrefix_t -get_conf_item_type( - const char *str, - char **data); - -/* - * Frees the contents of theCA list. - */ -void -free_ca_list_contents( - X509Seq *ca_list); - -DDS_Security_ValidationResult_t -get_trusted_ca_list ( - const char* trusted_ca_dir, - X509Seq *ca_list, - DDS_Security_SecurityException *ex); - -char * -string_from_data( - const unsigned char *data, - uint32_t size); - - -DDS_Security_ValidationResult_t -create_asymmetrical_signature( - EVP_PKEY *pkey, - const unsigned char *data, - const size_t dataLen, - unsigned char **signature, - size_t *signatureLen, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -validate_asymmetrical_signature( - EVP_PKEY *pkey, - const unsigned char *data, - const size_t dataLen, - const unsigned char *signature, - const size_t signatureLen, - DDS_Security_SecurityException *ex); +DDS_Security_ValidationResult_t check_certificate_expiry(const X509 *cert, DDS_Security_SecurityException *ex); +AuthenticationAlgoKind_t get_authentication_algo_kind(X509 *cert); +AuthenticationChallenge *generate_challenge(DDS_Security_SecurityException *ex); +DDS_Security_ValidationResult_t get_certificate_contents(X509 *cert, unsigned char **data, uint32_t *size, DDS_Security_SecurityException *ex); +DDS_Security_ValidationResult_t generate_dh_keys(EVP_PKEY **dhkey, AuthenticationAlgoKind_t authKind, DDS_Security_SecurityException *ex); +DDS_Security_ValidationResult_t dh_public_key_to_oct(EVP_PKEY *pkey, AuthenticationAlgoKind_t algo, unsigned char **buffer, uint32_t *length, DDS_Security_SecurityException *ex); +DDS_Security_ValidationResult_t dh_oct_to_public_key(EVP_PKEY **data, AuthenticationAlgoKind_t algo, const unsigned char *str, uint32_t size, DDS_Security_SecurityException *ex); +AuthConfItemPrefix_t get_conf_item_type(const char *str, char **data); +void free_ca_list_contents(X509Seq *ca_list); +DDS_Security_ValidationResult_t get_trusted_ca_list(const char* trusted_ca_dir, X509Seq *ca_list, DDS_Security_SecurityException *ex); +char * string_from_data(const unsigned char *data, uint32_t size); +DDS_Security_ValidationResult_t create_asymmetrical_signature(EVP_PKEY *pkey, const unsigned char *data, const size_t dataLen, unsigned char **signature, size_t *signatureLen, DDS_Security_SecurityException *ex); +DDS_Security_ValidationResult_t validate_asymmetrical_signature(EVP_PKEY *pkey, const unsigned char *data, const size_t dataLen, const unsigned char *signature, const size_t signatureLen, DDS_Security_SecurityException *ex); #endif /* AUTH_UTILS_H */ diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index 4d317d7..79f03bd 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -10,7 +10,9 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ - +#include +#include +#include #include #include #include @@ -19,12 +21,6 @@ #include #include #include -#include "authentication.h" -#include "dds/ddsrt/heap.h" -#include "dds/security/dds_security_api.h" -#include "dds/security/core/dds_security_timed_cb.h" -#include "dds/security/core/dds_security_utils.h" - #if OPENSLL_VERSION_NUMBER >= 0x10002000L #define AUTH_INCLUDE_EC #include @@ -40,431 +36,356 @@ #undef X509_NAME #endif -#include "dds/security/dds_security_api.h" -#include "dds/security/dds_security_api_types.h" +#include "dds/ddsrt/heap.h" #include "dds/ddsrt/atomics.h" -#include "stdbool.h" -#include #include "dds/ddsrt/string.h" #include "dds/ddsrt/sync.h" #include "dds/ddsrt/hopscotch.h" - +#include "dds/security/dds_security_api.h" +#include "dds/security/core/dds_security_timed_cb.h" +#include "dds/security/core/dds_security_utils.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/dds_security_api_types.h" #include "dds/security/core/shared_secret.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/dds_security_serialize.h" #include "auth_utils.h" -#include +#include "authentication.h" #ifndef EVP_PKEY_id #define EVP_PKEY_id(k) ((k)->type) #endif #if OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10100000L -#define REMOVE_THREAD_STATE() ERR_remove_thread_state(NULL); +#define REMOVE_THREAD_STATE() ERR_remove_thread_state(NULL); #elif OPENSSL_VERSION_NUMBER < 0x10000000L -#define REMOVE_THREAD_STATE() ERR_remove_state(0); +#define REMOVE_THREAD_STATE() ERR_remove_state(0); #else #define REMOVE_THREAD_STATE() #endif - #define HANDSHAKE_SIGNATURE_CONTENT_SIZE 6 +#define ADJUSTED_GUID_PREFIX_FLAG 0x80 -static const char * AUTH_PROTOCOL_CLASS = "DDS:Auth:PKI-DH"; -static const unsigned AUTH_PROTOCOL_VERSION_MAJOR = 1; -static const unsigned AUTH_PROTOCOL_VERSION_MINOR = 0; +static const char *AUTH_PROTOCOL_CLASS = "DDS:Auth:PKI-DH"; +static const unsigned AUTH_PROTOCOL_VERSION_MAJOR = 1; +static const unsigned AUTH_PROTOCOL_VERSION_MINOR = 0; -static const char * AUTH_REQUEST_TOKEN_CLASS_ID = "DDS:Auth:PKI-DH:1.0+AuthReq"; -static const char * AUTH_REQUEST_TOKEN_FUTURE_PROP_NAME = "future_challenge"; +static const char *AUTH_REQUEST_TOKEN_CLASS_ID = "DDS:Auth:PKI-DH:1.0+AuthReq"; +static const char *AUTH_REQUEST_TOKEN_FUTURE_PROP_NAME = "future_challenge"; -static const char * PROPERTY_IDENTITY_CA = "dds.sec.auth.identity_ca"; -static const char * PROPERTY_PRIVATE_KEY = "dds.sec.auth.private_key"; -static const char * PROPERTY_PASSWORD = "dds.sec.auth.password"; -static const char * PROPERTY_IDENTITY_CERT = "dds.sec.auth.identity_certificate"; -static const char * PROPERTY_TRUSTED_CA_DIR = "dds.sec.auth.trusted_ca_dir"; +static const char *PROPERTY_IDENTITY_CA = "dds.sec.auth.identity_ca"; +static const char *PROPERTY_PRIVATE_KEY = "dds.sec.auth.private_key"; +static const char *PROPERTY_PASSWORD = "dds.sec.auth.password"; +static const char *PROPERTY_IDENTITY_CERT = "dds.sec.auth.identity_certificate"; +static const char *PROPERTY_TRUSTED_CA_DIR = "dds.sec.auth.trusted_ca_dir"; -static const char * PROPERTY_CERT_SUBJECT_NAME = "dds.cert.sn"; -static const char * PROPERTY_CERT_ALGORITHM = "dds.cert.algo"; -static const char * PROPERTY_CA_SUBJECT_NAME = "dds.ca.sn"; -static const char * PROPERTY_CA_ALGORITHM = "dds.ca.aglo"; +static const char *PROPERTY_CERT_SUBJECT_NAME = "dds.cert.sn"; +static const char *PROPERTY_CERT_ALGORITHM = "dds.cert.algo"; +static const char *PROPERTY_CA_SUBJECT_NAME = "dds.ca.sn"; +static const char *PROPERTY_CA_ALGORITHM = "dds.ca.aglo"; -static const char * AUTH_HANDSHAKE_REQUEST_TOKEN_ID = "DDS:Auth:PKI-DH:1.0+Req"; -static const char * AUTH_HANDSHAKE_REPLY_TOKEN_ID = "DDS:Auth:PKI-DH:1.0+Reply"; +static const char *AUTH_HANDSHAKE_REQUEST_TOKEN_ID = "DDS:Auth:PKI-DH:1.0+Req"; +static const char *AUTH_HANDSHAKE_REPLY_TOKEN_ID = "DDS:Auth:PKI-DH:1.0+Reply"; -static const char * AUTH_HANDSHAKE_FINAL_TOKEN_ID = "DDS:Auth:PKI-DH:1.0+Final"; +static const char *AUTH_HANDSHAKE_FINAL_TOKEN_ID = "DDS:Auth:PKI-DH:1.0+Final"; -static const char * AUTH_DSIG_ALGO_RSA_2048_SHA256_IDENT = "RSASSA-PSS-SHA256"; -static const char * AUTH_DSIG_ALGO_ECDSA_SHA256_IDENT = "ECDSA-SHA256"; -static const char * AUTH_KAGREE_ALGO_RSA_2048_SHA256_IDENT = "DH+MODP-2048-256"; -static const char * AUTH_KAGREE_ALGO_ECDH_PRIME256V1_IDENT = "ECDH+prime256v1-CEUM"; +static const char *AUTH_DSIG_ALGO_RSA_2048_SHA256_IDENT = "RSASSA-PSS-SHA256"; +static const char *AUTH_DSIG_ALGO_ECDSA_SHA256_IDENT = "ECDSA-SHA256"; +static const char *AUTH_KAGREE_ALGO_RSA_2048_SHA256_IDENT = "DH+MODP-2048-256"; +static const char *AUTH_KAGREE_ALGO_ECDH_PRIME256V1_IDENT = "ECDH+prime256v1-CEUM"; +static const char *ACCESS_PERMISSIONS_CREDENTIAL_TOKEN_ID = "DDS:Access:PermissionsCredential"; +static const char *ACCESS_PROPERTY_PERMISSION_DOCUMENT = "dds.perm.cert"; -static const char * ACCESS_PERMISSIONS_CREDENTIAL_TOKEN_ID = "DDS:Access:PermissionsCredential"; -static const char * ACCESS_PROPERTY_PERMISSION_DOCUMENT = "dds.perm.cert"; - - -/** - * Implementation structure for storing encapsulated members of the instance - * while giving only the interface definition to user - */ - -typedef enum { - SECURITY_OBJECT_KIND_UNKNOWN, - SECURITY_OBJECT_KIND_LOCAL_IDENTITY, - SECURITY_OBJECT_KIND_REMOTE_IDENTITY, - SECURITY_OBJECT_KIND_IDENTITY_RELATION, - SECURITY_OBJECT_KIND_HANDSHAKE +typedef enum +{ + SECURITY_OBJECT_KIND_UNKNOWN, + SECURITY_OBJECT_KIND_LOCAL_IDENTITY, + SECURITY_OBJECT_KIND_REMOTE_IDENTITY, + SECURITY_OBJECT_KIND_IDENTITY_RELATION, + SECURITY_OBJECT_KIND_HANDSHAKE } SecurityObjectKind_t; -typedef enum { +typedef enum +{ CREATEDREQUEST, CREATEDREPLY - } CreatedHandshakeStep_t; typedef struct SecurityObject SecurityObject; - typedef void (*SecurityObjectDestructor)(SecurityObject *obj); -struct SecurityObject { - int64_t handle; - SecurityObjectKind_t kind; - SecurityObjectDestructor destructor; +struct SecurityObject +{ + int64_t handle; + SecurityObjectKind_t kind; + SecurityObjectDestructor destructor; }; - #ifndef NDEBUG -#define CHECK_OBJECT_KIND(o,k) assert(security_object_valid((SecurityObject *)(o), k)) +#define CHECK_OBJECT_KIND(o, k) assert(security_object_valid((SecurityObject *)(o), k)) #else -#define CHECK_OBJECT_KIND(o,k) +#define CHECK_OBJECT_KIND(o, k) #endif -#define SECURITY_OBJECT(o) ((SecurityObject *)(o)) -#define SECURITY_OBJECT_HANDLE(o) (SECURITY_OBJECT(o)->handle) -#define IDENTITY_HANDLE(o) ((DDS_Security_IdentityHandle) SECURITY_OBJECT_HANDLE(o)) -#define HANDSHAKE_HANDLE(o) ((DDS_Security_HandshakeHandle) SECURITY_OBJECT_HANDLE(o)) +#define SECURITY_OBJECT(o) ((SecurityObject *)(o)) +#define SECURITY_OBJECT_HANDLE(o) (SECURITY_OBJECT(o)->handle) +#define IDENTITY_HANDLE(o) ((DDS_Security_IdentityHandle)SECURITY_OBJECT_HANDLE(o)) +#define HANDSHAKE_HANDLE(o) ((DDS_Security_HandshakeHandle)SECURITY_OBJECT_HANDLE(o)) -#define SECURITY_OBJECT_VALID(o,k) security_object_valid((SecurityObject *)(o), k) +#define SECURITY_OBJECT_VALID(o, k) security_object_valid((SecurityObject *)(o), k) - -typedef struct LocalIdentityInfo { - SecurityObject _parent; - DDS_Security_DomainId domainId; - DDS_Security_GUID_t candidateGUID; - DDS_Security_GUID_t adjustedGUID; - X509 *identityCert; - X509 *identityCA; - EVP_PKEY *privateKey; - DDS_Security_OctetSeq pdata; - AuthenticationAlgoKind_t dsignAlgoKind; - AuthenticationAlgoKind_t kagreeAlgoKind; - char *permissionsDocument; +typedef struct LocalIdentityInfo +{ + SecurityObject _parent; + DDS_Security_DomainId domainId; + DDS_Security_GUID_t candidateGUID; + DDS_Security_GUID_t adjustedGUID; + X509 *identityCert; + X509 *identityCA; + EVP_PKEY *privateKey; + DDS_Security_OctetSeq pdata; + AuthenticationAlgoKind_t dsignAlgoKind; + AuthenticationAlgoKind_t kagreeAlgoKind; + char *permissionsDocument; } LocalIdentityInfo; -typedef struct RemoteIdentityInfo { - SecurityObject _parent; - DDS_Security_GUID_t guid; - X509 *identityCert; - AuthenticationAlgoKind_t dsignAlgoKind; - AuthenticationAlgoKind_t kagreeAlgoKind; - DDS_Security_IdentityToken *remoteIdentityToken; - DDS_Security_OctetSeq pdata; - char *permissionsDocument; - struct ddsrt_hh *linkHash; /* contains the IdentityRelation objects */ +typedef struct RemoteIdentityInfo +{ + SecurityObject _parent; + DDS_Security_GUID_t guid; + X509 *identityCert; + AuthenticationAlgoKind_t dsignAlgoKind; + AuthenticationAlgoKind_t kagreeAlgoKind; + DDS_Security_IdentityToken *remoteIdentityToken; + DDS_Security_OctetSeq pdata; + char *permissionsDocument; + struct ddsrt_hh *linkHash; /* contains the IdentityRelation objects */ } RemoteIdentityInfo; - /* This structure contains the relation between a local and a remote identity * The handle for this object is the same as the handle of the associated * local identity object. The IdentityRelation object will be stored with the * remote identity. */ -typedef struct IdentityRelation { - SecurityObject _parent; - LocalIdentityInfo *localIdentity; - RemoteIdentityInfo *remoteIdentity; - AuthenticationChallenge *lchallenge; - AuthenticationChallenge *rchallenge; +typedef struct IdentityRelation +{ + SecurityObject _parent; + LocalIdentityInfo *localIdentity; + RemoteIdentityInfo *remoteIdentity; + AuthenticationChallenge *lchallenge; + AuthenticationChallenge *rchallenge; } IdentityRelation; -typedef struct HandshakeInfo { - SecurityObject _parent; - IdentityRelation *relation; - HashValue_t hash_c1; - HashValue_t hash_c2; - EVP_PKEY *ldh; - EVP_PKEY *rdh; - DDS_Security_SharedSecretHandleImpl *shared_secret_handle_impl; - CreatedHandshakeStep_t created_in; +typedef struct HandshakeInfo +{ + SecurityObject _parent; + IdentityRelation *relation; + HashValue_t hash_c1; + HashValue_t hash_c2; + EVP_PKEY *ldh; + EVP_PKEY *rdh; + DDS_Security_SharedSecretHandleImpl *shared_secret_handle_impl; + CreatedHandshakeStep_t created_in; } HandshakeInfo; -typedef struct dds_security_authentication_impl { - dds_security_authentication base; - ddsrt_mutex_t lock; - struct ddsrt_hh *objectHash; - struct ddsrt_hh *remoteGuidHash; - struct dds_security_timed_cb_data *timed_callbacks; - struct dds_security_timed_dispatcher_t *dispatcher; - X509Seq trustedCAList; +typedef struct dds_security_authentication_impl +{ + dds_security_authentication base; + ddsrt_mutex_t lock; + struct ddsrt_hh *objectHash; + struct ddsrt_hh *remoteGuidHash; + struct dds_security_timed_cb_data *timed_callbacks; + struct dds_security_timed_dispatcher_t *dispatcher; + X509Seq trustedCAList; } dds_security_authentication_impl; /* data type for timer dispatcher */ -typedef struct { - dds_security_authentication_impl *auth; - DDS_Security_IdentityHandle hdl; +typedef struct +{ + dds_security_authentication_impl *auth; + DDS_Security_IdentityHandle hdl; } validity_cb_info; - -static bool -security_object_valid( - SecurityObject *obj, - SecurityObjectKind_t kind) +static bool security_object_valid(SecurityObject *obj, SecurityObjectKind_t kind) { - if (!obj) return false; - if (obj->kind != kind) return false; - if (kind == SECURITY_OBJECT_KIND_IDENTITY_RELATION) { - IdentityRelation *relation = (IdentityRelation *)obj; - if (!relation->localIdentity || !relation->remoteIdentity || (ddsrt_address)obj->handle != (ddsrt_address)relation->localIdentity) { - return false; - } - } else if ((ddsrt_address)obj->handle != (ddsrt_address)obj) { - return false; - } - return true; + if (!obj || obj->kind != kind) + return false; + if (kind == SECURITY_OBJECT_KIND_IDENTITY_RELATION) + { + IdentityRelation *relation = (IdentityRelation *)obj; + if (!relation->localIdentity || !relation->remoteIdentity || (ddsrt_address)obj->handle != (ddsrt_address)relation->localIdentity) + return false; + } + else if ((ddsrt_address)obj->handle != (ddsrt_address)obj) + return false; + return true; } -static uint32_t -security_object_hash ( - const void *obj) +static uint32_t security_object_hash(const void *obj) { - const SecurityObject *object = obj; -#define UINT64_CONST(x, y, z) (((uint64_t) (x) * 1000000 + (y)) * 1000000 + (z)) - const uint64_t c = UINT64_CONST (16292676, 669999, 574021); -#undef UINT64_CONST - const uint32_t x = (uint32_t) object->handle; - return (unsigned) ((x * c) >> 32); + const SecurityObject *object = obj; + const uint64_t c = UINT64_C (16292676669999574021); + const uint32_t x = (uint32_t)object->handle; + return (uint32_t)((x * c) >> 32); } -static int -security_object_equal ( - const void *ha, - const void *hb) +static int security_object_equal(const void *ha, const void *hb) { - const SecurityObject *la = ha; - const SecurityObject *lb = hb; - - return la->handle == lb->handle; + const SecurityObject *la = ha; + const SecurityObject *lb = hb; + return la->handle == lb->handle; } -static SecurityObject * -security_object_find( - const struct ddsrt_hh *hh, - int64_t handle) +static SecurityObject *security_object_find(const struct ddsrt_hh *hh, int64_t handle) { - struct SecurityObject template; - - template.handle = handle; - - return (SecurityObject *) ddsrt_hh_lookup(hh, &template);; + struct SecurityObject template; + template.handle = handle; + return (SecurityObject *)ddsrt_hh_lookup(hh, &template); } -static void -security_object_init( - SecurityObject *obj, - SecurityObjectKind_t kind, - SecurityObjectDestructor destructor) +static void security_object_init(SecurityObject *obj, SecurityObjectKind_t kind, SecurityObjectDestructor destructor) { - assert(obj); - - obj->kind = kind; - obj->handle = (int64_t)(ddsrt_address)obj; - obj->destructor = destructor; + assert(obj); + obj->kind = kind; + obj->handle = (int64_t)(ddsrt_address)obj; + obj->destructor = destructor; } -static void -security_object_deinit( - SecurityObject *obj) - +static void security_object_deinit(SecurityObject *obj) { - assert(obj); - obj->handle = DDS_SECURITY_HANDLE_NIL; - obj->kind = SECURITY_OBJECT_KIND_UNKNOWN; - obj->destructor = NULL; + assert(obj); + obj->handle = DDS_SECURITY_HANDLE_NIL; + obj->kind = SECURITY_OBJECT_KIND_UNKNOWN; + obj->destructor = NULL; } -static void -security_object_free( - SecurityObject *obj) +static void security_object_free(SecurityObject *obj) { - assert(obj); - if (obj && obj->destructor) { - obj->destructor(obj); - } + assert(obj); + if (obj && obj->destructor) + obj->destructor(obj); } -static void -localIdentityInfoFree( - SecurityObject *obj); - - - -static LocalIdentityInfo * -localIdentityInfoNew( - DDS_Security_DomainId domainId, - X509 *identityCert, - X509 *identityCa, - EVP_PKEY *privateKey, - const DDS_Security_GUID_t *candidate_participant_guid, - const DDS_Security_GUID_t *adjusted_participant_guid) +static void local_identity_info_free(SecurityObject *obj) { - LocalIdentityInfo *identity = NULL; - - assert(identityCert); - assert(identityCa); - assert(privateKey); - assert(candidate_participant_guid); - assert(adjusted_participant_guid); - assert(sizeof(DDS_Security_IdentityHandle) == 8); - - identity = ddsrt_malloc(sizeof(*identity)); - memset(identity, 0, sizeof(*identity)); - - security_object_init((SecurityObject *)identity, SECURITY_OBJECT_KIND_LOCAL_IDENTITY, localIdentityInfoFree); - - - - - identity->domainId = domainId; - identity->identityCert = identityCert; - identity->identityCA = identityCa; - identity->privateKey = privateKey; - identity->permissionsDocument = NULL; - identity->dsignAlgoKind = get_auhentication_algo_kind(identityCert); - identity->kagreeAlgoKind = AUTH_ALGO_KIND_EC_PRIME256V1; - - memcpy(&identity->candidateGUID, candidate_participant_guid, sizeof(DDS_Security_GUID_t)); - memcpy(&identity->adjustedGUID, adjusted_participant_guid, sizeof(DDS_Security_GUID_t)); - - return identity; + LocalIdentityInfo *identity = (LocalIdentityInfo *)obj; + CHECK_OBJECT_KIND(obj, SECURITY_OBJECT_KIND_LOCAL_IDENTITY); + if (identity) + { + if (identity->identityCert) + X509_free(identity->identityCert); + if (identity->identityCA) + X509_free(identity->identityCA); + if (identity->privateKey) + EVP_PKEY_free(identity->privateKey); + ddsrt_free(identity->pdata._buffer); + ddsrt_free(identity->permissionsDocument); + security_object_deinit((SecurityObject *)identity); + ddsrt_free(identity); + } } -static void -localIdentityInfoFree( - SecurityObject *obj) +static LocalIdentityInfo *local_identity_info_new(DDS_Security_DomainId domainId, X509 *identityCert, X509 *identityCa, EVP_PKEY *privateKey, const DDS_Security_GUID_t *candidate_participant_guid, const DDS_Security_GUID_t *adjusted_participant_guid) { - LocalIdentityInfo *identity = (LocalIdentityInfo *)obj; + LocalIdentityInfo *identity = NULL; + assert(identityCert); + assert(identityCa); + assert(privateKey); + assert(candidate_participant_guid); + assert(adjusted_participant_guid); + assert(sizeof(DDS_Security_IdentityHandle) == 8); - CHECK_OBJECT_KIND(obj, SECURITY_OBJECT_KIND_LOCAL_IDENTITY); + identity = ddsrt_malloc(sizeof(*identity)); + memset(identity, 0, sizeof(*identity)); - if (identity) { - if (identity->identityCert) { - X509_free(identity->identityCert); - } - if (identity->identityCA) { - X509_free(identity->identityCA); - } - if (identity->privateKey) { - EVP_PKEY_free(identity->privateKey); - } - ddsrt_free(identity->pdata._buffer); - ddsrt_free(identity->permissionsDocument); - security_object_deinit((SecurityObject *)identity); - ddsrt_free(identity); - } + security_object_init((SecurityObject *)identity, SECURITY_OBJECT_KIND_LOCAL_IDENTITY, local_identity_info_free); + + identity->domainId = domainId; + identity->identityCert = identityCert; + identity->identityCA = identityCa; + identity->privateKey = privateKey; + identity->permissionsDocument = NULL; + identity->dsignAlgoKind = get_authentication_algo_kind(identityCert); + identity->kagreeAlgoKind = AUTH_ALGO_KIND_EC_PRIME256V1; + + memcpy(&identity->candidateGUID, candidate_participant_guid, sizeof(DDS_Security_GUID_t)); + memcpy(&identity->adjustedGUID, adjusted_participant_guid, sizeof(DDS_Security_GUID_t)); + + return identity; } -static uint32_t -remote_guid_hash ( - const void *obj) +static uint32_t remote_guid_hash(const void *obj) { - const RemoteIdentityInfo *identity = obj; - uint32_t tmp[4]; - - memcpy(tmp, &identity->guid, sizeof(tmp)); - - return (tmp[0]^tmp[1]^tmp[2]^tmp[3]); + const RemoteIdentityInfo *identity = obj; + uint32_t tmp[4]; + memcpy(tmp, &identity->guid, sizeof(tmp)); + return (tmp[0] ^ tmp[1] ^ tmp[2] ^ tmp[3]); } -static int -remote_guid_equal ( - const void *ha, - const void *hb) +static int remote_guid_equal(const void *ha, const void *hb) { - const RemoteIdentityInfo *la = ha; - const RemoteIdentityInfo *lb = hb; - - return memcmp(&la->guid, &lb->guid, sizeof(la->guid)) == 0; + const RemoteIdentityInfo *la = ha; + const RemoteIdentityInfo *lb = hb; + return memcmp(&la->guid, &lb->guid, sizeof(la->guid)) == 0; } -static RemoteIdentityInfo * -find_remote_identity_by_guid( - const struct ddsrt_hh *hh, - const DDS_Security_GUID_t *guid) +static RemoteIdentityInfo *find_remote_identity_by_guid(const struct ddsrt_hh *hh, const DDS_Security_GUID_t *guid) { - struct RemoteIdentityInfo template; - - memcpy(&template.guid, guid, sizeof(*guid)); - - return (RemoteIdentityInfo *) ddsrt_hh_lookup(hh, &template); + struct RemoteIdentityInfo template; + memcpy(&template.guid, guid, sizeof(*guid)); + return (RemoteIdentityInfo *)ddsrt_hh_lookup(hh, &template); } -static void -remoteIdentityInfoFree( - SecurityObject *obj); - -static RemoteIdentityInfo * -remoteIdentityInfoNew( - const DDS_Security_GUID_t *guid, - const DDS_Security_IdentityToken *remote_identity_token) +static void remote_identity_info_free(SecurityObject *obj) { - RemoteIdentityInfo *identity = NULL; - - assert(guid); - assert(remote_identity_token); - - identity = ddsrt_malloc(sizeof(*identity)); - memset(identity, 0, sizeof(*identity)); - - security_object_init((SecurityObject *)identity, SECURITY_OBJECT_KIND_REMOTE_IDENTITY, remoteIdentityInfoFree); - - memcpy(&identity->guid, guid, sizeof(DDS_Security_GUID_t)); - identity->remoteIdentityToken = DDS_Security_DataHolder_alloc(); - DDS_Security_DataHolder_copy(identity->remoteIdentityToken, remote_identity_token); - identity->identityCert = NULL; - identity->dsignAlgoKind = AUTH_ALGO_KIND_UNKNOWN; - identity->kagreeAlgoKind = AUTH_ALGO_KIND_UNKNOWN; - identity->permissionsDocument = ddsrt_strdup(""); - identity->linkHash = ddsrt_hh_new(32, security_object_hash, security_object_equal); - - return identity; + RemoteIdentityInfo *identity = (RemoteIdentityInfo *)obj; + CHECK_OBJECT_KIND(obj, SECURITY_OBJECT_KIND_REMOTE_IDENTITY); + if (identity) + { + if (identity->identityCert) + X509_free(identity->identityCert); + DDS_Security_DataHolder_free(identity->remoteIdentityToken); + ddsrt_hh_free(identity->linkHash); + ddsrt_free(identity->pdata._buffer); + ddsrt_free(identity->permissionsDocument); + security_object_deinit((SecurityObject *)identity); + ddsrt_free(identity); + } } -static void -remoteIdentityInfoFree( - SecurityObject *obj) +static RemoteIdentityInfo *remote_identity_info_new(const DDS_Security_GUID_t *guid, const DDS_Security_IdentityToken *remote_identity_token) { - RemoteIdentityInfo *identity = (RemoteIdentityInfo *)obj; + assert(guid); + assert(remote_identity_token); - CHECK_OBJECT_KIND(obj, SECURITY_OBJECT_KIND_REMOTE_IDENTITY); - - if (identity) { - if (identity->identityCert) { - X509_free(identity->identityCert); - } - DDS_Security_DataHolder_free(identity->remoteIdentityToken); - - ddsrt_hh_free(identity->linkHash); - - ddsrt_free(identity->pdata._buffer); - ddsrt_free(identity->permissionsDocument); - security_object_deinit((SecurityObject *)identity); - ddsrt_free(identity); - } + RemoteIdentityInfo *identity = ddsrt_malloc(sizeof(*identity)); + memset(identity, 0, sizeof(*identity)); + security_object_init((SecurityObject *)identity, SECURITY_OBJECT_KIND_REMOTE_IDENTITY, remote_identity_info_free); + memcpy(&identity->guid, guid, sizeof(DDS_Security_GUID_t)); + identity->remoteIdentityToken = DDS_Security_DataHolder_alloc(); + DDS_Security_DataHolder_copy(identity->remoteIdentityToken, remote_identity_token); + identity->identityCert = NULL; + identity->dsignAlgoKind = AUTH_ALGO_KIND_UNKNOWN; + identity->kagreeAlgoKind = AUTH_ALGO_KIND_UNKNOWN; + identity->permissionsDocument = ddsrt_strdup(""); + identity->linkHash = ddsrt_hh_new(32, security_object_hash, security_object_equal); + return identity; } -static void -identityRelationFree( - SecurityObject *obj); +static void identity_relation_free(SecurityObject *obj) +{ + IdentityRelation *relation = (IdentityRelation *)obj; + CHECK_OBJECT_KIND(obj, SECURITY_OBJECT_KIND_IDENTITY_RELATION); + if (relation) + { + ddsrt_free(relation->lchallenge); + ddsrt_free(relation->rchallenge); + security_object_deinit((SecurityObject *)relation); + ddsrt_free(relation); + } +} /* The IdentityRelation provides the association between a local and a remote * identity. This object manages the challenges which are created for @@ -474,1462 +395,1056 @@ identityRelationFree( * The rchallenge is the challenge received from the remote identity it may be set when * an auth_request_message_token is received from the remote identity, */ -static IdentityRelation * -identityRelationNew( - LocalIdentityInfo *localIdentity, - RemoteIdentityInfo *remoteIdentity, - AuthenticationChallenge *lchallenge, - AuthenticationChallenge *rchallenge) +static IdentityRelation *identity_relation_new(LocalIdentityInfo *localIdentity, RemoteIdentityInfo *remoteIdentity, AuthenticationChallenge *lchallenge, AuthenticationChallenge *rchallenge) { - IdentityRelation *relation; - - assert(localIdentity); - assert(remoteIdentity); - - relation = ddsrt_malloc(sizeof(*relation)); - memset(relation, 0, sizeof(*relation)); - - security_object_init((SecurityObject *)relation, SECURITY_OBJECT_KIND_IDENTITY_RELATION, identityRelationFree); - relation->_parent.handle = SECURITY_OBJECT_HANDLE(localIdentity); - - relation->localIdentity = localIdentity; - relation->remoteIdentity = remoteIdentity; - relation->lchallenge = lchallenge; - relation->rchallenge = rchallenge; - - return relation; + IdentityRelation *relation; + assert(localIdentity); + assert(remoteIdentity); + relation = ddsrt_malloc(sizeof(*relation)); + memset(relation, 0, sizeof(*relation)); + security_object_init((SecurityObject *)relation, SECURITY_OBJECT_KIND_IDENTITY_RELATION, identity_relation_free); + relation->_parent.handle = SECURITY_OBJECT_HANDLE(localIdentity); + relation->localIdentity = localIdentity; + relation->remoteIdentity = remoteIdentity; + relation->lchallenge = lchallenge; + relation->rchallenge = rchallenge; + return relation; } -static void -identityRelationFree( - SecurityObject *obj) +static void handshake_info_free(SecurityObject *obj) { - IdentityRelation *relation = (IdentityRelation *)obj; - - CHECK_OBJECT_KIND(obj, SECURITY_OBJECT_KIND_IDENTITY_RELATION); - - if (relation) { - ddsrt_free(relation->lchallenge); - ddsrt_free(relation->rchallenge); - security_object_deinit((SecurityObject *)relation); - ddsrt_free(relation); + CHECK_OBJECT_KIND(obj, SECURITY_OBJECT_KIND_HANDSHAKE); + HandshakeInfo *handshake = (HandshakeInfo *)obj; + if (handshake) + { + if (handshake->ldh) + EVP_PKEY_free(handshake->ldh); + if (handshake->rdh) + EVP_PKEY_free(handshake->rdh); + if (handshake->shared_secret_handle_impl) + { + ddsrt_free(handshake->shared_secret_handle_impl->shared_secret); + ddsrt_free(handshake->shared_secret_handle_impl); } + security_object_deinit((SecurityObject *)handshake); + ddsrt_free(handshake); + } } -static void -handshakeInfoFree( - SecurityObject *obj); - -static HandshakeInfo * -handshakeInfoNew( - LocalIdentityInfo *localIdentity, - RemoteIdentityInfo *remoteIdentity, - IdentityRelation *relation) +static HandshakeInfo *handshake_info_new(LocalIdentityInfo *localIdentity, RemoteIdentityInfo *remoteIdentity, IdentityRelation *relation) { - HandshakeInfo *handshake; - - assert(localIdentity); - assert(remoteIdentity); - - DDSRT_UNUSED_ARG(localIdentity); - DDSRT_UNUSED_ARG(remoteIdentity); - handshake = ddsrt_malloc(sizeof(*handshake)); - memset(handshake, 0, sizeof(*handshake)); - - security_object_init((SecurityObject *)handshake, SECURITY_OBJECT_KIND_HANDSHAKE, handshakeInfoFree); - - handshake->relation = relation; - handshake->shared_secret_handle_impl = NULL; - - return handshake; + assert(localIdentity); + assert(remoteIdentity); + DDSRT_UNUSED_ARG(localIdentity); + DDSRT_UNUSED_ARG(remoteIdentity); + HandshakeInfo *handshake = ddsrt_malloc(sizeof(*handshake)); + memset(handshake, 0, sizeof(*handshake)); + security_object_init((SecurityObject *)handshake, SECURITY_OBJECT_KIND_HANDSHAKE, handshake_info_free); + handshake->relation = relation; + handshake->shared_secret_handle_impl = NULL; + return handshake; } -static void -handshakeInfoFree( - SecurityObject *obj) +static IdentityRelation *find_identity_relation(const RemoteIdentityInfo *remote, int64_t lid) { - HandshakeInfo *handshake = (HandshakeInfo *)obj; + return (IdentityRelation *)security_object_find(remote->linkHash, lid); +} - CHECK_OBJECT_KIND(obj, SECURITY_OBJECT_KIND_HANDSHAKE); +static void remove_identity_relation(RemoteIdentityInfo *remote, IdentityRelation *relation) +{ + (void)ddsrt_hh_remove(remote->linkHash, relation); + security_object_free((SecurityObject *)relation); +} - if (handshake) { - if (handshake->ldh) { - EVP_PKEY_free(handshake->ldh); - } - if (handshake->rdh) { - EVP_PKEY_free(handshake->rdh); - } - if(handshake->shared_secret_handle_impl) { - ddsrt_free( handshake->shared_secret_handle_impl->shared_secret); - ddsrt_free( handshake->shared_secret_handle_impl ); - } - security_object_deinit((SecurityObject *)handshake); - ddsrt_free(handshake); +static HandshakeInfo *find_handshake(const dds_security_authentication_impl *auth, int64_t localId, int64_t remoteId) +{ + struct ddsrt_hh_iter it; + SecurityObject *obj; + for (obj = ddsrt_hh_iter_first(auth->objectHash, &it); obj; obj = ddsrt_hh_iter_next(&it)) + { + if (obj->kind == SECURITY_OBJECT_KIND_HANDSHAKE) + { + IdentityRelation *relation = ((HandshakeInfo *)obj)->relation; + assert(relation); + if (SECURITY_OBJECT_HANDLE(relation->localIdentity) == localId && SECURITY_OBJECT_HANDLE(relation->remoteIdentity) == remoteId) + return (HandshakeInfo *)obj; } + } + return NULL; } -static IdentityRelation * -find_identity_relation( - const RemoteIdentityInfo *remote, - int64_t lid) +static char * get_authentication_class_id(void) { - return (IdentityRelation *)security_object_find(remote->linkHash, lid); + size_t sz = strlen(AUTH_PROTOCOL_CLASS) + 5; + char *classId = ddsrt_malloc(sz); + snprintf(classId, sz, "%s:%1u.%1u", AUTH_PROTOCOL_CLASS, AUTH_PROTOCOL_VERSION_MAJOR, AUTH_PROTOCOL_VERSION_MINOR); + return classId; } -static void -remove_identity_relation( - RemoteIdentityInfo *remote, - IdentityRelation *relation) +static const char *get_authentication_algo(AuthenticationAlgoKind_t kind) { - (void)ddsrt_hh_remove(remote->linkHash, relation); - security_object_free((SecurityObject *) relation); + switch (kind) + { + case AUTH_ALGO_KIND_RSA_2048: + return "RSA-2048"; + case AUTH_ALGO_KIND_EC_PRIME256V1: + return "EC-prime256v1"; + default: + assert(0); + return ""; + } } -static HandshakeInfo * -find_handshake( - const dds_security_authentication_impl *auth, - int64_t localId, - int64_t remoteId) +static const char *get_dsign_algo(AuthenticationAlgoKind_t kind) { - struct ddsrt_hh_iter it; - SecurityObject *obj; - IdentityRelation *relation; - HandshakeInfo *found = NULL; - - for (obj = ddsrt_hh_iter_first(auth->objectHash, &it); obj && !found; obj = ddsrt_hh_iter_next(&it)) { - if (obj->kind == SECURITY_OBJECT_KIND_HANDSHAKE) { - relation = ((HandshakeInfo *)obj)->relation; - assert(relation); - if ((SECURITY_OBJECT_HANDLE(relation->localIdentity) == localId) && - (SECURITY_OBJECT_HANDLE(relation->remoteIdentity) == remoteId)) { - found = (HandshakeInfo *)obj; - } - } - } - - return found; + switch (kind) + { + case AUTH_ALGO_KIND_RSA_2048: + return AUTH_DSIG_ALGO_RSA_2048_SHA256_IDENT; + case AUTH_ALGO_KIND_EC_PRIME256V1: + return AUTH_DSIG_ALGO_ECDSA_SHA256_IDENT; + default: + assert(0); + return ""; + } } -static char * -get_authentication_class_id( - void) +static const char *get_kagree_algo(AuthenticationAlgoKind_t kind) { - char *classId; - size_t sz; - - sz = strlen(AUTH_PROTOCOL_CLASS) + 5; - - classId = ddsrt_malloc(sz); - snprintf(classId, sz, "%s:%1u.%1u", AUTH_PROTOCOL_CLASS, AUTH_PROTOCOL_VERSION_MAJOR, AUTH_PROTOCOL_VERSION_MINOR); - - return classId; + switch (kind) + { + case AUTH_ALGO_KIND_RSA_2048: + return AUTH_KAGREE_ALGO_RSA_2048_SHA256_IDENT; + case AUTH_ALGO_KIND_EC_PRIME256V1: + return AUTH_KAGREE_ALGO_ECDH_PRIME256V1_IDENT; + default: + assert(0); + return ""; + } } -static const char * -get_authentication_algo( - AuthenticationAlgoKind_t kind) +static AuthenticationAlgoKind_t get_dsign_algo_from_string(const char *name) { - const char *result; - switch (kind) { - case AUTH_ALGO_KIND_RSA_2048: - result = "RSA-2048"; - break; - case AUTH_ALGO_KIND_EC_PRIME256V1: - result = "EC-prime256v1"; - break; - default: - assert(0); - result = ""; - break; - } - - return result; + if (name) + { + if (strcmp(AUTH_DSIG_ALGO_RSA_2048_SHA256_IDENT, name) == 0) + return AUTH_ALGO_KIND_RSA_2048; + if (strcmp(AUTH_DSIG_ALGO_ECDSA_SHA256_IDENT, name) == 0) + return AUTH_ALGO_KIND_EC_PRIME256V1; + } + return AUTH_ALGO_KIND_UNKNOWN; } -static const char * -get_dsign_algo( - AuthenticationAlgoKind_t kind) +static AuthenticationAlgoKind_t get_kagree_algo_from_string(const char *name) { - const char *result; - switch (kind) { - case AUTH_ALGO_KIND_RSA_2048: - result = AUTH_DSIG_ALGO_RSA_2048_SHA256_IDENT; - break; - case AUTH_ALGO_KIND_EC_PRIME256V1: - result = AUTH_DSIG_ALGO_ECDSA_SHA256_IDENT; - break; - default: - assert(0); - result = ""; - break; - } - - return result; + if (name) + { + if (strcmp(AUTH_KAGREE_ALGO_RSA_2048_SHA256_IDENT, name) == 0) + return AUTH_ALGO_KIND_RSA_2048; + if (strcmp(AUTH_KAGREE_ALGO_ECDH_PRIME256V1_IDENT, name) == 0) + return AUTH_ALGO_KIND_EC_PRIME256V1; + } + return AUTH_ALGO_KIND_UNKNOWN; } -static const char * -get_kagree_algo( - AuthenticationAlgoKind_t kind) +static void free_binary_properties(DDS_Security_BinaryProperty_t *seq, uint32_t length) { - const char *result; - switch (kind) { - case AUTH_ALGO_KIND_RSA_2048: - result = AUTH_KAGREE_ALGO_RSA_2048_SHA256_IDENT; - break; - case AUTH_ALGO_KIND_EC_PRIME256V1: - result = AUTH_KAGREE_ALGO_ECDH_PRIME256V1_IDENT; - break; - default: - assert(0); - result = ""; - break; - } - - return result; + assert(seq); + for (uint32_t i = 0; i < length; i++) + { + ddsrt_free(seq[i].name); + ddsrt_free(seq[i].value._buffer); + } + ddsrt_free(seq); } -static AuthenticationAlgoKind_t -get_dsign_algo_from_string( - const char *name) +static void get_hash_binary_property_seq(const DDS_Security_BinaryPropertySeq *seq, unsigned char hash[SHA256_DIGEST_LENGTH]) { - AuthenticationAlgoKind_t algoKind = AUTH_ALGO_KIND_UNKNOWN; - - if (name) { - if (strcmp(AUTH_DSIG_ALGO_RSA_2048_SHA256_IDENT, name) == 0) { - algoKind = AUTH_ALGO_KIND_RSA_2048; - } else if (strcmp(AUTH_DSIG_ALGO_ECDSA_SHA256_IDENT, name) == 0) { - algoKind = AUTH_ALGO_KIND_EC_PRIME256V1; - } - } - - return algoKind; + unsigned char *buffer; + size_t size; + DDS_Security_Serializer serializer = DDS_Security_Serializer_new(4096, 4096); + DDS_Security_Serialize_BinaryPropertySeq(serializer, seq); + DDS_Security_Serializer_buffer(serializer, &buffer, &size); + SHA256(buffer, size, hash); + ddsrt_free(buffer); + DDS_Security_Serializer_free(serializer); } -static AuthenticationAlgoKind_t -get_kagree_algo_from_string( - const char *name) +static DDS_Security_ValidationResult_t create_signature(EVP_PKEY *pkey, const DDS_Security_BinaryProperty_t **binary_properties, + const uint32_t binary_properties_length, unsigned char **signature, size_t *signatureLen, DDS_Security_SecurityException *ex) { - AuthenticationAlgoKind_t algoKind = AUTH_ALGO_KIND_UNKNOWN; + DDS_Security_ValidationResult_t result; + unsigned char *buffer; + size_t size; + DDS_Security_Serializer serializer = DDS_Security_Serializer_new(4096, 4096); - if (name) { - if (strcmp(AUTH_KAGREE_ALGO_RSA_2048_SHA256_IDENT, name) == 0) { - algoKind = AUTH_ALGO_KIND_RSA_2048; - } else if (strcmp(AUTH_KAGREE_ALGO_ECDH_PRIME256V1_IDENT, name) == 0) { - algoKind = AUTH_ALGO_KIND_EC_PRIME256V1; - } - } + DDS_Security_Serialize_BinaryPropertyArray(serializer, binary_properties, binary_properties_length); + DDS_Security_Serializer_buffer(serializer, &buffer, &size); - return algoKind; + result = create_asymmetrical_signature(pkey, buffer, size, signature, signatureLen, ex); + ddsrt_free(buffer); + DDS_Security_Serializer_free(serializer); + + return result; } -static void -free_binary_properties( - DDS_Security_BinaryProperty_t *seq, - uint32_t length) +static DDS_Security_ValidationResult_t validate_signature(EVP_PKEY *pkey, const DDS_Security_BinaryProperty_t **properties, + const uint32_t properties_length, unsigned char *signature, size_t signatureLen, DDS_Security_SecurityException *ex) { - uint32_t i; - assert (seq); - for (i = 0; i < length; i++) { - ddsrt_free(seq[i].name); - ddsrt_free(seq[i].value._buffer); - } - ddsrt_free(seq); + DDS_Security_ValidationResult_t result; + unsigned char *buffer; + size_t size; + DDS_Security_Serializer serializer = DDS_Security_Serializer_new(4096, 4096); + + DDS_Security_Serialize_BinaryPropertyArray(serializer, properties, properties_length); + DDS_Security_Serializer_buffer(serializer, &buffer, &size); + + result = validate_asymmetrical_signature(pkey, buffer, size, signature, signatureLen, ex); + ddsrt_free(buffer); + DDS_Security_Serializer_free(serializer); + + return result; } -static void -get_hash_binary_property_seq( - const DDS_Security_BinaryPropertySeq *seq, - unsigned char hash[SHA256_DIGEST_LENGTH]) +static DDS_Security_ValidationResult_t compute_hash_value(HashValue_t value, const DDS_Security_BinaryProperty_t **properties, + const uint32_t properties_length, DDS_Security_SecurityException *ex) { - DDS_Security_Serializer serializer; - unsigned char *buffer; - size_t size; - - serializer = DDS_Security_Serializer_new(4096, 4096); - - DDS_Security_Serialize_BinaryPropertySeq(serializer, seq); - DDS_Security_Serializer_buffer(serializer, &buffer, &size); - SHA256(buffer, size, hash); - ddsrt_free(buffer); - DDS_Security_Serializer_free(serializer); + DDSRT_UNUSED_ARG(ex); + unsigned char *buffer; + size_t size; + DDS_Security_Serializer serializer = DDS_Security_Serializer_new(4096, 4096); + DDS_Security_Serialize_BinaryPropertyArray(serializer, properties, properties_length); + DDS_Security_Serializer_buffer(serializer, &buffer, &size); + SHA256(buffer, size, value); + ddsrt_free(buffer); + DDS_Security_Serializer_free(serializer); + return DDS_SECURITY_VALIDATION_OK; } -static DDS_Security_ValidationResult_t -create_signature( - EVP_PKEY *pkey, - const DDS_Security_BinaryProperty_t **binary_properties, - const uint32_t binary_properties_length, - unsigned char **signature, - size_t *signatureLen, - DDS_Security_SecurityException *ex) +static DDS_Security_BinaryProperty_t *hash_value_to_binary_property(const char *name, HashValue_t hash) { - DDS_Security_ValidationResult_t result; - DDS_Security_Serializer serializer; - unsigned char *buffer; - size_t size; - - serializer = DDS_Security_Serializer_new(4096, 4096); - - DDS_Security_Serialize_BinaryPropertyArray(serializer,binary_properties, binary_properties_length); - DDS_Security_Serializer_buffer(serializer, &buffer, &size); - - result = create_asymmetrical_signature(pkey, buffer, size, signature, signatureLen, ex); - ddsrt_free(buffer); - DDS_Security_Serializer_free(serializer); - - return result; + DDS_Security_BinaryProperty_t *bp = DDS_Security_BinaryProperty_alloc(); + DDS_Security_BinaryProperty_set_by_value(bp, name, hash, sizeof(HashValue_t)); + return bp; } -static DDS_Security_ValidationResult_t -validate_signature( - EVP_PKEY *pkey, - const DDS_Security_BinaryProperty_t **properties, - const uint32_t properties_length, - unsigned char *signature, - size_t signatureLen, - DDS_Security_SecurityException *ex) +static void validity_callback(struct dds_security_timed_dispatcher_t *d, dds_security_timed_cb_kind kind, void *listener, void *arg) { - DDS_Security_ValidationResult_t result; - DDS_Security_Serializer serializer; - unsigned char *buffer; - size_t size; - - serializer = DDS_Security_Serializer_new(4096, 4096); - - DDS_Security_Serialize_BinaryPropertyArray(serializer, properties, properties_length); - DDS_Security_Serializer_buffer(serializer, &buffer, &size); - - result = validate_asymmetrical_signature(pkey, buffer, size, signature, signatureLen, ex); - ddsrt_free(buffer); - DDS_Security_Serializer_free(serializer); - - return result; + DDSRT_UNUSED_ARG(d); + assert(d); + assert(arg); + validity_cb_info *info = arg; + if (kind == DDS_SECURITY_TIMED_CB_KIND_TIMEOUT) + { + assert(listener); + dds_security_authentication_listener *auth_listener = (dds_security_authentication_listener *)listener; + if (auth_listener->on_revoke_identity) + auth_listener->on_revoke_identity(auth_listener, (dds_security_authentication *)info->auth, info->hdl); + } + ddsrt_free(arg); } -static DDS_Security_ValidationResult_t -compute_hash_value( - HashValue_t value, - const DDS_Security_BinaryProperty_t **properties, - const uint32_t properties_length, - DDS_Security_SecurityException *ex) +static void add_validity_end_trigger(dds_security_authentication_impl *auth, const DDS_Security_IdentityHandle identity_handle, dds_time_t end) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - DDS_Security_Serializer serializer; - unsigned char *buffer; - size_t size; - - DDSRT_UNUSED_ARG(ex); - - serializer = DDS_Security_Serializer_new(4096, 4096); - - DDS_Security_Serialize_BinaryPropertyArray(serializer, properties, properties_length); - DDS_Security_Serializer_buffer(serializer, &buffer, &size); - SHA256(buffer, size, value); - ddsrt_free(buffer); - DDS_Security_Serializer_free(serializer); - - return result; + validity_cb_info *arg = ddsrt_malloc(sizeof(validity_cb_info)); + arg->auth = auth; + arg->hdl = identity_handle; + dds_security_timed_dispatcher_add(auth->timed_callbacks, auth->dispatcher, validity_callback, end, (void *)arg); } -static DDS_Security_BinaryProperty_t * -hash_value_to_binary_property( - const char *name, - HashValue_t hash) +static DDS_Security_ValidationResult_t get_adjusted_participant_guid(X509 *cert, const DDS_Security_GUID_t *candidate, DDS_Security_GUID_t *adjusted, DDS_Security_SecurityException *ex) { - DDS_Security_BinaryProperty_t *bp = DDS_Security_BinaryProperty_alloc(); + unsigned char high[SHA256_DIGEST_LENGTH], low[SHA256_DIGEST_LENGTH]; + unsigned char *subject = NULL; + size_t size = 0; - DDS_Security_BinaryProperty_set_by_value(bp, name, hash, sizeof(HashValue_t)); + assert(cert); + assert(candidate); + assert(adjusted); - return bp; -} + if (get_subject_name_DER_encoded(cert, &subject, &size, ex) != DDS_SECURITY_VALIDATION_OK) + return DDS_SECURITY_VALIDATION_FAILED; -static void -validity_callback(struct dds_security_timed_dispatcher_t *d, - dds_security_timed_cb_kind kind, - void *listener, - void *arg) -{ - validity_cb_info *info = arg; - - DDSRT_UNUSED_ARG(d); - assert(d); - assert(arg); - - if (kind == DDS_SECURITY_TIMED_CB_KIND_TIMEOUT) { - assert(listener); - dds_security_authentication_listener *auth_listener = (dds_security_authentication_listener*)listener; - if (auth_listener->on_revoke_identity) { - auth_listener->on_revoke_identity(auth_listener, - (dds_security_authentication*)info->auth, - info->hdl); - - } - } - ddsrt_free(arg); -} - - -static void -add_validity_end_trigger(dds_security_authentication_impl *auth, - const DDS_Security_IdentityHandle identity_handle, - dds_time_t end) -{ - validity_cb_info *arg = ddsrt_malloc(sizeof(validity_cb_info)); - arg->auth = auth; - arg->hdl = identity_handle; - dds_security_timed_dispatcher_add(auth->timed_callbacks, auth->dispatcher, - validity_callback, - end, - (void*)arg); -} - - - -#define ADJUSTED_GUID_PREFIX_FLAG 0x80 - -static DDS_Security_ValidationResult_t -get_adjusted_participant_guid( - X509 *cert, - const DDS_Security_GUID_t *candidate, - DDS_Security_GUID_t *adjusted, - DDS_Security_SecurityException *ex) -{ - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_FAILED; - unsigned char high[SHA256_DIGEST_LENGTH], low[SHA256_DIGEST_LENGTH]; - unsigned char *subject = NULL; - size_t size=0; - - assert(cert); - assert(candidate); - assert(adjusted); - - result = get_subject_name_DER_encoded(cert, &subject, &size, ex); - if ( result == DDS_SECURITY_VALIDATION_OK ) { - DDS_Security_octet hb = ADJUSTED_GUID_PREFIX_FLAG; - int i; - - SHA256(subject, size, high); - SHA256(&candidate->prefix[0], sizeof(DDS_Security_GuidPrefix_t), low); - - adjusted->entityId = candidate->entityId; - for (i = 0; i < 6; i++) { - adjusted->prefix[i] = hb | high[i] >> 1; - hb = (DDS_Security_octet) (high[i] << 7); - } - for (i = 0; i < 6; i++) { - adjusted->prefix[i + 6] = low[i]; - } - ddsrt_free(subject); - } - - return result; + DDS_Security_octet hb = ADJUSTED_GUID_PREFIX_FLAG; + SHA256(subject, size, high); + SHA256(&candidate->prefix[0], sizeof(DDS_Security_GuidPrefix_t), low); + adjusted->entityId = candidate->entityId; + for (int i = 0; i < 6; i++) + { + adjusted->prefix[i] = hb | high[i] >> 1; + hb = (DDS_Security_octet)(high[i] << 7); + } + for (int i = 0; i < 6; i++) + adjusted->prefix[i + 6] = low[i]; + ddsrt_free(subject); + return DDS_SECURITY_VALIDATION_OK; } #undef ADJUSTED_GUID_PREFIX_FLAG -DDS_Security_ValidationResult_t -validate_local_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *local_identity_handle, - DDS_Security_GUID_t *adjusted_participant_guid, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - const DDS_Security_GUID_t *candidate_participant_guid, - DDS_Security_SecurityException *ex) +DDS_Security_ValidationResult_t validate_local_identity(dds_security_authentication *instance, DDS_Security_IdentityHandle *local_identity_handle, + DDS_Security_GUID_t *adjusted_participant_guid, const DDS_Security_DomainId domain_id, const DDS_Security_Qos *participant_qos, + const DDS_Security_GUID_t *candidate_participant_guid, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - dds_security_authentication_impl *implementation = (dds_security_authentication_impl *) instance; - LocalIdentityInfo *identity; - char *identityCertPEM; - char *identityCaPEM; - char *privateKeyPEM; - char *password; - X509 *identityCert; - X509 *identityCA; - EVP_PKEY *privateKey; - char *trusted_ca_dir; - unsigned i; - dds_time_t certExpiry = DDS_TIME_INVALID; + dds_security_authentication_impl *implementation = (dds_security_authentication_impl *)instance; + LocalIdentityInfo *identity; + char *identityCertPEM, *identityCaPEM, *privateKeyPEM, *password, *trusted_ca_dir; + X509 *identityCert, *identityCA; + EVP_PKEY *privateKey; + dds_time_t certExpiry = DDS_TIME_INVALID; - /* validate provided arguments */ - if (!instance || !local_identity_handle || !adjusted_participant_guid || !participant_qos || !candidate_participant_guid) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "validate_local_identity: Invalid parameter provided"); - goto err_bad_param; - } + if (!instance || !local_identity_handle || !adjusted_participant_guid || !participant_qos || !candidate_participant_guid) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "validate_local_identity: Invalid parameter provided"); + goto err_bad_param; + } - identityCertPEM = DDS_Security_Property_get_value(&participant_qos->property.value, PROPERTY_IDENTITY_CERT); - if (!identityCertPEM) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "validate_local_identity: missing property '%s'", PROPERTY_IDENTITY_CERT); - goto err_no_identity_cert; - } + if (!(identityCertPEM = DDS_Security_Property_get_value(&participant_qos->property.value, PROPERTY_IDENTITY_CERT))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "validate_local_identity: missing property '%s'", PROPERTY_IDENTITY_CERT); + goto err_no_identity_cert; + } - identityCaPEM = DDS_Security_Property_get_value(&participant_qos->property.value, PROPERTY_IDENTITY_CA); - if (!identityCaPEM) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "validate_local_identity: missing property '%s'", PROPERTY_IDENTITY_CA); - goto err_no_identity_ca; - } + if (!(identityCaPEM = DDS_Security_Property_get_value(&participant_qos->property.value, PROPERTY_IDENTITY_CA))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "validate_local_identity: missing property '%s'", PROPERTY_IDENTITY_CA); + goto err_no_identity_ca; + } - privateKeyPEM = DDS_Security_Property_get_value(&participant_qos->property.value, PROPERTY_PRIVATE_KEY); - if (!privateKeyPEM) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "validate_local_identity: missing property '%s'", PROPERTY_PRIVATE_KEY); - goto err_no_private_key; - } + if (!(privateKeyPEM = DDS_Security_Property_get_value(&participant_qos->property.value, PROPERTY_PRIVATE_KEY))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "validate_local_identity: missing property '%s'", PROPERTY_PRIVATE_KEY); + goto err_no_private_key; + } - password = DDS_Security_Property_get_value(&participant_qos->property.value, PROPERTY_PASSWORD); + password = DDS_Security_Property_get_value(&participant_qos->property.value, PROPERTY_PASSWORD); - trusted_ca_dir = DDS_Security_Property_get_value(&participant_qos->property.value, PROPERTY_TRUSTED_CA_DIR); - if (trusted_ca_dir && *trusted_ca_dir != '\0') + trusted_ca_dir = DDS_Security_Property_get_value(&participant_qos->property.value, PROPERTY_TRUSTED_CA_DIR); + if (trusted_ca_dir && strlen(trusted_ca_dir) > 0) + { + if (get_trusted_ca_list(trusted_ca_dir, &(implementation->trustedCAList), ex) != DDS_SECURITY_VALIDATION_OK) + goto err_inv_trusted_ca_dir; + } + + if (load_X509_certificate(identityCaPEM, &identityCA, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_inv_identity_ca; + + /* check for CA if listed in trusted CA files */ + if (implementation->trustedCAList.length > 0) + { + const EVP_MD *digest = EVP_get_digestbyname("sha1"); + uint32_t size; + unsigned char hash_buffer[20], hash_buffer_trusted[20]; + DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_FAILED; + + X509_digest(identityCA, digest, hash_buffer, &size); + for (unsigned i = 0; i < implementation->trustedCAList.length; ++i) { - if ((result = get_trusted_ca_list (trusted_ca_dir, &(implementation->trustedCAList), ex)) != DDS_SECURITY_VALIDATION_OK) - goto err_inv_trusted_ca_dir; + X509_digest(implementation->trustedCAList.buffer[i], digest, hash_buffer_trusted, &size); + if (memcmp(hash_buffer_trusted, hash_buffer, 20) == 0) + { + result = DDS_SECURITY_VALIDATION_OK; + break; + } } - - result = load_X509_certificate(identityCaPEM, &identityCA, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_inv_identity_ca; + if (result != DDS_SECURITY_VALIDATION_OK) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CA_NOT_TRUSTED_CODE, DDS_SECURITY_VALIDATION_FAILED, DDS_SECURITY_ERR_CA_NOT_TRUSTED_MESSAGE); + goto err_identity_ca_not_trusted; } + } + if (load_X509_certificate(identityCertPEM, &identityCert, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_inv_identity_cert; + if (load_X509_private_key(privateKeyPEM, password, &privateKey, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_inv_private_key; - /*check for CA if listed in trusted CA files*/ - if( implementation->trustedCAList.length != 0 ){ - const EVP_MD *digest = EVP_get_digestbyname("sha1"); - uint32_t size; - unsigned char hash_buffer[20]; - unsigned char hash_buffer_trusted[20]; - result = DDS_SECURITY_VALIDATION_FAILED; - X509_digest(identityCA, digest, hash_buffer, &size); - for (i = 0; i < implementation->trustedCAList.length; ++i) { - X509_digest(implementation->trustedCAList.buffer[i], digest, hash_buffer_trusted, &size); - if( memcmp( hash_buffer_trusted, hash_buffer,20 ) == 0){ - result = DDS_SECURITY_VALIDATION_OK; - break; - } - } + if (verify_certificate(identityCert, identityCA, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_verification_failed; - if (result != DDS_SECURITY_VALIDATION_OK) { /*not trusted*/ - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CA_NOT_TRUSTED_CODE, (int)result, DDS_SECURITY_ERR_CA_NOT_TRUSTED_MESSAGE); - goto err_identity_ca_not_trusted; - } - } - result = load_X509_certificate(identityCertPEM, &identityCert, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_inv_identity_cert; - } + if (get_adjusted_participant_guid(identityCert, candidate_participant_guid, adjusted_participant_guid, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_adj_guid_failed; - result = load_X509_private_key(privateKeyPEM, password, &privateKey, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_inv_private_key; - } + ddsrt_free(password); + ddsrt_free(privateKeyPEM); + ddsrt_free(identityCaPEM); + ddsrt_free(identityCertPEM); + ddsrt_free(trusted_ca_dir); - result = verify_certificate(identityCert, identityCA, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_verification_failed; - } + identity = local_identity_info_new(domain_id, identityCert, identityCA, privateKey, candidate_participant_guid, adjusted_participant_guid); + *local_identity_handle = IDENTITY_HANDLE(identity); - result = get_adjusted_participant_guid(identityCert, candidate_participant_guid, adjusted_participant_guid, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_adj_guid_failed; - } + if ((certExpiry = get_certificate_expiry(identityCert)) == DDS_TIME_INVALID) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Expiry date of the certificate is invalid"); + goto err_verification_failed; + } + else if (certExpiry != DDS_NEVER) + add_validity_end_trigger(implementation, *local_identity_handle, certExpiry); - ddsrt_free(password); - ddsrt_free(privateKeyPEM); - ddsrt_free(identityCaPEM); - ddsrt_free(identityCertPEM); - ddsrt_free(trusted_ca_dir); - - identity = localIdentityInfoNew(domain_id, identityCert, identityCA, privateKey, candidate_participant_guid, adjusted_participant_guid); - - *local_identity_handle = IDENTITY_HANDLE(identity); - - /* setup expiry listener */ - certExpiry = get_certificate_expiry( identityCert ); - - if( certExpiry == DDS_TIME_INVALID ){ - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Expiry date of the certificate is invalid"); - goto err_verification_failed; - } else if ( certExpiry != DDS_NEVER ){ - add_validity_end_trigger( implementation, - *local_identity_handle, - certExpiry); - } - - - ddsrt_mutex_lock(&implementation->lock); - (void)ddsrt_hh_add(implementation->objectHash, identity); - - ddsrt_mutex_unlock(&implementation->lock); - - return result; + ddsrt_mutex_lock(&implementation->lock); + (void)ddsrt_hh_add(implementation->objectHash, identity); + ddsrt_mutex_unlock(&implementation->lock); + return DDS_SECURITY_VALIDATION_OK; err_adj_guid_failed: err_verification_failed: - EVP_PKEY_free(privateKey); + EVP_PKEY_free(privateKey); err_inv_private_key: - X509_free(identityCert); + X509_free(identityCert); err_inv_identity_cert: err_identity_ca_not_trusted: - X509_free(identityCA); + X509_free(identityCA); err_inv_identity_ca: err_inv_trusted_ca_dir: - ddsrt_free(password); - ddsrt_free(privateKeyPEM); - ddsrt_free(trusted_ca_dir); + ddsrt_free(password); + ddsrt_free(privateKeyPEM); + ddsrt_free(trusted_ca_dir); err_no_private_key: - ddsrt_free(identityCaPEM); + ddsrt_free(identityCaPEM); err_no_identity_ca: - ddsrt_free(identityCertPEM); + ddsrt_free(identityCertPEM); err_no_identity_cert: err_bad_param: - return DDS_SECURITY_VALIDATION_FAILED; + return DDS_SECURITY_VALIDATION_FAILED; } -DDS_Security_boolean -get_identity_token(dds_security_authentication *instance, - DDS_Security_IdentityToken *identity_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex) +DDS_Security_boolean get_identity_token(dds_security_authentication *instance, DDS_Security_IdentityToken *identity_token, const DDS_Security_IdentityHandle handle, DDS_Security_SecurityException *ex) { - dds_security_authentication_impl *impl = (dds_security_authentication_impl *) instance; - SecurityObject *obj; - LocalIdentityInfo *identity; - char *snCert, *snCA; + dds_security_authentication_impl *impl = (dds_security_authentication_impl *)instance; + SecurityObject *obj; + LocalIdentityInfo *identity; + char *snCert, *snCA; - memset(identity_token, 0, sizeof(*identity_token)); + if (!instance || !identity_token) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_identity_token: Invalid parameter provided"); + goto err_bad_param; + } + memset(identity_token, 0, sizeof(*identity_token)); - /* validate provided arguments */ - if (!instance || !identity_token) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_identity_token: Invalid parameter provided"); - goto err_bad_param; - } + ddsrt_mutex_lock(&impl->lock); - ddsrt_mutex_lock(&impl->lock); + obj = security_object_find(impl->objectHash, handle); + if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_LOCAL_IDENTITY)) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_identity_token: Invalid handle provided"); + goto err_inv_handle; + } + identity = (LocalIdentityInfo *)obj; + if (!(snCert = get_certificate_subject_name(identity->identityCert, ex))) + goto err_sn_cert; + if (!(snCA = get_certificate_subject_name(identity->identityCA, ex))) + goto err_sn_ca; - obj = security_object_find(impl->objectHash, handle); - if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_LOCAL_IDENTITY)) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_identity_token: Invalid handle provided"); - goto err_inv_handle; - } - identity = (LocalIdentityInfo *)obj; + identity_token->class_id = get_authentication_class_id(); + identity_token->properties._length = 4; + identity_token->properties._buffer = DDS_Security_PropertySeq_allocbuf(4); + identity_token->properties._buffer[0].name = ddsrt_strdup(PROPERTY_CERT_SUBJECT_NAME); + identity_token->properties._buffer[0].value = snCert; + identity_token->properties._buffer[1].name = ddsrt_strdup(PROPERTY_CERT_ALGORITHM); + identity_token->properties._buffer[1].value = ddsrt_strdup(get_authentication_algo(get_authentication_algo_kind(identity->identityCert))); + identity_token->properties._buffer[2].name = ddsrt_strdup(PROPERTY_CA_SUBJECT_NAME); + identity_token->properties._buffer[2].value = snCA; + identity_token->properties._buffer[3].name = ddsrt_strdup(PROPERTY_CA_ALGORITHM); + identity_token->properties._buffer[3].value = ddsrt_strdup(get_authentication_algo(get_authentication_algo_kind(identity->identityCA))); - snCert = get_certificate_subject_name(identity->identityCert, ex); + ddsrt_mutex_unlock(&impl->lock); - if (!snCert) { - goto err_sn_cert; - } - - snCA = get_certificate_subject_name(identity->identityCA, ex); - if (!snCA) { - goto err_sn_ca; - } - - identity_token->class_id = get_authentication_class_id(); - identity_token->properties._length = 4; - identity_token->properties._buffer = DDS_Security_PropertySeq_allocbuf(4); - - identity_token->properties._buffer[0].name = ddsrt_strdup(PROPERTY_CERT_SUBJECT_NAME); - identity_token->properties._buffer[0].value = snCert; - - identity_token->properties._buffer[1].name = ddsrt_strdup(PROPERTY_CERT_ALGORITHM); - identity_token->properties._buffer[1].value = ddsrt_strdup(get_authentication_algo(get_auhentication_algo_kind(identity->identityCert))); - - identity_token->properties._buffer[2].name = ddsrt_strdup(PROPERTY_CA_SUBJECT_NAME); - identity_token->properties._buffer[2].value = snCA; - - identity_token->properties._buffer[3].name = ddsrt_strdup(PROPERTY_CA_ALGORITHM); - identity_token->properties._buffer[3].value = ddsrt_strdup(get_authentication_algo(get_auhentication_algo_kind(identity->identityCA))); - - ddsrt_mutex_unlock(&impl->lock); - - return true; + return true; err_sn_ca: - ddsrt_free(snCert); + ddsrt_free(snCert); err_sn_cert: err_inv_handle: - ddsrt_mutex_unlock(&impl->lock); + ddsrt_mutex_unlock(&impl->lock); err_bad_param: + return false; +} + +DDS_Security_boolean get_identity_status_token(dds_security_authentication *instance, DDS_Security_IdentityStatusToken *identity_status_token, const DDS_Security_IdentityHandle handle, DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(identity_status_token); + DDSRT_UNUSED_ARG(handle); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +DDS_Security_boolean set_permissions_credential_and_token(dds_security_authentication *instance, const DDS_Security_IdentityHandle handle, + const DDS_Security_PermissionsCredentialToken *permissions_credential, const DDS_Security_PermissionsToken *permissions_token, DDS_Security_SecurityException *ex) +{ + dds_security_authentication_impl *impl = (dds_security_authentication_impl *)instance; + LocalIdentityInfo *identity; + + if (!instance || handle == DDS_SECURITY_HANDLE_NIL || !permissions_credential || !permissions_token) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_identity_token: Invalid parameter provided"); return false; -} + } -DDS_Security_boolean get_identity_status_token( - dds_security_authentication *instance, - DDS_Security_IdentityStatusToken *identity_status_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(identity_status_token); - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); + if (!permissions_credential->class_id || strcmp(permissions_credential->class_id, ACCESS_PERMISSIONS_CREDENTIAL_TOKEN_ID) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_identity_token: Invalid parameter provided"); + return false; + } - return true; -} - -DDS_Security_boolean -set_permissions_credential_and_token( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle handle, - const DDS_Security_PermissionsCredentialToken *permissions_credential, - const DDS_Security_PermissionsToken *permissions_token, - DDS_Security_SecurityException *ex) -{ - dds_security_authentication_impl *impl = (dds_security_authentication_impl *) instance; - LocalIdentityInfo *identity; - - /* validate provided arguments */ - if ((!instance) || - (handle == DDS_SECURITY_HANDLE_NIL) || - (!permissions_credential) || - (!permissions_token) ){ - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, - DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_identity_token: Invalid parameter provided"); - return false; - } - - if (!permissions_credential->class_id || - (strcmp(permissions_credential->class_id, ACCESS_PERMISSIONS_CREDENTIAL_TOKEN_ID) != 0)) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, - DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_identity_token: Invalid parameter provided"); - return false; - } - - if ((permissions_credential->properties._length == 0) || - (permissions_credential->properties._buffer[0].name == NULL) || - (strcmp(permissions_credential->properties._buffer[0].name, ACCESS_PROPERTY_PERMISSION_DOCUMENT) != 0)) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, - DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_identity_token: Invalid parameter provided"); - return false; - } - - ddsrt_mutex_lock(&impl->lock); - - identity = (LocalIdentityInfo *)security_object_find(impl->objectHash, handle); - if (!identity || !SECURITY_OBJECT_VALID(identity, SECURITY_OBJECT_KIND_LOCAL_IDENTITY)) { - ddsrt_mutex_unlock(&impl->lock); - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_identity_token: Invalid handle provided"); - return false; - } - - if (permissions_credential->properties._buffer[0].value) { - identity->permissionsDocument = ddsrt_strdup(permissions_credential->properties._buffer[0].value); - } else { - identity->permissionsDocument = ddsrt_strdup(""); - } + if (permissions_credential->properties._length == 0 || permissions_credential->properties._buffer[0].name == NULL + || strcmp(permissions_credential->properties._buffer[0].name, ACCESS_PROPERTY_PERMISSION_DOCUMENT) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_identity_token: Invalid parameter provided"); + return false; + } + ddsrt_mutex_lock(&impl->lock); + identity = (LocalIdentityInfo *)security_object_find(impl->objectHash, handle); + if (!identity || !SECURITY_OBJECT_VALID(identity, SECURITY_OBJECT_KIND_LOCAL_IDENTITY)) + { ddsrt_mutex_unlock(&impl->lock); + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "get_identity_token: Invalid handle provided"); + return false; + } + identity->permissionsDocument = ddsrt_strdup(permissions_credential->properties._buffer[0].value ? permissions_credential->properties._buffer[0].value : ""); + ddsrt_mutex_unlock(&impl->lock); - return true; + return true; } - -static DDS_Security_ValidationResult_t -validate_remote_identity_token( - const LocalIdentityInfo *localIdent, - const DDS_Security_IdentityToken *token, - DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t validate_remote_identity_token(const LocalIdentityInfo *localIdent, const DDS_Security_IdentityToken *token, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - - DDSRT_UNUSED_ARG(localIdent); - - if (token->class_id) { - size_t sz = strlen(AUTH_PROTOCOL_CLASS); - - if (strncmp(AUTH_PROTOCOL_CLASS, token->class_id, sz) == 0) { - char *ptr = &token->class_id[sz]; - char postfix[2]; - unsigned major, minor; - - DDSRT_WARNING_MSVC_OFF(4996); - if (sscanf(ptr, ":%u.%u%1s", &major, &minor, postfix) == 2) { - DDSRT_WARNING_MSVC_ON(4996); - if (major == AUTH_PROTOCOL_VERSION_MAJOR) { - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "remote identity token: version %u.%u not supported", major, minor); - } - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "remote identity token: class_id has wrong format"); - } - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "remote identity token: class_id='%s' not supported", token->class_id); - } - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "remote identity token: class_id is empty"); - } - - return result; -} - -static DDS_Security_ValidationResult_t -validate_auth_request_token( - const DDS_Security_IdentityToken *token, - AuthenticationChallenge **challenge, - DDS_Security_SecurityException *ex) -{ - uint32_t index; - int found = 0; - - assert(token); - - if (!token->class_id) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "AuthRequestMessageToken invalid: missing class_id"); - goto err_inv_token; - } - - if (strncmp(token->class_id, AUTH_REQUEST_TOKEN_CLASS_ID, strlen(AUTH_REQUEST_TOKEN_CLASS_ID)) != 0) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "AuthRequestMessageToken invalid: class_id '%s' is invalid", token->class_id); - goto err_inv_token; - } - - if (!token->binary_properties._buffer) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "AuthRequestMessageToken invalid: properties are missing"); - goto err_inv_token; - } - - for (index = 0; index < token->binary_properties._length; index++) { - size_t len = strlen(AUTH_REQUEST_TOKEN_FUTURE_PROP_NAME); - if (token->binary_properties._buffer[index].name && - (strncmp(token->binary_properties._buffer[index].name, AUTH_REQUEST_TOKEN_FUTURE_PROP_NAME, len) == 0)) { - found = 1; - break; - } - } - - if (!found) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "AuthRequestMessageToken invalid: future_challenge not found"); - goto err_inv_token; - } - - if (token->binary_properties._buffer[index].value._length != sizeof(AuthenticationChallenge)) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "AuthRequestMessageToken invalid: future_challenge invalid size"); - goto err_inv_token; - } - - if (!token->binary_properties._buffer[index].value._buffer) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "AuthRequestMessageToken invalid: future_challenge invalid size"); - goto err_inv_token; - } - - if (challenge) { - *challenge = ddsrt_malloc(sizeof(AuthenticationChallenge)); - memcpy(*challenge, &token->binary_properties._buffer[index].value._buffer[0], sizeof(AuthenticationChallenge)); - } - - return DDS_SECURITY_VALIDATION_OK; - -err_inv_token: + DDSRT_UNUSED_ARG(localIdent); + if (!token->class_id) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "remote identity token: class_id is empty"); return DDS_SECURITY_VALIDATION_FAILED; + } + + size_t sz = strlen(AUTH_PROTOCOL_CLASS); + if (strncmp(AUTH_PROTOCOL_CLASS, token->class_id, sz) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "remote identity token: class_id='%s' not supported", token->class_id); + return DDS_SECURITY_VALIDATION_FAILED; + } + + char *ptr = &token->class_id[sz]; + unsigned major, minor; + char postfix[2]; + DDSRT_WARNING_MSVC_OFF(4996); + if (sscanf(ptr, ":%u.%u%1s", &major, &minor, postfix) != 2) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "remote identity token: class_id has wrong format"); + return DDS_SECURITY_VALIDATION_FAILED; + } + DDSRT_WARNING_MSVC_ON(4996); + + if (major != AUTH_PROTOCOL_VERSION_MAJOR) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "remote identity token: version %u.%u not supported", major, minor); + return DDS_SECURITY_VALIDATION_FAILED; + } + + return DDS_SECURITY_VALIDATION_OK; } -static void -fill_auth_request_token( - DDS_Security_AuthRequestMessageToken *token, - AuthenticationChallenge *challenge) +static DDS_Security_ValidationResult_t validate_auth_request_token(const DDS_Security_IdentityToken *token, AuthenticationChallenge **challenge, DDS_Security_SecurityException *ex) { - uint32_t len = sizeof(challenge->value); + uint32_t index; + int found = 0; + assert(token); + if (!token->class_id) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "AuthRequestMessageToken invalid: missing class_id"); + return DDS_SECURITY_VALIDATION_FAILED; + } + if (strncmp(token->class_id, AUTH_REQUEST_TOKEN_CLASS_ID, strlen(AUTH_REQUEST_TOKEN_CLASS_ID)) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "AuthRequestMessageToken invalid: class_id '%s' is invalid", token->class_id); + return DDS_SECURITY_VALIDATION_FAILED; + } + if (!token->binary_properties._buffer) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "AuthRequestMessageToken invalid: properties are missing"); + return DDS_SECURITY_VALIDATION_FAILED; + } - DDS_Security_DataHolder_deinit(token); + for (index = 0; index < token->binary_properties._length; index++) + { + size_t len = strlen(AUTH_REQUEST_TOKEN_FUTURE_PROP_NAME); + if (token->binary_properties._buffer[index].name && strncmp(token->binary_properties._buffer[index].name, AUTH_REQUEST_TOKEN_FUTURE_PROP_NAME, len) == 0) + { + found = 1; + break; + } + } + if (!found) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "AuthRequestMessageToken invalid: future_challenge not found"); + return DDS_SECURITY_VALIDATION_FAILED; + } - token->class_id = ddsrt_strdup(AUTH_REQUEST_TOKEN_CLASS_ID); - token->binary_properties._length = 1; - token->binary_properties._buffer = DDS_Security_BinaryPropertySeq_allocbuf(1); - token->binary_properties._buffer->name = ddsrt_strdup(AUTH_REQUEST_TOKEN_FUTURE_PROP_NAME); + if (token->binary_properties._buffer[index].value._length != sizeof(AuthenticationChallenge) + || !token->binary_properties._buffer[index].value._buffer) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "AuthRequestMessageToken invalid: future_challenge invalid size"); + return DDS_SECURITY_VALIDATION_FAILED; + } - token->binary_properties._buffer->value._length = len; - token->binary_properties._buffer->value._buffer = ddsrt_malloc(len); - memcpy(token->binary_properties._buffer->value._buffer, challenge->value, len); - token->binary_properties._buffer->propagate = true; + if (challenge) + { + *challenge = ddsrt_malloc(sizeof(AuthenticationChallenge)); + memcpy(*challenge, &token->binary_properties._buffer[index].value._buffer[0], sizeof(AuthenticationChallenge)); + } + return DDS_SECURITY_VALIDATION_OK; } -DDS_Security_ValidationResult_t -validate_remote_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *remote_identity_handle, - DDS_Security_AuthRequestMessageToken *local_auth_request_token, - const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityToken *remote_identity_token, - const DDS_Security_GUID_t *remote_participant_guid, - DDS_Security_SecurityException *ex) +static void fill_auth_request_token(DDS_Security_AuthRequestMessageToken *token, AuthenticationChallenge *challenge) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - dds_security_authentication_impl *impl = (dds_security_authentication_impl *) instance; - SecurityObject *obj; - LocalIdentityInfo *localIdent; - RemoteIdentityInfo *remoteIdent; - IdentityRelation *relation; - AuthenticationChallenge *lchallenge = NULL, *rchallenge = NULL; - int r; + uint32_t len = sizeof(challenge->value); + DDS_Security_DataHolder_deinit(token); + token->class_id = ddsrt_strdup(AUTH_REQUEST_TOKEN_CLASS_ID); + token->binary_properties._length = 1; + token->binary_properties._buffer = DDS_Security_BinaryPropertySeq_allocbuf(1); + token->binary_properties._buffer->name = ddsrt_strdup(AUTH_REQUEST_TOKEN_FUTURE_PROP_NAME); + token->binary_properties._buffer->value._length = len; + token->binary_properties._buffer->value._buffer = ddsrt_malloc(len); + memcpy(token->binary_properties._buffer->value._buffer, challenge->value, len); + token->binary_properties._buffer->propagate = true; +} - /* validate provided arguments */ - if (!instance || !remote_identity_handle || !local_auth_request_token || !remote_identity_token || !remote_participant_guid) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "validate_remote_identity: Invalid parameter provided"); - goto err_bad_param; +DDS_Security_ValidationResult_t validate_remote_identity(dds_security_authentication *instance, DDS_Security_IdentityHandle *remote_identity_handle, + DDS_Security_AuthRequestMessageToken *local_auth_request_token, const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, const DDS_Security_IdentityHandle local_identity_handle, + const DDS_Security_IdentityToken *remote_identity_token, const DDS_Security_GUID_t *remote_participant_guid, DDS_Security_SecurityException *ex) +{ + dds_security_authentication_impl *impl = (dds_security_authentication_impl *)instance; + SecurityObject *obj; + LocalIdentityInfo *localIdent; + RemoteIdentityInfo *remoteIdent; + IdentityRelation *relation; + AuthenticationChallenge *lchallenge = NULL, *rchallenge = NULL; + + if (!instance || !remote_identity_handle || !local_auth_request_token || !remote_identity_token || !remote_participant_guid) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "validate_remote_identity: Invalid parameter provided"); + goto err_bad_param; + } + + ddsrt_mutex_lock(&impl->lock); + obj = security_object_find(impl->objectHash, local_identity_handle); + if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_LOCAL_IDENTITY)) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "validate_remote_identity: Invalid handle provided"); + goto err_inv_handle; + } + localIdent = (LocalIdentityInfo *)obj; + + if (validate_remote_identity_token(localIdent, remote_identity_token, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_remote_identity_token; + + /* When the remote_auth_request_token is not null, check if it's contents is valid and set the futureChallenge from the data contained in the remote_auth_request_token. */ + if (remote_auth_request_token) + { + if (validate_auth_request_token(remote_auth_request_token, &rchallenge, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_inv_auth_req_token; + } + + if ((lchallenge = generate_challenge(ex)) == NULL) + goto err_alloc_challenge; + + /* The validate_remote_identity will also create a handshake structure which contains the relation between + a local an remote identity. This handshake structure is inserted in the remote identity structure. */ + + /* Check if the remote identity has already been validated by a previous validation request. */ + if (!(remoteIdent = find_remote_identity_by_guid(impl->remoteGuidHash, remote_participant_guid))) + { + remoteIdent = remote_identity_info_new(remote_participant_guid, remote_identity_token); + (void)ddsrt_hh_add(impl->objectHash, remoteIdent); + (void)ddsrt_hh_add(impl->remoteGuidHash, remoteIdent); + relation = identity_relation_new(localIdent, remoteIdent, lchallenge, rchallenge); + (void)ddsrt_hh_add(remoteIdent->linkHash, relation); + } + else + { + /* When the remote identity has already been validated before, check if the remote identity token matches with the existing one */ + if (!DDS_Security_DataHolder_equal(remoteIdent->remoteIdentityToken, remote_identity_token)) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "validate_remote_identity: remote_identity_token does not match with previously received one"); + goto err_inv_duplicate; } - ddsrt_mutex_lock(&impl->lock); - - obj = security_object_find(impl->objectHash, local_identity_handle); - if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_LOCAL_IDENTITY)) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "validate_remote_identity: Invalid handle provided"); - goto err_inv_handle; + if (!(relation = find_identity_relation(remoteIdent, SECURITY_OBJECT_HANDLE(localIdent)))) + { + relation = identity_relation_new(localIdent, remoteIdent, lchallenge, rchallenge); + int r = ddsrt_hh_add(remoteIdent->linkHash, relation); + assert(r); + (void)r; } - localIdent = (LocalIdentityInfo *) obj; - - /* Check if the provided remote_identity_token is compatible */ - result = validate_remote_identity_token(localIdent, remote_identity_token, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_remote_identity_token; + else + { + if (remote_auth_request_token) + { + assert(rchallenge); + ddsrt_free(relation->rchallenge); + relation->rchallenge = rchallenge; + } + ddsrt_free(lchallenge); } + } - /* When the remote_auth_request_token is not null, check if it's contents is valid and - * set the futureChallenge from the data contained in the remote_auth_request_token. - */ - if (remote_auth_request_token) { - result = validate_auth_request_token(remote_auth_request_token, &rchallenge, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_inv_auth_req_token; - } - } + ddsrt_mutex_unlock(&impl->lock); - if ((lchallenge = generate_challenge(ex)) == NULL) { - goto err_alloc_challenge; - } + if (!remote_auth_request_token) + { + /* Create local_auth_request_token with contents set to the challenge */ + fill_auth_request_token(local_auth_request_token, relation->lchallenge); + } + else + { + /* Set local_auth_request token to TokenNil */ + DDS_Security_set_token_nil(local_auth_request_token); + } - /* The validate_remote_identity will also create a handshake structure which contains the - * relation between an local an remote identity. This handshake structure is inserted in - * the remote identity structure. - */ - - /* Check if the remote identity has already been validated by a previous validation request. */ - remoteIdent = find_remote_identity_by_guid(impl->remoteGuidHash, remote_participant_guid); - if (!remoteIdent) { - remoteIdent = remoteIdentityInfoNew(remote_participant_guid, remote_identity_token); - (void)ddsrt_hh_add(impl->objectHash, remoteIdent); - (void)ddsrt_hh_add(impl->remoteGuidHash, remoteIdent); - relation = identityRelationNew(localIdent, remoteIdent, lchallenge, rchallenge); - (void)ddsrt_hh_add(remoteIdent->linkHash, relation); - } else { - /* When the remote identity has already been validated before, - check if the remote identity token matches with the existing one - */ - if (!DDS_Security_DataHolder_equal(remoteIdent->remoteIdentityToken, remote_identity_token)) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "validate_remote_identity: remote_identity_token does not match with previously received one"); - goto err_inv_duplicate; - } - - relation = find_identity_relation(remoteIdent, SECURITY_OBJECT_HANDLE(localIdent)); - if (!relation) { - relation = identityRelationNew(localIdent, remoteIdent, lchallenge, rchallenge); - r = ddsrt_hh_add(remoteIdent->linkHash, relation); - assert(r); - (void)r; - } else { - if (remote_auth_request_token) { - assert(rchallenge); - ddsrt_free(relation->rchallenge); - relation->rchallenge = rchallenge; - } - ddsrt_free(lchallenge); - } - } - - ddsrt_mutex_unlock(&impl->lock); - - if (!remote_auth_request_token) { - /* Create local_auth_request_token with contents set to the challenge */ - fill_auth_request_token(local_auth_request_token, relation->lchallenge); - } else { - /* Set local_auth_request token to TokenNil */ - DDS_Security_set_token_nil(local_auth_request_token); - } - - *remote_identity_handle = IDENTITY_HANDLE(remoteIdent);; - - if (memcmp(&localIdent->adjustedGUID, &remoteIdent->guid, sizeof(DDS_Security_GUID_t)) < 0) { - result = DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_REQUEST; - } else { - result = DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE; - } - - return result; + *remote_identity_handle = IDENTITY_HANDLE(remoteIdent); + return memcmp(&localIdent->adjustedGUID, &remoteIdent->guid, sizeof(DDS_Security_GUID_t)) < 0 ? + DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_REQUEST : DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE; err_inv_duplicate: - ddsrt_free(lchallenge); + ddsrt_free(lchallenge); err_alloc_challenge: - ddsrt_free(rchallenge); + ddsrt_free(rchallenge); err_inv_auth_req_token: err_remote_identity_token: err_inv_handle: - ddsrt_mutex_unlock(&impl->lock); + ddsrt_mutex_unlock(&impl->lock); err_bad_param: - return DDS_SECURITY_VALIDATION_FAILED; + return DDS_SECURITY_VALIDATION_FAILED; } -DDS_Security_ValidationResult_t -begin_handshake_request( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex) +DDS_Security_ValidationResult_t begin_handshake_request(dds_security_authentication *instance, DDS_Security_HandshakeHandle *handshake_handle, + DDS_Security_HandshakeMessageToken *handshake_message, const DDS_Security_IdentityHandle initiator_identity_handle, const DDS_Security_IdentityHandle replier_identity_handle, + const DDS_Security_OctetSeq *serialized_local_participant_data, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - dds_security_authentication_impl *impl = (dds_security_authentication_impl *) instance; - HandshakeInfo *handshake = NULL; - IdentityRelation *relation = NULL; - SecurityObject *obj; - LocalIdentityInfo *localIdent; - RemoteIdentityInfo *remoteIdent; - EVP_PKEY *dhkey; - DDS_Security_BinaryProperty_t *tokens; - DDS_Security_BinaryProperty_t *c_id; - DDS_Security_BinaryProperty_t *c_perm; - DDS_Security_BinaryProperty_t *c_pdata; - DDS_Security_BinaryProperty_t *c_dsign_algo; - DDS_Security_BinaryProperty_t *c_kagree_algo; - DDS_Security_BinaryProperty_t *hash_c1; - DDS_Security_BinaryProperty_t *dh1; - DDS_Security_BinaryProperty_t *challenge; - unsigned char *certData; - unsigned char *dhPubKeyData = NULL; - uint32_t certDataSize, dhPubKeyDataSize; - int created = 0; + dds_security_authentication_impl *impl = (dds_security_authentication_impl *)instance; + HandshakeInfo *handshake = NULL; + IdentityRelation *relation = NULL; + SecurityObject *obj; + LocalIdentityInfo *localIdent; + RemoteIdentityInfo *remoteIdent; + EVP_PKEY *dhkey; + DDS_Security_BinaryProperty_t *tokens, *c_id, *c_perm, *c_pdata, *c_dsign_algo, *c_kagree_algo, *hash_c1, *dh1, *challenge; + unsigned char *certData, *dhPubKeyData = NULL; + uint32_t certDataSize, dhPubKeyDataSize; + int created = 0; - /* validate provided arguments */ - if (!instance || !handshake_handle || !handshake_message || !serialized_local_participant_data) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "begin_handshake_request: Invalid parameter provided"); - goto err_bad_param; - } + if (!instance || !handshake_handle || !handshake_message || !serialized_local_participant_data) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_request: Invalid parameter provided"); + goto err_bad_param; + } - ddsrt_mutex_lock(&impl->lock); + ddsrt_mutex_lock(&impl->lock); - obj = security_object_find(impl->objectHash, initiator_identity_handle); - if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_LOCAL_IDENTITY)) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "begin_handshake_request: Invalid initiator_identity_handle provided"); - goto err_inv_handle; - } - localIdent = (LocalIdentityInfo *) obj; + obj = security_object_find(impl->objectHash, initiator_identity_handle); + if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_LOCAL_IDENTITY)) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_request: Invalid initiator_identity_handle provided"); + goto err_inv_handle; + } + localIdent = (LocalIdentityInfo *)obj; - obj = security_object_find(impl->objectHash, replier_identity_handle); - if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_REMOTE_IDENTITY)) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "begin_handshake_request: Invalid replier_identity_handle provided"); - goto err_inv_handle; - } - remoteIdent = (RemoteIdentityInfo *)obj; + obj = security_object_find(impl->objectHash, replier_identity_handle); + if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_REMOTE_IDENTITY)) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_request: Invalid replier_identity_handle provided"); + goto err_inv_handle; + } + remoteIdent = (RemoteIdentityInfo *)obj; - result = get_certificate_contents(localIdent->identityCert, &certData, &certDataSize, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_alloc_cid; - } - - handshake = find_handshake(impl, SECURITY_OBJECT_HANDLE(localIdent), SECURITY_OBJECT_HANDLE(remoteIdent)); - if (!handshake) { - relation = find_identity_relation(remoteIdent, SECURITY_OBJECT_HANDLE(localIdent)); - assert(relation); - handshake = handshakeInfoNew(localIdent, remoteIdent, relation); - handshake->created_in = CREATEDREQUEST; - (void)ddsrt_hh_add(impl->objectHash, handshake); - created = 1; - } else { - relation = handshake->relation; - assert(relation); - } - - if (!handshake->ldh) { - result = generate_dh_keys(&dhkey, localIdent->kagreeAlgoKind, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_gen_dh_keys; - } - - handshake->ldh = dhkey; - } - - result = dh_public_key_to_oct(handshake->ldh, localIdent->kagreeAlgoKind, &dhPubKeyData, &dhPubKeyDataSize, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_get_public_key; - } - - if (localIdent->pdata._length == 0) { - DDS_Security_OctetSeq_copy(&localIdent->pdata, serialized_local_participant_data); - } - - tokens = DDS_Security_BinaryPropertySeq_allocbuf(8); - c_id = &tokens[0]; - c_perm = &tokens[1]; - c_pdata = &tokens[2]; - c_dsign_algo = &tokens[3]; - c_kagree_algo = &tokens[4]; - hash_c1 = &tokens[5]; - dh1 = &tokens[6]; - challenge = &tokens[7]; - - /* Store the Identity Certificate associated with the local identify in c.id property */ - DDS_Security_BinaryProperty_set_by_ref(c_id, "c.id", certData, certDataSize); - - /* Store the permission document in the c.perm property */ - if (localIdent->permissionsDocument) { - DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", localIdent->permissionsDocument); - } else { - DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", ""); - } - - /* Store the provided local_participant_data in the c.pdata property */ - DDS_Security_BinaryProperty_set_by_value(c_pdata, "c.pdata", serialized_local_participant_data->_buffer, serialized_local_participant_data->_length); - - /* Set the used signing algorithm descriptor in c.dsign_algo */ - DDS_Security_BinaryProperty_set_by_string(c_dsign_algo, "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); - - /* Set the used key algorithm descriptor in c.kagree_algo */ - DDS_Security_BinaryProperty_set_by_string(c_kagree_algo, "c.kagree_algo", get_kagree_algo(localIdent->kagreeAlgoKind)); - - /* Calculate the hash_c1 */ - { - DDS_Security_BinaryPropertySeq bseq; - - bseq._length = 5; - bseq._buffer = tokens; - - get_hash_binary_property_seq(&bseq, handshake->hash_c1); - DDS_Security_BinaryProperty_set_by_value(hash_c1, "hash_c1", handshake->hash_c1, sizeof(HashValue_t)); - } - - /* Set the DH public key associated with the local participant in dh1 property */ - assert(dhPubKeyData); - assert(dhPubKeyDataSize < 1200); - DDS_Security_BinaryProperty_set_by_ref(dh1, "dh1", dhPubKeyData, dhPubKeyDataSize); - - /* Set the challenge in challenge1 property */ - DDS_Security_BinaryProperty_set_by_value(challenge, "challenge1", relation->lchallenge->value, sizeof(AuthenticationChallenge)); + if (get_certificate_contents(localIdent->identityCert, &certData, &certDataSize, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_alloc_cid; + if (!(handshake = find_handshake(impl, SECURITY_OBJECT_HANDLE(localIdent), SECURITY_OBJECT_HANDLE(remoteIdent)))) + { + relation = find_identity_relation(remoteIdent, SECURITY_OBJECT_HANDLE(localIdent)); + assert(relation); + handshake = handshake_info_new(localIdent, remoteIdent, relation); + handshake->created_in = CREATEDREQUEST; (void)ddsrt_hh_add(impl->objectHash, handshake); + created = 1; + } + else + { + relation = handshake->relation; + assert(relation); + } - ddsrt_mutex_unlock(&impl->lock); + if (!handshake->ldh) + { + if (generate_dh_keys(&dhkey, localIdent->kagreeAlgoKind, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_gen_dh_keys; + handshake->ldh = dhkey; + } - handshake_message->class_id = ddsrt_strdup(AUTH_HANDSHAKE_REQUEST_TOKEN_ID); - handshake_message->properties._length = 0; - handshake_message->properties._buffer = NULL; - handshake_message->binary_properties._length = 8; - handshake_message->binary_properties._buffer = tokens; - *handshake_handle = HANDSHAKE_HANDLE(handshake); + if (dh_public_key_to_oct(handshake->ldh, localIdent->kagreeAlgoKind, &dhPubKeyData, &dhPubKeyDataSize, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_get_public_key; - return DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE; + if (localIdent->pdata._length == 0) + DDS_Security_OctetSeq_copy(&localIdent->pdata, serialized_local_participant_data); + + tokens = DDS_Security_BinaryPropertySeq_allocbuf(8); + c_id = &tokens[0]; + c_perm = &tokens[1]; + c_pdata = &tokens[2]; + c_dsign_algo = &tokens[3]; + c_kagree_algo = &tokens[4]; + hash_c1 = &tokens[5]; + dh1 = &tokens[6]; + challenge = &tokens[7]; + + DDS_Security_BinaryProperty_set_by_ref(c_id, "c.id", certData, certDataSize); + DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", localIdent->permissionsDocument ? localIdent->permissionsDocument : ""); + DDS_Security_BinaryProperty_set_by_value(c_pdata, "c.pdata", serialized_local_participant_data->_buffer, serialized_local_participant_data->_length); + DDS_Security_BinaryProperty_set_by_string(c_dsign_algo, "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); + DDS_Security_BinaryProperty_set_by_string(c_kagree_algo, "c.kagree_algo", get_kagree_algo(localIdent->kagreeAlgoKind)); + + { + DDS_Security_BinaryPropertySeq bseq = { ._length = 5, ._buffer = tokens }; + get_hash_binary_property_seq(&bseq, handshake->hash_c1); + DDS_Security_BinaryProperty_set_by_value(hash_c1, "hash_c1", handshake->hash_c1, sizeof(HashValue_t)); + } + + /* Set the DH public key associated with the local participant in dh1 property */ + assert(dhPubKeyData); + assert(dhPubKeyDataSize < 1200); + DDS_Security_BinaryProperty_set_by_ref(dh1, "dh1", dhPubKeyData, dhPubKeyDataSize); + + /* Set the challenge in challenge1 property */ + DDS_Security_BinaryProperty_set_by_value(challenge, "challenge1", relation->lchallenge->value, sizeof(AuthenticationChallenge)); + + (void)ddsrt_hh_add(impl->objectHash, handshake); + + ddsrt_mutex_unlock(&impl->lock); + + handshake_message->class_id = ddsrt_strdup(AUTH_HANDSHAKE_REQUEST_TOKEN_ID); + handshake_message->properties._length = 0; + handshake_message->properties._buffer = NULL; + handshake_message->binary_properties._length = 8; + handshake_message->binary_properties._buffer = tokens; + *handshake_handle = HANDSHAKE_HANDLE(handshake); + + return DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE; err_get_public_key: err_gen_dh_keys: - if (created) { - (void)ddsrt_hh_remove(impl->objectHash, handshake); - security_object_free((SecurityObject *)handshake); - } + if (created) + { + (void)ddsrt_hh_remove(impl->objectHash, handshake); + security_object_free((SecurityObject *)handshake); + } err_alloc_cid: - ddsrt_free(certData); + ddsrt_free(certData); err_inv_handle: - ddsrt_mutex_unlock(&impl->lock); + ddsrt_mutex_unlock(&impl->lock); err_bad_param: - return DDS_SECURITY_VALIDATION_FAILED; + return DDS_SECURITY_VALIDATION_FAILED; } -static DDS_Security_ValidationResult_t -validate_pdata( - const DDS_Security_OctetSeq *seq, - X509 *cert, - DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t validate_pdata(const DDS_Security_OctetSeq *seq, X509 *cert, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - DDS_Security_Deserializer deserializer; - DDS_Security_ParticipantBuiltinTopicData *pdata; - DDS_Security_GUID_t cguid, aguid; + DDS_Security_ParticipantBuiltinTopicData *pdata; + DDS_Security_GUID_t cguid, aguid; + DDS_Security_Deserializer deserializer = DDS_Security_Deserializer_new(seq->_buffer, seq->_length); + if (!deserializer) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: c.pdata invalid encoding"); + goto failed_deser; + } - deserializer = DDS_Security_Deserializer_new(seq->_buffer, seq->_length); - if (!deserializer) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: c.pdata invalid encoding"); - goto err_invalid_data; - } + pdata = DDS_Security_ParticipantBuiltinTopicData_alloc(); + if (!DDS_Security_Deserialize_ParticipantBuiltinTopicData(deserializer, pdata, ex)) + goto failed; - pdata = DDS_Security_ParticipantBuiltinTopicData_alloc(); + memset(&cguid, 0, sizeof(DDS_Security_GUID_t)); + if (get_adjusted_participant_guid(cert, &cguid, &aguid, ex) != DDS_SECURITY_VALIDATION_OK) + goto failed; - if (!DDS_Security_Deserialize_ParticipantBuiltinTopicData(deserializer, pdata, ex)) { - result = DDS_SECURITY_VALIDATION_FAILED; - goto err_incorrect_data; - } + DDS_Security_BuiltinTopicKey_t key; + DDS_Security_BuiltinTopicKeyBE(key, pdata->key); + if (memcmp(key, aguid.prefix, 6) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: c.pdata contains incorrect participant guid"); + goto failed; + } + DDS_Security_ParticipantBuiltinTopicData_free(pdata); + DDS_Security_Deserializer_free(deserializer); + return DDS_SECURITY_VALIDATION_OK; - memset(&cguid, 0, sizeof(DDS_Security_GUID_t)); - result = get_adjusted_participant_guid(cert, &cguid, &aguid, ex); - if (result == DDS_SECURITY_VALIDATION_OK) { - DDS_Security_BuiltinTopicKey_t key; - DDS_Security_BuiltinTopicKeyBE(key, pdata->key); - if (memcmp(key, aguid.prefix, 6) != 0) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: c.pdata contains incorrect participant guid"); - } - } - -err_incorrect_data: - DDS_Security_ParticipantBuiltinTopicData_free(pdata); - DDS_Security_Deserializer_free(deserializer); -err_invalid_data: - return result; +failed: + DDS_Security_ParticipantBuiltinTopicData_free(pdata); + DDS_Security_Deserializer_free(deserializer); +failed_deser: + return DDS_SECURITY_VALIDATION_FAILED; } -static DDS_Security_ValidationResult_t -validate_handshake_request_token( - const DDS_Security_HandshakeMessageToken *token, - HandshakeInfo *handshake, - X509Seq *trusted_ca_list, - DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t validate_handshake_request_token(const DDS_Security_HandshakeMessageToken *token, HandshakeInfo *handshake, X509Seq *trusted_ca_list, DDS_Security_SecurityException *ex) { + IdentityRelation *relation = handshake->relation; + X509 *identityCert; + const DDS_Security_BinaryProperty_t *c_id, *c_perm, *c_pdata, *c_dsign_algo, *c_kagree_algo, *dh1, *challenge, *hash_c1; + EVP_PKEY *pdhkey = NULL; + AuthenticationAlgoKind_t dsignAlgoKind, kagreeAlgoKind; + + assert(relation); + + if (!token->class_id || strncmp(AUTH_HANDSHAKE_REQUEST_TOKEN_ID, token->class_id, strlen(AUTH_HANDSHAKE_REQUEST_TOKEN_ID)) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken incorrect class_id: %s (expected %s)", token->class_id ? token->class_id : "NULL", AUTH_HANDSHAKE_REQUEST_TOKEN_ID); + goto err_inv_class_id; + } + + /* Check presents of mandatory properties: c.i, c.perm, c.pdata, c.dsign_algo, c.kagree_algo, dh1, challenge1 */ + c_id = DDS_Security_DataHolder_find_binary_property(token, "c.id"); + if (!c_id || c_id->value._length == 0 || c_id->value._buffer == NULL) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property c.id missing"); + goto err_no_c_id; + } + + if (load_X509_certificate_from_data((char *)c_id->value._buffer, (int)c_id->value._length, &identityCert, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_identity_cert_load; + + { DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - IdentityRelation *relation = handshake->relation; - X509 *identityCert; - const DDS_Security_BinaryProperty_t *c_id; - const DDS_Security_BinaryProperty_t *c_perm; - const DDS_Security_BinaryProperty_t *c_pdata; - const DDS_Security_BinaryProperty_t *c_dsign_algo; - const DDS_Security_BinaryProperty_t *c_kagree_algo; - const DDS_Security_BinaryProperty_t *dh1; - const DDS_Security_BinaryProperty_t *challenge; - const DDS_Security_BinaryProperty_t *hash_c1; - EVP_PKEY *pdhkey = NULL; - AuthenticationAlgoKind_t dsignAlgoKind; - AuthenticationAlgoKind_t kagreeAlgoKind; - unsigned i; - - assert(relation); - - /* Check class_id */ - if (!token->class_id || - (strncmp(AUTH_HANDSHAKE_REQUEST_TOKEN_ID, token->class_id, strlen(AUTH_HANDSHAKE_REQUEST_TOKEN_ID)) != 0)) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken incorrect class_id: %s (expected %s)", token->class_id ? token->class_id: "NULL", AUTH_HANDSHAKE_REQUEST_TOKEN_ID); - goto err_inv_class_id; - } - - /* Check presents of mandatory properties - * - c.id - * - c.perm - * - c.pdata - * - c.dsign_algo - * - c.kagree_algo - * - dh1 - * - challenge1 - */ - c_id = DDS_Security_DataHolder_find_binary_property(token, "c.id"); - if (!c_id || (c_id->value._length == 0) || (c_id->value._buffer == NULL)) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property c.id missing"); - goto err_no_c_id; - } - - result = load_X509_certificate_from_data((char*)c_id->value._buffer, (int)c_id->value._length, &identityCert, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_identity_cert_load; - } - - if( trusted_ca_list->length == 0 ){ //no trusted set. check with local CA - result = verify_certificate(identityCert, relation->localIdentity->identityCA, ex); - } - else{ - /* Make sure we have a clean exception, in case it was uninitialized. */ - DDS_Security_Exception_clean(ex); - for (i = 0; i < trusted_ca_list->length; ++i) { - /* We'll only return the exception of the last one, if it failed. */ - DDS_Security_Exception_reset(ex); - result = verify_certificate(identityCert, trusted_ca_list->buffer[i], ex); - if (result == DDS_SECURITY_VALIDATION_OK) { - break; - } - } - } - - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_inv_identity_cert; - } - - result = check_certificate_expiry( identityCert, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_inv_identity_cert; - } - - c_perm = DDS_Security_DataHolder_find_binary_property(token, "c.perm"); - if (!c_perm) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property c.perm missing"); - goto err_no_c_perm; - } - - if (c_perm->value._length > 0) { - ddsrt_free(relation->remoteIdentity->permissionsDocument); - relation->remoteIdentity->permissionsDocument = string_from_data(c_perm->value._buffer, c_perm->value._length); - } - - c_pdata = DDS_Security_DataHolder_find_binary_property(token, "c.pdata"); - if (!c_pdata) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property c.pdata missing"); - goto err_no_c_pdata; - } - - result = validate_pdata(&c_pdata->value, identityCert, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_inv_pdata; - } - - c_dsign_algo = DDS_Security_DataHolder_find_binary_property(token, "c.dsign_algo"); - if (!c_dsign_algo) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property c.dsign_algo missing"); - goto err_no_c_dsign_algo; - } - - dsignAlgoKind = get_dsign_algo_from_string((const char *)c_dsign_algo->value._buffer); - if (dsignAlgoKind == AUTH_ALGO_KIND_UNKNOWN) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property c.dsign_algo not supported"); - goto err_no_c_dsign_algo; - } - - c_kagree_algo = DDS_Security_DataHolder_find_binary_property(token, "c.kagree_algo"); - if (!c_kagree_algo) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property c.kagree_algo missing"); - goto err_no_c_kagree_algo; - } - - kagreeAlgoKind = get_kagree_algo_from_string((const char *)c_kagree_algo->value._buffer); - if (kagreeAlgoKind == AUTH_ALGO_KIND_UNKNOWN) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property c.kagree_algo not support"); - goto err_no_c_kagree_algo; - } - - dh1 = DDS_Security_DataHolder_find_binary_property(token, "dh1"); - if (!dh1 || dh1->value._length == 0 || dh1->value._buffer == NULL) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property dh1 missing"); - goto err_no_dh; - } - - result = dh_oct_to_public_key(&pdhkey, kagreeAlgoKind, dh1->value._buffer, dh1->value._length, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_no_dh; - } - - challenge = DDS_Security_DataHolder_find_binary_property(token, "challenge1"); - if (!challenge) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property challenge1 missing"); - goto err_no_challenge; - } - - if (challenge->value._length != sizeof(AuthenticationChallenge) || challenge->value._buffer == NULL) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property challenge1 invalid"); - goto err_no_challenge; - } - - /* When validate_remote_identity was provided with a remote_auth_request_token - * then the future_challenge in the remote identity was set and the challenge1 - * property of the handshake_request_token should be the same as the - * future_challenge stored in the remote identity. - */ - if (relation->rchallenge) { - if (memcmp(relation->rchallenge->value, challenge->value._buffer, sizeof(AuthenticationChallenge)) != 0) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property challenge1 does not match future_challenge"); - goto err_no_challenge; - } - } else { - if (challenge->value._length == sizeof(relation->rchallenge->value)) { - relation->rchallenge = ddsrt_malloc(sizeof(AuthenticationChallenge)); - memcpy(relation->rchallenge, challenge->value._buffer, challenge->value._length); - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property challenge1 invalid (incorrect size)"); - goto err_no_challenge; - } - } - - /* Compute the hash_c1 value */ + if (trusted_ca_list->length == 0) + result = verify_certificate(identityCert, relation->localIdentity->identityCA, ex); + else { - const DDS_Security_BinaryProperty_t * binary_properties[5]; - - binary_properties[0] = c_id; - binary_properties[1] = c_perm; - binary_properties[2] = c_pdata; - binary_properties[3] = c_dsign_algo; - binary_properties[4] = c_kagree_algo; - - (void)compute_hash_value(&handshake->hash_c1[0], binary_properties, 5, NULL); + DDS_Security_Exception_clean(ex); + for (unsigned i = 0; i < trusted_ca_list->length; ++i) + { + DDS_Security_Exception_reset(ex); + if ((result = verify_certificate(identityCert, trusted_ca_list->buffer[i], ex)) == DDS_SECURITY_VALIDATION_OK) + break; + } } + if (result != DDS_SECURITY_VALIDATION_OK) + goto err_inv_identity_cert; + } - hash_c1 = DDS_Security_DataHolder_find_binary_property(token, "hash_c1"); - if (hash_c1) { - if ((hash_c1->value._length == sizeof(HashValue_t)) && - (memcmp(hash_c1->value._buffer, &handshake->hash_c1, sizeof(HashValue_t)) == 0)) { - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property hash_c1 invalid (incorrect size)"); - goto err_inv_hash_c1; - } + if (check_certificate_expiry(identityCert, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_inv_identity_cert; + + if (!(c_perm = DDS_Security_DataHolder_find_binary_property(token, "c.perm"))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property c.perm missing"); + goto err_no_c_perm; + } + if (c_perm->value._length > 0) + { + ddsrt_free(relation->remoteIdentity->permissionsDocument); + relation->remoteIdentity->permissionsDocument = string_from_data(c_perm->value._buffer, c_perm->value._length); + } + + if (!(c_pdata = DDS_Security_DataHolder_find_binary_property(token, "c.pdata"))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property c.pdata missing"); + goto err_no_c_pdata; + } + if (validate_pdata(&c_pdata->value, identityCert, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_inv_pdata; + + if (!(c_dsign_algo = DDS_Security_DataHolder_find_binary_property(token, "c.dsign_algo"))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property c.dsign_algo missing"); + goto err_no_c_dsign_algo; + } + + if ((dsignAlgoKind = get_dsign_algo_from_string((const char *)c_dsign_algo->value._buffer)) == AUTH_ALGO_KIND_UNKNOWN) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property c.dsign_algo not supported"); + goto err_no_c_dsign_algo; + } + + if (!(c_kagree_algo = DDS_Security_DataHolder_find_binary_property(token, "c.kagree_algo"))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property c.kagree_algo missing"); + goto err_no_c_kagree_algo; + } + + if ((kagreeAlgoKind = get_kagree_algo_from_string((const char *)c_kagree_algo->value._buffer)) == AUTH_ALGO_KIND_UNKNOWN) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property c.kagree_algo not support"); + goto err_no_c_kagree_algo; + } + + dh1 = DDS_Security_DataHolder_find_binary_property(token, "dh1"); + if (!dh1 || dh1->value._length == 0 || dh1->value._buffer == NULL) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property dh1 missing"); + goto err_no_dh; + } + if (dh_oct_to_public_key(&pdhkey, kagreeAlgoKind, dh1->value._buffer, dh1->value._length, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_no_dh; + + if (!(challenge = DDS_Security_DataHolder_find_binary_property(token, "challenge1"))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property challenge1 missing"); + goto err_no_challenge; + } + if (challenge->value._length != sizeof(AuthenticationChallenge) || challenge->value._buffer == NULL) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property challenge1 invalid"); + goto err_no_challenge; + } + + /* When validate_remote_identity was provided with a remote_auth_request_token then the future_challenge in the remote identity was set and the challenge1 + property of the handshake_request_token should be the same as the future_challenge stored in the remote identity. */ + if (relation->rchallenge) + { + if (memcmp(relation->rchallenge->value, challenge->value._buffer, sizeof(AuthenticationChallenge)) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property challenge1 does not match future_challenge"); + goto err_no_challenge; } - - if (!relation->remoteIdentity->identityCert) { - relation->remoteIdentity->identityCert = identityCert; - } else { - X509_free(relation->remoteIdentity->identityCert); - relation->remoteIdentity->identityCert = identityCert; + } + else + { + if (challenge->value._length == sizeof(relation->rchallenge->value)) + { + relation->rchallenge = ddsrt_malloc(sizeof(AuthenticationChallenge)); + memcpy(relation->rchallenge, challenge->value._buffer, challenge->value._length); } + else + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property challenge1 invalid (incorrect size)"); + goto err_no_challenge; + } + } - relation->remoteIdentity->dsignAlgoKind = dsignAlgoKind; - relation->remoteIdentity->kagreeAlgoKind = kagreeAlgoKind; + { + const DDS_Security_BinaryProperty_t *binary_properties[] = { c_id, c_perm, c_pdata, c_dsign_algo, c_kagree_algo }; + (void)compute_hash_value(&handshake->hash_c1[0], binary_properties, 5, NULL); + } + if ((hash_c1 = DDS_Security_DataHolder_find_binary_property(token, "hash_c1"))) + { + if (hash_c1->value._length != sizeof(HashValue_t) || memcmp(hash_c1->value._buffer, &handshake->hash_c1, sizeof(HashValue_t)) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property hash_c1 invalid (incorrect size)"); + goto err_inv_hash_c1; + } + } - DDS_Security_OctetSeq_copy(&relation->remoteIdentity->pdata, &c_pdata->value); - - handshake->rdh = pdhkey; - - return result; + if (relation->remoteIdentity->identityCert) + X509_free(relation->remoteIdentity->identityCert); + relation->remoteIdentity->identityCert = identityCert; + relation->remoteIdentity->dsignAlgoKind = dsignAlgoKind; + relation->remoteIdentity->kagreeAlgoKind = kagreeAlgoKind; + DDS_Security_OctetSeq_copy(&relation->remoteIdentity->pdata, &c_pdata->value); + handshake->rdh = pdhkey; + return DDS_SECURITY_VALIDATION_OK; err_inv_hash_c1: err_no_challenge: - EVP_PKEY_free(pdhkey); + EVP_PKEY_free(pdhkey); err_no_dh: err_no_c_kagree_algo: err_no_c_dsign_algo: @@ -1937,349 +1452,243 @@ err_inv_pdata: err_no_c_pdata: err_no_c_perm: err_inv_identity_cert: - X509_free(identityCert); + X509_free(identityCert); err_identity_cert_load: err_no_c_id: err_inv_class_id: - return result; + return DDS_SECURITY_VALIDATION_FAILED; } - -static DDS_Security_ValidationResult_t -validate_handshake_reply_token( - const DDS_Security_HandshakeMessageToken *token, - HandshakeInfo *handshake, - EVP_PKEY **pdhkey, - X509Seq *trusted_ca_list, - DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t validate_handshake_reply_token(const DDS_Security_HandshakeMessageToken *token, HandshakeInfo *handshake, EVP_PKEY **pdhkey, X509Seq *trusted_ca_list, DDS_Security_SecurityException *ex) { + IdentityRelation *relation = handshake->relation; + X509 *identityCert; + EVP_PKEY *public_key; + const DDS_Security_BinaryProperty_t *c_id, *c_perm, *c_pdata, *c_dsign_algo, *c_kagree_algo, *dh1, *dh2, *hash_c1, *hash_c2, *challenge1, *challenge2, *signature; + AuthenticationAlgoKind_t dsignAlgoKind, kagreeAlgoKind; + + assert(relation); + + if (!token->class_id || strncmp(AUTH_HANDSHAKE_REPLY_TOKEN_ID, token->class_id, strlen(AUTH_HANDSHAKE_REPLY_TOKEN_ID)) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken incorrect class_id: %s (expected %s)", token->class_id ? token->class_id : "NULL", AUTH_HANDSHAKE_REPLY_TOKEN_ID); + goto err_inv_class_id; + } + + /* Check presents of mandatory properties: c.id, c.perm, c.pdata, c.dsign_algo, c.kagree_algo, challenge1, dh2, challenge2, signature */ + c_id = DDS_Security_DataHolder_find_binary_property(token, "c.id"); + if (!c_id || (c_id->value._length == 0) || (c_id->value._buffer == NULL)) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property c.id missing"); + goto err_no_c_id; + } + + /* Verify Identity Certificate */ + if (load_X509_certificate_from_data((char *)c_id->value._buffer, (int)c_id->value._length, &identityCert, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_identity_cert_load; + + { DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - IdentityRelation *relation = handshake->relation; - X509 *identityCert; - EVP_PKEY *public_key; - const DDS_Security_BinaryProperty_t *c_id; - const DDS_Security_BinaryProperty_t *c_perm; - const DDS_Security_BinaryProperty_t *c_pdata; - const DDS_Security_BinaryProperty_t *c_dsign_algo; - const DDS_Security_BinaryProperty_t *c_kagree_algo; - const DDS_Security_BinaryProperty_t *dh1; - const DDS_Security_BinaryProperty_t *dh2; - const DDS_Security_BinaryProperty_t *hash_c1; - const DDS_Security_BinaryProperty_t *hash_c2; - const DDS_Security_BinaryProperty_t *challenge1; - const DDS_Security_BinaryProperty_t *challenge2; - const DDS_Security_BinaryProperty_t *signature; - AuthenticationAlgoKind_t dsignAlgoKind; - AuthenticationAlgoKind_t kagreeAlgoKind; - - unsigned i; - - assert(relation); - - /* Check class_id */ - if (!token->class_id || - (strncmp(AUTH_HANDSHAKE_REPLY_TOKEN_ID, token->class_id, strlen(AUTH_HANDSHAKE_REPLY_TOKEN_ID)) != 0)) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken incorrect class_id: %s (expected %s)", token->class_id ? token->class_id: "NULL", AUTH_HANDSHAKE_REPLY_TOKEN_ID); - goto err_inv_class_id; - } - - /* Check presents of mandatory properties - * - c.id - * - c.perm - * - c.pdata - * - c.dsign_algo - * - c.kagree_algo - * - challenge1 - * - dh2 - * - challenge2 - * - signature - */ - c_id = DDS_Security_DataHolder_find_binary_property(token, "c.id"); - if (!c_id || (c_id->value._length == 0) || (c_id->value._buffer == NULL)) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property c.id missing"); - goto err_no_c_id; - } - - /* Verify Identity Certificate */ - result = load_X509_certificate_from_data((char*)c_id->value._buffer, (int)c_id->value._length, &identityCert, ex); - if (result != DDS_SECURITY_VALIDATION_OK ) { - goto err_identity_cert_load; - } - - if( trusted_ca_list->length == 0 ){ //no trusted set. check with local CA - result = verify_certificate(identityCert, relation->localIdentity->identityCA, ex); - } - else{ - /* Make sure we have a clean exception, in case it was uninitialized. */ - DDS_Security_Exception_clean(ex); - for (i = 0; i < trusted_ca_list->length; ++i) { - /* We'll only return the exception of the last one, if it failed. */ - DDS_Security_Exception_reset(ex); - result = verify_certificate(identityCert, trusted_ca_list->buffer[i], ex); - if (result == DDS_SECURITY_VALIDATION_OK) { - break; - } - } - } - - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_inv_identity_cert; - } - - result = check_certificate_expiry( identityCert, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_inv_identity_cert; - } - - c_perm = DDS_Security_DataHolder_find_binary_property(token, "c.perm"); - if (!c_perm) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property c.perm missing"); - goto err_no_c_perm; - } - - if (c_perm->value._length > 0) { - ddsrt_free(relation->remoteIdentity->permissionsDocument); - relation->remoteIdentity->permissionsDocument = string_from_data(c_perm->value._buffer, c_perm->value._length); - } - - c_pdata = DDS_Security_DataHolder_find_binary_property(token, "c.pdata"); - if (!c_pdata) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property c.pdata missing"); - goto err_no_c_pdata; - } - - result = validate_pdata(&c_pdata->value, identityCert, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_inv_pdata; - } - - c_dsign_algo = DDS_Security_DataHolder_find_binary_property(token, "c.dsign_algo"); - if (!c_dsign_algo) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property c.dsign_algo missing"); - goto err_no_c_dsign_algo; - } - - dsignAlgoKind = get_dsign_algo_from_string((const char *)c_dsign_algo->value._buffer); - if (dsignAlgoKind == AUTH_ALGO_KIND_UNKNOWN) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property c.dsign_algo not supported"); - goto err_no_c_dsign_algo; - } - - c_kagree_algo = DDS_Security_DataHolder_find_binary_property(token, "c.kagree_algo"); - if (!c_kagree_algo) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property c.kagree_algo missing"); - goto err_no_c_kagree_algo; - } - - kagreeAlgoKind = get_kagree_algo_from_string((const char *)c_kagree_algo->value._buffer); - if (kagreeAlgoKind == AUTH_ALGO_KIND_UNKNOWN) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property c.kagree_algo not support"); - goto err_no_c_kagree_algo; - } - - /* dh1 is optional */ - dh1 = DDS_Security_DataHolder_find_binary_property(token, "dh1"); - DDSRT_UNUSED_ARG(dh1); /*print it for integration purposes */ - - dh2 = DDS_Security_DataHolder_find_binary_property(token, "dh2"); - if (!dh2 || dh2->value._length == 0 || dh2->value._buffer == NULL) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property dh2 missing"); - goto err_no_dh; - } - - hash_c1 = DDS_Security_DataHolder_find_binary_property(token, "hash_c1"); - if (hash_c1) { - if ((hash_c1->value._length == sizeof(HashValue_t)) && - (memcmp(hash_c1->value._buffer, handshake->hash_c1, sizeof(HashValue_t)) == 0)) { - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property hash_c1 invalid"); - goto err_inv_hash_c1; - } - } - - /* Compute the hash_c2 value */ + if (trusted_ca_list->length == 0) + result = verify_certificate(identityCert, relation->localIdentity->identityCA, ex); + else { - const DDS_Security_BinaryProperty_t * binary_properties[5]; - - binary_properties[0] = c_id; - binary_properties[1] = c_perm; - binary_properties[2] = c_pdata; - binary_properties[3] = c_dsign_algo; - binary_properties[4] = c_kagree_algo; - - (void)compute_hash_value(&handshake->hash_c2[0], binary_properties, 5, NULL); + DDS_Security_Exception_clean(ex); + for (unsigned i = 0; i < trusted_ca_list->length; ++i) + { + DDS_Security_Exception_reset(ex); + result = verify_certificate(identityCert, trusted_ca_list->buffer[i], ex); + if (result == DDS_SECURITY_VALIDATION_OK) + break; + } } + if (result != DDS_SECURITY_VALIDATION_OK) + goto err_inv_identity_cert; + } - hash_c2 = DDS_Security_DataHolder_find_binary_property(token, "hash_c2"); - if (hash_c2) { - if ((hash_c2->value._length == sizeof(HashValue_t)) && - (memcmp(hash_c2->value._buffer, handshake->hash_c2, sizeof(HashValue_t)) == 0)) { - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property hash_c2 invalid"); - goto err_inv_hash_c2; - } + if (check_certificate_expiry(identityCert, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_inv_identity_cert; + + if (!(c_perm = DDS_Security_DataHolder_find_binary_property(token, "c.perm"))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property c.perm missing"); + goto err_no_c_perm; + } + if (c_perm->value._length > 0) + { + ddsrt_free(relation->remoteIdentity->permissionsDocument); + relation->remoteIdentity->permissionsDocument = string_from_data(c_perm->value._buffer, c_perm->value._length); + } + + if (!(c_pdata = DDS_Security_DataHolder_find_binary_property(token, "c.pdata"))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property c.pdata missing"); + goto err_no_c_pdata; + } + if (validate_pdata(&c_pdata->value, identityCert, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_inv_pdata; + + if (!(c_dsign_algo = DDS_Security_DataHolder_find_binary_property(token, "c.dsign_algo"))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property c.dsign_algo missing"); + goto err_no_c_dsign_algo; + } + + if ((dsignAlgoKind = get_dsign_algo_from_string((const char *)c_dsign_algo->value._buffer)) == AUTH_ALGO_KIND_UNKNOWN) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property c.dsign_algo not supported"); + goto err_no_c_dsign_algo; + } + + if (!(c_kagree_algo = DDS_Security_DataHolder_find_binary_property(token, "c.kagree_algo"))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property c.kagree_algo missing"); + goto err_no_c_kagree_algo; + } + + if ((kagreeAlgoKind = get_kagree_algo_from_string((const char *)c_kagree_algo->value._buffer)) == AUTH_ALGO_KIND_UNKNOWN) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property c.kagree_algo not support"); + goto err_no_c_kagree_algo; + } + + /* dh1 is optional */ + dh1 = DDS_Security_DataHolder_find_binary_property(token, "dh1"); + DDSRT_UNUSED_ARG(dh1); + + dh2 = DDS_Security_DataHolder_find_binary_property(token, "dh2"); + if (!dh2 || dh2->value._length == 0 || dh2->value._buffer == NULL) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property dh2 missing"); + goto err_no_dh; + } + + if ((hash_c1 = DDS_Security_DataHolder_find_binary_property(token, "hash_c1"))) + { + if (hash_c1->value._length != sizeof(HashValue_t) || memcmp(hash_c1->value._buffer, handshake->hash_c1, sizeof(HashValue_t)) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property hash_c1 invalid"); + goto err_inv_hash_c1; } + } - signature = DDS_Security_DataHolder_find_binary_property(token, "signature"); - if (!signature || signature->value._length == 0 || signature->value._buffer == NULL) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property signature missing"); - goto err_no_signature; + { + const DDS_Security_BinaryProperty_t *binary_properties[] = { c_id, c_perm, c_pdata, c_dsign_algo, c_kagree_algo }; + (void)compute_hash_value(&handshake->hash_c2[0], binary_properties, 5, NULL); + } + + if ((hash_c2 = DDS_Security_DataHolder_find_binary_property(token, "hash_c2"))) + { + if (hash_c2->value._length != sizeof(HashValue_t) || memcmp(hash_c2->value._buffer, handshake->hash_c2, sizeof(HashValue_t)) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property hash_c2 invalid"); + goto err_inv_hash_c2; } + } - *pdhkey = NULL; - result = dh_oct_to_public_key(pdhkey, kagreeAlgoKind, dh2->value._buffer, dh2->value._length, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_inv_dh; + signature = DDS_Security_DataHolder_find_binary_property(token, "signature"); + if (!signature || signature->value._length == 0 || signature->value._buffer == NULL) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property signature missing"); + goto err_no_signature; + } + + *pdhkey = NULL; + if (dh_oct_to_public_key(pdhkey, kagreeAlgoKind, dh2->value._buffer, dh2->value._length, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_inv_dh; + + if (!(challenge1 = DDS_Security_DataHolder_find_binary_property(token, "challenge1"))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge1 missing"); + goto err_no_challenge; + } + if (challenge1->value._length != sizeof(AuthenticationChallenge) || challenge1->value._buffer == NULL) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge1 invalid"); + goto err_no_challenge; + } + + if (!(challenge2 = DDS_Security_DataHolder_find_binary_property(token, "challenge2"))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge2 missing"); + goto err_no_challenge; + } + if (challenge2->value._length != sizeof(AuthenticationChallenge) || challenge2->value._buffer == NULL) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge2 invalid"); + goto err_no_challenge; + } + + /* When validate_remote_identity was provided with a remote_auth_request_token then the future_challenge in the remote identity was set and the challenge2 + property of the handshake_reply_token should be the same as the future_challenge stored in the remote identity. */ + if (relation->rchallenge) + { + if (memcmp(relation->rchallenge->value, challenge2->value._buffer, sizeof(AuthenticationChallenge)) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge2 does not match future_challenge"); + goto err_no_challenge; } - - challenge1 = DDS_Security_DataHolder_find_binary_property(token, "challenge1"); - if (!challenge1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property challenge1 missing"); - goto err_no_challenge; + } + else + { + if (challenge2->value._length == sizeof(relation->rchallenge->value)) + { + relation->rchallenge = ddsrt_malloc(sizeof(AuthenticationChallenge)); + memcpy(relation->rchallenge, challenge2->value._buffer, challenge2->value._length); } - - if (challenge1->value._length != sizeof(AuthenticationChallenge) || challenge1->value._buffer == NULL) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property challenge1 invalid"); - goto err_no_challenge; + else + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge2 invalid (incorrect size)"); + goto err_no_challenge; } + } - - challenge2 = DDS_Security_DataHolder_find_binary_property(token, "challenge2"); - if (!challenge2) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property challenge2 missing"); - goto err_no_challenge; + if (relation->lchallenge) + { + if (memcmp(relation->lchallenge->value, challenge1->value._buffer, sizeof(AuthenticationChallenge)) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge1 does not match future_challenge"); + goto err_no_challenge; } + } + else + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: No future challenge exists for this token"); + goto err_no_challenge; + } - if (challenge2->value._length != sizeof(AuthenticationChallenge) || challenge2->value._buffer == NULL) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property challenge2 invalid"); - goto err_no_challenge; - } - /* When validate_remote_identity was provided with a remote_auth_request_token - * then the future_challenge in the remote identity was set and the challenge2 - * property of the handshake_reply_token should be the same as the - * future_challenge stored in the remote identity. - */ + /* TODO: check if an identity certificate was already associated with the remote identity and when that is the case both should be the same */ + if (relation->remoteIdentity->identityCert) + X509_free(relation->remoteIdentity->identityCert); + relation->remoteIdentity->identityCert = identityCert; + relation->remoteIdentity->dsignAlgoKind = dsignAlgoKind; + relation->remoteIdentity->kagreeAlgoKind = kagreeAlgoKind; + if ((public_key = X509_get_pubkey(relation->remoteIdentity->identityCert))) + { + DDS_Security_BinaryProperty_t *hash_c1_val = hash_value_to_binary_property("hash_c1", handshake->hash_c1); + DDS_Security_BinaryProperty_t *hash_c2_val = hash_value_to_binary_property("hash_c2", handshake->hash_c2); + const DDS_Security_BinaryProperty_t *properties[HANDSHAKE_SIGNATURE_CONTENT_SIZE] = { hash_c2_val, challenge2, dh2, challenge1, dh1, hash_c1_val }; + DDS_Security_ValidationResult_t result = validate_signature(public_key, properties, HANDSHAKE_SIGNATURE_CONTENT_SIZE, signature->value._buffer, signature->value._length, ex); + EVP_PKEY_free(public_key); + DDS_Security_BinaryProperty_free(hash_c1_val); + DDS_Security_BinaryProperty_free(hash_c2_val); + if (result != DDS_SECURITY_VALIDATION_OK) + goto err_inv_signature; + } + else + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "X509_get_pubkey failed"); + goto err_inv_signature; + } - - if (relation->rchallenge) { - if (memcmp(relation->rchallenge->value, challenge2->value._buffer, sizeof(AuthenticationChallenge)) != 0) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property challenge2 does not match future_challenge"); - goto err_no_challenge; - } - } else { - if (challenge2->value._length == sizeof(relation->rchallenge->value)) { - relation->rchallenge = ddsrt_malloc(sizeof(AuthenticationChallenge)); - memcpy(relation->rchallenge, challenge2->value._buffer, challenge2->value._length); - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property challenge2 invalid (incorrect size)"); - goto err_no_challenge; - } - } - - - if (relation->lchallenge) { - if (memcmp(relation->lchallenge->value, challenge1->value._buffer, sizeof(AuthenticationChallenge)) != 0) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property challenge1 does not match future_challenge"); - goto err_no_challenge; - } - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: No future challenge exists for this token"); - goto err_no_challenge; - } - - - /* TODO: check if an identity certificate was already associated with the remote identity and - * when that is the case both should be the same - */ - if (!relation->remoteIdentity->identityCert) { - relation->remoteIdentity->identityCert = identityCert; - } else { - X509_free(relation->remoteIdentity->identityCert); - relation->remoteIdentity->identityCert = identityCert; - } - - relation->remoteIdentity->dsignAlgoKind = dsignAlgoKind; - relation->remoteIdentity->kagreeAlgoKind = kagreeAlgoKind; - - - public_key = X509_get_pubkey(relation->remoteIdentity->identityCert); - if (public_key) { - /*prepare properties*/ - const DDS_Security_BinaryProperty_t *properties[HANDSHAKE_SIGNATURE_CONTENT_SIZE]; - DDS_Security_BinaryProperty_t *hash_c1_val = hash_value_to_binary_property("hash_c1", handshake->hash_c1); - DDS_Security_BinaryProperty_t *hash_c2_val = hash_value_to_binary_property("hash_c2", handshake->hash_c2); - - properties[0] = hash_c2_val; - properties[1] = challenge2; - properties[2] = dh2; - properties[3] = challenge1; - properties[4] = dh1; - properties[5] = hash_c1_val; - - result = validate_signature(public_key,properties, HANDSHAKE_SIGNATURE_CONTENT_SIZE, signature->value._buffer,signature->value._length, ex); - - EVP_PKEY_free(public_key); - DDS_Security_BinaryProperty_free(hash_c1_val); - DDS_Security_BinaryProperty_free(hash_c2_val); - - if( result != DDS_SECURITY_VALIDATION_OK) { - goto err_inv_signature; - } - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "X509_get_pubkey failed"); - goto err_inv_identity_cert; - } - - - DDS_Security_OctetSeq_copy(&relation->remoteIdentity->pdata, &c_pdata->value); - - return result; + DDS_Security_OctetSeq_copy(&relation->remoteIdentity->pdata, &c_pdata->value); + return DDS_SECURITY_VALIDATION_OK; err_inv_signature: err_no_challenge: err_inv_dh: + EVP_PKEY_free(*pdhkey); err_no_signature: err_inv_hash_c2: err_inv_hash_c1: @@ -2290,1203 +1699,847 @@ err_inv_pdata: err_no_c_pdata: err_no_c_perm: err_inv_identity_cert: - X509_free(identityCert); + X509_free(identityCert); err_identity_cert_load: err_no_c_id: err_inv_class_id: - return result; + return DDS_SECURITY_VALIDATION_FAILED; } - -static DDS_Security_ValidationResult_t -validate_handshake_final_token( - const DDS_Security_HandshakeMessageToken *token, - HandshakeInfo *handshake, - DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t validate_handshake_final_token(const DDS_Security_HandshakeMessageToken *token, HandshakeInfo *handshake, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - IdentityRelation *relation = handshake->relation; - const DDS_Security_BinaryProperty_t *dh1; - const DDS_Security_BinaryProperty_t *dh2; - const DDS_Security_BinaryProperty_t *hash_c1; - const DDS_Security_BinaryProperty_t *hash_c2; - const DDS_Security_BinaryProperty_t *challenge1; - const DDS_Security_BinaryProperty_t *challenge2; - const DDS_Security_BinaryProperty_t *signature; - EVP_PKEY *public_key; + IdentityRelation *relation = handshake->relation; + const DDS_Security_BinaryProperty_t *dh1, *dh2, *hash_c1, *hash_c2, *challenge1, *challenge2, *signature; + EVP_PKEY *public_key; + assert(relation); + + if (!token->class_id || strncmp(AUTH_HANDSHAKE_FINAL_TOKEN_ID, token->class_id, strlen(AUTH_HANDSHAKE_FINAL_TOKEN_ID)) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken incorrect class_id: %s (expected %s)", token->class_id ? token->class_id : "NULL", AUTH_HANDSHAKE_FINAL_TOKEN_ID); + goto failed; + } + + /* Check presents of mandatory properties: challenge1, challenge2, signature */ + + /* dh1 and dh2 are optional */ + dh1 = DDS_Security_DataHolder_find_binary_property(token, "dh1"); + DDSRT_UNUSED_ARG(dh1); + dh2 = DDS_Security_DataHolder_find_binary_property(token, "dh2"); + DDSRT_UNUSED_ARG(dh2); + + /* hash_c1 is optional */ + if ((hash_c1 = DDS_Security_DataHolder_find_binary_property(token, "hash_c1"))) + { + if (hash_c1->value._length != sizeof(HashValue_t) || memcmp(hash_c1->value._buffer, handshake->hash_c1, sizeof(HashValue_t)) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property hash_c1 invalid"); + goto failed; + } + } + + /* hash_c2 is optional */ + if ((hash_c2 = DDS_Security_DataHolder_find_binary_property(token, "hash_c2"))) + { + if (hash_c2->value._length != sizeof(HashValue_t) || memcmp(hash_c2->value._buffer, handshake->hash_c2, sizeof(HashValue_t)) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property hash_c2 invalid"); + goto failed; + } + } + + if (!(challenge1 = DDS_Security_DataHolder_find_binary_property(token, "challenge1"))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge1 missing"); + goto failed; + } + if (challenge1->value._length != sizeof(AuthenticationChallenge) || challenge1->value._buffer == NULL) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge1 invalid"); + goto failed; + } + + if (!(challenge2 = DDS_Security_DataHolder_find_binary_property(token, "challenge2"))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge2 missing"); + goto failed; + } + if (challenge2->value._length != sizeof(AuthenticationChallenge) || challenge2->value._buffer == NULL) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge2 invalid"); + goto failed; + } + + /* When validate_remote_identity was provided with a remote_auth_request_token then the future_challenge in the remote identity was set and the challenge1 + property of the handshake_reply_token should be the same as the future_challenge stored in the remote identity. */ + if (relation->rchallenge) + { + if (memcmp(relation->rchallenge->value, challenge1->value._buffer, sizeof(AuthenticationChallenge)) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge1 does not match future_challenge"); + goto failed; + } + } + else + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: No challenge exists to check challenge1 in the token."); + goto failed; + } + + if (relation->lchallenge) + { + if (memcmp(relation->lchallenge->value, challenge2->value._buffer, sizeof(AuthenticationChallenge)) != 0) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge2 does not match future_challenge"); + goto failed; + } + } + else + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: No challenge exists to check challenge2 in the token."); + goto failed; + } + + if (!(signature = DDS_Security_DataHolder_find_binary_property(token, "signature"))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property signature missing"); + goto failed; + } + + /* Validate signature */ + if ((public_key = X509_get_pubkey(relation->remoteIdentity->identityCert))) + { + DDS_Security_BinaryProperty_t *hash_c1_val = hash_value_to_binary_property("hash_c1", handshake->hash_c1); + DDS_Security_BinaryProperty_t *hash_c2_val = hash_value_to_binary_property("hash_c2", handshake->hash_c2); + const DDS_Security_BinaryProperty_t *properties[HANDSHAKE_SIGNATURE_CONTENT_SIZE] = { hash_c1_val, challenge1, dh1, challenge2, dh2, hash_c2_val }; + DDS_Security_ValidationResult_t result = validate_signature(public_key, properties, HANDSHAKE_SIGNATURE_CONTENT_SIZE, signature->value._buffer, signature->value._length, ex); + EVP_PKEY_free(public_key); + DDS_Security_BinaryProperty_free(hash_c1_val); + DDS_Security_BinaryProperty_free(hash_c2_val); + if (result != DDS_SECURITY_VALIDATION_OK) + goto failed; + } + else + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "X509_get_pubkey failed"); + goto failed; + } + return DDS_SECURITY_VALIDATION_OK; + +failed: + return DDS_SECURITY_VALIDATION_FAILED; +} + +DDS_Security_ValidationResult_t begin_handshake_reply(dds_security_authentication *instance, DDS_Security_HandshakeHandle *handshake_handle, + DDS_Security_HandshakeMessageToken *handshake_message_out, const DDS_Security_HandshakeMessageToken *handshake_message_in, + const DDS_Security_IdentityHandle initiator_identity_handle, const DDS_Security_IdentityHandle replier_identity_handle, + const DDS_Security_OctetSeq *serialized_local_participant_data, DDS_Security_SecurityException *ex) +{ + dds_security_authentication_impl *impl = (dds_security_authentication_impl *)instance; + HandshakeInfo *handshake = NULL; + IdentityRelation *relation = NULL; + SecurityObject *obj; + LocalIdentityInfo *localIdent; + RemoteIdentityInfo *remoteIdent; + EVP_PKEY *dhkeyLocal = NULL; + DDS_Security_BinaryProperty_t *tokens, *c_id, *c_perm, *c_pdata, *c_dsign_algo, *c_kagree_algo, *hash_c1, *hash_c2, *dh1, *dh2, *challenge1, *challenge2, *signature; + const DDS_Security_BinaryProperty_t *hash_c1_ref, *dh1_ref; + unsigned char *certData, *dhPubKeyData; + uint32_t certDataSize, dhPubKeyDataSize, tokenSize; + int created = 0; + + if (!instance || !handshake_handle || !handshake_message_out || !handshake_message_in || !serialized_local_participant_data) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: Invalid parameter provided"); + goto err_bad_param; + } + + if (serialized_local_participant_data->_length == 0 || serialized_local_participant_data->_buffer == NULL) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: Invalid parameter provided"); + goto err_bad_param; + } + + ddsrt_mutex_lock(&impl->lock); + + obj = security_object_find(impl->objectHash, replier_identity_handle); + if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_LOCAL_IDENTITY)) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: Invalid replier_identity_handle provided"); + goto err_inv_handle; + } + localIdent = (LocalIdentityInfo *)obj; + + obj = security_object_find(impl->objectHash, initiator_identity_handle); + if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_REMOTE_IDENTITY)) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: Invalid initiator_identity_handle provided"); + goto err_inv_handle; + } + remoteIdent = (RemoteIdentityInfo *)obj; + if (!(handshake = find_handshake(impl, SECURITY_OBJECT_HANDLE(localIdent), SECURITY_OBJECT_HANDLE(remoteIdent)))) + { + relation = find_identity_relation(remoteIdent, SECURITY_OBJECT_HANDLE(localIdent)); assert(relation); + handshake = handshake_info_new(localIdent, remoteIdent, relation); + handshake->created_in = CREATEDREPLY; + (void)ddsrt_hh_add(impl->objectHash, handshake); + created = 1; + } + else + { + relation = handshake->relation; + assert(relation); + } - /* Check class_id */ - if (!token->class_id || - (strncmp(AUTH_HANDSHAKE_FINAL_TOKEN_ID, token->class_id, strlen(AUTH_HANDSHAKE_FINAL_TOKEN_ID)) != 0)) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken incorrect class_id: %s (expected %s)", token->class_id ? token->class_id: "NULL", AUTH_HANDSHAKE_FINAL_TOKEN_ID); - goto err_inv_class_id; - } + if (validate_handshake_request_token(handshake_message_in, handshake, &(impl->trustedCAList), ex) != DDS_SECURITY_VALIDATION_OK) + goto err_inv_token; + if (get_certificate_contents(localIdent->identityCert, &certData, &certDataSize, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_alloc_cid; - /* Check presents of mandatory properties - * - challenge1 - * - challenge2 - * - signature - */ + if (!handshake->ldh) + { + if (generate_dh_keys(&dhkeyLocal, remoteIdent->kagreeAlgoKind, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_gen_dh_keys; + handshake->ldh = dhkeyLocal; + EVP_PKEY_copy_parameters(handshake->rdh, handshake->ldh); + } - /* dh1 is optional */ - dh1 = DDS_Security_DataHolder_find_binary_property(token, "dh1"); + if (dh_public_key_to_oct(handshake->ldh, remoteIdent->kagreeAlgoKind, &dhPubKeyData, &dhPubKeyDataSize, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_get_public_key; - DDSRT_UNUSED_ARG(dh1); /*print it for integration purposes */ + if (localIdent->pdata._length == 0) + DDS_Security_OctetSeq_copy(&localIdent->pdata, serialized_local_participant_data); - /* dh2 is optional */ - dh2 = DDS_Security_DataHolder_find_binary_property(token, "dh2"); - DDSRT_UNUSED_ARG(dh2); /*print it for integration purposes */ + hash_c1_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "hash_c1"); + tokenSize = hash_c1_ref ? 12 : 11; - /* hash_c1 is optional */ - hash_c1 = DDS_Security_DataHolder_find_binary_property(token, "hash_c1"); - if (hash_c1) { - if ((hash_c1->value._length == sizeof(HashValue_t)) && - (memcmp(hash_c1->value._buffer, handshake->hash_c1, sizeof(HashValue_t)) == 0)) { - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property hash_c1 invalid"); - goto err_inv_hash_c1; - } - } + tokens = DDS_Security_BinaryPropertySeq_allocbuf(tokenSize); + c_id = &tokens[0]; + c_perm = &tokens[1]; + c_pdata = &tokens[2]; + c_dsign_algo = &tokens[3]; + c_kagree_algo = &tokens[4]; + signature = &tokens[5]; + hash_c2 = &tokens[6]; + challenge2 = &tokens[7]; + dh2 = &tokens[8]; + challenge1 = &tokens[9]; + dh1 = &tokens[10]; + hash_c1 = hash_c1_ref ? &tokens[11] : NULL; - /* hash_c2 is optional */ - hash_c2 = DDS_Security_DataHolder_find_binary_property(token, "hash_c2"); - if (hash_c2) { - if ((hash_c2->value._length == sizeof(HashValue_t)) && - (memcmp(hash_c2->value._buffer, handshake->hash_c2, sizeof(HashValue_t)) == 0)) { - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "begin_handshake_reply: HandshakeMessageToken property hash_c2 invalid"); - goto err_inv_hash_c2; - } - } + /* Store the Identity Certificate associated with the local identify in c.id property */ + DDS_Security_BinaryProperty_set_by_ref(c_id, "c.id", certData, certDataSize); + certData = NULL; + DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", localIdent->permissionsDocument ? localIdent->permissionsDocument : ""); + DDS_Security_BinaryProperty_set_by_value(c_pdata, "c.pdata", serialized_local_participant_data->_buffer, serialized_local_participant_data->_length); + DDS_Security_BinaryProperty_set_by_string(c_dsign_algo, "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); + DDS_Security_BinaryProperty_set_by_string(c_kagree_algo, "c.kagree_algo", get_kagree_algo(remoteIdent->kagreeAlgoKind)); - challenge1 = DDS_Security_DataHolder_find_binary_property(token, "challenge1"); - if (!challenge1) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property challenge1 missing"); - goto err_no_challenge; - } + /* Calculate the hash_c2 */ + { + DDS_Security_BinaryPropertySeq bseq = { ._length = 5, ._buffer = tokens }; + get_hash_binary_property_seq(&bseq, handshake->hash_c2); + DDS_Security_BinaryProperty_set_by_value(hash_c2, "hash_c2", handshake->hash_c2, sizeof(HashValue_t)); + } - if (challenge1->value._length != sizeof(AuthenticationChallenge) || challenge1->value._buffer == NULL) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property challenge1 invalid"); - goto err_no_challenge; - } + /* Set the DH public key associated with the local participant in dh2 property */ + DDS_Security_BinaryProperty_set_by_ref(dh2, "dh2", dhPubKeyData, dhPubKeyDataSize); + /* Set the DH public key associated with the local participant in hash_c1 property */ + if (hash_c1) + DDS_Security_BinaryProperty_set_by_value(hash_c1, "hash_c1", hash_c1_ref->value._buffer, hash_c1_ref->value._length); - challenge2 = DDS_Security_DataHolder_find_binary_property(token, "challenge2"); - if (!challenge2) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property challenge2 missing"); - goto err_no_challenge; - } + /* Set the DH public key associated with the local participant in dh1 property */ + if (dh1) + { + dh1_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "dh1"); + if (dh1_ref) + DDS_Security_BinaryProperty_set_by_value(dh1, "dh1", dh1_ref->value._buffer, dh1_ref->value._length); + } - if (challenge2->value._length != sizeof(AuthenticationChallenge) || challenge2->value._buffer == NULL) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property challenge2 invalid"); - goto err_no_challenge; - } + assert(relation->rchallenge); + DDS_Security_BinaryProperty_set_by_value(challenge1, "challenge1", relation->rchallenge->value, sizeof(AuthenticationChallenge)); + assert(relation->lchallenge); + DDS_Security_BinaryProperty_set_by_value(challenge2, "challenge2", relation->lchallenge->value, sizeof(AuthenticationChallenge)); - /* When validate_remote_identity was provided with a remote_auth_request_token - * then the future_challenge in the remote identity was set and the challenge1 - * property of the handshake_reply_token should be the same as the - * future_challenge stored in the remote identity. - */ + /* Calculate the signature */ + { + unsigned char *sign; + size_t signlen; + DDS_Security_BinaryProperty_t *hash_c1_val = hash_value_to_binary_property("hash_c1", handshake->hash_c1); + DDS_Security_BinaryProperty_t *hash_c2_val = hash_value_to_binary_property("hash_c2", handshake->hash_c2); + const DDS_Security_BinaryProperty_t *binary_properties[HANDSHAKE_SIGNATURE_CONTENT_SIZE] = { hash_c2_val, challenge2, dh2, challenge1, dh1, hash_c1_val }; + DDS_Security_ValidationResult_t result = create_signature(localIdent->privateKey, binary_properties, HANDSHAKE_SIGNATURE_CONTENT_SIZE, &sign, &signlen, ex); + DDS_Security_BinaryProperty_free(hash_c1_val); + DDS_Security_BinaryProperty_free(hash_c2_val); + if (result != DDS_SECURITY_VALIDATION_OK) + goto err_signature; + DDS_Security_BinaryProperty_set_by_ref(signature, "signature", sign, (uint32_t)signlen); + } + (void)ddsrt_hh_add(impl->objectHash, handshake); + handshake_message_out->class_id = ddsrt_strdup(AUTH_HANDSHAKE_REPLY_TOKEN_ID); + handshake_message_out->binary_properties._length = tokenSize; + handshake_message_out->binary_properties._buffer = tokens; + ddsrt_mutex_unlock(&impl->lock); - if (relation->rchallenge) { - if (memcmp(relation->rchallenge->value, challenge1->value._buffer, sizeof(AuthenticationChallenge)) != 0) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property challenge1 does not match future_challenge"); - goto err_no_challenge; - } - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: No challenge exists to check challenge1 in the token."); - goto err_no_challenge; - } + *handshake_handle = HANDSHAKE_HANDLE(handshake); + return DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE; - if (relation->lchallenge) { - if (memcmp(relation->lchallenge->value, challenge2->value._buffer, sizeof(AuthenticationChallenge)) != 0) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property challenge2 does not match future_challenge"); - goto err_no_challenge; - } - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: No challenge exists to check challenge2 in the token."); - goto err_no_challenge; - } - - signature = DDS_Security_DataHolder_find_binary_property(token, "signature"); - if (!signature) { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, - "process_handshake: HandshakeMessageToken property signature missing"); - goto err_no_challenge; - } - - /* Validate signature */ - public_key = X509_get_pubkey(relation->remoteIdentity->identityCert); - if (public_key) { - /*prepare properties*/ - const DDS_Security_BinaryProperty_t *properties[HANDSHAKE_SIGNATURE_CONTENT_SIZE]; - DDS_Security_BinaryProperty_t *hash_c1_val = hash_value_to_binary_property("hash_c1", handshake->hash_c1); - DDS_Security_BinaryProperty_t *hash_c2_val = hash_value_to_binary_property("hash_c2", handshake->hash_c2); - - properties[0] = hash_c1_val; - properties[1] = challenge1; - properties[2] = dh1; - properties[3] = challenge2; - properties[4] = dh2; - properties[5] = hash_c2_val; - - result = validate_signature(public_key,properties, HANDSHAKE_SIGNATURE_CONTENT_SIZE ,signature->value._buffer,signature->value._length,ex ); - - EVP_PKEY_free(public_key); - DDS_Security_BinaryProperty_free(hash_c1_val); - DDS_Security_BinaryProperty_free(hash_c2_val); - - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_inv_signature; - } - } else { - result = DDS_SECURITY_VALIDATION_FAILED; - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "X509_get_pubkey failed"); - goto err_inv_identity_cert; - } - -err_inv_hash_c2: -err_inv_hash_c1: -err_no_challenge: -err_inv_class_id: -err_inv_identity_cert: -err_inv_signature: - return result; +err_signature: + free_binary_properties(tokens, tokenSize); +err_get_public_key: +err_gen_dh_keys: + ddsrt_free(certData); +err_alloc_cid: +err_inv_token: + if (created) + { + (void)ddsrt_hh_remove(impl->objectHash, handshake); + security_object_free((SecurityObject *)handshake); + } +err_inv_handle: + ddsrt_mutex_unlock(&impl->lock); +err_bad_param: + return DDS_SECURITY_VALIDATION_FAILED; } -DDS_Security_ValidationResult_t -begin_handshake_reply( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex) +static bool generate_shared_secret(const HandshakeInfo *handshake, unsigned char **shared_secret, DDS_Security_long *length, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - dds_security_authentication_impl *impl = (dds_security_authentication_impl *) instance; - HandshakeInfo *handshake = NULL; - IdentityRelation *relation = NULL; - SecurityObject *obj; - LocalIdentityInfo *localIdent; - RemoteIdentityInfo *remoteIdent; - EVP_PKEY *dhkeyLocal = NULL; - DDS_Security_BinaryProperty_t *tokens; - DDS_Security_BinaryProperty_t *c_id; - DDS_Security_BinaryProperty_t *c_perm; - DDS_Security_BinaryProperty_t *c_pdata; - DDS_Security_BinaryProperty_t *c_dsign_algo; - DDS_Security_BinaryProperty_t *c_kagree_algo; - DDS_Security_BinaryProperty_t *hash_c1; - const DDS_Security_BinaryProperty_t *hash_c1_ref; - DDS_Security_BinaryProperty_t *hash_c2; - DDS_Security_BinaryProperty_t *dh1; - const DDS_Security_BinaryProperty_t *dh1_ref; - DDS_Security_BinaryProperty_t *dh2; - DDS_Security_BinaryProperty_t *challenge1; - DDS_Security_BinaryProperty_t *challenge2; - DDS_Security_BinaryProperty_t *signature; - unsigned char *certData; - unsigned char *dhPubKeyData; - uint32_t certDataSize, dhPubKeyDataSize; - uint32_t tokenSize, idx; - int created = 0; + EVP_PKEY_CTX *ctx; + size_t skeylen; + unsigned char *secret = NULL; + *shared_secret = NULL; - /* validate provided arguments */ - if (!instance || !handshake_handle || !handshake_message_out || !handshake_message_in || !serialized_local_participant_data) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "begin_handshake_reply: Invalid parameter provided"); - goto err_bad_param; - } + if (!(ctx = EVP_PKEY_CTX_new(handshake->ldh, NULL /* no engine */))) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: Shared secret failed to create context: "); + goto fail_ctx_new; + } - if ((serialized_local_participant_data->_length == 0) || (serialized_local_participant_data->_buffer == NULL)) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "begin_handshake_reply: Invalid parameter provided"); - goto err_bad_param; - } + if (EVP_PKEY_derive_init(ctx) <= 0) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: Shared secret failed to initialize context: "); + goto fail_derive; + } + if (EVP_PKEY_derive_set_peer(ctx, handshake->rdh) <= 0) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: Shared secret failed to set peer key: "); + goto fail_derive; + } - ddsrt_mutex_lock(&impl->lock); + /* Determine buffer length */ + if (EVP_PKEY_derive(ctx, NULL, &skeylen) <= 0) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: Shared secret failed to determine key length: "); + goto fail_derive; + } - obj = security_object_find(impl->objectHash, replier_identity_handle); - if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_LOCAL_IDENTITY)) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "begin_handshake_reply: Invalid replier_identity_handle provided"); - goto err_inv_handle; - } - localIdent = (LocalIdentityInfo *) obj; + secret = ddsrt_malloc(skeylen); + if (EVP_PKEY_derive(ctx, secret, &skeylen) <= 0) + { + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: Could not compute the shared secret: "); + goto fail_derive; + } - obj = security_object_find(impl->objectHash, initiator_identity_handle); - if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_REMOTE_IDENTITY)) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "begin_handshake_reply: Invalid initiator_identity_handle provided"); - goto err_inv_handle; - } - remoteIdent = (RemoteIdentityInfo *)obj; + *shared_secret = ddsrt_malloc(SHA256_DIGEST_LENGTH); + *length = SHA256_DIGEST_LENGTH; + SHA256(secret, skeylen, *shared_secret); + ddsrt_free(secret); + EVP_PKEY_CTX_free(ctx); + return true; - handshake = find_handshake(impl, SECURITY_OBJECT_HANDLE(localIdent), SECURITY_OBJECT_HANDLE(remoteIdent)); - if (!handshake) { - relation = find_identity_relation(remoteIdent, SECURITY_OBJECT_HANDLE(localIdent)); - assert(relation); - handshake = handshakeInfoNew(localIdent, remoteIdent, relation); - handshake->created_in = CREATEDREPLY; - (void)ddsrt_hh_add(impl->objectHash, handshake); - created = 1; - } else { - relation = handshake->relation; - assert(relation); - } +fail_derive: + ddsrt_free(secret); + EVP_PKEY_CTX_free(ctx); +fail_ctx_new: + return false; +} - result = validate_handshake_request_token(handshake_message_in, handshake, &(impl->trustedCAList), ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_inv_token; - } +DDS_Security_ValidationResult_t process_handshake(dds_security_authentication *instance, DDS_Security_HandshakeMessageToken *handshake_message_out, + const DDS_Security_HandshakeMessageToken *handshake_message_in, const DDS_Security_HandshakeHandle handshake_handle, DDS_Security_SecurityException *ex) +{ + DDS_Security_ValidationResult_t hs_result = DDS_SECURITY_VALIDATION_OK; + dds_security_authentication_impl *impl = (dds_security_authentication_impl *)instance; + HandshakeInfo *handshake = NULL; + IdentityRelation *relation = NULL; + SecurityObject *obj; + EVP_PKEY *dhkeyRemote = NULL; + DDS_Security_BinaryProperty_t *tokens = NULL, *hash_c1 = NULL, *hash_c2 = NULL, *dh1, *dh2, *challenge1, *challenge2, *signature; + const DDS_Security_BinaryProperty_t *hash_c1_ref, *hash_c2_ref, *challenge1_ref, *challenge2_ref, *dh1_ref, *dh2_ref; + uint32_t tokenSize = 0, idx; + DDS_Security_octet *challenge1_ref_for_shared_secret, *challenge2_ref_for_shared_secret; - result = get_certificate_contents(localIdent->identityCert, &certData, &certDataSize, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_alloc_cid; - } + /* validate provided arguments */ + if (!instance || !handshake_handle || !handshake_message_out || !handshake_message_in) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: Invalid parameter provided"); + goto err_bad_param; + } - if (!handshake->ldh) { - result = generate_dh_keys(&dhkeyLocal, remoteIdent->kagreeAlgoKind, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_gen_dh_keys; - } + memset(handshake_message_out, 0, sizeof(DDS_Security_HandshakeMessageToken)); - handshake->ldh = dhkeyLocal; - EVP_PKEY_copy_parameters(handshake->rdh, handshake->ldh); - } + ddsrt_mutex_lock(&impl->lock); + obj = security_object_find(impl->objectHash, handshake_handle); + if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_HANDSHAKE)) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: Invalid replier_identity_handle provided"); + goto err_inv_handle; + } + handshake = (HandshakeInfo *)obj; + relation = handshake->relation; + assert(relation); - result = dh_public_key_to_oct(handshake->ldh, remoteIdent->kagreeAlgoKind, &dhPubKeyData, &dhPubKeyDataSize, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_get_public_key; - } + /* check if the handle created by a handshake_request or handshake_reply */ + switch (handshake->created_in) + { + case CREATEDREQUEST: + /* The source of the handshake_handle is a begin_handshake_request function. So, handshake_message_in is from a remote begin_handshake_reply function */ + /* Verify Message Token contents according to Spec 9.3.2.5.2 (Reply Message) */ + if (validate_handshake_reply_token(handshake_message_in, handshake, &dhkeyRemote, &(impl->trustedCAList), ex) != DDS_SECURITY_VALIDATION_OK) + goto err_inv_token; - if (localIdent->pdata._length == 0) { - DDS_Security_OctetSeq_copy(&localIdent->pdata, serialized_local_participant_data); - } + handshake->rdh = dhkeyRemote; + EVP_PKEY_copy_parameters(handshake->rdh, handshake->ldh); + /* Prepare HandshakeFinalMessageToken */ hash_c1_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "hash_c1"); - tokenSize = hash_c1_ref ? 12 : 11; - + hash_c2_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "hash_c2"); + dh1_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "dh1"); + dh2_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "dh2"); + challenge1_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "challenge1"); + challenge2_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "challenge2"); + tokenSize = 3; /* challenge1, challenge2 and signature are in already */ + if (hash_c1_ref) tokenSize++; + if (hash_c2_ref) tokenSize++; + if (dh1_ref) tokenSize++; + if (dh2_ref) tokenSize++; tokens = DDS_Security_BinaryPropertySeq_allocbuf(tokenSize); idx = 0; - c_id = &tokens[idx++]; - c_perm = &tokens[idx++]; - c_pdata = &tokens[idx++]; - c_dsign_algo = &tokens[idx++]; - c_kagree_algo = &tokens[idx++]; signature = &tokens[idx++]; - hash_c2 = &tokens[idx++]; + hash_c2 = hash_c2_ref ? &tokens[idx++] : NULL; challenge2 = &tokens[idx++]; - dh2 = &tokens[idx++]; + dh2 = dh2_ref ? &tokens[idx++] : NULL; challenge1 = &tokens[idx++]; - dh1 = &tokens[idx++]; + dh1 = dh1_ref ? &tokens[idx++] : NULL; hash_c1 = hash_c1_ref ? &tokens[idx++] : NULL; - /* Store the Identity Certificate associated with the local identify in c.id property */ - DDS_Security_BinaryProperty_set_by_ref(c_id, "c.id", certData, certDataSize); - certData = NULL; - - /* Store the permission document in the c.perm property */ - if (localIdent->permissionsDocument) { - DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", localIdent->permissionsDocument); - } else { - DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", ""); - } - - /* Store the provided local_participant_data in the c.pdata property */ - DDS_Security_BinaryProperty_set_by_value(c_pdata, "c.pdata", serialized_local_participant_data->_buffer, serialized_local_participant_data->_length); - - /* Set the used signing algorithm descriptor in c.dsign_algo */ - DDS_Security_BinaryProperty_set_by_string(c_dsign_algo, "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); - - /* Set the used key algorithm descriptor in c.kagree_algo */ - DDS_Security_BinaryProperty_set_by_string(c_kagree_algo, "c.kagree_algo", get_kagree_algo(remoteIdent->kagreeAlgoKind)); - - /* Calculate the hash_c2 */ - { - DDS_Security_BinaryPropertySeq bseq; - - bseq._length = 5; - bseq._buffer = tokens; - - get_hash_binary_property_seq(&bseq, handshake->hash_c2); - DDS_Security_BinaryProperty_set_by_value(hash_c2, "hash_c2", handshake->hash_c2, sizeof(HashValue_t)); - } - - /* Set the DH public key associated with the local participant in dh2 property */ - DDS_Security_BinaryProperty_set_by_ref(dh2, "dh2", dhPubKeyData, dhPubKeyDataSize); - - /* Set the DH public key associated with the local participant in hash_c1 property */ - if (hash_c1) { - DDS_Security_BinaryProperty_set_by_value(hash_c1, "hash_c1", hash_c1_ref->value._buffer, hash_c1_ref->value._length); - } - - /* Set the DH public key associated with the local participant in dh1 property */ - if (dh1) { - dh1_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "dh1"); - if (dh1_ref) { - DDS_Security_BinaryProperty_set_by_value(dh1, "dh1", dh1_ref->value._buffer, dh1_ref->value._length); - } - } - - /* Set the challenge in challenge1 property */ - assert(relation->rchallenge); - DDS_Security_BinaryProperty_set_by_value(challenge1, "challenge1", relation->rchallenge->value, sizeof(AuthenticationChallenge)); - - /* Set the challenge in challenge2 property */ + if (hash_c1) + DDS_Security_BinaryProperty_set_by_value(hash_c1, "hash_c1", hash_c1_ref->value._buffer, hash_c1_ref->value._length); + if (hash_c2) + DDS_Security_BinaryProperty_set_by_value(hash_c2, "hash_c2", hash_c2_ref->value._buffer, hash_c2_ref->value._length); + if (dh1) + DDS_Security_BinaryProperty_set_by_value(dh1, "dh1", dh1_ref->value._buffer, dh1_ref->value._length); + if (dh2) + DDS_Security_BinaryProperty_set_by_value(dh2, "dh2", dh2_ref->value._buffer, dh2_ref->value._length); assert(relation->lchallenge); - - DDS_Security_BinaryProperty_set_by_value(challenge2, "challenge2", relation->lchallenge->value, sizeof(AuthenticationChallenge)); + if (challenge1 && challenge1_ref) + DDS_Security_BinaryProperty_set_by_value(challenge1, "challenge1", challenge1_ref->value._buffer, challenge1_ref->value._length); + assert(relation->rchallenge); + if (challenge2 && challenge2_ref) + DDS_Security_BinaryProperty_set_by_value(challenge2, "challenge2", challenge2_ref->value._buffer, challenge2_ref->value._length); /* Calculate the signature */ { - unsigned char *sign; - size_t signlen; - const DDS_Security_BinaryProperty_t * binary_properties[ HANDSHAKE_SIGNATURE_CONTENT_SIZE ]; - DDS_Security_BinaryProperty_t *hash_c1_val = hash_value_to_binary_property("hash_c1", handshake->hash_c1); - DDS_Security_BinaryProperty_t *hash_c2_val = hash_value_to_binary_property("hash_c2", handshake->hash_c2); - - binary_properties[0] = hash_c2_val; - binary_properties[1] = challenge2; - binary_properties[2] = dh2; - binary_properties[3] = challenge1; - binary_properties[4] = dh1; - binary_properties[5] = hash_c1_val; - - result = create_signature(localIdent->privateKey, binary_properties, HANDSHAKE_SIGNATURE_CONTENT_SIZE , &sign, &signlen, ex); - - DDS_Security_BinaryProperty_free(hash_c1_val); - DDS_Security_BinaryProperty_free(hash_c2_val); - - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_signature; - } - DDS_Security_BinaryProperty_set_by_ref(signature, "signature", sign, (uint32_t)signlen); + unsigned char *sign; + size_t signlen; + DDS_Security_BinaryProperty_t *hash_c1_val = hash_value_to_binary_property("hash_c1", handshake->hash_c1); + DDS_Security_BinaryProperty_t *hash_c2_val = hash_value_to_binary_property("hash_c2", handshake->hash_c2); + const DDS_Security_BinaryProperty_t *binary_properties[HANDSHAKE_SIGNATURE_CONTENT_SIZE] = { hash_c1_val, challenge1, dh1, challenge2, dh2, hash_c2_val }; + DDS_Security_ValidationResult_t result = create_signature(relation->localIdentity->privateKey, binary_properties, HANDSHAKE_SIGNATURE_CONTENT_SIZE, &sign, &signlen, ex); + DDS_Security_BinaryProperty_free(hash_c1_val); + DDS_Security_BinaryProperty_free(hash_c2_val); + if (result != DDS_SECURITY_VALIDATION_OK) + goto err_signature; + DDS_Security_BinaryProperty_set_by_ref(signature, "signature", sign, (uint32_t)signlen); } - (void)ddsrt_hh_add(impl->objectHash, handshake); - - handshake_message_out->class_id = ddsrt_strdup(AUTH_HANDSHAKE_REPLY_TOKEN_ID); + handshake_message_out->class_id = ddsrt_strdup(AUTH_HANDSHAKE_FINAL_TOKEN_ID); handshake_message_out->binary_properties._length = tokenSize; handshake_message_out->binary_properties._buffer = tokens; + challenge1_ref_for_shared_secret = (DDS_Security_octet *)(handshake->relation->lchallenge); + challenge2_ref_for_shared_secret = (DDS_Security_octet *)(handshake->relation->rchallenge); + hs_result = DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE; + break; + case CREATEDREPLY: + /* The source of the handshake_handle is a begin_handshake_reply function So, handshake_message_in is from a remote process_handshake function */ + /* Verify Message Token contents according to Spec 9.3.2.5.3 (Final Message) */ + if (validate_handshake_final_token(handshake_message_in, handshake, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_inv_token; + challenge2_ref_for_shared_secret = (DDS_Security_octet *)(handshake->relation->lchallenge); + challenge1_ref_for_shared_secret = (DDS_Security_octet *)(handshake->relation->rchallenge); + hs_result = DDS_SECURITY_VALIDATION_OK; + break; + + default: ddsrt_mutex_unlock(&impl->lock); + goto err_bad_param; + } + { + DDS_Security_long shared_secret_length; + unsigned char *shared_secret; + if (!generate_shared_secret(handshake, &shared_secret, &shared_secret_length, ex)) + goto err_openssl; + handshake->shared_secret_handle_impl = ddsrt_malloc(sizeof(DDS_Security_SharedSecretHandleImpl)); + handshake->shared_secret_handle_impl->shared_secret = shared_secret; + handshake->shared_secret_handle_impl->shared_secret_size = shared_secret_length; + memcpy(handshake->shared_secret_handle_impl->challenge1, challenge1_ref_for_shared_secret, DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE); + memcpy(handshake->shared_secret_handle_impl->challenge2, challenge2_ref_for_shared_secret, DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE); + } - *handshake_handle = HANDSHAKE_HANDLE(handshake); - - if (result == DDS_SECURITY_VALIDATION_OK) { - result = DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE; - } - - return result; - -err_signature: - free_binary_properties(tokens, tokenSize); -err_get_public_key: -err_gen_dh_keys: - ddsrt_free(certData); -err_alloc_cid: -err_inv_token: - if (created) { - (void)ddsrt_hh_remove(impl->objectHash, handshake); - security_object_free((SecurityObject *)handshake); - } -err_inv_handle: - ddsrt_mutex_unlock(&impl->lock); -err_bad_param: - return DDS_SECURITY_VALIDATION_FAILED; -} - - -static bool -generate_shared_secret( - const HandshakeInfo *handshake, - unsigned char **shared_secret, - DDS_Security_long *length, - DDS_Security_SecurityException *ex) -{ - bool result = false; - EVP_PKEY_CTX *ctx; - size_t skeylen; - unsigned char *secret = NULL; - - *shared_secret = NULL; - - ctx = EVP_PKEY_CTX_new( handshake->ldh, NULL /* no engine */); - if (!ctx) + { + /* setup expiry listener */ + dds_time_t cert_exp = get_certificate_expiry(handshake->relation->remoteIdentity->identityCert); + if (cert_exp == DDS_TIME_INVALID) { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "process_handshake: Shared secret failed to create context: "); - goto fail_ctx_new; + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Expiry date of the certificate is invalid"); + goto err_invalid_expiry; } - - if (EVP_PKEY_derive_init(ctx) <= 0) - { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "process_handshake: Shared secret failed to initialize context: "); - goto fail_derive; - } - if (EVP_PKEY_derive_set_peer(ctx, handshake->rdh) <= 0) - { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "process_handshake: Shared secret failed to set peer key: "); - goto fail_derive; - } - - /* Determine buffer length */ - if (EVP_PKEY_derive(ctx, NULL, &skeylen) <= 0) - { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "process_handshake: Shared secret failed to determine key length: "); - goto fail_derive; - } - - secret = ddsrt_malloc(skeylen); - if (EVP_PKEY_derive(ctx, secret, &skeylen) <= 0) - { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "process_handshake: Could not compute the shared secret: "); - goto fail_derive; - } - - *shared_secret = ddsrt_malloc(SHA256_DIGEST_LENGTH); - *length = SHA256_DIGEST_LENGTH; - - SHA256(secret, skeylen, *shared_secret); - - result = true; - -fail_derive: - ddsrt_free(secret); - EVP_PKEY_CTX_free(ctx); -fail_ctx_new: - return result; -} - - - - -DDS_Security_ValidationResult_t -process_handshake( - dds_security_authentication *instance, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) -{ - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - dds_security_authentication_impl *impl = (dds_security_authentication_impl *) instance; - HandshakeInfo *handshake = NULL; - IdentityRelation *relation = NULL; - SecurityObject *obj; - EVP_PKEY *dhkeyRemote = NULL; - DDS_Security_BinaryProperty_t *tokens = NULL; - DDS_Security_BinaryProperty_t *hash_c1 = NULL; - const DDS_Security_BinaryProperty_t *hash_c1_ref; - const DDS_Security_BinaryProperty_t *hash_c2_ref; - const DDS_Security_BinaryProperty_t *challenge1_ref; - const DDS_Security_BinaryProperty_t *challenge2_ref; - const DDS_Security_BinaryProperty_t *dh1_ref; - const DDS_Security_BinaryProperty_t *dh2_ref; - DDS_Security_BinaryProperty_t *hash_c2 = NULL; - DDS_Security_BinaryProperty_t *dh1; - DDS_Security_BinaryProperty_t *dh2; - DDS_Security_BinaryProperty_t *challenge1; - DDS_Security_BinaryProperty_t *challenge2; - DDS_Security_BinaryProperty_t *signature; - uint32_t tokenSize=0, idx; - DDS_Security_octet * challenge1_ref_for_shared_secret, *challenge2_ref_for_shared_secret; - - /* validate provided arguments */ - if (!instance || !handshake_handle || !handshake_message_out || !handshake_message_in) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, - DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "process_handshake: Invalid parameter provided"); - goto err_bad_param; - } - - memset(handshake_message_out, 0, sizeof(DDS_Security_HandshakeMessageToken)); - - ddsrt_mutex_lock(&impl->lock); - - obj = security_object_find(impl->objectHash, handshake_handle); - if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_HANDSHAKE)) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, - DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, - "process_handshake: Invalid replier_identity_handle provided"); - goto err_inv_handle; - } - handshake = (HandshakeInfo *) obj; - relation = handshake->relation; - assert(relation); - - /* check if the handle created by a handshake_request or handshake_reply */ - - switch (handshake->created_in) { - case CREATEDREQUEST: - /* The source of the handshake_handle is a begin_handshake_request function - * So, handshake_message_in should have been came from a remote begin_handshake_reply function - */ - /* Verify Message Token contents according to Spec 9.3.2.5.2 (Reply Message) */ - result = validate_handshake_reply_token(handshake_message_in, handshake, &dhkeyRemote, &(impl->trustedCAList), ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_inv_token; - } - - /*set received remote DH (dh2) */ - handshake->rdh = dhkeyRemote; - - EVP_PKEY_copy_parameters(handshake->rdh, handshake->ldh); - - /* Prepare HandshakeFinalMessageToken */ - - /* Get references from message_in */ - hash_c1_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "hash_c1"); - hash_c2_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "hash_c2"); - dh1_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "dh1"); - dh2_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "dh2"); - challenge1_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, - "challenge1"); - challenge2_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, - "challenge2"); - - tokenSize = 3; /* challenge1, challenge2 and signature are already exist */ - if (hash_c1_ref) - tokenSize++; - if (hash_c2_ref) - tokenSize++; - if (dh1_ref) - tokenSize++; - if (dh2_ref) - tokenSize++; - - tokens = DDS_Security_BinaryPropertySeq_allocbuf(tokenSize); - idx = 0; - signature = &tokens[idx++]; - hash_c2 = hash_c2_ref ? &tokens[idx++] : NULL; - challenge2 = &tokens[idx++]; - dh2 = dh2_ref ? &tokens[idx++] : NULL; - challenge1 = &tokens[idx++]; - dh1 = dh1_ref ? &tokens[idx++] : NULL; - hash_c1 = hash_c1_ref ? &tokens[idx++] : NULL; - - if (hash_c1) { - DDS_Security_BinaryProperty_set_by_value(hash_c1, "hash_c1", hash_c1_ref->value._buffer, - hash_c1_ref->value._length); - } - if (hash_c2) { - DDS_Security_BinaryProperty_set_by_value(hash_c2, "hash_c2", hash_c2_ref->value._buffer, - hash_c2_ref->value._length); - } - if (dh1) { - DDS_Security_BinaryProperty_set_by_value(dh1, "dh1", dh1_ref->value._buffer, - dh1_ref->value._length); - } - if (dh2) { - DDS_Security_BinaryProperty_set_by_value(dh2, "dh2", dh2_ref->value._buffer, - dh2_ref->value._length); - } - assert(relation->lchallenge); - if (challenge1 && challenge1_ref) { - DDS_Security_BinaryProperty_set_by_value(challenge1, "challenge1", challenge1_ref->value._buffer, - challenge1_ref->value._length); - } - assert(relation->rchallenge); - if (challenge2 && challenge2_ref) { - DDS_Security_BinaryProperty_set_by_value(challenge2, "challenge2", challenge2_ref->value._buffer, - challenge2_ref->value._length); - } - - - /* Calculate the signature */ - { - const DDS_Security_BinaryProperty_t * binary_properties[ HANDSHAKE_SIGNATURE_CONTENT_SIZE ]; - DDS_Security_BinaryProperty_t *hash_c1_val = hash_value_to_binary_property("hash_c1", handshake->hash_c1); - DDS_Security_BinaryProperty_t *hash_c2_val = hash_value_to_binary_property("hash_c2", handshake->hash_c2); - unsigned char *sign; - size_t signlen; - - binary_properties[0] = hash_c1_val; - binary_properties[1] = challenge1; - binary_properties[2] = dh1; - binary_properties[3] = challenge2; - binary_properties[4] = dh2; - binary_properties[5] = hash_c2_val; - - result = create_signature(relation->localIdentity->privateKey, binary_properties, HANDSHAKE_SIGNATURE_CONTENT_SIZE, &sign, &signlen, ex); - - DDS_Security_BinaryProperty_free(hash_c1_val); - DDS_Security_BinaryProperty_free(hash_c2_val); - - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_signature; - } - - DDS_Security_BinaryProperty_set_by_ref(signature, "signature", sign, (uint32_t)signlen); - } - - handshake_message_out->class_id = ddsrt_strdup(AUTH_HANDSHAKE_FINAL_TOKEN_ID); - handshake_message_out->binary_properties._length = tokenSize; - handshake_message_out->binary_properties._buffer = tokens; - - challenge1_ref_for_shared_secret = (DDS_Security_octet*)(handshake->relation->lchallenge); - challenge2_ref_for_shared_secret = (DDS_Security_octet*)(handshake->relation->rchallenge); - - result = DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE; - - break; - case CREATEDREPLY: - /* The source of the handshake_handle is a begin_handshake_reply function - * So, handshake_message_in should have been came from a remote process_handshake function - */ - - /* Verify Message Token contents according to Spec 9.3.2.5.3 (Final Message) */ - result = validate_handshake_final_token(handshake_message_in, handshake, ex); - if (result != DDS_SECURITY_VALIDATION_OK) { - goto err_inv_token; - } - - - challenge2_ref_for_shared_secret = (DDS_Security_octet*)(handshake->relation->lchallenge); - challenge1_ref_for_shared_secret = (DDS_Security_octet*)(handshake->relation->rchallenge); - - result = DDS_SECURITY_VALIDATION_OK; - - break; - default: - ddsrt_mutex_unlock(&impl->lock); - goto err_bad_param; - } - - /* Compute shared secret */ - { - DDS_Security_long shared_secret_length; - unsigned char *shared_secret; - - if (!generate_shared_secret(handshake, &shared_secret, &shared_secret_length, ex)) { - goto err_openssl; - } - - handshake->shared_secret_handle_impl = ddsrt_malloc( sizeof(DDS_Security_SharedSecretHandleImpl)); - handshake->shared_secret_handle_impl->shared_secret = shared_secret; - handshake->shared_secret_handle_impl->shared_secret_size = shared_secret_length; - - /* put references to challenge1 and challenge2 into shared secret object */ - memcpy( handshake->shared_secret_handle_impl->challenge1, challenge1_ref_for_shared_secret, DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE); - memcpy( handshake->shared_secret_handle_impl->challenge2, challenge2_ref_for_shared_secret, DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE); - } - - { /* setup expiry listener */ - dds_time_t certExpiry = get_certificate_expiry( handshake->relation->remoteIdentity->identityCert ); - - if( certExpiry == DDS_TIME_INVALID ){ - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, (int)result, "Expiry date of the certificate is invalid"); - goto err_invalid_expiry; - } else if( certExpiry != DDS_NEVER ){ - add_validity_end_trigger( impl, - IDENTITY_HANDLE( handshake->relation->remoteIdentity ), - certExpiry); - } - - } - - ddsrt_mutex_unlock(&impl->lock); - - return result; + else if (cert_exp != DDS_NEVER) + add_validity_end_trigger(impl, IDENTITY_HANDLE(handshake->relation->remoteIdentity), cert_exp); + } + ddsrt_mutex_unlock(&impl->lock); + return hs_result; err_invalid_expiry: - ddsrt_free( handshake->shared_secret_handle_impl->shared_secret ); - ddsrt_free( handshake->shared_secret_handle_impl ); + ddsrt_free(handshake->shared_secret_handle_impl->shared_secret); + ddsrt_free(handshake->shared_secret_handle_impl); + handshake->shared_secret_handle_impl = NULL; err_openssl: err_signature: - if (handshake_message_out->class_id) { - DDS_Security_DataHolder_deinit(handshake_message_out); - } + if (handshake_message_out->class_id) + DDS_Security_DataHolder_deinit(handshake_message_out); err_inv_token: err_inv_handle: - ddsrt_mutex_unlock(&impl->lock); + ddsrt_mutex_unlock(&impl->lock); err_bad_param: - return DDS_SECURITY_VALIDATION_FAILED; + return DDS_SECURITY_VALIDATION_FAILED; } -DDS_Security_SharedSecretHandle get_shared_secret( - dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) +DDS_Security_SharedSecretHandle get_shared_secret(dds_security_authentication *instance, const DDS_Security_HandshakeHandle handshake_handle, DDS_Security_SecurityException *ex) { + dds_security_authentication_impl *impl = (dds_security_authentication_impl *)instance; + SecurityObject *obj; - dds_security_authentication_impl *impl = (dds_security_authentication_impl *) instance; - SecurityObject *obj; + if (!instance || !handshake_handle) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_handshake_handle: Invalid parameter provided"); + goto err_bad_param; + } + ddsrt_mutex_lock(&impl->lock); + obj = security_object_find(impl->objectHash, handshake_handle); + if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_HANDSHAKE)) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_handshake_handle: Invalid handle provided"); + goto err_invalid_handle; + } + ddsrt_mutex_unlock(&impl->lock); + return (DDS_Security_SharedSecretHandle)(ddsrt_address)((HandshakeInfo *)obj)->shared_secret_handle_impl; - /* validate provided arguments */ - if (!instance || !handshake_handle) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_handshake_handle: Invalid parameter provided"); - goto err_bad_param; - } - - ddsrt_mutex_lock(&impl->lock); - obj = security_object_find(impl->objectHash, handshake_handle); - if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_HANDSHAKE)) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_handshake_handle: Invalid handle provided"); - goto err_invalid_handle; - } - - ddsrt_mutex_unlock(&impl->lock); - return (DDS_Security_SharedSecretHandle)(ddsrt_address)((HandshakeInfo*)obj)->shared_secret_handle_impl; - - - err_invalid_handle: - ddsrt_mutex_unlock(&impl->lock); - err_bad_param: - return DDS_SECURITY_HANDLE_NIL; +err_invalid_handle: + ddsrt_mutex_unlock(&impl->lock); +err_bad_param: + return DDS_SECURITY_HANDLE_NIL; } -DDS_Security_boolean -get_authenticated_peer_credential_token( - dds_security_authentication *instance, - DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) +DDS_Security_boolean get_authenticated_peer_credential_token(dds_security_authentication *instance, DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, + const DDS_Security_HandshakeHandle handshake_handle, DDS_Security_SecurityException *ex) { - dds_security_authentication_impl *impl = (dds_security_authentication_impl *) instance; - HandshakeInfo *handshake = NULL; - X509 *identity_cert; - char *permissions_doc; - unsigned char *cert_data; - uint32_t cert_data_size; + dds_security_authentication_impl *impl = (dds_security_authentication_impl *)instance; + HandshakeInfo *handshake = NULL; + X509 *identity_cert; + char *permissions_doc; + unsigned char *cert_data; + uint32_t cert_data_size; - /* validate provided arguments */ - if (!instance || !handshake_handle || !peer_credential_token) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, - DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, - DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); - return false; - } + if (!instance || !handshake_handle || !peer_credential_token) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + return false; + } - ddsrt_mutex_lock(&impl->lock); + ddsrt_mutex_lock(&impl->lock); - handshake = (HandshakeInfo *) security_object_find(impl->objectHash, handshake_handle); - if (!handshake || !SECURITY_OBJECT_VALID(handshake, SECURITY_OBJECT_KIND_HANDSHAKE)) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, - DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, - DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); - goto err_inv_handle; - } + handshake = (HandshakeInfo *)security_object_find(impl->objectHash, handshake_handle); + if (!handshake || !SECURITY_OBJECT_VALID(handshake, SECURITY_OBJECT_KIND_HANDSHAKE)) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); + goto err_inv_handle; + } - identity_cert = handshake->relation->remoteIdentity->identityCert; - if (!identity_cert) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, - DDS_SECURITY_ERR_OPERATION_NOT_PERMITTED_CODE, 0, - DDS_SECURITY_ERR_OPERATION_NOT_PERMITTED_MESSAGE); - goto err_missing_attr; - } + if (!(identity_cert = handshake->relation->remoteIdentity->identityCert)) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_OPERATION_NOT_PERMITTED_CODE, 0, DDS_SECURITY_ERR_OPERATION_NOT_PERMITTED_MESSAGE); + goto err_missing_attr; + } - permissions_doc = handshake->relation->remoteIdentity->permissionsDocument; - if (!permissions_doc) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, - DDS_SECURITY_ERR_MISSING_REMOTE_PERMISSIONS_DOCUMENT_CODE, 0, - DDS_SECURITY_ERR_MISSING_REMOTE_PERMISSIONS_DOCUMENT_MESSAGE); - goto err_missing_attr; - } + if (!(permissions_doc = handshake->relation->remoteIdentity->permissionsDocument)) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_MISSING_REMOTE_PERMISSIONS_DOCUMENT_CODE, 0, DDS_SECURITY_ERR_MISSING_REMOTE_PERMISSIONS_DOCUMENT_MESSAGE); + goto err_missing_attr; + } - if (get_certificate_contents(identity_cert, &cert_data, &cert_data_size, ex) != DDS_SECURITY_VALIDATION_OK) { - goto err_alloc_cid; - } + if (get_certificate_contents(identity_cert, &cert_data, &cert_data_size, ex) != DDS_SECURITY_VALIDATION_OK) + goto err_alloc_cid; - memset(peer_credential_token, 0, sizeof(*peer_credential_token)); - - peer_credential_token->class_id = get_authentication_class_id(); - - peer_credential_token->properties._length = 2; - peer_credential_token->properties._buffer = DDS_Security_PropertySeq_allocbuf(peer_credential_token->properties._length); - - peer_credential_token->properties._buffer[0].name = ddsrt_strdup("c.id"); - peer_credential_token->properties._buffer[0].value = (char *)cert_data; - peer_credential_token->properties._buffer[0].propagate = false; - - peer_credential_token->properties._buffer[1].name = ddsrt_strdup("c.perm"); - peer_credential_token->properties._buffer[1].value = ddsrt_strdup(permissions_doc); - peer_credential_token->properties._buffer[1].propagate = false; - - ddsrt_mutex_unlock(&impl->lock); - - return true; + memset(peer_credential_token, 0, sizeof(*peer_credential_token)); + peer_credential_token->class_id = get_authentication_class_id(); + peer_credential_token->properties._length = 2; + peer_credential_token->properties._buffer = DDS_Security_PropertySeq_allocbuf(peer_credential_token->properties._length); + peer_credential_token->properties._buffer[0].name = ddsrt_strdup("c.id"); + peer_credential_token->properties._buffer[0].value = (char *)cert_data; + peer_credential_token->properties._buffer[0].propagate = false; + peer_credential_token->properties._buffer[1].name = ddsrt_strdup("c.perm"); + peer_credential_token->properties._buffer[1].value = ddsrt_strdup(permissions_doc); + peer_credential_token->properties._buffer[1].propagate = false; + ddsrt_mutex_unlock(&impl->lock); + return true; err_alloc_cid: err_missing_attr: err_inv_handle: - ddsrt_mutex_unlock(&impl->lock); + ddsrt_mutex_unlock(&impl->lock); + return false; +} + +DDS_Security_boolean set_listener(dds_security_authentication *instance, const dds_security_authentication_listener *listener, DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(ex); + dds_security_authentication_impl *auth = (dds_security_authentication_impl *)instance; + if (listener) + dds_security_timed_dispatcher_enable(auth->timed_callbacks, auth->dispatcher, (void *)listener); + else + dds_security_timed_dispatcher_disable(auth->timed_callbacks, auth->dispatcher); + return true; +} + +DDS_Security_boolean return_identity_token(dds_security_authentication *instance, const DDS_Security_IdentityToken *token, DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(token); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +DDS_Security_boolean return_identity_status_token(dds_security_authentication *instance, const DDS_Security_IdentityStatusToken *token, DDS_Security_SecurityException *ex) +{ + DDSRT_UNUSED_ARG(token); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; +} + +DDS_Security_boolean return_authenticated_peer_credential_token(dds_security_authentication *instance, const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, DDS_Security_SecurityException *ex) +{ + if (!instance || !peer_credential_token) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); return false; + } + DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)peer_credential_token); + return true; } -DDS_Security_boolean set_listener(dds_security_authentication *instance, - const dds_security_authentication_listener *listener, - DDS_Security_SecurityException *ex) +DDS_Security_boolean return_handshake_handle(dds_security_authentication *instance, const DDS_Security_HandshakeHandle handshake_handle, DDS_Security_SecurityException *ex) { - dds_security_authentication_impl *auth = (dds_security_authentication_impl*)instance; + dds_security_authentication_impl *impl = (dds_security_authentication_impl *)instance; - DDSRT_UNUSED_ARG(ex); + if (!instance || !handshake_handle) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_handshake_handle: Invalid parameter provided"); + goto err_bad_param; + } - if (listener) { - dds_security_timed_dispatcher_enable(auth->timed_callbacks, auth->dispatcher, (void*)listener); - } else { - dds_security_timed_dispatcher_disable(auth->timed_callbacks, auth->dispatcher); + ddsrt_mutex_lock(&impl->lock); + SecurityObject *obj = security_object_find(impl->objectHash, handshake_handle); + if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_HANDSHAKE)) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_handshake_handle: Invalid handle provided"); + goto err_invalid_handle; + } + HandshakeInfo *handshake = (HandshakeInfo *)obj; + assert(handshake->relation); + (void)ddsrt_hh_remove(impl->objectHash, obj); + security_object_free((SecurityObject *)handshake); + ddsrt_mutex_unlock(&impl->lock); + return true; + +err_invalid_handle: + ddsrt_mutex_unlock(&impl->lock); +err_bad_param: + return false; +} + +static void invalidate_local_related_objects(dds_security_authentication_impl *impl, LocalIdentityInfo *localIdent) +{ + struct ddsrt_hh_iter it; + SecurityObject *obj; + + for (obj = ddsrt_hh_iter_first(impl->objectHash, &it); obj != NULL; obj = ddsrt_hh_iter_next(&it)) + { + if (obj->kind == SECURITY_OBJECT_KIND_REMOTE_IDENTITY) + { + RemoteIdentityInfo *remoteIdent = (RemoteIdentityInfo *)obj; + HandshakeInfo *handshake = find_handshake(impl, SECURITY_OBJECT_HANDLE(localIdent), SECURITY_OBJECT_HANDLE(remoteIdent)); + if (handshake) + { + (void)ddsrt_hh_remove(impl->objectHash, handshake); + security_object_free((SecurityObject *)handshake); + } + IdentityRelation *relation = find_identity_relation(remoteIdent, SECURITY_OBJECT_HANDLE(localIdent)); + if (relation) + remove_identity_relation(remoteIdent, relation); } - - return true; + } } -DDS_Security_boolean return_identity_token(dds_security_authentication *instance, - const DDS_Security_IdentityToken *token, - DDS_Security_SecurityException *ex) +static void invalidate_remote_related_objects(dds_security_authentication_impl *impl, RemoteIdentityInfo *remoteIdentity) { - DDSRT_UNUSED_ARG(token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_identity_status_token( - dds_security_authentication *instance, - const DDS_Security_IdentityStatusToken *token, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -DDS_Security_boolean return_authenticated_peer_credential_token( - dds_security_authentication *instance, - const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - DDS_Security_SecurityException *ex) -{ - if ((!instance) || (!peer_credential_token)) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_PARAMETER_CODE, 0, DDS_SECURITY_ERR_INVALID_PARAMETER_MESSAGE); - return false; + struct ddsrt_hh_iter it; + for (IdentityRelation *relation = ddsrt_hh_iter_first(remoteIdentity->linkHash, &it); relation != NULL; relation = ddsrt_hh_iter_next(&it)) + { + HandshakeInfo *handshake = find_handshake(impl, SECURITY_OBJECT_HANDLE(relation->localIdentity), SECURITY_OBJECT_HANDLE(remoteIdentity)); + if (handshake) + { + (void)ddsrt_hh_remove(impl->objectHash, handshake); + security_object_free((SecurityObject *)handshake); } - - DDS_Security_DataHolder_deinit((DDS_Security_DataHolder *)peer_credential_token); - - return true; + (void)ddsrt_hh_remove(remoteIdentity->linkHash, relation); + security_object_free((SecurityObject *)relation); + } } -DDS_Security_boolean -return_handshake_handle(dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex) +DDS_Security_boolean return_identity_handle(dds_security_authentication *instance, const DDS_Security_IdentityHandle identity_handle, DDS_Security_SecurityException *ex) { - dds_security_authentication_impl *impl = (dds_security_authentication_impl *) instance; - SecurityObject *obj; - HandshakeInfo *handshake; + dds_security_authentication_impl *impl = (dds_security_authentication_impl *)instance; + SecurityObject *obj; + LocalIdentityInfo *localIdent; + RemoteIdentityInfo *remoteIdent; - /* validate provided arguments */ - if (!instance || !handshake_handle) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_handshake_handle: Invalid parameter provided"); - goto err_bad_param; - } - - ddsrt_mutex_lock(&impl->lock); - obj = security_object_find(impl->objectHash, handshake_handle); - if (!obj || !security_object_valid(obj, SECURITY_OBJECT_KIND_HANDSHAKE)) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_handshake_handle: Invalid handle provided"); - goto err_invalid_handle; - } - handshake = (HandshakeInfo *)obj; - - assert(handshake->relation); + if (!instance || !identity_handle) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_identity_handle: Invalid parameter provided"); + goto err_bad_param; + } + /* Currently the implementation of the handle does not provide information about the kind of handle. In this case a valid handle could refer to a LocalIdentityObject or a RemoteIdentityObject */ + ddsrt_mutex_lock(&impl->lock); + if (!(obj = security_object_find(impl->objectHash, identity_handle))) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_identity_handle: Invalid handle provided"); + goto failed; + } + switch (obj->kind) + { + case SECURITY_OBJECT_KIND_LOCAL_IDENTITY: + localIdent = (LocalIdentityInfo *)obj; + invalidate_local_related_objects(impl, localIdent); (void)ddsrt_hh_remove(impl->objectHash, obj); - security_object_free((SecurityObject *)handshake); + security_object_free(obj); + break; + case SECURITY_OBJECT_KIND_REMOTE_IDENTITY: + remoteIdent = (RemoteIdentityInfo *)obj; + invalidate_remote_related_objects(impl, remoteIdent); + (void)ddsrt_hh_remove(impl->remoteGuidHash, remoteIdent); + (void)ddsrt_hh_remove(impl->objectHash, obj); + security_object_free(obj); + break; + default: + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_identity_handle: Invalid handle provided"); + goto failed; + } + ddsrt_mutex_unlock(&impl->lock); + return true; - ddsrt_mutex_unlock(&impl->lock); - - return true; - -err_invalid_handle: - ddsrt_mutex_unlock(&impl->lock); +failed: + ddsrt_mutex_unlock(&impl->lock); err_bad_param: - return false; + return false; } - -static void -invalidate_local_related_objects( - dds_security_authentication_impl *impl, - LocalIdentityInfo *localIdent) +DDS_Security_boolean return_sharedsecret_handle(dds_security_authentication *instance, const DDS_Security_SharedSecretHandle sharedsecret_handle, DDS_Security_SecurityException *ex) { - struct ddsrt_hh_iter it; - SecurityObject *obj; - - for (obj = ddsrt_hh_iter_first(impl->objectHash, &it); obj != NULL; obj = ddsrt_hh_iter_next(&it)) { - if (obj->kind == SECURITY_OBJECT_KIND_REMOTE_IDENTITY) { - RemoteIdentityInfo *remoteIdent = (RemoteIdentityInfo *)obj; - IdentityRelation *relation; - HandshakeInfo *handshake; - - handshake = find_handshake(impl, SECURITY_OBJECT_HANDLE(localIdent), SECURITY_OBJECT_HANDLE(remoteIdent)); - if (handshake) { - (void)ddsrt_hh_remove(impl->objectHash, handshake); - security_object_free((SecurityObject *) handshake); - } - - relation = find_identity_relation(remoteIdent, SECURITY_OBJECT_HANDLE(localIdent)); - if (relation) { - remove_identity_relation(remoteIdent, relation); - } - } - } + DDSRT_UNUSED_ARG(sharedsecret_handle); + DDSRT_UNUSED_ARG(ex); + DDSRT_UNUSED_ARG(instance); + return true; } -static void -invalidate_remote_related_objects( - dds_security_authentication_impl *impl, - RemoteIdentityInfo *remoteIdentity) +int32_t init_authentication(const char *argument, void **context) { - struct ddsrt_hh_iter it; - IdentityRelation *relation; - HandshakeInfo *handshake; + DDSRT_UNUSED_ARG(argument); + dds_security_authentication_impl *authentication; - for (relation = ddsrt_hh_iter_first(remoteIdentity->linkHash, &it); relation != NULL; relation = ddsrt_hh_iter_next(&it)) { - handshake = find_handshake(impl, SECURITY_OBJECT_HANDLE(relation->localIdentity), SECURITY_OBJECT_HANDLE(remoteIdentity)); - if (handshake) { - (void)ddsrt_hh_remove(impl->objectHash, handshake); - security_object_free((SecurityObject *) handshake); - } + authentication = (dds_security_authentication_impl *)ddsrt_malloc(sizeof(dds_security_authentication_impl)); + memset(authentication, 0, sizeof(dds_security_authentication_impl)); - (void)ddsrt_hh_remove(remoteIdentity->linkHash, relation); - security_object_free((SecurityObject *) relation); - } -} + authentication->timed_callbacks = dds_security_timed_cb_new(); + authentication->dispatcher = dds_security_timed_dispatcher_new(authentication->timed_callbacks); -DDS_Security_boolean -return_identity_handle( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle identity_handle, - DDS_Security_SecurityException *ex) -{ - DDS_Security_boolean result = true; - dds_security_authentication_impl *impl = (dds_security_authentication_impl *) instance; - SecurityObject *obj; - LocalIdentityInfo *localIdent; - RemoteIdentityInfo *remoteIdent; + authentication->base.validate_local_identity = &validate_local_identity; + authentication->base.get_identity_token = &get_identity_token; + authentication->base.get_identity_status_token = &get_identity_status_token; + authentication->base.set_permissions_credential_and_token = &set_permissions_credential_and_token; + authentication->base.validate_remote_identity = &validate_remote_identity; + authentication->base.begin_handshake_request = &begin_handshake_request; + authentication->base.begin_handshake_reply = &begin_handshake_reply; + authentication->base.process_handshake = &process_handshake; + authentication->base.get_shared_secret = &get_shared_secret; + authentication->base.get_authenticated_peer_credential_token = &get_authenticated_peer_credential_token; + authentication->base.set_listener = &set_listener; + authentication->base.return_identity_token = &return_identity_token; + authentication->base.return_identity_status_token = &return_identity_status_token; + authentication->base.return_authenticated_peer_credential_token = &return_authenticated_peer_credential_token; + authentication->base.return_handshake_handle = &return_handshake_handle; + authentication->base.return_identity_handle = &return_identity_handle; + authentication->base.return_sharedsecret_handle = &return_sharedsecret_handle; + ddsrt_mutex_init(&authentication->lock); + authentication->objectHash = ddsrt_hh_new(32, security_object_hash, security_object_equal); + authentication->remoteGuidHash = ddsrt_hh_new(32, remote_guid_hash, remote_guid_equal); + memset(&authentication->trustedCAList, 0, sizeof(X509Seq)); - /* validate provided arguments */ - if (!instance || !identity_handle) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_identity_handle: Invalid parameter provided"); - goto err_bad_param; - } + OpenSSL_add_all_algorithms(); + OpenSSL_add_all_ciphers(); + OpenSSL_add_all_digests(); + ERR_load_BIO_strings(); + ERR_load_crypto_strings(); - /* Currently the implementation of the handle does not provide information - * about the kind of handle. In this case a valid handle could refer to a - * LocalIdentityObject or a RemoteIdentityObject - */ - - ddsrt_mutex_lock(&impl->lock); - - obj = security_object_find(impl->objectHash, identity_handle); - if (!obj) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_identity_handle: Invalid handle provided"); - goto err_invalid_handle; - } - - switch (obj->kind) { - case SECURITY_OBJECT_KIND_LOCAL_IDENTITY: - localIdent = (LocalIdentityInfo *) obj; - invalidate_local_related_objects(impl, localIdent); - (void)ddsrt_hh_remove(impl->objectHash, obj); - security_object_free(obj); - break; - case SECURITY_OBJECT_KIND_REMOTE_IDENTITY: - remoteIdent = (RemoteIdentityInfo *) obj; - invalidate_remote_related_objects(impl, remoteIdent); - (void)ddsrt_hh_remove(impl->remoteGuidHash, remoteIdent); - (void)ddsrt_hh_remove(impl->objectHash, obj); - security_object_free(obj); - break; - default: - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "return_identity_handle: Invalid handle provided"); - result = false; - break; - } - - ddsrt_mutex_unlock(&impl->lock); - - return result; - -err_invalid_handle: - ddsrt_mutex_unlock(&impl->lock); -err_bad_param: - return false; -} - -DDS_Security_boolean return_sharedsecret_handle( - dds_security_authentication *instance, - const DDS_Security_SharedSecretHandle sharedsecret_handle, - DDS_Security_SecurityException *ex) -{ - DDSRT_UNUSED_ARG(sharedsecret_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - - return true; -} - -int32_t -init_authentication( const char *argument, void **context) -{ - - dds_security_authentication_impl *authentication; - - DDSRT_UNUSED_ARG(argument); - - /* allocate implementation wrapper */ - authentication = (dds_security_authentication_impl*) ddsrt_malloc( - sizeof(dds_security_authentication_impl)); - memset(authentication, 0, sizeof(dds_security_authentication_impl)); - - /* assign dispatcher to be notified when a validity date ends */ - authentication->timed_callbacks = dds_security_timed_cb_new(); - authentication->dispatcher = dds_security_timed_dispatcher_new(authentication->timed_callbacks); - - /* assign the interface functions */ - authentication->base.validate_local_identity = &validate_local_identity; - - authentication->base.get_identity_token = &get_identity_token; - - authentication->base.get_identity_status_token = &get_identity_status_token; - - authentication->base.set_permissions_credential_and_token = - &set_permissions_credential_and_token; - - authentication->base.validate_remote_identity = &validate_remote_identity; - - authentication->base.begin_handshake_request = &begin_handshake_request; - - authentication->base.begin_handshake_reply = &begin_handshake_reply; - - authentication->base.process_handshake = &process_handshake; - - authentication->base.get_shared_secret = &get_shared_secret; - - authentication->base.get_authenticated_peer_credential_token = - &get_authenticated_peer_credential_token; - - authentication->base.set_listener = &set_listener; - - authentication->base.return_identity_token = &return_identity_token; - - authentication->base.return_identity_status_token = - &return_identity_status_token; - - authentication->base.return_authenticated_peer_credential_token = - &return_authenticated_peer_credential_token; - - authentication->base.return_handshake_handle = &return_handshake_handle; - - authentication->base.return_identity_handle = &return_identity_handle; - - authentication->base.return_sharedsecret_handle = &return_sharedsecret_handle; - - ddsrt_mutex_init(&authentication->lock); - - authentication->objectHash = ddsrt_hh_new(32, security_object_hash, security_object_equal); - authentication->remoteGuidHash = ddsrt_hh_new(32, remote_guid_hash, remote_guid_equal); - - memset( &authentication->trustedCAList, 0, sizeof(X509Seq)); - - - /* Initialize openssl */ - OpenSSL_add_all_algorithms(); - OpenSSL_add_all_ciphers(); - OpenSSL_add_all_digests(); - ERR_load_BIO_strings(); - ERR_load_crypto_strings(); - - //return the instance - *context = authentication; - return 0; - -/* we can not get ddsrt_mutex_init result. So ignore the lines below */ -#if MUTEX_INIT_RESULT_IMPLEMENTED -err_mutex_failed: - ddsrt_free(authentication); - return -1; -#endif + *context = authentication; + return 0; } int32_t finalize_authentication(void *instance) { - dds_security_authentication_impl *authentication = instance; - - if( authentication ){ - ddsrt_mutex_lock(&authentication->lock); - - dds_security_timed_dispatcher_free(authentication->timed_callbacks, authentication->dispatcher); - dds_security_timed_cb_free(authentication->timed_callbacks); - - if (authentication->remoteGuidHash) { - ddsrt_hh_free(authentication->remoteGuidHash); - } - - if (authentication->objectHash) { - struct ddsrt_hh_iter it; - SecurityObject *obj; - for (obj = ddsrt_hh_iter_first(authentication->objectHash, &it); obj != NULL; obj = ddsrt_hh_iter_next(&it)) { - security_object_free(obj); - } - ddsrt_hh_free(authentication->objectHash); - } - - free_ca_list_contents(&(authentication->trustedCAList)); - - ddsrt_mutex_unlock(&authentication->lock); - - ddsrt_mutex_destroy(&authentication->lock); - - ddsrt_free((dds_security_authentication_impl*) instance); + dds_security_authentication_impl *authentication = instance; + if (authentication) + { + ddsrt_mutex_lock(&authentication->lock); + dds_security_timed_dispatcher_free(authentication->timed_callbacks, authentication->dispatcher); + dds_security_timed_cb_free(authentication->timed_callbacks); + if (authentication->remoteGuidHash) + ddsrt_hh_free(authentication->remoteGuidHash); + if (authentication->objectHash) + { + struct ddsrt_hh_iter it; + for (SecurityObject *obj = ddsrt_hh_iter_first(authentication->objectHash, &it); obj != NULL; obj = ddsrt_hh_iter_next(&it)) + security_object_free(obj); + ddsrt_hh_free(authentication->objectHash); } + free_ca_list_contents(&(authentication->trustedCAList)); + ddsrt_mutex_unlock(&authentication->lock); + ddsrt_mutex_destroy(&authentication->lock); + ddsrt_free((dds_security_authentication_impl *)instance); + } - RAND_cleanup(); - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - REMOVE_THREAD_STATE(); - ERR_free_strings(); - - return 0; + RAND_cleanup(); + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); + REMOVE_THREAD_STATE(); + ERR_free_strings(); + return 0; } diff --git a/src/security/builtin_plugins/authentication/src/authentication.h b/src/security/builtin_plugins/authentication/src/authentication.h index dcbcfd6..4e56a12 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.h +++ b/src/security/builtin_plugins/authentication/src/authentication.h @@ -10,7 +10,6 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ - #ifndef SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ #define SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ @@ -18,129 +17,34 @@ #include "dds/security/dds_security_api.h" #include "dds/security/export.h" -SECURITY_EXPORT int32_t -init_authentication(const char *argument, void **context); - -SECURITY_EXPORT int32_t -finalize_authentication(void *context); - - - - -DDS_Security_ValidationResult_t -validate_local_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *local_identity_handle, - DDS_Security_GUID_t *adjusted_participant_guid, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - const DDS_Security_GUID_t *candidate_participant_guid, - - DDS_Security_SecurityException *ex); -DDS_Security_boolean -get_identity_token(dds_security_authentication *instance, - DDS_Security_IdentityToken *identity_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex); -DDS_Security_boolean -set_permissions_credential_and_token( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle handle, - const DDS_Security_PermissionsCredentialToken *permissions_credential, - const DDS_Security_PermissionsToken *permissions_token, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -validate_remote_identity( - dds_security_authentication *instance, - DDS_Security_IdentityHandle *remote_identity_handle, - DDS_Security_AuthRequestMessageToken *local_auth_request_token, - const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityToken *remote_identity_token, - const DDS_Security_GUID_t *remote_participant_guid, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -begin_handshake_request( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -begin_handshake_reply( - dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex); - -DDS_Security_ValidationResult_t -process_handshake( - dds_security_authentication *instance, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_SharedSecretHandle get_shared_secret( - dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -get_authenticated_peer_credential_token( - dds_security_authentication *instance, - DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - - -DDS_Security_boolean get_identity_status_token( - dds_security_authentication *instance, - DDS_Security_IdentityStatusToken *identity_status_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean set_listener(dds_security_authentication *instance, - const dds_security_authentication_listener *listener, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_identity_token(dds_security_authentication *instance, - const DDS_Security_IdentityToken *token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_identity_status_token( - dds_security_authentication *instance, - const DDS_Security_IdentityStatusToken *token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_authenticated_peer_credential_token( - dds_security_authentication *instance, - const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean -return_handshake_handle(dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); -DDS_Security_boolean -return_identity_handle( - dds_security_authentication *instance, - const DDS_Security_IdentityHandle identity_handle, - DDS_Security_SecurityException *ex); - -DDS_Security_boolean return_sharedsecret_handle( - dds_security_authentication *instance, - const DDS_Security_SharedSecretHandle sharedsecret_handle, - DDS_Security_SecurityException *ex); +SECURITY_EXPORT int32_t init_authentication(const char *argument, void **context); +SECURITY_EXPORT int32_t finalize_authentication(void *context); +DDS_Security_ValidationResult_t validate_local_identity(dds_security_authentication *instance, DDS_Security_IdentityHandle *local_identity_handle, DDS_Security_GUID_t *adjusted_participant_guid, + const DDS_Security_DomainId domain_id, const DDS_Security_Qos *participant_qos, const DDS_Security_GUID_t *candidate_participant_guid, DDS_Security_SecurityException *ex); +DDS_Security_boolean get_identity_token(dds_security_authentication *instance, DDS_Security_IdentityToken *identity_token, const DDS_Security_IdentityHandle handle, DDS_Security_SecurityException *ex); +DDS_Security_boolean set_permissions_credential_and_token(dds_security_authentication *instance, const DDS_Security_IdentityHandle handle, const DDS_Security_PermissionsCredentialToken *permissions_credential, + const DDS_Security_PermissionsToken *permissions_token, DDS_Security_SecurityException *ex); +DDS_Security_ValidationResult_t validate_remote_identity(dds_security_authentication *instance, DDS_Security_IdentityHandle *remote_identity_handle, DDS_Security_AuthRequestMessageToken *local_auth_request_token, + const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, const DDS_Security_IdentityHandle local_identity_handle, const DDS_Security_IdentityToken *remote_identity_token, + const DDS_Security_GUID_t *remote_participant_guid, DDS_Security_SecurityException *ex); +DDS_Security_ValidationResult_t begin_handshake_request(dds_security_authentication *instance, DDS_Security_HandshakeHandle *handshake_handle, DDS_Security_HandshakeMessageToken *handshake_message, + const DDS_Security_IdentityHandle initiator_identity_handle, const DDS_Security_IdentityHandle replier_identity_handle, const DDS_Security_OctetSeq *serialized_local_participant_data, DDS_Security_SecurityException *ex); +DDS_Security_ValidationResult_t begin_handshake_reply(dds_security_authentication *instance, DDS_Security_HandshakeHandle *handshake_handle, DDS_Security_HandshakeMessageToken *handshake_message_out, + const DDS_Security_HandshakeMessageToken *handshake_message_in, const DDS_Security_IdentityHandle initiator_identity_handle, const DDS_Security_IdentityHandle replier_identity_handle, + const DDS_Security_OctetSeq *serialized_local_participant_data, DDS_Security_SecurityException *ex); +DDS_Security_ValidationResult_t process_handshake(dds_security_authentication *instance, DDS_Security_HandshakeMessageToken *handshake_message_out, const DDS_Security_HandshakeMessageToken *handshake_message_in, + const DDS_Security_HandshakeHandle handshake_handle, DDS_Security_SecurityException *ex); +DDS_Security_SharedSecretHandle get_shared_secret(dds_security_authentication *instance, const DDS_Security_HandshakeHandle handshake_handle, DDS_Security_SecurityException *ex); +DDS_Security_boolean get_authenticated_peer_credential_token(dds_security_authentication *instance, DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, + const DDS_Security_HandshakeHandle handshake_handle, DDS_Security_SecurityException *ex); +DDS_Security_boolean get_identity_status_token(dds_security_authentication *instance, DDS_Security_IdentityStatusToken *identity_status_token, const DDS_Security_IdentityHandle handle, DDS_Security_SecurityException *ex); +DDS_Security_boolean set_listener(dds_security_authentication *instance, const dds_security_authentication_listener *listener, DDS_Security_SecurityException *ex); +DDS_Security_boolean return_identity_token(dds_security_authentication *instance, const DDS_Security_IdentityToken *token, DDS_Security_SecurityException *ex); +DDS_Security_boolean return_identity_status_token(dds_security_authentication *instance, const DDS_Security_IdentityStatusToken *token, DDS_Security_SecurityException *ex); +DDS_Security_boolean return_authenticated_peer_credential_token(dds_security_authentication *instance, const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, DDS_Security_SecurityException *ex); +DDS_Security_boolean return_handshake_handle(dds_security_authentication *instance, const DDS_Security_HandshakeHandle handshake_handle, DDS_Security_SecurityException *ex); +DDS_Security_boolean return_identity_handle(dds_security_authentication *instance, const DDS_Security_IdentityHandle identity_handle, DDS_Security_SecurityException *ex); +DDS_Security_boolean return_sharedsecret_handle(dds_security_authentication *instance, const DDS_Security_SharedSecretHandle sharedsecret_handle, DDS_Security_SecurityException *ex); #endif /* SECURITY_BUILTIN_PLUGINS_AUTHENTICATION_H_ */ From 0768ad59edfacc203db8f047c2321472a2c243e8 Mon Sep 17 00:00:00 2001 From: Dennis Potman <45659984+dennis-adlink@users.noreply.github.com> Date: Fri, 20 Mar 2020 13:44:27 +0100 Subject: [PATCH 129/238] Remove duplicated code in authentication plugin (#442) * Remove duplicated code in authentication plugin Signed-off-by: Dennis Potman * Fix build warnings Signed-off-by: Dennis Potman * Fix memory leak and call create_validate_asymmetrical_signature directly from create_validate_signature_impl Signed-off-by: Dennis Potman * Fix refcount issue (assert in openssl) for identity cert in hs remote info Signed-off-by: Dennis Potman * Refactoring of validate_handshake_token function Co-authored-by: Erik Boasson Signed-off-by: Dennis Potman --- .../authentication/src/auth_utils.c | 84 +- .../authentication/src/auth_utils.h | 4 +- .../authentication/src/authentication.c | 802 ++++++------------ .../dds/security/core/dds_security_utils.h | 12 +- src/security/core/src/dds_security_utils.c | 73 +- 5 files changed, 348 insertions(+), 627 deletions(-) diff --git a/src/security/builtin_plugins/authentication/src/auth_utils.c b/src/security/builtin_plugins/authentication/src/auth_utils.c index 54e94b2..e79a951 100644 --- a/src/security/builtin_plugins/authentication/src/auth_utils.c +++ b/src/security/builtin_plugins/authentication/src/auth_utils.c @@ -956,94 +956,54 @@ DDS_Security_ValidationResult_t get_trusted_ca_list(const char *trusted_ca_dir, return failed ? DDS_SECURITY_VALIDATION_FAILED : DDS_SECURITY_VALIDATION_OK; } -DDS_Security_ValidationResult_t create_asymmetrical_signature(EVP_PKEY *pkey, const unsigned char *data, const size_t dataLen, +DDS_Security_ValidationResult_t create_validate_asymmetrical_signature(bool create, EVP_PKEY *pkey, const unsigned char *data, const size_t dataLen, unsigned char **signature, size_t *signatureLen, DDS_Security_SecurityException *ex) { EVP_MD_CTX *mdctx = NULL; EVP_PKEY_CTX *kctx = NULL; - if (!(mdctx = EVP_MD_CTX_create())) { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to create signing context: "); - goto err_create_ctx; + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to create digest context: "); + return DDS_SECURITY_VALIDATION_FAILED; } - if (EVP_DigestSignInit(mdctx, &kctx, EVP_sha256(), NULL, pkey) != 1) + if ((create ? EVP_DigestSignInit(mdctx, &kctx, EVP_sha256(), NULL, pkey) : EVP_DigestVerifyInit(mdctx, &kctx, EVP_sha256(), NULL, pkey)) != 1) { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to initialize signing context: "); - goto err_sign; + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to initialize digest context: "); + goto err; } if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { if (EVP_PKEY_CTX_set_rsa_padding(kctx, RSA_PKCS1_PSS_PADDING) < 1) { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to initialize signing context: "); - goto err_sign; + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to initialize digest context: "); + goto err; } } - if (EVP_DigestSignUpdate(mdctx, data, dataLen) != 1) + if ((create ? EVP_DigestSignUpdate(mdctx, data, dataLen) : EVP_DigestVerifyUpdate(mdctx, data, dataLen)) != 1) { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to update signing context: "); - goto err_sign; + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to update digest context: "); + goto err; } - if (EVP_DigestSignFinal(mdctx, NULL, signatureLen) != 1) + if (create) { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to finalize signing context: "); - goto err_sign; - } - *signature = ddsrt_malloc(sizeof(unsigned char) * (*signatureLen)); - if (EVP_DigestSignFinal(mdctx, *signature, signatureLen) != 1) - { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to finalize signing context: "); - ddsrt_free(*signature); - goto err_sign; - } - EVP_MD_CTX_destroy(mdctx); - return DDS_SECURITY_VALIDATION_OK; - -err_sign: - EVP_MD_CTX_destroy(mdctx); -err_create_ctx: - return DDS_SECURITY_VALIDATION_FAILED; -} - -DDS_Security_ValidationResult_t validate_asymmetrical_signature(EVP_PKEY *pkey, const unsigned char *data, const size_t dataLen, - const unsigned char *signature, const size_t signatureLen, DDS_Security_SecurityException *ex) -{ - EVP_MD_CTX *mdctx = NULL; - EVP_PKEY_CTX *kctx = NULL; - if (!(mdctx = EVP_MD_CTX_create())) - { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to create verify context: "); - goto err_create_ctx; - } - if (EVP_DigestVerifyInit(mdctx, &kctx, EVP_sha256(), NULL, pkey) != 1) - { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to initialize verify context: "); - goto err_verify; - } - if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) - { - if (EVP_PKEY_CTX_set_rsa_padding(kctx, RSA_PKCS1_PSS_PADDING) < 1) + if (EVP_DigestSignFinal(mdctx, NULL, signatureLen) != 1) { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to initialize signing context: "); - goto err_verify; + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to finalize digest context: "); + goto err; } + *signature = ddsrt_malloc(sizeof(unsigned char) * (*signatureLen)); } - if (EVP_DigestVerifyUpdate(mdctx, data, dataLen) != 1) + if ((create ? EVP_DigestSignFinal(mdctx, *signature, signatureLen) : EVP_DigestVerifyFinal(mdctx, *signature, *signatureLen)) != 1) { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to update verify context: "); - goto err_verify; - } - if (EVP_DigestVerifyFinal(mdctx, signature, signatureLen) != 1) - { - DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to finalize verify context: "); - goto err_verify; + DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Failed to finalize digest context: "); + if (create) + ddsrt_free(*signature); + goto err; } EVP_MD_CTX_destroy(mdctx); return DDS_SECURITY_VALIDATION_OK; -err_verify: +err: EVP_MD_CTX_destroy(mdctx); -err_create_ctx: return DDS_SECURITY_VALIDATION_FAILED; } diff --git a/src/security/builtin_plugins/authentication/src/auth_utils.h b/src/security/builtin_plugins/authentication/src/auth_utils.h index bbde1ba..52ca1f7 100644 --- a/src/security/builtin_plugins/authentication/src/auth_utils.h +++ b/src/security/builtin_plugins/authentication/src/auth_utils.h @@ -100,7 +100,7 @@ AuthConfItemPrefix_t get_conf_item_type(const char *str, char **data); void free_ca_list_contents(X509Seq *ca_list); DDS_Security_ValidationResult_t get_trusted_ca_list(const char* trusted_ca_dir, X509Seq *ca_list, DDS_Security_SecurityException *ex); char * string_from_data(const unsigned char *data, uint32_t size); -DDS_Security_ValidationResult_t create_asymmetrical_signature(EVP_PKEY *pkey, const unsigned char *data, const size_t dataLen, unsigned char **signature, size_t *signatureLen, DDS_Security_SecurityException *ex); -DDS_Security_ValidationResult_t validate_asymmetrical_signature(EVP_PKEY *pkey, const unsigned char *data, const size_t dataLen, const unsigned char *signature, const size_t signatureLen, DDS_Security_SecurityException *ex); +DDS_Security_ValidationResult_t create_validate_asymmetrical_signature(bool create, EVP_PKEY *pkey, const unsigned char *data, const size_t dataLen, + unsigned char **signature, size_t *signatureLen, DDS_Security_SecurityException *ex); #endif /* AUTH_UTILS_H */ diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index 79f03bd..951e07e 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -570,40 +570,33 @@ static void get_hash_binary_property_seq(const DDS_Security_BinaryPropertySeq *s DDS_Security_Serializer_free(serializer); } -static DDS_Security_ValidationResult_t create_signature(EVP_PKEY *pkey, const DDS_Security_BinaryProperty_t **binary_properties, - const uint32_t binary_properties_length, unsigned char **signature, size_t *signatureLen, DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t create_validate_signature_impl(bool create, EVP_PKEY *pkey, const DDS_Security_BinaryProperty_t **bprops, + const uint32_t n_bprops, unsigned char **signature, size_t *signature_len, DDS_Security_SecurityException *ex) { DDS_Security_ValidationResult_t result; unsigned char *buffer; size_t size; DDS_Security_Serializer serializer = DDS_Security_Serializer_new(4096, 4096); - - DDS_Security_Serialize_BinaryPropertyArray(serializer, binary_properties, binary_properties_length); + DDS_Security_Serialize_BinaryPropertyArray(serializer, bprops, n_bprops); DDS_Security_Serializer_buffer(serializer, &buffer, &size); - - result = create_asymmetrical_signature(pkey, buffer, size, signature, signatureLen, ex); + result = create_validate_asymmetrical_signature(create, pkey, buffer, size, signature, signature_len, ex); ddsrt_free(buffer); DDS_Security_Serializer_free(serializer); - return result; } -static DDS_Security_ValidationResult_t validate_signature(EVP_PKEY *pkey, const DDS_Security_BinaryProperty_t **properties, - const uint32_t properties_length, unsigned char *signature, size_t signatureLen, DDS_Security_SecurityException *ex) +static DDS_Security_ValidationResult_t create_signature(EVP_PKEY *pkey, const DDS_Security_BinaryProperty_t **bprops, + const uint32_t n_bprops, unsigned char **signature, size_t *signature_len, DDS_Security_SecurityException *ex) { - DDS_Security_ValidationResult_t result; - unsigned char *buffer; - size_t size; - DDS_Security_Serializer serializer = DDS_Security_Serializer_new(4096, 4096); + return create_validate_signature_impl(true, pkey, bprops, n_bprops, signature, signature_len, ex); +} - DDS_Security_Serialize_BinaryPropertyArray(serializer, properties, properties_length); - DDS_Security_Serializer_buffer(serializer, &buffer, &size); - - result = validate_asymmetrical_signature(pkey, buffer, size, signature, signatureLen, ex); - ddsrt_free(buffer); - DDS_Security_Serializer_free(serializer); - - return result; +static DDS_Security_ValidationResult_t validate_signature(EVP_PKEY *pkey, const DDS_Security_BinaryProperty_t **bprops, + const uint32_t n_bprops, const unsigned char *signature, size_t signature_len, DDS_Security_SecurityException *ex) +{ + unsigned char *s = (unsigned char *)signature; + size_t s_len = signature_len; + return create_validate_signature_impl(false, pkey, bprops, n_bprops, &s, &s_len, ex); } static DDS_Security_ValidationResult_t compute_hash_value(HashValue_t value, const DDS_Security_BinaryProperty_t **properties, @@ -1089,19 +1082,12 @@ DDS_Security_ValidationResult_t validate_remote_identity(dds_security_authentica ddsrt_free(lchallenge); } } - ddsrt_mutex_unlock(&impl->lock); if (!remote_auth_request_token) - { - /* Create local_auth_request_token with contents set to the challenge */ fill_auth_request_token(local_auth_request_token, relation->lchallenge); - } else - { - /* Set local_auth_request token to TokenNil */ DDS_Security_set_token_nil(local_auth_request_token); - } *remote_identity_handle = IDENTITY_HANDLE(remoteIdent); return memcmp(&localIdent->adjustedGUID, &remoteIdent->guid, sizeof(DDS_Security_GUID_t)) < 0 ? @@ -1206,6 +1192,7 @@ DDS_Security_ValidationResult_t begin_handshake_request(dds_security_authenticat DDS_Security_BinaryProperty_set_by_string(c_dsign_algo, "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); DDS_Security_BinaryProperty_set_by_string(c_kagree_algo, "c.kagree_algo", get_kagree_algo(localIdent->kagreeAlgoKind)); + /* Todo: including hash_c1 is optional (conform spec); add a configuration option to leave it out */ { DDS_Security_BinaryPropertySeq bseq = { ._length = 5, ._buffer = tokens }; get_hash_binary_property_seq(&bseq, handshake->hash_c1); @@ -1285,549 +1272,314 @@ failed_deser: return DDS_SECURITY_VALIDATION_FAILED; } -static DDS_Security_ValidationResult_t validate_handshake_request_token(const DDS_Security_HandshakeMessageToken *token, HandshakeInfo *handshake, X509Seq *trusted_ca_list, DDS_Security_SecurityException *ex) +enum handshake_token_type { - IdentityRelation *relation = handshake->relation; - X509 *identityCert; - const DDS_Security_BinaryProperty_t *c_id, *c_perm, *c_pdata, *c_dsign_algo, *c_kagree_algo, *dh1, *challenge, *hash_c1; - EVP_PKEY *pdhkey = NULL; - AuthenticationAlgoKind_t dsignAlgoKind, kagreeAlgoKind; + HS_TOKEN_REQ, + HS_TOKEN_REPLY, + HS_TOKEN_FINAL +}; - assert(relation); +static DDS_Security_ValidationResult_t set_exception (DDS_Security_SecurityException *ex, const char *fmt, ...) + ddsrt_attribute_format ((printf, 2, 3)) ddsrt_attribute_warn_unused_result; - if (!token->class_id || strncmp(AUTH_HANDSHAKE_REQUEST_TOKEN_ID, token->class_id, strlen(AUTH_HANDSHAKE_REQUEST_TOKEN_ID)) != 0) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken incorrect class_id: %s (expected %s)", token->class_id ? token->class_id : "NULL", AUTH_HANDSHAKE_REQUEST_TOKEN_ID); - goto err_inv_class_id; - } - - /* Check presents of mandatory properties: c.i, c.perm, c.pdata, c.dsign_algo, c.kagree_algo, dh1, challenge1 */ - c_id = DDS_Security_DataHolder_find_binary_property(token, "c.id"); - if (!c_id || c_id->value._length == 0 || c_id->value._buffer == NULL) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property c.id missing"); - goto err_no_c_id; - } - - if (load_X509_certificate_from_data((char *)c_id->value._buffer, (int)c_id->value._length, &identityCert, ex) != DDS_SECURITY_VALIDATION_OK) - goto err_identity_cert_load; - - { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - if (trusted_ca_list->length == 0) - result = verify_certificate(identityCert, relation->localIdentity->identityCA, ex); - else - { - DDS_Security_Exception_clean(ex); - for (unsigned i = 0; i < trusted_ca_list->length; ++i) - { - DDS_Security_Exception_reset(ex); - if ((result = verify_certificate(identityCert, trusted_ca_list->buffer[i], ex)) == DDS_SECURITY_VALIDATION_OK) - break; - } - } - if (result != DDS_SECURITY_VALIDATION_OK) - goto err_inv_identity_cert; - } - - if (check_certificate_expiry(identityCert, ex) != DDS_SECURITY_VALIDATION_OK) - goto err_inv_identity_cert; - - if (!(c_perm = DDS_Security_DataHolder_find_binary_property(token, "c.perm"))) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property c.perm missing"); - goto err_no_c_perm; - } - if (c_perm->value._length > 0) - { - ddsrt_free(relation->remoteIdentity->permissionsDocument); - relation->remoteIdentity->permissionsDocument = string_from_data(c_perm->value._buffer, c_perm->value._length); - } - - if (!(c_pdata = DDS_Security_DataHolder_find_binary_property(token, "c.pdata"))) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property c.pdata missing"); - goto err_no_c_pdata; - } - if (validate_pdata(&c_pdata->value, identityCert, ex) != DDS_SECURITY_VALIDATION_OK) - goto err_inv_pdata; - - if (!(c_dsign_algo = DDS_Security_DataHolder_find_binary_property(token, "c.dsign_algo"))) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property c.dsign_algo missing"); - goto err_no_c_dsign_algo; - } - - if ((dsignAlgoKind = get_dsign_algo_from_string((const char *)c_dsign_algo->value._buffer)) == AUTH_ALGO_KIND_UNKNOWN) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property c.dsign_algo not supported"); - goto err_no_c_dsign_algo; - } - - if (!(c_kagree_algo = DDS_Security_DataHolder_find_binary_property(token, "c.kagree_algo"))) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property c.kagree_algo missing"); - goto err_no_c_kagree_algo; - } - - if ((kagreeAlgoKind = get_kagree_algo_from_string((const char *)c_kagree_algo->value._buffer)) == AUTH_ALGO_KIND_UNKNOWN) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property c.kagree_algo not support"); - goto err_no_c_kagree_algo; - } - - dh1 = DDS_Security_DataHolder_find_binary_property(token, "dh1"); - if (!dh1 || dh1->value._length == 0 || dh1->value._buffer == NULL) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property dh1 missing"); - goto err_no_dh; - } - if (dh_oct_to_public_key(&pdhkey, kagreeAlgoKind, dh1->value._buffer, dh1->value._length, ex) != DDS_SECURITY_VALIDATION_OK) - goto err_no_dh; - - if (!(challenge = DDS_Security_DataHolder_find_binary_property(token, "challenge1"))) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property challenge1 missing"); - goto err_no_challenge; - } - if (challenge->value._length != sizeof(AuthenticationChallenge) || challenge->value._buffer == NULL) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property challenge1 invalid"); - goto err_no_challenge; - } - - /* When validate_remote_identity was provided with a remote_auth_request_token then the future_challenge in the remote identity was set and the challenge1 - property of the handshake_request_token should be the same as the future_challenge stored in the remote identity. */ - if (relation->rchallenge) - { - if (memcmp(relation->rchallenge->value, challenge->value._buffer, sizeof(AuthenticationChallenge)) != 0) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property challenge1 does not match future_challenge"); - goto err_no_challenge; - } - } - else - { - if (challenge->value._length == sizeof(relation->rchallenge->value)) - { - relation->rchallenge = ddsrt_malloc(sizeof(AuthenticationChallenge)); - memcpy(relation->rchallenge, challenge->value._buffer, challenge->value._length); - } - else - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property challenge1 invalid (incorrect size)"); - goto err_no_challenge; - } - } - - { - const DDS_Security_BinaryProperty_t *binary_properties[] = { c_id, c_perm, c_pdata, c_dsign_algo, c_kagree_algo }; - (void)compute_hash_value(&handshake->hash_c1[0], binary_properties, 5, NULL); - } - if ((hash_c1 = DDS_Security_DataHolder_find_binary_property(token, "hash_c1"))) - { - if (hash_c1->value._length != sizeof(HashValue_t) || memcmp(hash_c1->value._buffer, &handshake->hash_c1, sizeof(HashValue_t)) != 0) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property hash_c1 invalid (incorrect size)"); - goto err_inv_hash_c1; - } - } - - if (relation->remoteIdentity->identityCert) - X509_free(relation->remoteIdentity->identityCert); - relation->remoteIdentity->identityCert = identityCert; - relation->remoteIdentity->dsignAlgoKind = dsignAlgoKind; - relation->remoteIdentity->kagreeAlgoKind = kagreeAlgoKind; - DDS_Security_OctetSeq_copy(&relation->remoteIdentity->pdata, &c_pdata->value); - handshake->rdh = pdhkey; - return DDS_SECURITY_VALIDATION_OK; - -err_inv_hash_c1: -err_no_challenge: - EVP_PKEY_free(pdhkey); -err_no_dh: -err_no_c_kagree_algo: -err_no_c_dsign_algo: -err_inv_pdata: -err_no_c_pdata: -err_no_c_perm: -err_inv_identity_cert: - X509_free(identityCert); -err_identity_cert_load: -err_no_c_id: -err_inv_class_id: +static DDS_Security_ValidationResult_t set_exception (DDS_Security_SecurityException *ex, const char *fmt, ...) +{ + va_list ap; + va_start (ap, fmt); + DDS_Security_Exception_vset (ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, fmt, ap); + va_end (ap); return DDS_SECURITY_VALIDATION_FAILED; } -static DDS_Security_ValidationResult_t validate_handshake_reply_token(const DDS_Security_HandshakeMessageToken *token, HandshakeInfo *handshake, EVP_PKEY **pdhkey, X509Seq *trusted_ca_list, DDS_Security_SecurityException *ex) +static const DDS_Security_BinaryProperty_t *find_required_binprop (const DDS_Security_HandshakeMessageToken *token, const char *name, DDS_Security_SecurityException *ex) { - IdentityRelation *relation = handshake->relation; - X509 *identityCert; - EVP_PKEY *public_key; - const DDS_Security_BinaryProperty_t *c_id, *c_perm, *c_pdata, *c_dsign_algo, *c_kagree_algo, *dh1, *dh2, *hash_c1, *hash_c2, *challenge1, *challenge2, *signature; - AuthenticationAlgoKind_t dsignAlgoKind, kagreeAlgoKind; - - assert(relation); - - if (!token->class_id || strncmp(AUTH_HANDSHAKE_REPLY_TOKEN_ID, token->class_id, strlen(AUTH_HANDSHAKE_REPLY_TOKEN_ID)) != 0) + DDS_Security_ValidationResult_t result; + const DDS_Security_BinaryProperty_t *prop = DDS_Security_DataHolder_find_binary_property (token, name); + if (prop == NULL) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken incorrect class_id: %s (expected %s)", token->class_id ? token->class_id : "NULL", AUTH_HANDSHAKE_REPLY_TOKEN_ID); - goto err_inv_class_id; + result = set_exception (ex, "process_handshake: HandshakeMessageToken property %s missing", name); + (void) result; + return NULL; } - - /* Check presents of mandatory properties: c.id, c.perm, c.pdata, c.dsign_algo, c.kagree_algo, challenge1, dh2, challenge2, signature */ - c_id = DDS_Security_DataHolder_find_binary_property(token, "c.id"); - if (!c_id || (c_id->value._length == 0) || (c_id->value._buffer == NULL)) + else if (prop->value._length > INT_MAX) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property c.id missing"); - goto err_no_c_id; + result = set_exception (ex, "process_handshake: HandshakeMessageToken property %s has unsupported size (%"PRIu32" bytes)", name, prop->value._length); + (void) result; + return NULL; } - - /* Verify Identity Certificate */ - if (load_X509_certificate_from_data((char *)c_id->value._buffer, (int)c_id->value._length, &identityCert, ex) != DDS_SECURITY_VALIDATION_OK) - goto err_identity_cert_load; - - { - DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_OK; - if (trusted_ca_list->length == 0) - result = verify_certificate(identityCert, relation->localIdentity->identityCA, ex); - else - { - DDS_Security_Exception_clean(ex); - for (unsigned i = 0; i < trusted_ca_list->length; ++i) - { - DDS_Security_Exception_reset(ex); - result = verify_certificate(identityCert, trusted_ca_list->buffer[i], ex); - if (result == DDS_SECURITY_VALIDATION_OK) - break; - } - } - if (result != DDS_SECURITY_VALIDATION_OK) - goto err_inv_identity_cert; - } - - if (check_certificate_expiry(identityCert, ex) != DDS_SECURITY_VALIDATION_OK) - goto err_inv_identity_cert; - - if (!(c_perm = DDS_Security_DataHolder_find_binary_property(token, "c.perm"))) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property c.perm missing"); - goto err_no_c_perm; - } - if (c_perm->value._length > 0) - { - ddsrt_free(relation->remoteIdentity->permissionsDocument); - relation->remoteIdentity->permissionsDocument = string_from_data(c_perm->value._buffer, c_perm->value._length); - } - - if (!(c_pdata = DDS_Security_DataHolder_find_binary_property(token, "c.pdata"))) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property c.pdata missing"); - goto err_no_c_pdata; - } - if (validate_pdata(&c_pdata->value, identityCert, ex) != DDS_SECURITY_VALIDATION_OK) - goto err_inv_pdata; - - if (!(c_dsign_algo = DDS_Security_DataHolder_find_binary_property(token, "c.dsign_algo"))) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property c.dsign_algo missing"); - goto err_no_c_dsign_algo; - } - - if ((dsignAlgoKind = get_dsign_algo_from_string((const char *)c_dsign_algo->value._buffer)) == AUTH_ALGO_KIND_UNKNOWN) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property c.dsign_algo not supported"); - goto err_no_c_dsign_algo; - } - - if (!(c_kagree_algo = DDS_Security_DataHolder_find_binary_property(token, "c.kagree_algo"))) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property c.kagree_algo missing"); - goto err_no_c_kagree_algo; - } - - if ((kagreeAlgoKind = get_kagree_algo_from_string((const char *)c_kagree_algo->value._buffer)) == AUTH_ALGO_KIND_UNKNOWN) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property c.kagree_algo not support"); - goto err_no_c_kagree_algo; - } - - /* dh1 is optional */ - dh1 = DDS_Security_DataHolder_find_binary_property(token, "dh1"); - DDSRT_UNUSED_ARG(dh1); - - dh2 = DDS_Security_DataHolder_find_binary_property(token, "dh2"); - if (!dh2 || dh2->value._length == 0 || dh2->value._buffer == NULL) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property dh2 missing"); - goto err_no_dh; - } - - if ((hash_c1 = DDS_Security_DataHolder_find_binary_property(token, "hash_c1"))) - { - if (hash_c1->value._length != sizeof(HashValue_t) || memcmp(hash_c1->value._buffer, handshake->hash_c1, sizeof(HashValue_t)) != 0) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property hash_c1 invalid"); - goto err_inv_hash_c1; - } - } - - { - const DDS_Security_BinaryProperty_t *binary_properties[] = { c_id, c_perm, c_pdata, c_dsign_algo, c_kagree_algo }; - (void)compute_hash_value(&handshake->hash_c2[0], binary_properties, 5, NULL); - } - - if ((hash_c2 = DDS_Security_DataHolder_find_binary_property(token, "hash_c2"))) - { - if (hash_c2->value._length != sizeof(HashValue_t) || memcmp(hash_c2->value._buffer, handshake->hash_c2, sizeof(HashValue_t)) != 0) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property hash_c2 invalid"); - goto err_inv_hash_c2; - } - } - - signature = DDS_Security_DataHolder_find_binary_property(token, "signature"); - if (!signature || signature->value._length == 0 || signature->value._buffer == NULL) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property signature missing"); - goto err_no_signature; - } - - *pdhkey = NULL; - if (dh_oct_to_public_key(pdhkey, kagreeAlgoKind, dh2->value._buffer, dh2->value._length, ex) != DDS_SECURITY_VALIDATION_OK) - goto err_inv_dh; - - if (!(challenge1 = DDS_Security_DataHolder_find_binary_property(token, "challenge1"))) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge1 missing"); - goto err_no_challenge; - } - if (challenge1->value._length != sizeof(AuthenticationChallenge) || challenge1->value._buffer == NULL) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge1 invalid"); - goto err_no_challenge; - } - - if (!(challenge2 = DDS_Security_DataHolder_find_binary_property(token, "challenge2"))) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge2 missing"); - goto err_no_challenge; - } - if (challenge2->value._length != sizeof(AuthenticationChallenge) || challenge2->value._buffer == NULL) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge2 invalid"); - goto err_no_challenge; - } - - /* When validate_remote_identity was provided with a remote_auth_request_token then the future_challenge in the remote identity was set and the challenge2 - property of the handshake_reply_token should be the same as the future_challenge stored in the remote identity. */ - if (relation->rchallenge) - { - if (memcmp(relation->rchallenge->value, challenge2->value._buffer, sizeof(AuthenticationChallenge)) != 0) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge2 does not match future_challenge"); - goto err_no_challenge; - } - } - else - { - if (challenge2->value._length == sizeof(relation->rchallenge->value)) - { - relation->rchallenge = ddsrt_malloc(sizeof(AuthenticationChallenge)); - memcpy(relation->rchallenge, challenge2->value._buffer, challenge2->value._length); - } - else - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge2 invalid (incorrect size)"); - goto err_no_challenge; - } - } - - if (relation->lchallenge) - { - if (memcmp(relation->lchallenge->value, challenge1->value._buffer, sizeof(AuthenticationChallenge)) != 0) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge1 does not match future_challenge"); - goto err_no_challenge; - } - } - else - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: No future challenge exists for this token"); - goto err_no_challenge; - } - - /* TODO: check if an identity certificate was already associated with the remote identity and when that is the case both should be the same */ - if (relation->remoteIdentity->identityCert) - X509_free(relation->remoteIdentity->identityCert); - relation->remoteIdentity->identityCert = identityCert; - relation->remoteIdentity->dsignAlgoKind = dsignAlgoKind; - relation->remoteIdentity->kagreeAlgoKind = kagreeAlgoKind; - - if ((public_key = X509_get_pubkey(relation->remoteIdentity->identityCert))) - { - DDS_Security_BinaryProperty_t *hash_c1_val = hash_value_to_binary_property("hash_c1", handshake->hash_c1); - DDS_Security_BinaryProperty_t *hash_c2_val = hash_value_to_binary_property("hash_c2", handshake->hash_c2); - const DDS_Security_BinaryProperty_t *properties[HANDSHAKE_SIGNATURE_CONTENT_SIZE] = { hash_c2_val, challenge2, dh2, challenge1, dh1, hash_c1_val }; - DDS_Security_ValidationResult_t result = validate_signature(public_key, properties, HANDSHAKE_SIGNATURE_CONTENT_SIZE, signature->value._buffer, signature->value._length, ex); - EVP_PKEY_free(public_key); - DDS_Security_BinaryProperty_free(hash_c1_val); - DDS_Security_BinaryProperty_free(hash_c2_val); - if (result != DDS_SECURITY_VALIDATION_OK) - goto err_inv_signature; - } - else - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "X509_get_pubkey failed"); - goto err_inv_signature; - } - - DDS_Security_OctetSeq_copy(&relation->remoteIdentity->pdata, &c_pdata->value); - return DDS_SECURITY_VALIDATION_OK; - -err_inv_signature: -err_no_challenge: -err_inv_dh: - EVP_PKEY_free(*pdhkey); -err_no_signature: -err_inv_hash_c2: -err_inv_hash_c1: -err_no_dh: -err_no_c_kagree_algo: -err_no_c_dsign_algo: -err_inv_pdata: -err_no_c_pdata: -err_no_c_perm: -err_inv_identity_cert: - X509_free(identityCert); -err_identity_cert_load: -err_no_c_id: -err_inv_class_id: - return DDS_SECURITY_VALIDATION_FAILED; + return prop; } -static DDS_Security_ValidationResult_t validate_handshake_final_token(const DDS_Security_HandshakeMessageToken *token, HandshakeInfo *handshake, DDS_Security_SecurityException *ex) +static const DDS_Security_BinaryProperty_t *find_required_nonempty_binprop (const DDS_Security_HandshakeMessageToken *token, const char *name, DDS_Security_SecurityException *ex) { - IdentityRelation *relation = handshake->relation; - const DDS_Security_BinaryProperty_t *dh1, *dh2, *hash_c1, *hash_c2, *challenge1, *challenge2, *signature; - EVP_PKEY *public_key; - - assert(relation); - - if (!token->class_id || strncmp(AUTH_HANDSHAKE_FINAL_TOKEN_ID, token->class_id, strlen(AUTH_HANDSHAKE_FINAL_TOKEN_ID)) != 0) + DDS_Security_ValidationResult_t result; + const DDS_Security_BinaryProperty_t *prop = find_required_binprop (token, name, ex); + if (prop != NULL && (prop->value._length == 0 || prop->value._buffer == NULL)) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken incorrect class_id: %s (expected %s)", token->class_id ? token->class_id : "NULL", AUTH_HANDSHAKE_FINAL_TOKEN_ID); - goto failed; + // FIXME: _buffer == NULL check must go, that should've been guaranteed before + result = set_exception (ex, "process_handshake: HandshakeMessageToken property %s is empty", name); + (void) result; + return NULL; } + return prop; +} - /* Check presents of mandatory properties: challenge1, challenge2, signature */ - - /* dh1 and dh2 are optional */ - dh1 = DDS_Security_DataHolder_find_binary_property(token, "dh1"); - DDSRT_UNUSED_ARG(dh1); - dh2 = DDS_Security_DataHolder_find_binary_property(token, "dh2"); - DDSRT_UNUSED_ARG(dh2); - - /* hash_c1 is optional */ - if ((hash_c1 = DDS_Security_DataHolder_find_binary_property(token, "hash_c1"))) +static const DDS_Security_BinaryProperty_t *find_required_binprop_exactsize (const DDS_Security_HandshakeMessageToken *token, const char *name, size_t size, DDS_Security_SecurityException *ex) +{ + DDS_Security_ValidationResult_t result; + const DDS_Security_BinaryProperty_t *prop = find_required_binprop (token, name, ex); + if (prop != NULL && prop->value._length != size) { - if (hash_c1->value._length != sizeof(HashValue_t) || memcmp(hash_c1->value._buffer, handshake->hash_c1, sizeof(HashValue_t)) != 0) + result = set_exception (ex, "process_handshake: HandshakeMessageToken property %s has wrong size (%"PRIu32" while expecting %"PRIuSIZE")", name, prop->value._length, size); + (void) result; + return NULL; + } + return prop; +} + +static X509 *load_X509_certificate_from_binprop (const DDS_Security_BinaryProperty_t *prop, X509 *own_ca, const X509Seq *trusted_ca_list, DDS_Security_SecurityException *ex) +{ + X509 *cert; + + if (load_X509_certificate_from_data ((char *) prop->value._buffer, (int) prop->value._length, &cert, ex) != DDS_SECURITY_VALIDATION_OK) + return NULL; + + DDS_Security_ValidationResult_t result = DDS_SECURITY_VALIDATION_FAILED; + if (trusted_ca_list->length == 0) + result = verify_certificate (cert, own_ca, ex); + else + { + DDS_Security_Exception_clean (ex); + for (unsigned i = 0; i < trusted_ca_list->length; ++i) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property hash_c1 invalid"); - goto failed; + DDS_Security_Exception_reset (ex); + if ((result = verify_certificate (cert, trusted_ca_list->buffer[i], ex)) == DDS_SECURITY_VALIDATION_OK) + break; } } - - /* hash_c2 is optional */ - if ((hash_c2 = DDS_Security_DataHolder_find_binary_property(token, "hash_c2"))) + if (result != DDS_SECURITY_VALIDATION_OK || check_certificate_expiry (cert, ex) != DDS_SECURITY_VALIDATION_OK) { - if (hash_c2->value._length != sizeof(HashValue_t) || memcmp(hash_c2->value._buffer, handshake->hash_c2, sizeof(HashValue_t)) != 0) + X509_free (cert); + return NULL; + } + return cert; +} + +static DDS_Security_ValidationResult_t validate_handshake_token_impl (const DDS_Security_HandshakeMessageToken *token, enum handshake_token_type token_type, + HandshakeInfo *handshake, EVP_PKEY **pdhkey_reply, X509Seq *trusted_ca_list, EVP_PKEY **pdhkey_req, X509 **identityCert, DDS_Security_SecurityException *ex) +{ + IdentityRelation * const relation = handshake->relation; + const DDS_Security_BinaryProperty_t *c_pdata = NULL; + AuthenticationAlgoKind_t dsignAlgoKind = AUTH_ALGO_KIND_UNKNOWN, kagreeAlgoKind = AUTH_ALGO_KIND_UNKNOWN; + const DDS_Security_BinaryProperty_t *dh1 = NULL, *dh2 = NULL; + const DDS_Security_BinaryProperty_t *hash_c1 = NULL, *hash_c2 = NULL; + const DDS_Security_BinaryProperty_t *challenge1 = NULL, *challenge2 = NULL; + const DDS_Security_BinaryProperty_t *signature = NULL; + const char *token_class_id = NULL; + + assert (relation); + assert (pdhkey_req == NULL || *pdhkey_req == NULL); + assert (pdhkey_reply == NULL || *pdhkey_reply == NULL); + assert (pdhkey_req == NULL || token_type == HS_TOKEN_REQ); + assert (pdhkey_reply == NULL || token_type == HS_TOKEN_REPLY); + + switch (token_type) + { + case HS_TOKEN_REQ: token_class_id = AUTH_HANDSHAKE_REQUEST_TOKEN_ID; break; + case HS_TOKEN_REPLY: token_class_id = AUTH_HANDSHAKE_REPLY_TOKEN_ID; break; + case HS_TOKEN_FINAL: token_class_id = AUTH_HANDSHAKE_FINAL_TOKEN_ID; break; + } + assert (token_class_id); + + if (!token->class_id || strncmp (token_class_id, token->class_id, strlen (token_class_id)) != 0) + return set_exception (ex, "process_handshake: HandshakeMessageToken incorrect class_id: %s (expected %s)", token->class_id ? token->class_id : "NULL", token_class_id); + + if (token_type == HS_TOKEN_REQ || token_type == HS_TOKEN_REPLY) + { + const DDS_Security_BinaryProperty_t *c_id, *c_perm, *c_dsign_algo, *c_kagree_algo; + + if ((c_id = find_required_nonempty_binprop (token, "c.id", ex)) == NULL) + return DDS_SECURITY_VALIDATION_FAILED; + if ((*identityCert = load_X509_certificate_from_binprop (c_id, relation->localIdentity->identityCA, trusted_ca_list, ex)) == NULL) + return DDS_SECURITY_VALIDATION_FAILED; + + if ((c_perm = find_required_binprop (token, "c.perm", ex)) == NULL) + return DDS_SECURITY_VALIDATION_FAILED; + if (c_perm->value._length > 0) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "begin_handshake_reply: HandshakeMessageToken property hash_c2 invalid"); - goto failed; + ddsrt_free (relation->remoteIdentity->permissionsDocument); + relation->remoteIdentity->permissionsDocument = string_from_data (c_perm->value._buffer, c_perm->value._length); } + + if ((c_pdata = find_required_binprop (token, "c.pdata", ex)) == NULL) + return DDS_SECURITY_VALIDATION_FAILED; + if (validate_pdata (&c_pdata->value, *identityCert, ex) != DDS_SECURITY_VALIDATION_OK) + return DDS_SECURITY_VALIDATION_FAILED; + + if ((c_dsign_algo = find_required_nonempty_binprop (token, "c.dsign_algo", ex)) == NULL) + return DDS_SECURITY_VALIDATION_FAILED; + if ((dsignAlgoKind = get_dsign_algo_from_string ((const char *) c_dsign_algo->value._buffer)) == AUTH_ALGO_KIND_UNKNOWN) + return set_exception (ex, "process_handshake: HandshakeMessageToken property c.dsign_algo not supported"); + + if ((c_kagree_algo = find_required_nonempty_binprop (token, "c.kagree_algo", ex)) == NULL) + return DDS_SECURITY_VALIDATION_FAILED; + if ((kagreeAlgoKind = get_kagree_algo_from_string ((const char *) c_kagree_algo->value._buffer)) == AUTH_ALGO_KIND_UNKNOWN) + return set_exception (ex, "process_handshake: HandshakeMessageToken property c.kagree_algo not supported"); + + /* calculate the hash value and set in handshake hash_c1 (req) or hash_c2 (reply) */ + const DDS_Security_BinaryProperty_t *binary_properties[] = { c_id, c_perm, c_pdata, c_dsign_algo, c_kagree_algo }; + (void) compute_hash_value ((token_type == HS_TOKEN_REQ) ? handshake->hash_c1 : handshake->hash_c2, binary_properties, 5, NULL); } - if (!(challenge1 = DDS_Security_DataHolder_find_binary_property(token, "challenge1"))) + if ((dh1 = find_required_nonempty_binprop (token, "dh1", ex)) == NULL) + return DDS_SECURITY_VALIDATION_FAILED; + if ((challenge1 = find_required_binprop_exactsize (token, "challenge1", sizeof (AuthenticationChallenge), ex)) == NULL) + return DDS_SECURITY_VALIDATION_FAILED; + if (token_type == HS_TOKEN_REQ) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge1 missing"); - goto failed; - } - if (challenge1->value._length != sizeof(AuthenticationChallenge) || challenge1->value._buffer == NULL) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge1 invalid"); - goto failed; + if (dh_oct_to_public_key (pdhkey_req, kagreeAlgoKind, dh1->value._buffer, dh1->value._length, ex) != DDS_SECURITY_VALIDATION_OK) + return DDS_SECURITY_VALIDATION_FAILED; } - if (!(challenge2 = DDS_Security_DataHolder_find_binary_property(token, "challenge2"))) + if (token_type == HS_TOKEN_REPLY || token_type == HS_TOKEN_FINAL) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge2 missing"); - goto failed; + if ((dh2 = find_required_nonempty_binprop (token, "dh2", ex)) == NULL) + return DDS_SECURITY_VALIDATION_FAILED; + if ((challenge2 = find_required_binprop_exactsize (token, "challenge2", sizeof (AuthenticationChallenge), ex)) == NULL) + return DDS_SECURITY_VALIDATION_FAILED; + if ((signature = find_required_nonempty_binprop (token, "signature", ex)) == NULL) + return DDS_SECURITY_VALIDATION_FAILED; } - if (challenge2->value._length != sizeof(AuthenticationChallenge) || challenge2->value._buffer == NULL) + if (token_type == HS_TOKEN_REPLY) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge2 invalid"); - goto failed; + if (dh_oct_to_public_key (pdhkey_reply, kagreeAlgoKind, dh2->value._buffer, dh2->value._length, ex) != DDS_SECURITY_VALIDATION_OK) + return DDS_SECURITY_VALIDATION_FAILED; } - /* When validate_remote_identity was provided with a remote_auth_request_token then the future_challenge in the remote identity was set and the challenge1 - property of the handshake_reply_token should be the same as the future_challenge stored in the remote identity. */ + /* When validate_remote_identity was provided with a remote_auth_request_token then the future_challenge in + the remote identity was set and the challenge(1|2) property of the handshake_(request|reply|final)_token + should be the same as the future_challenge stored in the remote identity. */ + const DDS_Security_BinaryProperty_t *rc = (token_type == HS_TOKEN_REPLY) ? challenge2 : challenge1; if (relation->rchallenge) { - if (memcmp(relation->rchallenge->value, challenge1->value._buffer, sizeof(AuthenticationChallenge)) != 0) + if (memcmp (relation->rchallenge->value, rc->value._buffer, sizeof (AuthenticationChallenge)) != 0) + return set_exception (ex, "process_handshake: HandshakeMessageToken property challenge%d does not match future_challenge", (token_type == HS_TOKEN_REPLY) ? 2 : 1); + } + else if (token_type != HS_TOKEN_FINAL) + { + relation->rchallenge = ddsrt_memdup (rc->value._buffer, sizeof (AuthenticationChallenge)); + } + + /* From DDS Security spec: inclusion of the hash_c1 property is optional. Its only purpose is to + facilitate troubleshoot interoperability problems. */ + if ((hash_c1 = DDS_Security_DataHolder_find_binary_property (token, "hash_c1"))) + { + /* hash_c1 should be set during req or reply token validation */ + assert (handshake->hash_c1 != NULL); + if (hash_c1->value._length != sizeof (HashValue_t) || memcmp (hash_c1->value._buffer, handshake->hash_c1, sizeof (HashValue_t)) != 0) + return set_exception (ex, "process_handshake: HandshakeMessageToken property hash_c1 invalid"); + } + + if (token_type == HS_TOKEN_REPLY || token_type == HS_TOKEN_FINAL) + { + /* hash_c2 should be set during reply token validation */ + assert (handshake->hash_c2 != NULL); + + /* From DDS Security spec: inclusion of the hash_c2 property is optional. Its only purpose is to + facilitate troubleshoot interoperability problems. */ + if ((hash_c2 = DDS_Security_DataHolder_find_binary_property (token, "hash_c2"))) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge1 does not match future_challenge"); - goto failed; + if (hash_c2->value._length != sizeof (HashValue_t) || memcmp (hash_c2->value._buffer, handshake->hash_c2, sizeof (HashValue_t)) != 0) + return set_exception (ex, "process_handshake: HandshakeMessageToken property hash_c2 invalid"); } - } - else - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: No challenge exists to check challenge1 in the token."); - goto failed; + if (relation->lchallenge == NULL) + return set_exception (ex, "process_handshake: No future challenge exists for this token"); + const DDS_Security_BinaryProperty_t *lc = (token_type == HS_TOKEN_REPLY) ? challenge1 : challenge2; + if (memcmp (relation->lchallenge->value, lc->value._buffer, sizeof (AuthenticationChallenge)) != 0) + return set_exception (ex, "process_handshake: HandshakeMessageToken property challenge1 does not match future_challenge"); } - if (relation->lchallenge) + if (token_type == HS_TOKEN_REQ) { - if (memcmp(relation->lchallenge->value, challenge2->value._buffer, sizeof(AuthenticationChallenge)) != 0) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property challenge2 does not match future_challenge"); - goto failed; - } - } - else - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: No challenge exists to check challenge2 in the token."); - goto failed; + if (!EVP_PKEY_up_ref (*pdhkey_req)) + return set_exception (ex, "process_handshake: failed to increment refcount of DH key"); + handshake->rdh = *pdhkey_req; } - if (!(signature = DDS_Security_DataHolder_find_binary_property(token, "signature"))) + if (token_type == HS_TOKEN_REQ || token_type == HS_TOKEN_REPLY) { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "process_handshake: HandshakeMessageToken property signature missing"); - goto failed; + assert (*identityCert != NULL); + assert (dsignAlgoKind != AUTH_ALGO_KIND_UNKNOWN); + assert (kagreeAlgoKind != AUTH_ALGO_KIND_UNKNOWN); + assert (c_pdata != NULL); + + /* TODO: check if an identity certificate was already associated with the remote identity and when that is the case both should be the same */ + if (relation->remoteIdentity->identityCert) + X509_free (relation->remoteIdentity->identityCert); + if (!X509_up_ref (*identityCert)) + return set_exception (ex, "process_handshake: failed to increment refcount of identity certificate"); + relation->remoteIdentity->identityCert = *identityCert; + relation->remoteIdentity->dsignAlgoKind = dsignAlgoKind; + relation->remoteIdentity->kagreeAlgoKind = kagreeAlgoKind; + DDS_Security_OctetSeq_copy (&relation->remoteIdentity->pdata, &c_pdata->value); } - /* Validate signature */ - if ((public_key = X509_get_pubkey(relation->remoteIdentity->identityCert))) + if (token_type == HS_TOKEN_REPLY || token_type == HS_TOKEN_FINAL) { - DDS_Security_BinaryProperty_t *hash_c1_val = hash_value_to_binary_property("hash_c1", handshake->hash_c1); - DDS_Security_BinaryProperty_t *hash_c2_val = hash_value_to_binary_property("hash_c2", handshake->hash_c2); - const DDS_Security_BinaryProperty_t *properties[HANDSHAKE_SIGNATURE_CONTENT_SIZE] = { hash_c1_val, challenge1, dh1, challenge2, dh2, hash_c2_val }; - DDS_Security_ValidationResult_t result = validate_signature(public_key, properties, HANDSHAKE_SIGNATURE_CONTENT_SIZE, signature->value._buffer, signature->value._length, ex); - EVP_PKEY_free(public_key); - DDS_Security_BinaryProperty_free(hash_c1_val); - DDS_Security_BinaryProperty_free(hash_c2_val); + EVP_PKEY *public_key; + if ((public_key = X509_get_pubkey (relation->remoteIdentity->identityCert)) == NULL) + return set_exception (ex, "X509_get_pubkey failed"); + + DDS_Security_BinaryProperty_t hash_c1_val = { + .name = "hash_c1", .value = { ._length = sizeof (handshake->hash_c1), ._buffer = handshake->hash_c1 } + }; + DDS_Security_BinaryProperty_t hash_c2_val = { + .name = "hash_c2", .value = { ._length = sizeof (handshake->hash_c2), ._buffer = handshake->hash_c2 } + }; + const DDS_Security_BinaryProperty_t **properties; + if (token_type == HS_TOKEN_REPLY) + properties = (const DDS_Security_BinaryProperty_t *[]) { &hash_c2_val, challenge2, dh2, challenge1, dh1, &hash_c1_val }; + else + properties = (const DDS_Security_BinaryProperty_t *[]) { &hash_c1_val, challenge1, dh1, challenge2, dh2, &hash_c2_val }; + const DDS_Security_ValidationResult_t result = validate_signature (public_key, properties, 6, signature->value._buffer, signature->value._length, ex); + EVP_PKEY_free (public_key); if (result != DDS_SECURITY_VALIDATION_OK) - goto failed; + return result; } - else - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "X509_get_pubkey failed"); - goto failed; - } - return DDS_SECURITY_VALIDATION_OK; -failed: - return DDS_SECURITY_VALIDATION_FAILED; + return DDS_SECURITY_VALIDATION_OK; +} + +static DDS_Security_ValidationResult_t validate_handshake_token(const DDS_Security_HandshakeMessageToken *token, enum handshake_token_type token_type, HandshakeInfo *handshake, + EVP_PKEY **pdhkey_reply, X509Seq *trusted_ca_list, DDS_Security_SecurityException *ex) +{ + X509 *identityCert = NULL; + EVP_PKEY *pdhkey_req = NULL; + + const DDS_Security_ValidationResult_t ret = validate_handshake_token_impl (token, token_type, handshake, pdhkey_reply, trusted_ca_list, + (token_type == HS_TOKEN_REQ) ? &pdhkey_req : NULL, &identityCert, ex); + + if (ret != DDS_SECURITY_VALIDATION_OK) + { + IdentityRelation *relation = handshake->relation; + if (relation->remoteIdentity->identityCert) + { + X509_free (relation->remoteIdentity->identityCert); + relation->remoteIdentity->identityCert = NULL; + } + if (pdhkey_reply && *pdhkey_reply) + EVP_PKEY_free (*pdhkey_reply); + } + + if (pdhkey_req) + EVP_PKEY_free (pdhkey_req); + if (identityCert) + { + /* free id cert also when validation succeeded, because the refcount was increased + when assigning this cert to relation->remoteIdentity */ + X509_free (identityCert); + } + return ret; } DDS_Security_ValidationResult_t begin_handshake_reply(dds_security_authentication *instance, DDS_Security_HandshakeHandle *handshake_handle, @@ -1892,7 +1644,7 @@ DDS_Security_ValidationResult_t begin_handshake_reply(dds_security_authenticatio assert(relation); } - if (validate_handshake_request_token(handshake_message_in, handshake, &(impl->trustedCAList), ex) != DDS_SECURITY_VALIDATION_OK) + if (validate_handshake_token(handshake_message_in, HS_TOKEN_REQ, handshake, NULL, &(impl->trustedCAList), ex) != DDS_SECURITY_VALIDATION_OK) goto err_inv_token; if (get_certificate_contents(localIdent->identityCert, &certData, &certDataSize, ex) != DDS_SECURITY_VALIDATION_OK) goto err_alloc_cid; @@ -1937,7 +1689,7 @@ DDS_Security_ValidationResult_t begin_handshake_reply(dds_security_authenticatio DDS_Security_BinaryProperty_set_by_string(c_dsign_algo, "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); DDS_Security_BinaryProperty_set_by_string(c_kagree_algo, "c.kagree_algo", get_kagree_algo(remoteIdent->kagreeAlgoKind)); - /* Calculate the hash_c2 */ + /* Todo: including hash_c2 is optional (conform spec); add a configuration option to leave it out */ { DDS_Security_BinaryPropertySeq bseq = { ._length = 5, ._buffer = tokens }; get_hash_binary_property_seq(&bseq, handshake->hash_c2); @@ -2099,7 +1851,7 @@ DDS_Security_ValidationResult_t process_handshake(dds_security_authentication *i case CREATEDREQUEST: /* The source of the handshake_handle is a begin_handshake_request function. So, handshake_message_in is from a remote begin_handshake_reply function */ /* Verify Message Token contents according to Spec 9.3.2.5.2 (Reply Message) */ - if (validate_handshake_reply_token(handshake_message_in, handshake, &dhkeyRemote, &(impl->trustedCAList), ex) != DDS_SECURITY_VALIDATION_OK) + if (validate_handshake_token(handshake_message_in, HS_TOKEN_REPLY, handshake, &dhkeyRemote, &(impl->trustedCAList), ex) != DDS_SECURITY_VALIDATION_OK) goto err_inv_token; handshake->rdh = dhkeyRemote; @@ -2168,7 +1920,7 @@ DDS_Security_ValidationResult_t process_handshake(dds_security_authentication *i case CREATEDREPLY: /* The source of the handshake_handle is a begin_handshake_reply function So, handshake_message_in is from a remote process_handshake function */ /* Verify Message Token contents according to Spec 9.3.2.5.3 (Final Message) */ - if (validate_handshake_final_token(handshake_message_in, handshake, ex) != DDS_SECURITY_VALIDATION_OK) + if (validate_handshake_token(handshake_message_in, HS_TOKEN_FINAL, handshake, NULL, NULL, ex) != DDS_SECURITY_VALIDATION_OK) goto err_inv_token; challenge2_ref_for_shared_secret = (DDS_Security_octet *)(handshake->relation->lchallenge); challenge1_ref_for_shared_secret = (DDS_Security_octet *)(handshake->relation->rchallenge); diff --git a/src/security/core/include/dds/security/core/dds_security_utils.h b/src/security/core/include/dds/security/core/dds_security_utils.h index c9cbf0e..c61829a 100644 --- a/src/security/core/include/dds/security/core/dds_security_utils.h +++ b/src/security/core/include/dds/security/core/dds_security_utils.h @@ -14,6 +14,7 @@ #define DSCMN_SECURITY_UTILS_H_ #include +#include #include #include #include "dds/export.h" @@ -261,6 +262,15 @@ DDS_EXPORT void DDS_Security_HandleSeq_deinit( DDS_Security_HandleSeq *seq); +DDS_EXPORT void +DDS_Security_Exception_vset( + DDS_Security_SecurityException *ex, + const char *context, + int code, + int minor_code, + const char *fmt, + va_list ap); + DDS_EXPORT void DDS_Security_Exception_set( DDS_Security_SecurityException *ex, @@ -268,7 +278,7 @@ DDS_Security_Exception_set( int code, int minor_code, const char *fmt, - ...); + ...); #ifdef DDSI_INCLUDE_SSL diff --git a/src/security/core/src/dds_security_utils.c b/src/security/core/src/dds_security_utils.c index 3c04c60..723a383 100644 --- a/src/security/core/src/dds_security_utils.c +++ b/src/security/core/src/dds_security_utils.c @@ -760,50 +760,49 @@ DDS_Security_HandleSeq_deinit( DDS_Security_HandleSeq_freebuf(seq); } - - - -void -DDS_Security_Exception_set( - DDS_Security_SecurityException *ex, - const char *context, - int code, - int minor_code, - const char *fmt, - ...) +void DDS_Security_Exception_vset (DDS_Security_SecurityException *ex, const char *context, int code, int minor_code, const char *fmt, va_list args1) { - int32_t ret; - size_t len; - char buf[1] = { '\0' }; - char *str = NULL; - va_list args1, args2; + int32_t ret; + size_t len; + char buf[1] = { '\0' }; + char *str = NULL; + va_list args2; - assert(context); - assert(fmt); - assert(ex); - DDSRT_UNUSED_ARG( context ); + assert(context); + assert(fmt); + assert(ex); + DDSRT_UNUSED_ARG( context ); - va_start(args1, fmt); - va_copy(args2, args1); + va_copy(args2, args1); - if ((ret = vsnprintf(buf, sizeof(buf), fmt, args1)) >= 0) { - len = (size_t)ret; /* +1 for null byte */ - if ((str = ddsrt_malloc(len + 1)) == NULL) { - assert(false); - } else if ((ret = vsnprintf(str, len + 1, fmt, args2)) >= 0) { - assert((size_t) ret == len); - } else { - ddsrt_free(str); - str = NULL; - } + if ((ret = vsnprintf(buf, sizeof(buf), fmt, args1)) >= 0) { + len = (size_t)ret; /* +1 for null byte */ + if ((str = ddsrt_malloc(len + 1)) == NULL) { + assert(false); + } else if ((ret = vsnprintf(str, len + 1, fmt, args2)) >= 0) { + assert((size_t) ret == len); + } else { + ddsrt_free(str); + str = NULL; } + } - va_end(args1); - va_end(args2); + va_end(args1); - ex->message = str; - ex->code = code; - ex->minor_code = minor_code; + ex->message = str; + ex->code = code; + ex->minor_code = minor_code; +} + +void DDS_Security_Exception_set (DDS_Security_SecurityException *ex, const char *context, int code, int minor_code, const char *fmt, ...) +{ + va_list args1; + assert(context); + assert(fmt); + assert(ex); + va_start(args1, fmt); + DDS_Security_Exception_vset (ex, context, code, minor_code, fmt, args1); + va_end(args1); } #ifdef DDSI_INCLUDE_SSL From cec8aea6c9b479b0428310dbf2b5fe14bee5855b Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 23 Mar 2020 08:13:51 +0100 Subject: [PATCH 130/238] Compound literals go out of scope, too Signed-off-by: Erik Boasson --- .../builtin_plugins/authentication/src/authentication.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index 951e07e..7e15f05 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -1536,12 +1536,13 @@ static DDS_Security_ValidationResult_t validate_handshake_token_impl (const DDS_ DDS_Security_BinaryProperty_t hash_c2_val = { .name = "hash_c2", .value = { ._length = sizeof (handshake->hash_c2), ._buffer = handshake->hash_c2 } }; - const DDS_Security_BinaryProperty_t **properties; + DDS_Security_ValidationResult_t result; if (token_type == HS_TOKEN_REPLY) - properties = (const DDS_Security_BinaryProperty_t *[]) { &hash_c2_val, challenge2, dh2, challenge1, dh1, &hash_c1_val }; + result = validate_signature (public_key, (const DDS_Security_BinaryProperty_t *[]) { + &hash_c2_val, challenge2, dh2, challenge1, dh1, &hash_c1_val }, 6, signature->value._buffer, signature->value._length, ex); else - properties = (const DDS_Security_BinaryProperty_t *[]) { &hash_c1_val, challenge1, dh1, challenge2, dh2, &hash_c2_val }; - const DDS_Security_ValidationResult_t result = validate_signature (public_key, properties, 6, signature->value._buffer, signature->value._length, ex); + result = validate_signature (public_key, (const DDS_Security_BinaryProperty_t *[]) { + &hash_c1_val, challenge1, dh1, challenge2, dh2, &hash_c2_val }, 6, signature->value._buffer, signature->value._length, ex); EVP_PKEY_free (public_key); if (result != DDS_SECURITY_VALIDATION_OK) return result; From bf23dee70af4756186855665b2845666f06913d2 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 24 Mar 2020 21:24:16 +0100 Subject: [PATCH 131/238] Fix in access control identity subject compare Fixed a bug in the subject compare function for identity subjects, that could cause using the incorrect permission grant in case multiple grants are provided in the permissions configuration of the access control plugin. Signed-off-by: Dennis Potman --- .../builtin_plugins/access_control/src/access_control_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/security/builtin_plugins/access_control/src/access_control_utils.c b/src/security/builtin_plugins/access_control/src/access_control_utils.c index 6c56d9e..ca80d77 100644 --- a/src/security/builtin_plugins/access_control/src/access_control_utils.c +++ b/src/security/builtin_plugins/access_control/src/access_control_utils.c @@ -282,7 +282,7 @@ bool ac_check_subjects_are_equal(const char *permissions_sn, const char *identit if (name_idsn == NULL || tok_idsn == NULL) goto check_subj_equal_failed; value_pmsn = DDS_Security_Property_get_value(&prop_pmsn, name_idsn); - if (value_pmsn == NULL || strcmp(value_pmsn, value_pmsn) != 0) + if (value_pmsn == NULL || strcmp(tok_idsn, value_pmsn) != 0) { ddsrt_free(value_pmsn); goto check_subj_equal_failed; From d03587fcea25d8d739f8ff81f6ad3c151dbc5ee2 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Wed, 25 Mar 2020 08:47:51 +0100 Subject: [PATCH 132/238] Add identity bob to default test permissions xml Signed-off-by: Dennis Potman --- .../tests/common/etc/default_permissions.p7s | 59 +++++++++++++++---- .../tests/common/etc/default_permissions.xml | 35 ++++++++++- 2 files changed, 80 insertions(+), 14 deletions(-) diff --git a/src/security/core/tests/common/etc/default_permissions.p7s b/src/security/core/tests/common/etc/default_permissions.p7s index 3417eac..ddc97bc 100644 --- a/src/security/core/tests/common/etc/default_permissions.p7s +++ b/src/security/core/tests/common/etc/default_permissions.p7s @@ -1,16 +1,16 @@ MIME-Version: 1.0 -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----024D6D35BD8D71C15552DF3E23F615BB" +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----A38CC2CF99C9B2ECE7711B9937B56A67" This is an S/MIME signed message -------024D6D35BD8D71C15552DF3E23F615BB +------A38CC2CF99C9B2ECE7711B9937B56A67 Content-Type: text/plain - + emailAddress=alice@cycloneddssecurity.adlinktech.com,CN=Alice Example,O=Example Organization,OU=Organizational Unit Name,L=Locality Name,ST=OV,C=NL @@ -43,10 +43,43 @@ Content-Type: text/plain DENY + + emailAddress=bob@cycloneddssecurity.adlinktech.com,CN=Bob Example,O=Example Organization,OU=Organizational Unit Name,L=Locality Name,ST=OV,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + * + + + + + * + + + * + + + + DENY + -------024D6D35BD8D71C15552DF3E23F615BB +------A38CC2CF99C9B2ECE7711B9937B56A67 Content-Type: application/x-pkcs7-signature; name="smime.p7s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="smime.p7s" @@ -82,16 +115,16 @@ DBdFeGFtcGxlIENBIE9yZ2FuaXphdGlvbjEfMB0GA1UEAwwWRXhhbXBsZSBQZXJt aXNzaW9ucyBDQTE6MDgGCSqGSIb3DQEJARYrYXV0aG9yaXR5QGN5Y2xvbmVkZHNz ZWN1cml0eS5hZGxpbmt0ZWNoLmNvbQIUfoby6818hlJQ+41KUHiM6BZll/0wDQYJ YIZIAWUDBAIBBQCggeQwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG -9w0BCQUxDxcNMjAwMjI3MTM1MDU2WjAvBgkqhkiG9w0BCQQxIgQgLVEvOwNNW9+x -+KKNuY51LjFOBF441MR89lv8fK5pDKMweQYJKoZIhvcNAQkPMWwwajALBglghkgB +9w0BCQUxDxcNMjAwMzI1MDczMTM5WjAvBgkqhkiG9w0BCQQxIgQg3FQPbVj9xFlc +/eoZaddhdX1BXlKZyENrbh7DcCwklVwweQYJKoZIhvcNAQkPMWwwajALBglghkgB ZQMEASowCwYJYIZIAWUDBAEWMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAOBggq hkiG9w0DAgICAIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwIC -ASgwDQYJKoZIhvcNAQEBBQAEggEAxDaQlT3KGO3Z69Dgh1JAnkR8fEW+SK/pRls0 -du8ZemKaeLAgwwS9rbMh+6YJqsYWrp1LWjxNI3oJqTp1RvcRzJJXF48nkP+Oe1jY -2KX9wx5LthmrT/573EvZHkXsx7mBu3Ar2etm4iE3lqkblEiynTNfy4XmJBNdB+u8 -cTzzm6J9372FK3iu5Od9yVDV33Ys/OHBI8GYcrK9RBKovkctr2fK+RJHaVqrDy3y -oE03GAaFr8brL2g9WlWRsE3nuRvPXppsz32kUWvHLUfEpGbq1K/9C137JSgVHNX2 -atfV404PDWdFqL/JMSdc8RIJTzY6I2Bwrg8z1912DkYD5KPuOA== +ASgwDQYJKoZIhvcNAQEBBQAEggEAWJxDp9TDqXKazAlIj9SZ8mQXhhGoTDeqZbxE +Bs561dHUmQVtA2S85TWGiCffKqWj3wlF5GwZNneYEV1deE3LZFa0o1+/VpeIBSGO +Qs1xKS7zx8IkGok3k88bh+eohDrgpzdLWkZeJ4P7J/3JmCMFdTXuCpuQYhRIrXO0 +pq4ueV2qGyCN6GZS2PC88GV0xeoS62Vj1Xze8omfgDI7KCPhKz6gJSEFUUqIzg7p +Zhqm15qorUoBVXcvMwaG95/xZVfcZzMbmJB/nhwd9KYu9ImkGj6ssSbgr3VR4OkQ +gQUib4aVQJQgBaWEPrgSjRkAp9rMB7R9IW6p2auMA/Gd/kbd7g== -------024D6D35BD8D71C15552DF3E23F615BB-- +------A38CC2CF99C9B2ECE7711B9937B56A67-- diff --git a/src/security/core/tests/common/etc/default_permissions.xml b/src/security/core/tests/common/etc/default_permissions.xml index 74e3c9f..5802a3e 100644 --- a/src/security/core/tests/common/etc/default_permissions.xml +++ b/src/security/core/tests/common/etc/default_permissions.xml @@ -2,7 +2,7 @@ - + emailAddress=alice@cycloneddssecurity.adlinktech.com,CN=Alice Example,O=Example Organization,OU=Organizational Unit Name,L=Locality Name,ST=OV,C=NL @@ -35,5 +35,38 @@ DENY + + emailAddress=bob@cycloneddssecurity.adlinktech.com,CN=Bob Example,O=Example Organization,OU=Organizational Unit Name,L=Locality Name,ST=OV,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + * + + + + + * + + + * + + + + DENY + From 4fe9cf290da8e4cbbd79c3c26078256fc5bf29c1 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 23 Mar 2020 17:26:18 +0100 Subject: [PATCH 133/238] Add DDS_HAS_PROPERTY_LIST_QOS feature test macro If set, dds_q{set,get}_{prop,bprop} are available. Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/ddsc/dds_public_qos.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/ddsc/include/dds/ddsc/dds_public_qos.h b/src/core/ddsc/include/dds/ddsc/dds_public_qos.h index 9ce40f0..4146960 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_qos.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_qos.h @@ -23,6 +23,11 @@ #include "dds/export.h" #include "dds/ddsc/dds_public_qosdefs.h" +/* Whether or not the "property list" QoS setting is supported in this version. If it is, + the "dds.sec." properties are treated specially, preventing the accidental creation of + an non-secure participant by an implementation built without support for DDS Security. */ +#define DDS_HAS_PROPERTY_LIST_QOS 1 + #if defined (__cplusplus) extern "C" { #endif From d4e9300dadb1d600aa639ee20a188439dc25a701 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 23 Mar 2020 17:27:29 +0100 Subject: [PATCH 134/238] Do not silently ignore security QoS settings When built without support for DDS Security, any attempt to create a participant QoS settings in the security name space (those prefixed by "dds.sec.") must fail. Signed-off-by: Erik Boasson --- src/core/ddsc/tests/config.c | 40 +++ .../ddsi/include/dds/ddsi/ddsi_security_omg.h | 9 +- src/core/ddsi/include/dds/ddsi/ddsi_xqos.h | 4 +- src/core/ddsi/src/ddsi_plist.c | 26 +- src/core/ddsi/src/ddsi_security_omg.c | 12 +- src/core/ddsi/src/q_entity.c | 291 +++++++++--------- 6 files changed, 226 insertions(+), 156 deletions(-) diff --git a/src/core/ddsc/tests/config.c b/src/core/ddsc/tests/config.c index 546062a..159a4ac 100644 --- a/src/core/ddsc/tests/config.c +++ b/src/core/ddsc/tests/config.c @@ -141,3 +141,43 @@ CU_Test(ddsc_security_config, empty, .init = ddsrt_init, .fini = ddsrt_fini) CU_ASSERT_FATAL(found == 0x7); #endif } + +CU_Test(ddsc_security_qos, empty, .init = ddsrt_init, .fini = ddsrt_fini) +{ + /* Expected traces when creating participant with some (not all) security QoS + settings. We need to test this one here to be sure that it also refuses to + start when security is configured but the implementation doesn't include + support for it. */ + const char *log_expected[] = { +#ifdef DDSI_INCLUDE_SECURITY + "new_participant(*): using security settings from QoS*", + "new_participant(*): required security property * missing*", +#endif + NULL + }; + + /* Set up the trace sinks to detect the config parsing. */ + dds_set_log_mask (DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG); + dds_set_log_sink (&logger, (void *) log_expected); + dds_set_trace_sink (&logger, (void *) log_expected); + + /* Create participant with incomplete/nonsensical security configuration: this should always fail */ + found = 0; + dds_qos_t *qos = dds_create_qos (); + dds_qset_prop (qos, "dds.sec.nonsense", ""); + dds_entity_t domain = dds_create_domain (0, "trace"); + CU_ASSERT_FATAL (domain > 0); + dds_entity_t participant = dds_create_participant (0, qos, NULL); + dds_delete_qos (qos); + CU_ASSERT_FATAL (participant < 0); + (void) dds_delete (domain); + dds_set_log_sink (NULL, NULL); + dds_set_trace_sink (NULL, NULL); + + /* All traces should have been provided. */ +#ifndef DDSI_INCLUDE_SECURITY + CU_ASSERT_FATAL (found == 0x0); +#else + CU_ASSERT_FATAL (found == 0x3); +#endif +} 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 30e2c4a..7eaaee1 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h @@ -184,11 +184,12 @@ bool q_omg_proxy_participant_is_secure(const struct proxy_participant *proxypp); * @param[in] pp The participant to check if alloweed by security. * #param[in] domain_id The domain_id * - * @returns bool - * @retval true Participant is allowed - * @retval false Participant is not allowed + * @returns dds_return_t + * @retval DDS_RETCODE_OK Participant is allowed + * @retval DDS_RETCODE_NOT_ALLOWED_BY_SECURITY + * Participant is not allowed */ -bool q_omg_security_check_create_participant(struct participant *pp, uint32_t domain_id); +dds_return_t q_omg_security_check_create_participant(struct participant *pp, uint32_t domain_id); void q_omg_security_participant_set_initialized(struct participant *pp); diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_xqos.h b/src/core/ddsi/include/dds/ddsi/ddsi_xqos.h index fac06d4..b7e803a 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_xqos.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_xqos.h @@ -322,7 +322,9 @@ DDS_EXPORT void ddsi_xqos_addtomsg (struct nn_xmsg *m, const dds_qos_t *xqos, ui DDS_EXPORT void ddsi_xqos_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos); DDS_EXPORT size_t ddsi_xqos_print (char * __restrict buf, size_t bufsize, const dds_qos_t *xqos); DDS_EXPORT dds_qos_t *ddsi_xqos_dup (const dds_qos_t *src); -DDS_EXPORT bool ddsi_xqos_has_prop (const dds_qos_t *xqos, const char *pname, bool startswith, bool check_non_empty); +DDS_EXPORT bool ddsi_xqos_has_prop_prefix (const dds_qos_t *xqos, const char *nameprefix); +DDS_EXPORT bool ddsi_xqos_find_prop (const dds_qos_t *xqos, const char *name, const char **value); + #ifdef DDSI_INCLUDE_SECURITY struct omg_security_configuration_type; DDS_EXPORT void ddsi_xqos_mergein_security_config (dds_qos_t *xqos, const struct omg_security_configuration_type *cfg); diff --git a/src/core/ddsi/src/ddsi_plist.c b/src/core/ddsi/src/ddsi_plist.c index ea032ad..f440276 100644 --- a/src/core/ddsi/src/ddsi_plist.c +++ b/src/core/ddsi/src/ddsi_plist.c @@ -3179,16 +3179,30 @@ dds_qos_t * ddsi_xqos_dup (const dds_qos_t *src) return dst; } -bool ddsi_xqos_has_prop (const dds_qos_t *xqos, const char *pname, bool startswith, bool check_non_empty) +bool ddsi_xqos_has_prop_prefix (const dds_qos_t *xqos, const char *nameprefix) { if (!(xqos->present & QP_PROPERTY_LIST)) return false; + const size_t len = strlen (nameprefix); + for (uint32_t i = 0; i < xqos->property.value.n; i++) + { + if (strncmp (xqos->property.value.props[i].name, nameprefix, len) == 0) + return true; + } + return false; +} - for (uint32_t i = 0; i < xqos->property.value.n; i++) { - if (startswith && (strncmp(xqos->property.value.props[i].name, pname, strlen(pname)) == 0)) { - return !check_non_empty || strlen(xqos->property.value.props[i].value) != 0; - } else if (!startswith && (strcmp(xqos->property.value.props[i].name, pname) == 0)) { - return !check_non_empty || strlen(xqos->property.value.props[i].value) != 0; +bool ddsi_xqos_find_prop (const dds_qos_t *xqos, const char *name, const char **value) +{ + if (!(xqos->present & QP_PROPERTY_LIST)) + return false; + for (uint32_t i = 0; i < xqos->property.value.n; i++) + { + if (strcmp (xqos->property.value.props[i].name, name) == 0) + { + if (value) + *value = xqos->property.value.props[i].value; + return true; } } return false; diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 64ec164..2dd78ab 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -844,9 +844,9 @@ bool q_omg_participant_allow_unauthenticated(struct participant *pp) return ((pp->sec_attr != NULL) && pp->sec_attr->attr.allow_unauthenticated_participants); } -bool q_omg_security_check_create_participant(struct participant *pp, uint32_t domain_id) +dds_return_t q_omg_security_check_create_participant(struct participant *pp, uint32_t domain_id) { - bool allowed = false; + dds_return_t ret = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY; struct dds_security_context *sc = q_omg_security_get_secure_context(pp); DDS_Security_IdentityHandle identity_handle = DDS_SECURITY_HANDLE_NIL; DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; @@ -860,7 +860,7 @@ bool q_omg_security_check_create_participant(struct participant *pp, uint32_t do ddsi_guid_t adjusted_guid; if (!sc) - return true; + return DDS_RETCODE_OK; /* Validate local identity */ ETRACE (pp, "validate_local_identity: candidate_guid: "PGUIDFMT" ", PGUID (pp->e.guid)); @@ -953,7 +953,7 @@ bool q_omg_security_check_create_participant(struct participant *pp, uint32_t do ETRACE (pp, "\n"); - allowed = true; + ret = DDS_RETCODE_OK; no_crypto: no_sec_attr: @@ -963,11 +963,11 @@ no_credentials: if (credential_token.class_id) (void)sc->access_control_context->return_permissions_credential_token(sc->access_control_context, &credential_token, NULL); not_allowed: - if (!allowed) + if (ret != DDS_RETCODE_OK) participant_sec_attributes_free(sec_attr); validation_failed: q_omg_shallow_free_security_qos(&par_qos); - return allowed; + return ret; } void q_omg_security_participant_set_initialized(struct participant *pp) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 5136dc8..614ad98 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -204,7 +204,6 @@ int is_builtin_endpoint (ddsi_entityid_t id, nn_vendorid_t vendorid) } #ifdef DDSI_INCLUDE_SECURITY - static int is_builtin_volatile_endpoint (ddsi_entityid_t id) { switch (id.u) { @@ -217,13 +216,13 @@ static int is_builtin_volatile_endpoint (ddsi_entityid_t id) return 0; } #else - +#ifndef NDEBUG static int is_builtin_volatile_endpoint (ddsi_entityid_t id) { DDSRT_UNUSED_ARG(id); return 0; } - +#endif #endif bool is_local_orphan_endpoint (const struct entity_common *e) @@ -633,9 +632,63 @@ static void add_security_builtin_endpoints(struct participant *pp, ddsi_guid_t * } #endif +static void add_builtin_endpoints(struct participant *pp, ddsi_guid_t *subguid, const ddsi_guid_t *group_guid, struct ddsi_domaingv *gv, bool add_writers, bool add_readers) +{ + if (add_writers) + { + struct whc_writer_info *wrinfo = whc_make_wrinfo (NULL, &gv->builtin_endpoint_xqos_wr); + + /* SEDP writers: */ + subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER); + new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); + pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER; + + subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER); + new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); + pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER; + + /* PMD writer: */ + subguid->entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER); + new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); + pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER; + + if (gv->config.do_topic_discovery) + { + subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER); + new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); + pp->bes |= NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER; + } + + whc_free_wrinfo (wrinfo); + } + + /* SPDP, SEDP, PMD readers: */ + if (add_readers) + { + subguid->entityid = to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER); + new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->spdp_endpoint_xqos, NULL, NULL, NULL); + pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR; + + subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER); + new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); + pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_DETECTOR; + + subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER); + new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); + pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_DETECTOR; + + subguid->entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER); + new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); + pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER; + } #ifdef DDSI_INCLUDE_SECURITY + if (q_omg_participant_is_secure (pp)) + add_security_builtin_endpoints (pp, subguid, group_guid, gv, add_writers, add_readers); +#endif +} +#ifdef DDSI_INCLUDE_SECURITY static void connect_participant_secure(struct ddsi_domaingv *gv, struct participant *pp) { struct proxy_participant *proxypp; @@ -749,6 +802,81 @@ static void participant_remove_wr_lease_locked (struct participant * pp, struct } } +#ifdef DDSI_INCLUDE_SECURITY +static dds_return_t check_and_load_security_config (struct ddsi_domaingv * const gv, const ddsi_guid_t *ppguid, dds_qos_t *qos) +{ + /* If some security properties (name starts with dds.sec. conform DDS Security spec 7.2.4.1) + are present in the QoS, all must be and they will be used. If none are, take the settings + from the configuration if it has them. When no security configuration exists anywhere, + create an unsecured participant. + + This may modify "qos" */ + if (ddsi_xqos_has_prop_prefix (qos, "dds.sec.")) + { + char const * const req[] = { + DDS_SEC_PROP_AUTH_IDENTITY_CA, + DDS_SEC_PROP_AUTH_PRIV_KEY, + DDS_SEC_PROP_AUTH_IDENTITY_CERT, + DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, + DDS_SEC_PROP_ACCESS_GOVERNANCE, + DDS_SEC_PROP_ACCESS_PERMISSIONS, + + DDS_SEC_PROP_AUTH_LIBRARY_PATH, + DDS_SEC_PROP_AUTH_LIBRARY_INIT, + DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE, + DDS_SEC_PROP_CRYPTO_LIBRARY_PATH, + DDS_SEC_PROP_CRYPTO_LIBRARY_INIT, + DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE, + DDS_SEC_PROP_ACCESS_LIBRARY_PATH, + DDS_SEC_PROP_ACCESS_LIBRARY_INIT, + DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE + }; + GVLOGDISC ("new_participant("PGUIDFMT"): using security settings from QoS\n", PGUID (*ppguid)); + + /* check if all required security properties exist in qos; report all missing ones, not just the first */ + dds_return_t ret = DDS_RETCODE_OK; + for (size_t i = 0; i < sizeof(req) / sizeof(req[0]); i++) + { + const char *value; + if (!ddsi_xqos_find_prop (qos, req[i], &value) || strlen (value) == 0) + { + GVERROR ("new_participant("PGUIDFMT"): required security property %s missing in Property QoS\n", PGUID (*ppguid), req[i]); + ret = DDS_RETCODE_PRECONDITION_NOT_MET; + } + } + if (ret != DDS_RETCODE_OK) + return ret; + } + else if (gv->config.omg_security_configuration) + { + /* For security, configuration can be provided through the configuration. However, the specification + (and the plugins) expect it to be in the QoS, so merge it in. */ + GVLOGDISC ("new_participant("PGUIDFMT"): using security settings from configuration\n", PGUID (*ppguid)); + ddsi_xqos_mergein_security_config (qos, &gv->config.omg_security_configuration->cfg); + } + else + { + /* No security configuration */ + return DDS_RETCODE_OK; + } + + if (q_omg_is_security_loaded (gv->security_context)) + { + GVLOGDISC ("new_participant("PGUIDFMT"): security is already loaded for this domain\n", PGUID (*ppguid)); + return DDS_RETCODE_OK; + } + else if (q_omg_security_load (gv->security_context, qos) < 0) + { + GVERROR ("Could not load security\n"); + return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY; + } + else + { + return DDS_RETCODE_OK; + } +} +#endif + dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv, unsigned flags, const ddsi_plist_t *plist) { struct participant *pp; @@ -828,77 +956,18 @@ dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv #ifdef DDSI_INCLUDE_SECURITY pp->sec_attr = NULL; - /* - * if there there are security properties check them . - * if there are no security properties, then merge from security configuration if there is - */ - /* check for existing security properties (name starts with dds.sec. conform DDS Security spec 7.2.4.1) - * and return if any is found */ + if ((ret = check_and_load_security_config (gv, ppguid, &pp->plist->qos)) != DDS_RETCODE_OK) + goto not_allowed; + if ((ret = q_omg_security_check_create_participant (pp, gv->config.domainId)) != DDS_RETCODE_OK) + goto not_allowed; + *ppguid = pp->e.guid; +#else + if (ddsi_xqos_has_prop_prefix (&pp->plist->qos, "dds.sec.")) { - bool ready_to_load_security = false; - if (ddsi_xqos_has_prop(&pp->plist->qos, "dds.sec.", true, false)) { - char *req[] = {DDS_SEC_PROP_AUTH_IDENTITY_CA, - DDS_SEC_PROP_AUTH_PRIV_KEY, - DDS_SEC_PROP_AUTH_IDENTITY_CERT, - DDS_SEC_PROP_ACCESS_PERMISSIONS_CA, - DDS_SEC_PROP_ACCESS_GOVERNANCE, - DDS_SEC_PROP_ACCESS_PERMISSIONS, - - DDS_SEC_PROP_AUTH_LIBRARY_PATH, - DDS_SEC_PROP_AUTH_LIBRARY_INIT, - DDS_SEC_PROP_AUTH_LIBRARY_FINALIZE, - DDS_SEC_PROP_CRYPTO_LIBRARY_PATH, - DDS_SEC_PROP_CRYPTO_LIBRARY_INIT, - DDS_SEC_PROP_CRYPTO_LIBRARY_FINALIZE, - DDS_SEC_PROP_ACCESS_LIBRARY_PATH, - DDS_SEC_PROP_ACCESS_LIBRARY_INIT, - DDS_SEC_PROP_ACCESS_LIBRARY_FINALIZE}; - GVLOGDISC ("new_participant(" - PGUIDFMT - "): using security settings from QoS\n", PGUID(*ppguid)); - - /* check if all required security properties exist in qos */ - for (size_t i = 0; i < sizeof(req) / sizeof(req[0]); i++) { - if (!ddsi_xqos_has_prop(&pp->plist->qos, req[i], false, true)) { - GVERROR ("new_participant(" - PGUIDFMT - "): required security property %s missing in Property QoS\n", PGUID(*ppguid), req[i]); - ret = DDS_RETCODE_PRECONDITION_NOT_MET; - } - } - if (ret == DDS_RETCODE_OK) { - ready_to_load_security = true; - } else { - goto new_pp_err_secprop; - } - } else if (gv->config.omg_security_configuration) { - /* For security, configuration can be provided through the configuration. - * However, the specification (and the plugins) expect it to be in the QoS. */ - GVLOGDISC ("new_participant(" - PGUIDFMT - "): using security settings from configuration\n", PGUID(*ppguid)); - ddsi_xqos_mergein_security_config(&pp->plist->qos, &gv->config.omg_security_configuration->cfg); - ready_to_load_security = true; - } - - if( q_omg_is_security_loaded( gv->security_context ) == false ){ - if (ready_to_load_security && q_omg_security_load(gv->security_context, &pp->plist->qos) < 0) { - GVERROR("Could not load security\n"); - ret = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY; - goto new_pp_err_secprop; - } - } else { - GVLOGDISC ("new_participant(" - PGUIDFMT - "): security is already loaded for this domain\n", PGUID(*ppguid)); - } - - if (!q_omg_security_check_create_participant (pp, gv->config.domainId)) - { - ret = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY; - goto not_allowed; - } - *ppguid = pp->e.guid; + /* disallow creating a participant with a security configuration if there is support for security + has been left out */ + ret = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY; + goto not_allowed; } #endif @@ -927,9 +996,7 @@ dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv subguid.prefix = pp->e.guid.prefix; memset (&group_guid, 0, sizeof (group_guid)); - /* SPDP writer */ - /* Note: skip SEDP <=> skip SPDP because of the way ddsi_discovery.c does things - currently. */ + /* SPDP is very much special and must be done first */ if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS)) { subguid.entityid = to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER); @@ -938,70 +1005,15 @@ dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv whc_free_wrinfo (wrinfo); /* But we need the as_disc address set for SPDP, because we need to send it to everyone regardless of the existence of readers. */ - force_as_disc_address(gv, &subguid); + force_as_disc_address (gv, &subguid); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER; } /* Make it globally visible, else the endpoint matching won't work. */ entidx_insert_participant_guid (gv->entity_index, pp); - /* SEDP writers: */ - wrinfo = whc_make_wrinfo (NULL, &gv->builtin_endpoint_xqos_wr); - if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS)) - { - subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); - pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER; - - subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); - pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER; - } - - if (gv->config.do_topic_discovery) - { - /* TODO: make this one configurable, we don't want all participants to publish all topics (or even just those that they use themselves) */ - subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); - pp->bes |= NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER; - } - - /* PMD writer: */ - if (!(flags & RTPS_PF_NO_BUILTIN_WRITERS)) - { - subguid.entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); - pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER; - } - - whc_free_wrinfo (wrinfo); - - /* SPDP, SEDP, PMD readers: */ - if (!(flags & RTPS_PF_NO_BUILTIN_READERS)) - { - subguid.entityid = to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER); - new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->spdp_endpoint_xqos, NULL, NULL, NULL); - pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR; - - subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER); - new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); - pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_DETECTOR; - - subguid.entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER); - new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); - pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_DETECTOR; - - subguid.entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER); - new_reader_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); - pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER; - } - -#ifdef DDSI_INCLUDE_SECURITY - if (q_omg_participant_is_secure(pp)) - { - add_security_builtin_endpoints(pp, &subguid, &group_guid, gv, !(flags & RTPS_PF_NO_BUILTIN_WRITERS), !(flags & RTPS_PF_NO_BUILTIN_READERS)); - } -#endif + /* add all built-in endpoints other than the SPDP writer */ + add_builtin_endpoints (pp, &subguid, &group_guid, gv, !(flags & RTPS_PF_NO_BUILTIN_WRITERS), !(flags & RTPS_PF_NO_BUILTIN_READERS)); /* If the participant doesn't have the full set of builtin writers it depends on the privileged participant, which must exist, hence @@ -1009,7 +1021,8 @@ dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv If it is the privileged participant, set the global variable pointing to it. Except when the participant is only locally available. */ - if (!(flags & RTPS_PF_ONLY_LOCAL)) { + if (!(flags & RTPS_PF_ONLY_LOCAL)) + { ddsrt_mutex_lock (&gv->privileged_pp_lock); if ((pp->bes & builtin_writers_besmask) != builtin_writers_besmask) { @@ -1066,16 +1079,16 @@ dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv } #ifdef DDSI_INCLUDE_SECURITY - if (q_omg_participant_is_secure(pp)) + if (q_omg_participant_is_secure (pp)) { connect_participant_secure (gv, pp); } #endif return ret; -#ifdef DDSI_INCLUDE_SECURITY not_allowed: -new_pp_err_secprop: + if (ppconn) + ddsi_conn_free (ppconn); ddsi_plist_fini (pp->plist); ddsrt_free (pp->plist); inverse_uint32_set_fini (&pp->avail_entityids.x); @@ -1085,7 +1098,6 @@ new_pp_err_secprop: ddsrt_mutex_lock (&gv->participant_set_lock); gv->nparticipants--; ddsrt_mutex_unlock (&gv->participant_set_lock); -#endif new_pp_err: return ret; } @@ -4886,6 +4898,7 @@ void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *pp const bool is_secure = ((bes & NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_ANNOUNCER) != 0); assert (!is_secure || (plist->present & PP_IDENTITY_TOKEN)); assert (is_secure || (bes & ~NN_BES_MASK_NON_SECURITY) == 0); + (void) is_secure; assert (ppguid->entityid.u == NN_ENTITYID_PARTICIPANT); assert (entidx_lookup_proxy_participant_guid (gv->entity_index, ppguid) == NULL); From ecbd585f12fd11e9efe689b6dce6a578fd0665cd Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 25 Mar 2020 10:39:44 +0100 Subject: [PATCH 135/238] Generate header with compile-time features Currently: * DDS_HAS_SECURITY for DDS Security support * DDS_HAS_LIFESPAN for lifespan QoS support * DDS_HAS_DEADLINE_MISSED for "deadline missed" event support These are defined to 1 if support for the feature is included in the build and left undefined if it isn't. Signed-off-by: Erik Boasson --- src/CMakeLists.txt | 20 ++++++++++++++++++++ src/core/ddsc/include/dds/dds.h | 1 + src/features.h.in | 24 ++++++++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 src/features.h.in diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ee0b287..9e5f5c7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,6 +16,26 @@ if(NOT ${PROJECT_NAME} STREQUAL "CycloneDDS") message(FATAL_ERROR "Top-level CMakeLists.txt was moved to the top-level directory. Please run cmake on ${dir} instead of ${CMAKE_CURRENT_LIST_DIR}") endif() +# Generate a header file listing compile-time options relevant to the API. Define to +# "1" if enabled so that the generated features.h ends up having either +# +# - #define DDS_HAS_SECURITY 1 +# or +# - /* #undef DDS_HAS_SECURITY */ +# +# which caters both for those who prefer #ifdef DDS_HAS_SECURITY and for those who prefer +# #if DDS_HAS_SECURITY. +if(ENABLE_SECURITY) + set(DDS_HAS_SECURITY "1") +endif() +if(ENABLE_LIFESPAN) + set(DDS_HAS_LIFESPAN "1") +endif() +if(ENABLE_DEADLINE_MISSED) + set(DDS_HAS_DEADLINE_MISSED "1") +endif() +configure_file(features.h.in "${CMAKE_CURRENT_BINARY_DIR}/core/include/dds/features.h") + add_definitions(-DDDSI_INCLUDE_NETWORK_PARTITIONS -DDDSI_INCLUDE_SSM) # OpenSSL is huge, raising the RSS by 1MB or so, and moreover find_package(OpenSSL) causes diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index b50f1d0..aa2f139 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -25,6 +25,7 @@ #endif #include "dds/export.h" +#include "dds/features.h" /** * Handle to an entity. A valid entity handle will always have a positive diff --git a/src/features.h.in b/src/features.h.in new file mode 100644 index 0000000..636f19f --- /dev/null +++ b/src/features.h.in @@ -0,0 +1,24 @@ +/* + * Copyright(c) 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef _DDS_PUBLIC_FEATURES_H_ +#define _DDS_PUBLIC_FEATURES_H_ + +/* Whether or not support for DDS Security is included */ +#cmakedefine DDS_HAS_SECURITY @DDS_HAS_SECURITY@ + +/* Whether or not support for the lifespan QoS is included */ +#cmakedefine DDS_HAS_LIFESPAN @DDS_HAS_LIFESPAN@ + +/* Whether or not support for generating "deadline missed" events is included */ +#cmakedefine DDS_HAS_DEADLINE_MISSED @DDS_HAS_DEADLINE_MISSED@ + +#endif From d82b7fdd73258fc8be53a18e7cd99589bf3baa2e Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 25 Mar 2020 14:48:35 +0100 Subject: [PATCH 136/238] Return PRECONDITION_NOT_MET if security not supported As opposed to NOT_ALLOWED_BY_SECURITY. There is a meaningful difference between something being disallowed and something being impossible. Co-Authored-By: Kyle Fazzari Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/dds.h | 16 +++++++++++++++- src/core/ddsi/src/q_entity.c | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index aa2f139..7e36253 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -739,8 +739,22 @@ dds_set_listener(dds_entity_t entity, const dds_listener_t * listener); * * @retval >0 * A valid participant handle. + * @retval DDS_RETCODE_NOT_ALLOWED_BY_SECURITY + * An invalid DDS Security configuration was specified (whether + * that be missing or incorrect entries, expired certificates, + * or anything else related to the security settings and + * implementation). + * @retval DDS_RETCODE_PRECONDITION_NOT_MET + * Some security properties specified in the QoS, but the Cyclone + * build does not include support for DDS Security. + * @retval DDS_RETCODE_OUT_OF_RESOURCES + * Some resource limit (maximum participants, memory, handles, + * &c.) prevented creation of the participant. * @retval DDS_RETCODE_ERROR - * An internal error has occurred. + * The "CYCLONEDDS_URI" environment variable lists non-existent + * or invalid configuration files, or contains invalid embedded + * configuration items; or an unspecified internal error has + * occurred. */ DDS_EXPORT dds_entity_t dds_create_participant( diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 614ad98..242cb28 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -966,7 +966,7 @@ dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv { /* disallow creating a participant with a security configuration if there is support for security has been left out */ - ret = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY; + ret = DDS_RETCODE_PRECONDITION_NOT_MET; goto not_allowed; } #endif From a77fe10a040c3994c41884d1cfa04d4643627f5e Mon Sep 17 00:00:00 2001 From: Marcel Jordense Date: Tue, 24 Mar 2020 19:15:36 +0100 Subject: [PATCH 137/238] Add index on receiver specific key to improve verification of origin authentication signing Signed-off-by: Marcel Jordense --- src/core/ddsi/src/ddsi_security_omg.c | 20 +- .../access_control/src/access_control.c | 1 + .../src/access_control_objects.c | 7 +- .../cryptographic/src/crypto_defs.h | 8 + .../cryptographic/src/crypto_key_factory.c | 452 +++++++++++------- .../cryptographic/src/crypto_key_factory.h | 10 + .../cryptographic/src/crypto_objects.c | 331 ++++++++++--- .../cryptographic/src/crypto_objects.h | 117 ++++- .../cryptographic/src/crypto_transform.c | 60 +-- .../src/decode_datareader_submessage_utests.c | 4 +- .../src/decode_datawriter_submessage_utests.c | 4 +- .../src/decode_rtps_message_utests.c | 2 + .../src/encode_datareader_submessage_utests.c | 4 +- .../src/encode_datawriter_submessage_utests.c | 4 +- .../src/encode_rtps_message_utests.c | 30 +- .../src/preprocess_secure_submsg_utests.c | 2 + .../src/register_local_datareader_utests.c | 24 +- .../src/register_local_datawriter_utests.c | 24 +- .../core/tests/secure_communication.c | 8 +- 19 files changed, 753 insertions(+), 359 deletions(-) diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 2dd78ab..40768d9 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -389,7 +389,16 @@ static void proxypp_pp_match_free(struct dds_security_context *sc, struct proxyp if (pm->permissions_handle != DDS_SECURITY_HANDLE_NIL) { if (!sc->access_control_context->return_permissions_handle(sc->access_control_context, pm->permissions_handle, &exception)) + { + /* FIXME: enable exception warning when access control is updated to return a permission handle for each + * matching local and remote participant. + */ +#if 0 EXCEPTION_ERROR(sc, &exception, "Failed to return remote permissions handle"); +#else + DDS_Security_Exception_reset(&exception); +#endif + } } ddsrt_free(pm); } @@ -1011,6 +1020,8 @@ static void cleanup_participant_sec_attributes(void *arg) if ((attr = participant_index_remove(sc, info->crypto_handle)) == NULL) return; + GVTRACE("cleanup participant "PGUIDFMT" security attributes\n", PGUID(attr->pp_guid)); + pm = ddsrt_avl_cfind_min(&pp_proxypp_treedef, &attr->proxy_participants); while (pm) { @@ -1041,7 +1052,8 @@ static void cleanup_participant_sec_attributes(void *arg) EXCEPTION_ERROR(sc, &exception, "Failed to return participant security attributes"); } - (void)sc->crypto_context->crypto_key_factory->unregister_participant(sc->crypto_context->crypto_key_factory, attr->crypto_handle, NULL); + if (!sc->crypto_context->crypto_key_factory->unregister_participant(sc->crypto_context->crypto_key_factory, attr->crypto_handle, &exception)) + EXCEPTION_ERROR(sc, &exception, "Failed to unregister participant"); ddsrt_avl_cfree(&pp_proxypp_treedef, &attr->proxy_participants, NULL); ddsrt_mutex_unlock(&attr->lock); @@ -1702,7 +1714,7 @@ bool q_omg_security_register_remote_participant(struct participant *pp, struct p proxypp->sec_attr->crypto_handle = crypto_handle; - GVTRACE("match pp->crypto=%"PRId64" proxypp->crypto=%"PRId64"\n", pp->sec_attr->crypto_handle, crypto_handle); + 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); @@ -2031,7 +2043,7 @@ static bool q_omg_security_register_remote_writer_match(struct proxy_writer *pwr match = find_or_create_entity_match(gv->security_matches, &pwr->e.guid, &rd->e.guid); if (match->matched) *crypto_handle = match->crypto_handle; - else + else if (match->crypto_handle == 0) { /* Generate writer crypto info. */ match->crypto_handle = sc->crypto_context->crypto_key_factory->register_matched_remote_datawriter( @@ -2382,7 +2394,7 @@ static bool q_omg_security_register_remote_reader_match(struct proxy_reader *prd match = find_or_create_entity_match(gv->security_matches, &prd->e.guid, &wr->e.guid); if (match->matched) *crypto_handle = match->crypto_handle; - else + else if (match->crypto_handle == 0) { /* Generate writer crypto info. */ match->crypto_handle = sc->crypto_context->crypto_key_factory->register_matched_remote_datareader( diff --git a/src/security/builtin_plugins/access_control/src/access_control.c b/src/security/builtin_plugins/access_control/src/access_control.c index d26b761..1728a9b 100644 --- a/src/security/builtin_plugins/access_control/src/access_control.c +++ b/src/security/builtin_plugins/access_control/src/access_control.c @@ -2381,6 +2381,7 @@ check_and_create_remote_participant_rights( permissions = ddsrt_malloc(sizeof(remote_permissions)); permissions->ref_cnt = 0; permissions->permissions_tree = NULL; + permissions->remote_permissions_token_class_id = NULL; if (!ac_parse_permissions_xml(permissions_xml, &(permissions->permissions_tree), ex)) { ddsrt_free(permissions); diff --git a/src/security/builtin_plugins/access_control/src/access_control_objects.c b/src/security/builtin_plugins/access_control/src/access_control_objects.c index cee88cb..8988061 100644 --- a/src/security/builtin_plugins/access_control/src/access_control_objects.c +++ b/src/security/builtin_plugins/access_control/src/access_control_objects.c @@ -270,9 +270,12 @@ ac_remote_participant_access_rights_new( rights->local_rights = (local_participant_access_rights *)ACCESS_CONTROL_OBJECT_KEEP(local_rights); if (rights->permissions) { - rights->permissions->remote_permissions_token_class_id = ddsrt_strdup(remote_permissions_token->class_id); rights->permissions->ref_cnt++; - rights->identity_subject_name = ddsrt_strdup(identity_subject); + if (rights->permissions->remote_permissions_token_class_id == NULL) + { + rights->permissions->remote_permissions_token_class_id = ddsrt_strdup(remote_permissions_token->class_id); + rights->identity_subject_name = ddsrt_strdup(identity_subject); + } } else { diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_defs.h b/src/security/builtin_plugins/cryptographic/src/crypto_defs.h index 5947f29..0d2a983 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_defs.h +++ b/src/security/builtin_plugins/cryptographic/src/crypto_defs.h @@ -12,8 +12,10 @@ #ifndef CRYPTO_DEFS_H #define CRYPTO_DEFS_H +#include "dds/security/core/dds_security_types.h" #include "dds/security/dds_security_api.h" + #define DDS_CRYPTO_PLUGIN_CONTEXT "Cryptographic" #define CRYPTO_HMAC_SIZE 16 @@ -111,4 +113,10 @@ typedef enum RTPS_Message_Type RTPS_Message_Type_SRTPS_POSTFIX = 0x34 } RTPS_Message_Type; +struct receiver_specific_mac +{ + DDS_Security_CryptoTransformKeyId receiver_mac_key_id; + crypto_hmac_t receiver_mac; +}; + #endif /* CRYPTO_DEFS_H */ diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c index 61e3f9e..02ba273 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c @@ -238,66 +238,38 @@ attribute_to_data_protection_kind( return kind; } -static void -remove_relation_from_keymaterial( - const participant_key_material *key_material, - CryptoObject *local_crypto, - CryptoObject *remote_crypto) -{ - endpoint_relation *relation; - - relation = crypto_endpoint_relation_find_by_crypto(key_material->endpoint_relations, local_crypto, remote_crypto); - if (relation) - { - crypto_object_table_remove_object(key_material->endpoint_relations, (CryptoObject *)relation); - CRYPTO_OBJECT_RELEASE(relation); - } -} - static void remove_remote_writer_relation( dds_security_crypto_key_factory_impl *implementation, - remote_datawriter_crypto *remote_writer) + remote_datawriter_crypto *rmt_wr) { - remote_participant_crypto *remote_participant; - participant_key_material *key_material; + remote_participant_crypto *rmt_pp; DDSRT_UNUSED_ARG(implementation); - assert(remote_writer); - remote_participant = remote_writer->participant; - assert(remote_participant); + assert(rmt_wr); + rmt_pp = rmt_wr->participant; + assert(rmt_pp); - key_material = (participant_key_material *)crypto_object_table_find( - remote_participant->key_material, CRYPTO_OBJECT_HANDLE(remote_writer->local_reader->participant)); - if (key_material) - { - remove_relation_from_keymaterial(key_material, (CryptoObject *)remote_writer->local_reader, (CryptoObject *)remote_writer); - CRYPTO_OBJECT_RELEASE(key_material); - } + if (rmt_wr->writer2reader_key_material[0]) + crypto_remove_endpoint_relation(rmt_pp, (CryptoObject *)rmt_wr->local_reader, rmt_wr->writer2reader_key_material[0]->sender_key_id); } static void remove_remote_reader_relation( dds_security_crypto_key_factory_impl *implementation, - remote_datareader_crypto *remote_reader) + remote_datareader_crypto *rmt_rd) { - remote_participant_crypto *remote_participant; - participant_key_material *key_material; + remote_participant_crypto *rmt_pp; DDSRT_UNUSED_ARG(implementation); - assert(remote_reader); - remote_participant = remote_reader->participant; - assert(remote_participant); + assert(rmt_rd); + rmt_pp = rmt_rd->participant; + assert(rmt_pp); - key_material = (participant_key_material *)crypto_object_table_find( - remote_participant->key_material, CRYPTO_OBJECT_HANDLE(remote_reader->local_writer->participant)); - if (key_material) - { - remove_relation_from_keymaterial(key_material, (CryptoObject *)remote_reader->local_writer, (CryptoObject *)remote_reader); - CRYPTO_OBJECT_RELEASE(key_material); - } + if (rmt_rd->reader2writer_key_material) + crypto_remove_endpoint_relation(rmt_pp, (CryptoObject *)rmt_rd->local_writer, rmt_rd->reader2writer_key_material->sender_key_id); } /** @@ -388,8 +360,8 @@ register_matched_remote_participant( { /* declarations */ dds_security_crypto_key_factory_impl *implementation = (dds_security_crypto_key_factory_impl *)instance; - remote_participant_crypto *participant_crypto; - local_participant_crypto *local_participant_crypto_ref; + remote_participant_crypto *rmt_pp_crypto; + local_participant_crypto *loc_pp_crypto; DDS_Security_SecurityException exception; participant_key_material *key_material; @@ -414,8 +386,8 @@ register_matched_remote_participant( /* Check if local_participant_crypto_handle exists in the map */ - local_participant_crypto_ref = (local_participant_crypto *)crypto_object_table_find(implementation->crypto_objects, local_participant_crypto_handle); - if (local_participant_crypto_ref == NULL) + loc_pp_crypto = (local_participant_crypto *)crypto_object_table_find(implementation->crypto_objects, local_participant_crypto_handle); + if (loc_pp_crypto == NULL) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); @@ -428,23 +400,22 @@ register_matched_remote_participant( crypto_object_table_walk(implementation->crypto_objects, resolve_remote_participant_by_id, &arg); if (arg.pprmte) { - participant_crypto = arg.pprmte; + rmt_pp_crypto = arg.pprmte; } else { - participant_crypto = crypto_remote_participant_crypto__new(remote_participant_identity); - crypto_object_table_insert(implementation->crypto_objects, (CryptoObject *)participant_crypto); + rmt_pp_crypto = crypto_remote_participant_crypto__new(remote_participant_identity); + crypto_object_table_insert(implementation->crypto_objects, (CryptoObject *)rmt_pp_crypto); } } - key_material = (participant_key_material *)crypto_object_table_find(participant_crypto->key_material, local_participant_crypto_ref->_parent.handle); - + key_material = crypto_remote_participant_lookup_keymat(rmt_pp_crypto, PARTICIPANT_CRYPTO_HANDLE(loc_pp_crypto)); if (!key_material) { - key_material = crypto_participant_key_material_new(local_participant_crypto_ref); + key_material = crypto_participant_key_material_new(loc_pp_crypto, rmt_pp_crypto); /* set remote participant keymaterial with local keymaterial values */ - crypto_master_key_material_set(key_material->local_P2P_key_material, local_participant_crypto_ref->key_material); + crypto_master_key_material_set(key_material->local_P2P_key_material, loc_pp_crypto->key_material); if (!calculate_kx_keys(shared_secret, key_material->P2P_kx_key_material, &exception)) goto fail_calc_key; @@ -453,8 +424,8 @@ register_matched_remote_participant( key_material->P2P_reader_session = crypto_session_key_material_new(key_material->P2P_kx_key_material); /* if we do not have OriginAuthentication, receiver specific info remains empty/NULL */ - if ((local_participant_crypto_ref->rtps_protection_kind == DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION) || - (local_participant_crypto_ref->rtps_protection_kind == DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION)) + if ((loc_pp_crypto->rtps_protection_kind == DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION) || + (loc_pp_crypto->rtps_protection_kind == DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION)) { if (RAND_bytes(key_material->local_P2P_key_material->master_receiver_specific_key, (int)CRYPTO_KEY_SIZE_BYTES(key_material->local_P2P_key_material->transformation_kind)) < 0) { @@ -464,25 +435,26 @@ register_matched_remote_participant( } key_material->local_P2P_key_material->receiver_specific_key_id = ddsrt_atomic_inc32_ov(&implementation->next_key_id); } - participant_crypto->session = (session_key_material *)CRYPTO_OBJECT_KEEP(local_participant_crypto_ref->session); + rmt_pp_crypto->session = (session_key_material *)CRYPTO_OBJECT_KEEP(loc_pp_crypto->session); - crypto_object_table_insert(participant_crypto->key_material, (CryptoObject *)key_material); + crypto_local_participant_add_keymat(loc_pp_crypto, key_material); + crypto_remote_participant_add_keymat(rmt_pp_crypto, key_material); } - participant_crypto->rtps_protection_kind = local_participant_crypto_ref->rtps_protection_kind; /* Same as local */ + rmt_pp_crypto->rtps_protection_kind = loc_pp_crypto->rtps_protection_kind; /* Same as local */ CRYPTO_OBJECT_RELEASE(key_material); - CRYPTO_OBJECT_RELEASE(participant_crypto); - CRYPTO_OBJECT_RELEASE(local_participant_crypto_ref); + CRYPTO_OBJECT_RELEASE(rmt_pp_crypto); + CRYPTO_OBJECT_RELEASE(loc_pp_crypto); - return PARTICIPANT_CRYPTO_HANDLE(participant_crypto); + return PARTICIPANT_CRYPTO_HANDLE(rmt_pp_crypto); /* error cases*/ err_random_generation: fail_calc_key: CRYPTO_OBJECT_RELEASE(key_material); - CRYPTO_OBJECT_RELEASE(participant_crypto); - CRYPTO_OBJECT_RELEASE(local_participant_crypto_ref); + CRYPTO_OBJECT_RELEASE(rmt_pp_crypto); + CRYPTO_OBJECT_RELEASE(loc_pp_crypto); err_invalid_argument: return DDS_SECURITY_HANDLE_NIL; } @@ -502,8 +474,6 @@ register_local_datawriter( DDS_Security_ProtectionKind metadata_protection; DDS_Security_BasicProtectionKind data_protection; - memset(ex, 0, sizeof(*ex)); - if (participant_crypto_handle == DDS_SECURITY_HANDLE_NIL) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, @@ -582,8 +552,6 @@ register_matched_remote_datareader( DDS_Security_ProtectionKind metadata_protectionKind; DDS_Security_BasicProtectionKind data_protectionKind; - memset(ex, 0, sizeof(*ex)); - DDSRT_UNUSED_ARG(shared_secret); DDSRT_UNUSED_ARG(relay_only); @@ -620,9 +588,7 @@ register_matched_remote_datareader( /* check if the writer is BuiltinParticipantVolatileMessageSecureWriter */ if (local_writer->is_builtin_participant_volatile_message_secure_writer) { - participant_key_material *key_material; - - key_material = (participant_key_material *)crypto_object_table_find(remote_participant->key_material, CRYPTO_OBJECT_HANDLE(local_writer->participant)); + participant_key_material *key_material = crypto_remote_participant_lookup_keymat(remote_participant, CRYPTO_OBJECT_HANDLE(local_writer->participant)); assert(key_material); reader_crypto->reader2writer_key_material = (master_key_material *)CRYPTO_OBJECT_KEEP(key_material->P2P_kx_key_material); @@ -729,6 +695,11 @@ register_local_datareader( reader_crypto->reader_session = crypto_session_key_material_new(reader_crypto->reader_key_material); } } + else + { + participant_crypto->builtin_reader = reader_crypto; + + } crypto_object_table_insert(implementation->crypto_objects, (CryptoObject *)reader_crypto); CRYPTO_OBJECT_RELEASE(participant_crypto); @@ -789,10 +760,7 @@ register_matched_remote_datawriter( /* check if the writer is BuiltinParticipantVolatileMessageSecureWriter */ if (local_reader->is_builtin_participant_volatile_message_secure_reader) { - participant_key_material *key_material; - endpoint_relation *relation; - - key_material = (participant_key_material *)crypto_object_table_find(remote_participant->key_material, CRYPTO_OBJECT_HANDLE(local_reader->participant)); + participant_key_material *key_material = crypto_remote_participant_lookup_keymat(remote_participant, CRYPTO_OBJECT_HANDLE(local_reader->participant)); assert(key_material); writer_crypto->reader2writer_key_material = (master_key_material *)CRYPTO_OBJECT_KEEP(key_material->P2P_kx_key_material); @@ -801,8 +769,9 @@ register_matched_remote_datawriter( writer_crypto->reader_session = (session_key_material *)CRYPTO_OBJECT_KEEP(key_material->P2P_reader_session); writer_crypto->is_builtin_participant_volatile_message_secure_writer = true; - relation = crypto_endpoint_relation_new(DDS_SECURITY_DATAWRITER_SUBMESSAGE, 0, (CryptoObject *)local_reader, (CryptoObject *)writer_crypto); - crypto_object_table_insert(key_material->endpoint_relations, (CryptoObject *)relation); + key_relation * relation = crypto_key_relation_new(DDS_SECURITY_DATAWRITER_SUBMESSAGE, 0, (CryptoObject *)local_reader, (CryptoObject *)writer_crypto, NULL); + + crypto_insert_endpoint_relation(remote_participant, relation); CRYPTO_OBJECT_RELEASE(relation); CRYPTO_OBJECT_RELEASE(key_material); } @@ -847,29 +816,81 @@ unregister_participant( const DDS_Security_ParticipantCryptoHandle participant_crypto_handle, DDS_Security_SecurityException *ex) { + dds_security_crypto_key_factory_impl *implementation = (dds_security_crypto_key_factory_impl *)instance; DDS_Security_boolean result = false; CryptoObject *obj; - dds_security_crypto_key_factory_impl *implementation = (dds_security_crypto_key_factory_impl *)instance; + local_participant_crypto *loc_pp_crypto; + remote_participant_crypto *rmt_pp_crypto; + participant_key_material *keymat; + DDS_Security_ParticipantCryptoHandle *handles = NULL; + size_t num, i; if ((obj = crypto_object_table_find(implementation->crypto_objects, participant_crypto_handle)) != NULL) { - if ((obj->kind == CRYPTO_OBJECT_KIND_LOCAL_CRYPTO) || (obj->kind == CRYPTO_OBJECT_KIND_REMOTE_CRYPTO)) + switch (obj->kind) { + case CRYPTO_OBJECT_KIND_LOCAL_CRYPTO: + { + loc_pp_crypto = (local_participant_crypto *)obj; + + num = crypto_local_participnant_get_matching(loc_pp_crypto, &handles); + for (i = 0; i < num; i++) + { + if ((keymat = crypto_local_participant_remove_keymat(loc_pp_crypto, handles[i])) != NULL) + CRYPTO_OBJECT_RELEASE(keymat); + + if ((rmt_pp_crypto = (remote_participant_crypto *)crypto_object_table_find(implementation->crypto_objects, handles[i])) != NULL) + { + if ((keymat = crypto_remote_participant_remove_keymat(rmt_pp_crypto, participant_crypto_handle)) != NULL) + { + if (keymat->remote_key_material && keymat->remote_key_material->receiver_specific_key_id != 0) + crypto_remove_specific_key_relation(rmt_pp_crypto, keymat->remote_key_material->receiver_specific_key_id); + CRYPTO_OBJECT_RELEASE(keymat); + } + CRYPTO_OBJECT_RELEASE(rmt_pp_crypto); + } + } + ddsrt_free(handles); crypto_object_table_remove_object(implementation->crypto_objects, obj); result = true; } - else + break; + case CRYPTO_OBJECT_KIND_REMOTE_CRYPTO: { - DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, - DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); + rmt_pp_crypto = (remote_participant_crypto *)obj; + + num = crypto_remote_participnant_get_matching(rmt_pp_crypto, &handles); + for (i = 0; i < num; i++) + { + if ((keymat = crypto_remote_participant_remove_keymat(rmt_pp_crypto, handles[i])) != NULL) + { + if (keymat->remote_key_material && keymat->remote_key_material->receiver_specific_key_id != 0) + crypto_remove_specific_key_relation(rmt_pp_crypto, keymat->remote_key_material->receiver_specific_key_id); + CRYPTO_OBJECT_RELEASE(keymat); + } + + if ((loc_pp_crypto = (local_participant_crypto *)crypto_object_table_find(implementation->crypto_objects, handles[i])) != NULL) + { + if ((keymat = crypto_local_participant_remove_keymat(loc_pp_crypto, participant_crypto_handle)) != NULL) + CRYPTO_OBJECT_RELEASE(keymat); + CRYPTO_OBJECT_RELEASE(loc_pp_crypto); + } + } + ddsrt_free(handles); + crypto_object_table_remove_object(implementation->crypto_objects, obj); + result = true; + } + break; + default: + { + DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); + } + break; } CRYPTO_OBJECT_RELEASE(obj); } else - { - DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, - DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); - } + DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); return result; } @@ -887,25 +908,30 @@ unregister_datawriter( /* check if the handle is applicable*/ if ((obj = crypto_object_table_find(implementation->crypto_objects, datawriter_crypto_handle)) != NULL) { - if ((obj->kind == CRYPTO_OBJECT_KIND_LOCAL_WRITER_CRYPTO) || (obj->kind == CRYPTO_OBJECT_KIND_REMOTE_WRITER_CRYPTO)) + switch (obj->kind) { - if (obj->kind == CRYPTO_OBJECT_KIND_REMOTE_WRITER_CRYPTO) - remove_remote_writer_relation(implementation, (remote_datawriter_crypto *)obj); + case CRYPTO_OBJECT_KIND_LOCAL_WRITER_CRYPTO: + crypto_object_table_remove_object(implementation->crypto_objects, obj); + result = true; + break; + case CRYPTO_OBJECT_KIND_REMOTE_WRITER_CRYPTO: + { + remote_datawriter_crypto *rmt_wr = (remote_datawriter_crypto *)obj; + remove_remote_writer_relation(implementation, rmt_wr); + if (rmt_wr->writer2reader_key_material[0] && rmt_wr->writer2reader_key_material[0]->receiver_specific_key_id != 0) + crypto_remove_specific_key_relation(rmt_wr->participant, rmt_wr->writer2reader_key_material[0]->receiver_specific_key_id); crypto_object_table_remove_object(implementation->crypto_objects, obj); result = true; } - else - { - DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, - DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); + break; + default: + DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); + break; } CRYPTO_OBJECT_RELEASE(obj); } else - { - DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, - DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); - } + DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); return result; } @@ -923,25 +949,30 @@ unregister_datareader( /* check if the handle is applicable*/ if ((obj = crypto_object_table_find(implementation->crypto_objects, datareader_crypto_handle)) != NULL) { - if ((obj->kind == CRYPTO_OBJECT_KIND_LOCAL_READER_CRYPTO) || (obj->kind == CRYPTO_OBJECT_KIND_REMOTE_READER_CRYPTO)) + switch (obj->kind) { - if (obj->kind == CRYPTO_OBJECT_KIND_REMOTE_READER_CRYPTO) - remove_remote_reader_relation(implementation, (remote_datareader_crypto *)obj); + case CRYPTO_OBJECT_KIND_LOCAL_READER_CRYPTO: + crypto_object_table_remove_object(implementation->crypto_objects, obj); + result = true; + break; + case CRYPTO_OBJECT_KIND_REMOTE_READER_CRYPTO: + { + remote_datareader_crypto *rmt_rd = (remote_datareader_crypto *)obj; + remove_remote_reader_relation(implementation, rmt_rd); + if (rmt_rd->reader2writer_key_material && rmt_rd->reader2writer_key_material->receiver_specific_key_id != 0) + crypto_remove_specific_key_relation(rmt_rd->participant, rmt_rd->reader2writer_key_material->receiver_specific_key_id); crypto_object_table_remove_object(implementation->crypto_objects, obj); result = true; } - else - { - DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, - DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); + break; + default: + DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); + break; } CRYPTO_OBJECT_RELEASE(obj); } else - { - DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, - DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); - } + DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); return result; } @@ -1040,6 +1071,7 @@ crypto_factory_get_participant_crypto_tokens( dds_security_crypto_key_factory_impl *impl = (dds_security_crypto_key_factory_impl *)factory; remote_participant_crypto *remote_crypto = (remote_participant_crypto *)crypto_object_table_find(impl->crypto_objects, remote_id); bool result = false; + if (!remote_crypto) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, @@ -1053,7 +1085,7 @@ crypto_factory_get_participant_crypto_tokens( goto err_remote; } - if (!(*pp_key_material = (participant_key_material *)crypto_object_table_find(remote_crypto->key_material, local_id))) + if (!(*pp_key_material = (participant_key_material *)crypto_remote_participant_lookup_keymat(remote_crypto, local_id))) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); @@ -1096,12 +1128,26 @@ crypto_factory_set_participant_crypto_tokens( goto err_inv_remote; } - key_material = (participant_key_material *)crypto_object_table_find(remote_crypto->key_material, local_id); + key_material = crypto_remote_participant_lookup_keymat(remote_crypto, local_id); if (key_material) { if (!key_material->remote_key_material) key_material->remote_key_material = crypto_master_key_material_new(CRYPTO_TRANSFORMATION_KIND_NONE); crypto_token_copy(key_material->remote_key_material, remote_key_mat); + + uint32_t specific_key = key_material->remote_key_material->receiver_specific_key_id; + if (specific_key != 0) + { + key_relation *relation = crypto_find_specific_key_relation(remote_crypto, specific_key); + if (!relation) + { + local_participant_crypto *local_crypto = (local_participant_crypto *)crypto_object_table_find(impl->crypto_objects, local_id); + relation = crypto_key_relation_new(0, specific_key, CRYPTO_OBJECT(local_crypto), CRYPTO_OBJECT(remote_crypto), key_material->remote_key_material); + crypto_insert_specific_key_relation(remote_crypto, relation); + CRYPTO_OBJECT_RELEASE(local_crypto); + } + CRYPTO_OBJECT_RELEASE(relation); + } CRYPTO_OBJECT_RELEASE(key_material); } else @@ -1189,8 +1235,7 @@ crypto_factory_set_datawriter_crypto_tokens( remote_datawriter_crypto *remote_writer_crypto; local_datareader_crypto *local_reader_crypto; master_key_material *writer_master_key[2] = {NULL, NULL}; - participant_key_material *keys; - endpoint_relation *relation; + key_relation *relation; uint32_t key_id, i; assert (num_key_mat > 0); @@ -1246,16 +1291,24 @@ crypto_factory_set_datawriter_crypto_tokens( else remote_writer_crypto->writer2reader_key_material[1] = (master_key_material *)CRYPTO_OBJECT_KEEP(writer_master_key[0]); - keys = (participant_key_material *)crypto_object_table_find( - remote_writer_crypto->participant->key_material, CRYPTO_OBJECT_HANDLE(local_reader_crypto->participant)); - assert(keys); - key_id = remote_writer_crypto->writer2reader_key_material[0]->sender_key_id; - relation = crypto_endpoint_relation_new(DDS_SECURITY_DATAWRITER_SUBMESSAGE, key_id, (CryptoObject *)local_reader_crypto, (CryptoObject *)remote_writer_crypto); - crypto_object_table_insert(keys->endpoint_relations, (CryptoObject *)relation); + relation = crypto_key_relation_new(DDS_SECURITY_DATAWRITER_SUBMESSAGE, key_id, (CryptoObject *)local_reader_crypto, (CryptoObject *)remote_writer_crypto, NULL); + crypto_insert_endpoint_relation(remote_writer_crypto->participant, relation); CRYPTO_OBJECT_RELEASE(relation); - CRYPTO_OBJECT_RELEASE(keys); + + uint32_t specific_key = remote_writer_crypto->writer2reader_key_material[0]->receiver_specific_key_id; + if (specific_key != 0) + { + relation = crypto_find_specific_key_relation(remote_writer_crypto->participant, specific_key); + if (!relation) + { + relation = crypto_key_relation_new(0, specific_key, CRYPTO_OBJECT(local_reader_crypto), CRYPTO_OBJECT(remote_writer_crypto), remote_writer_crypto->writer2reader_key_material[0]); + crypto_insert_specific_key_relation(remote_writer_crypto->participant, relation); + } + CRYPTO_OBJECT_RELEASE(relation); + } + result = true; err_inv_local: @@ -1328,8 +1381,7 @@ crypto_factory_set_datareader_crypto_tokens( bool result = false; remote_datareader_crypto *remote_reader_crypto; local_datawriter_crypto *local_writer_crypto; - participant_key_material *keys; - endpoint_relation *relation; + key_relation *relation; uint32_t key_id; remote_reader_crypto = (remote_datareader_crypto *)crypto_object_table_find(impl->crypto_objects, remote_reader_handle); @@ -1373,23 +1425,30 @@ crypto_factory_set_datareader_crypto_tokens( remote_reader_crypto->reader2writer_key_material = crypto_master_key_material_new(CRYPTO_TRANSFORMATION_KIND_NONE); crypto_token_copy(remote_reader_crypto->reader2writer_key_material, key_mat); - keys = (participant_key_material *)crypto_object_table_find( - remote_reader_crypto->participant->key_material, CRYPTO_OBJECT_HANDLE(local_writer_crypto->participant)); - assert(keys); - key_id = remote_reader_crypto->reader2writer_key_material->sender_key_id; - relation = crypto_endpoint_relation_new(DDS_SECURITY_DATAREADER_SUBMESSAGE, key_id, (CryptoObject *)local_writer_crypto, (CryptoObject *)remote_reader_crypto); - crypto_object_table_insert(keys->endpoint_relations, (CryptoObject *)relation); + relation = crypto_key_relation_new(DDS_SECURITY_DATAREADER_SUBMESSAGE, key_id, (CryptoObject *)local_writer_crypto, (CryptoObject *)remote_reader_crypto, NULL); + crypto_insert_endpoint_relation(remote_reader_crypto->participant, relation); CRYPTO_OBJECT_RELEASE(relation); - CRYPTO_OBJECT_RELEASE(keys); + + uint32_t specific_key = remote_reader_crypto->reader2writer_key_material->receiver_specific_key_id; + if (specific_key != 0) + { + relation = crypto_find_specific_key_relation(remote_reader_crypto->participant, specific_key); + if (!relation) + { + relation = crypto_key_relation_new(0, specific_key, CRYPTO_OBJECT(local_writer_crypto), CRYPTO_OBJECT(remote_reader_crypto), remote_reader_crypto->reader2writer_key_material); + crypto_insert_specific_key_relation(remote_reader_crypto->participant, relation); + } + CRYPTO_OBJECT_RELEASE(relation); + } + result = true; err_inv_local: CRYPTO_OBJECT_RELEASE(local_writer_crypto); err_inv_remote: CRYPTO_OBJECT_RELEASE(remote_reader_crypto); - return result; } @@ -1494,7 +1553,7 @@ crypto_factory_get_local_participant_data_key_material( result = true; err_inv_crypto: - CRYPTO_OBJECT_RELEASE(CRYPTO_OBJECT(participant_crypto)); + CRYPTO_OBJECT_RELEASE(participant_crypto); err_no_crypto: return result; } @@ -1587,9 +1646,7 @@ crypto_factory_get_reader_key_material( result = true; } else - { result = get_local_volatile_sec_reader_key_material(impl, writer_id, session_key, protection_kind, ex); - } err_inv_crypto: CRYPTO_OBJECT_RELEASE(reader_crypto); @@ -1656,6 +1713,7 @@ crypto_factory_get_remote_writer_key_material( err_inv_crypto: CRYPTO_OBJECT_RELEASE(writer_crypto); err_no_crypto: + return result; } @@ -1805,25 +1863,6 @@ err_no_crypto: return result; } -struct collect_remote_participant_keys_args -{ - uint32_t key_id; - endpoint_relation *relation; -}; - -/* Currently only collecting the first only */ -static int -collect_remote_participant_keys( - CryptoObject *obj, - void *arg) -{ - participant_key_material *keys = (participant_key_material *)obj; - struct collect_remote_participant_keys_args *info = arg; - - info->relation = crypto_endpoint_relation_find_by_key(keys->endpoint_relations, info->key_id); - return (info->relation) ? 0 : 1; -} - bool crypto_factory_get_endpoint_relation( const dds_security_crypto_key_factory *factory, @@ -1837,20 +1876,20 @@ crypto_factory_get_endpoint_relation( { bool result = false; dds_security_crypto_key_factory_impl *impl = (dds_security_crypto_key_factory_impl *)factory; - remote_participant_crypto *remote_pp_crypto; - local_participant_crypto *local_pp_crypto = NULL; - participant_key_material *keys = NULL; - endpoint_relation *relation = NULL; + remote_participant_crypto *rmt_pp; + local_participant_crypto *loc_pp = NULL; + local_datareader_crypto *loc_rd = NULL; + key_relation *relation = NULL; - remote_pp_crypto = (remote_participant_crypto *)crypto_object_table_find(impl->crypto_objects, remote_participant_handle); - if (!remote_pp_crypto) + rmt_pp = (remote_participant_crypto *)crypto_object_table_find(impl->crypto_objects, remote_participant_handle); + if (!rmt_pp) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); goto invalid_handle; } - else if (!CRYPTO_OBJECT_VALID(remote_pp_crypto, CRYPTO_OBJECT_KIND_REMOTE_CRYPTO)) + else if (!CRYPTO_OBJECT_VALID(rmt_pp, CRYPTO_OBJECT_KIND_REMOTE_CRYPTO)) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, @@ -1858,40 +1897,27 @@ crypto_factory_get_endpoint_relation( goto invalid_handle; } - if (local_participant_handle != DDS_SECURITY_HANDLE_NIL) + if (key_id == 0 && local_participant_handle != DDS_SECURITY_HANDLE_NIL) { - local_pp_crypto = (local_participant_crypto *)crypto_object_table_find(impl->crypto_objects, local_participant_handle); - if (!local_pp_crypto) + loc_pp = (local_participant_crypto *)crypto_object_table_find(impl->crypto_objects, local_participant_handle); + if (!loc_pp) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, - DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, - DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); + DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, + DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); goto invalid_handle; } - else if (!CRYPTO_OBJECT_VALID(local_pp_crypto, CRYPTO_OBJECT_KIND_LOCAL_CRYPTO)) + else if (!CRYPTO_OBJECT_VALID(loc_pp, CRYPTO_OBJECT_KIND_LOCAL_CRYPTO)) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, - DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, - DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); + DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, + DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); goto invalid_handle; } - keys = (participant_key_material *)crypto_object_table_find(remote_pp_crypto->key_material, local_participant_handle); - } - - if (keys) - { - relation = crypto_endpoint_relation_find_by_key(keys->endpoint_relations, key_id); - CRYPTO_OBJECT_RELEASE(keys); - } - else - { - struct collect_remote_participant_keys_args args = {key_id, NULL}; - /* FIXME: Returning arbitrary local-remote relation will not work in Cyclone, - * because participants can have different security settings */ - crypto_object_table_walk(remote_pp_crypto->key_material, collect_remote_participant_keys, &args); - relation = args.relation; + loc_rd = loc_pp->builtin_reader; } + relation = crypto_find_endpoint_relation(rmt_pp, CRYPTO_OBJECT(loc_rd), key_id); if (!relation) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, @@ -1900,6 +1926,8 @@ crypto_factory_get_endpoint_relation( goto invalid_handle; } + assert(key_id == relation->key_id); + *category = relation->kind; *remote_handle = CRYPTO_OBJECT_HANDLE(relation->remote_crypto); *local_handle = CRYPTO_OBJECT_HANDLE(relation->local_crypto); @@ -1907,8 +1935,66 @@ crypto_factory_get_endpoint_relation( invalid_handle: CRYPTO_OBJECT_RELEASE(relation); - CRYPTO_OBJECT_RELEASE(local_pp_crypto); - CRYPTO_OBJECT_RELEASE(remote_pp_crypto); - + CRYPTO_OBJECT_RELEASE(loc_pp); + CRYPTO_OBJECT_RELEASE(rmt_pp); + return result; +} + +bool +crypto_factory_get_specific_keymat( + const dds_security_crypto_key_factory *factory, + CryptoObjectKind_t kind, + DDS_Security_Handle rmt_handle, + const struct receiver_specific_mac * const mac_list, + uint32_t num_mac, + uint32_t *index, + master_key_material **key_mat) +{ + dds_security_crypto_key_factory_impl *impl = (dds_security_crypto_key_factory_impl *)factory; + CryptoObject *obj; + remote_participant_crypto *rmt_pp = NULL; + remote_datawriter_crypto *rmt_wr = NULL; + remote_datareader_crypto *rmt_rd = NULL; + key_relation *relation = NULL; + bool result = false; + + obj = crypto_object_table_find(impl->crypto_objects, rmt_handle); + if (!obj) + return false; + + switch (kind) + { + case CRYPTO_OBJECT_KIND_REMOTE_CRYPTO: + rmt_pp = (remote_participant_crypto *)obj; + break; + case CRYPTO_OBJECT_KIND_REMOTE_WRITER_CRYPTO: + rmt_wr = (remote_datawriter_crypto *)obj; + rmt_pp = rmt_wr->participant; + break; + case CRYPTO_OBJECT_KIND_REMOTE_READER_CRYPTO: + rmt_rd = (remote_datareader_crypto *)obj; + rmt_pp = rmt_rd->participant; + break; + default: + goto invalid_handle; + break; + } + + for (uint32_t i = 0; i < num_mac; i++) + { + uint32_t key_id = CRYPTO_TRANSFORM_ID(mac_list[i].receiver_mac_key_id); + relation = crypto_find_specific_key_relation(rmt_pp, key_id); + if (relation) + { + *index = i; + *key_mat = CRYPTO_OBJECT_KEEP(relation->key_material); + result = true; + break; + } + } + +invalid_handle: + CRYPTO_OBJECT_RELEASE(relation); + CRYPTO_OBJECT_RELEASE(obj); return result; } diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.h b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.h index 2fec8d7..3e49766 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.h +++ b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.h @@ -148,4 +148,14 @@ bool crypto_factory_get_endpoint_relation( DDS_Security_SecureSubmessageCategory_t *category, DDS_Security_SecurityException *ex); +bool +crypto_factory_get_specific_keymat( + const dds_security_crypto_key_factory *factory, + CryptoObjectKind_t kind, + DDS_Security_Handle rmt_handle, + const struct receiver_specific_mac * const mac_list, + uint32_t num_mac, + uint32_t *index, + master_key_material **key_mat); + #endif /* CRYPTO_KEY_FACTORY_H */ diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_objects.c b/src/security/builtin_plugins/cryptographic/src/crypto_objects.c index 86b1ea0..075744e 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_objects.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_objects.c @@ -18,6 +18,64 @@ #include "crypto_objects.h" #include "crypto_utils.h" +static int compare_participant_handle(const void *va, const void *vb); +static int compare_endpoint_relation (const void *va, const void *vb); +static int compare_relation_key (const void *va, const void *vb); +static void key_relation_free(CryptoObject *obj); + +const ddsrt_avl_ctreedef_t loc_pp_keymat_treedef = + DDSRT_AVL_CTREEDEF_INITIALIZER (offsetof (struct participant_key_material, loc_avlnode), offsetof (struct participant_key_material, rmt_pp_handle), compare_participant_handle, 0); + +const ddsrt_avl_ctreedef_t rmt_pp_keymat_treedef = + DDSRT_AVL_CTREEDEF_INITIALIZER (offsetof (struct participant_key_material, rmt_avlnode), offsetof (struct participant_key_material, loc_pp_handle), compare_participant_handle, 0); + +const ddsrt_avl_treedef_t endpoint_relation_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct key_relation, avlnode), 0, compare_endpoint_relation, 0); + +const ddsrt_avl_treedef_t specific_key_treedef = + DDSRT_AVL_TREEDEF_INITIALIZER (offsetof (struct key_relation, avlnode), offsetof (struct key_relation, key_id), compare_relation_key, 0); + + +static int compare_participant_handle(const void *va, const void *vb) +{ + const DDS_Security_ParticipantCryptoHandle *ha = va; + const DDS_Security_ParticipantCryptoHandle *hb = vb; + + if (*ha > *hb) + return 1; + else if (*ha < *hb) + return -1; + return 0; +} + +static int compare_endpoint_relation (const void *va, const void *vb) +{ + const key_relation *ra = va; + const key_relation *rb = vb; + int r; + + r = (int)(ra->key_id - rb->key_id); + if (r != 0 || ra->local_crypto == 0 || rb->local_crypto == 0) + { + return r; + } + + if (ra->local_crypto > rb->local_crypto) + return 1; + else if (ra->local_crypto < rb->local_crypto) + return -1; + else + return 0; +} + +static int compare_relation_key (const void *va, const void *vb) +{ + const uint32_t *ka = va; + const uint32_t *kb = vb; + + return (int)(*ka - *kb); +} + bool crypto_object_valid(CryptoObject *obj, CryptoObjectKind_t kind) { return (obj && obj->kind == kind && obj->handle == (int64_t)(uintptr_t)obj); @@ -57,16 +115,15 @@ static void crypto_object_deinit(CryptoObject *obj) void crypto_object_free(CryptoObject *obj) { + if (obj && obj->destructor) obj->destructor(obj); } -CryptoObject * crypto_object_keep(CryptoObject *obj) +void * crypto_object_keep(CryptoObject *obj) { if (obj) - { ddsrt_atomic_inc32(&obj->refcount); - } return obj; } @@ -76,26 +133,6 @@ void crypto_object_release(CryptoObject *obj) crypto_object_free(obj); } -static uint32_t participant_key_material_hash(const void *obj) -{ - const participant_key_material *object = obj; - return (uint32_t)object->pp_local_handle; -} - -static int participant_key_material_equal(const void *ha, const void *hb) -{ - const participant_key_material *la = ha; - const participant_key_material *lb = hb; - return la->pp_local_handle == lb->pp_local_handle; -} - -static CryptoObject * participant_key_material_find(const struct CryptoObjectTable *table, const void *arg) -{ - struct participant_key_material template; - template.pp_local_handle = *(int64_t *)arg; - return crypto_object_table_find_by_template(table, &template); -} - CryptoObject * crypto_object_table_find_by_template(const struct CryptoObjectTable *table, const void *template) { return (CryptoObject *)ddsrt_hh_lookup(table->htab, template); @@ -301,7 +338,7 @@ session_key_material * crypto_session_key_material_new(master_key_material *mast session->init_vector_suffix = crypto_get_random_uint64(); session->max_blocks_per_session = INT64_MAX; /* FIXME: should be a config parameter */ session->block_counter = session->max_blocks_per_session; - session->master_key_material = (master_key_material *)CRYPTO_OBJECT_KEEP(master_key); + session->master_key_material = CRYPTO_OBJECT_KEEP(master_key); return session; } @@ -321,7 +358,9 @@ static void local_participant_crypto__free(CryptoObject *obj) CHECK_CRYPTO_OBJECT_KIND (obj, CRYPTO_OBJECT_KIND_LOCAL_CRYPTO); CRYPTO_OBJECT_RELEASE (participant_crypto->session); CRYPTO_OBJECT_RELEASE (participant_crypto->key_material); + ddsrt_avl_cfree(&loc_pp_keymat_treedef, &participant_crypto->key_material_table, 0); crypto_object_deinit ((CryptoObject *)participant_crypto); + ddsrt_mutex_init(&participant_crypto->lock); ddsrt_free (participant_crypto); } } @@ -333,6 +372,9 @@ local_participant_crypto * crypto_local_participant_crypto__new(DDS_Security_Ide local_participant_crypto *participant_crypto = ddsrt_calloc (1, sizeof(*participant_crypto)); participant_crypto->identity_handle = participant_identity; crypto_object_init ((CryptoObject *)participant_crypto, CRYPTO_OBJECT_KIND_LOCAL_CRYPTO, local_participant_crypto__free); + ddsrt_mutex_init(&participant_crypto->lock); + ddsrt_avl_cinit(&loc_pp_keymat_treedef, &participant_crypto->key_material_table); + return participant_crypto; } @@ -344,8 +386,11 @@ static void remote_participant_crypto__free(CryptoObject *obj) if (participant_crypto) { CRYPTO_OBJECT_RELEASE (participant_crypto->session); - crypto_object_table_free (participant_crypto->key_material); + ddsrt_avl_cfree(&rmt_pp_keymat_treedef, &participant_crypto->key_material_table, 0); crypto_object_deinit ((CryptoObject *)participant_crypto); + ddsrt_avl_free(&endpoint_relation_treedef, &participant_crypto->relation_index, 0); + ddsrt_avl_free(&specific_key_treedef, &participant_crypto->specific_key_index, 0); + ddsrt_mutex_destroy(&participant_crypto->lock); ddsrt_free(participant_crypto); } } @@ -356,7 +401,10 @@ remote_participant_crypto * crypto_remote_participant_crypto__new(DDS_Security_I remote_participant_crypto *participant_crypto = ddsrt_calloc (1, sizeof(*participant_crypto)); crypto_object_init ((CryptoObject *)participant_crypto, CRYPTO_OBJECT_KIND_REMOTE_CRYPTO, remote_participant_crypto__free); participant_crypto->identity_handle = participant_identity; - participant_crypto->key_material = crypto_object_table_new (participant_key_material_hash, participant_key_material_equal, participant_key_material_find); + ddsrt_avl_cinit(&rmt_pp_keymat_treedef, &participant_crypto->key_material_table); + ddsrt_mutex_init(&participant_crypto->lock); + ddsrt_avl_init(&endpoint_relation_treedef, &participant_crypto->relation_index); + ddsrt_avl_init(&specific_key_treedef, &participant_crypto->specific_key_index); return participant_crypto; } @@ -373,29 +421,129 @@ static void participant_key_material_free(CryptoObject *obj) CRYPTO_OBJECT_RELEASE(keymaterial->P2P_kx_key_material); CRYPTO_OBJECT_RELEASE(keymaterial->local_P2P_key_material); CRYPTO_OBJECT_RELEASE(keymaterial->remote_key_material); - crypto_object_table_free(keymaterial->endpoint_relations); crypto_object_deinit((CryptoObject *)keymaterial); ddsrt_free(keymaterial); } } -participant_key_material * crypto_participant_key_material_new(const local_participant_crypto *pplocal) +participant_key_material * crypto_participant_key_material_new(const local_participant_crypto *loc_pp_crypto, const remote_participant_crypto *rmt_pp_crypto) { participant_key_material *keymaterial = ddsrt_calloc(1, sizeof(*keymaterial)); crypto_object_init((CryptoObject *)keymaterial, CRYPTO_OBJECT_KIND_PARTICIPANT_KEY_MATERIAL, participant_key_material_free); - keymaterial->pp_local_handle = pplocal->_parent.handle; - keymaterial->endpoint_relations = crypto_object_table_new(NULL, NULL, NULL); + keymaterial->loc_pp_handle = PARTICIPANT_CRYPTO_HANDLE(loc_pp_crypto); + keymaterial->rmt_pp_handle = PARTICIPANT_CRYPTO_HANDLE(rmt_pp_crypto); keymaterial->local_P2P_key_material = crypto_master_key_material_new(CRYPTO_TRANSFORMATION_KIND_NONE); keymaterial->P2P_kx_key_material = crypto_master_key_material_new(CRYPTO_TRANSFORMATION_KIND_AES256_GCM); /* as defined in table 67 of the DDS Security spec v1.1 */ return keymaterial; } -static void endpoint_relation_free(CryptoObject *obj) +void crypto_local_participant_add_keymat(local_participant_crypto *loc_pp_crypto, participant_key_material *keymat) { - endpoint_relation *relation = (endpoint_relation *)obj; + ddsrt_mutex_lock(&loc_pp_crypto->lock); + ddsrt_avl_cinsert(&loc_pp_keymat_treedef, &loc_pp_crypto->key_material_table, CRYPTO_OBJECT_KEEP(keymat)); + ddsrt_mutex_unlock(&loc_pp_crypto->lock); +} + +participant_key_material * crypto_local_participant_remove_keymat(local_participant_crypto *loc_pp_crypto, DDS_Security_ParticipantCryptoHandle rmt_pp_handle) +{ + participant_key_material *keymat; + ddsrt_avl_dpath_t dpath; + + ddsrt_mutex_lock(&loc_pp_crypto->lock); + keymat = ddsrt_avl_clookup_dpath(&loc_pp_keymat_treedef, &loc_pp_crypto->key_material_table, &rmt_pp_handle, &dpath); + if (keymat) + ddsrt_avl_cdelete_dpath(&loc_pp_keymat_treedef, &loc_pp_crypto->key_material_table, keymat, &dpath); + ddsrt_mutex_unlock(&loc_pp_crypto->lock); + + return keymat; +} + +participant_key_material * crypto_local_participant_lookup_keymat(local_participant_crypto *loc_pp_crypto, DDS_Security_ParticipantCryptoHandle rmt_pp_handle) +{ + participant_key_material *keymat; + + ddsrt_mutex_lock(&loc_pp_crypto->lock); + keymat = CRYPTO_OBJECT_KEEP(ddsrt_avl_clookup(&loc_pp_keymat_treedef, &loc_pp_crypto->key_material_table, &rmt_pp_handle)); + ddsrt_mutex_unlock(&loc_pp_crypto->lock); + + return keymat; +} + +void crypto_remote_participant_add_keymat(remote_participant_crypto *rmt_pp_crypto, participant_key_material *keymat) +{ + ddsrt_mutex_lock(&rmt_pp_crypto->lock); + ddsrt_avl_cinsert(&rmt_pp_keymat_treedef, &rmt_pp_crypto->key_material_table, CRYPTO_OBJECT_KEEP(keymat)); + ddsrt_mutex_unlock(&rmt_pp_crypto->lock); +} + +participant_key_material * crypto_remote_participant_remove_keymat(remote_participant_crypto *rmt_pp_crypto, DDS_Security_ParticipantCryptoHandle loc_pp_handle) +{ + participant_key_material *keymat; + ddsrt_avl_dpath_t dpath; + + ddsrt_mutex_lock(&rmt_pp_crypto->lock); + keymat = ddsrt_avl_clookup_dpath(&rmt_pp_keymat_treedef, &rmt_pp_crypto->key_material_table, &loc_pp_handle, &dpath); + if (keymat) + ddsrt_avl_cdelete_dpath(&rmt_pp_keymat_treedef, &rmt_pp_crypto->key_material_table, keymat, &dpath); + ddsrt_mutex_unlock(&rmt_pp_crypto->lock); + + return keymat; +} + +participant_key_material * crypto_remote_participant_lookup_keymat(remote_participant_crypto *rmt_pp_crypto, DDS_Security_ParticipantCryptoHandle loc_pp_handle) +{ + participant_key_material *keymat; + + ddsrt_mutex_lock(&rmt_pp_crypto->lock); + keymat = CRYPTO_OBJECT_KEEP(ddsrt_avl_clookup(&rmt_pp_keymat_treedef, &rmt_pp_crypto->key_material_table, &loc_pp_handle)); + ddsrt_mutex_unlock(&rmt_pp_crypto->lock); + + return keymat; +} + +size_t crypto_local_participnant_get_matching(local_participant_crypto *loc_pp_crypto, DDS_Security_ParticipantCryptoHandle **handles) +{ + participant_key_material *keymat; + ddsrt_avl_citer_t it; + size_t num, i; + + ddsrt_mutex_lock(&loc_pp_crypto->lock); + num = ddsrt_avl_ccount(&loc_pp_crypto->key_material_table); + if (num > 0) + { + *handles = ddsrt_malloc(num * sizeof(DDS_Security_ParticipantCryptoHandle)); + for (i = 0, keymat = ddsrt_avl_citer_first(&loc_pp_keymat_treedef, &loc_pp_crypto->key_material_table, &it); i < num && keymat; i++, keymat = ddsrt_avl_citer_next(&it)) + (*handles)[i] = keymat->rmt_pp_handle; + } + ddsrt_mutex_unlock(&loc_pp_crypto->lock); + return num; +} + +size_t crypto_remote_participnant_get_matching(remote_participant_crypto *rmt_pp_crypto, DDS_Security_ParticipantCryptoHandle **handles) +{ + participant_key_material *keymat; + ddsrt_avl_citer_t it; + size_t num, i; + + ddsrt_mutex_lock(&rmt_pp_crypto->lock); + num = ddsrt_avl_ccount(&rmt_pp_crypto->key_material_table); + if (num > 0) + { + *handles = ddsrt_malloc(num * sizeof(DDS_Security_ParticipantCryptoHandle)); + for (i = 0, keymat = ddsrt_avl_citer_first(&rmt_pp_keymat_treedef, &rmt_pp_crypto->key_material_table, &it); i < num && keymat; i++, keymat = ddsrt_avl_citer_next(&it)) + (*handles)[i] = keymat->loc_pp_handle; + } + ddsrt_mutex_unlock(&rmt_pp_crypto->lock); + return num; +} + +static void key_relation_free(CryptoObject *obj) +{ + key_relation *relation = (key_relation *)obj; if (relation) { + CRYPTO_OBJECT_RELEASE(relation->key_material); CRYPTO_OBJECT_RELEASE(relation->local_crypto); CRYPTO_OBJECT_RELEASE(relation->remote_crypto); crypto_object_deinit((CryptoObject *)relation); @@ -403,16 +551,17 @@ static void endpoint_relation_free(CryptoObject *obj) } } -endpoint_relation * crypto_endpoint_relation_new(DDS_Security_SecureSubmessageCategory_t kind, - uint32_t key_id, CryptoObject *local_crypto, CryptoObject *remote_crypto) +key_relation * crypto_key_relation_new(DDS_Security_SecureSubmessageCategory_t kind, + uint32_t key_id, CryptoObject *local_crypto, CryptoObject *remote_crypto, master_key_material *keymat) { - endpoint_relation *relation = ddsrt_malloc(sizeof(*relation)); - crypto_object_init((CryptoObject *)relation, CRYPTO_OBJECT_KIND_ENDPOINT_RELATION, endpoint_relation_free); + key_relation *relation = ddsrt_malloc(sizeof(*relation)); + crypto_object_init((CryptoObject *)relation, CRYPTO_OBJECT_KIND_RELATION, key_relation_free); relation->kind = kind; relation->key_id = key_id; relation->local_crypto = CRYPTO_OBJECT_KEEP(local_crypto); relation->remote_crypto = CRYPTO_OBJECT_KEEP(remote_crypto); + relation->key_material = (master_key_material *)CRYPTO_OBJECT_KEEP(keymat); return relation; } @@ -539,60 +688,90 @@ remote_datareader_crypto *crypto_remote_datareader_crypto__new(const remote_part return reader_crypto; } - -typedef struct endpoint_relation_find_arg +void crypto_insert_endpoint_relation( + remote_participant_crypto *rpc, + key_relation *relation) { - CryptoObject *found; - CryptoObject *local_crypto; - CryptoObject *remote_crypto; - uint32_t key_id; -} endpoint_relation_find_arg; + ddsrt_mutex_lock(&rpc->lock); + ddsrt_avl_insert(&endpoint_relation_treedef, &rpc->relation_index, CRYPTO_OBJECT_KEEP(relation)); + ddsrt_mutex_unlock(&rpc->lock); +} -static int endpoint_relation_cmp_key(CryptoObject *obj, void *arg) +void crypto_remove_endpoint_relation( + remote_participant_crypto *rpc, + CryptoObject *lch, + uint32_t key_id) { - const endpoint_relation *rel = (const endpoint_relation *)obj; - endpoint_relation_find_arg *find_arg = (endpoint_relation_find_arg *)arg; + key_relation template; + key_relation *relation; + ddsrt_avl_dpath_t dpath; - if (rel->key_id == find_arg->key_id) + template.key_id = key_id; + template.local_crypto = lch; + + ddsrt_mutex_lock(&rpc->lock); + relation = ddsrt_avl_lookup_dpath(&endpoint_relation_treedef, &rpc->relation_index, &template, &dpath); + if (relation) { - find_arg->found = crypto_object_keep(obj); - return 0; + ddsrt_avl_delete_dpath(&endpoint_relation_treedef, &rpc->relation_index, relation, &dpath); + CRYPTO_OBJECT_RELEASE(relation); } - return 1; + ddsrt_mutex_unlock(&rpc->lock); } -static int endpoint_relation_cmp_crypto(CryptoObject *obj, void *arg) +key_relation * crypto_find_endpoint_relation( + remote_participant_crypto *rpc, + CryptoObject *lch, + uint32_t key_id) { - const endpoint_relation *rel = (const endpoint_relation *)obj; - endpoint_relation_find_arg *find_arg = (endpoint_relation_find_arg *)arg; + key_relation template; + key_relation *relation; - if ((rel->local_crypto == find_arg->local_crypto) && - (rel->remote_crypto == find_arg->remote_crypto)) + template.key_id = key_id; + template.local_crypto = lch; + + ddsrt_mutex_lock(&rpc->lock); + relation = CRYPTO_OBJECT_KEEP(ddsrt_avl_lookup(&endpoint_relation_treedef, &rpc->relation_index, &template)); + ddsrt_mutex_unlock(&rpc->lock); + + return relation; +} + +void crypto_insert_specific_key_relation( + remote_participant_crypto *rpc, + key_relation *relation) +{ + ddsrt_mutex_lock(&rpc->lock); + ddsrt_avl_insert(&specific_key_treedef, &rpc->specific_key_index, CRYPTO_OBJECT_KEEP(relation)); + ddsrt_mutex_unlock(&rpc->lock); +} + +void crypto_remove_specific_key_relation( + remote_participant_crypto *rpc, + uint32_t key_id) +{ + key_relation *relation; + ddsrt_avl_dpath_t dpath; + + ddsrt_mutex_lock(&rpc->lock); + relation = ddsrt_avl_lookup_dpath(&specific_key_treedef, &rpc->specific_key_index, &key_id, &dpath); + if (relation) { - find_arg->found = crypto_object_keep(obj); - return 0; + ddsrt_avl_delete_dpath(&specific_key_treedef, &rpc->specific_key_index, relation, &dpath); + CRYPTO_OBJECT_RELEASE(relation); } - return 1; + ddsrt_mutex_unlock(&rpc->lock); } -endpoint_relation * crypto_endpoint_relation_find_by_key(struct CryptoObjectTable *table, uint32_t key_id) +key_relation * crypto_find_specific_key_relation( + remote_participant_crypto *rpc, + uint32_t key_id) { - endpoint_relation_find_arg find_arg; - find_arg.found = NULL; - find_arg.key_id = key_id; - find_arg.local_crypto = NULL; - find_arg.remote_crypto = NULL; - crypto_object_table_walk(table, endpoint_relation_cmp_key, &find_arg); - return (endpoint_relation *)(find_arg.found); -} + key_relation *relation; -endpoint_relation * crypto_endpoint_relation_find_by_crypto(struct CryptoObjectTable *table, CryptoObject *local_crypto, CryptoObject *remote_crypto) -{ - endpoint_relation_find_arg find_arg; - find_arg.found = NULL; - find_arg.key_id = 0; - find_arg.local_crypto = local_crypto; - find_arg.remote_crypto = remote_crypto; - crypto_object_table_walk(table, endpoint_relation_cmp_crypto, &find_arg); - return (endpoint_relation *)(find_arg.found); + ddsrt_mutex_lock(&rpc->lock); + relation = CRYPTO_OBJECT_KEEP(ddsrt_avl_lookup(&specific_key_treedef, &rpc->specific_key_index, &key_id)); + ddsrt_mutex_unlock(&rpc->lock); + + return relation; } diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_objects.h b/src/security/builtin_plugins/cryptographic/src/crypto_objects.h index 9a55570..0ef700b 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_objects.h +++ b/src/security/builtin_plugins/cryptographic/src/crypto_objects.h @@ -16,6 +16,8 @@ #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/sync.h" #include "dds/ddsrt/types.h" +#include "dds/ddsrt/avl.h" +#include "dds/ddsrt/sync.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_utils.h" #include "crypto_defs.h" @@ -38,6 +40,7 @@ #define CRYPTO_TRANSFORM_HAS_KEYS(k) ((k) != CRYPTO_TRANSFORMATION_KIND_NONE && (k) != CRYPTO_TRANSFORMATION_KIND_INVALID) + typedef DDS_Security_ParticipantCryptoHandle DDS_Security_LocalParticipantCryptoHandle; typedef DDS_Security_ParticipantCryptoHandle DDS_Security_RemoteParticipantCryptoHandle; @@ -53,7 +56,7 @@ typedef enum CRYPTO_OBJECT_KIND_KEY_MATERIAL, CRYPTO_OBJECT_KIND_SESSION_KEY_MATERIAL, CRYPTO_OBJECT_KIND_PARTICIPANT_KEY_MATERIAL, - CRYPTO_OBJECT_KIND_ENDPOINT_RELATION + CRYPTO_OBJECT_KIND_RELATION } CryptoObjectKind_t; typedef struct CryptoObject CryptoObject; @@ -103,44 +106,54 @@ typedef struct remote_session_info crypto_session_key_t key; } remote_session_info; -typedef struct endpoint_relation +typedef struct key_relation { CryptoObject _parent; + ddsrt_avl_node_t avlnode; DDS_Security_SecureSubmessageCategory_t kind; uint32_t key_id; CryptoObject *local_crypto; CryptoObject *remote_crypto; -} endpoint_relation; + master_key_material *key_material; +} key_relation; typedef struct local_participant_crypto { CryptoObject _parent; + ddsrt_mutex_t lock; master_key_material *key_material; DDS_Security_IdentityHandle identity_handle; + ddsrt_avl_ctree_t key_material_table; session_key_material *session; DDS_Security_ProtectionKind rtps_protection_kind; + struct local_datareader_crypto *builtin_reader; } local_participant_crypto; typedef struct participant_key_material { CryptoObject _parent; - DDS_Security_ParticipantCryptoHandle pp_local_handle; + ddsrt_avl_node_t loc_avlnode; + ddsrt_avl_node_t rmt_avlnode; + DDS_Security_ParticipantCryptoHandle loc_pp_handle; + DDS_Security_ParticipantCryptoHandle rmt_pp_handle; master_key_material *remote_key_material; master_key_material *local_P2P_key_material; master_key_material *P2P_kx_key_material; session_key_material *P2P_writer_session; session_key_material *P2P_reader_session; - struct CryptoObjectTable *endpoint_relations; } participant_key_material; typedef struct remote_participant_crypto { CryptoObject _parent; + ddsrt_mutex_t lock; DDS_Security_GUID_t remoteGuid; DDS_Security_IdentityHandle identity_handle; - struct CryptoObjectTable *key_material; + ddsrt_avl_ctree_t key_material_table; session_key_material *session; DDS_Security_ProtectionKind rtps_protection_kind; + ddsrt_avl_tree_t relation_index; + ddsrt_avl_tree_t specific_key_index; } remote_participant_crypto; typedef struct local_datawriter_crypto @@ -223,28 +236,45 @@ void crypto_object_init( CryptoObjectKind_t kind, CryptoObjectDestructor destructor); -endpoint_relation * -crypto_endpoint_relation_new( +key_relation * +crypto_key_relation_new( DDS_Security_SecureSubmessageCategory_t kind, uint32_t key_id, CryptoObject *local_crypto, - CryptoObject *remote_crypto); + CryptoObject *remote_crypto, + master_key_material *keymat); -endpoint_relation * -crypto_endpoint_relation_find_by_key( - struct CryptoObjectTable *table, +void +crypto_insert_endpoint_relation( + remote_participant_crypto *rpc, + key_relation *relation); + +void +crypto_remove_endpoint_relation( + remote_participant_crypto *rpc, + CryptoObject *lch, uint32_t key_id); -endpoint_relation * -crypto_endpoint_relation_find_by_crypto( - struct CryptoObjectTable *table, - CryptoObject *local_crypto, - CryptoObject *remote_crypto); +key_relation * +crypto_find_endpoint_relation( + remote_participant_crypto *rpc, + CryptoObject *lch, + uint32_t key_id); -bool endpoint_relation_get_locals( - const endpoint_relation *relation, - const local_participant_crypto *participant, - DDS_Security_HandleSeq *list); +void +crypto_insert_specific_key_relation( + remote_participant_crypto *rpc, + key_relation *relation); + +void +crypto_remove_specific_key_relation( + remote_participant_crypto *rpc, + uint32_t key_id); + +key_relation * +crypto_find_specific_key_relation( + remote_participant_crypto *rpc, + uint32_t key_id); local_datawriter_crypto * crypto_local_datawriter_crypto__new( @@ -272,7 +302,7 @@ crypto_remote_datawriter_crypto__new( DDS_Security_BasicProtectionKind data_protection, local_datareader_crypto *local_reader); -CryptoObject * +void * crypto_object_keep( CryptoObject *obj); @@ -296,7 +326,8 @@ crypto_remote_participant_crypto__new( participant_key_material * crypto_participant_key_material_new( - const local_participant_crypto *pplocal); + const local_participant_crypto *loc_pp_crypto, + const remote_participant_crypto *rmt_pp_crypto); struct CryptoObjectTable; @@ -351,4 +382,44 @@ void crypto_object_table_walk( CryptoObjectTableCallback callback, void *arg); +void +crypto_local_participant_add_keymat( + local_participant_crypto *loc_pp_crypte, + participant_key_material *keymat); + +participant_key_material * +crypto_local_participant_remove_keymat( + local_participant_crypto *loc_pp_crypte, + DDS_Security_ParticipantCryptoHandle rmt_pp_handle); + +participant_key_material * +crypto_local_participant_lookup_keymat( + local_participant_crypto *loc_pp_crypte, + DDS_Security_ParticipantCryptoHandle rmt_pp_handle); + +void +crypto_remote_participant_add_keymat( + remote_participant_crypto *rmt_pp_crypte, + participant_key_material *keymat); + +participant_key_material * +crypto_remote_participant_remove_keymat( + remote_participant_crypto *rmt_pp_crypte, + DDS_Security_ParticipantCryptoHandle loc_pp_handle); + +participant_key_material * +crypto_remote_participant_lookup_keymat( + remote_participant_crypto *rmt_pp_crypte, + DDS_Security_ParticipantCryptoHandle loc_pp_handle); + +size_t +crypto_local_participnant_get_matching( + local_participant_crypto *loc_pp_crypto, + DDS_Security_ParticipantCryptoHandle **handles); + +size_t +crypto_remote_participnant_get_matching( + remote_participant_crypto *rmt_pp_crypto, + DDS_Security_ParticipantCryptoHandle **handles); + #endif /* CRYPTO_OBJECTS_H */ diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_transform.c b/src/security/builtin_plugins/cryptographic/src/crypto_transform.c index 0088f94..7fd39d6 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_transform.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_transform.c @@ -68,12 +68,6 @@ struct crypto_contents_ref unsigned char *_data; }; -struct receiver_specific_mac -{ - DDS_Security_CryptoTransformKeyId receiver_mac_key_id; - crypto_hmac_t receiver_mac; -}; - struct receiver_specific_mac_seq { uint32_t _length; @@ -1467,64 +1461,73 @@ enc_dr_submsg_inv_args: return result; } -static DDS_Security_boolean +static bool check_reader_specific_mac( + dds_security_crypto_key_factory *factory, struct crypto_header *header, struct crypto_footer *footer, - master_key_material *key_material, + CryptoObjectKind_t kind, + DDS_Security_Handle rmt_handle, const char *context, DDS_Security_SecurityException *ex) { + bool result = false; + master_key_material *keymat = NULL; + uint32_t index; uint32_t session_id; crypto_session_key_t key; crypto_hmac_t *href = NULL; crypto_hmac_t hmac; - uint32_t i; - if (key_material->receiver_specific_key_id == 0) + if (footer->receiver_specific_macs._length == 0) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_RECEIVER_SIGN_CODE, 0, - "%s: don't have receiver key material to check specific mac", context); + "%s: message does not contain a receiver specific mac", context); return false; } - session_id = CRYPTO_TRANSFORM_ID(header->session_id); - for (i = 0; !href && (i < footer->receiver_specific_macs._length); i++) + if (!crypto_factory_get_specific_keymat(factory, kind, rmt_handle, &footer->receiver_specific_macs._buffer[0], footer->receiver_specific_macs._length, &index, &keymat)) { - uint32_t id = CRYPTO_TRANSFORM_ID(footer->receiver_specific_macs._buffer[i].receiver_mac_key_id); - - if (id == key_material->receiver_specific_key_id) - href = &footer->receiver_specific_macs._buffer[i].receiver_mac; + DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_RECEIVER_SIGN_CODE, 0, + "%s: message does not contain a known receiver specific key", context); + goto check_failed; } + href = &footer->receiver_specific_macs._buffer[index].receiver_mac; if (!href) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_RECEIVER_SIGN_CODE, 0, "%s: message does not contain receiver specific mac", context); - return false; + goto check_failed; } - if (!crypto_calculate_receiver_specific_key(&key, session_id, key_material->master_salt, key_material->master_receiver_specific_key, key_material->transformation_kind, ex)) + session_id = CRYPTO_TRANSFORM_ID(header->session_id); + if (!crypto_calculate_receiver_specific_key(&key, session_id, keymat->master_salt, keymat->master_receiver_specific_key, keymat->transformation_kind, ex)) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_RECEIVER_SIGN_CODE, 0, "%s: failed to calculate receiver specific session key", context); - return false; + goto check_failed; } - if (!crypto_cipher_encrypt_data(&key, crypto_get_key_size(key_material->transformation_kind), header->session_id, NULL, 0, footer->common_mac.data, CRYPTO_HMAC_SIZE, NULL, NULL, &hmac, ex)) + if (!crypto_cipher_encrypt_data(&key, crypto_get_key_size(keymat->transformation_kind), header->session_id, NULL, 0, footer->common_mac.data, CRYPTO_HMAC_SIZE, NULL, NULL, &hmac, ex)) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_RECEIVER_SIGN_CODE, 0, "%s: failed to calculate receiver specific hmac", context); - return false; + goto check_failed; } if (memcmp(hmac.data, href->data, CRYPTO_HMAC_SIZE) != 0) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_RECEIVER_SIGN_CODE, 0, "%s: message does not contain a valid receiver specific mac", context); - return false; + goto check_failed; } - return true; + + result = true; + +check_failed: + CRYPTO_OBJECT_RELEASE(keymat); + return result; } static DDS_Security_boolean encode_rtps_message_sign ( @@ -1869,7 +1872,7 @@ decode_rtps_message(dds_security_crypto_transform *instance, transform_kind = CRYPTO_TRANSFORM_KIND(header.transform_identifier.transformation_kind); - /* Retrieve key material from sending_participant_crypto and receiving_participant_crypto from factory */ + /* Retrieve key material from sending_participant_crypto and receiving_participant_crypto from factory */ if (!crypto_factory_get_participant_crypto_tokens(factory, receiving_participant_crypto, sending_participant_crypto, &pp_key_material, &remote_protection_kind, ex)) goto fail_tokens; @@ -1878,7 +1881,7 @@ decode_rtps_message(dds_security_crypto_transform *instance, if (has_origin_authentication(remote_protection_kind)) { /* default governance value */ - if (!check_reader_specific_mac(&header, footer, pp_key_material->remote_key_material, context, ex)) + if (!check_reader_specific_mac(factory, &header, footer, CRYPTO_OBJECT_KIND_REMOTE_CRYPTO, sending_participant_crypto, context, ex)) goto fail_reader_mac; } @@ -2095,7 +2098,7 @@ decode_datawriter_submessage( if (has_origin_authentication(protection_kind)) { - if (!check_reader_specific_mac(&header, footer, writer_master_key, context, ex)) + if (!check_reader_specific_mac(factory, &header, footer, CRYPTO_OBJECT_KIND_REMOTE_WRITER_CRYPTO, writer_crypto, context, ex)) goto fail_reader_mac; } @@ -2137,6 +2140,7 @@ decode_datawriter_submessage( "decode_datawriter_submessage: submessage is signed, which is unexpected"); goto fail_decrypt; } + assert(transform_id != 0); /* When the CryptoHeader indicates that authentication is performed then calculate the HMAC */ if (!crypto_cipher_decrypt_data(&remote_session, header.session_id, NULL, 0, contents._data, contents._length, NULL, 0, &footer->common_mac, ex)) goto fail_decrypt; @@ -2218,7 +2222,7 @@ decode_datareader_submessage( if (has_origin_authentication(protection_kind)) { - if (!check_reader_specific_mac(&header, footer, reader_master_key, context, ex)) + if (!check_reader_specific_mac(factory, &header, footer, CRYPTO_OBJECT_KIND_REMOTE_READER_CRYPTO, reader_crypto, context, ex)) goto fail_reader_mac; } diff --git a/src/security/builtin_plugins/tests/decode_datareader_submessage/src/decode_datareader_submessage_utests.c b/src/security/builtin_plugins/tests/decode_datareader_submessage/src/decode_datareader_submessage_utests.c index 2dab5df..6af6f07 100644 --- a/src/security/builtin_plugins/tests/decode_datareader_submessage/src/decode_datareader_submessage_utests.c +++ b/src/security/builtin_plugins/tests/decode_datareader_submessage/src/decode_datareader_submessage_utests.c @@ -63,11 +63,13 @@ struct crypto_footer unsigned char length[4]; }; +#if 0 struct receiver_specific_mac { DDS_Security_CryptoTransformKeyId receiver_mac_key_id; unsigned char receiver_mac[CRYPTO_HMAC_SIZE]; }; +#endif struct seq_number { @@ -1559,7 +1561,7 @@ CU_Test(ddssec_builtin_decode_datareader_submessage, invalid_data, .init = suite CU_ASSERT(len == 1); rmac = (struct receiver_specific_mac *)(footer + 1); - rmac->receiver_mac[0] = (unsigned char)(rmac->receiver_mac[0] + 1); + rmac->receiver_mac.data[0] = (unsigned char)(rmac->receiver_mac.data[0] + 1); result = crypto->crypto_transform->decode_datareader_submessage( crypto->crypto_transform, diff --git a/src/security/builtin_plugins/tests/decode_datawriter_submessage/src/decode_datawriter_submessage_utests.c b/src/security/builtin_plugins/tests/decode_datawriter_submessage/src/decode_datawriter_submessage_utests.c index 0e700ca..4c297fc 100644 --- a/src/security/builtin_plugins/tests/decode_datawriter_submessage/src/decode_datawriter_submessage_utests.c +++ b/src/security/builtin_plugins/tests/decode_datawriter_submessage/src/decode_datawriter_submessage_utests.c @@ -70,11 +70,13 @@ struct crypto_footer unsigned char length[4]; }; +#if 0 struct receiver_specific_mac { DDS_Security_CryptoTransformKeyId receiver_mac_key_id; unsigned char receiver_mac[CRYPTO_HMAC_SIZE]; }; +#endif static void reset_exception(DDS_Security_SecurityException *ex) { @@ -1579,7 +1581,7 @@ CU_Test(ddssec_builtin_decode_datawriter_submessage, invalid_data, .init = suite CU_ASSERT(len == 1); rmac = (struct receiver_specific_mac *)(footer + 1); - rmac->receiver_mac[0] = (unsigned char)(rmac->receiver_mac[0] + 1); + rmac->receiver_mac.data[0] = (unsigned char)(rmac->receiver_mac.data[0] + 1); result = crypto->crypto_transform->decode_datawriter_submessage( crypto->crypto_transform, diff --git a/src/security/builtin_plugins/tests/decode_rtps_message/src/decode_rtps_message_utests.c b/src/security/builtin_plugins/tests/decode_rtps_message/src/decode_rtps_message_utests.c index ea8a576..0923af3 100644 --- a/src/security/builtin_plugins/tests/decode_rtps_message/src/decode_rtps_message_utests.c +++ b/src/security/builtin_plugins/tests/decode_rtps_message/src/decode_rtps_message_utests.c @@ -75,11 +75,13 @@ struct crypto_footer unsigned char length[4]; }; +#if 0 struct receiver_specific_mac { DDS_Security_CryptoTransformKeyId receiver_mac_key_id; unsigned char receiver_mac[CRYPTO_HMAC_SIZE]; }; +#endif static void reset_exception(DDS_Security_SecurityException *ex) { diff --git a/src/security/builtin_plugins/tests/encode_datareader_submessage/src/encode_datareader_submessage_utests.c b/src/security/builtin_plugins/tests/encode_datareader_submessage/src/encode_datareader_submessage_utests.c index 7d97531..30bacaa 100644 --- a/src/security/builtin_plugins/tests/encode_datareader_submessage/src/encode_datareader_submessage_utests.c +++ b/src/security/builtin_plugins/tests/encode_datareader_submessage/src/encode_datareader_submessage_utests.c @@ -66,11 +66,13 @@ struct crypto_footer uint32_t length; }; +#if 0 struct receiver_specific_mac { DDS_Security_CryptoTransformKeyId receiver_mac_key_id; unsigned char receiver_mac[CRYPTO_HMAC_SIZE]; }; +#endif struct encrypted_data { @@ -744,7 +746,7 @@ static bool check_writer_signing(DDS_Security_DatareaderCryptoHandleSeq *list, s for (i = 0; i < list->_length; i++) { key_id = ddsrt_bswap4u(*(uint32_t *)rmac[i].receiver_mac_key_id); - if (!check_writer_sign(list->_buffer[i], session_id, key_id, key_size, init_vector, footer->common_mac, rmac[i].receiver_mac)) + if (!check_writer_sign(list->_buffer[i], session_id, key_id, key_size, init_vector, footer->common_mac, rmac[i].receiver_mac.data)) { return false; } diff --git a/src/security/builtin_plugins/tests/encode_datawriter_submessage/src/encode_datawriter_submessage_utests.c b/src/security/builtin_plugins/tests/encode_datawriter_submessage/src/encode_datawriter_submessage_utests.c index f7433ac..a186641 100644 --- a/src/security/builtin_plugins/tests/encode_datawriter_submessage/src/encode_datawriter_submessage_utests.c +++ b/src/security/builtin_plugins/tests/encode_datawriter_submessage/src/encode_datawriter_submessage_utests.c @@ -72,11 +72,13 @@ struct crypto_footer uint32_t length; }; +#if 0 struct receiver_specific_mac { DDS_Security_CryptoTransformKeyId receiver_mac_key_id; unsigned char receiver_mac[CRYPTO_HMAC_SIZE]; }; +#endif struct encrypted_data { @@ -742,7 +744,7 @@ static bool check_reader_signing(DDS_Security_DatareaderCryptoHandleSeq *list, s for (i = 0; i < list->_length; i++) { key_id = ddsrt_bswap4u(*(uint32_t *)rmac[i].receiver_mac_key_id); - if (!check_reader_sign(list->_buffer[i], session_id, key_id, key_size, init_vector, footer->common_mac, rmac[i].receiver_mac)) + if (!check_reader_sign(list->_buffer[i], session_id, key_id, key_size, init_vector, footer->common_mac, rmac[i].receiver_mac.data)) { return false; } diff --git a/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c b/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c index bdcbb95..cc6cd22 100644 --- a/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c +++ b/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c @@ -73,11 +73,13 @@ struct crypto_footer uint32_t length; }; +#if 0 struct receiver_specific_mac { DDS_Security_CryptoTransformKeyId receiver_mac_key_id; unsigned char receiver_mac[CRYPTO_HMAC_SIZE]; }; +#endif static void reset_exception(DDS_Security_SecurityException *ex) { @@ -567,32 +569,20 @@ static session_key_material * get_local_participant_session(DDS_Security_Partici return participant_crypto_impl->session; } -static participant_key_material * keymaterial_table_find(struct CryptoObjectTable *table, uint64_t handle) -{ - CryptoObject *object; - assert(table); - - ddsrt_mutex_lock(&table->lock); - object = table->findfnc(table, &handle); - ddsrt_mutex_unlock(&table->lock); - - return (participant_key_material *)object; -} - static master_key_material * get_remote_participant_key_material(DDS_Security_ParticipantCryptoHandle participant_crypto) { participant_key_material *key_material; + master_key_material * master_keymat = NULL; remote_participant_crypto *participant_crypto_impl = (remote_participant_crypto *)participant_crypto; - key_material = (participant_key_material *)keymaterial_table_find(participant_crypto_impl->key_material, (uint64_t) local_particpant_crypto); - if (!key_material) + key_material = crypto_remote_participant_lookup_keymat(participant_crypto_impl, local_particpant_crypto); + if (key_material) { - return NULL; - } - else - { - return key_material->local_P2P_key_material; + master_keymat = key_material->local_P2P_key_material; + CRYPTO_OBJECT_RELEASE(key_material); } + + return master_keymat; } static void set_protection_kind(DDS_Security_ParticipantCryptoHandle participant_crypto, DDS_Security_ProtectionKind protection_kind) @@ -692,7 +682,7 @@ static bool check_signing( for (i = 0; i < list->_length; i++) { key_id = ddsrt_bswap4u(*(uint32_t *)rmac[i].receiver_mac_key_id); - if (!check_sign(list->_buffer[i], session_id, key_id, key_size, init_vector, footer->common_mac, rmac[i].receiver_mac)) + if (!check_sign(list->_buffer[i], session_id, key_id, key_size, init_vector, footer->common_mac, rmac[i].receiver_mac.data)) { return false; } diff --git a/src/security/builtin_plugins/tests/preprocess_secure_submsg/src/preprocess_secure_submsg_utests.c b/src/security/builtin_plugins/tests/preprocess_secure_submsg/src/preprocess_secure_submsg_utests.c index f469a09..62a6973 100644 --- a/src/security/builtin_plugins/tests/preprocess_secure_submsg/src/preprocess_secure_submsg_utests.c +++ b/src/security/builtin_plugins/tests/preprocess_secure_submsg/src/preprocess_secure_submsg_utests.c @@ -663,6 +663,7 @@ CU_Test(ddssec_builtin_preprocess_secure_submsg, invalid_args, .init = suite_pre CU_ASSERT(exception.message != NULL); reset_exception(&exception); + #if 0 /* unknown local_participant_handle */ result = crypto->crypto_transform->preprocess_secure_submsg( crypto->crypto_transform, @@ -681,6 +682,7 @@ CU_Test(ddssec_builtin_preprocess_secure_submsg, invalid_args, .init = suite_pre CU_ASSERT(exception.code != 0); CU_ASSERT(exception.message != NULL); reset_exception(&exception); +#endif /* remote_participant_handle = DDS_SECURITY_HANDLE_NIL */ result = crypto->crypto_transform->preprocess_secure_submsg( diff --git a/src/security/builtin_plugins/tests/register_local_datareader/src/register_local_datareader_utests.c b/src/security/builtin_plugins/tests/register_local_datareader/src/register_local_datareader_utests.c index 5747ac3..503ef14 100644 --- a/src/security/builtin_plugins/tests/register_local_datareader/src/register_local_datareader_utests.c +++ b/src/security/builtin_plugins/tests/register_local_datareader/src/register_local_datareader_utests.c @@ -54,6 +54,14 @@ static void prepare_participant_security_attributes(DDS_Security_ParticipantSecu attributes->plugin_participant_attributes |= DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_RTPS_ENCRYPTED; } +static void reset_exception(DDS_Security_SecurityException *ex) +{ + ex->code = 0; + ex->minor_code = 0; + ddsrt_free(ex->message); + ex->message = NULL; +} + static void suite_register_local_datareader_init(void) { DDS_Security_IdentityHandle participant_identity = 5; //valid dummy value @@ -111,6 +119,14 @@ static void suite_register_local_datareader_init(void) static void suite_register_local_datareader_fini(void) { DDS_Security_SharedSecretHandleImpl *shared_secret_handle_impl = (DDS_Security_SharedSecretHandleImpl *)shared_secret_handle; + DDS_Security_SecurityException exception = {NULL, 0, 0}; + + crypto->crypto_key_factory->unregister_participant(crypto->crypto_key_factory, remote_participant_crypto_handle, &exception); + reset_exception(&exception); + + crypto->crypto_key_factory->unregister_participant(crypto->crypto_key_factory, local_participant_crypto_handle, &exception); + reset_exception(&exception); + unload_plugins(plugins); ddsrt_free(shared_secret_handle_impl->shared_secret); ddsrt_free(shared_secret_handle_impl); @@ -120,13 +136,7 @@ static void suite_register_local_datareader_fini(void) remote_participant_crypto_handle = DDS_SECURITY_HANDLE_NIL; } -static void reset_exception(DDS_Security_SecurityException *ex) -{ - ex->code = 0; - ex->minor_code = 0; - ddsrt_free(ex->message); - ex->message = NULL; -} + static void prepare_endpoint_security_attributes(DDS_Security_EndpointSecurityAttributes *attributes) { diff --git a/src/security/builtin_plugins/tests/register_local_datawriter/src/register_local_datawriter_utests.c b/src/security/builtin_plugins/tests/register_local_datawriter/src/register_local_datawriter_utests.c index 16d13f3..4830f68 100644 --- a/src/security/builtin_plugins/tests/register_local_datawriter/src/register_local_datawriter_utests.c +++ b/src/security/builtin_plugins/tests/register_local_datawriter/src/register_local_datawriter_utests.c @@ -54,6 +54,14 @@ static void prepare_participant_security_attributes(DDS_Security_ParticipantSecu attributes->plugin_participant_attributes |= DDS_SECURITY_PLUGIN_PARTICIPANT_ATTRIBUTES_FLAG_IS_RTPS_ENCRYPTED; } +static void reset_exception(DDS_Security_SecurityException *ex) +{ + ex->code = 0; + ex->minor_code = 0; + ddsrt_free(ex->message); + ex->message = NULL; +} + static void suite_register_local_datawriter_init(void) { DDS_Security_IdentityHandle participant_identity = 5; //valid dummy value @@ -114,6 +122,14 @@ static void suite_register_local_datawriter_init(void) static void suite_register_local_datawriter_fini(void) { + DDS_Security_SecurityException exception = {NULL, 0, 0}; + + crypto->crypto_key_factory->unregister_participant(crypto->crypto_key_factory, remote_participant_crypto_handle, &exception); + reset_exception(&exception); + + crypto->crypto_key_factory->unregister_participant(crypto->crypto_key_factory, local_participant_crypto_handle, &exception); + reset_exception(&exception); + unload_plugins(plugins); shared_secret_handle = DDS_SECURITY_HANDLE_NIL; crypto = NULL; @@ -121,14 +137,6 @@ static void suite_register_local_datawriter_fini(void) remote_participant_crypto_handle = DDS_SECURITY_HANDLE_NIL; } -static void reset_exception(DDS_Security_SecurityException *ex) -{ - ex->code = 0; - ex->minor_code = 0; - ddsrt_free(ex->message); - ex->message = NULL; -} - static void prepare_endpoint_security_attributes(DDS_Security_EndpointSecurityAttributes *attributes) { memset(attributes, 0, sizeof(DDS_Security_EndpointSecurityAttributes)); diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index 039174a..5b46630 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -435,13 +435,13 @@ static void test_data_protection_kind(DDS_Security_ProtectionKind rtps_pk, DDS_S static void test_multiple_readers(size_t n_dom, size_t n_pp, size_t n_rd, DDS_Security_ProtectionKind metadata_pk, DDS_Security_BasicProtectionKind payload_pk) { struct domain_sec_config domain_config = { PK_N, PK_N, PK_N, metadata_pk, payload_pk, NULL }; - test_write_read (&domain_config, n_dom, n_pp, n_rd, 1, 1, 1, NULL); + test_write_read (&domain_config, n_dom, n_pp, n_rd, 1, 1, 1, set_encryption_parameters_basic); } static void test_multiple_writers(size_t n_rd_dom, size_t n_rd, size_t n_wr_dom, size_t n_wr, DDS_Security_ProtectionKind metadata_pk) { struct domain_sec_config domain_config = { PK_N, PK_N, PK_N, metadata_pk, BPK_N, NULL }; - test_write_read (&domain_config, n_rd_dom, 1, n_rd, n_wr_dom, 1, n_wr, NULL); + test_write_read (&domain_config, n_rd_dom, 1, n_rd, n_wr_dom, 1, n_wr, set_encryption_parameters_basic); } static void test_payload_secret(DDS_Security_ProtectionKind rtps_pk, DDS_Security_ProtectionKind metadata_pk, DDS_Security_BasicProtectionKind payload_pk) @@ -544,7 +544,7 @@ CU_TheoryDataPoints(ddssec_secure_communication, multiple_readers) = { CU_DataPoints(size_t, 1, 3, 1, 3), /* number of participants per domain */ CU_DataPoints(size_t, 3, 1, 3, 3), /* number of readers per participant */ }; -CU_Theory((size_t n_dom, size_t n_pp, size_t n_rd), ddssec_secure_communication, multiple_readers, .timeout = 60, .disabled = true) +CU_Theory((size_t n_dom, size_t n_pp, size_t n_rd), ddssec_secure_communication, multiple_readers, .timeout = 60, .disabled = false) { DDS_Security_ProtectionKind metadata_pk[] = { PK_N, PK_SOA, PK_EOA }; DDS_Security_BasicProtectionKind payload_pk[] = { BPK_N, BPK_S, BPK_E }; @@ -563,7 +563,7 @@ CU_TheoryDataPoints(ddssec_secure_communication, multiple_readers_writers) = { CU_DataPoints(size_t, 1, 1, 2), /* number of writer domains */ CU_DataPoints(size_t, 1, 3, 3), /* number of writers per domain */ }; -CU_Theory((size_t n_rd_dom, size_t n_rd, size_t n_wr_dom, size_t n_wr), ddssec_secure_communication, multiple_readers_writers, .timeout = 60, .disabled = true) +CU_Theory((size_t n_rd_dom, size_t n_rd, size_t n_wr_dom, size_t n_wr), ddssec_secure_communication, multiple_readers_writers, .timeout = 60, .disabled = false) { DDS_Security_ProtectionKind metadata_pk[] = { PK_SOA, PK_EOA }; for (size_t metadata = 0; metadata < sizeof (metadata_pk) / sizeof (metadata_pk[0]); metadata++) From 9175f44273153172d3a6829ccccc20047742dc93 Mon Sep 17 00:00:00 2001 From: Marcel Jordense Date: Thu, 26 Mar 2020 18:51:01 +0100 Subject: [PATCH 138/238] Send crypto tokens after handshake is completely finished Signed-off-by: Marcel Jordense --- .../ddsi/include/dds/ddsi/ddsi_security_omg.h | 16 +++++++ src/core/ddsi/src/ddsi_security_omg.c | 43 +++++++++++++++---- src/core/ddsi/src/q_entity.c | 3 +- .../cryptographic/src/crypto_key_factory.c | 24 +++++++++++ .../cryptographic/src/crypto_key_factory.h | 7 +++ .../src/encode_rtps_message_utests.c | 14 +----- 6 files changed, 86 insertions(+), 21 deletions(-) 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 7eaaee1..dc63d5a 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h @@ -64,6 +64,7 @@ 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; }; @@ -85,6 +86,7 @@ struct proxypp_pp_match { DDS_Security_ParticipantCryptoHandle pp_crypto_handle; DDS_Security_PermissionsHandle permissions_handle; DDS_Security_SharedSecretHandle shared_secret; + bool authenticated; }; struct participant_sec_attributes { @@ -558,6 +560,20 @@ bool q_omg_security_remote_participant_is_initialized(struct proxy_participant * */ bool q_omg_security_register_remote_participant(struct participant *pp, struct proxy_participant *proxypp, int64_t shared_secret); +/** + * @brief Sets the matching participant and proxy participant as authorized. + * + * When the authentication handshake has finished successfully and the + * volatile secure readers and writers are matched then with this function + * the matching local and remote participant are set to authenticated which + * allows the crypto tokens to be exchanged and the corresponding entities + * be matched. + * + * @param[in] pp The participant. + * @param[in] proxypp The proxy participant. + */ +void q_omg_security_set_remote_participant_authenticated(struct participant *pp, struct proxy_participant *proxypp); + /** * @brief Removes a registered proxy participant from administation of the authentication, * access control and crypto plugins. diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 40768d9..70b2b93 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -378,6 +378,7 @@ static struct proxypp_pp_match * proxypp_pp_match_new(struct participant *pp, DD pm->pp_crypto_handle = pp->sec_attr->crypto_handle; pm->permissions_handle = permissions_hdl; pm->shared_secret = shared_secret; + pm->authenticated = false; return pm; } @@ -1753,6 +1754,37 @@ register_failed: return ret; } +void q_omg_security_set_remote_participant_authenticated(struct participant *pp, struct proxy_participant *proxypp) +{ + struct proxypp_pp_match *pm; + + ddsrt_mutex_lock(&proxypp->sec_attr->lock); + pm = ddsrt_avl_lookup(&proxypp_pp_treedef, &proxypp->sec_attr->participants, &pp->sec_attr->crypto_handle); + if (pm) + pm->authenticated = true; + ddsrt_mutex_unlock(&proxypp->sec_attr->lock); +} + +static bool is_volatile_secure_endpoint(ddsi_entityid_t entityid) +{ + return ((entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER) || (entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER)); +} + +static struct proxypp_pp_match * get_pp_proxypp_match_if_authenticated(struct participant *pp, struct proxy_participant *proxypp, ddsi_entityid_t entityid) +{ + struct proxypp_pp_match *pm; + + ddsrt_mutex_lock(&proxypp->sec_attr->lock); + pm = ddsrt_avl_lookup(&proxypp_pp_treedef, &proxypp->sec_attr->participants, &pp->sec_attr->crypto_handle); + if (pm) + { + if (!pm->authenticated && !is_volatile_secure_endpoint(entityid)) + pm = NULL; + } + ddsrt_mutex_unlock(&proxypp->sec_attr->lock); + return pm; +} + void q_omg_security_deregister_remote_participant(struct proxy_participant *proxypp) { struct ddsi_domaingv *gv = proxypp->e.gv; @@ -2028,11 +2060,9 @@ static bool q_omg_security_register_remote_writer_match(struct proxy_writer *pwr struct security_entity_match *match; bool send_tokens = false; - 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); + *crypto_handle = 0; - if (!pm) + if ((pm = 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. @@ -2380,10 +2410,7 @@ static bool q_omg_security_register_remote_reader_match(struct proxy_reader *prd *crypto_handle = 0; - 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); - if (!pm) + if ((pm = 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. diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 242cb28..23a64a9 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -3620,7 +3620,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se assert ((wr->xqos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL) || (wr->e.guid.entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER)); } - wr->handle_as_transient_local = (wr->xqos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL); + wr->handle_as_transient_local = (wr->xqos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL || wr->e.guid.entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER); wr->include_keyhash = wr->e.gv->config.generate_keyhash && ((wr->e.guid.entityid.u & NN_ENTITYID_KIND_MASK) == NN_ENTITYID_KIND_WRITER_WITH_KEY); @@ -4773,6 +4773,7 @@ void handshake_end_cb(struct ddsi_handshake *handshake, struct participant *pp, DDS_CLOG (DDS_LC_DISCOVERY, &gv->logconfig, "handshake (lguid="PGUIDFMT" rguid="PGUIDFMT") processed\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid)); if (q_omg_security_register_remote_participant(pp, proxypp, shared_secret)) { match_volatile_secure_endpoints(pp, proxypp); + q_omg_security_set_remote_participant_authenticated(pp, proxypp); } break; diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c index 02ba273..ab75a63 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c @@ -1998,3 +1998,27 @@ invalid_handle: CRYPTO_OBJECT_RELEASE(obj); return result; } + +master_key_material * +crypto_factory_get_master_key_material_for_test( + const dds_security_crypto_key_factory *factory, + DDS_Security_ParticipantCryptoHandle local_id, + DDS_Security_ParticipantCryptoHandle remote_id) +{ + dds_security_crypto_key_factory_impl *impl = (dds_security_crypto_key_factory_impl *)factory; + remote_participant_crypto *rmt_cr = (remote_participant_crypto *)crypto_object_table_find(impl->crypto_objects, remote_id); + participant_key_material *keymat; + master_key_material *master_keymat = NULL; + + if (rmt_cr) + { + keymat = crypto_remote_participant_lookup_keymat(rmt_cr, local_id); + if (keymat) + { + master_keymat = keymat->local_P2P_key_material; + CRYPTO_OBJECT_RELEASE(keymat); + } + } + + return master_keymat; +} diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.h b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.h index 3e49766..a908e2c 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.h +++ b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.h @@ -14,6 +14,7 @@ #include "dds/security/dds_security_api.h" #include "crypto_objects.h" +#include "dds/security/export.h" /** * @brief Allocation function for implementer structure (with internal variables) transparently. @@ -158,4 +159,10 @@ crypto_factory_get_specific_keymat( uint32_t *index, master_key_material **key_mat); +SECURITY_EXPORT master_key_material * +crypto_factory_get_master_key_material_for_test( + const dds_security_crypto_key_factory *factory, + DDS_Security_ParticipantCryptoHandle local_id, + DDS_Security_ParticipantCryptoHandle remote_id); + #endif /* CRYPTO_KEY_FACTORY_H */ diff --git a/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c b/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c index cc6cd22..ea77f41 100644 --- a/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c +++ b/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c @@ -28,6 +28,7 @@ #include "CUnit/Test.h" #include "common/src/loader.h" #include "common/src/crypto_helper.h" +#include "crypto_key_factory.h" #include "crypto_objects.h" #include "crypto_utils.h" @@ -571,18 +572,7 @@ static session_key_material * get_local_participant_session(DDS_Security_Partici static master_key_material * get_remote_participant_key_material(DDS_Security_ParticipantCryptoHandle participant_crypto) { - participant_key_material *key_material; - master_key_material * master_keymat = NULL; - remote_participant_crypto *participant_crypto_impl = (remote_participant_crypto *)participant_crypto; - - key_material = crypto_remote_participant_lookup_keymat(participant_crypto_impl, local_particpant_crypto); - if (key_material) - { - master_keymat = key_material->local_P2P_key_material; - CRYPTO_OBJECT_RELEASE(key_material); - } - - return master_keymat; + return crypto_factory_get_master_key_material_for_test(crypto->crypto_key_factory, local_particpant_crypto, participant_crypto); } static void set_protection_kind(DDS_Security_ParticipantCryptoHandle participant_crypto, DDS_Security_ProtectionKind protection_kind) From fa0c6777d4497f2b6bef35a24d5e532a9c56a866 Mon Sep 17 00:00:00 2001 From: Marcel Jordense Date: Fri, 27 Mar 2020 14:51:13 +0100 Subject: [PATCH 139/238] Remove setting volatile secure writer to incorrect state Signed-off-by: Marcel Jordense --- src/core/ddsi/src/q_entity.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 23a64a9..f0fff03 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -3620,7 +3620,7 @@ static void new_writer_guid_common_init (struct writer *wr, const struct ddsi_se assert ((wr->xqos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL) || (wr->e.guid.entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER)); } - wr->handle_as_transient_local = (wr->xqos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL || wr->e.guid.entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER); + wr->handle_as_transient_local = (wr->xqos->durability.kind == DDS_DURABILITY_TRANSIENT_LOCAL); wr->include_keyhash = wr->e.gv->config.generate_keyhash && ((wr->e.guid.entityid.u & NN_ENTITYID_KIND_MASK) == NN_ENTITYID_KIND_WRITER_WITH_KEY); From c8d8d2f8e692037cb33e7c45291cc4c24dc5bd26 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 26 Mar 2020 20:21:56 +0100 Subject: [PATCH 140/238] Stop threads doing handshake processing earlier In particular before the state they depend on gets torn down. Signed-off-by: Erik Boasson --- .../ddsi/include/dds/ddsi/ddsi_handshake.h | 7 ++++ .../ddsi/include/dds/ddsi/ddsi_security_omg.h | 6 ++-- src/core/ddsi/src/ddsi_handshake.c | 32 +++++++++---------- src/core/ddsi/src/ddsi_security_omg.c | 5 +++ src/core/ddsi/src/q_init.c | 14 +++++--- 5 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_handshake.h b/src/core/ddsi/include/dds/ddsi/ddsi_handshake.h index 307eb72..a76f009 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_handshake.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_handshake.h @@ -168,6 +168,13 @@ struct ddsi_handshake * ddsi_handshake_find(struct participant *pp, struct proxy */ void ddsi_handshake_admin_init(struct ddsi_domaingv *gv); +/** +* @brief Stop handshake background processing. +* +* @param[in] gv The global parameters +*/ +void ddsi_handshake_admin_stop(struct ddsi_domaingv *gv); + /** * @brief Deinitialze the handshake administration. * 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 dc63d5a..32946ba 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h @@ -1102,6 +1102,8 @@ dds_return_t q_omg_security_load( struct dds_security_context *security_context, 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 ); bool q_omg_is_security_loaded( struct dds_security_context *sc ); @@ -1395,10 +1397,6 @@ inline dds_return_t q_omg_security_load( UNUSED_ARG( struct dds_security_context return DDS_RETCODE_ERROR; } -inline void q_omg_security_init( UNUSED_ARG( struct dds_security_context *sc) ) {} - -inline void q_omg_security_deinit( UNUSED_ARG( struct dds_security_context *sc) ) {} - inline bool q_omg_is_security_loaded( UNUSED_ARG( struct dds_security_context *sc )) { return false; } inline void q_omg_security_deregister_remote_reader_match(UNUSED_ARG(const struct proxy_reader *prd), UNUSED_ARG(const struct writer *wr), UNUSED_ARG(struct wr_prd_match *match)) diff --git a/src/core/ddsi/src/ddsi_handshake.c b/src/core/ddsi/src/ddsi_handshake.c index 847c796..b23d214 100644 --- a/src/core/ddsi/src/ddsi_handshake.c +++ b/src/core/ddsi/src/ddsi_handshake.c @@ -1120,21 +1120,6 @@ static void release_handshake(void *arg) ddsi_handshake_release((struct ddsi_handshake *)arg); } -static void ddsi_handshake_admin_delete(struct ddsi_hsadmin *hsadmin) -{ - if (hsadmin) - { - ddsrt_mutex_destroy(&hsadmin->lock); - ddsrt_avl_free(&handshake_treedef, &hsadmin->handshakes, release_handshake); - if (hsadmin->fsm_control) - { - dds_security_fsm_control_stop(hsadmin->fsm_control); - dds_security_fsm_control_free(hsadmin->fsm_control); - } - ddsrt_free(hsadmin); - } -} - static struct ddsi_handshake * ddsi_handshake_find_locked( struct ddsi_hsadmin *hsadmin, struct participant *pp, @@ -1213,10 +1198,23 @@ void ddsi_handshake_admin_init(struct ddsi_domaingv *gv) void ddsi_handshake_admin_deinit(struct ddsi_domaingv *gv) { - assert(gv); - ddsi_handshake_admin_delete(gv->hsadmin); + struct ddsi_hsadmin *hsadmin = gv->hsadmin; + if (hsadmin) + { + ddsrt_mutex_destroy(&hsadmin->lock); + ddsrt_avl_free(&handshake_treedef, &hsadmin->handshakes, release_handshake); + if (hsadmin->fsm_control) + dds_security_fsm_control_free(hsadmin->fsm_control); + ddsrt_free(hsadmin); + } } +void ddsi_handshake_admin_stop(struct ddsi_domaingv *gv) +{ + struct ddsi_hsadmin *hsadmin = gv->hsadmin; + if (hsadmin && hsadmin->fsm_control) + dds_security_fsm_control_stop(hsadmin->fsm_control); +} #else diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 70b2b93..46a0d0b 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -623,6 +623,11 @@ static void release_plugins (dds_security_context *sc) sc->crypto_context = NULL; } +void q_omg_security_stop (struct ddsi_domaingv *gv) +{ + ddsi_handshake_admin_stop(gv); +} + void q_omg_security_deinit (struct ddsi_domaingv *gv) { dds_security_context *sc = gv->security_context; diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 6e756e0..859be30 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -1518,12 +1518,12 @@ err_unicast_sockets: ddsrt_hh_free (gv->sertopics); 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); ddsi_xqos_fini (&gv->builtin_stateless_xqos_wr); ddsi_xqos_fini (&gv->builtin_stateless_xqos_rd); ddsi_xqos_fini (&gv->builtin_volatile_xqos_wr); ddsi_xqos_fini (&gv->builtin_volatile_xqos_rd); - - q_omg_security_deinit (gv); #endif ddsi_xqos_fini (&gv->builtin_endpoint_xqos_wr); ddsi_xqos_fini (&gv->builtin_endpoint_xqos_rd); @@ -1749,6 +1749,12 @@ void rtps_stop (struct ddsi_domaingv *gv) thread_state_asleep (ts1); } + /* Stop background (handshake) processing in security implementation, + do this only once we know no new events will be coming in. */ +#if DDSI_INCLUDE_SECURITY + q_omg_security_stop (gv); +#endif + /* Wait until all participants are really gone => by then we can be certain that no new GC requests will be added, short of what we do here */ @@ -1854,7 +1860,6 @@ void rtps_fini (struct ddsi_domaingv *gv) } ddsi_tkmap_free (gv->m_tkmap); - entity_index_free (gv->entity_index); gv->entity_index = NULL; deleted_participants_admin_free (gv->deleted_participants); @@ -1873,12 +1878,11 @@ void rtps_fini (struct ddsi_domaingv *gv) ddsrt_mutex_destroy (&gv->sertopics_lock); #ifdef DDSI_INCLUDE_SECURITY + q_omg_security_deinit (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); ddsi_xqos_fini (&gv->builtin_volatile_xqos_rd); - - q_omg_security_deinit (gv); #endif ddsi_xqos_fini (&gv->builtin_endpoint_xqos_wr); ddsi_xqos_fini (&gv->builtin_endpoint_xqos_rd); From b18fd395d3d96d745589b99e232a79007ed92865 Mon Sep 17 00:00:00 2001 From: eboasson Date: Mon, 30 Mar 2020 10:32:58 +0200 Subject: [PATCH 141/238] Do not rewrite secure messages in retransmit queue (#456) * Do not rewrite secure messages in retransmit queue Messages to be retransmitted spend some time on a transmit queue, and are subject to the rewriting of the destination information to reduce the number of outgoing copies. Self-evidently, altering the message header does not sit well with encryption and/or authentication of messages. The way the rewriting works is that the offset of the "reader entity id" in the DATA submessage is saved on message construction (the GUID prefix is at a fixed location), so that it can be read and possibly zero'd out later. The crypto transformations move the message around and it so happens that it can end up pointing to the key id in the encoded message. Zeroing that one out leads to uninterpretable messages. This commit adds a message/event kind to distinguish between retransmit that may and retransmit that may not be merged (and thus rewritten) and gets used when the crypto plugin is invoked to transform a message. Signed-off-by: Erik Boasson * Update comment on changing REXMIT to REXMIT_NOMERGE Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_xmsg.h | 3 ++- src/core/ddsi/src/q_xevent.c | 29 +++++++++++++++++++------ src/core/ddsi/src/q_xmsg.c | 19 ++++++++++++++++ 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_xmsg.h b/src/core/ddsi/include/dds/ddsi/q_xmsg.h index 2b423a2..0a282fe 100644 --- a/src/core/ddsi/include/dds/ddsi/q_xmsg.h +++ b/src/core/ddsi/include/dds/ddsi/q_xmsg.h @@ -43,7 +43,8 @@ struct nn_xmsg_marker { enum nn_xmsg_kind { NN_XMSG_KIND_CONTROL, NN_XMSG_KIND_DATA, - NN_XMSG_KIND_DATA_REXMIT + NN_XMSG_KIND_DATA_REXMIT, + NN_XMSG_KIND_DATA_REXMIT_NOMERGE }; /* XMSGPOOL */ diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index a248eaf..ae6de3c 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -103,6 +103,7 @@ enum xeventkind_nt { XEVK_MSG, XEVK_MSG_REXMIT, + XEVK_MSG_REXMIT_NOMERGE, XEVK_ENTITYID, XEVK_NT_CALLBACK }; @@ -126,7 +127,7 @@ struct xevent_nt struct nn_xmsg *msg; size_t queued_rexmit_bytes; ddsrt_avl_node_t msg_avlnode; - } msg_rexmit; + } msg_rexmit; /* and msg_rexmit_nomerge */ struct { /* xmsg is self-contained / relies on reference counts */ struct nn_xmsg *msg; @@ -178,7 +179,7 @@ static void update_rexmit_counts (struct xeventq *evq, struct xevent_nt *ev) #if 0 EVQTRACE ("ZZZ(%p,%"PRIuSIZE")", (void *) ev, ev->u.msg_rexmit.queued_rexmit_bytes); #endif - assert (ev->kind == XEVK_MSG_REXMIT); + assert (ev->kind == XEVK_MSG_REXMIT || ev->kind == XEVK_MSG_REXMIT_NOMERGE); assert (ev->u.msg_rexmit.queued_rexmit_bytes <= evq->queued_rexmit_bytes); assert (evq->queued_rexmit_msgs > 0); evq->queued_rexmit_bytes -= ev->u.msg_rexmit.queued_rexmit_bytes; @@ -205,9 +206,20 @@ static void trace_msg (UNUSED_ARG (struct xeventq *evq), UNUSED_ARG (const char static struct xevent_nt *lookup_msg (struct xeventq *evq, struct nn_xmsg *msg) { - assert (nn_xmsg_kind (msg) == NN_XMSG_KIND_DATA_REXMIT); - trace_msg (evq, "lookup-msg", msg); - return ddsrt_avl_lookup (&msg_xevents_treedef, &evq->msg_xevents, msg); + switch (nn_xmsg_kind (msg)) + { + case NN_XMSG_KIND_CONTROL: + case NN_XMSG_KIND_DATA: + assert (0); + return NULL; + case NN_XMSG_KIND_DATA_REXMIT: + trace_msg (evq, "lookup-msg", msg); + return ddsrt_avl_lookup (&msg_xevents_treedef, &evq->msg_xevents, msg); + case NN_XMSG_KIND_DATA_REXMIT_NOMERGE: + return NULL; + } + assert (0); + return NULL; } static void remember_msg (struct xeventq *evq, struct xevent_nt *ev) @@ -1324,6 +1336,7 @@ static void handle_individual_xevent_nt (struct xevent_nt *xev, struct nn_xpack handle_xevk_msg (xp, xev); break; case XEVK_MSG_REXMIT: + case XEVK_MSG_REXMIT_NOMERGE: handle_xevk_msg_rexmit (xp, xev); break; case XEVK_ENTITYID: @@ -1563,7 +1576,7 @@ int qxev_msg_rexmit_wrlock_held (struct xeventq *evq, struct nn_xmsg *msg, int f struct xevent_nt *ev; assert (evq); - assert (nn_xmsg_kind (msg) == NN_XMSG_KIND_DATA_REXMIT); + assert (nn_xmsg_kind (msg) == NN_XMSG_KIND_DATA_REXMIT || nn_xmsg_kind (msg) == NN_XMSG_KIND_DATA_REXMIT_NOMERGE); ddsrt_mutex_lock (&evq->lock); if ((ev = lookup_msg (evq, msg)) != NULL && nn_xmsg_merge_rexmit_destinations_wrlock_held (gv, ev->u.msg_rexmit.msg, msg)) { @@ -1587,7 +1600,9 @@ int qxev_msg_rexmit_wrlock_held (struct xeventq *evq, struct nn_xmsg *msg, int f } else { - ev = qxev_common_nt (evq, XEVK_MSG_REXMIT); + const enum xeventkind_nt kind = + (nn_xmsg_kind (msg) == NN_XMSG_KIND_DATA_REXMIT) ? XEVK_MSG_REXMIT : XEVK_MSG_REXMIT_NOMERGE; + ev = qxev_common_nt (evq, kind); ev->u.msg_rexmit.msg = msg; ev->u.msg_rexmit.queued_rexmit_bytes = msg_size; evq->queued_rexmit_bytes += msg_size; diff --git a/src/core/ddsi/src/q_xmsg.c b/src/core/ddsi/src/q_xmsg.c index d450100..70c70e5 100644 --- a/src/core/ddsi/src/q_xmsg.c +++ b/src/core/ddsi/src/q_xmsg.c @@ -429,6 +429,7 @@ static int submsg_is_compatible (const struct nn_xmsg *msg, SubmessageKind_t smk break; case NN_XMSG_KIND_DATA: case NN_XMSG_KIND_DATA_REXMIT: + case NN_XMSG_KIND_DATA_REXMIT_NOMERGE: switch (smkind) { case SMID_PAD: @@ -551,6 +552,12 @@ void nn_xmsg_submsg_remove(struct nn_xmsg *msg, struct nn_xmsg_marker sm_marker) { /* Just reset the message size to the start of the current sub-message. */ msg->sz = sm_marker.offset; + + /* Deleting the submessage means the readerId offset in a DATA_REXMIT message is no + longer valid. Converting the message kind to a _NOMERGE one ensures no subsequent + operation will assume its validity. */ + if (msg->kind == NN_XMSG_KIND_DATA_REXMIT) + msg->kind = NN_XMSG_KIND_DATA_REXMIT_NOMERGE; } void nn_xmsg_submsg_replace(struct nn_xmsg *msg, struct nn_xmsg_marker sm_marker, unsigned char *new_submsg, size_t new_len) @@ -573,6 +580,17 @@ void nn_xmsg_submsg_replace(struct nn_xmsg *msg, struct nn_xmsg_marker sm_marker /* Replace the sub-message. */ memcpy(msg->data->payload + sm_marker.offset, new_submsg, new_len); + + /* The replacement submessage may have undergone any transformation and so the readerId + offset in a DATA_REXMIT message is potentially no longer valid. Converting the + message kind to a _NOMERGE one ensures no subsequent operation will assume its + validity. This is used by the security implementation when encrypting and/or signing + messages and apart from the offset possibly no longer being valid (for which one + might conceivably be able to correct), there is also the issue that it may now be + meaningless junk or that rewriting it would make the receiver reject it as having + been tampered with. */ + if (msg->kind == NN_XMSG_KIND_DATA_REXMIT) + msg->kind = NN_XMSG_KIND_DATA_REXMIT_NOMERGE; } void nn_xmsg_submsg_append_refd_payload(struct nn_xmsg *msg, struct nn_xmsg_marker sm_marker) @@ -1614,6 +1632,7 @@ int nn_xpack_addmsg (struct nn_xpack *xp, struct nn_xmsg *m, const uint32_t flag break; case NN_XMSG_KIND_DATA: case NN_XMSG_KIND_DATA_REXMIT: + case NN_XMSG_KIND_DATA_REXMIT_NOMERGE: GVTRACE ("%s("PGUIDFMT":#%"PRId64"/%u)", (m->kind == NN_XMSG_KIND_DATA) ? "data" : "rexmit", PGUID (m->kindspecific.data.wrguid), From 4f3cbf7a1cea74ad7f9216923c008016598dd3ce Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 23 Mar 2020 11:59:43 +0100 Subject: [PATCH 142/238] Clean up representation of discovery messages * Remove the "plist" and "rawcdr" abuse of the "serdata_default" sample representation. * Introduce a new "plist" topic type and a new "pserop" topic type. The former represents parameter lists as used in discovery, the second arbitrary samples using the serialiser in ddsi_plist.c. * Introduce sertopics for each of the built-in "topics" used by the DDSI discovery protocol using the two new topic types, and reference these in the readers/writers used in discovery. * Construct and deconstruct the discovery message by using the conversion routines for these sample types, rather than fiddling with, e.g., the baroque interface for adding parameter lists to messages. * As a consequence, it introduces standardized logging of received and transmitted discovery data and eliminates the annoying "(null)/(null)" and "(blob)" descriptions in the trace. * Limits the dumping of octet sequences in discovery data to the first 100 bytes to make the embedded certificates and permissions documents (somewhat) manageable. * Eliminates the (many) null pointer checks on reader/writer topics. * Fixes the printing of nested sequences in discovery data (not used before) and the formatting of GUIDs. Various interfaces remain unchanged and so while this removes cruft from the core code, it moves some of it into the conversion routines for the new topic types. It also now allocates some memory when processing incoming discovery data, whereas before it had no need to do so. Allowing for aliasing of data in the new sertopics and adding a way to initialize these specific types on the stack (both minor changes) suffices for eliminating those allocations. Signed-off-by: Erik Boasson Check actual topic type before "downcasting" Signed-off-by: Erik Boasson Free the memory we own and is actually allocated Signed-off-by: Erik Boasson Ignore logging newlines if nothing is buffered Signed-off-by: Erik Boasson Suffix data with "(trunc)" one byte earlier The sample printing code changed over time and now stops as soon as it can once it has filled up the buffer. As the return value is simply the number of bytes written, if that number is equal to buffer size less one (because of the terminating nul) it may or may not have been truncated, but the likelihood is that it has been. So add the "(trunc)" suffix once that point has been reached. Signed-off-by: Erik Boasson --- docs/manual/options.md | 10 +- etc/cyclonedds.rnc | 5 - etc/cyclonedds.xsd | 7 - src/core/ddsc/src/dds_topic.c | 20 +- src/core/ddsi/CMakeLists.txt | 6 + .../ddsi/include/dds/ddsi/ddsi_domaingv.h | 14 +- src/core/ddsi/include/dds/ddsi/ddsi_plist.h | 2 +- .../include/dds/ddsi/ddsi_plist_generic.h | 3 + src/core/ddsi/include/dds/ddsi/ddsi_pmd.h | 18 +- .../include/dds/ddsi/ddsi_security_exchange.h | 4 +- .../ddsi/include/dds/ddsi/ddsi_security_msg.h | 1 + .../include/dds/ddsi/ddsi_serdata_default.h | 3 +- .../include/dds/ddsi/ddsi_serdata_plist.h | 76 ++ .../include/dds/ddsi/ddsi_serdata_pserop.h | 78 ++ src/core/ddsi/include/dds/ddsi/q_config.h | 2 - .../ddsi/include/dds/ddsi/q_ddsi_discovery.h | 8 +- src/core/ddsi/include/dds/ddsi/q_entity.h | 4 +- src/core/ddsi/include/dds/ddsi/q_protocol.h | 12 +- src/core/ddsi/src/ddsi_entity_index.c | 47 +- src/core/ddsi/src/ddsi_plist.c | 86 ++- src/core/ddsi/src/ddsi_pmd.c | 117 ++- src/core/ddsi/src/ddsi_security_exchange.c | 271 ++----- src/core/ddsi/src/ddsi_security_msg.c | 3 +- src/core/ddsi/src/ddsi_security_omg.c | 97 +-- src/core/ddsi/src/ddsi_serdata_default.c | 153 ---- src/core/ddsi/src/ddsi_serdata_plist.c | 303 ++++++++ src/core/ddsi/src/ddsi_serdata_pserop.c | 297 ++++++++ src/core/ddsi/src/ddsi_sertopic.c | 26 +- src/core/ddsi/src/ddsi_sertopic_plist.c | 95 +++ src/core/ddsi/src/ddsi_sertopic_pserop.c | 118 +++ src/core/ddsi/src/q_config.c | 2 - src/core/ddsi/src/q_ddsi_discovery.c | 670 +++++------------- src/core/ddsi/src/q_entity.c | 69 +- src/core/ddsi/src/q_init.c | 78 +- src/core/ddsi/src/q_receive.c | 2 +- src/core/ddsi/src/q_transmit.c | 8 +- src/core/ddsi/src/q_xevent.c | 8 +- src/ddsrt/src/log.c | 18 +- 38 files changed, 1489 insertions(+), 1252 deletions(-) create mode 100644 src/core/ddsi/include/dds/ddsi/ddsi_serdata_plist.h create mode 100644 src/core/ddsi/include/dds/ddsi/ddsi_serdata_pserop.h create mode 100644 src/core/ddsi/src/ddsi_serdata_plist.c create mode 100644 src/core/ddsi/src/ddsi_serdata_pserop.c create mode 100644 src/core/ddsi/src/ddsi_sertopic_plist.c create mode 100644 src/core/ddsi/src/ddsi_sertopic_pserop.c diff --git a/docs/manual/options.md b/docs/manual/options.md index 1ebf816..b343bf1 100644 --- a/docs/manual/options.md +++ b/docs/manual/options.md @@ -451,7 +451,7 @@ The default value is: "dds_security_crypto". ### //CycloneDDS/Domain/Discovery -Children: [DSGracePeriod](#cycloneddsdomaindiscoverydsgraceperiod), [DefaultMulticastAddress](#cycloneddsdomaindiscoverydefaultmulticastaddress), [EnableTopicDiscovery](#cycloneddsdomaindiscoveryenabletopicdiscovery), [ExternalDomainId](#cycloneddsdomaindiscoveryexternaldomainid), [MaxAutoParticipantIndex](#cycloneddsdomaindiscoverymaxautoparticipantindex), [ParticipantIndex](#cycloneddsdomaindiscoveryparticipantindex), [Peers](#cycloneddsdomaindiscoverypeers), [Ports](#cycloneddsdomaindiscoveryports), [SPDPInterval](#cycloneddsdomaindiscoveryspdpinterval), [SPDPMulticastAddress](#cycloneddsdomaindiscoveryspdpmulticastaddress), [Tag](#cycloneddsdomaindiscoverytag) +Children: [DSGracePeriod](#cycloneddsdomaindiscoverydsgraceperiod), [DefaultMulticastAddress](#cycloneddsdomaindiscoverydefaultmulticastaddress), [ExternalDomainId](#cycloneddsdomaindiscoveryexternaldomainid), [MaxAutoParticipantIndex](#cycloneddsdomaindiscoverymaxautoparticipantindex), [ParticipantIndex](#cycloneddsdomaindiscoveryparticipantindex), [Peers](#cycloneddsdomaindiscoverypeers), [Ports](#cycloneddsdomaindiscoveryports), [SPDPInterval](#cycloneddsdomaindiscoveryspdpinterval), [SPDPMulticastAddress](#cycloneddsdomaindiscoveryspdpmulticastaddress), [Tag](#cycloneddsdomaindiscoverytag) The Discovery element allows specifying various parameters related to the @@ -482,14 +482,6 @@ Discovery/SPDPMulticastAddress. The default value is: "auto". -#### //CycloneDDS/Domain/Discovery/EnableTopicDiscovery -Boolean - -Do not use. - -The default value is: "true". - - #### //CycloneDDS/Domain/Discovery/ExternalDomainId Text diff --git a/etc/cyclonedds.rnc b/etc/cyclonedds.rnc index 7088cb5..1ee2c4d 100644 --- a/etc/cyclonedds.rnc +++ b/etc/cyclonedds.rnc @@ -407,11 +407,6 @@ Discovery/SPDPMulticastAddress.

    The default value is: text }? & [ a:documentation [ xml:lang="en" """ -

    Do not use.

    The default value is: "true".

    """ ] ] - element EnableTopicDiscovery { - xsd:boolean - }? - & [ a:documentation [ xml:lang="en" """

    An override for the domain id, to be used in discovery and for determining the port number mapping. This allows creating multiple domains in a single process while making them appear as a single domain diff --git a/etc/cyclonedds.xsd b/etc/cyclonedds.xsd index ad9cb88..d552a5c 100644 --- a/etc/cyclonedds.xsd +++ b/etc/cyclonedds.xsd @@ -522,7 +522,6 @@ the discovery of peers.</p> - @@ -556,12 +555,6 @@ Discovery/SPDPMulticastAddress.</p><p>The default value is: &quot;auto&quot;.</p> - - - -<p>Do not use.</p><p>The default value is: &quot;true&quot;.</p> - - diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index 7a8ad16..a07b4e3 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -247,6 +247,7 @@ static dds_return_t lookup_and_check_ktopic (struct dds_ktopic **ktp_out, dds_pa static dds_entity_t create_topic_pp_locked (struct dds_participant *pp, struct dds_ktopic *ktp, bool implicit, struct ddsi_sertopic *sertopic_registered, const dds_listener_t *listener, const ddsi_plist_t *sedp_plist) { + (void) sedp_plist; dds_entity_t hdl; dds_topic *tp = dds_alloc (sizeof (*tp)); hdl = dds_entity_init (&tp->m_entity, &pp->m_entity, DDS_KIND_TOPIC, implicit, NULL, listener, DDS_TOPIC_STATUS_MASK); @@ -254,25 +255,6 @@ static dds_entity_t create_topic_pp_locked (struct dds_participant *pp, struct d dds_entity_register_child (&pp->m_entity, &tp->m_entity); tp->m_ktopic = ktp; tp->m_stopic = sertopic_registered; - - /* Publish Topic */ - if (sedp_plist) - { - struct participant *ddsi_pp; - ddsi_plist_t plist; - - thread_state_awake (lookup_thread_state (), &pp->m_entity.m_domain->gv); - ddsi_pp = entidx_lookup_participant_guid (pp->m_entity.m_domain->gv.entity_index, &pp->m_entity.m_guid); - assert (ddsi_pp); - - ddsi_plist_init_empty (&plist); - ddsi_plist_mergein_missing (&plist, sedp_plist, ~(uint64_t)0, ~(uint64_t)0); - ddsi_xqos_mergein_missing (&plist.qos, ktp->qos, ~(uint64_t)0); - sedp_write_topic (ddsi_pp, &plist); - ddsi_plist_fini (&plist); - thread_state_asleep (lookup_thread_state ()); - } - dds_entity_init_complete (&tp->m_entity); return hdl; } diff --git a/src/core/ddsi/CMakeLists.txt b/src/core/ddsi/CMakeLists.txt index 6ef3f88..e20181a 100644 --- a/src/core/ddsi/CMakeLists.txt +++ b/src/core/ddsi/CMakeLists.txt @@ -24,8 +24,12 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src" ddsi_handshake.c ddsi_serdata.c ddsi_serdata_default.c + ddsi_serdata_pserop.c + ddsi_serdata_plist.c ddsi_sertopic.c ddsi_sertopic_default.c + ddsi_sertopic_pserop.c + ddsi_sertopic_plist.c ddsi_iid.c ddsi_tkmap.c ddsi_vendor.c @@ -91,6 +95,8 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi" ddsi_serdata.h ddsi_sertopic.h ddsi_serdata_default.h + ddsi_serdata_pserop.h + ddsi_serdata_plist.h ddsi_iid.h ddsi_tkmap.h ddsi_vendor.h diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h b/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h index ed0dc0a..0deb8ea 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h @@ -294,8 +294,18 @@ struct ddsi_domaingv { transmit queue*/ struct serdatapool *serpool; struct nn_xmsgpool *xmsgpool; - struct ddsi_sertopic *plist_topic; /* used for all discovery data */ - struct ddsi_sertopic *rawcdr_topic; /* used for participant message data */ + struct ddsi_sertopic *spdp_topic; /* key = participant GUID */ + struct ddsi_sertopic *sedp_reader_topic; /* key = endpoint GUID */ + struct ddsi_sertopic *sedp_writer_topic; /* key = endpoint GUID */ + struct ddsi_sertopic *pmd_topic; /* participant message data */ +#ifdef DDSI_INCLUDE_SECURITY + struct ddsi_sertopic *spdp_secure_topic; /* key = participant GUID */ + struct ddsi_sertopic *sedp_reader_secure_topic; /* key = endpoint GUID */ + struct ddsi_sertopic *sedp_writer_secure_topic; /* key = endpoint GUID */ + struct ddsi_sertopic *pmd_secure_topic; /* participant message data */ + struct ddsi_sertopic *pgm_stateless_topic; /* participant generic message */ + struct ddsi_sertopic *pgm_volatile_topic; /* participant generic message */ +#endif ddsrt_mutex_t sendq_lock; ddsrt_cond_t sendq_cond; diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_plist.h b/src/core/ddsi/include/dds/ddsi/ddsi_plist.h index bd3a998..3f8c283 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_plist.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_plist.h @@ -311,7 +311,7 @@ struct nn_rsample_info; struct nn_rdata; DDS_EXPORT unsigned char *ddsi_plist_quickscan (struct nn_rsample_info *dest, const struct nn_rmsg *rmsg, const ddsi_plist_src_t *src); -DDS_EXPORT const unsigned char *ddsi_plist_findparam_native_unchecked (const void *src, nn_parameterid_t pid); +DDS_EXPORT dds_return_t ddsi_plist_findparam_checking (const void *buf, size_t bufsz, uint16_t encoding, nn_parameterid_t needle, void **needlep, size_t *needlesz); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_plist_generic.h b/src/core/ddsi/include/dds/ddsi/ddsi_plist_generic.h index 481aa6c..6408942 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_plist_generic.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_plist_generic.h @@ -19,6 +19,7 @@ #include "dds/export.h" #include "dds/ddsrt/attributes.h" +#include "dds/ddsrt/retcode.h" #if defined (__cplusplus) extern "C" { @@ -48,9 +49,11 @@ enum pserop { DDS_EXPORT void plist_fini_generic (void * __restrict dst, const enum pserop *desc, bool aliased); DDS_EXPORT dds_return_t plist_deser_generic (void * __restrict dst, const void * __restrict src, size_t srcsize, bool bswap, const enum pserop * __restrict desc); DDS_EXPORT dds_return_t plist_ser_generic (void **dst, size_t *dstsize, const void *src, const enum pserop * __restrict desc); +DDS_EXPORT dds_return_t plist_ser_generic_be (void **dst, size_t *dstsize, const void *src, const enum pserop * __restrict desc); DDS_EXPORT dds_return_t plist_unalias_generic (void * __restrict dst, const enum pserop * __restrict desc); DDS_EXPORT bool plist_equal_generic (const void *srcx, const void *srcy, const enum pserop * __restrict desc); DDS_EXPORT size_t plist_memsize_generic (const enum pserop * __restrict desc); +DDS_EXPORT size_t plist_print_generic (char * __restrict buf, size_t bufsize, const void * __restrict src, const enum pserop * __restrict desc); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_pmd.h b/src/core/ddsi/include/dds/ddsi/ddsi_pmd.h index 0948247..40cf62a 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_pmd.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_pmd.h @@ -12,7 +12,12 @@ #ifndef DDSI_PMD_H #define DDSI_PMD_H +#include #include "dds/ddsrt/time.h" +#include "dds/ddsi/ddsi_serdata.h" +#include "dds/ddsi/ddsi_plist_generic.h" +#include "dds/ddsi/ddsi_guid.h" +#include "dds/ddsi/ddsi_xqos.h" #if defined (__cplusplus) extern "C" { @@ -25,9 +30,20 @@ struct nn_xpack; struct participant; struct receiver_state; +typedef struct ParticipantMessageData { + ddsi_guid_prefix_t participantGuidPrefix; + uint32_t kind; /* really 4 octets */ + ddsi_octetseq_t value; +} ParticipantMessageData_t; + +extern const enum pserop participant_message_data_ops[]; +extern size_t participant_message_data_nops; +extern const enum pserop participant_message_data_ops_key[]; +extern size_t participant_message_data_nops_key; + void write_pmd_message_guid (struct ddsi_domaingv * const gv, struct ddsi_guid *pp_guid, unsigned pmd_kind); void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack *xp, struct participant *pp, unsigned pmd_kind); -void handle_pmd_message (const struct receiver_state *rst, ddsrt_wctime_t timestamp, uint32_t statusinfo, const void *vdata, uint32_t len); +void handle_pmd_message (const struct receiver_state *rst, struct ddsi_serdata *sample_common); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_security_exchange.h b/src/core/ddsi/include/dds/ddsi/ddsi_security_exchange.h index b271e7e..07268d0 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_exchange.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_exchange.h @@ -29,8 +29,8 @@ extern "C" { #define GMCLASSID_SECURITY_DATAREADER_CRYPTO_TOKENS "dds.sec.datareader_crypto_tokens" bool write_auth_handshake_message(const struct participant *pp, const struct proxy_participant *proxypp, nn_dataholderseq_t *mdata, bool request, const nn_message_identity_t *related_message_id); -void handle_auth_handshake_message(const struct receiver_state *rst, ddsi_entityid_t wr_entity_id, ddsrt_wctime_t timestamp, unsigned statusinfo, const void *vdata, size_t len); -void handle_crypto_exchange_message(const struct receiver_state *rst, ddsi_entityid_t wr_entity_id, ddsrt_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len); +void handle_auth_handshake_message(const struct receiver_state *rst, ddsi_entityid_t wr_entity_id, struct ddsi_serdata *sample); +void handle_crypto_exchange_message(const struct receiver_state *rst, struct ddsi_serdata *sample); void auth_get_serialized_participant_data(struct participant *pp, ddsi_octetseq_t *seq); bool write_crypto_participant_tokens(const struct participant *pp, const struct proxy_participant *proxypp, const nn_dataholderseq_t *tokens); bool write_crypto_writer_tokens(const struct writer *wr, const struct proxy_reader *prd, const nn_dataholderseq_t *tokens); diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_security_msg.h b/src/core/ddsi/include/dds/ddsi/ddsi_security_msg.h index 072a3eb..99c5c31 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_msg.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_msg.h @@ -95,6 +95,7 @@ nn_participant_generic_message_serialize( size_t *len); DDS_EXPORT extern const enum pserop pserop_participant_generic_message[]; +DDS_EXPORT extern const size_t pserop_participant_generic_message_nops; DDS_EXPORT int volatile_secure_data_filter( diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h index 0eed3d6..50c9744 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_default.h @@ -18,6 +18,7 @@ #include "dds/ddsrt/avl.h" #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_sertopic.h" +#include "dds/ddsi/ddsi_plist_generic.h" #include "dds/dds.h" @@ -136,8 +137,6 @@ extern DDS_EXPORT const struct ddsi_sertopic_ops ddsi_sertopic_ops_default; extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_cdr; extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_cdr_nokey; -extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_plist; -extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_rawcdr; struct serdatapool * ddsi_serdatapool_new (void); void ddsi_serdatapool_free (struct serdatapool * pool); diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_plist.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_plist.h new file mode 100644 index 0000000..1ceee87 --- /dev/null +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_plist.h @@ -0,0 +1,76 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSI_SERDATA_PLIST_H +#define DDSI_SERDATA_PLIST_H + +#include "dds/ddsi/q_protocol.h" /* for nn_parameterid_t */ +#include "dds/ddsi/ddsi_keyhash.h" +#include "dds/ddsi/ddsi_serdata.h" +#include "dds/ddsi/ddsi_sertopic.h" + +#include "dds/dds.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +/* There is an alignment requirement on the raw data (it must be at + offset mod 8 for the conversion to/from a dds_stream to work). + So we define two types: one without any additional padding, and + one where the appropriate amount of padding is inserted */ +#define DDSI_SERDATA_PLIST_PREPAD \ + struct ddsi_serdata c; \ + uint32_t pos; \ + uint32_t size; \ + nn_vendorid_t vendorid; \ + nn_protocol_version_t protoversion; \ + ddsi_keyhash_t keyhash +#define DDSI_SERDATA_PLIST_POSTPAD \ + uint16_t identifier; \ + uint16_t options; \ + char data[] + +struct ddsi_serdata_plist_unpadded { + DDSI_SERDATA_PLIST_PREPAD; + DDSI_SERDATA_PLIST_POSTPAD; +}; + +#ifdef __GNUC__ +#define DDSI_SERDATA_PLIST_PAD(n) ((n) % 8) +#else +#define DDSI_SERDATA_PLIST_PAD(n) (n) +#endif + +struct ddsi_serdata_plist { + DDSI_SERDATA_PLIST_PREPAD; + char pad[DDSI_SERDATA_PLIST_PAD (8 - (offsetof (struct ddsi_serdata_plist_unpadded, data) % 8))]; + DDSI_SERDATA_PLIST_POSTPAD; +}; + +#undef DDSI_SERDATA_PLIST_PAD +#undef DDSI_SERDATA_PLIST_POSTPAD +#undef DDSI_SERDATA_PLIST_PREPAD + +struct ddsi_sertopic_plist { + struct ddsi_sertopic c; + uint16_t native_encoding_identifier; /* PL_CDR_(LE|BE) */ + nn_parameterid_t keyparam; +}; + +extern DDS_EXPORT const struct ddsi_sertopic_ops ddsi_sertopic_ops_plist; +extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_plist; + +#if defined (__cplusplus) +} +#endif + +#endif diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata_pserop.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_pserop.h new file mode 100644 index 0000000..6771a07 --- /dev/null +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata_pserop.h @@ -0,0 +1,78 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSI_SERDATA_PSEROP_H +#define DDSI_SERDATA_PSEROP_H + +#include "dds/ddsi/ddsi_serdata.h" +#include "dds/ddsi/ddsi_sertopic.h" +#include "dds/ddsi/ddsi_plist_generic.h" + +#include "dds/dds.h" + +#if defined (__cplusplus) +extern "C" { +#endif + +/* There is an alignment requirement on the raw data (it must be at + offset mod 8 for the conversion to/from a dds_stream to work). + So we define two types: one without any additional padding, and + one where the appropriate amount of padding is inserted */ +#define DDSI_SERDATA_PSEROP_PREPAD \ + struct ddsi_serdata c; \ + void *sample; \ + bool keyless; /*cached from topic*/ \ + uint32_t pos; \ + uint32_t size +#define DDSI_SERDATA_PSEROP_POSTPAD \ + uint16_t identifier; \ + uint16_t options; \ + char data[] + +struct ddsi_serdata_pserop_unpadded { + DDSI_SERDATA_PSEROP_PREPAD; + DDSI_SERDATA_PSEROP_POSTPAD; +}; + +#ifdef __GNUC__ +#define DDSI_SERDATA_PSEROP_PAD(n) ((n) % 8) +#else +#define DDSI_SERDATA_PSEROP_PAD(n) (n) +#endif + +struct ddsi_serdata_pserop { + DDSI_SERDATA_PSEROP_PREPAD; + char pad[DDSI_SERDATA_PSEROP_PAD (8 - (offsetof (struct ddsi_serdata_pserop_unpadded, data) % 8))]; + DDSI_SERDATA_PSEROP_POSTPAD; +}; + +#undef DDSI_SERDATA_PSEROP_PAD +#undef DDSI_SERDATA_PSEROP_POSTPAD +#undef DDSI_SERDATA_PSEROP_PREPAD + +struct ddsi_sertopic_pserop { + struct ddsi_sertopic c; + uint16_t native_encoding_identifier; /* CDR_(LE|BE) */ + size_t memsize; + size_t nops; + const enum pserop *ops; + size_t nops_key; + const enum pserop *ops_key; /* NULL <=> no key; != NULL <=> 16-byte key at offset 0 */ +}; + +extern DDS_EXPORT const struct ddsi_sertopic_ops ddsi_sertopic_ops_pserop; +extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_pserop; + +#if defined (__cplusplus) +} +#endif + +#endif diff --git a/src/core/ddsi/include/dds/ddsi/q_config.h b/src/core/ddsi/include/dds/ddsi/q_config.h index 16c8149..dfc16bd 100644 --- a/src/core/ddsi/include/dds/ddsi/q_config.h +++ b/src/core/ddsi/include/dds/ddsi/q_config.h @@ -261,8 +261,6 @@ struct config unsigned delivery_queue_maxsamples; - int do_topic_discovery; - uint32_t max_msg_size; uint32_t fragment_size; diff --git a/src/core/ddsi/include/dds/ddsi/q_ddsi_discovery.h b/src/core/ddsi/include/dds/ddsi/q_ddsi_discovery.h index e18dde9..3b71125 100644 --- a/src/core/ddsi/include/dds/ddsi/q_ddsi_discovery.h +++ b/src/core/ddsi/include/dds/ddsi/q_ddsi_discovery.h @@ -25,7 +25,11 @@ struct nn_rsample_info; struct nn_rdata; struct ddsi_plist; -void get_participant_builtin_topic_data(const struct participant *pp, struct nn_xmsg *mpayload, bool be); +struct participant_builtin_topic_data_locators { + struct nn_locators_one def_uni_loc_one, def_multi_loc_one, meta_uni_loc_one, meta_multi_loc_one; +}; + +void get_participant_builtin_topic_data (const struct participant *pp, ddsi_plist_t *dst, struct participant_builtin_topic_data_locators *locs); int spdp_write (struct participant *pp); int spdp_dispose_unregister (struct participant *pp); @@ -35,8 +39,6 @@ int sedp_write_reader (struct reader *rd); int sedp_dispose_unregister_writer (struct writer *wr); int sedp_dispose_unregister_reader (struct reader *rd); -int sedp_write_topic (struct participant *pp, const struct ddsi_plist *datap); - int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const ddsi_guid_t *rdguid, void *qarg); #if defined (__cplusplus) diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 6e2b17f..86e8826 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -291,7 +291,7 @@ struct writer struct addrset *ssm_as; #endif uint32_t alive_vclock; /* virtual clock counting transitions between alive/not-alive */ - const struct ddsi_sertopic * topic; /* topic, but may be NULL for built-ins */ + const struct ddsi_sertopic * topic; /* topic */ struct addrset *as; /* set of addresses to publish to */ struct addrset *as_group; /* alternate case, used for SPDP, when using Cloud with multiple bootstrap locators */ struct xevent *heartbeat_xevent; /* timed event for "periodically" publishing heartbeats when unack'd data present, NULL <=> unreliable */ @@ -350,7 +350,7 @@ struct reader #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS struct addrset *as; #endif - const struct ddsi_sertopic * topic; /* topic is NULL for built-in readers */ + const struct ddsi_sertopic * topic; /* topic */ uint32_t num_writers; /* total number of matching PROXY writers */ ddsrt_avl_tree_t writers; /* all matching PROXY writers, see struct rd_pwr_match */ ddsrt_avl_tree_t local_writers; /* all matching LOCAL writers, see struct rd_wr_match */ diff --git a/src/core/ddsi/include/dds/ddsi/q_protocol.h b/src/core/ddsi/include/dds/ddsi/q_protocol.h index 9fcda7f..688a8a1 100644 --- a/src/core/ddsi/include/dds/ddsi/q_protocol.h +++ b/src/core/ddsi/include/dds/ddsi/q_protocol.h @@ -203,7 +203,7 @@ typedef uint16_t nn_parameterid_t; /* spec says short */ typedef struct nn_parameter { nn_parameterid_t parameterid; uint16_t length; /* spec says signed short */ - /* char value[]; O! how I long for C99 */ + /* char value[] */ } nn_parameter_t; typedef struct Data_DataFrag_common { @@ -318,18 +318,10 @@ typedef union Submessage { NackFrag_t nackfrag; } Submessage_t; -DDSRT_WARNING_MSVC_OFF(4200) -typedef struct ParticipantMessageData { - ddsi_guid_prefix_t participantGuidPrefix; - uint32_t kind; /* really 4 octets */ - uint32_t length; - char value[]; -} ParticipantMessageData_t; -DDSRT_WARNING_MSVC_ON(4200) #define PARTICIPANT_MESSAGE_DATA_KIND_UNKNOWN 0x0u #define PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE 0x1u #define PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE 0x2u -#define PARTICIPANT_MESSAGE_DATA_VENDER_SPECIFIC_KIND_FLAG 0x8000000u +#define PARTICIPANT_MESSAGE_DATA_VENDOR_SPECIFIC_KIND_FLAG 0x8000000u #define PID_VENDORSPECIFIC_FLAG 0x8000u #define PID_UNRECOGNIZED_INCOMPATIBLE_FLAG 0x4000u diff --git a/src/core/ddsi/src/ddsi_entity_index.c b/src/core/ddsi/src/ddsi_entity_index.c index e23c922..fd40aae 100644 --- a/src/core/ddsi/src/ddsi_entity_index.c +++ b/src/core/ddsi/src/ddsi_entity_index.c @@ -70,20 +70,6 @@ static int entity_guid_eq_wrapper (const void *a, const void *b) return entity_guid_eq (a, b); } -static int all_entities_compare_isbuiltin (const struct entity_common *e, nn_vendorid_t vendor) -{ - const unsigned char *guid_bytes = (const unsigned char *) &e->guid; - if (guid_bytes[0] != 0 && guid_bytes[0] != 0xff) - return is_builtin_endpoint (e->guid.entityid, vendor); - else - { - for (size_t i = 1; i < sizeof (e->guid); i++) - if (guid_bytes[i] != guid_bytes[0]) - return is_builtin_endpoint (e->guid.entityid, vendor) && !is_local_orphan_endpoint (e); - return 0; - } -} - static int all_entities_compare (const void *va, const void *vb) { const struct entity_common *a = va; @@ -104,28 +90,20 @@ static int all_entities_compare (const void *va, const void *vb) case EK_WRITER: { const struct writer *wra = va; const struct writer *wrb = vb; - if (!all_entities_compare_isbuiltin (a, NN_VENDORID_ECLIPSE)) { - assert ((wra->xqos->present & QP_TOPIC_NAME) && wra->xqos->topic_name); - tp_a = wra->xqos->topic_name; - } - if (!all_entities_compare_isbuiltin (b, NN_VENDORID_ECLIPSE)) { - assert ((wrb->xqos->present & QP_TOPIC_NAME) && wrb->xqos->topic_name); - tp_b = wrb->xqos->topic_name; - } + assert ((wra->xqos->present & QP_TOPIC_NAME) && wra->xqos->topic_name); + assert ((wrb->xqos->present & QP_TOPIC_NAME) && wrb->xqos->topic_name); + tp_a = wra->xqos->topic_name; + tp_b = wrb->xqos->topic_name; break; } case EK_READER: { const struct reader *rda = va; const struct reader *rdb = vb; - if (!all_entities_compare_isbuiltin (a, NN_VENDORID_ECLIPSE)) { - assert ((rda->xqos->present & QP_TOPIC_NAME) && rda->xqos->topic_name); - tp_a = rda->xqos->topic_name; - } - if (!all_entities_compare_isbuiltin (b, NN_VENDORID_ECLIPSE)) { - assert ((rdb->xqos->present & QP_TOPIC_NAME) && rdb->xqos->topic_name); - tp_b = rdb->xqos->topic_name; - } + assert ((rda->xqos->present & QP_TOPIC_NAME) && rda->xqos->topic_name); + assert ((rdb->xqos->present & QP_TOPIC_NAME) && rdb->xqos->topic_name); + tp_a = rda->xqos->topic_name; + tp_b = rdb->xqos->topic_name; break; } @@ -133,14 +111,11 @@ static int all_entities_compare (const void *va, const void *vb) case EK_PROXY_READER: { const struct generic_proxy_endpoint *ga = va; const struct generic_proxy_endpoint *gb = vb; - if (!all_entities_compare_isbuiltin (a, ga->c.vendor)) { - assert ((ga->c.xqos->present & QP_TOPIC_NAME) && ga->c.xqos->topic_name); + /* built-in reader/writer proxies don't have topic name set */ + if (ga->c.xqos->present & QP_TOPIC_NAME) tp_a = ga->c.xqos->topic_name; - } - if (!all_entities_compare_isbuiltin (b, gb->c.vendor)) { - assert ((gb->c.xqos->present & QP_TOPIC_NAME) && gb->c.xqos->topic_name); + if (gb->c.xqos->present & QP_TOPIC_NAME) tp_b = gb->c.xqos->topic_name; - } break; } } diff --git a/src/core/ddsi/src/ddsi_plist.c b/src/core/ddsi/src/ddsi_plist.c index f440276..cd91486 100644 --- a/src/core/ddsi/src/ddsi_plist.c +++ b/src/core/ddsi/src/ddsi_plist.c @@ -1028,6 +1028,19 @@ dds_return_t plist_ser_generic (void **dst, size_t *dstsize, const void *src, co return ret; } +dds_return_t plist_ser_generic_be (void **dst, size_t *dstsize, const void *src, const enum pserop * __restrict desc) +{ + const size_t srcoff = 0; + size_t dstoff = 0; + dds_return_t ret; + *dstsize = ser_generic_size (src, srcoff, desc); + if ((*dst = ddsrt_malloc (*dstsize == 0 ? 1 : *dstsize)) == NULL) + return DDS_RETCODE_OUT_OF_RESOURCES; + ret = ser_generic_embeddable (*dst, &dstoff, src, srcoff, desc, true); + assert (dstoff == *dstsize); + return ret; +} + static dds_return_t unalias_generic (void * __restrict dst, size_t * __restrict dstoff, bool gen_seq_aliased, const enum pserop * __restrict desc) { #define COMPLEX(basecase_, type_, ...) do { \ @@ -1249,7 +1262,14 @@ static uint32_t isprint_runlen (uint32_t n, const unsigned char *xs) static bool prtf_octetseq (char * __restrict *buf, size_t * __restrict bufsize, uint32_t n, const unsigned char *xs) { + /* Truncate octet sequences: 100 is arbitrary but experience suggests it is + usually enough, and truncating it helps a lot when printing handshake + messages during authentication. */ + const uint32_t lim = 100; + bool trunc = (n > lim); uint32_t i = 0; + if (trunc) + n = lim; while (i < n) { uint32_t m = isprint_runlen (n - i, xs); @@ -1272,7 +1292,7 @@ static bool prtf_octetseq (char * __restrict *buf, size_t * __restrict bufsize, } } } - return true; + return trunc ? prtf (buf, bufsize, "...") : true; } static bool print_generic1 (char * __restrict *buf, size_t * __restrict bufsize, const void *src, size_t srcoff, const enum pserop * __restrict desc, const char *sep) @@ -1387,7 +1407,7 @@ static bool print_generic1 (char * __restrict *buf, size_t * __restrict bufsize, } case XG: { /* GUID */ ddsi_guid_t const * const x = deser_generic_src (src, &srcoff, alignof (ddsi_guid_t)); - if (!prtf (buf, bufsize, "%s"PGUIDFMT, sep, PGUID (*x))) + if (!prtf (buf, bufsize, "%s{"PGUIDFMT"}", sep, PGUID (*x))) return false; srcoff += sizeof (*x); break; @@ -1415,14 +1435,13 @@ static bool print_generic1 (char * __restrict *buf, size_t * __restrict bufsize, if (!prtf (buf, bufsize, "}")) return false; srcoff += sizeof (*x); - while (*++desc != XSTOP) { } break; } case Xopt: break; } sep = ":"; - desc++; + desc = pserop_advance(desc); } } @@ -2845,20 +2864,47 @@ dds_return_t ddsi_plist_init_frommsg (ddsi_plist_t *dest, char **nextafterplist, return DDS_RETCODE_BAD_PARAMETER; } -const unsigned char *ddsi_plist_findparam_native_unchecked (const void *src, nn_parameterid_t pid) +dds_return_t ddsi_plist_findparam_checking (const void *buf, size_t bufsz, uint16_t encoding, nn_parameterid_t needle, void **needlep, size_t *needlesz) { - /* Scans the parameter list starting at src looking just for pid, returning NULL if not found; - no further checking is done and the input is assumed to valid and in native format. Clearly - this is only to be used for internally generated data -- to precise, for grabbing the key - value from discovery data that is being sent out. */ - const nn_parameter_t *par = src; - while (par->parameterid != pid) + /* set needle to PID_SENTINEL if all you want to do is scan the structure */ + assert (needle == PID_SENTINEL || (needlep != NULL && needlesz != NULL)); + bool bswap; + if (needlep) + *needlep = NULL; + switch (encoding) { - if (par->parameterid == PID_SENTINEL) - return NULL; - par = (const nn_parameter_t *) ((const char *) (par + 1) + par->length); + case PL_CDR_LE: + bswap = (DDSRT_ENDIAN != DDSRT_LITTLE_ENDIAN); + break; + case PL_CDR_BE: + bswap = (DDSRT_ENDIAN != DDSRT_BIG_ENDIAN); + break; + default: + return DDS_RETCODE_BAD_PARAMETER; } - return (unsigned char *) (par + 1); + const unsigned char *pl = buf; + const unsigned char *endp = pl + bufsz; + while (pl + sizeof (nn_parameter_t) <= endp) + { + const nn_parameter_t *par = (const nn_parameter_t *) pl; + nn_parameterid_t pid; + uint16_t length; + pid = (nn_parameterid_t) (bswap ? ddsrt_bswap2u (par->parameterid) : par->parameterid); + length = (uint16_t) (bswap ? ddsrt_bswap2u (par->length) : par->length); + pl += sizeof (*par); + + if (pid == PID_SENTINEL) + return (needlep && *needlep == NULL) ? DDS_RETCODE_NOT_FOUND : DDS_RETCODE_OK; + else if (length > (size_t) (endp - pl) || (length % 4) != 0 /* DDSI 9.4.2.11 */) + return DDS_RETCODE_BAD_PARAMETER; + else if (pid == needle) + { + *needlep = (void *) pl; + *needlesz = length; + } + pl += length; + } + return DDS_RETCODE_BAD_PARAMETER; } unsigned char *ddsi_plist_quickscan (struct nn_rsample_info *dest, const struct nn_rmsg *rmsg, const ddsi_plist_src_t *src) @@ -3379,6 +3425,9 @@ static void plist_or_xqos_print (char * __restrict *buf, size_t * __restrict buf /* shift == 0: plist, shift > 0: just qos */ const char *sep = ""; uint64_t pw, qw; + if (*bufsize == 0) + return; + (*buf)[0] = 0; if (shift > 0) { const dds_qos_t *qos = src; @@ -3464,3 +3513,10 @@ void ddsi_plist_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds { plist_or_xqos_log (cat, logcfg, plist, 0, ~(uint64_t)0, ~(uint64_t)0); } + +size_t plist_print_generic (char * __restrict buf, size_t bufsize, const void * __restrict src, const enum pserop * __restrict desc) +{ + const size_t bufsize_in = bufsize; + (void) print_generic (&buf, &bufsize, src, 0, desc); + return bufsize_in - bufsize; +} diff --git a/src/core/ddsi/src/ddsi_pmd.c b/src/core/ddsi/src/ddsi_pmd.c index 9e7db55..dd19eee 100644 --- a/src/core/ddsi/src/ddsi_pmd.c +++ b/src/core/ddsi/src/ddsi_pmd.c @@ -14,6 +14,7 @@ #include "dds/ddsi/ddsi_pmd.h" #include "dds/ddsi/ddsi_serdata.h" #include "dds/ddsi/ddsi_serdata_default.h" +#include "dds/ddsi/ddsi_serdata_pserop.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_entity.h" @@ -30,20 +31,13 @@ #include "dds/ddsi/sysdeps.h" -static void debug_print_rawdata (const struct ddsi_domaingv *gv, const char *msg, const void *data, size_t len) -{ - const unsigned char *c = data; - size_t i; - GVTRACE ("%s<", msg); - for (i = 0; i < len; i++) - { - if (32 < c[i] && c[i] <= 127) - GVTRACE ("%s%c", (i > 0 && (i%4) == 0) ? " " : "", c[i]); - else - GVTRACE ("%s\\x%02x", (i > 0 && (i%4) == 0) ? " " : "", c[i]); - } - GVTRACE (">"); -} +/* note: treating guid prefix + kind as if it were a GUID because that matches + the octet-sequence/sequence-of-uint32 distinction between the specified wire + representation and the internal representation */ +const enum pserop participant_message_data_ops[] = { XG, XO, XSTOP }; +size_t participant_message_data_nops = sizeof (participant_message_data_ops) / sizeof (participant_message_data_ops[0]); +const enum pserop participant_message_data_ops_key[] = { XG, XSTOP }; +size_t participant_message_data_nops_key = sizeof (participant_message_data_ops_key) / sizeof (participant_message_data_ops_key[0]); void write_pmd_message_guid (struct ddsi_domaingv * const gv, struct ddsi_guid *pp_guid, unsigned pmd_kind) { @@ -67,10 +61,8 @@ void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack *xp, s #define PMD_DATA_LENGTH 1 struct ddsi_domaingv * const gv = pp->e.gv; struct writer *wr; - union { - ParticipantMessageData_t pmd; - char pad[offsetof (ParticipantMessageData_t, value) + PMD_DATA_LENGTH]; - } u; + unsigned char data[PMD_DATA_LENGTH] = { 0 }; + ParticipantMessageData_t pmd; struct ddsi_serdata *serdata; struct ddsi_tkmap_instance *tk; @@ -80,18 +72,11 @@ void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack *xp, s return; } - u.pmd.participantGuidPrefix = nn_hton_guid_prefix (pp->e.guid.prefix); - u.pmd.kind = ddsrt_toBE4u (pmd_kind); - u.pmd.length = PMD_DATA_LENGTH; - memset (u.pmd.value, 0, u.pmd.length); - - struct ddsi_rawcdr_sample raw = { - .blob = &u, - .size = offsetof (ParticipantMessageData_t, value) + PMD_DATA_LENGTH, - .key = &u.pmd, - .keysize = 16 - }; - serdata = ddsi_serdata_from_sample (gv->rawcdr_topic, SDK_DATA, &raw); + pmd.participantGuidPrefix = pp->e.guid.prefix; + pmd.kind = pmd_kind; + pmd.value.length = (uint32_t) sizeof (data); + pmd.value.value = data; + serdata = ddsi_serdata_from_sample (gv->pmd_topic, SDK_DATA, &pmd); serdata->timestamp = ddsrt_time_wallclock (); tk = ddsi_tkmap_lookup_instance_ref (gv->m_tkmap, serdata); @@ -100,66 +85,44 @@ void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack *xp, s #undef PMD_DATA_LENGTH } -void handle_pmd_message (const struct receiver_state *rst, ddsrt_wctime_t timestamp, uint32_t statusinfo, const void *vdata, uint32_t len) +void handle_pmd_message (const struct receiver_state *rst, struct ddsi_serdata *sample_common) { - const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */ - const int bswap = (data->identifier == CDR_LE) ^ (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN); + /* use sample with knowledge of internal representation: there's a deserialized sample inside already */ + const struct ddsi_serdata_pserop *sample = (const struct ddsi_serdata_pserop *) sample_common; struct proxy_participant *proxypp; ddsi_guid_t ppguid; struct lease *l; - RSTTRACE (" PMD ST%x", statusinfo); - if (data->identifier != CDR_LE && data->identifier != CDR_BE) + RSTTRACE (" PMD ST%x", sample->c.statusinfo); + switch (sample->c.statusinfo & (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER)) { - RSTTRACE (" PMD data->identifier %u !?\n", ntohs (data->identifier)); - return; - } - - switch (statusinfo & (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER)) - { - case 0: - if (offsetof (ParticipantMessageData_t, value) > len - sizeof (struct CDRHeader)) - debug_print_rawdata (rst->gv, " SHORT1", data, len); - else + case 0: { + const ParticipantMessageData_t *pmd = sample->sample; + RSTTRACE (" pp %"PRIx32":%"PRIx32":%"PRIx32" kind %"PRIu32" data %"PRIu32, PGUIDPREFIX (pmd->participantGuidPrefix), pmd->kind, pmd->value.length); + ppguid.prefix = pmd->participantGuidPrefix; + ppguid.entityid.u = NN_ENTITYID_PARTICIPANT; + if ((proxypp = entidx_lookup_proxy_participant_guid (rst->gv->entity_index, &ppguid)) == NULL) + RSTTRACE (" PPunknown"); + else if (pmd->kind == PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE && + (l = ddsrt_atomic_ldvoidp (&proxypp->minl_man)) != NULL) { - const ParticipantMessageData_t *pmd = (ParticipantMessageData_t *) (data + 1); - ddsi_guid_prefix_t p = nn_ntoh_guid_prefix (pmd->participantGuidPrefix); - uint32_t kind = ntohl (pmd->kind); - uint32_t length = bswap ? ddsrt_bswap4u (pmd->length) : pmd->length; - RSTTRACE (" pp %"PRIx32":%"PRIx32":%"PRIx32" kind %u data %u", p.u[0], p.u[1], p.u[2], kind, length); - if (len - sizeof (struct CDRHeader) - offsetof (ParticipantMessageData_t, value) < length) - debug_print_rawdata (rst->gv, " SHORT2", pmd->value, len - sizeof (struct CDRHeader) - offsetof (ParticipantMessageData_t, value)); - else - debug_print_rawdata (rst->gv, "", pmd->value, length); - ppguid.prefix = p; - ppguid.entityid.u = NN_ENTITYID_PARTICIPANT; - if ((proxypp = entidx_lookup_proxy_participant_guid (rst->gv->entity_index, &ppguid)) == NULL) - RSTTRACE (" PPunknown"); - else if (kind == PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE && - (l = ddsrt_atomic_ldvoidp (&proxypp->minl_man)) != NULL) - { - /* Renew lease for entity with shortest manual-by-participant lease */ - lease_renew (l, ddsrt_time_elapsed ()); - } + /* Renew lease for entity with shortest manual-by-participant lease */ + lease_renew (l, ddsrt_time_elapsed ()); } break; + } case NN_STATUSINFO_DISPOSE: case NN_STATUSINFO_UNREGISTER: - case NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER: - /* Serialized key; BE or LE doesn't matter as both fields are - defined as octets. */ - if (len < sizeof (struct CDRHeader) + sizeof (ddsi_guid_prefix_t)) - debug_print_rawdata (rst->gv, " SHORT3", data, len); + case NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER: { + const ParticipantMessageData_t *pmd = sample->sample; + ppguid.prefix = pmd->participantGuidPrefix; + ppguid.entityid.u = NN_ENTITYID_PARTICIPANT; + if (delete_proxy_participant_by_guid (rst->gv, &ppguid, sample->c.timestamp, 0) < 0) + RSTTRACE (" unknown"); else - { - ppguid.prefix = nn_ntoh_guid_prefix (*((ddsi_guid_prefix_t *) (data + 1))); - ppguid.entityid.u = NN_ENTITYID_PARTICIPANT; - if (delete_proxy_participant_by_guid (rst->gv, &ppguid, timestamp, 0) < 0) - RSTTRACE (" unknown"); - else - RSTTRACE (" delete"); - } + RSTTRACE (" delete"); break; + } } RSTTRACE ("\n"); } diff --git a/src/core/ddsi/src/ddsi_security_exchange.c b/src/core/ddsi/src/ddsi_security_exchange.c index 45a6aed..6d8061d 100644 --- a/src/core/ddsi/src/ddsi_security_exchange.c +++ b/src/core/ddsi/src/ddsi_security_exchange.c @@ -22,6 +22,7 @@ #include "dds/ddsi/ddsi_serdata_default.h" #include "dds/ddsi/ddsi_security_omg.h" #include "dds/ddsi/ddsi_handshake.h" +#include "dds/ddsi/ddsi_serdata_pserop.h" #include "dds/ddsi/q_ddsi_discovery.h" #include "dds/ddsi/ddsi_tkmap.h" #include "dds/ddsi/q_xmsg.h" @@ -29,79 +30,11 @@ #include "dds/ddsi/q_log.h" #include "dds/ddsi/q_bswap.h" -//#define SECURITY_LOG_MESSAGE_DATA - -#ifdef SECURITY_LOG_MESSAGE_DATA -static void nn_property_seq_log(struct ddsi_domaingv *gv, const dds_propertyseq_t *seq) -{ - uint32_t i; - - GVTRACE("{"); - for (i = 0; i < seq->n; i++) { - GVTRACE("n=%s,v=%s", seq->props[i].name, seq->props[i].value); - } - GVTRACE("}"); -} - -static void nn_binary_property_seq_log(struct ddsi_domaingv *gv, const dds_binarypropertyseq_t *seq) -{ - uint32_t i; - - GVTRACE("{"); - for (i = 0; i < seq->n; i++) { - uint32_t j; - GVTRACE("n=%s,v={", seq->props[i].name); - for (j = 0; j < seq->props[i].value.length; j++) { - GVTRACE("%02x", seq->props[i].value.value[j]); - } - GVTRACE("}"); - } - GVTRACE("}"); -} - -static void nn_dataholder_seq_log(struct ddsi_domaingv *gv, const char *prefix, const nn_dataholderseq_t *dhseq) -{ - uint32_t i; - - GVTRACE("%s={", prefix); - for (i = 0; i < dhseq->n; i++) { - GVTRACE("cid=%s,", dhseq->tags[i].class_id); - nn_property_seq_log(gv, &dhseq->tags[i].properties); - GVTRACE(","); - nn_binary_property_seq_log(gv, &dhseq->tags[i].binary_properties); - } - GVTRACE("}"); -} -#endif - -static void nn_participant_generic_message_log(struct ddsi_domaingv *gv, const struct nn_participant_generic_message *msg, int conv) -{ - ddsi_guid_t spguid = conv ? nn_ntoh_guid(msg->message_identity.source_guid ): msg->message_identity.source_guid; - ddsi_guid_t rmguid = conv ? nn_ntoh_guid(msg->related_message_identity.source_guid) : msg->related_message_identity.source_guid; - ddsi_guid_t dpguid = conv ? nn_ntoh_guid(msg->destination_participant_guid) : msg->destination_participant_guid; - ddsi_guid_t deguid = conv ? nn_ntoh_guid(msg->destination_endpoint_guid) : msg->destination_endpoint_guid; - ddsi_guid_t seguid = conv ? nn_ntoh_guid(msg->source_endpoint_guid) : msg->source_endpoint_guid; - - GVTRACE (" msg="); - GVTRACE("mi=" PGUIDFMT "#%" PRId64 ",", PGUID(spguid), msg->message_identity.sequence_number); - GVTRACE("rmi=" PGUIDFMT "#%" PRId64 ",", PGUID(rmguid), msg->related_message_identity.sequence_number); - GVTRACE("dpg=" PGUIDFMT ",", PGUID(dpguid)); - GVTRACE("deg=" PGUIDFMT ",", PGUID(deguid)); - GVTRACE("seg=" PGUIDFMT ",", PGUID(seguid)); - GVTRACE("cid=%s", msg->message_class_id); -#ifdef SECURITY_LOG_MESSAGE_DATA - nn_dataholder_seq_log(gv, ",mdata", &msg->message_data); -#endif - GVTRACE ("\n"); -} - bool write_auth_handshake_message(const struct participant *pp, const struct proxy_participant *proxypp, nn_dataholderseq_t *mdata, bool request, const nn_message_identity_t *related_message_id) { struct ddsi_domaingv *gv = pp->e.gv; struct nn_participant_generic_message pmg; struct ddsi_serdata *serdata; - unsigned char *blob; - size_t len; struct writer *wr; int64_t seq; struct proxy_reader *prd; @@ -129,27 +62,10 @@ bool write_auth_handshake_message(const struct participant *pp, const struct pro nn_participant_generic_message_init(&pmg, &wr->e.guid, seq, &proxypp->e.guid, NULL, NULL, DDS_SECURITY_AUTH_HANDSHAKE, mdata, related_message_id); } - if (nn_participant_generic_message_serialize(&pmg, &blob, &len) != DDS_RETCODE_OK) - return false; - - GVTRACE("write_handshake("PGUIDFMT" --> "PGUIDFMT")(lguid="PGUIDFMT" rguid="PGUIDFMT") ", - PGUID (wr->e.guid), PGUID (prd_guid), - PGUID (pp->e.guid), PGUID (proxypp->e.guid)); - nn_participant_generic_message_log(gv, &pmg, 1); - - struct ddsi_rawcdr_sample raw = { - .blob = blob, - .size = len, - .key = NULL, - .keysize = 0 - }; - serdata = ddsi_serdata_from_sample (gv->rawcdr_topic, SDK_DATA, &raw); + serdata = ddsi_serdata_from_sample (wr->topic, SDK_DATA, &pmg); serdata->timestamp = ddsrt_time_wallclock (); - result = enqueue_sample_wrlock_held (wr, seq, NULL, serdata, prd, 1) == 0; ddsi_serdata_unref (serdata); - dds_free(blob); - ddsrt_mutex_unlock (&wr->e.lock); nn_participant_generic_message_deinit(&pmg); @@ -159,71 +75,53 @@ bool write_auth_handshake_message(const struct participant *pp, const struct pro void auth_get_serialized_participant_data(struct participant *pp, ddsi_octetseq_t *seq) { struct nn_xmsg *mpayload; + ddsi_plist_t ps; + struct participant_builtin_topic_data_locators locs; size_t sz; char *payload; - mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid, pp, 0, NN_XMSG_KIND_DATA); - - get_participant_builtin_topic_data(pp, mpayload, true); + get_participant_builtin_topic_data (pp, &ps, &locs); + ddsi_plist_addtomsg_bo (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0, true); + nn_xmsg_addpar_sentinel_bo (mpayload, true); + ddsi_plist_fini (&ps); payload = nn_xmsg_payload (&sz, mpayload); - - seq->length = (uint32_t)sz; - seq->value = ddsrt_malloc(sz); - memcpy(seq->value, payload, sz); + seq->length = (uint32_t) sz; + seq->value = ddsrt_malloc (sz); + memcpy (seq->value, payload, sz); nn_xmsg_free (mpayload); } -void handle_auth_handshake_message(const struct receiver_state *rst, ddsi_entityid_t wr_entity_id, ddsrt_wctime_t timestamp, unsigned statusinfo, const void *vdata, size_t len) +void handle_auth_handshake_message(const struct receiver_state *rst, ddsi_entityid_t wr_entity_id, struct ddsi_serdata *sample_common) { - const struct CDRHeader *hdr = vdata; /* built-ins not deserialized (yet) */ - const bool bswap = (hdr->identifier == CDR_LE) ^ DDSRT_LITTLE_ENDIAN; - const void *data = (void *) (hdr + 1); - size_t size = (len - sizeof(struct CDRHeader)); - struct nn_participant_generic_message msg; + const struct ddsi_serdata_pserop *sample = (const struct ddsi_serdata_pserop *) sample_common; + const struct nn_participant_generic_message *msg = sample->sample; struct participant *pp = NULL; struct proxy_writer *pwr = NULL; ddsi_guid_t guid; - ddsi_guid_t *pwr_guid; + const ddsi_guid_t *pwr_guid; struct ddsi_handshake *handshake; DDSRT_UNUSED_ARG(wr_entity_id); - DDSRT_UNUSED_ARG(timestamp); - RSTTRACE ("recv_handshake ST%x", statusinfo); - if ((hdr->identifier != CDR_LE) && (hdr->identifier != PL_CDR_LE) && - (hdr->identifier != CDR_BE) && (hdr->identifier != PL_CDR_BE)) + if (msg->message_identity.source_guid.entityid.u == NN_ENTITYID_PARTICIPANT) { - RSTTRACE (" data->identifier %d !?\n", ntohs (hdr->identifier)); - return; - } - - if (nn_participant_generic_message_deseralize(&msg, data, size, bswap) < 0) - { - RSTTRACE ("deserialize failed\n"); - goto err_deser; - } - - nn_participant_generic_message_log(rst->gv, &msg, 0); - - if (msg.message_identity.source_guid.entityid.u == NN_ENTITYID_PARTICIPANT) - { - guid = msg.message_identity.source_guid; + guid = msg->message_identity.source_guid; guid.entityid.u = NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER; - pwr_guid= &guid; + pwr_guid = &guid; } - else if (msg.message_identity.source_guid.entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER) + else if (msg->message_identity.source_guid.entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER) { - pwr_guid= &msg.message_identity.source_guid; + pwr_guid = &msg->message_identity.source_guid; } else { RSTTRACE ("invalid source entity id\n"); - goto invalid_source; + return; } - if ((pp = entidx_lookup_participant_guid(rst->gv->entity_index, &msg.destination_participant_guid)) == NULL) + if ((pp = entidx_lookup_participant_guid(rst->gv->entity_index, &msg->destination_participant_guid)) == NULL) { - RSTTRACE ("destination participant ("PGUIDFMT") not found\n", PGUID(msg.destination_participant_guid)); + RSTTRACE ("destination participant ("PGUIDFMT") not found\n", PGUID (msg->destination_participant_guid)); } else if ((pwr = entidx_lookup_proxy_writer_guid(rst->gv->entity_index, pwr_guid)) == NULL) { @@ -235,15 +133,10 @@ void handle_auth_handshake_message(const struct receiver_state *rst, ddsi_entity } else { -// RSTTRACE (" ("PGUIDFMT" --> "PGUIDFMT")\n", PGUID (pwr->c.proxypp->e.guid), PGUID (pp->e.guid)); - ddsi_handshake_handle_message(handshake, pp, pwr->c.proxypp, &msg); - ddsi_handshake_release(handshake); + //RSTTRACE (" ("PGUIDFMT" --> "PGUIDFMT")\n", PGUID (pwr->c.proxypp->e.guid), PGUID (pp->e.guid)); + ddsi_handshake_handle_message (handshake, pp, pwr->c.proxypp, msg); + ddsi_handshake_release (handshake); } - -invalid_source: - nn_participant_generic_message_deinit(&msg); -err_deser: - return; } static bool write_crypto_exchange_message(const struct participant *pp, const ddsi_guid_t *dst_pguid, const ddsi_guid_t *src_eguid, const ddsi_guid_t *dst_eguid, const char *classid, const nn_dataholderseq_t *tokens) @@ -254,8 +147,6 @@ static bool write_crypto_exchange_message(const struct participant *pp, const dd struct ddsi_serdata *serdata; struct proxy_reader *prd; ddsi_guid_t prd_guid; - unsigned char *data; - size_t len; struct writer *wr; seqno_t seq; int r; @@ -278,30 +169,11 @@ static bool write_crypto_exchange_message(const struct participant *pp, const dd /* Get serialized message. */ nn_participant_generic_message_init(&pmg, &wr->e.guid, seq, dst_pguid, dst_eguid, src_eguid, classid, tokens, NULL); - nn_participant_generic_message_serialize(&pmg, &data, &len); - - nn_participant_generic_message_log(gv, &pmg, 0); - - /* Get the key value. */ - ddsrt_md5_state_t md5st; - ddsrt_md5_byte_t digest[16]; - ddsrt_md5_init (&md5st); - ddsrt_md5_append (&md5st, (const ddsrt_md5_byte_t *)data, sizeof (nn_message_identity_t)); - ddsrt_md5_finish (&md5st, digest); - - /* Write the sample. */ - struct ddsi_rawcdr_sample raw = { - .blob = data, - .size = len, - .key = digest, - .keysize = 16 - }; - serdata = ddsi_serdata_from_sample (gv->rawcdr_topic, SDK_DATA, &raw); + serdata = ddsi_serdata_from_sample (wr->topic, SDK_DATA, &pmg); + serdata->timestamp = ddsrt_time_wallclock (); tk = ddsi_tkmap_lookup_instance_ref (gv->m_tkmap, serdata); - r = write_sample_p2p_wrlock_held(wr, seq, NULL, serdata, tk, prd); ddsrt_mutex_unlock (&wr->e.lock); - ddsrt_free(data); ddsi_tkmap_instance_unref (gv->m_tkmap, tk); ddsi_serdata_unref (serdata); @@ -331,86 +203,51 @@ bool write_crypto_reader_tokens(const struct reader *rd, const struct proxy_writ return write_crypto_exchange_message(pp, &proxypp->e.guid, &rd->e.guid, &pwr->e.guid, GMCLASSID_SECURITY_DATAREADER_CRYPTO_TOKENS, tokens); } -void handle_crypto_exchange_message(const struct receiver_state *rst, ddsi_entityid_t wr_entity_id, ddsrt_wctime_t timestamp, unsigned statusinfo, const void *vdata, unsigned len) +void handle_crypto_exchange_message(const struct receiver_state *rst, struct ddsi_serdata *sample_common) { - struct ddsi_domaingv *gv = rst->gv; - const struct CDRHeader *hdr = vdata; /* built-ins not deserialized (yet) */ - const int bswap = (hdr->identifier == CDR_LE) ^ DDSRT_LITTLE_ENDIAN; - const void *data = (void *) (hdr + 1); - unsigned size = (unsigned)(len - sizeof(struct CDRHeader)); - struct nn_participant_generic_message msg; - ddsi_guid_t rd_guid; - ddsi_guid_t pwr_guid; + struct ddsi_domaingv * const gv = rst->gv; + const struct ddsi_serdata_pserop *sample = (const struct ddsi_serdata_pserop *) sample_common; + const struct nn_participant_generic_message *msg = sample->sample; ddsi_guid_t proxypp_guid; - struct participant *pp; - struct proxy_participant *proxypp; - DDSRT_UNUSED_ARG(timestamp); - - rd_guid.prefix = rst->dst_guid_prefix; - rd_guid.entityid.u = NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER; - pwr_guid.prefix = rst->src_guid_prefix; - pwr_guid.entityid = wr_entity_id; - - GVTRACE ("recv crypto tokens ("PGUIDFMT" --> "PGUIDFMT") ST%x", PGUID (pwr_guid), PGUID (rd_guid), statusinfo); - - memset(&msg, 0, sizeof(msg)); - if (nn_participant_generic_message_deseralize(&msg, data, size, bswap) < 0) - goto deser_msg_failed; - - nn_participant_generic_message_log(gv, &msg, 0); - - if (!msg.message_class_id) - { - ddsi_guid_t guid; - guid.prefix = rst->dst_guid_prefix; - guid.entityid.u = NN_ENTITYID_PARTICIPANT; - GVWARNING("participant "PGUIDFMT" received a crypto exchange message with empty class_id", PGUID(guid)); - goto invalid_msg; - } - - proxypp_guid.prefix = msg.message_identity.source_guid.prefix; + proxypp_guid.prefix = msg->message_identity.source_guid.prefix; proxypp_guid.entityid.u = NN_ENTITYID_PARTICIPANT; - if (strcmp(GMCLASSID_SECURITY_PARTICIPANT_CRYPTO_TOKENS, msg.message_class_id) == 0) + if (strcmp(GMCLASSID_SECURITY_PARTICIPANT_CRYPTO_TOKENS, msg->message_class_id) == 0) { - pp = entidx_lookup_participant_guid(gv->entity_index, &msg.destination_participant_guid); + struct participant * const pp = entidx_lookup_participant_guid(gv->entity_index, &msg->destination_participant_guid); if (!pp) { - GVWARNING("received a crypto exchange message from "PGUIDFMT" with participant unknown "PGUIDFMT, PGUID(proxypp_guid), PGUID(msg.destination_participant_guid)); - goto invalid_msg; + GVWARNING("received a crypto exchange message from "PGUIDFMT" with participant unknown "PGUIDFMT, PGUID(proxypp_guid), PGUID(msg->destination_participant_guid)); + return; } - proxypp = entidx_lookup_proxy_participant_guid(gv->entity_index, &proxypp_guid); + struct proxy_participant *proxypp = entidx_lookup_proxy_participant_guid(gv->entity_index, &proxypp_guid); if (!proxypp) { - GVWARNING("received a crypto exchange message from "PGUIDFMT" with proxy participant unknown "PGUIDFMT, PGUID(proxypp_guid), PGUID(msg.destination_participant_guid)); - goto invalid_msg; + GVWARNING("received a crypto exchange message from "PGUIDFMT" with proxy participant unknown "PGUIDFMT, PGUID(proxypp_guid), PGUID(msg->destination_participant_guid)); + return; } - q_omg_security_set_participant_crypto_tokens(pp, proxypp, &msg.message_data); + q_omg_security_set_participant_crypto_tokens(pp, proxypp, &msg->message_data); } - else if (strcmp(GMCLASSID_SECURITY_DATAWRITER_CRYPTO_TOKENS, msg.message_class_id) == 0) + else if (strcmp(GMCLASSID_SECURITY_DATAWRITER_CRYPTO_TOKENS, msg->message_class_id) == 0) { - struct reader *rd; - - rd = entidx_lookup_reader_guid(gv->entity_index, &msg.destination_endpoint_guid); + struct reader * const rd = entidx_lookup_reader_guid(gv->entity_index, &msg->destination_endpoint_guid); if (!rd) { - GVWARNING("received a crypto exchange message from "PGUIDFMT" with reader unknown "PGUIDFMT, PGUID(proxypp_guid), PGUID(msg.destination_participant_guid)); - goto invalid_msg; + GVWARNING("received a crypto exchange message from "PGUIDFMT" with reader unknown "PGUIDFMT, PGUID(proxypp_guid), PGUID(msg->destination_participant_guid)); + return; } - q_omg_security_set_remote_writer_crypto_tokens(rd, &msg.source_endpoint_guid, &msg.message_data); + q_omg_security_set_remote_writer_crypto_tokens(rd, &msg->source_endpoint_guid, &msg->message_data); } - else if (strcmp(GMCLASSID_SECURITY_DATAREADER_CRYPTO_TOKENS, msg.message_class_id) == 0) + else if (strcmp(GMCLASSID_SECURITY_DATAREADER_CRYPTO_TOKENS, msg->message_class_id) == 0) { - struct writer *wr; - - wr = entidx_lookup_writer_guid(gv->entity_index, &msg.destination_endpoint_guid); + struct writer * const wr = entidx_lookup_writer_guid(gv->entity_index, &msg->destination_endpoint_guid); if (!wr) { - GVWARNING("received a crypto exchange message from "PGUIDFMT" with writer unknown "PGUIDFMT, PGUID(proxypp_guid), PGUID(msg.destination_participant_guid)); - goto invalid_msg; + GVWARNING("received a crypto exchange message from "PGUIDFMT" with writer unknown "PGUIDFMT, PGUID(proxypp_guid), PGUID(msg->destination_participant_guid)); + return; } - q_omg_security_set_remote_reader_crypto_tokens(wr, &msg.source_endpoint_guid, &msg.message_data); + q_omg_security_set_remote_reader_crypto_tokens(wr, &msg->source_endpoint_guid, &msg->message_data); } else { @@ -419,12 +256,6 @@ void handle_crypto_exchange_message(const struct receiver_state *rst, ddsi_entit guid.entityid.u = NN_ENTITYID_PARTICIPANT; GVWARNING("participant "PGUIDFMT" received a crypto exchange message with unknown class_id", PGUID(guid)); } - -invalid_msg: - nn_participant_generic_message_deinit(&msg); -deser_msg_failed: - return; } - #endif /* DDSI_INCLUDE_SECURITY */ diff --git a/src/core/ddsi/src/ddsi_security_msg.c b/src/core/ddsi/src/ddsi_security_msg.c index 8838327..ce44537 100644 --- a/src/core/ddsi/src/ddsi_security_msg.c +++ b/src/core/ddsi/src/ddsi_security_msg.c @@ -25,7 +25,6 @@ #include "dds/ddsi/ddsi_plist.h" #include "dds/security/core/dds_security_utils.h" - const enum pserop pserop_participant_generic_message[] = { /* nn_participant_generic_message */ @@ -47,7 +46,7 @@ const enum pserop pserop_participant_generic_message[] = XSTOP, XSTOP /* end */ }; - +const size_t pserop_participant_generic_message_nops = sizeof (pserop_participant_generic_message) / sizeof (pserop_participant_generic_message[0]); static void alias_simple_sequence(ddsi_octetseq_t *dst, const ddsi_octetseq_t *src, size_t elem_size) diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 46a0d0b..c046a72 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -762,61 +762,6 @@ error: return DDS_RETCODE_ERROR; } -static const char * get_builtin_topic_name(ddsi_entityid_t id) -{ - switch (id.u) { - case NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER: - case NN_ENTITYID_SEDP_BUILTIN_TOPIC_READER: - return "DCPSTopic"; - break; - case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER: - case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER: - return "DCPSPublication"; - break; - case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER: - case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER: - return "DCPSSubscription"; - break; - case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER: - case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER: - return "DCPSParticipant"; - break; - case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER: - case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER: - return "DCPSParticipantMessage"; - break; - case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER: - case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_READER: - return "DCPSPublicationsSecure"; - break; - case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER: - case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_READER: - return "DCPSSubscriptionsSecure"; - break; - case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER: - case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_READER: - return "DCPSParticipantStatelessMessage"; - break; - case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER: - case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_READER: - return "DCPSParticipantMessageSecure"; - break; - case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER: - case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER: - return "DCPSParticipantVolatileMessageSecure"; - break; - case NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER: - case NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_READER: - return "DCPSParticipantsSecure"; - break; - default: - return "(null)"; - break; - } - - return NULL; -} - static void notify_handshake_recv_token(struct participant *pp, struct proxy_participant *proxypp) { struct ddsi_handshake *handshake; @@ -828,22 +773,6 @@ static void notify_handshake_recv_token(struct participant *pp, struct proxy_par } } -static const char * get_reader_topic_name(struct reader *rd) -{ - if (rd->topic) { - return rd->topic->name; - } - return get_builtin_topic_name(rd->e.guid.entityid); -} - -static const char * get_writer_topic_name(struct writer *wr) -{ - if (wr->topic) { - return wr->topic->name; - } - return get_builtin_topic_name(wr->e.guid.entityid); -} - bool q_omg_participant_is_secure(const struct participant *pp) { return ((pp->sec_attr != NULL) && (pp->sec_attr->crypto_handle != DDS_SECURITY_HANDLE_NIL)); @@ -1292,7 +1221,6 @@ void q_omg_security_register_writer(struct writer *wr) DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; DDS_Security_PartitionQosPolicy partitions; DDS_Security_PropertySeq properties; - const char *topic_name; if (!sc) return; @@ -1303,8 +1231,7 @@ void q_omg_security_register_writer(struct writer *wr) memset(&(partitions), 0, sizeof(DDS_Security_PartitionQosPolicy)); wr->sec_attr = writer_sec_attributes_new(); - topic_name = get_writer_topic_name(wr); - if (!sc->access_control_context->get_datawriter_sec_attributes(sc->access_control_context, pp->sec_attr->permissions_handle, topic_name, &partitions, NULL, &wr->sec_attr->attr, &exception)) + if (!sc->access_control_context->get_datawriter_sec_attributes(sc->access_control_context, pp->sec_attr->permissions_handle, wr->topic->name, &partitions, NULL, &wr->sec_attr->attr, &exception)) { EXCEPTION_ERROR(sc, &exception, "Failed to retrieve writer security attributes"); goto no_attr; @@ -1413,7 +1340,6 @@ void q_omg_security_register_reader(struct reader *rd) DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; DDS_Security_PartitionQosPolicy partitions; DDS_Security_PropertySeq properties; - const char *topic_name; if (!sc) return; @@ -1425,8 +1351,7 @@ void q_omg_security_register_reader(struct reader *rd) rd->sec_attr = reader_sec_attributes_new(); - topic_name = get_reader_topic_name(rd); - if (!sc->access_control_context->get_datareader_sec_attributes(sc->access_control_context, pp->sec_attr->permissions_handle, topic_name, &partitions, NULL, &rd->sec_attr->attr, &exception)) + if (!sc->access_control_context->get_datareader_sec_attributes(sc->access_control_context, pp->sec_attr->permissions_handle, rd->topic->name, &partitions, NULL, &rd->sec_attr->attr, &exception)) { EXCEPTION_ERROR(sc, &exception, "Failed to retrieve reader security attributes"); goto no_attr; @@ -2650,7 +2575,7 @@ static bool q_omg_security_encode_datareader_submessage(struct reader *rd, const const struct dds_security_context *sc = q_omg_security_get_secure_context (rd->c.pp); assert (sc); - GVTRACE (" encode_datareader_submessage "PGUIDFMT" %s/%s", PGUID (rd->e.guid), get_reader_topic_name (rd), rd->topic ? rd->topic->type_name : "(null)"); + GVTRACE (" encode_datareader_submessage "PGUIDFMT" %s/%s", PGUID (rd->e.guid), rd->topic->name, rd->topic->type_name); // FIXME: print_buf(src_buf, src_len, "q_omg_security_encode_datareader_submessage(SOURCE)"); ddsrt_mutex_lock (&rd->e.lock); @@ -2665,8 +2590,7 @@ static bool q_omg_security_encode_datareader_submessage(struct reader *rd, const if ((hdls._length = (DDS_Security_unsigned_long) idx) == 0) { - GVTRACE ("Submsg encoding failed for datareader "PGUIDFMT" %s/%s: no matching writers\n", PGUID (rd->e.guid), - get_reader_topic_name (rd), rd->topic ? rd->topic->type_name : "(null)"); + GVTRACE ("Submsg encoding failed for datareader "PGUIDFMT" %s/%s: no matching writers\n", PGUID (rd->e.guid), rd->topic->name, rd->topic->type_name); goto err_enc_drd_subm; } @@ -2678,8 +2602,8 @@ static bool q_omg_security_encode_datareader_submessage(struct reader *rd, const if (!(result = sc->crypto_context->crypto_transform->encode_datareader_submessage ( sc->crypto_context->crypto_transform, &encoded_buffer, &plain_buffer, rd->sec_attr->crypto_handle, &hdls, &ex))) { - GVWARNING ("Submsg encoding failed for datareader "PGUIDFMT" %s/%s: %s", PGUID (rd->e.guid), get_reader_topic_name (rd), - rd->topic ? rd->topic->type_name : "(null)", ex.message ? ex.message : "Unknown error"); + GVWARNING ("Submsg encoding failed for datareader "PGUIDFMT" %s/%s: %s", PGUID (rd->e.guid), rd->topic->name, + rd->topic->type_name, ex.message ? ex.message : "Unknown error"); GVTRACE ("\n"); DDS_Security_Exception_reset (&ex); goto err_enc_drd_subm; @@ -2723,7 +2647,7 @@ static bool q_omg_security_encode_datawriter_submessage (struct writer *wr, cons const struct dds_security_context *sc = q_omg_security_get_secure_context (wr->c.pp); assert (sc); - GVTRACE (" encode_datawriter_submessage "PGUIDFMT" %s/%s", PGUID (wr->e.guid), get_writer_topic_name (wr), wr->topic ? wr->topic->type_name : "(null)"); + GVTRACE (" encode_datawriter_submessage "PGUIDFMT" %s/%s", PGUID (wr->e.guid), wr->topic->name, wr->topic->type_name); // FIXME: print_buf(src_buf, src_len, "q_omg_security_encode_datawriter_submessage(SOURCE)"); @@ -2738,7 +2662,7 @@ static bool q_omg_security_encode_datawriter_submessage (struct writer *wr, cons if ((hdls._length = (DDS_Security_unsigned_long) idx) == 0) { GVTRACE ("Submsg encoding failed for datawriter "PGUIDFMT" %s/%s: no matching readers\n", PGUID (wr->e.guid), - get_writer_topic_name (wr), wr->topic ? wr->topic->type_name : "(null)"); + wr->topic->name, wr->topic->type_name); goto err_enc_dwr_subm; } @@ -2762,8 +2686,7 @@ static bool q_omg_security_encode_datawriter_submessage (struct writer *wr, cons if (!result) { - GVWARNING ("Submsg encoding failed for datawriter "PGUIDFMT" %s/%s: %s", PGUID (wr->e.guid), get_writer_topic_name (wr), - wr->topic ? wr->topic->type_name : "(null)", ex.message ? ex.message : "Unknown error"); + GVWARNING ("Submsg encoding failed for datawriter "PGUIDFMT" %s/%s: %s", PGUID (wr->e.guid), wr->topic->name, wr->topic->type_name, ex.message ? ex.message : "Unknown error"); GVTRACE ("\n"); DDS_Security_Exception_reset (&ex); goto err_enc_dwr_subm; @@ -2916,7 +2839,7 @@ static bool q_omg_security_encode_serialized_payload (const struct writer *wr, c // FIXME: print_buf(src_buf, src_len, "q_omg_security_encode_serialized_payload(SOURCE)"); - GVTRACE (" encode_payload "PGUIDFMT" %s/%s\n", PGUID (wr->e.guid), wr->topic ? wr->topic->name : "(null)", wr->topic ? wr->topic->type_name : "(null)"); + GVTRACE (" encode_payload "PGUIDFMT" %s/%s\n", PGUID (wr->e.guid), wr->topic->name, wr->topic->type_name); memset (&extra_inline_qos, 0, sizeof (extra_inline_qos)); memset (&encoded_buffer, 0, sizeof (encoded_buffer)); diff --git a/src/core/ddsi/src/ddsi_serdata_default.c b/src/core/ddsi/src/ddsi_serdata_default.c index bd49d4b..4a37c91 100644 --- a/src/core/ddsi/src/ddsi_serdata_default.c +++ b/src/core/ddsi/src/ddsi_serdata_default.c @@ -461,92 +461,6 @@ static struct ddsi_serdata *serdata_default_from_sample_cdr_nokey (const struct return fix_serdata_default_nokey (d, tpcmn->serdata_basehash); } -static struct ddsi_serdata *serdata_default_from_sample_plist (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, const void *vsample) -{ - /* Currently restricted to DDSI discovery data (XTypes will need a rethink of the default representation and that may result in discovery data being moved to that new representation), and that means: keys are either GUIDs or an unbounded string for topics, for which MD5 is acceptable. Furthermore, these things don't get written very often, so scanning the parameter list to get the key value out is good enough for now. And at least it keeps the DDSI discovery data writing out of the internals of the sample representation */ - const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)tpcmn; - const struct ddsi_plist_sample *sample = vsample; - struct ddsi_serdata_default *d = serdata_default_new(tp, kind); - if (d == NULL) - return NULL; - serdata_default_append_blob (&d, 1, sample->size, sample->blob); - const unsigned char *rawkey = ddsi_plist_findparam_native_unchecked (sample->blob, sample->keyparam); -#ifndef NDEBUG - size_t keysize; -#endif - assert(rawkey); - switch (sample->keyparam) - { - case PID_PARTICIPANT_GUID: - case PID_ENDPOINT_GUID: - case PID_GROUP_GUID: - d->keyhash.m_set = 1; - d->keyhash.m_iskey = 1; - d->keyhash.m_keysize = sizeof(d->keyhash.m_hash); - memcpy (d->keyhash.m_hash, rawkey, 16); -#ifndef NDEBUG - keysize = 16; -#endif - break; - - case PID_TOPIC_NAME: { - const char *topic_name = (const char *) (rawkey + sizeof(uint32_t)); - uint32_t topic_name_sz; - uint32_t topic_name_sz_BE; - ddsrt_md5_state_t md5st; - ddsrt_md5_byte_t digest[16]; - topic_name_sz = (uint32_t) strlen (topic_name) + 1; - topic_name_sz_BE = ddsrt_toBE4u (topic_name_sz); - d->keyhash.m_set = 1; - d->keyhash.m_iskey = 0; - d->keyhash.m_keysize = sizeof(d->keyhash.m_hash); - ddsrt_md5_init (&md5st); - ddsrt_md5_append (&md5st, (const ddsrt_md5_byte_t *) &topic_name_sz_BE, sizeof (topic_name_sz_BE)); - ddsrt_md5_append (&md5st, (const ddsrt_md5_byte_t *) topic_name, topic_name_sz); - ddsrt_md5_finish (&md5st, digest); - memcpy (d->keyhash.m_hash, digest, 16); -#ifndef NDEBUG - keysize = sizeof (uint32_t) + topic_name_sz; -#endif - break; - } - - default: - abort(); - } - - /* if it is supposed to be just a key, rawkey must be be the first field and followed only by a sentinel */ - assert (kind != SDK_KEY || rawkey == (const unsigned char *)sample->blob + sizeof (nn_parameter_t)); - assert (kind != SDK_KEY || sample->size == sizeof (nn_parameter_t) + alignup_size (keysize, 4) + sizeof (nn_parameter_t)); - return fix_serdata_default (d, tp->c.serdata_basehash); -} - -static struct ddsi_serdata *serdata_default_from_sample_rawcdr (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, const void *vsample) -{ - /* Currently restricted to DDSI discovery data (XTypes will need a rethink of the default representation and that may result in discovery data being moved to that new representation), and that means: keys are either GUIDs or an unbounded string for topics, for which MD5 is acceptable. Furthermore, these things don't get written very often, so scanning the parameter list to get the key value out is good enough for now. And at least it keeps the DDSI discovery data writing out of the internals of the sample representation */ - const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)tpcmn; - const struct ddsi_rawcdr_sample *sample = vsample; - struct ddsi_serdata_default *d = serdata_default_new(tp, kind); - if (d == NULL) - return NULL; - assert (sample->keysize <= 16); - serdata_default_append_blob (&d, 1, sample->size, sample->blob); - serdata_default_append_aligned (&d, 0, 4); - d->keyhash.m_set = 1; - d->keyhash.m_iskey = 1; - if (sample->keysize == 0) - { - d->keyhash.m_keysize = 0; - return fix_serdata_default_nokey (d, tp->c.serdata_basehash); - } - else - { - memcpy (&d->keyhash.m_hash, sample->key, sample->keysize); - d->keyhash.m_keysize = (unsigned)sample->keysize & 0x1f; - return fix_serdata_default (d, tp->c.serdata_basehash); - } -} - static struct ddsi_serdata *serdata_default_to_topicless (const struct ddsi_serdata *serdata_common) { const struct ddsi_serdata_default *d = (const struct ddsi_serdata_default *)serdata_common; @@ -669,37 +583,6 @@ static size_t serdata_default_print_cdr (const struct ddsi_sertopic *sertopic_co return dds_stream_print_sample (&is, tp, buf, size); } -static size_t serdata_default_print_plist (const struct ddsi_sertopic *sertopic_common, const struct ddsi_serdata *serdata_common, char *buf, size_t size) -{ - const struct ddsi_serdata_default *d = (const struct ddsi_serdata_default *)serdata_common; - const struct ddsi_sertopic_default *tp = (const struct ddsi_sertopic_default *)sertopic_common; - ddsi_plist_src_t src; - ddsi_plist_t tmp; - src.buf = (const unsigned char *) d->data; - src.bufsz = d->pos; - src.encoding = d->hdr.identifier; - src.factory = tp->c.gv->m_factory; - src.logconfig = &tp->c.gv->logconfig; - src.protocol_version.major = RTPS_MAJOR; - src.protocol_version.minor = RTPS_MINOR; - src.strict = false; - src.vendorid = NN_VENDORID_ECLIPSE; - if (ddsi_plist_init_frommsg (&tmp, NULL, ~(uint64_t)0, ~(uint64_t)0, &src) < 0) - return (size_t) snprintf (buf, size, "(unparseable-plist)"); - else - { - size_t ret = ddsi_plist_print (buf, size, &tmp); - ddsi_plist_fini (&tmp); - return ret; - } -} - -static size_t serdata_default_print_raw (const struct ddsi_sertopic *sertopic_common, const struct ddsi_serdata *serdata_common, char *buf, size_t size) -{ - (void)sertopic_common; (void)serdata_common; - return (size_t) snprintf (buf, size, "(blob)"); -} - static void serdata_default_get_keyhash (const struct ddsi_serdata *serdata_common, struct ddsi_keyhash *buf, bool force_md5) { const struct ddsi_serdata_default *d = (const struct ddsi_serdata_default *)serdata_common; @@ -753,39 +636,3 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_cdr_nokey = { .print = serdata_default_print_cdr, .get_keyhash = serdata_default_get_keyhash }; - -const struct ddsi_serdata_ops ddsi_serdata_ops_plist = { - .get_size = serdata_default_get_size, - .eqkey = serdata_default_eqkey, - .free = serdata_default_free, - .from_ser = serdata_default_from_ser, - .from_ser_iov = serdata_default_from_ser_iov, - .from_keyhash = 0, - .from_sample = serdata_default_from_sample_plist, - .to_ser = serdata_default_to_ser, - .to_sample = 0, - .to_ser_ref = serdata_default_to_ser_ref, - .to_ser_unref = serdata_default_to_ser_unref, - .to_topicless = serdata_default_to_topicless, - .topicless_to_sample = 0, - .print = serdata_default_print_plist, - .get_keyhash = serdata_default_get_keyhash -}; - -const struct ddsi_serdata_ops ddsi_serdata_ops_rawcdr = { - .get_size = serdata_default_get_size, - .eqkey = serdata_default_eqkey, - .free = serdata_default_free, - .from_ser = serdata_default_from_ser, - .from_ser_iov = serdata_default_from_ser_iov, - .from_keyhash = 0, - .from_sample = serdata_default_from_sample_rawcdr, - .to_ser = serdata_default_to_ser, - .to_sample = 0, - .to_ser_ref = serdata_default_to_ser_ref, - .to_ser_unref = serdata_default_to_ser_unref, - .to_topicless = serdata_default_to_topicless, - .topicless_to_sample = 0, - .print = serdata_default_print_raw, - .get_keyhash = serdata_default_get_keyhash -}; diff --git a/src/core/ddsi/src/ddsi_serdata_plist.c b/src/core/ddsi/src/ddsi_serdata_plist.c new file mode 100644 index 0000000..225f9e9 --- /dev/null +++ b/src/core/ddsi/src/ddsi_serdata_plist.c @@ -0,0 +1,303 @@ +/* + * Copyright(c) 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include + +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/log.h" +#include "dds/ddsrt/md5.h" +#include "dds/ddsrt/mh3.h" +#include "dds/ddsi/q_bswap.h" +#include "dds/ddsi/q_config.h" +#include "dds/ddsi/q_freelist.h" +#include "dds/ddsi/ddsi_tkmap.h" +#include "dds/ddsi/ddsi_cdrstream.h" +#include "dds/ddsi/q_radmin.h" +#include "dds/ddsi/ddsi_domaingv.h" +#include "dds/ddsi/ddsi_serdata_plist.h" +#include "dds/ddsi/q_xmsg.h" + +static uint32_t serdata_plist_get_size (const struct ddsi_serdata *dcmn) +{ + const struct ddsi_serdata_plist *d = (const struct ddsi_serdata_plist *) dcmn; + return 4 + d->pos; // FIXME: +4 for CDR header should be eliminated +} + +static bool serdata_plist_eqkey (const struct ddsi_serdata *acmn, const struct ddsi_serdata *bcmn) +{ + const struct ddsi_serdata_plist *a = (const struct ddsi_serdata_plist *) acmn; + const struct ddsi_serdata_plist *b = (const struct ddsi_serdata_plist *) bcmn; + return memcmp (&a->keyhash, &b->keyhash, sizeof (a->keyhash)) == 0; +} + +static void serdata_plist_free (struct ddsi_serdata *dcmn) +{ + struct ddsi_serdata_plist *d = (struct ddsi_serdata_plist *) dcmn; + ddsrt_free (d); +} + +static struct ddsi_serdata_plist *serdata_plist_new (const struct ddsi_sertopic_plist *tp, enum ddsi_serdata_kind kind, size_t size, const void *cdr_header) +{ + /* FIXME: check whether this really is the correct maximum: offsets are relative + to the CDR header, but there are also some places that use a serdata as-if it + were a stream, and those use offsets (m_index) relative to the start of the + serdata */ + if (size < 4 || size > UINT32_MAX - offsetof (struct ddsi_serdata_plist, identifier)) + return NULL; + struct ddsi_serdata_plist *d = ddsrt_malloc (sizeof (*d) + size); + if (d == NULL) + return NULL; + ddsi_serdata_init (&d->c, &tp->c, kind); + d->pos = 0; + d->size = (uint32_t) size; + // FIXME: vendorid/protoversion are not available when creating a serdata + // these should be overruled by the one creating the serdata + d->vendorid = NN_VENDORID_UNKNOWN; + d->protoversion.major = RTPS_MAJOR; + d->protoversion.minor = RTPS_MINOR; + const uint16_t *hdrsrc = cdr_header; + d->identifier = hdrsrc[0]; + d->options = hdrsrc[1]; + if (d->identifier != PL_CDR_LE && d->identifier != PL_CDR_BE) + { + ddsrt_free (d); + return NULL; + } + return d; +} + +static struct ddsi_serdata *serdata_plist_fix (const struct ddsi_sertopic_plist *tp, struct ddsi_serdata_plist *d) +{ + assert (tp->keyparam != PID_SENTINEL); + void *needlep; + size_t needlesz; + if (ddsi_plist_findparam_checking (d->data, d->pos, d->identifier, tp->keyparam, &needlep, &needlesz) != DDS_RETCODE_OK) + { + ddsrt_free (d); + return NULL; + } + assert (needlep); + if (needlesz != sizeof (d->keyhash)) + { + ddsrt_free (d); + return NULL; + } + memcpy (&d->keyhash, needlep, 16); + d->c.hash = ddsrt_mh3 (&d->keyhash, sizeof (d->keyhash), 0) ^ tp->c.serdata_basehash; + return &d->c; +} + +static struct ddsi_serdata *serdata_plist_from_ser (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, const struct nn_rdata *fragchain, size_t size) +{ + const struct ddsi_sertopic_plist *tp = (const struct ddsi_sertopic_plist *) tpcmn; + struct ddsi_serdata_plist *d = serdata_plist_new (tp, kind, size, NN_RMSG_PAYLOADOFF (fragchain->rmsg, NN_RDATA_PAYLOAD_OFF (fragchain))); + uint32_t off = 4; /* must skip the CDR header */ + assert (fragchain->min == 0); + assert (fragchain->maxp1 >= off); /* CDR header must be in first fragment */ + while (fragchain) + { + assert (fragchain->min <= off); + assert (fragchain->maxp1 <= size); + if (fragchain->maxp1 > off) + { + /* only copy if this fragment adds data */ + const unsigned char *payload = NN_RMSG_PAYLOADOFF (fragchain->rmsg, NN_RDATA_PAYLOAD_OFF (fragchain)); + uint32_t n = fragchain->maxp1 - off; + memcpy (d->data + d->pos, payload + off - fragchain->min, n); + d->pos += n; + off = fragchain->maxp1; + } + fragchain = fragchain->nextfrag; + } + return serdata_plist_fix (tp, d); +} + +static struct ddsi_serdata *serdata_plist_from_ser_iov (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size) +{ + const struct ddsi_sertopic_plist *tp = (const struct ddsi_sertopic_plist *) tpcmn; + assert (niov >= 1); + struct ddsi_serdata_plist *d = serdata_plist_new (tp, kind, size, iov[0].iov_base); + memcpy (d->data + d->pos, (const char *) iov[0].iov_base + 4, iov[0].iov_len - 4); + d->pos += (uint32_t) iov[0].iov_len - 4; + for (ddsrt_msg_iovlen_t i = 1; i < niov; i++) + { + memcpy (d->data + d->pos, (const char *) iov[i].iov_base, iov[i].iov_len); + d->pos += (uint32_t) iov[i].iov_len; + } + return serdata_plist_fix (tp, d); +} + +static struct ddsi_serdata *serdata_plist_from_keyhash (const struct ddsi_sertopic *tpcmn, const ddsi_keyhash_t *keyhash) +{ + const struct ddsi_sertopic_plist *tp = (const struct ddsi_sertopic_plist *) tpcmn; + const struct { uint16_t identifier, options; nn_parameter_t par; ddsi_keyhash_t kh; } in = { + .identifier = CDR_BE, + .options = 0, + .par = { + .parameterid = ddsrt_toBE2u (tp->keyparam), + .length = sizeof (*keyhash) + }, + *keyhash + }; + const ddsrt_iovec_t iov = { .iov_base = (void *) &in, .iov_len = sizeof (in) }; + return serdata_plist_from_ser_iov (tpcmn, SDK_KEY, 1, &iov, sizeof (in) - 4); +} + +static bool serdata_plist_topicless_to_sample (const struct ddsi_sertopic *topic_common, const struct ddsi_serdata *serdata_common, void *sample, void **bufptr, void *buflim) +{ + const struct ddsi_serdata_plist *d = (const struct ddsi_serdata_plist *)serdata_common; + const struct ddsi_sertopic_plist *tp = (const struct ddsi_sertopic_plist *) topic_common; + struct ddsi_domaingv * const gv = tp->c.gv; + if (bufptr) abort(); else { (void)buflim; } /* FIXME: haven't implemented that bit yet! */ + ddsi_plist_src_t src = { + .buf = (const unsigned char *) d->data, + .bufsz = d->pos, + .encoding = d->identifier, + .factory = gv->m_factory, + .logconfig = &gv->logconfig, + .protocol_version = d->protoversion, + .strict = NN_STRICT_P (gv->config), + .vendorid = d->vendorid + }; + const dds_return_t rc = ddsi_plist_init_frommsg (sample, NULL, ~(uint64_t)0, ~(uint64_t)0, &src); + // FIXME: need a more informative return type + if (rc != DDS_RETCODE_OK && rc != DDS_RETCODE_UNSUPPORTED) + GVWARNING ("SPDP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); + return (rc == DDS_RETCODE_OK); +} + +static bool serdata_plist_to_sample (const struct ddsi_serdata *serdata_common, void *sample, void **bufptr, void *buflim) +{ + /* the "plist" topics only differ in the parameter that is used as the key value */ + return serdata_plist_topicless_to_sample (serdata_common->topic, serdata_common, sample, bufptr, buflim); +} + +static void serdata_plist_to_ser (const struct ddsi_serdata *serdata_common, size_t off, size_t sz, void *buf) +{ + const struct ddsi_serdata_plist *d = (const struct ddsi_serdata_plist *)serdata_common; + memcpy (buf, (char *) &d->identifier + off, sz); +} + +static struct ddsi_serdata *serdata_plist_to_ser_ref (const struct ddsi_serdata *serdata_common, size_t off, size_t sz, ddsrt_iovec_t *ref) +{ + const struct ddsi_serdata_plist *d = (const struct ddsi_serdata_plist *)serdata_common; + ref->iov_base = (char *) &d->identifier + off; + ref->iov_len = (ddsrt_iov_len_t) sz; + return ddsi_serdata_ref (serdata_common); +} + +static void serdata_plist_to_ser_unref (struct ddsi_serdata *serdata_common, const ddsrt_iovec_t *ref) +{ + (void) ref; + ddsi_serdata_unref (serdata_common); +} + +static struct ddsi_serdata *serdata_plist_from_sample (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, const void *sample) +{ + const struct ddsi_sertopic_plist *tp = (const struct ddsi_sertopic_plist *)tpcmn; + const struct { uint16_t identifier, options; } header = { tp->native_encoding_identifier, 0 }; + const ddsi_guid_t nullguid = { .prefix = { .u = { 0,0,0 } }, .entityid = { .u = 0 } }; + + // FIXME: key must not require byteswapping (GUIDs are ok) + // FIXME: rework plist stuff so it doesn't need an nn_xmsg + struct nn_xmsg *mpayload = nn_xmsg_new (tp->c.gv->xmsgpool, &nullguid, NULL, 0, NN_XMSG_KIND_DATA); + memcpy (nn_xmsg_append (mpayload, NULL, 4), &header, 4); + ddsi_plist_addtomsg (mpayload, sample, ~(uint64_t)0, ~(uint64_t)0); + nn_xmsg_addpar_sentinel (mpayload); + + size_t sz; + unsigned char *blob = nn_xmsg_payload (&sz, mpayload); +#ifndef NDEBUG + void *needle; + size_t needlesz; + assert (ddsi_plist_findparam_checking (blob + 4, sz, header.identifier, tp->keyparam, &needle, &needlesz) == DDS_RETCODE_OK); + assert (needle && needlesz == 16); +#endif + ddsrt_iovec_t iov = { .iov_base = blob, .iov_len = (ddsrt_iov_len_t) sz }; + struct ddsi_serdata *d = serdata_plist_from_ser_iov (tpcmn, kind, 1, &iov, sz - 4); + nn_xmsg_free (mpayload); + + /* we know the vendor when we construct a serdata from a sample */ + struct ddsi_serdata_plist *d_plist = (struct ddsi_serdata_plist *) d; + d_plist->vendorid = NN_VENDORID_ECLIPSE; + return d; +} + +static struct ddsi_serdata *serdata_plist_to_topicless (const struct ddsi_serdata *serdata_common) +{ + const struct ddsi_serdata_plist *d = (const struct ddsi_serdata_plist *) serdata_common; + const struct ddsi_sertopic_plist *tp = (const struct ddsi_sertopic_plist *) d->c.topic; + ddsrt_iovec_t iov = { .iov_base = (char *) &d->identifier, .iov_len = 4 + d->pos }; + struct ddsi_serdata *dcmn_tl = serdata_plist_from_ser_iov (&tp->c, SDK_KEY, 1, &iov, d->pos); + assert (dcmn_tl != NULL); + dcmn_tl->topic = NULL; + return dcmn_tl; +} + +static void serdata_plist_get_keyhash (const struct ddsi_serdata *serdata_common, struct ddsi_keyhash *buf, bool force_md5) +{ + const struct ddsi_serdata_plist *d = (const struct ddsi_serdata_plist *)serdata_common; + if (!force_md5) + memcpy (buf, &d->keyhash, 16); + else + { + ddsrt_md5_state_t md5st; + ddsrt_md5_init (&md5st); + ddsrt_md5_append (&md5st, (ddsrt_md5_byte_t *) &d->keyhash, 16); + ddsrt_md5_finish (&md5st, (ddsrt_md5_byte_t *) buf->value); + } +} + +static size_t serdata_plist_print_plist (const struct ddsi_sertopic *sertopic_common, const struct ddsi_serdata *serdata_common, char *buf, size_t size) +{ + const struct ddsi_serdata_plist *d = (const struct ddsi_serdata_plist *) serdata_common; + const struct ddsi_sertopic_plist *tp = (const struct ddsi_sertopic_plist *) sertopic_common; + ddsi_plist_src_t src = { + .buf = (const unsigned char *) d->data, + .bufsz = d->pos, + .encoding = d->identifier, + .factory = tp->c.gv->m_factory, + .logconfig = &tp->c.gv->logconfig, + .protocol_version = d->protoversion, + .strict = false, + .vendorid = d->vendorid + }; + ddsi_plist_t tmp; + if (ddsi_plist_init_frommsg (&tmp, NULL, ~(uint64_t)0, ~(uint64_t)0, &src) < 0) + return (size_t) snprintf (buf, size, "(unparseable-plist)"); + else + { + size_t ret = ddsi_plist_print (buf, size, &tmp); + ddsi_plist_fini (&tmp); + return ret; + } +} + +const struct ddsi_serdata_ops ddsi_serdata_ops_plist = { + .get_size = serdata_plist_get_size, + .eqkey = serdata_plist_eqkey, + .free = serdata_plist_free, + .from_ser = serdata_plist_from_ser, + .from_ser_iov = serdata_plist_from_ser_iov, + .from_keyhash = serdata_plist_from_keyhash, + .from_sample = serdata_plist_from_sample, + .to_ser = serdata_plist_to_ser, + .to_sample = serdata_plist_to_sample, + .to_ser_ref = serdata_plist_to_ser_ref, + .to_ser_unref = serdata_plist_to_ser_unref, + .to_topicless = serdata_plist_to_topicless, + .topicless_to_sample = serdata_plist_topicless_to_sample, + .print = serdata_plist_print_plist, + .get_keyhash = serdata_plist_get_keyhash +}; diff --git a/src/core/ddsi/src/ddsi_serdata_pserop.c b/src/core/ddsi/src/ddsi_serdata_pserop.c new file mode 100644 index 0000000..a3df6d2 --- /dev/null +++ b/src/core/ddsi/src/ddsi_serdata_pserop.c @@ -0,0 +1,297 @@ +/* + * Copyright(c) 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include + +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/log.h" +#include "dds/ddsrt/md5.h" +#include "dds/ddsrt/mh3.h" +#include "dds/ddsi/q_bswap.h" +#include "dds/ddsi/q_config.h" +#include "dds/ddsi/q_freelist.h" +#include "dds/ddsi/ddsi_tkmap.h" +#include "dds/ddsi/ddsi_cdrstream.h" +#include "dds/ddsi/q_radmin.h" +#include "dds/ddsi/ddsi_domaingv.h" +#include "dds/ddsi/ddsi_serdata_pserop.h" + +static uint32_t serdata_pserop_get_size (const struct ddsi_serdata *dcmn) +{ + const struct ddsi_serdata_pserop *d = (const struct ddsi_serdata_pserop *) dcmn; + return 4 + d->pos; // FIXME: +4 for CDR header should be eliminated +} + +static bool serdata_pserop_eqkey (const struct ddsi_serdata *acmn, const struct ddsi_serdata *bcmn) +{ + const struct ddsi_serdata_pserop *a = (const struct ddsi_serdata_pserop *) acmn; + const struct ddsi_serdata_pserop *b = (const struct ddsi_serdata_pserop *) bcmn; + if (a->keyless != b->keyless) + return false; + else if (a->keyless) + return true; + else + return memcmp (a->sample, b->sample, 16) == 0; +} + +static void serdata_pserop_free (struct ddsi_serdata *dcmn) +{ + struct ddsi_serdata_pserop *d = (struct ddsi_serdata_pserop *) dcmn; + const struct ddsi_sertopic_pserop *tp = (const struct ddsi_sertopic_pserop *) d->c.topic; + if (d->c.kind == SDK_DATA) + plist_fini_generic (d->sample, tp->ops, true); + if (d->sample) + ddsrt_free (d->sample); + ddsrt_free (d); +} + +static struct ddsi_serdata_pserop *serdata_pserop_new (const struct ddsi_sertopic_pserop *tp, enum ddsi_serdata_kind kind, size_t size, const void *cdr_header) +{ + /* FIXME: check whether this really is the correct maximum: offsets are relative + to the CDR header, but there are also some places that use a serdata as-if it + were a stream, and those use offsets (m_index) relative to the start of the + serdata */ + assert (kind != SDK_EMPTY); + if (size < 4 || size > UINT32_MAX - offsetof (struct ddsi_serdata_pserop, identifier)) + return NULL; + struct ddsi_serdata_pserop *d = ddsrt_malloc (sizeof (*d) + size); + if (d == NULL) + return NULL; + ddsi_serdata_init (&d->c, &tp->c, kind); + d->keyless = (tp->ops_key == NULL); + d->pos = 0; + d->size = (uint32_t) size; + const uint16_t *hdrsrc = cdr_header; + d->identifier = hdrsrc[0]; + d->options = hdrsrc[1]; + assert (d->identifier == CDR_LE || d->identifier == CDR_BE); + if (kind == SDK_KEY && d->keyless) + d->sample = NULL; + else if ((d->sample = ddsrt_malloc ((kind == SDK_DATA) ? tp->memsize : 16)) == NULL) + { + ddsrt_free (d); + return NULL; + } + return d; +} + +static struct ddsi_serdata *serdata_pserop_fix (const struct ddsi_sertopic_pserop *tp, struct ddsi_serdata_pserop *d) +{ + const bool needs_bswap = (d->identifier != tp->native_encoding_identifier); + const enum pserop *ops = (d->c.kind == SDK_DATA) ? tp->ops : tp->ops_key; + d->c.hash = tp->c.serdata_basehash; + if (ops != NULL) + { + assert (d->pos >= 16 && tp->memsize >= 16); + if (plist_deser_generic (d->sample, d->data, d->pos, needs_bswap, (d->c.kind == SDK_DATA) ? tp->ops : tp->ops_key) < 0) + { + ddsrt_free (d->sample); + ddsrt_free (d); + return NULL; + } + if (tp->ops_key) + { + assert (d->pos >= 16 && tp->memsize >= 16); + d->c.hash ^= ddsrt_mh3 (d->sample, 16, 0); + } + } + return &d->c; +} + +static struct ddsi_serdata *serdata_pserop_from_ser (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, const struct nn_rdata *fragchain, size_t size) +{ + const struct ddsi_sertopic_pserop *tp = (const struct ddsi_sertopic_pserop *)tpcmn; + struct ddsi_serdata_pserop *d = serdata_pserop_new (tp, kind, size, NN_RMSG_PAYLOADOFF (fragchain->rmsg, NN_RDATA_PAYLOAD_OFF (fragchain))); + uint32_t off = 4; /* must skip the CDR header */ + assert (fragchain->min == 0); + assert (fragchain->maxp1 >= off); /* CDR header must be in first fragment */ + while (fragchain) + { + assert (fragchain->min <= off); + assert (fragchain->maxp1 <= size); + if (fragchain->maxp1 > off) + { + /* only copy if this fragment adds data */ + const unsigned char *payload = NN_RMSG_PAYLOADOFF (fragchain->rmsg, NN_RDATA_PAYLOAD_OFF (fragchain)); + uint32_t n = fragchain->maxp1 - off; + memcpy (d->data + d->pos, payload + off - fragchain->min, n); + d->pos += n; + off = fragchain->maxp1; + } + fragchain = fragchain->nextfrag; + } + return serdata_pserop_fix (tp, d); +} + +static struct ddsi_serdata *serdata_pserop_from_ser_iov (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size) +{ + const struct ddsi_sertopic_pserop *tp = (const struct ddsi_sertopic_pserop *)tpcmn; + assert (niov >= 1); + struct ddsi_serdata_pserop *d = serdata_pserop_new (tp, kind, size, iov[0].iov_base); + const uint16_t *hdrsrc = (uint16_t *) iov[0].iov_base; + d->identifier = hdrsrc[0]; + d->options = hdrsrc[1]; + assert (d->identifier == CDR_LE || d->identifier == CDR_BE); + memcpy (d->data + d->pos, (const char *) iov[0].iov_base + 4, iov[0].iov_len - 4); + d->pos += (uint32_t) iov[0].iov_len - 4; + for (ddsrt_msg_iovlen_t i = 1; i < niov; i++) + { + memcpy (d->data + d->pos, (const char *) iov[i].iov_base, iov[i].iov_len); + d->pos += (uint32_t) iov[i].iov_len; + } + return serdata_pserop_fix (tp, d); +} + +static struct ddsi_serdata *serdata_pserop_from_keyhash (const struct ddsi_sertopic *tpcmn, const ddsi_keyhash_t *keyhash) +{ + const struct { uint16_t identifier, options; ddsi_keyhash_t kh; } in = { CDR_BE, 0, *keyhash }; + const ddsrt_iovec_t iov = { .iov_base = (void *) &in, .iov_len = sizeof (in) }; + return serdata_pserop_from_ser_iov (tpcmn, SDK_KEY, 1, &iov, sizeof (in) - 4); +} + +static bool serdata_pserop_to_sample (const struct ddsi_serdata *serdata_common, void *sample, void **bufptr, void *buflim) +{ + const struct ddsi_serdata_pserop *d = (const struct ddsi_serdata_pserop *)serdata_common; + const struct ddsi_sertopic_pserop *tp = (const struct ddsi_sertopic_pserop *) d->c.topic; + if (bufptr) abort(); else { (void)buflim; } /* FIXME: haven't implemented that bit yet! */ + if (d->c.kind == SDK_KEY) + memcpy (sample, d->sample, 16); + else + { + dds_return_t x; + x = plist_deser_generic (sample, d->data, d->pos, d->identifier != tp->native_encoding_identifier, tp->ops); + plist_unalias_generic (sample, tp->ops); + assert (x >= 0); + (void) x; + } + return true; /* FIXME: can't conversion to sample fail? */ +} + +static void serdata_pserop_to_ser (const struct ddsi_serdata *serdata_common, size_t off, size_t sz, void *buf) +{ + const struct ddsi_serdata_pserop *d = (const struct ddsi_serdata_pserop *)serdata_common; + memcpy (buf, (char *) &d->identifier + off, sz); +} + +static struct ddsi_serdata *serdata_pserop_to_ser_ref (const struct ddsi_serdata *serdata_common, size_t off, size_t sz, ddsrt_iovec_t *ref) +{ + const struct ddsi_serdata_pserop *d = (const struct ddsi_serdata_pserop *)serdata_common; + ref->iov_base = (char *) &d->identifier + off; + ref->iov_len = (ddsrt_iov_len_t) sz; + return ddsi_serdata_ref (serdata_common); +} + +static void serdata_pserop_to_ser_unref (struct ddsi_serdata *serdata_common, const ddsrt_iovec_t *ref) +{ + (void) ref; + ddsi_serdata_unref (serdata_common); +} + +static struct ddsi_serdata *serdata_pserop_from_sample (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, const void *sample) +{ + const struct ddsi_sertopic_pserop *tp = (const struct ddsi_sertopic_pserop *)tpcmn; + const struct { uint16_t identifier, options; } header = { tp->native_encoding_identifier, 0 }; + if (kind == SDK_KEY && tp->ops_key == NULL) + return serdata_pserop_fix (tp, serdata_pserop_new (tp, kind, 0, &header)); + else + { + void *data; + size_t size; + if (plist_ser_generic (&data, &size, sample, (kind == SDK_DATA) ? tp->ops : tp->ops_key) < 0) + return NULL; + const size_t size4 = (size + 3) & ~(size_t)3; + struct ddsi_serdata_pserop *d = serdata_pserop_new (tp, kind, size4, &header); + assert (tp->ops_key == NULL || (size >= 16 && tp->memsize >= 16)); + memcpy (d->data, data, size); + memset (d->data + size, 0, size4 - size); + d->pos = (uint32_t) size; + ddsrt_free (data); // FIXME: shouldn't allocate twice & copy + // FIXME: and then this silly thing deserialises it immediately again -- perhaps it should be a bit lazier + return serdata_pserop_fix (tp, d); + } +} + +static struct ddsi_serdata *serdata_pserop_to_topicless (const struct ddsi_serdata *serdata_common) +{ + const struct ddsi_serdata_pserop *d = (const struct ddsi_serdata_pserop *)serdata_common; + const struct ddsi_sertopic_pserop *tp = (const struct ddsi_sertopic_pserop *)d->c.topic; + ddsrt_iovec_t iov = { .iov_base = (char *) &d->identifier, .iov_len = (ddsrt_iov_len_t) (4 + d->pos) }; + struct ddsi_serdata *dcmn_tl = serdata_pserop_from_ser_iov (&tp->c, SDK_KEY, 1, &iov, iov.iov_len); + assert (dcmn_tl != NULL); + dcmn_tl->topic = NULL; + return dcmn_tl; +} + +static bool serdata_pserop_topicless_to_sample (const struct ddsi_sertopic *topic_common, const struct ddsi_serdata *serdata_common, void *sample, void **bufptr, void *buflim) +{ + const struct ddsi_serdata_pserop *d = (const struct ddsi_serdata_pserop *)serdata_common; + const struct ddsi_sertopic_pserop *tp = (const struct ddsi_sertopic_pserop *)topic_common; + if (bufptr) abort(); else { (void)buflim; } /* FIXME: haven't implemented that bit yet! */ + if (tp->ops_key) + memcpy (sample, d->sample, 16); + return true; +} + +static void serdata_pserop_get_keyhash (const struct ddsi_serdata *serdata_common, struct ddsi_keyhash *buf, bool force_md5) +{ + const struct ddsi_serdata_pserop *d = (const struct ddsi_serdata_pserop *)serdata_common; + const struct ddsi_sertopic_pserop *tp = (const struct ddsi_sertopic_pserop *)d->c.topic; + if (tp->ops_key == NULL) + memset (buf, 0, 16); + else + { + /* need big-endian representation for key hash, so be lazy & re-serialize + (and yes, it costs another malloc ...); note that key at offset 0 implies + ops_key is a prefix of ops */ + void *be; + size_t besize; + (void) plist_ser_generic_be (&be, &besize, d->sample, tp->ops_key); + assert (besize == 16); /* that's the deal with keys for now */ + if (!force_md5) + memcpy (buf, be, 16); + else + { + ddsrt_md5_state_t md5st; + ddsrt_md5_init (&md5st); + ddsrt_md5_append (&md5st, (ddsrt_md5_byte_t *) be, 16); + ddsrt_md5_finish (&md5st, (ddsrt_md5_byte_t *) buf->value); + } + ddsrt_free (be); + } +} + +static size_t serdata_pserop_print_pserop (const struct ddsi_sertopic *sertopic_common, const struct ddsi_serdata *serdata_common, char *buf, size_t size) +{ + const struct ddsi_serdata_pserop *d = (const struct ddsi_serdata_pserop *)serdata_common; + const struct ddsi_sertopic_pserop *tp = (const struct ddsi_sertopic_pserop *)sertopic_common; + return plist_print_generic (buf, size, d->sample, tp->ops); +} + +const struct ddsi_serdata_ops ddsi_serdata_ops_pserop = { + .get_size = serdata_pserop_get_size, + .eqkey = serdata_pserop_eqkey, + .free = serdata_pserop_free, + .from_ser = serdata_pserop_from_ser, + .from_ser_iov = serdata_pserop_from_ser_iov, + .from_keyhash = serdata_pserop_from_keyhash, + .from_sample = serdata_pserop_from_sample, + .to_ser = serdata_pserop_to_ser, + .to_sample = serdata_pserop_to_sample, + .to_ser_ref = serdata_pserop_to_ser_ref, + .to_ser_unref = serdata_pserop_to_ser_unref, + .to_topicless = serdata_pserop_to_topicless, + .topicless_to_sample = serdata_pserop_topicless_to_sample, + .print = serdata_pserop_print_pserop, + .get_keyhash = serdata_pserop_get_keyhash +}; diff --git a/src/core/ddsi/src/ddsi_sertopic.c b/src/core/ddsi/src/ddsi_sertopic.c index 04052cc..8c58c8f 100644 --- a/src/core/ddsi/src/ddsi_sertopic.c +++ b/src/core/ddsi/src/ddsi_sertopic.c @@ -56,8 +56,7 @@ uint32_t ddsi_sertopic_hash (const struct ddsi_sertopic *a) struct ddsi_sertopic *ddsi_sertopic_ref (const struct ddsi_sertopic *sertopic_const) { struct ddsi_sertopic *sertopic = (struct ddsi_sertopic *) sertopic_const; - if (sertopic) - ddsrt_atomic_inc32 (&sertopic->refc); + ddsrt_atomic_inc32 (&sertopic->refc); return sertopic; } @@ -68,7 +67,7 @@ struct ddsi_sertopic *ddsi_sertopic_lookup_locked (struct ddsi_domaingv *gv, con if (sertopic != NULL) assert (sertopic->gv != NULL); #endif - return ddsi_sertopic_ref (sertopic); + return sertopic ? ddsi_sertopic_ref (sertopic) : NULL; } void ddsi_sertopic_register_locked (struct ddsi_domaingv *gv, struct ddsi_sertopic *sertopic) @@ -84,21 +83,18 @@ void ddsi_sertopic_register_locked (struct ddsi_domaingv *gv, struct ddsi_sertop void ddsi_sertopic_unref (struct ddsi_sertopic *sertopic) { - if (sertopic) + if (ddsrt_atomic_dec32_ov (&sertopic->refc) == 1) { - if (ddsrt_atomic_dec32_ov (&sertopic->refc) == 1) + /* if registered, drop from set of registered sertopics */ + if (sertopic->gv) { - /* if registered, drop from set of registered sertopics */ - if (sertopic->gv) - { - ddsrt_mutex_lock (&sertopic->gv->sertopics_lock); - (void) ddsrt_hh_remove (sertopic->gv->sertopics, sertopic); - ddsrt_mutex_unlock (&sertopic->gv->sertopics_lock); - sertopic->gv = NULL; - } - - ddsi_sertopic_free (sertopic); + ddsrt_mutex_lock (&sertopic->gv->sertopics_lock); + (void) ddsrt_hh_remove (sertopic->gv->sertopics, sertopic); + ddsrt_mutex_unlock (&sertopic->gv->sertopics_lock); + sertopic->gv = NULL; } + + ddsi_sertopic_free (sertopic); } } diff --git a/src/core/ddsi/src/ddsi_sertopic_plist.c b/src/core/ddsi/src/ddsi_sertopic_plist.c new file mode 100644 index 0000000..f9f98b0 --- /dev/null +++ b/src/core/ddsi/src/ddsi_sertopic_plist.c @@ -0,0 +1,95 @@ +/* + * Copyright(c) 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include + +#include "dds/ddsrt/mh3.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsi/ddsi_plist.h" +#include "dds/ddsi/ddsi_sertopic.h" +#include "dds/ddsi/ddsi_serdata_plist.h" + +static bool sertopic_plist_equal (const struct ddsi_sertopic *acmn, const struct ddsi_sertopic *bcmn) +{ + const struct ddsi_sertopic_plist *a = (struct ddsi_sertopic_plist *) acmn; + const struct ddsi_sertopic_plist *b = (struct ddsi_sertopic_plist *) bcmn; + if (a->native_encoding_identifier != b->native_encoding_identifier) + return false; + if (a->keyparam != b->keyparam) + return false; + return true; +} + +static uint32_t sertopic_plist_hash (const struct ddsi_sertopic *tpcmn) +{ + const struct ddsi_sertopic_plist *tp = (struct ddsi_sertopic_plist *) tpcmn; + uint32_t h = 0; + h = ddsrt_mh3 (&tp->native_encoding_identifier, sizeof (tp->native_encoding_identifier), h); + h = ddsrt_mh3 (&tp->keyparam, sizeof (tp->keyparam), h); + return h; +} + +static void sertopic_plist_free (struct ddsi_sertopic *tpcmn) +{ + struct ddsi_sertopic_plist *tp = (struct ddsi_sertopic_plist *) tpcmn; + ddsi_sertopic_fini (&tp->c); + ddsrt_free (tp); +} + +static void sertopic_plist_zero_samples (const struct ddsi_sertopic *sertopic_common, void *sample, size_t count) +{ + (void) sertopic_common; + ddsi_plist_t *xs = sample; + for (size_t i = 0; i < count; i++) + ddsi_plist_init_empty (&xs[i]); +} + +static void sertopic_plist_realloc_samples (void **ptrs, const struct ddsi_sertopic *sertopic_common, void *old, size_t oldcount, size_t count) +{ + (void) sertopic_common; + ddsi_plist_t *new = (oldcount == count) ? old : dds_realloc (old, count * sizeof (ddsi_plist_t)); + if (new) + { + for (size_t i = count; i < oldcount; i++) + ddsi_plist_init_empty (&new[i]); + for (size_t i = 0; i < count; i++) + ptrs[i] = &new[i]; + } +} + +static void sertopic_plist_free_samples (const struct ddsi_sertopic *sertopic_common, void **ptrs, size_t count, dds_free_op_t op) +{ + (void) sertopic_common; + if (count > 0) + { +#ifndef NDEBUG + for (size_t i = 0, off = 0; i < count; i++, off += sizeof (ddsi_plist_t)) + assert ((char *)ptrs[i] == (char *)ptrs[0] + off); +#endif + ddsi_plist_t *xs = ptrs[0]; + for (size_t i = 0; i < count; i++) + ddsi_plist_fini (&xs[i]); + if (op & DDS_FREE_ALL_BIT) + dds_free (ptrs[0]); + } +} + +const struct ddsi_sertopic_ops ddsi_sertopic_ops_plist = { + .equal = sertopic_plist_equal, + .hash = sertopic_plist_hash, + .free = sertopic_plist_free, + .zero_samples = sertopic_plist_zero_samples, + .realloc_samples = sertopic_plist_realloc_samples, + .free_samples = sertopic_plist_free_samples +}; diff --git a/src/core/ddsi/src/ddsi_sertopic_pserop.c b/src/core/ddsi/src/ddsi_sertopic_pserop.c new file mode 100644 index 0000000..c8ebdb9 --- /dev/null +++ b/src/core/ddsi/src/ddsi_sertopic_pserop.c @@ -0,0 +1,118 @@ +/* + * Copyright(c) 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include + +#include "dds/ddsrt/md5.h" +#include "dds/ddsrt/mh3.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsi/q_bswap.h" +#include "dds/ddsi/q_config.h" +#include "dds/ddsi/q_freelist.h" +#include "dds/ddsi/ddsi_plist_generic.h" +#include "dds/ddsi/ddsi_sertopic.h" +#include "dds/ddsi/ddsi_serdata_pserop.h" + +static bool sertopic_pserop_equal (const struct ddsi_sertopic *acmn, const struct ddsi_sertopic *bcmn) +{ + const struct ddsi_sertopic_pserop *a = (struct ddsi_sertopic_pserop *) acmn; + const struct ddsi_sertopic_pserop *b = (struct ddsi_sertopic_pserop *) bcmn; + if (a->native_encoding_identifier != b->native_encoding_identifier) + return false; + if (a->memsize != b->memsize) + return false; + if (a->nops != b->nops) + return false; + assert (a->nops > 0); + if (memcmp (a->ops, b->ops, a->nops * sizeof (*a->ops)) != 0) + return false; + if (a->nops_key != b->nops_key) + return false; + if (a->ops_key && memcmp (a->ops_key, b->ops_key, a->nops_key * sizeof (*a->ops_key)) != 0) + return false; + return true; +} + +static uint32_t sertopic_pserop_hash (const struct ddsi_sertopic *tpcmn) +{ + const struct ddsi_sertopic_pserop *tp = (struct ddsi_sertopic_pserop *) tpcmn; + uint32_t h = 0; + h = ddsrt_mh3 (&tp->native_encoding_identifier, sizeof (tp->native_encoding_identifier), h); + h = ddsrt_mh3 (&tp->memsize, sizeof (tp->memsize), h); + h = ddsrt_mh3 (&tp->nops, sizeof (tp->nops), h); + h = ddsrt_mh3 (tp->ops, tp->nops * sizeof (*tp->ops), h); + h = ddsrt_mh3 (&tp->nops_key, sizeof (tp->nops_key), h); + if (tp->ops_key) + h = ddsrt_mh3 (tp->ops_key, tp->nops_key * sizeof (*tp->ops_key), h); + return h; +} + +static void sertopic_pserop_free (struct ddsi_sertopic *tpcmn) +{ + struct ddsi_sertopic_pserop *tp = (struct ddsi_sertopic_pserop *) tpcmn; + ddsi_sertopic_fini (&tp->c); + ddsrt_free (tp); +} + +static void sertopic_pserop_zero_samples (const struct ddsi_sertopic *sertopic_common, void *sample, size_t count) +{ + const struct ddsi_sertopic_pserop *tp = (const struct ddsi_sertopic_pserop *)sertopic_common; + memset (sample, 0, tp->memsize * count); +} + +static void sertopic_pserop_realloc_samples (void **ptrs, const struct ddsi_sertopic *sertopic_common, void *old, size_t oldcount, size_t count) +{ + const struct ddsi_sertopic_pserop *tp = (const struct ddsi_sertopic_pserop *)sertopic_common; + const size_t size = tp->memsize; + char *new = (oldcount == count) ? old : dds_realloc (old, size * count); + if (new && count > oldcount) + memset (new + size * oldcount, 0, size * (count - oldcount)); + for (size_t i = 0; i < count; i++) + { + void *ptr = (char *) new + i * size; + ptrs[i] = ptr; + } +} + +static void sertopic_pserop_free_samples (const struct ddsi_sertopic *sertopic_common, void **ptrs, size_t count, dds_free_op_t op) +{ + if (count > 0) + { + const struct ddsi_sertopic_pserop *tp = (const struct ddsi_sertopic_pserop *)sertopic_common; + const size_t size = tp->memsize; +#ifndef NDEBUG + for (size_t i = 0, off = 0; i < count; i++, off += size) + assert ((char *)ptrs[i] == (char *)ptrs[0] + off); +#endif + char *ptr = ptrs[0]; + for (size_t i = 0; i < count; i++) + { + plist_fini_generic (ptr, tp->ops, false); + ptr += size; + } + if (op & DDS_FREE_ALL_BIT) + { + dds_free (ptrs[0]); + } + } +} + +const struct ddsi_sertopic_ops ddsi_sertopic_ops_pserop = { + .equal = sertopic_pserop_equal, + .hash = sertopic_pserop_hash, + .free = sertopic_pserop_free, + .zero_samples = sertopic_pserop_zero_samples, + .realloc_samples = sertopic_pserop_realloc_samples, + .free_samples = sertopic_pserop_free_samples +}; diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 2739e6b..515a4c6 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -863,8 +863,6 @@ static const struct cfgelem discovery_cfgelems[] = { BLURB("

    This element specifies the interval between spontaneous transmissions of participant discovery packets.

    ") }, { LEAF("DefaultMulticastAddress"), 1, "auto", ABSOFF(defaultMulticastAddressString), 0, uf_networkAddress, 0, pf_networkAddress, BLURB("

    This element specifies the default multicast address for all traffic other than participant discovery packets. It defaults to Discovery/SPDPMulticastAddress.

    ") }, - { LEAF("EnableTopicDiscovery"), 1, "true", ABSOFF(do_topic_discovery), 0, uf_boolean, 0, pf_boolean, - BLURB("

    Do not use.

    ") }, { GROUP("Ports", discovery_ports_cfgelems), BLURB("

    The Ports element allows specifying various parameters related to the port numbers used for discovery. These all have default values specified by the DDSI 2.1 specification and rarely need to be changed.

    ") }, END_MARKER diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 29421d3..865a8dc 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -32,6 +32,7 @@ #include "dds/ddsi/q_xevent.h" #include "dds/ddsi/q_addrset.h" #include "dds/ddsi/q_ddsi_discovery.h" +#include "dds/ddsi/ddsi_serdata_plist.h" #include "dds/ddsi/q_radmin.h" #include "dds/ddsi/ddsi_entity_index.h" @@ -175,36 +176,22 @@ static void maybe_add_pp_as_meta_to_as_disc (struct ddsi_domaingv *gv, const str } } -static int write_mpayload (struct writer *wr, int alive, nn_parameterid_t keyparam, struct nn_xmsg *mpayload) +void get_participant_builtin_topic_data (const struct participant *pp, ddsi_plist_t *dst, struct participant_builtin_topic_data_locators *locs) { - struct thread_state1 * const ts1 = lookup_thread_state (); - struct ddsi_plist_sample plist_sample; - struct ddsi_serdata *serdata; - nn_xmsg_payload_to_plistsample (&plist_sample, keyparam, mpayload); - serdata = ddsi_serdata_from_sample (wr->e.gv->plist_topic, alive ? SDK_DATA : SDK_KEY, &plist_sample); - serdata->statusinfo = alive ? 0 : NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER; - serdata->timestamp = ddsrt_time_wallclock (); - return write_sample_nogc_notk (ts1, NULL, wr, serdata); -} - -void get_participant_builtin_topic_data(const struct participant *pp, struct nn_xmsg *mpayload, bool be) -{ - struct nn_locators_one def_uni_loc_one, def_multi_loc_one, meta_uni_loc_one, meta_multi_loc_one; - ddsi_plist_t ps; size_t size; char node[64]; uint64_t qosdiff; - ddsi_plist_init_empty (&ps); - ps.present |= PP_PARTICIPANT_GUID | PP_BUILTIN_ENDPOINT_SET | + ddsi_plist_init_empty (dst); + dst->present |= PP_PARTICIPANT_GUID | PP_BUILTIN_ENDPOINT_SET | PP_PROTOCOL_VERSION | PP_VENDORID | PP_PARTICIPANT_LEASE_DURATION | PP_DOMAIN_ID; - ps.participant_guid = pp->e.guid; - ps.builtin_endpoint_set = pp->bes; - ps.protocol_version.major = RTPS_MAJOR; - ps.protocol_version.minor = RTPS_MINOR; - ps.vendorid = NN_VENDORID_ECLIPSE; - ps.domain_id = pp->e.gv->config.extDomainId.value; + dst->participant_guid = pp->e.guid; + dst->builtin_endpoint_set = pp->bes; + dst->protocol_version.major = RTPS_MAJOR; + dst->protocol_version.minor = RTPS_MINOR; + dst->vendorid = NN_VENDORID_ECLIPSE; + dst->domain_id = pp->e.gv->config.extDomainId.value; /* Be sure not to send a DOMAIN_TAG when it is the default (an empty) string: it is an "incompatible-if-unrecognized" parameter, and so implementations that don't understand the parameter will refuse to @@ -212,34 +199,34 @@ void get_participant_builtin_topic_data(const struct participant *pp, struct nn_ compatibility. */ if (strcmp (pp->e.gv->config.domainTag, "") != 0) { - ps.present |= PP_DOMAIN_TAG; - ps.aliased |= PP_DOMAIN_TAG; - ps.domain_tag = pp->e.gv->config.domainTag; + dst->present |= PP_DOMAIN_TAG; + dst->aliased |= PP_DOMAIN_TAG; + dst->domain_tag = pp->e.gv->config.domainTag; } - ps.default_unicast_locators.n = 1; - ps.default_unicast_locators.first = - ps.default_unicast_locators.last = &def_uni_loc_one; - ps.metatraffic_unicast_locators.n = 1; - ps.metatraffic_unicast_locators.first = - ps.metatraffic_unicast_locators.last = &meta_uni_loc_one; - def_uni_loc_one.next = NULL; - meta_uni_loc_one.next = NULL; + dst->default_unicast_locators.n = 1; + dst->default_unicast_locators.first = + dst->default_unicast_locators.last = &locs->def_uni_loc_one; + dst->metatraffic_unicast_locators.n = 1; + dst->metatraffic_unicast_locators.first = + dst->metatraffic_unicast_locators.last = &locs->meta_uni_loc_one; + locs->def_uni_loc_one.next = NULL; + locs->meta_uni_loc_one.next = NULL; if (pp->e.gv->config.many_sockets_mode == MSM_MANY_UNICAST) { - def_uni_loc_one.loc = pp->m_locator; - meta_uni_loc_one.loc = pp->m_locator; + locs->def_uni_loc_one.loc = pp->m_locator; + locs->meta_uni_loc_one.loc = pp->m_locator; } else { - def_uni_loc_one.loc = pp->e.gv->loc_default_uc; - meta_uni_loc_one.loc = pp->e.gv->loc_meta_uc; + locs->def_uni_loc_one.loc = pp->e.gv->loc_default_uc; + locs->meta_uni_loc_one.loc = pp->e.gv->loc_meta_uc; } if (pp->e.gv->config.publish_uc_locators) { - ps.present |= PP_DEFAULT_UNICAST_LOCATOR | PP_METATRAFFIC_UNICAST_LOCATOR; - ps.aliased |= PP_DEFAULT_UNICAST_LOCATOR | PP_METATRAFFIC_UNICAST_LOCATOR; + dst->present |= PP_DEFAULT_UNICAST_LOCATOR | PP_METATRAFFIC_UNICAST_LOCATOR; + dst->aliased |= PP_DEFAULT_UNICAST_LOCATOR | PP_METATRAFFIC_UNICAST_LOCATOR; } if (pp->e.gv->config.allowMulticast) @@ -260,51 +247,51 @@ void get_participant_builtin_topic_data(const struct participant *pp, struct nn_ #endif if (include) { - ps.present |= PP_DEFAULT_MULTICAST_LOCATOR | PP_METATRAFFIC_MULTICAST_LOCATOR; - ps.aliased |= PP_DEFAULT_MULTICAST_LOCATOR | PP_METATRAFFIC_MULTICAST_LOCATOR; - ps.default_multicast_locators.n = 1; - ps.default_multicast_locators.first = - ps.default_multicast_locators.last = &def_multi_loc_one; - ps.metatraffic_multicast_locators.n = 1; - ps.metatraffic_multicast_locators.first = - ps.metatraffic_multicast_locators.last = &meta_multi_loc_one; - def_multi_loc_one.next = NULL; - def_multi_loc_one.loc = pp->e.gv->loc_default_mc; - meta_multi_loc_one.next = NULL; - meta_multi_loc_one.loc = pp->e.gv->loc_meta_mc; + dst->present |= PP_DEFAULT_MULTICAST_LOCATOR | PP_METATRAFFIC_MULTICAST_LOCATOR; + dst->aliased |= PP_DEFAULT_MULTICAST_LOCATOR | PP_METATRAFFIC_MULTICAST_LOCATOR; + dst->default_multicast_locators.n = 1; + dst->default_multicast_locators.first = + dst->default_multicast_locators.last = &locs->def_multi_loc_one; + dst->metatraffic_multicast_locators.n = 1; + dst->metatraffic_multicast_locators.first = + dst->metatraffic_multicast_locators.last = &locs->meta_multi_loc_one; + locs->def_multi_loc_one.next = NULL; + locs->def_multi_loc_one.loc = pp->e.gv->loc_default_mc; + locs->meta_multi_loc_one.next = NULL; + locs->meta_multi_loc_one.loc = pp->e.gv->loc_meta_mc; } } - ps.participant_lease_duration = pp->lease_duration; + dst->participant_lease_duration = pp->lease_duration; /* Add Adlink specific version information */ { - ps.present |= PP_ADLINK_PARTICIPANT_VERSION_INFO; - memset (&ps.adlink_participant_version_info, 0, sizeof (ps.adlink_participant_version_info)); - ps.adlink_participant_version_info.version = 0; - ps.adlink_participant_version_info.flags = + dst->present |= PP_ADLINK_PARTICIPANT_VERSION_INFO; + memset (&dst->adlink_participant_version_info, 0, sizeof (dst->adlink_participant_version_info)); + dst->adlink_participant_version_info.version = 0; + dst->adlink_participant_version_info.flags = NN_ADLINK_FL_DDSI2_PARTICIPANT_FLAG | NN_ADLINK_FL_PTBES_FIXED_0 | NN_ADLINK_FL_SUPPORTS_STATUSINFOX; if (pp->e.gv->config.besmode == BESMODE_MINIMAL) - ps.adlink_participant_version_info.flags |= NN_ADLINK_FL_MINIMAL_BES_MODE; + dst->adlink_participant_version_info.flags |= NN_ADLINK_FL_MINIMAL_BES_MODE; ddsrt_mutex_lock (&pp->e.gv->privileged_pp_lock); if (pp->is_ddsi2_pp) - ps.adlink_participant_version_info.flags |= NN_ADLINK_FL_PARTICIPANT_IS_DDSI2; + dst->adlink_participant_version_info.flags |= NN_ADLINK_FL_PARTICIPANT_IS_DDSI2; ddsrt_mutex_unlock (&pp->e.gv->privileged_pp_lock); if (ddsrt_gethostname(node, sizeof(node)-1) < 0) (void) ddsrt_strlcpy (node, "unknown", sizeof (node)); size = strlen(node) + strlen(DDS_VERSION) + strlen(DDS_HOST_NAME) + strlen(DDS_TARGET_NAME) + 4; /* + ///'\0' */ - ps.adlink_participant_version_info.internals = ddsrt_malloc(size); - (void) snprintf(ps.adlink_participant_version_info.internals, size, "%s/%s/%s/%s", node, DDS_VERSION, DDS_HOST_NAME, DDS_TARGET_NAME); - ETRACE (pp, "spdp_write("PGUIDFMT") - internals: %s\n", PGUID (pp->e.guid), ps.adlink_participant_version_info.internals); + dst->adlink_participant_version_info.internals = ddsrt_malloc(size); + (void) snprintf(dst->adlink_participant_version_info.internals, size, "%s/%s/%s/%s", node, DDS_VERSION, DDS_HOST_NAME, DDS_TARGET_NAME); + ETRACE (pp, "spdp_write("PGUIDFMT") - internals: %s\n", PGUID (pp->e.guid), dst->adlink_participant_version_info.internals); } #ifdef DDSI_INCLUDE_SECURITY /* Add Security specific information. */ - if (q_omg_get_participant_security_info(pp, &(ps.participant_security_info))) { - ps.present |= PP_PARTICIPANT_SECURITY_INFO; - ps.aliased |= PP_PARTICIPANT_SECURITY_INFO; + if (q_omg_get_participant_security_info(pp, &(dst->participant_security_info))) { + dst->present |= PP_PARTICIPANT_SECURITY_INFO; + dst->aliased |= PP_PARTICIPANT_SECURITY_INFO; } #endif @@ -313,62 +300,28 @@ void get_participant_builtin_topic_data(const struct participant *pp, struct nn_ if (pp->e.gv->config.explicitly_publish_qos_set_to_default) qosdiff |= ~QP_UNRECOGNIZED_INCOMPATIBLE_MASK; - assert (ps.qos.present == 0); - ddsi_plist_addtomsg_bo (mpayload, &ps, ~(uint64_t)0, 0, be); - ddsi_plist_addtomsg_bo (mpayload, pp->plist, 0, qosdiff, be); + assert (dst->qos.present == 0); + ddsi_plist_mergein_missing (dst, pp->plist, 0, qosdiff); #ifdef DDSI_INCLUDE_SECURITY if (q_omg_participant_is_secure(pp)) - ddsi_plist_addtomsg_bo (mpayload, pp->plist, PP_IDENTITY_TOKEN | PP_PERMISSIONS_TOKEN, 0, be); + ddsi_plist_mergein_missing (dst, pp->plist, PP_IDENTITY_TOKEN | PP_PERMISSIONS_TOKEN, 0); #endif - nn_xmsg_addpar_sentinel_bo (mpayload, be); - ddsi_plist_fini (&ps); +} + +static int write_and_fini_plist (struct writer *wr, ddsi_plist_t *ps, bool alive) +{ + struct ddsi_serdata *serdata = ddsi_serdata_from_sample (wr->topic, alive ? SDK_DATA : SDK_KEY, ps); + ddsi_plist_fini (ps); + serdata->statusinfo = alive ? 0 : (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER); + serdata->timestamp = ddsrt_time_wallclock (); + return write_sample_nogc_notk (lookup_thread_state (), NULL, wr, serdata); } int spdp_write (struct participant *pp) { - struct nn_xmsg *mpayload; struct writer *wr; - int ret; - - if (pp->e.onlylocal) { - /* This topic is only locally available. */ - return 0; - } - - ETRACE (pp, "spdp_write("PGUIDFMT")\n", PGUID (pp->e.guid)); - - if ((wr = get_builtin_writer (pp, NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER)) == NULL) - { - ETRACE (pp, "spdp_write("PGUIDFMT") - builtin participant writer not found\n", PGUID (pp->e.guid)); - return 0; - } - - /* First create a fake message for the payload: we can add plists to - xmsgs easily, but not to serdata. But it is rather easy to copy - the payload of an xmsg over to a serdata ... Expected size isn't - terribly important, the msg will grow as needed, address space is - essentially meaningless because we only use the message to - construct the payload. */ - mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid, pp, 0, NN_XMSG_KIND_DATA); - get_participant_builtin_topic_data(pp, mpayload, false); - ret = write_mpayload (wr, 1, PID_PARTICIPANT_GUID, mpayload); - nn_xmsg_free (mpayload); - return ret; -} - - - -#if 0 -int spdp_write (struct participant *pp) -{ - struct nn_xmsg *mpayload; - struct nn_locators_one def_uni_loc_one, def_multi_loc_one, meta_uni_loc_one, meta_multi_loc_one; ddsi_plist_t ps; - struct writer *wr; - size_t size; - char node[64]; - uint64_t qosdiff; - int ret; + struct participant_builtin_topic_data_locators locs; if (pp->e.onlylocal) { /* This topic is only locally available. */ @@ -383,154 +336,14 @@ int spdp_write (struct participant *pp) return 0; } - /* First create a fake message for the payload: we can add plists to - xmsgs easily, but not to serdata. But it is rather easy to copy - the payload of an xmsg over to a serdata ... Expected size isn't - terribly important, the msg will grow as needed, address space is - essentially meaningless because we only use the message to - construct the payload. */ - mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid, pp, 0, NN_XMSG_KIND_DATA); - - ddsi_plist_init_empty (&ps); - ps.present |= PP_PARTICIPANT_GUID | PP_BUILTIN_ENDPOINT_SET | - PP_PROTOCOL_VERSION | PP_VENDORID | PP_PARTICIPANT_LEASE_DURATION | - PP_DOMAIN_ID; - ps.participant_guid = pp->e.guid; - ps.builtin_endpoint_set = pp->bes; - ps.protocol_version.major = RTPS_MAJOR; - ps.protocol_version.minor = RTPS_MINOR; - ps.vendorid = NN_VENDORID_ECLIPSE; - ps.domain_id = pp->e.gv->config.extDomainId.value; - /* Be sure not to send a DOMAIN_TAG when it is the default (an empty) - string: it is an "incompatible-if-unrecognized" parameter, and so - implementations that don't understand the parameter will refuse to - discover us, and so sending the default would break backwards - compatibility. */ - if (strcmp (pp->e.gv->config.domainTag, "") != 0) - { - ps.present |= PP_DOMAIN_TAG; - ps.aliased |= PP_DOMAIN_TAG; - ps.domain_tag = pp->e.gv->config.domainTag; - } - ps.default_unicast_locators.n = 1; - ps.default_unicast_locators.first = - ps.default_unicast_locators.last = &def_uni_loc_one; - ps.metatraffic_unicast_locators.n = 1; - ps.metatraffic_unicast_locators.first = - ps.metatraffic_unicast_locators.last = &meta_uni_loc_one; - def_uni_loc_one.next = NULL; - meta_uni_loc_one.next = NULL; - - if (pp->e.gv->config.many_sockets_mode == MSM_MANY_UNICAST) - { - def_uni_loc_one.loc = pp->m_locator; - meta_uni_loc_one.loc = pp->m_locator; - } - else - { - def_uni_loc_one.loc = pp->e.gv->loc_default_uc; - meta_uni_loc_one.loc = pp->e.gv->loc_meta_uc; - } - - if (pp->e.gv->config.publish_uc_locators) - { - ps.present |= PP_DEFAULT_UNICAST_LOCATOR | PP_METATRAFFIC_UNICAST_LOCATOR; - ps.aliased |= PP_DEFAULT_UNICAST_LOCATOR | PP_METATRAFFIC_UNICAST_LOCATOR; - } - - if (pp->e.gv->config.allowMulticast) - { - int include = 0; -#ifdef DDSI_INCLUDE_SSM - /* Note that if the default multicast address is an SSM address, - we will simply advertise it. The recipients better understand - it means the writers will publish to address and the readers - favour SSM. */ - if (ddsi_is_ssm_mcaddr (pp->e.gv, &pp->e.gv->loc_default_mc)) - include = (pp->e.gv->config.allowMulticast & AMC_SSM) != 0; - else - include = (pp->e.gv->config.allowMulticast & AMC_ASM) != 0; -#else - if (pp->e.gv->config.allowMulticast & AMC_ASM) - include = 1; -#endif - if (include) - { - ps.present |= PP_DEFAULT_MULTICAST_LOCATOR | PP_METATRAFFIC_MULTICAST_LOCATOR; - ps.aliased |= PP_DEFAULT_MULTICAST_LOCATOR | PP_METATRAFFIC_MULTICAST_LOCATOR; - ps.default_multicast_locators.n = 1; - ps.default_multicast_locators.first = - ps.default_multicast_locators.last = &def_multi_loc_one; - ps.metatraffic_multicast_locators.n = 1; - ps.metatraffic_multicast_locators.first = - ps.metatraffic_multicast_locators.last = &meta_multi_loc_one; - def_multi_loc_one.next = NULL; - def_multi_loc_one.loc = pp->e.gv->loc_default_mc; - meta_multi_loc_one.next = NULL; - meta_multi_loc_one.loc = pp->e.gv->loc_meta_mc; - } - } - ps.participant_lease_duration = pp->lease_duration; - - /* Add Adlink specific version information */ - { - ps.present |= PP_ADLINK_PARTICIPANT_VERSION_INFO; - memset (&ps.adlink_participant_version_info, 0, sizeof (ps.adlink_participant_version_info)); - ps.adlink_participant_version_info.version = 0; - ps.adlink_participant_version_info.flags = - NN_ADLINK_FL_DDSI2_PARTICIPANT_FLAG | - NN_ADLINK_FL_PTBES_FIXED_0 | - NN_ADLINK_FL_SUPPORTS_STATUSINFOX; - if (pp->e.gv->config.besmode == BESMODE_MINIMAL) - ps.adlink_participant_version_info.flags |= NN_ADLINK_FL_MINIMAL_BES_MODE; - ddsrt_mutex_lock (&pp->e.gv->privileged_pp_lock); - if (pp->is_ddsi2_pp) - ps.adlink_participant_version_info.flags |= NN_ADLINK_FL_PARTICIPANT_IS_DDSI2; - ddsrt_mutex_unlock (&pp->e.gv->privileged_pp_lock); - - if (ddsrt_gethostname(node, sizeof(node)-1) < 0) - (void) ddsrt_strlcpy (node, "unknown", sizeof (node)); - size = strlen(node) + strlen(DDS_VERSION) + strlen(DDS_HOST_NAME) + strlen(DDS_TARGET_NAME) + 4; /* + ///'\0' */ - ps.adlink_participant_version_info.internals = ddsrt_malloc(size); - (void) snprintf(ps.adlink_participant_version_info.internals, size, "%s/%s/%s/%s", node, DDS_VERSION, DDS_HOST_NAME, DDS_TARGET_NAME); - ETRACE (pp, "spdp_write("PGUIDFMT") - internals: %s\n", PGUID (pp->e.guid), ps.adlink_participant_version_info.internals); - } - -#ifdef DDSI_INCLUDE_SECURITY - /* Add Security specific information. */ - if (q_omg_get_participant_security_info(pp, &(ps.participant_security_info))) { - ps.present |= PP_PARTICIPANT_SECURITY_INFO; - ps.aliased |= PP_PARTICIPANT_SECURITY_INFO; - } -#endif - - /* Participant QoS's insofar as they are set, different from the default. Currently, that means just USER_DATA. */ - qosdiff = ddsi_xqos_delta (&pp->plist->qos, &pp->e.gv->default_plist_pp.qos, QP_USER_DATA); - if (pp->e.gv->config.explicitly_publish_qos_set_to_default) - qosdiff |= ~QP_UNRECOGNIZED_INCOMPATIBLE_MASK; - - assert (ps.qos.present == 0); - ddsi_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, 0); - ddsi_plist_addtomsg (mpayload, pp->plist, 0, qosdiff); -#ifdef DDSI_INCLUDE_SECURITY - if (q_omg_participant_is_secure(pp)) - ddsi_plist_addtomsg (mpayload, pp->plist, PP_IDENTITY_TOKEN | PP_PERMISSIONS_TOKEN, 0); -#endif - nn_xmsg_addpar_sentinel (mpayload); - ddsi_plist_fini (&ps); - - ret = write_mpayload (wr, 1, PID_PARTICIPANT_GUID, mpayload); - nn_xmsg_free (mpayload); - return ret; + get_participant_builtin_topic_data (pp, &ps, &locs); + return write_and_fini_plist (wr, &ps, true); } -#endif static int spdp_dispose_unregister_with_wr (struct participant *pp, unsigned entityid) { - struct nn_xmsg *mpayload; ddsi_plist_t ps; struct writer *wr; - int ret; if ((wr = get_builtin_writer (pp, entityid)) == NULL) { @@ -540,17 +353,10 @@ static int spdp_dispose_unregister_with_wr (struct participant *pp, unsigned ent return 0; } - mpayload = nn_xmsg_new (pp->e.gv->xmsgpool, &pp->e.guid, pp, 0, NN_XMSG_KIND_DATA); ddsi_plist_init_empty (&ps); ps.present |= PP_PARTICIPANT_GUID; ps.participant_guid = pp->e.guid; - ddsi_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0); - nn_xmsg_addpar_sentinel (mpayload); - ddsi_plist_fini (&ps); - - ret = write_mpayload (wr, 0, PID_PARTICIPANT_GUID, mpayload); - nn_xmsg_free (mpayload); - return ret; + return write_and_fini_plist (wr, &ps, false); } int spdp_dispose_unregister (struct participant *pp) @@ -1016,46 +822,23 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, dds return 1; } -static void handle_SPDP (const struct receiver_state *rst, ddsi_entityid_t pwr_entityid, seqno_t seq, ddsrt_wctime_t timestamp, unsigned statusinfo, const void *vdata, uint32_t len) +static void handle_SPDP (const struct receiver_state *rst, ddsi_entityid_t pwr_entityid, seqno_t seq, const struct ddsi_serdata *serdata) { struct ddsi_domaingv * const gv = rst->gv; - const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */ - if (data == NULL) + ddsi_plist_t decoded_data; + if (ddsi_serdata_to_sample (serdata, &decoded_data, NULL, NULL)) { - RSTTRACE ("SPDP ST%x no payload?\n", statusinfo); - return; - } - else - { - ddsi_plist_t decoded_data; - ddsi_plist_src_t src; int interesting = 0; - dds_return_t plist_ret; - src.protocol_version = rst->protocol_version; - src.vendorid = rst->vendor; - src.encoding = data->identifier; - src.buf = (unsigned char *) data + 4; - src.bufsz = len - 4; - src.strict = NN_STRICT_P (gv->config); - src.factory = gv->m_factory; - src.logconfig = &gv->logconfig; - if ((plist_ret = ddsi_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) - { - if (plist_ret != DDS_RETCODE_UNSUPPORTED) - GVWARNING ("SPDP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); - return; - } - - switch (statusinfo & (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER)) + switch (serdata->statusinfo & (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER)) { case 0: - interesting = handle_SPDP_alive (rst, seq, timestamp, &decoded_data); + interesting = handle_SPDP_alive (rst, seq, serdata->timestamp, &decoded_data); break; case NN_STATUSINFO_DISPOSE: case NN_STATUSINFO_UNREGISTER: case (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER): - interesting = handle_SPDP_dead (rst, pwr_entityid, timestamp, &decoded_data, statusinfo); + interesting = handle_SPDP_dead (rst, pwr_entityid, serdata->timestamp, &decoded_data, serdata->statusinfo); break; } @@ -1115,10 +898,8 @@ static int sedp_write_endpoint { struct ddsi_domaingv * const gv = wr->e.gv; const dds_qos_t *defqos = is_writer_entityid (epguid->entityid) ? &gv->default_xqos_wr : &gv->default_xqos_rd; - struct nn_xmsg *mpayload; uint64_t qosdiff; ddsi_plist_t ps; - int ret; ddsi_plist_init_empty (&ps); ps.present |= PP_ENDPOINT_GUID; @@ -1193,20 +974,9 @@ static int sedp_write_endpoint } } - /* The message is only a temporary thing, used only for encoding - the QoS and other settings. So the header fields aren't really - important, except that they need to be set to reasonable things - or it'll crash */ - mpayload = nn_xmsg_new (gv->xmsgpool, &wr->e.guid, wr->c.pp, 0, NN_XMSG_KIND_DATA); - ddsi_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0); - if (xqos) ddsi_xqos_addtomsg (mpayload, xqos, qosdiff); - nn_xmsg_addpar_sentinel (mpayload); - ddsi_plist_fini (&ps); - - GVLOGDISC ("sedp: write for "PGUIDFMT" via "PGUIDFMT"\n", PGUID (*epguid), PGUID (wr->e.guid)); - ret = write_mpayload (wr, alive, PID_ENDPOINT_GUID, mpayload); - nn_xmsg_free (mpayload); - return ret; + if (xqos) + ddsi_xqos_mergein_missing (&ps.qos, xqos, qosdiff); + return write_and_fini_plist (wr, &ps, alive); } static struct writer *get_sedp_writer (const struct participant *pp, unsigned entityid) @@ -1597,145 +1367,39 @@ static void handle_SEDP_dead (const struct receiver_state *rst, ddsi_plist_t *da GVLOGDISC (" %s\n", (res < 0) ? " unknown" : " delete"); } -static void handle_SEDP (const struct receiver_state *rst, seqno_t seq, ddsrt_wctime_t timestamp, unsigned statusinfo, const void *vdata, uint32_t len) +static void handle_SEDP (const struct receiver_state *rst, seqno_t seq, struct ddsi_serdata *serdata) { - struct ddsi_domaingv * const gv = rst->gv; - const struct CDRHeader *data = vdata; /* built-ins not deserialized (yet) */ - GVLOGDISC ("SEDP ST%x", statusinfo); - if (data == NULL) + ddsi_plist_t decoded_data; + if (ddsi_serdata_to_sample (serdata, &decoded_data, NULL, NULL)) { - GVLOGDISC (" no payload?\n"); - return; - } - else - { - ddsi_plist_t decoded_data; - ddsi_plist_src_t src; - dds_return_t plist_ret; - src.protocol_version = rst->protocol_version; - src.vendorid = rst->vendor; - src.encoding = data->identifier; - src.buf = (unsigned char *) data + 4; - src.bufsz = len - 4; - src.strict = NN_STRICT_P (gv->config); - src.factory = gv->m_factory; - src.logconfig = &gv->logconfig; - if ((plist_ret = ddsi_plist_init_frommsg (&decoded_data, NULL, ~(uint64_t)0, ~(uint64_t)0, &src)) < 0) - { - if (plist_ret != DDS_RETCODE_UNSUPPORTED) - GVWARNING ("SEDP (vendor %u.%u): invalid qos/parameters\n", src.vendorid.id[0], src.vendorid.id[1]); - return; - } - - switch (statusinfo & (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER)) + switch (serdata->statusinfo & (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER)) { case 0: - handle_SEDP_alive (rst, seq, &decoded_data, &rst->src_guid_prefix, rst->vendor, timestamp); + handle_SEDP_alive (rst, seq, &decoded_data, &rst->src_guid_prefix, rst->vendor, serdata->timestamp); break; - case NN_STATUSINFO_DISPOSE: case NN_STATUSINFO_UNREGISTER: case (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER): - handle_SEDP_dead (rst, &decoded_data, timestamp); + handle_SEDP_dead (rst, &decoded_data, serdata->timestamp); break; } - ddsi_plist_fini (&decoded_data); } } /****************************************************************************** - *** - *** Topics - *** *****************************************************************************/ -int sedp_write_topic (struct participant *pp, const struct ddsi_plist *datap) -{ - struct writer *sedp_wr; - struct nn_xmsg *mpayload; - uint64_t delta; - int ret; - - assert (datap->qos.present & QP_TOPIC_NAME); - - if (pp->e.onlylocal) { - /* This topic is only locally available. */ - return 0; - } - - sedp_wr = get_sedp_writer (pp, NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER); - - mpayload = nn_xmsg_new (sedp_wr->e.gv->xmsgpool, &sedp_wr->e.guid, pp, 0, NN_XMSG_KIND_DATA); - delta = ddsi_xqos_delta (&datap->qos, &sedp_wr->e.gv->default_xqos_tp, ~(uint64_t)0); - if (sedp_wr->e.gv->config.explicitly_publish_qos_set_to_default) - delta |= ~QP_UNRECOGNIZED_INCOMPATIBLE_MASK; - ddsi_plist_addtomsg (mpayload, datap, ~(uint64_t)0, delta); - nn_xmsg_addpar_sentinel (mpayload); - - ETRACE (pp, "sedp: write topic %s via "PGUIDFMT"\n", datap->qos.topic_name, PGUID (sedp_wr->e.guid)); - ret = write_mpayload (sedp_wr, 1, PID_TOPIC_NAME, mpayload); - nn_xmsg_free (mpayload); - return ret; -} - - -/****************************************************************************** - *****************************************************************************/ - -/* FIXME: defragment is a copy of the one in q_receive.c, but the deserialised should be enhanced to handle fragmented data (and arguably the processing here should be built on proper data readers) */ -static int defragment (unsigned char **datap, const struct nn_rdata *fragchain, uint32_t sz) -{ - if (fragchain->nextfrag == NULL) - { - *datap = NN_RMSG_PAYLOADOFF (fragchain->rmsg, NN_RDATA_PAYLOAD_OFF (fragchain)); - return 0; - } - else - { - unsigned char *buf; - uint32_t off = 0; - buf = ddsrt_malloc (sz); - while (fragchain) - { - assert (fragchain->min <= off); - assert (fragchain->maxp1 <= sz); - if (fragchain->maxp1 > off) - { - /* only copy if this fragment adds data */ - const unsigned char *payload = NN_RMSG_PAYLOADOFF (fragchain->rmsg, NN_RDATA_PAYLOAD_OFF (fragchain)); - memcpy (buf + off, payload + off - fragchain->min, fragchain->maxp1 - off); - off = fragchain->maxp1; - } - fragchain = fragchain->nextfrag; - } - *datap = buf; - return 1; - } -} - int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, UNUSED_ARG (const ddsi_guid_t *rdguid), UNUSED_ARG (void *qarg)) { struct ddsi_domaingv * const gv = sampleinfo->rst->gv; struct proxy_writer *pwr; - struct { - struct CDRHeader cdr; - nn_parameter_t p_endpoint_guid; - char kh[16]; - nn_parameter_t p_sentinel; - } keyhash_payload; unsigned statusinfo; int need_keyhash; ddsi_guid_t srcguid; Data_DataFrag_common_t *msg; unsigned char data_smhdr_flags; ddsi_plist_t qos; - unsigned char *datap; - int needs_free; - uint32_t datasz = sampleinfo->size; - ddsrt_wctime_t timestamp; - - needs_free = defragment (&datap, fragchain, sampleinfo->size); /* Luckily, most of the Data and DataFrag headers are the same - and in particular, all that we care about here is the same. The @@ -1770,7 +1434,7 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str consequently expect to need the keyhash. Then, if sampleinfo says it is a complex qos, or the keyhash is required, extract all we need from the inline qos. */ - need_keyhash = (datasz == 0 || (data_smhdr_flags & (DATA_FLAG_KEYFLAG | DATA_FLAG_DATAFLAG)) == 0); + need_keyhash = (sampleinfo->size == 0 || (data_smhdr_flags & (DATA_FLAG_KEYFLAG | DATA_FLAG_DATAFLAG)) == 0); if (!(sampleinfo->complex_qos || need_keyhash)) { ddsi_plist_init_empty (&qos); @@ -1809,113 +1473,117 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str goto done_upd_deliv; } - /* Built-ins still do their own deserialization (SPDP <=> pwr == - NULL)). */ - if (statusinfo == 0) + /* proxy writers don't reference a topic object, SPDP doesn't have matched readers + but all the GUIDs are known, so be practical and map that */ + const struct ddsi_sertopic *topic; + switch (srcguid.entityid.u) { - if (datasz == 0 || !(data_smhdr_flags & DATA_FLAG_DATAFLAG)) - { - GVWARNING ("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": built-in data but no payload\n", - sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], - PGUID (srcguid), sampleinfo->seq); - goto done_upd_deliv; - } + case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER: + topic = gv->spdp_topic; + break; + case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER: + topic = gv->sedp_writer_topic; + break; + case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER: + topic = gv->sedp_reader_topic; + break; + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER: + topic = gv->pmd_topic; + break; +#ifdef DDSI_INCLUDE_SECURITY + case NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER: + topic = gv->spdp_secure_topic; + break; + case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER: + topic = gv->sedp_writer_secure_topic; + break; + case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER: + topic = gv->sedp_reader_secure_topic; + break; + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER: + topic = gv->pmd_secure_topic; + break; + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER: + topic = gv->pgm_stateless_topic; + break; + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER: + topic = gv->pgm_volatile_topic; + break; +#endif + default: + topic = NULL; + break; } - else if (datasz) + if (topic == NULL) { - /* Raw data must be full payload for write, just keys for - dispose and unregister. First has been checked; the second - hasn't been checked fully yet. */ - if (!(data_smhdr_flags & DATA_FLAG_KEYFLAG)) - { - GVWARNING ("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": dispose/unregister of built-in data but payload not just key\n", - sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], - PGUID (srcguid), sampleinfo->seq); - goto done_upd_deliv; - } + /* unrecognized source entity id => ignore */ + goto done_upd_deliv; } + + struct ddsi_serdata *d; + if (data_smhdr_flags & DATA_FLAG_DATAFLAG) + d = ddsi_serdata_from_ser (topic, SDK_DATA, fragchain, sampleinfo->size); + else if (data_smhdr_flags & DATA_FLAG_KEYFLAG) + d = ddsi_serdata_from_ser (topic, SDK_KEY, fragchain, sampleinfo->size); else if ((qos.present & PP_KEYHASH) && !NN_STRICT_P(gv->config)) - { - /* For SPDP/SEDP, fake a parameter list with just a keyhash. For - PMD, just use the keyhash directly. Too hard to fix everything - at the same time ... */ - if (srcguid.entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER) - { - datap = qos.keyhash.value; - datasz = sizeof (qos.keyhash); - } - else - { - nn_parameterid_t pid; - keyhash_payload.cdr.identifier = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? PL_CDR_LE : PL_CDR_BE); - keyhash_payload.cdr.options = 0; - switch (srcguid.entityid.u) - { - case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER: - case NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER: - pid = PID_PARTICIPANT_GUID; - break; - case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER: - case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER: - case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER: - case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER: - pid = PID_ENDPOINT_GUID; - break; - case NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER: - case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER: - /* placeholders */ - pid = PID_ENDPOINT_GUID; - break; - default: - GVLOGDISC ("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": mapping keyhash to ENDPOINT_GUID", - sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], - PGUID (srcguid), sampleinfo->seq); - pid = PID_ENDPOINT_GUID; - break; - } - keyhash_payload.p_endpoint_guid.parameterid = pid; - keyhash_payload.p_endpoint_guid.length = sizeof (ddsi_keyhash_t); - memcpy (keyhash_payload.kh, &qos.keyhash, sizeof (qos.keyhash)); - keyhash_payload.p_sentinel.parameterid = PID_SENTINEL; - keyhash_payload.p_sentinel.length = 0; - datap = (unsigned char *) &keyhash_payload; - datasz = sizeof (keyhash_payload); - } - } + d = ddsi_serdata_from_keyhash (topic, &qos.keyhash); else { - GVWARNING ("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": dispose/unregister with no content\n", + GVLOGDISC ("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": missing payload\n", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (srcguid), sampleinfo->seq); goto done_upd_deliv; } - if (sampleinfo->timestamp.v != DDSRT_WCTIME_INVALID.v) - timestamp = sampleinfo->timestamp; - else - timestamp = ddsrt_time_wallclock (); + d->timestamp = (sampleinfo->timestamp.v != DDSRT_WCTIME_INVALID.v) ? sampleinfo->timestamp : ddsrt_time_wallclock (); + d->statusinfo = statusinfo; + // set protocol version & vendor id for plist types + // FIXME: find a better way then fixing these up afterward + if (d->ops == &ddsi_serdata_ops_plist) + { + struct ddsi_serdata_plist *d_plist = (struct ddsi_serdata_plist *) d; + d_plist->protoversion = sampleinfo->rst->protocol_version; + d_plist->vendorid = sampleinfo->rst->vendor; + } + + if (gv->logconfig.c.mask & DDS_LC_TRACE) + { + ddsi_guid_t guid; + char tmp[2048]; + size_t res = 0; + tmp[0] = 0; + if (gv->logconfig.c.mask & DDS_LC_CONTENT) + res = ddsi_serdata_print (d, tmp, sizeof (tmp)); + if (pwr) guid = pwr->e.guid; else memset (&guid, 0, sizeof (guid)); + GVTRACE ("data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": ST%x %s/%s:%s%s\n", + sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], + PGUID (guid), sampleinfo->seq, statusinfo, d->topic->name, d->topic->type_name, + tmp, res < sizeof (tmp) - 1 ? "" : "(trunc)"); + } + switch (srcguid.entityid.u) { case NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER: case NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER: - handle_SPDP (sampleinfo->rst, srcguid.entityid, sampleinfo->seq, timestamp, statusinfo, datap, datasz); + handle_SPDP (sampleinfo->rst, srcguid.entityid, sampleinfo->seq, d); break; case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER: case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER: case NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER: case NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER: - handle_SEDP (sampleinfo->rst, sampleinfo->seq, timestamp, statusinfo, datap, datasz); + handle_SEDP (sampleinfo->rst, sampleinfo->seq, d); break; case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER: - case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER: - handle_pmd_message (sampleinfo->rst, timestamp, statusinfo, datap, datasz); + case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER: { + handle_pmd_message (sampleinfo->rst, d); break; + } #ifdef DDSI_INCLUDE_SECURITY case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER: - handle_auth_handshake_message(sampleinfo->rst, srcguid.entityid, timestamp, statusinfo, datap, datasz); + handle_auth_handshake_message(sampleinfo->rst, srcguid.entityid, d); break; case NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER: - handle_crypto_exchange_message(sampleinfo->rst, srcguid.entityid, timestamp, statusinfo, datap, datasz); + handle_crypto_exchange_message(sampleinfo->rst, d); break; #endif default: @@ -1925,9 +1593,9 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str break; } + ddsi_serdata_unref (d); + done_upd_deliv: - if (needs_free) - ddsrt_free (datap); if (pwr) { /* No proxy writer for SPDP */ diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index f0fff03..5f76314 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -563,7 +563,7 @@ static void add_security_builtin_endpoints(struct participant *pp, ddsi_guid_t * subguid->entityid = to_entityid (NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER); wrinfo = whc_make_wrinfo (NULL, &gv->builtin_endpoint_xqos_wr); - new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); + new_writer_guid (NULL, subguid, group_guid, pp, gv->spdp_secure_topic, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); whc_free_wrinfo (wrinfo); /* But we need the as_disc address set for SPDP, because we need to send it to everyone regardless of the existence of readers. */ @@ -572,28 +572,28 @@ static void add_security_builtin_endpoints(struct participant *pp, ddsi_guid_t * subguid->entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER); wrinfo = whc_make_wrinfo (NULL, &gv->builtin_stateless_xqos_wr); - new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_stateless_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); + new_writer_guid (NULL, subguid, group_guid, pp, gv->pgm_stateless_topic, &gv->builtin_stateless_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); whc_free_wrinfo (wrinfo); pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_STATELESS_MESSAGE_ANNOUNCER; subguid->entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER); wrinfo = whc_make_wrinfo (NULL, &gv->builtin_volatile_xqos_wr); - new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_volatile_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); + new_writer_guid (NULL, subguid, group_guid, pp, gv->pgm_volatile_topic, &gv->builtin_volatile_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); whc_free_wrinfo (wrinfo); pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_VOLATILE_SECURE_ANNOUNCER; wrinfo = whc_make_wrinfo (NULL, &gv->builtin_endpoint_xqos_wr); subguid->entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER); - new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); + new_writer_guid (NULL, subguid, group_guid, pp, gv->pmd_secure_topic, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_SECURE_ANNOUNCER; subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER); - new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); + new_writer_guid (NULL, subguid, group_guid, pp, gv->sedp_writer_secure_topic, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); pp->bes |= NN_BUILTIN_ENDPOINT_PUBLICATION_MESSAGE_SECURE_ANNOUNCER; subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER); - new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); + new_writer_guid (NULL, subguid, group_guid, pp, gv->sedp_reader_secure_topic, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); pp->bes |= NN_BUILTIN_ENDPOINT_SUBSCRIPTION_MESSAGE_SECURE_ANNOUNCER; whc_free_wrinfo (wrinfo); @@ -602,11 +602,11 @@ static void add_security_builtin_endpoints(struct participant *pp, ddsi_guid_t * if (add_readers) { subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_READER); - new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, subguid, group_guid, pp, gv->sedp_reader_secure_topic, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); pp->bes |= NN_BUILTIN_ENDPOINT_SUBSCRIPTION_MESSAGE_SECURE_DETECTOR; subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_READER); - new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, subguid, group_guid, pp, gv->sedp_writer_secure_topic, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); pp->bes |= NN_BUILTIN_ENDPOINT_PUBLICATION_MESSAGE_SECURE_DETECTOR; } @@ -615,19 +615,19 @@ static void add_security_builtin_endpoints(struct participant *pp, ddsi_guid_t * * besmode flag setting, because all participant do require authentication. */ subguid->entityid = to_entityid (NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_READER); - new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, subguid, group_guid, pp, gv->spdp_secure_topic, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_DETECTOR; subguid->entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER); - new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_volatile_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, subguid, group_guid, pp, gv->pgm_volatile_topic, &gv->builtin_volatile_xqos_rd, NULL, NULL, NULL); pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_VOLATILE_SECURE_DETECTOR; subguid->entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_READER); - new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_stateless_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, subguid, group_guid, pp, gv->pgm_stateless_topic, &gv->builtin_stateless_xqos_rd, NULL, NULL, NULL); pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_STATELESS_MESSAGE_DETECTOR; subguid->entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_READER); - new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, subguid, group_guid, pp, gv->pmd_secure_topic, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_SECURE_DETECTOR; } #endif @@ -640,25 +640,18 @@ static void add_builtin_endpoints(struct participant *pp, ddsi_guid_t *subguid, /* SEDP writers: */ subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_WRITER); - new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); + new_writer_guid (NULL, subguid, group_guid, pp, gv->sedp_reader_topic, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_ANNOUNCER; subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_WRITER); - new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); + new_writer_guid (NULL, subguid, group_guid, pp, gv->sedp_writer_topic, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_ANNOUNCER; /* PMD writer: */ subguid->entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER); - new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); + new_writer_guid (NULL, subguid, group_guid, pp, gv->pmd_topic, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER; - if (gv->config.do_topic_discovery) - { - subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_TOPIC_WRITER); - new_writer_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_wr, whc_new(gv, wrinfo), NULL, NULL); - pp->bes |= NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER; - } - whc_free_wrinfo (wrinfo); } @@ -666,19 +659,19 @@ static void add_builtin_endpoints(struct participant *pp, ddsi_guid_t *subguid, if (add_readers) { subguid->entityid = to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER); - new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->spdp_endpoint_xqos, NULL, NULL, NULL); + new_reader_guid (NULL, subguid, group_guid, pp, gv->spdp_topic, &gv->spdp_endpoint_xqos, NULL, NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR; subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_READER); - new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, subguid, group_guid, pp, gv->sedp_reader_topic, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_SUBSCRIPTION_DETECTOR; subguid->entityid = to_entityid (NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_READER); - new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, subguid, group_guid, pp, gv->sedp_writer_topic, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); pp->bes |= NN_DISC_BUILTIN_ENDPOINT_PUBLICATION_DETECTOR; subguid->entityid = to_entityid (NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER); - new_reader_guid (NULL, subguid, group_guid, pp, NULL, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); + new_reader_guid (NULL, subguid, group_guid, pp, gv->pmd_topic, &gv->builtin_endpoint_xqos_rd, NULL, NULL, NULL); pp->bes |= NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER; } @@ -1001,7 +994,7 @@ dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv { subguid.entityid = to_entityid (NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_WRITER); wrinfo = whc_make_wrinfo (NULL, &gv->spdp_endpoint_xqos); - new_writer_guid (NULL, &subguid, &group_guid, pp, NULL, &gv->spdp_endpoint_xqos, whc_new(gv, wrinfo), NULL, NULL); + new_writer_guid (NULL, &subguid, &group_guid, pp, gv->spdp_topic, &gv->spdp_endpoint_xqos, whc_new(gv, wrinfo), NULL, NULL); whc_free_wrinfo (wrinfo); /* But we need the as_disc address set for SPDP, because we need to send it to everyone regardless of the existence of readers. */ @@ -2590,9 +2583,6 @@ already_matched: return; } - - - static void proxy_reader_add_connection (struct proxy_reader *prd, struct writer *wr, int64_t crypto_handle) { struct prd_wr_match *m = ddsrt_malloc (sizeof (*m)); @@ -2615,7 +2605,6 @@ static void proxy_reader_add_connection (struct proxy_reader *prd, struct writer } else { - assert (wr->topic || is_builtin_endpoint (wr->e.guid.entityid, NN_VENDORID_ECLIPSE)); ELOGDISC (prd, " proxy_reader_add_connection(wr "PGUIDFMT" prd "PGUIDFMT")\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); ddsrt_avl_insert_ipath (&prd_writers_treedef, &prd->writers, m, &path); @@ -2920,7 +2909,6 @@ static void connect_writer_with_proxy_reader_wrapper (struct entity_common *vwr, struct proxy_reader *prd = (struct proxy_reader *) vprd; assert (wr->e.kind == EK_WRITER); assert (prd->e.kind == EK_PROXY_READER); - assert (is_builtin_endpoint (wr->e.guid.entityid, NN_VENDORID_ECLIPSE) == is_builtin_endpoint (prd->e.guid.entityid, prd->c.vendor)); connect_writer_with_proxy_reader (wr, prd, tnow); } @@ -2930,7 +2918,6 @@ static void connect_proxy_writer_with_reader_wrapper (struct entity_common *vpwr struct reader *rd = (struct reader *) vrd; assert (pwr->e.kind == EK_PROXY_WRITER); assert (rd->e.kind == EK_READER); - assert (is_builtin_endpoint (rd->e.guid.entityid, NN_VENDORID_ECLIPSE) == is_builtin_endpoint (pwr->e.guid.entityid, pwr->c.vendor)); connect_proxy_writer_with_reader (pwr, rd, tnow); } @@ -2940,8 +2927,6 @@ static void connect_writer_with_reader_wrapper (struct entity_common *vwr, struc struct reader *rd = (struct reader *) vrd; assert (wr->e.kind == EK_WRITER); assert (rd->e.kind == EK_READER); - assert (!is_builtin_endpoint (wr->e.guid.entityid, NN_VENDORID_ECLIPSE) || is_local_orphan_endpoint (&wr->e)); - assert (!is_builtin_endpoint (rd->e.guid.entityid, NN_VENDORID_ECLIPSE)); connect_writer_with_reader (wr, rd, tnow); } @@ -3234,7 +3219,7 @@ static void new_reader_writer_common (const struct ddsrt_log_cfg *logcfg, const { const char *partition = "(default)"; const char *partition_suffix = ""; - assert (is_builtin_entityid (guid->entityid, NN_VENDORID_ECLIPSE) ? (topic == NULL) : (topic != NULL)); + assert (topic != NULL); if (is_builtin_entityid (guid->entityid, NN_VENDORID_ECLIPSE)) { /* continue printing it as not being in a partition, the actual @@ -3252,8 +3237,8 @@ static void new_reader_writer_common (const struct ddsrt_log_cfg *logcfg, const is_writer_entityid (guid->entityid) ? "writer" : "reader", PGUID (*guid), partition, partition_suffix, - topic ? topic->name : "(null)", - topic ? topic->type_name : "(null)"); + topic->name, + topic->type_name); } static void endpoint_common_init (struct entity_common *e, struct endpoint_common *c, struct ddsi_domaingv *gv, enum entity_kind kind, const struct ddsi_guid *guid, const struct ddsi_guid *group_guid, struct participant *pp, bool onlylocal) @@ -3282,12 +3267,12 @@ static void endpoint_common_fini (struct entity_common *e, struct endpoint_commo static int set_topic_type_name (dds_qos_t *xqos, const struct ddsi_sertopic * topic) { - if (!(xqos->present & QP_TYPE_NAME) && topic) + if (!(xqos->present & QP_TYPE_NAME)) { xqos->present |= QP_TYPE_NAME; xqos->type_name = ddsrt_strdup (topic->type_name); } - if (!(xqos->present & QP_TOPIC_NAME) && topic) + if (!(xqos->present & QP_TOPIC_NAME)) { xqos->present |= QP_TOPIC_NAME; xqos->topic_name = ddsrt_strdup (topic->name); @@ -3754,7 +3739,7 @@ static dds_return_t new_writer_guid (struct writer **wr_out, const struct ddsi_g delete_participant won't interfere with our ability to address the participant */ - const bool onlylocal = topic && builtintopic_is_builtintopic (pp->e.gv->builtin_topic_interface, topic); + const bool onlylocal = builtintopic_is_builtintopic (pp->e.gv->builtin_topic_interface, topic); endpoint_common_init (&wr->e, &wr->c, pp->e.gv, EK_WRITER, guid, group_guid, pp, onlylocal); new_writer_guid_common_init(wr, topic, xqos, whc, status_cb, status_entity); @@ -4241,7 +4226,7 @@ static dds_return_t new_reader_guid if (rd_out) *rd_out = rd; - const bool onlylocal = topic && builtintopic_is_builtintopic (pp->e.gv->builtin_topic_interface, topic); + const bool onlylocal = builtintopic_is_builtintopic (pp->e.gv->builtin_topic_interface, topic); endpoint_common_init (&rd->e, &rd->c, pp->e.gv, EK_READER, guid, group_guid, pp, onlylocal); /* Copy QoS, merging in defaults */ diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c index 859be30..cabcf49 100644 --- a/src/core/ddsi/src/q_init.c +++ b/src/core/ddsi/src/q_init.c @@ -50,6 +50,7 @@ #include "dds/ddsi/q_debmon.h" #include "dds/ddsi/q_init.h" #include "dds/ddsi/ddsi_threadmon.h" +#include "dds/ddsi/ddsi_pmd.h" #include "dds/ddsi/ddsi_tran.h" #include "dds/ddsi/ddsi_udp.h" @@ -57,6 +58,8 @@ #include "dds/ddsi/ddsi_raweth.h" #include "dds/ddsi/ddsi_mcgroup.h" #include "dds/ddsi/ddsi_serdata_default.h" +#include "dds/ddsi/ddsi_serdata_pserop.h" +#include "dds/ddsi/ddsi_serdata_plist.h" #include "dds/ddsi/ddsi_security_omg.h" #include "dds/ddsi/ddsi_tkmap.h" @@ -788,38 +791,75 @@ static void wait_for_receive_threads (struct ddsi_domaingv *gv) } } -static struct ddsi_sertopic *make_special_topic (const char *name, struct serdatapool *serpool, uint16_t enc_id, const struct ddsi_serdata_ops *ops) +static struct ddsi_sertopic *make_special_topic_pserop (const char *name, const char *typename, size_t memsize, size_t nops, const enum pserop *ops, size_t nops_key, const enum pserop *ops_key) { - /* FIXME: two things (at least) - - it claims there is a key, but the underlying type description is missing - that only works as long as it ends up comparing the keyhash field ... - the keyhash field should be eliminated; but this can simply be moved over to an alternate - topic class, it need not use the "default" one, that's mere expediency - - initialising/freeing them here, in this manner, is not very clean - it should be moved to somewhere in the topic implementation - (kinda natural if they stop being "default" ones) */ - struct ddsi_sertopic_default *st = ddsrt_malloc (sizeof (*st)); + struct ddsi_sertopic_pserop *st = ddsrt_malloc (sizeof (*st)); memset (st, 0, sizeof (*st)); - ddsi_sertopic_init (&st->c, name, name, &ddsi_sertopic_ops_default, ops, false); - st->native_encoding_identifier = enc_id; - st->serpool = serpool; + ddsi_sertopic_init (&st->c, name, typename, &ddsi_sertopic_ops_pserop, &ddsi_serdata_ops_pserop, nops_key == 0); + st->native_encoding_identifier = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN) ? CDR_LE : CDR_BE; + st->memsize = memsize; + st->nops = nops; + st->ops = ops; + st->nops_key = nops_key; + st->ops_key = ops_key; + return (struct ddsi_sertopic *) st; +} + +static struct ddsi_sertopic *make_special_topic_plist (const char *name, const char *typename, nn_parameterid_t keyparam) +{ + struct ddsi_sertopic_plist *st = ddsrt_malloc (sizeof (*st)); + memset (st, 0, sizeof (*st)); + ddsi_sertopic_init (&st->c, name, typename, &ddsi_sertopic_ops_plist, &ddsi_serdata_ops_plist, false); + st->native_encoding_identifier = (DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN) ? PL_CDR_LE : PL_CDR_BE; + st->keyparam = keyparam; return (struct ddsi_sertopic *) st; } static void free_special_topics (struct ddsi_domaingv *gv) { - ddsi_sertopic_unref (gv->plist_topic); - ddsi_sertopic_unref (gv->rawcdr_topic); +#ifdef DDSI_INCLUDE_SECURITY + ddsi_sertopic_unref (gv->pgm_volatile_topic); + ddsi_sertopic_unref (gv->pgm_stateless_topic); + ddsi_sertopic_unref (gv->pmd_secure_topic); + ddsi_sertopic_unref (gv->spdp_secure_topic); + ddsi_sertopic_unref (gv->sedp_reader_secure_topic); + ddsi_sertopic_unref (gv->sedp_writer_secure_topic); +#endif + ddsi_sertopic_unref (gv->pmd_topic); + ddsi_sertopic_unref (gv->spdp_topic); + ddsi_sertopic_unref (gv->sedp_reader_topic); + ddsi_sertopic_unref (gv->sedp_writer_topic); } static void make_special_topics (struct ddsi_domaingv *gv) { - gv->plist_topic = make_special_topic ("plist", gv->serpool, DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? PL_CDR_LE : PL_CDR_BE, &ddsi_serdata_ops_plist); - gv->rawcdr_topic = make_special_topic ("rawcdr", gv->serpool, DDSRT_ENDIAN == DDSRT_LITTLE_ENDIAN ? CDR_LE : CDR_BE, &ddsi_serdata_ops_rawcdr); + gv->spdp_topic = make_special_topic_plist ("DCPSParticipant", "ParticipantBuiltinTopicData", PID_PARTICIPANT_GUID); + gv->sedp_reader_topic = make_special_topic_plist ("DCPSSubscription", "SubscriptionBuiltinTopicData", PID_ENDPOINT_GUID); + gv->sedp_writer_topic = make_special_topic_plist ("DCPSPublication", "PublicationBuiltinTopicData", PID_ENDPOINT_GUID); + gv->pmd_topic = make_special_topic_pserop ("DCPSParticipantMessage", "ParticipantMessageData", sizeof (ParticipantMessageData_t), participant_message_data_nops, participant_message_data_ops, participant_message_data_nops_key, participant_message_data_ops_key); + +#ifdef DDSI_INCLUDE_SECURITY + gv->spdp_secure_topic = make_special_topic_plist ("DCPSParticipantsSecure", "ParticipantBuiltinTopicDataSecure", PID_PARTICIPANT_GUID); + gv->sedp_reader_secure_topic = make_special_topic_plist ("DCPSSubscriptionsSecure", "SubscriptionBuiltinTopicDataSecure", PID_ENDPOINT_GUID); + gv->sedp_writer_secure_topic = make_special_topic_plist ("DCPSPublicationsSecure", "PublicationBuiltinTopicDataSecure", PID_ENDPOINT_GUID); + gv->pmd_secure_topic = make_special_topic_pserop ("DCPSParticipantMessageSecure", "ParticipantMessageDataSecure", sizeof (ParticipantMessageData_t), participant_message_data_nops, participant_message_data_ops, participant_message_data_nops_key, participant_message_data_ops_key); + gv->pgm_stateless_topic = make_special_topic_pserop ("DCPSParticipantStatelessMessage", "ParticipantStatelessMessage", sizeof (nn_participant_generic_message_t), pserop_participant_generic_message_nops, pserop_participant_generic_message, 0, NULL); + gv->pgm_volatile_topic = make_special_topic_pserop ("DCPSParticipantVolatileMessageSecure", "ParticipantVolatileMessageSecure", sizeof (nn_participant_generic_message_t), pserop_participant_generic_message_nops, pserop_participant_generic_message, 0, NULL); +#endif ddsrt_mutex_lock (&gv->sertopics_lock); - ddsi_sertopic_register_locked (gv, gv->plist_topic); - ddsi_sertopic_register_locked (gv, gv->rawcdr_topic); + ddsi_sertopic_register_locked (gv, gv->spdp_topic); + ddsi_sertopic_register_locked (gv, gv->sedp_reader_topic); + ddsi_sertopic_register_locked (gv, gv->sedp_writer_topic); + ddsi_sertopic_register_locked (gv, gv->pmd_topic); +#ifdef DDSI_INCLUDE_SECURITY + ddsi_sertopic_register_locked (gv, gv->spdp_secure_topic); + ddsi_sertopic_register_locked (gv, gv->sedp_reader_secure_topic); + ddsi_sertopic_register_locked (gv, gv->sedp_writer_secure_topic); + ddsi_sertopic_register_locked (gv, gv->pmd_secure_topic); + ddsi_sertopic_register_locked (gv, gv->pgm_stateless_topic); + ddsi_sertopic_register_locked (gv, gv->pgm_volatile_topic); +#endif ddsrt_mutex_unlock (&gv->sertopics_lock); /* register increments refcount (which is reasonable), but at some point diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 9f3f143..f85403c 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -1976,7 +1976,7 @@ static struct ddsi_serdata *remote_make_sample (struct ddsi_tkmap_instance **tk, GVTRACE ("data(application, vendor %u.%u): "PGUIDFMT" #%"PRId64": ST%x %s/%s:%s%s", sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], PGUID (guid), sampleinfo->seq, statusinfo, topic->name, topic->type_name, - tmp, res < sizeof (tmp) ? "" : "(trunc)"); + tmp, res < sizeof (tmp) - 1 ? "" : "(trunc)"); } } return sample; diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 7b1f451..2b27d54 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -966,8 +966,6 @@ static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct ddsi_pli { char ppbuf[1024]; int tmp; - const char *tname = wr->topic ? wr->topic->name : "(null)"; - const char *ttname = wr->topic ? wr->topic->type_name : "(null)"; ppbuf[0] = '\0'; tmp = sizeof (ppbuf) - 1; if (wr->e.gv->logconfig.c.mask & DDS_LC_CONTENT) @@ -975,7 +973,7 @@ static int insert_sample_in_whc (struct writer *wr, seqno_t seq, struct ddsi_pli ETRACE (wr, "write_sample "PGUIDFMT" #%"PRId64, PGUID (wr->e.guid), seq); if (plist != 0 && (plist->present & PP_COHERENT_SET)) ETRACE (wr, " C#%"PRId64"", fromSN (plist->coherent_set_seqno)); - ETRACE (wr, ": ST%"PRIu32" %s/%s:%s%s\n", serdata->statusinfo, tname, ttname, ppbuf, tmp < (int) sizeof (ppbuf) ? "" : " (trunc)"); + ETRACE (wr, ": ST%"PRIu32" %s/%s:%s%s\n", serdata->statusinfo, wr->topic->name, wr->topic->type_name, ppbuf, tmp < (int) sizeof (ppbuf) ? "" : " (trunc)"); } assert (wr->reliable || have_reliable_subs (wr) == 0); @@ -1235,13 +1233,11 @@ static int write_sample_eot (struct thread_state1 * const ts1, struct nn_xpack * { char ppbuf[1024]; int tmp; - const char *tname = wr->topic ? wr->topic->name : "(null)"; - const char *ttname = wr->topic ? wr->topic->type_name : "(null)"; ppbuf[0] = '\0'; tmp = sizeof (ppbuf) - 1; GVWARNING ("dropping oversize (%"PRIu32" > %"PRIu32") sample from local writer "PGUIDFMT" %s/%s:%s%s\n", ddsi_serdata_size (serdata), gv->config.max_sample_size, - PGUID (wr->e.guid), tname, ttname, ppbuf, + PGUID (wr->e.guid), wr->topic->name, wr->topic->type_name, ppbuf, tmp < (int) sizeof (ppbuf) ? "" : " (trunc)"); r = DDS_RETCODE_BAD_PARAMETER; goto drop; diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index ae6de3c..3c4ff83 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -1099,15 +1099,9 @@ static bool resend_spdp_sample_by_guid_key (struct writer *wr, const ddsi_guid_t ddsi_plist_init_empty (&ps); ps.present |= PP_PARTICIPANT_GUID; ps.participant_guid = *guid; - struct nn_xmsg *mpayload = nn_xmsg_new (gv->xmsgpool, guid, wr->c.pp, 0, NN_XMSG_KIND_DATA); - ddsi_plist_addtomsg (mpayload, &ps, ~(uint64_t)0, ~(uint64_t)0); - nn_xmsg_addpar_sentinel (mpayload); + struct ddsi_serdata *sd = ddsi_serdata_from_sample (gv->spdp_topic, SDK_KEY, &ps); ddsi_plist_fini (&ps); - struct ddsi_plist_sample plist_sample; - nn_xmsg_payload_to_plistsample (&plist_sample, PID_PARTICIPANT_GUID, mpayload); - struct ddsi_serdata *sd = ddsi_serdata_from_sample (gv->plist_topic, SDK_KEY, &plist_sample); struct whc_borrowed_sample sample; - nn_xmsg_free (mpayload); ddsrt_mutex_lock (&wr->e.lock); sample_found = whc_borrow_sample_key (wr->whc, sd, &sample); diff --git a/src/ddsrt/src/log.c b/src/ddsrt/src/log.c index f426b90..bf20966 100644 --- a/src/ddsrt/src/log.c +++ b/src/ddsrt/src/log.c @@ -215,10 +215,6 @@ static void vlog1 (const struct ddsrt_log_cfg_impl *cfg, uint32_t cat, uint32_t used with the global one. */ assert (domid == cfg->c.domid || cfg == &logconfig); - if (*fmt == 0) { - return; - } - lb = &log_buffer; /* Thread-local buffer is always initialized with all zeroes. The pos @@ -227,6 +223,20 @@ static void vlog1 (const struct ddsrt_log_cfg_impl *cfg, uint32_t cat, uint32_t lb->pos = BUF_OFFSET; lb->buf[lb->pos] = 0; } + + /* drop any prefix of new lines if there is current no data in the buffer: + there are some tricky problems in tracing some details depending on + enabled categories (like which subset of discovery related data gets + traced), and it sometimes helps to be able to trace just a newline + knowing it won't have any effect if nothing is buffered */ + if (lb->pos == BUF_OFFSET) { + while (*fmt == '\n') + fmt++; + } + if (*fmt == 0) { + return; + } + nrem = sizeof (lb->buf) - lb->pos; if (nrem > 0) { n = vsnprintf (lb->buf + lb->pos, nrem, fmt, ap); From 99df0956e798c4d219d52b47fbc682c5e4ba144b Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 31 Mar 2020 16:27:21 +0200 Subject: [PATCH 143/238] Crypto endpoint relation compare routines cleanup * Trying not to assume an int is at least 32 bits. * Technically speaking, comparing "unrelated" addresses is undefined behaviour which can be avoided by a cast to uintptr_t. * The early out if either local_crypto == 0 does work in context, provided the nodes in tree never have local_crypto == 0. That implies crypto_insert_endpoint_relation must never have a 0 in there, which I think the callers do respect. Still I think it is better to not hide these assumptions in the compare function and address the problem in the lookup function instead. These changes likely make the code fractionally slower, but I do think they improve clarity. Signed-off-by: Erik Boasson --- .../cryptographic/src/crypto_objects.c | 42 +++++++------------ .../core/tests/secure_communication.c | 2 +- 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_objects.c b/src/security/builtin_plugins/cryptographic/src/crypto_objects.c index 075744e..17929af 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_objects.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_objects.c @@ -52,17 +52,13 @@ static int compare_endpoint_relation (const void *va, const void *vb) { const key_relation *ra = va; const key_relation *rb = vb; - int r; - - r = (int)(ra->key_id - rb->key_id); - if (r != 0 || ra->local_crypto == 0 || rb->local_crypto == 0) - { - return r; - } - - if (ra->local_crypto > rb->local_crypto) + if (ra->key_id > rb->key_id) return 1; - else if (ra->local_crypto < rb->local_crypto) + else if (ra->key_id < rb->key_id) + return -1; + else if ((uintptr_t) ra->local_crypto > (uintptr_t) rb->local_crypto) + return 1; + else if ((uintptr_t) ra->local_crypto < (uintptr_t) rb->local_crypto) return -1; else return 0; @@ -72,8 +68,7 @@ static int compare_relation_key (const void *va, const void *vb) { const uint32_t *ka = va; const uint32_t *kb = vb; - - return (int)(*ka - *kb); + return (*ka == *kb) ? 0 : (*ka < *kb) ? -1 : 1; } bool crypto_object_valid(CryptoObject *obj, CryptoObjectKind_t kind) @@ -692,6 +687,7 @@ void crypto_insert_endpoint_relation( remote_participant_crypto *rpc, key_relation *relation) { + assert (relation->local_crypto != NULL && relation->remote_crypto != NULL); ddsrt_mutex_lock(&rpc->lock); ddsrt_avl_insert(&endpoint_relation_treedef, &rpc->relation_index, CRYPTO_OBJECT_KEEP(relation)); ddsrt_mutex_unlock(&rpc->lock); @@ -702,15 +698,11 @@ void crypto_remove_endpoint_relation( CryptoObject *lch, uint32_t key_id) { - key_relation template; + const key_relation template = { .key_id = key_id, .local_crypto = lch }; key_relation *relation; ddsrt_avl_dpath_t dpath; - - template.key_id = key_id; - template.local_crypto = lch; - ddsrt_mutex_lock(&rpc->lock); - relation = ddsrt_avl_lookup_dpath(&endpoint_relation_treedef, &rpc->relation_index, &template, &dpath); + relation = ddsrt_avl_lookup_dpath(&endpoint_relation_treedef, &rpc->relation_index, &template, &dpath); if (relation) { ddsrt_avl_delete_dpath(&endpoint_relation_treedef, &rpc->relation_index, relation, &dpath); @@ -724,16 +716,14 @@ key_relation * crypto_find_endpoint_relation( CryptoObject *lch, uint32_t key_id) { - key_relation template; - key_relation *relation; - - template.key_id = key_id; - template.local_crypto = lch; - + const key_relation template = { .key_id = key_id, .local_crypto = lch }; + key_relation *relation, *cand; ddsrt_mutex_lock(&rpc->lock); - relation = CRYPTO_OBJECT_KEEP(ddsrt_avl_lookup(&endpoint_relation_treedef, &rpc->relation_index, &template)); + if ((cand = ddsrt_avl_lookup_succ_eq (&endpoint_relation_treedef, &rpc->relation_index, &template)) == NULL || cand->key_id != key_id) + relation = NULL; + else + relation = CRYPTO_OBJECT_KEEP (cand); ddsrt_mutex_unlock(&rpc->lock); - return relation; } diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index 5b46630..10769e0 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -544,7 +544,7 @@ CU_TheoryDataPoints(ddssec_secure_communication, multiple_readers) = { CU_DataPoints(size_t, 1, 3, 1, 3), /* number of participants per domain */ CU_DataPoints(size_t, 3, 1, 3, 3), /* number of readers per participant */ }; -CU_Theory((size_t n_dom, size_t n_pp, size_t n_rd), ddssec_secure_communication, multiple_readers, .timeout = 60, .disabled = false) +CU_Theory((size_t n_dom, size_t n_pp, size_t n_rd), ddssec_secure_communication, multiple_readers, .timeout = 90, .disabled = false) { DDS_Security_ProtectionKind metadata_pk[] = { PK_N, PK_SOA, PK_EOA }; DDS_Security_BasicProtectionKind payload_pk[] = { BPK_N, BPK_S, BPK_E }; From f792b3ceed6f2cc932ac76435d7fc6f434b4f2ef Mon Sep 17 00:00:00 2001 From: Marcel Jordense Date: Mon, 6 Apr 2020 17:01:38 +0200 Subject: [PATCH 144/238] Store security info of the proxy endpoints in the common part Signed-off-by: Marcel Jordense --- .../ddsi/include/dds/ddsi/ddsi_security_omg.h | 54 ++++----------- src/core/ddsi/include/dds/ddsi/q_entity.h | 6 -- src/core/ddsi/src/ddsi_security_omg.c | 65 ++++++------------- src/core/ddsi/src/q_entity.c | 16 +---- 4 files changed, 33 insertions(+), 108 deletions(-) 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 32946ba..6d5efcb 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h @@ -624,27 +624,6 @@ int64_t q_omg_security_get_remote_participant_handle(struct proxy_participant *p */ void q_omg_security_set_participant_crypto_tokens(struct participant *pp, struct proxy_participant *proxypp, const nn_dataholderseq_t *tokens); -/** - * @brief Set security information, depending on plist and proxy participant, - * into the given proxy writer. - * - * @param[in] pwr Proxy writer to set security info on. - * @param[in] plist Paramater list, possibly contains security info. - */ -void set_proxy_writer_security_info(struct proxy_writer *pwr, const ddsi_plist_t *plist); - -/** - * @brief Determine the security settings associated with the remote writer. - * - * From the security information contained in the parameter list from the remote writer - * the corresponding security settings are determined and returned in the info parameter. - * - * @param[in] pwr The remote writer. - * @param[in] plist The parameter list from the remote writer. - * @param[out] info The security settings associated with the remote writer. - */ -void q_omg_get_proxy_writer_security_info(struct proxy_writer *pwr, const ddsi_plist_t *plist, nn_security_info_t *info); - /** * @brief Check if the writer has the is_discovery_protected flag set * @@ -739,27 +718,6 @@ 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 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 * @@ -797,6 +755,18 @@ bool q_omg_reader_is_submessage_protected(const struct reader *rd); */ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *prd, uint32_t domain_id, struct participant *pp, bool *relay_only); + +/** + * @brief Set security information, depending on plist and proxy participant, + * into the given proxy endpoint. + * + * @param[in] entity The endpoint common attributes. + * @param[in] proxypp_sec_info The security info of the proxy participant + * @param[in] plist Paramater list which may contain security info. + * @param[in] info The proxy endpoint security info to be set. + */ +void q_omg_get_proxy_endpoint_security_info(const struct entity_common *entity, nn_security_info_t *proxypp_sec_info, const ddsi_plist_t *plist, nn_security_info_t *info); + /** * @brief Check it the local writer is allowed to communicate with the remote reader. * diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 86e8826..a6f6543 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -455,9 +455,6 @@ struct proxy_writer { ddsi2direct_directread_cb_t ddsi2direct_cb; void *ddsi2direct_cbarg; struct lease *lease; -#ifdef DDSI_INCLUDE_SECURITY - nn_security_info_t security_info; -#endif }; @@ -473,9 +470,6 @@ struct proxy_reader { #endif ddsrt_avl_tree_t writers; /* matching LOCAL writers */ filter_fn_t filter; -#ifdef DDSI_INCLUDE_SECURITY - nn_security_info_t security_info; -#endif }; DDS_EXPORT extern const ddsrt_avl_treedef_t wr_readers_treedef; diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index c046a72..0fc64d1 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -1926,7 +1926,7 @@ bool q_omg_security_check_remote_writer_permissions(const struct proxy_writer *p } } - if (SECURITY_INFO_IS_WRITE_PROTECTED(pwr->security_info)) + if (SECURITY_INFO_IS_WRITE_PROTECTED(pwr->c.security_info)) { DDS_Security_PermissionsHandle permissions_handle; @@ -1937,7 +1937,7 @@ bool q_omg_security_check_remote_writer_permissions(const struct proxy_writer *p } else { - q_omg_shallow_copy_PublicationBuiltinTopicDataSecure(&publication_data, &pwr->e.guid, pwr->c.xqos, &pwr->security_info); + q_omg_shallow_copy_PublicationBuiltinTopicDataSecure(&publication_data, &pwr->e.guid, pwr->c.xqos, &pwr->c.security_info); ok = sc->access_control_context->check_remote_datawriter(sc->access_control_context, permissions_handle, (int)domain_id, &publication_data, &exception); q_omg_shallow_free_PublicationBuiltinTopicDataSecure(&publication_data); if (!ok) @@ -2067,11 +2067,11 @@ bool q_omg_security_match_remote_writer_enabled(struct reader *rd, struct proxy_ * q_omg_participant_allow_unauthenticated() returns FALSE there. */ (void)q_omg_get_reader_security_info(rd, &info); - if (!SECURITY_INFO_COMPATIBLE(pwr->security_info, info, NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID)) + if (!SECURITY_INFO_COMPATIBLE(pwr->c.security_info, info, NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID)) { GVWARNING("match_remote_writer "PGUIDFMT" with reader "PGUIDFMT" security_attributes mismatch: 0x%08x.0x%08x - 0x%08x.0x%08x\n", PGUID(pwr->e.guid), PGUID(rd->e.guid), - pwr->security_info.security_attributes, pwr->security_info.plugin_security_attributes, + pwr->c.security_info.security_attributes, pwr->c.security_info.plugin_security_attributes, info.security_attributes, info.plugin_security_attributes); return false; } @@ -2092,11 +2092,11 @@ bool q_omg_security_match_remote_writer_enabled(struct reader *rd, struct proxy_ * the valid flag is 0. To be able to support these product, assume * that the attributes are the same. If there is actually a mismatch, * communication will fail at a later moment anyway. */ - if (!SECURITY_ATTR_IS_VALID(pwr->security_info.security_attributes)) { - pwr->security_info.security_attributes = info.security_attributes; + if (!SECURITY_ATTR_IS_VALID(pwr->c.security_info.security_attributes)) { + pwr->c.security_info.security_attributes = info.security_attributes; } - if (!SECURITY_ATTR_IS_VALID(pwr->security_info.plugin_security_attributes)) { - pwr->security_info.plugin_security_attributes = info.plugin_security_attributes; + if (!SECURITY_ATTR_IS_VALID(pwr->c.security_info.plugin_security_attributes)) { + pwr->c.security_info.plugin_security_attributes = info.plugin_security_attributes; } return q_omg_security_register_remote_writer_match(pwr, rd, crypto_handle); @@ -2148,7 +2148,7 @@ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *p } } - if (SECURITY_INFO_IS_READ_PROTECTED(prd->security_info)) + if (SECURITY_INFO_IS_READ_PROTECTED(prd->c.security_info)) { DDS_Security_PermissionsHandle permissions_handle; @@ -2162,7 +2162,7 @@ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *p DDS_Security_SubscriptionBuiltinTopicDataSecure subscription_data; DDS_Security_boolean sec_relay_only; - q_omg_shallow_copy_SubscriptionBuiltinTopicDataSecure(&subscription_data, &prd->e.guid, prd->c.xqos, &prd->security_info); + q_omg_shallow_copy_SubscriptionBuiltinTopicDataSecure(&subscription_data, &prd->e.guid, prd->c.xqos, &prd->c.security_info); ok = sc->access_control_context->check_remote_datareader(sc->access_control_context, permissions_handle, (int)domain_id, &subscription_data, &sec_relay_only, &exception); q_omg_shallow_free_SubscriptionBuiltinTopicDataSecure(&subscription_data); if (ok) @@ -2180,11 +2180,14 @@ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *p return ok; } -static void q_omg_get_proxy_endpoint_security_info(const struct entity_common *entity, nn_security_info_t *proxypp_sec_info, const ddsi_plist_t *plist, nn_security_info_t *info) +void q_omg_get_proxy_endpoint_security_info(const struct entity_common *entity, nn_security_info_t *proxypp_sec_info, const ddsi_plist_t *plist, nn_security_info_t *info) { const bool proxypp_info_available = (proxypp_sec_info->security_attributes != 0 || proxypp_sec_info->plugin_security_attributes != 0); + info->security_attributes = 0; + info->plugin_security_attributes = 0; + /* * If Security info is present, use that. * Otherwise, use the specified values for the secure builtin endpoints. @@ -2251,34 +2254,6 @@ static void q_omg_get_proxy_endpoint_security_info(const struct entity_common *e NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID | NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_PROTECTED; info->plugin_security_attributes = 0; } - else - { - info->security_attributes = 0; - info->plugin_security_attributes = 0; - } -} - -void q_omg_get_proxy_reader_security_info(struct proxy_reader *prd, const ddsi_plist_t *plist, nn_security_info_t *info) -{ - q_omg_get_proxy_endpoint_security_info(&(prd->e), &(prd->c.proxypp->security_info), plist, info); -} - -void set_proxy_reader_security_info(struct proxy_reader *prd, const ddsi_plist_t *plist) -{ - assert (prd); - q_omg_get_proxy_endpoint_security_info (&prd->e, &prd->c.proxypp->security_info, plist, &prd->c.security_info); -} - - -void q_omg_get_proxy_writer_security_info(struct proxy_writer *pwr, const ddsi_plist_t *plist, nn_security_info_t *info) -{ - q_omg_get_proxy_endpoint_security_info(&(pwr->e), &(pwr->c.proxypp->security_info), plist, info); -} - -void set_proxy_writer_security_info(struct proxy_writer *pwr, const ddsi_plist_t *plist) -{ - assert (pwr); - q_omg_get_proxy_endpoint_security_info (&pwr->e, &pwr->c.proxypp->security_info, plist, &pwr->c.security_info); } void q_omg_security_deregister_remote_reader_match(const struct ddsi_domaingv *gv, const ddsi_guid_t *wr_guid, struct wr_prd_match *m) @@ -2417,11 +2392,11 @@ bool q_omg_security_match_remote_reader_enabled(struct writer *wr, struct proxy_ * q_omg_participant_allow_unauthenticated() returns FALSE there. */ (void)q_omg_get_writer_security_info(wr, &info); - if (!SECURITY_INFO_COMPATIBLE(prd->security_info, info, NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID)) + if (!SECURITY_INFO_COMPATIBLE(prd->c.security_info, info, NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID)) { GVWARNING("match_remote_reader "PGUIDFMT" with writer "PGUIDFMT" security_attributes mismatch: 0x%08x.0x%08x - 0x%08x.0x%08x\n", PGUID(prd->e.guid), PGUID(wr->e.guid), - prd->security_info.security_attributes, prd->security_info.plugin_security_attributes, + prd->c.security_info.security_attributes, prd->c.security_info.plugin_security_attributes, info.security_attributes, info.plugin_security_attributes); return false; } @@ -2442,11 +2417,11 @@ bool q_omg_security_match_remote_reader_enabled(struct writer *wr, struct proxy_ * the valid flag is 0. To be able to support these product, assume * that the attributes are the same. If there is actually a mismatch, * communication will fail at a later moment anyway. */ - if (!SECURITY_ATTR_IS_VALID(prd->security_info.security_attributes)) { - prd->security_info.security_attributes = info.security_attributes; + if (!SECURITY_ATTR_IS_VALID(prd->c.security_info.security_attributes)) { + prd->c.security_info.security_attributes = info.security_attributes; } - if (!SECURITY_ATTR_IS_VALID(prd->security_info.plugin_security_attributes)) { - prd->security_info.plugin_security_attributes = info.plugin_security_attributes; + if (!SECURITY_ATTR_IS_VALID(prd->c.security_info.plugin_security_attributes)) { + prd->c.security_info.plugin_security_attributes = info.plugin_security_attributes; } return q_omg_security_register_remote_reader_match(prd, wr, crypto_handle, relay_only); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 7c1ff62..569fb01 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -4475,9 +4475,6 @@ dds_return_t delete_reader (struct ddsi_domaingv *gv, const struct ddsi_guid *gu GVLOGDISC ("delete_reader_guid(guid "PGUIDFMT") ...\n", PGUID (*guid)); builtintopic_write (rd->e.gv->builtin_topic_interface, &rd->e, ddsrt_time_wallclock(), false); entidx_remove_reader_guid (gv->entity_index, rd); -#ifdef DDSI_INCLUDE_SECURITY - q_omg_security_deregister_reader(rd); -#endif gcreq_reader (rd); return 0; } @@ -5369,8 +5366,7 @@ static int proxy_endpoint_common_init (struct entity_common *e, struct proxy_end memset (&c->group_guid, 0, sizeof (c->group_guid)); #ifdef DDSI_INCLUDE_SECURITY - c->security_info.security_attributes = 0; - c->security_info.plugin_security_attributes = 0; + q_omg_get_proxy_endpoint_security_info(e, &proxypp->security_info, plist, &c->security_info); #endif if ((ret = ref_proxy_participant (proxypp, c)) != DDS_RETCODE_OK) @@ -5516,11 +5512,6 @@ int new_proxy_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, pwr->ddsi2direct_cb = 0; pwr->ddsi2direct_cbarg = 0; -#ifdef DDSI_INCLUDE_SECURITY - set_proxy_writer_security_info(pwr, plist); - q_omg_get_proxy_writer_security_info(pwr, plist, &(pwr->security_info)); -#endif - local_reader_ary_init (&pwr->rdary); /* locking the entity prevents matching while the built-in topic hasn't been published yet */ @@ -5798,14 +5789,9 @@ int new_proxy_reader (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, #endif prd->is_fict_trans_reader = 0; -#ifdef DDSI_INCLUDE_SECURITY - set_proxy_reader_security_info(prd, plist); -#endif - ddsrt_avl_init (&prd_writers_treedef, &prd->writers); #ifdef DDSI_INCLUDE_SECURITY - q_omg_get_proxy_reader_security_info(prd, plist, &(prd->security_info)); if (prd->e.guid.entityid.u == NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER) prd->filter = volatile_secure_data_filter; else From b6640d86b024ebb3f9258ab3c205104c40676eda Mon Sep 17 00:00:00 2001 From: Marcel Jordense Date: Mon, 6 Apr 2020 17:33:52 +0200 Subject: [PATCH 145/238] Correct length of encrypted submessage body Signed-off-by: Marcel Jordense --- .../cryptographic/src/crypto_transform.c | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_transform.c b/src/security/builtin_plugins/cryptographic/src/crypto_transform.c index 7fd39d6..21c3e1c 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_transform.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_transform.c @@ -1103,7 +1103,7 @@ encode_datawriter_submessage_encrypt ( */ size = 2 * sizeof(struct submsg_header) + sizeof(struct crypto_header) + sizeof(struct crypto_footer) + ALIGN4(plain_submsg->_length); - size += reader_crypto_list->_length * CRYPTO_HMAC_SIZE; + size += reader_crypto_list->_length * sizeof(struct receiver_specific_mac); /* assure that the buffer contains enough memory to accommodate the encrypted payload */ if (is_encryption_required(session->master_key_material->transformation_kind)) size += sizeof(struct submsg_header) + sizeof(uint32_t) + CRYPTO_ENCRYPTION_MAX_PADDING; @@ -1150,9 +1150,9 @@ encode_datawriter_submessage_encrypt ( /* adjust the length of the body submessage when needed */ encrypted->length = ddsrt_toBE4u(payload_len); - if (payload_len + sizeof(encrypted->length) > plain_submsg->_length) + if (payload_len > plain_submsg->_length) { - size_t inc = payload_len + sizeof(encrypted->length) - plain_submsg->_length; + size_t inc = payload_len - plain_submsg->_length; body->length = (uint16_t)(body->length + inc); data._length += (uint32_t)inc; } @@ -1182,7 +1182,9 @@ encode_datawriter_submessage_encrypt ( footer->receiver_specific_macs._length = 0; *encoded_submsg = data; - if (has_origin_authentication(protection_kind)) + if (!has_origin_authentication(protection_kind)) + *index = (int32_t) reader_crypto_list->_length; + else { if (reader_crypto_list->_length != 0) { @@ -1191,10 +1193,7 @@ encode_datawriter_submessage_encrypt ( (*index)++; } } - else - { - *index = (int32_t) reader_crypto_list->_length; - } + result = true; enc_dw_submsg_fail: @@ -1357,7 +1356,7 @@ encode_datareader_submessage( */ size = 2 * sizeof(struct submsg_header) + sizeof(struct crypto_header) + sizeof(struct crypto_footer) + ALIGN4(plain_submsg->_length); - size += writer_crypto_list->_length * CRYPTO_HMAC_SIZE; + size += writer_crypto_list->_length * sizeof(struct receiver_specific_mac); /* assure that the buffer contains enough memory to accommodate the encrypted payload */ if (is_encryption_required(session->master_key_material->transformation_kind)) size += sizeof(struct submsg_header) + sizeof(uint32_t) + CRYPTO_ENCRYPTION_MAX_PADDING; @@ -1405,9 +1404,9 @@ encode_datareader_submessage( /* adjust the length of the body submessage when needed */ encrypted->length = ddsrt_toBE4u(payload_len); - if (payload_len + sizeof(encrypted->length) > plain_submsg->_length) + if (payload_len > plain_submsg->_length) { - size_t inc = payload_len + sizeof(encrypted->length) - plain_submsg->_length; + size_t inc = payload_len - plain_submsg->_length; body->length = (uint16_t)(body->length + inc); data._length += (uint32_t)inc; } @@ -1641,7 +1640,7 @@ static DDS_Security_boolean encode_rtps_message_encrypt ( size = RTPS_HEADER_SIZE; /* RTPS Header */ size += 2 * sizeof(struct submsg_header) + sizeof(struct crypto_header) + sizeof(struct crypto_footer) + ALIGN4(plain_rtps_message->_length); - size += receiving_participant_crypto_list->_length * CRYPTO_HMAC_SIZE; + size += receiving_participant_crypto_list->_length * sizeof(struct receiver_specific_mac); size += sizeof(struct submsg_header) + RTPS_HEADER_SIZE; /* INFO_SRC */ if (is_encryption_required(session->master_key_material->transformation_kind)) From cb1d06b442f9cb718a5f1944ec0ca34f0d3cad4f Mon Sep 17 00:00:00 2001 From: Marcel Jordense Date: Tue, 7 Apr 2020 11:01:53 +0200 Subject: [PATCH 146/238] Freeing the writer security attributes should be done by the gc Signed-off-by: Marcel Jordense --- src/core/ddsi/src/q_entity.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 569fb01..826124f 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -4052,9 +4052,7 @@ dds_return_t delete_writer_nolinger (struct ddsi_domaingv *gv, const struct ddsi return DDS_RETCODE_BAD_PARAMETER; } GVLOGDISC ("delete_writer_nolinger(guid "PGUIDFMT") ...\n", PGUID (*guid)); -#ifdef DDSI_INCLUDE_SECURITY - q_omg_security_deregister_writer(wr); -#endif + ddsrt_mutex_lock (&wr->e.lock); delete_writer_nolinger_locked (wr); ddsrt_mutex_unlock (&wr->e.lock); From 9c09eca2e951bc5e95e154d28e64f7c23dcf3a7e Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 1 Apr 2020 13:02:03 +0200 Subject: [PATCH 147/238] Do not assume string in algo binary property Interpretation of the c.dsign_algo and c.kagree_algo properties must not assume the binary property to be a null-terminated string. Signed-off-by: Erik Boasson --- .../authentication/src/authentication.c | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index 7e15f05..14eb2c3 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -523,27 +523,31 @@ static const char *get_kagree_algo(AuthenticationAlgoKind_t kind) } } -static AuthenticationAlgoKind_t get_dsign_algo_from_string(const char *name) +static bool str_octseq_equal (const char *str, const DDS_Security_OctetSeq *binstr) { - if (name) - { - if (strcmp(AUTH_DSIG_ALGO_RSA_2048_SHA256_IDENT, name) == 0) + size_t i; + for (i = 0; str[i] && i < binstr->_length; i++) + if ((unsigned char) str[i] != binstr->_buffer[i]) + return false; + /* allow zero-termination in binstr */ + return (str[i] == 0 && (i == binstr->_length || binstr->_buffer[i] == 0)); +} + +static AuthenticationAlgoKind_t get_dsign_algo_from_octseq(const DDS_Security_OctetSeq *name) +{ + if (str_octseq_equal(AUTH_DSIG_ALGO_RSA_2048_SHA256_IDENT, name)) return AUTH_ALGO_KIND_RSA_2048; - if (strcmp(AUTH_DSIG_ALGO_ECDSA_SHA256_IDENT, name) == 0) - return AUTH_ALGO_KIND_EC_PRIME256V1; - } + if (str_octseq_equal(AUTH_DSIG_ALGO_ECDSA_SHA256_IDENT, name)) + return AUTH_ALGO_KIND_EC_PRIME256V1; return AUTH_ALGO_KIND_UNKNOWN; } -static AuthenticationAlgoKind_t get_kagree_algo_from_string(const char *name) +static AuthenticationAlgoKind_t get_kagree_algo_from_octseq(const DDS_Security_OctetSeq *name) { - if (name) - { - if (strcmp(AUTH_KAGREE_ALGO_RSA_2048_SHA256_IDENT, name) == 0) - return AUTH_ALGO_KIND_RSA_2048; - if (strcmp(AUTH_KAGREE_ALGO_ECDH_PRIME256V1_IDENT, name) == 0) - return AUTH_ALGO_KIND_EC_PRIME256V1; - } + if (str_octseq_equal(AUTH_KAGREE_ALGO_RSA_2048_SHA256_IDENT, name)) + return AUTH_ALGO_KIND_RSA_2048; + if (str_octseq_equal(AUTH_KAGREE_ALGO_ECDH_PRIME256V1_IDENT, name)) + return AUTH_ALGO_KIND_EC_PRIME256V1; return AUTH_ALGO_KIND_UNKNOWN; } @@ -1418,12 +1422,12 @@ static DDS_Security_ValidationResult_t validate_handshake_token_impl (const DDS_ if ((c_dsign_algo = find_required_nonempty_binprop (token, "c.dsign_algo", ex)) == NULL) return DDS_SECURITY_VALIDATION_FAILED; - if ((dsignAlgoKind = get_dsign_algo_from_string ((const char *) c_dsign_algo->value._buffer)) == AUTH_ALGO_KIND_UNKNOWN) + if ((dsignAlgoKind = get_dsign_algo_from_octseq (&c_dsign_algo->value)) == AUTH_ALGO_KIND_UNKNOWN) return set_exception (ex, "process_handshake: HandshakeMessageToken property c.dsign_algo not supported"); if ((c_kagree_algo = find_required_nonempty_binprop (token, "c.kagree_algo", ex)) == NULL) return DDS_SECURITY_VALIDATION_FAILED; - if ((kagreeAlgoKind = get_kagree_algo_from_string ((const char *) c_kagree_algo->value._buffer)) == AUTH_ALGO_KIND_UNKNOWN) + if ((kagreeAlgoKind = get_kagree_algo_from_octseq (&c_kagree_algo->value)) == AUTH_ALGO_KIND_UNKNOWN) return set_exception (ex, "process_handshake: HandshakeMessageToken property c.kagree_algo not supported"); /* calculate the hash value and set in handshake hash_c1 (req) or hash_c2 (reply) */ From eb7e5e3a8781c966e91262cfbd84de2dc2b475d4 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 7 Apr 2020 10:27:39 +0200 Subject: [PATCH 148/238] Disallow junk after optional terminator in string/binprop compare Signed-off-by: Erik Boasson --- .../builtin_plugins/authentication/src/authentication.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index 14eb2c3..127357a 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -529,8 +529,10 @@ static bool str_octseq_equal (const char *str, const DDS_Security_OctetSeq *bins for (i = 0; str[i] && i < binstr->_length; i++) if ((unsigned char) str[i] != binstr->_buffer[i]) return false; - /* allow zero-termination in binstr */ - return (str[i] == 0 && (i == binstr->_length || binstr->_buffer[i] == 0)); + /* allow zero-termination in binstr, but disallow anything other than a single \0 */ + return (str[i] == 0 && + (i == binstr->_length || + (i+1 == binstr->_length && binstr->_buffer[i] == 0))); } static AuthenticationAlgoKind_t get_dsign_algo_from_octseq(const DDS_Security_OctetSeq *name) From 52edbe94e98e8d2c1ef98610ef30f3bcb2f8d774 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 8 Apr 2020 11:35:49 +0200 Subject: [PATCH 149/238] plist handling of invalid input and keyhashes This fixes some issues with the new discovery data ("plist" topics) discovered on interoperating with some other DDS implementations: * The interpretation of a keyhash as if it were a valid sample was wrong in various ways: inconsistent endianness, incorrect encoding identifier and a missing sentinel. As Cyclone follows the spec and always provides a well-formed payload, the problem only surfaces when interoperating with implementations that expect the recipient to make do with a keyhash. * Various paths failed to check for failure causing potential null pointer dereferences. Signed-off-by: Erik Boasson --- src/core/ddsi/src/ddsi_serdata_plist.c | 16 ++++++++++++---- src/core/ddsi/src/q_ddsi_discovery.c | 7 +++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/core/ddsi/src/ddsi_serdata_plist.c b/src/core/ddsi/src/ddsi_serdata_plist.c index 225f9e9..528fa81 100644 --- a/src/core/ddsi/src/ddsi_serdata_plist.c +++ b/src/core/ddsi/src/ddsi_serdata_plist.c @@ -102,6 +102,8 @@ static struct ddsi_serdata *serdata_plist_from_ser (const struct ddsi_sertopic * { const struct ddsi_sertopic_plist *tp = (const struct ddsi_sertopic_plist *) tpcmn; struct ddsi_serdata_plist *d = serdata_plist_new (tp, kind, size, NN_RMSG_PAYLOADOFF (fragchain->rmsg, NN_RDATA_PAYLOAD_OFF (fragchain))); + if (d == NULL) + return NULL; uint32_t off = 4; /* must skip the CDR header */ assert (fragchain->min == 0); assert (fragchain->maxp1 >= off); /* CDR header must be in first fragment */ @@ -128,6 +130,8 @@ static struct ddsi_serdata *serdata_plist_from_ser_iov (const struct ddsi_sertop const struct ddsi_sertopic_plist *tp = (const struct ddsi_sertopic_plist *) tpcmn; assert (niov >= 1); struct ddsi_serdata_plist *d = serdata_plist_new (tp, kind, size, iov[0].iov_base); + if (d == NULL) + return NULL; memcpy (d->data + d->pos, (const char *) iov[0].iov_base + 4, iov[0].iov_len - 4); d->pos += (uint32_t) iov[0].iov_len - 4; for (ddsrt_msg_iovlen_t i = 1; i < niov; i++) @@ -141,14 +145,18 @@ static struct ddsi_serdata *serdata_plist_from_ser_iov (const struct ddsi_sertop static struct ddsi_serdata *serdata_plist_from_keyhash (const struct ddsi_sertopic *tpcmn, const ddsi_keyhash_t *keyhash) { const struct ddsi_sertopic_plist *tp = (const struct ddsi_sertopic_plist *) tpcmn; - const struct { uint16_t identifier, options; nn_parameter_t par; ddsi_keyhash_t kh; } in = { - .identifier = CDR_BE, + const struct { uint16_t identifier, options; nn_parameter_t par; ddsi_keyhash_t kh; nn_parameter_t sentinel; } in = { + .identifier = PL_CDR_BE, .options = 0, .par = { .parameterid = ddsrt_toBE2u (tp->keyparam), - .length = sizeof (*keyhash) + .length = ddsrt_toBE2u ((uint16_t) sizeof (*keyhash)) }, - *keyhash + .kh = *keyhash, + .sentinel = { + .parameterid = ddsrt_toBE2u (PID_SENTINEL), + .length = 0 + } }; const ddsrt_iovec_t iov = { .iov_base = (void *) &in, .iov_len = sizeof (in) }; return serdata_plist_from_ser_iov (tpcmn, SDK_KEY, 1, &iov, sizeof (in) - 4); diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 865a8dc..f8ee6eb 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -1534,6 +1534,13 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str PGUID (srcguid), sampleinfo->seq); goto done_upd_deliv; } + if (d == NULL) + { + GVLOG (DDS_LC_DISCOVERY | DDS_LC_WARNING, "data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": deserialization failed\n", + sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1], + PGUID (srcguid), sampleinfo->seq); + goto done_upd_deliv; + } d->timestamp = (sampleinfo->timestamp.v != DDSRT_WCTIME_INVALID.v) ? sampleinfo->timestamp : ddsrt_time_wallclock (); d->statusinfo = statusinfo; From e88552123c4c3c4164fb909b798b3d6147d2de9d Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 8 Apr 2020 11:42:53 +0200 Subject: [PATCH 150/238] Peers may have a secure announcer without using security There exist implementations that advertise security-related built-endpoints regardless of whether the participant has security configured. Therefore, the test whether security is enabled for the participant cannot simply be the presence of such an endpoint, because the absence of an IDENTITY_TOKEN in the data is then considered an error. This commit simply changes the check to requiring the presence of the endpoint and the presence of the IDENTITY_TOKEN. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_ddsi_discovery.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index f8ee6eb..98db5b0 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -638,16 +638,12 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, dds } } - const bool is_secure = (datap->builtin_endpoint_set & NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_ANNOUNCER) != 0; + const bool is_secure = ((datap->builtin_endpoint_set & NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_ANNOUNCER) != 0 && + (datap->present & PP_IDENTITY_TOKEN)); /* Make sure we don't create any security builtin endpoint when it's considered unsecure. */ if (!is_secure) builtin_endpoint_set &= NN_BES_MASK_NON_SECURITY; GVLOGDISC ("SPDP ST0 "PGUIDFMT" bes %x%s NEW", PGUID (datap->participant_guid), builtin_endpoint_set, is_secure ? " (secure)" : ""); - if (is_secure && !(datap->present & PP_IDENTITY_TOKEN)) - { - GVLOGDISC (" identity token missing\n"); - return 0; - } if (datap->present & PP_PARTICIPANT_LEASE_DURATION) { From 1fd4ab290fcd11ad78f63e9070dd9cfcc8ec6ff3 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 8 Apr 2020 22:12:34 +0200 Subject: [PATCH 151/238] Do not build security tests if BUILD_IDLC=NO Signed-off-by: Erik Boasson --- src/security/core/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/security/core/CMakeLists.txt b/src/security/core/CMakeLists.txt index 19f4823..7765227 100644 --- a/src/security/core/CMakeLists.txt +++ b/src/security/core/CMakeLists.txt @@ -45,7 +45,7 @@ target_include_directories(security_core "$>" ) -if(BUILD_TESTING) +if(BUILD_TESTING AND BUILD_IDLC) add_subdirectory(tests) endif() From b2b9630c38b556530001168ce8177e85b56876c3 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Sun, 5 Apr 2020 20:54:24 +0200 Subject: [PATCH 152/238] Prevent time-out in handshake The security handshake is started when a node receives an SPDP message. The SPDP receiver will reply with an SPDP, followed by a dds.sec.auth_request. Because the initial SPDP sender will receive the auth_request immediately after (or even before) the SPDP reply message, that node may not have finished (or not even started) matching the remote writers and therefore it drops the auth_request message. This results in a time-out in the handshake process, and the auth_request has to be re-send. To avoid this, a short (rather arbitrarily chosen, based on local testing) sleep is introduced before the auth_request message is sent. Signed-off-by: Dennis Potman --- src/core/ddsi/src/ddsi_handshake.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/core/ddsi/src/ddsi_handshake.c b/src/core/ddsi/src/ddsi_handshake.c index b23d214..61f8477 100644 --- a/src/core/ddsi/src/ddsi_handshake.c +++ b/src/core/ddsi/src/ddsi_handshake.c @@ -553,7 +553,15 @@ static void func_validate_remote_identity(struct dds_security_fsm *fsm, void *ar * to be send. */ if (handshake->local_auth_request_token.class_id && strlen(handshake->local_auth_request_token.class_id) != 0) + { + /* A short sleep to give the remote node some time for matching the + BuiltinParticipantStatelessMessageWriter, so that it won't drop the + sample we're sending (that would result in a time-out and the + handshake taking 1s longer than required) */ + dds_sleepfor (DDS_MSECS(10)); + HSTRACE("FSM: validate_remote_identity: send_handshake_message AUTH_REQUEST\n"); (void)send_handshake_message(handshake, &handshake->local_auth_request_token, pp, proxypp, 1); + } validation_failed: ident_token_missing: From 3a838f6912bb8be74b08a5ccfb5966ad465789dd Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Mon, 6 Apr 2020 14:46:27 +0200 Subject: [PATCH 153/238] Replace sleep in func_validate_remote_identity by an FSM wait-state before state_validate_remote_identity Signed-off-by: Dennis Potman --- src/core/ddsi/src/ddsi_handshake.c | 31 ++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/core/ddsi/src/ddsi_handshake.c b/src/core/ddsi/src/ddsi_handshake.c index 61f8477..9f105fd 100644 --- a/src/core/ddsi/src/ddsi_handshake.c +++ b/src/core/ddsi/src/ddsi_handshake.c @@ -141,6 +141,7 @@ static bool validate_handshake(struct ddsi_handshake *handshake, struct particip #define RESEND_TIMEOUT DDS_SECS(1) #define SEND_TOKENS_TIMEOUT DDS_MSECS(100) #define AUTHENTICATION_TIMEOUT DDS_SECS(100) +#define INITIAL_DELAY DDS_MSECS(10) static void func_validate_remote_identity (struct dds_security_fsm *fsm, void *arg); static void func_handshake_init_message_resend(struct dds_security_fsm *fsm, void *arg); @@ -153,6 +154,7 @@ static void func_validation_failed (struct dds_security_fsm *fsm, voi static void func_send_crypto_tokens_final (struct dds_security_fsm *fsm, void *arg); static void func_send_crypto_tokens (struct dds_security_fsm *fsm, void *arg); +static dds_security_fsm_state state_initial_delay = { NULL, INITIAL_DELAY }; static dds_security_fsm_state state_validate_remote_identity = { func_validate_remote_identity, 0 }; static dds_security_fsm_state state_validate_remote_identity_retry_wait = { NULL, RETRY_TIMEOUT }; static dds_security_fsm_state state_handshake_init_message_resend = { func_handshake_init_message_resend, 0 }; @@ -192,6 +194,7 @@ static void q_handshake_fsm_debug( if (current == NULL) state = "NULL"; + else if (current == &state_initial_delay) state = "state_initial_delay"; else if (current == &state_validate_remote_identity) state = "state_validate_remote_identity"; else if (current == &state_validate_remote_identity_retry_wait) state = "state_validate_remote_identity_retry_wait"; else if (current == &state_handshake_init_message_resend) state = "state_handshake_init_message_resend"; @@ -250,6 +253,15 @@ static void q_handshake_fsm_debug( [START] | + .---------------------. + | state_initial_delay | + |---------------------| + | initial_delay | + '---------------------' + | + TIMEOUT + EVENT_RECEIVED_MESSAGE_REQUEST + | v .---------------------------------. | state_validate_remote_identity | @@ -367,6 +379,17 @@ VALIDATION_FAILED | | static const dds_security_fsm_transition handshake_transistions [] = { /* Start */ { NULL, EVENT_AUTO, NULL, + &state_initial_delay }, + /* initial delay: a short delay to give the remote node some time for matching the + BuiltinParticipantStatelessMessageWriter, so that it won't drop the auth_request + we're sending (that would result in a time-out and the handshake taking longer + than required). For the node that receives the auth_request, the transition for + the event EVENT_RECEIVED_MESSAGE_REQUEST is added, because that node may receive the + auth_request during this delay and can continue immediately (as the sender already + waited for this delay before sending the request) */ + { &state_initial_delay, EVENT_TIMEOUT, NULL, + &state_validate_remote_identity }, + { &state_initial_delay, EVENT_RECEIVED_MESSAGE_REQUEST, NULL, &state_validate_remote_identity }, /* validate remote identity */ { &state_validate_remote_identity, EVENT_VALIDATION_PENDING_RETRY, NULL, @@ -553,15 +576,7 @@ static void func_validate_remote_identity(struct dds_security_fsm *fsm, void *ar * to be send. */ if (handshake->local_auth_request_token.class_id && strlen(handshake->local_auth_request_token.class_id) != 0) - { - /* A short sleep to give the remote node some time for matching the - BuiltinParticipantStatelessMessageWriter, so that it won't drop the - sample we're sending (that would result in a time-out and the - handshake taking 1s longer than required) */ - dds_sleepfor (DDS_MSECS(10)); - HSTRACE("FSM: validate_remote_identity: send_handshake_message AUTH_REQUEST\n"); (void)send_handshake_message(handshake, &handshake->local_auth_request_token, pp, proxypp, 1); - } validation_failed: ident_token_missing: From 1e484a3c6ff604ed472015e4dca39dfcfb440996 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Mon, 6 Apr 2020 22:38:36 +0200 Subject: [PATCH 154/238] Introduced a new state in handshake fsm that combines validate_remote_entity and begin_handshake_reply into a single step, which is used in case a auth_request message is received during the initial delay when starting the handshake process Signed-off-by: Dennis Potman --- src/core/ddsi/src/ddsi_handshake.c | 386 ++++++++++++++++------------- 1 file changed, 219 insertions(+), 167 deletions(-) diff --git a/src/core/ddsi/src/ddsi_handshake.c b/src/core/ddsi/src/ddsi_handshake.c index 9f105fd..7040450 100644 --- a/src/core/ddsi/src/ddsi_handshake.c +++ b/src/core/ddsi/src/ddsi_handshake.c @@ -143,18 +143,20 @@ static bool validate_handshake(struct ddsi_handshake *handshake, struct particip #define AUTHENTICATION_TIMEOUT DDS_SECS(100) #define INITIAL_DELAY DDS_MSECS(10) -static void func_validate_remote_identity (struct dds_security_fsm *fsm, void *arg); -static void func_handshake_init_message_resend(struct dds_security_fsm *fsm, void *arg); -static void func_begin_handshake_reply (struct dds_security_fsm *fsm, void *arg); -static void func_begin_handshake_request (struct dds_security_fsm *fsm, void *arg); -static void func_process_handshake (struct dds_security_fsm *fsm, void *arg); -static void func_handshake_message_resend (struct dds_security_fsm *fsm, void *arg); -static void func_validation_ok (struct dds_security_fsm *fsm, void *arg); -static void func_validation_failed (struct dds_security_fsm *fsm, void *arg); -static void func_send_crypto_tokens_final (struct dds_security_fsm *fsm, void *arg); -static void func_send_crypto_tokens (struct dds_security_fsm *fsm, void *arg); +static void func_validate_remote_and_begin_reply (struct dds_security_fsm *fsm, void *arg); +static void func_validate_remote_identity (struct dds_security_fsm *fsm, void *arg); +static void func_handshake_init_message_resend (struct dds_security_fsm *fsm, void *arg); +static void func_begin_handshake_reply (struct dds_security_fsm *fsm, void *arg); +static void func_begin_handshake_request (struct dds_security_fsm *fsm, void *arg); +static void func_process_handshake (struct dds_security_fsm *fsm, void *arg); +static void func_handshake_message_resend (struct dds_security_fsm *fsm, void *arg); +static void func_validation_ok (struct dds_security_fsm *fsm, void *arg); +static void func_validation_failed (struct dds_security_fsm *fsm, void *arg); +static void func_send_crypto_tokens_final (struct dds_security_fsm *fsm, void *arg); +static void func_send_crypto_tokens (struct dds_security_fsm *fsm, void *arg); static dds_security_fsm_state state_initial_delay = { NULL, INITIAL_DELAY }; +static dds_security_fsm_state state_validate_remote_and_begin_reply = { func_validate_remote_and_begin_reply, 0 }; static dds_security_fsm_state state_validate_remote_identity = { func_validate_remote_identity, 0 }; static dds_security_fsm_state state_validate_remote_identity_retry_wait = { NULL, RETRY_TIMEOUT }; static dds_security_fsm_state state_handshake_init_message_resend = { func_handshake_init_message_resend, 0 }; @@ -195,6 +197,7 @@ static void q_handshake_fsm_debug( if (current == NULL) state = "NULL"; else if (current == &state_initial_delay) state = "state_initial_delay"; + else if (current == &state_validate_remote_and_begin_reply) state = "state_validate_remote_and_begin_reply"; else if (current == &state_validate_remote_identity) state = "state_validate_remote_identity"; else if (current == &state_validate_remote_identity_retry_wait) state = "state_validate_remote_identity_retry_wait"; else if (current == &state_handshake_init_message_resend) state = "state_handshake_init_message_resend"; @@ -249,124 +252,126 @@ static void q_handshake_fsm_debug( /************************************************************************************************************ - Inspiration from https://confluence.prismtech.com/display/VC/Authentication?preview=/30379826/34340895/PT_StateMachine_3g.gif - [START] | - .---------------------. - | state_initial_delay | - |---------------------| - | initial_delay | - '---------------------' - | - TIMEOUT - EVENT_RECEIVED_MESSAGE_REQUEST - | - v - .---------------------------------. - | state_validate_remote_identity | - .------------|---------------------------------|----------.--------------------. - | | func_validate_remote_identity() | | | - | '---------------------------------' | VALIDATION_PENDING_HANDSHAKE_MESSAGE -VALIDATION_FAILED ^ | VALIDATION_PENDING_RETRY | | -VALIDATION_OK | | | | - | TIMEOUT | v | v - | .-------------------------------------------. | .-----------------------------------. - | | state_validate_remote_identity_retry_wait | | | state_handshake_init_message_wait |<---------------. - | |-------------------------------------------| | |-----------------------------------| AUTO | - | | retry_timeout | | | resend_timeout |---------. | - | '-------------------------------------------' | '-----------------------------------' TIMEOUT | | - | | | | | - | .-----------------------------------' | | | - | | VALIDATION_PENDING_HANDSHAKE_REQUEST | v | - | | | .--------------------------------------. - | v RECEIVED_MESSAGE_REQUEST | state_handshake_init_message_resend | - | .--------------------------------. | |--------------------------------------| - | | state_begin_handshake_request | VALIDATION_PENDING_RETRY | | func_handshake_init_message_resend() | - | |--------------------------------|------------. | '--------------------------------------' - | | func_begin_handshake_request() | | | ^ - | '--------------------------------' | | | - | | | ^ | | | - | | | | TIMEOUT v | | - | VALIDATION_FAILED | .------------------------------------------. | | - | VALIDATION_OK | | state_begin_handshake_request_retry_wait | | | - | | | |------------------------------------------| | | - |--------' | | retry_timeout | | | - | | '------------------------------------------' | | - | | v VALIDATION_FAILED - | | .------------------------------. | - | VALIDATION_PENDING_HANDSHAKE_MESSAGE | state_begin_handshake_reply |------------' - | | .-------|------------------------------| - | | | | func_begin_handshake_reply() |------------. - | | | '------------------------------' | - | | | VALIDATION_OK | ^ VALIDATION_PENDING_RETRY - | | | | | | - | | VALIDATION_PENDING_HANDSHAKE_MESSAGE v | TIMEOUT | - | | | goto state_validation_ok | | - | | v | v - | | .------------------------------. .------------------------------------------. - | | | state_handshake_message_wait | | state_begin_handshake_reply_retry_wait | - | .--------------->|------------------------------|-------. |------------------------------------------| - | | | resend_timeout | | | retry_timeout | - | | '------------------------------' | '------------------------------------------' - | | AUTO | ^ | - | | TIMEOUT | | | - | .---------------------------------. | | | RECEIVED_MESSAGE_REPLY - | | state_handshake_message_resend | | VALIDATION_FAILED | RECEIVED_MESSAGE_FINAL - | |---------------------------------|<--------------' | | - | | func_handshake_message_resend() | | v - | '---------------------------------' .--------------------------. - | | state_process_handshake | - | .--------------------------------|--------------------------|--------------------------. - | | .------------------>| func_process_handshake() | | - | | | '--------------------------' | - | | | | | - | VALIDATION_PENDING_RETRY TIMEOUT VALIDATION_OK | | - | v | v | - | .------------------------------------. .-------------------------------. | - | | state_process_handshake_retry_wait | | state_send_crypto_tokens_wait | | - | |------------------------------------| |-------------------------------| | - | | retry_timeout | | send_tokens_timeout | | - | '------------------------------------' '-------------------------------' | - | | | VALIDATION_OK_FINAL_MESSAGE - | .-------------' '---------. | - | | RECV_CRYPTO_TOKENS TIMEOUT | | - | v v | - | .---------------------------------. .---------------------------. | - | | state_send_crypto_tokens_final | | state_send_crypto_tokens | | - | .--------------|---------------------------------| |---------------------------| | - | | | func_send_crypto_tokens_final() | | func_send_crypto_tokens() | | - | | '---------------------------------' '---------------------------' | - | | ^ | | - | VALIDATION_OK | .--------------------. VALIDATION_OK_FINAL_MESSAGE | - | | TIMEOUT | | RECV_CRYPTO_TOKENS | | | - | | | v | v | - | | .-------------------------------------. .--------------------------. | - | | | state_send_crypto_tokens_final_wait | | state_wait_crypto_tokens |<--------' - | | |-------------------------------------| |--------------------------| - | | | send_tokens_timeout | | |---------. - | | '-------------------------------------' '--------------------------' | - | | ^ | ^ | - | | | RECEIVED_MESSAGE_REPLY AUTO VALIDATION_OK - | | RECV_CRYPTO_TOKENS v | | - | | | .---------------------------------. | - | | | | state_handshake_final_resend | | - | | '---------------------|---------------------------------| | - | VALIDATION_OK | | func_handshake_message_resend() | | - |---------------------------------------------------------. '---------------------------------' | - | | | - '---------------. | | -VALIDATION_FAILED | | | - v v | - .--------------------------. .----------------------. | - | state_validation_failed | | state_validation_ok | | - |--------------------------| |----------------------|<----------------------------------------' - | func_validation_failed() | | func_validation_ok() | - '--------------------------' '----------------------' - | | - v v - [END] [END] - + .---------------------. .----------------------------------------. + | state_initial_delay | | state_validate_remote_and_begin_reply | + |---------------------|------------------------------->|----------------------------------------|------------------. + | initial_delay | RECEIVED_MESSAGE_REQUEST | func_validate_remote_and_begin_reply() | | + '---------------------' '----------------------------------------' | + | VALIDATION_PENDING_RETRY + TIMEOUT VALIDATION_PENDING_HANDSHAKE_MESSAGE + | VALIDATION_OK + v VALIDATION_FAILED + .---------------------------------. | + | state_validate_remote_identity | | + .------------|---------------------------------|----------.--------------------. | + | | func_validate_remote_identity() | | | | + | '---------------------------------' | VALIDATION_PENDING_HANDSHAKE_MESSAGE | +VALIDATION_FAILED ^ | VALIDATION_PENDING_RETRY | | | +VALIDATION_OK | | | | | + | TIMEOUT | v | v | + | .-------------------------------------------. | .-----------------------------------. | + | | state_validate_remote_identity_retry_wait | | | state_handshake_init_message_wait |<---------------. | + | |-------------------------------------------| | |-----------------------------------| AUTO | | + | | retry_timeout | | | resend_timeout |---------. | | + | '-------------------------------------------' | '-----------------------------------' TIMEOUT | | | + | | | | | | + | .-----------------------------------' | | | | + | | VALIDATION_PENDING_HANDSHAKE_REQUEST | v | | + | | | .--------------------------------------. | + | v RECEIVED_MESSAGE_REQUEST | state_handshake_init_message_resend | | + | .--------------------------------. | |--------------------------------------| | + | | state_begin_handshake_request | VALIDATION_PENDING_RETRY | | func_handshake_init_message_resend() | | + | |--------------------------------|------------. | '--------------------------------------' | + | | func_begin_handshake_request() | | | ^ | + | '--------------------------------' | | | | + | | | ^ | | | | + | | | | TIMEOUT v | | | + | VALIDATION_FAILED | .------------------------------------------. | | | + | VALIDATION_OK | | state_begin_handshake_request_retry_wait | | | | + | | | |------------------------------------------| | | | + |--------' | | retry_timeout | | | | + | | '------------------------------------------' | | | + | | v VALIDATION_FAILED | + | | .------------------------------. | | + | VALIDATION_PENDING_HANDSHAKE_MESSAGE | state_begin_handshake_reply |------------' | + | | .-------|------------------------------| | + | | | | func_begin_handshake_reply() |------------. | + | | | '------------------------------' | | + | | | VALIDATION_OK | ^ VALIDATION_PENDING_RETRY | + | | | | | | | + | | | | | | VALIDATION_PENDING_RETRY | + | | VALIDATION_PENDING_HANDSHAKE_MESSAGE v | TIMEOUT |--------------------------| + | | | goto state_validation_ok | | | + | | v | v | + | | .------------------------------. .------------------------------------------. | + | | | state_handshake_message_wait |<--------. | state_begin_handshake_reply_retry_wait | | + | .--------------->|------------------------------|------. | |------------------------------------------| | + | | | resend_timeout | | | | retry_timeout | | + | | '------------------------------' | | '------------------------------------------' | + | | | ^ | | | + | | AUTO | | | | VALIDATION_PENDING_HANDSHAKE_MESSAGE | + | | | | | '-----------------------------------------------------| + | | TIMEOUT | | | | + | .---------------------------------. | | | RECEIVED_MESSAGE_REPLY | + | | state_handshake_message_resend | | VALIDATION_FAILED | RECEIVED_MESSAGE_FINAL | + | |---------------------------------|<--------------' | | | + | | func_handshake_message_resend() | | v | + | '---------------------------------' .--------------------------. | + | | state_process_handshake | | + | .--------------------------------|--------------------------|--------------------------. | + | | .------------------>| func_process_handshake() | | | + | | | '--------------------------' | | + | | | | | | + | VALIDATION_PENDING_RETRY TIMEOUT VALIDATION_OK | | | + | v | v | | + | .------------------------------------. .-------------------------------. | | + | | state_process_handshake_retry_wait | | state_send_crypto_tokens_wait | | | + | |------------------------------------| |-------------------------------| | | + | | retry_timeout | | send_tokens_timeout | | | + | '------------------------------------' '-------------------------------' | | + | | | VALIDATION_OK_FINAL_MESSAGE | + | .-------------' '---------. | | + | | RECV_CRYPTO_TOKENS TIMEOUT | | | + | v v | | + | .---------------------------------. .---------------------------. | | + | | state_send_crypto_tokens_final | | state_send_crypto_tokens | | | + | .--------------|---------------------------------| |---------------------------| | | + | | | func_send_crypto_tokens_final() | | func_send_crypto_tokens() | | | + | | '---------------------------------' '---------------------------' | | + | | ^ | | | + | VALIDATION_OK | .--------------------. VALIDATION_OK_FINAL_MESSAGE | | + | | TIMEOUT | | RECV_CRYPTO_TOKENS | | | | + | | | v | v | | + | | .-------------------------------------. .--------------------------. | | + | | | state_send_crypto_tokens_final_wait | | state_wait_crypto_tokens |<--------' | + | | |-------------------------------------| |--------------------------| | + | | | send_tokens_timeout | | |---------. | + | | '-------------------------------------' '--------------------------' | | + | | ^ | ^ | | + | | | RECEIVED_MESSAGE_REPLY AUTO VALIDATION_OK | + | | RECV_CRYPTO_TOKENS v | | | + | | | .---------------------------------. | | + | | | | state_handshake_final_resend | | | + | | '---------------------|---------------------------------| | | + | VALIDATION_OK | | func_handshake_message_resend() | | | + |---------------------------------------------------------. '---------------------------------' | | + | | | | + '---------------. | | | +VALIDATION_FAILED | | | | + v v | | + .--------------------------. .----------------------. | | + | state_validation_failed | | state_validation_ok | | | + |--------------------------| |----------------------|<----------------------------------------' | + | func_validation_failed() | | func_validation_ok() | | + '--------------------------' '----------------------' | + | ^ | ^ | + v | v | VALIDATION_OK | + [END] | [END] | | + | | | + | VALIDATION_FAILED | | + '---------------------------------------------------------------------------------------------------' .----------------------------------------. | state_begin_handshake_reply_retry_wait | @@ -390,7 +395,16 @@ static const dds_security_fsm_transition handshake_transistions [] = { &state_initial_delay, EVENT_TIMEOUT, NULL, &state_validate_remote_identity }, { &state_initial_delay, EVENT_RECEIVED_MESSAGE_REQUEST, NULL, - &state_validate_remote_identity }, + &state_validate_remote_and_begin_reply }, + /* validate remote and begin reply */ + { &state_validate_remote_and_begin_reply, EVENT_VALIDATION_PENDING_RETRY, NULL, + &state_begin_handshake_reply_retry_wait }, + { &state_validate_remote_and_begin_reply, EVENT_VALIDATION_FAILED, NULL, + &state_handshake_init_message_resend }, + { &state_validate_remote_and_begin_reply, EVENT_VALIDATION_OK, NULL, + &state_validation_ok }, + { &state_validate_remote_and_begin_reply, EVENT_VALIDATION_PENDING_HANDSHAKE_MESSAGE, NULL, + &state_handshake_message_wait }, /* validate remote identity */ { &state_validate_remote_identity, EVENT_VALIDATION_PENDING_RETRY, NULL, &state_validate_remote_identity_retry_wait }, @@ -520,22 +534,14 @@ static bool send_handshake_message(const struct ddsi_handshake *handshake, DDS_S return ret; } -static void func_validate_remote_identity(struct dds_security_fsm *fsm, void *arg) +static DDS_Security_ValidationResult_t validate_remote_identity_impl(struct ddsi_handshake *handshake, dds_security_authentication *auth, + struct participant *pp, struct proxy_participant *proxypp) { DDS_Security_ValidationResult_t ret; - DDS_Security_SecurityException exception = {0}; - struct ddsi_handshake *handshake = (struct ddsi_handshake*)arg; - dds_security_authentication *auth = handshake->auth; - struct participant *pp; - struct proxy_participant *proxypp; DDS_Security_IdentityToken remote_identity_token; int64_t remote_identity_handle; ddsi_guid_t remote_guid; - - if (!validate_handshake(handshake, &pp, &proxypp)) - return; - - TRACE_FUNC(fsm); + DDS_Security_SecurityException exception = {0}; if (!(proxypp->plist->present & PP_IDENTITY_TOKEN)) { @@ -578,9 +584,25 @@ static void func_validate_remote_identity(struct dds_security_fsm *fsm, void *ar if (handshake->local_auth_request_token.class_id && strlen(handshake->local_auth_request_token.class_id) != 0) (void)send_handshake_message(handshake, &handshake->local_auth_request_token, pp, proxypp, 1); -validation_failed: ident_token_missing: - /* Use return value as state machine event. */ +validation_failed: + return ret; +} + +static void func_validate_remote_identity(struct dds_security_fsm *fsm, void *arg) +{ + DDS_Security_ValidationResult_t ret; + struct ddsi_handshake *handshake = (struct ddsi_handshake*)arg; + dds_security_authentication *auth = handshake->auth; + struct participant *pp; + struct proxy_participant *proxypp; + + if (!validate_handshake(handshake, &pp, &proxypp)) + return; + + TRACE_FUNC(fsm); + + ret = validate_remote_identity_impl(handshake, auth, pp, proxypp); dds_security_fsm_dispatch(fsm, (int32_t)ret, true); } @@ -603,19 +625,11 @@ static void func_handshake_init_message_resend(struct dds_security_fsm *fsm, voi (void)send_handshake_message(handshake, &handshake->local_auth_request_token, pp, proxypp, 1); } -static void func_begin_handshake_reply(struct dds_security_fsm *fsm, void *arg) +static DDS_Security_ValidationResult_t begin_handshake_reply_impl(struct ddsi_handshake *handshake, dds_security_authentication *auth, + struct participant *pp, struct proxy_participant *proxypp) { DDS_Security_ValidationResult_t ret; DDS_Security_SecurityException exception = {0}; - struct ddsi_handshake *handshake = arg; - dds_security_authentication *auth = handshake->auth; - struct participant *pp; - struct proxy_participant *proxypp; - - if (!validate_handshake(handshake, &pp, &proxypp)) - return; - - TRACE_FUNC(fsm); ddsrt_mutex_lock(&handshake->lock); @@ -632,31 +646,26 @@ static void func_begin_handshake_reply(struct dds_security_fsm *fsm, void *arg) HSTRACE("FSM: begin_handshake_reply (lguid="PGUIDFMT" rguid="PGUIDFMT") ret=%d\n", PGUID (pp->e.guid), PGUID (proxypp->e.guid), ret); /* Trace a failed handshake. */ - if ((ret != DDS_SECURITY_VALIDATION_OK ) && - (ret != DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE ) && - (ret != DDS_SECURITY_VALIDATION_PENDING_RETRY ) && - (ret != DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE)) + if (ret != DDS_SECURITY_VALIDATION_OK + && ret != DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE + && ret != DDS_SECURITY_VALIDATION_PENDING_RETRY + && ret != DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE) { HSEXCEPTION(&exception, "Begin handshake reply failed"); - ret = DDS_SECURITY_VALIDATION_FAILED; goto handshake_failed; } - if (ret == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE) { - if (!send_handshake_message(handshake, handshake->handshake_message_out, pp, proxypp, 0)) { - ret = DDS_SECURITY_VALIDATION_FAILED; + if (ret == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE) + { + if (!send_handshake_message(handshake, handshake->handshake_message_out, pp, proxypp, 0)) goto handshake_failed; - } } else if (ret == DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE) { if (send_handshake_message(handshake, handshake->handshake_message_out, pp, proxypp, 0)) ret = DDS_SECURITY_VALIDATION_OK; else - { - ret = DDS_SECURITY_VALIDATION_FAILED; goto handshake_failed; - } } if (ret == DDS_SECURITY_VALIDATION_OK) @@ -665,18 +674,61 @@ static void func_begin_handshake_reply(struct dds_security_fsm *fsm, void *arg) if (handshake->shared_secret == DDS_SECURITY_HANDLE_NIL) { HSEXCEPTION(&exception, "Getting shared secret failed"); - ret = DDS_SECURITY_VALIDATION_FAILED; goto handshake_failed; } } - - dds_security_fsm_dispatch(fsm, (int32_t)ret, true); - return; + return ret; handshake_failed: DDS_Security_DataHolder_free(handshake->handshake_message_out); handshake->handshake_message_out = NULL; - /* Use return value as state machine event. */ + return DDS_SECURITY_VALIDATION_FAILED; +} + +static void func_begin_handshake_reply(struct dds_security_fsm *fsm, void *arg) +{ + DDS_Security_ValidationResult_t ret; + struct ddsi_handshake *handshake = arg; + dds_security_authentication *auth = handshake->auth; + struct participant *pp; + struct proxy_participant *proxypp; + + if (!validate_handshake(handshake, &pp, &proxypp)) + return; + + TRACE_FUNC(fsm); + + ret = begin_handshake_reply_impl(handshake, auth, pp, proxypp); + dds_security_fsm_dispatch(fsm, (int32_t)ret, true); +} + +static void func_validate_remote_and_begin_reply(struct dds_security_fsm *fsm, void *arg) +{ + DDS_Security_ValidationResult_t ret; + struct ddsi_handshake *handshake = arg; + dds_security_authentication *auth = handshake->auth; + struct participant *pp; + struct proxy_participant *proxypp; + + if (!validate_handshake(handshake, &pp, &proxypp)) + return; + + TRACE_FUNC(fsm); + + ret = validate_remote_identity_impl(handshake, auth, pp, proxypp); + /* In the only path to this state an auth_request is received so the result + of validate_remote_identity should be PENDING_HANDSHAKE_MESSAGE, or failed + in case of an error. */ + if (ret != DDS_SECURITY_VALIDATION_FAILED) + { + if (ret != DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE) + { + HSWARNING("func_validate_remote_and_begin_reply: invalid result %d from validate_remote_identity", ret); + ret = DDS_SECURITY_VALIDATION_FAILED; + } + else + ret = begin_handshake_reply_impl(handshake, auth, pp, proxypp); + } dds_security_fsm_dispatch(fsm, (int32_t)ret, true); } From 829e33ac82a1b064fa67e730e277046fe5b21ea2 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 7 Apr 2020 13:05:06 +0200 Subject: [PATCH 155/238] Remove unused field from struct ddsi_handshake Signed-off-by: Dennis Potman --- src/core/ddsi/src/ddsi_handshake.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/ddsi/src/ddsi_handshake.c b/src/core/ddsi/src/ddsi_handshake.c index 7040450..72da225 100644 --- a/src/core/ddsi/src/ddsi_handshake.c +++ b/src/core/ddsi/src/ddsi_handshake.c @@ -91,7 +91,6 @@ struct ddsi_handshake DDS_Security_AuthRequestMessageToken *remote_auth_request_token; DDS_Security_OctetSeq pdata; int64_t shared_secret; - int handled_handshake_message; }; struct ddsi_hsadmin { @@ -1139,7 +1138,6 @@ void ddsi_handshake_handle_message(struct ddsi_handshake *handshake, const struc DDS_Security_DataHolder_deinit(&handshake->handshake_message_in_token); q_omg_security_dataholder_copyout(&handshake->handshake_message_in_token, &msg->message_data.tags[0]); memcpy(&handshake->handshake_message_in_id, &msg->message_identity, sizeof(handshake->handshake_message_in_id)); - handshake->handled_handshake_message = 0; dds_security_fsm_dispatch(handshake->fsm, event, false); ddsrt_mutex_unlock(&handshake->lock); } From 534eac2a11f58aff0e670e189b6aebc1adb0a32a Mon Sep 17 00:00:00 2001 From: Marcel Jordense Date: Fri, 3 Apr 2020 13:42:16 +0200 Subject: [PATCH 156/238] Remove temporarily stored crypto handles and tokens after entities are matched Signed-off-by: Marcel Jordense --- .../ddsi/include/dds/ddsi/ddsi_domaingv.h | 1 - .../ddsi/include/dds/ddsi/ddsi_security_omg.h | 61 +- src/core/ddsi/src/ddsi_security_omg.c | 646 ++++++++++-------- src/core/ddsi/src/q_entity.c | 6 + src/core/ddsi/src/q_init.c | 15 +- 5 files changed, 439 insertions(+), 290 deletions(-) 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); From a6a9d1f7c166790384ee4139288af80a0c1d35db Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Wed, 11 Mar 2020 13:17:39 +0100 Subject: [PATCH 157/238] Security core tests: new tests and refactoring Refactoring security core tests and adding more tests: - Dynamically generate ca and identity certificates in authentication tests, so that certificate expiry is tested. Added writing/reading samples to these tests to ensure that nodes can (or cannot) communicate in a specific test case - Secure communication tests: improved the validation of encryption in wrapper - Added test for access control plugin settings - Replaced the in-code test identities (and included ca private keys), added an additional identity Signed-off-by: Dennis Potman --- src/security/core/tests/CMakeLists.txt | 2 + src/security/core/tests/access_control.c | 63 +-- src/security/core/tests/authentication.c | 380 +++++++++++++++--- src/security/core/tests/common/cert_utils.c | 142 +++++++ src/security/core/tests/common/cert_utils.h | 20 + .../core/tests/common/cryptography_wrapper.c | 79 +++- .../core/tests/common/cryptography_wrapper.h | 7 + .../core/tests/common/handshake_test_utils.c | 199 +++++---- .../core/tests/common/handshake_test_utils.h | 14 +- .../tests/common/security_config_test_utils.c | 81 +++- .../tests/common/security_config_test_utils.h | 4 +- .../core/tests/common/test_identity.h | 284 ++++++++++--- src/security/core/tests/handshake.c | 10 +- .../core/tests/secure_communication.c | 40 +- 14 files changed, 1083 insertions(+), 242 deletions(-) create mode 100644 src/security/core/tests/common/cert_utils.c create mode 100644 src/security/core/tests/common/cert_utils.h diff --git a/src/security/core/tests/CMakeLists.txt b/src/security/core/tests/CMakeLists.txt index 5618269..639b84b 100644 --- a/src/security/core/tests/CMakeLists.txt +++ b/src/security/core/tests/CMakeLists.txt @@ -75,7 +75,9 @@ if(ENABLE_SSL) list(APPEND security_core_test_sources "common/security_config_test_utils.c" "common/handshake_test_utils.c" + "common/cert_utils.c" "authentication.c" + "access_control.c" "config.c" "handshake.c" "plugin_loading.c" diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index 0b25a90..061dfef 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -44,15 +44,15 @@ static const char *config = " " " " " " - " " TEST_IDENTITY_CERTIFICATE "" - " " TEST_IDENTITY_PRIVATE_KEY "" - " " TEST_IDENTITY_CA_CERTIFICATE "" + " data:," TEST_IDENTITY1_CERTIFICATE "" + " data:," TEST_IDENTITY1_PRIVATE_KEY "" + " data:," TEST_IDENTITY_CA1_CERTIFICATE "" " " " " " " - " ${TEST_GOVERNANCE}" - " ${TEST_PERMISSIONS_CA}" - " ${TEST_PERMISSIONS}" + " ${INCL_GOV:+}${TEST_GOVERNANCE}${INCL_GOV:+}" + " ${INCL_PERM_CA:+}${TEST_PERMISSIONS_CA}${INCL_PERM_CA:+}" + " ${INCL_PERM:+}${TEST_PERMISSIONS}${INCL_PERM:+}" " " " " " " @@ -69,9 +69,12 @@ static dds_entity_t g_participant1 = 0; static dds_entity_t g_domain2 = 0; static dds_entity_t g_participant2 = 0; -static void access_control_init(const char * gov, const char * perm, const char * ca, bool exp_pp_fail) +static void access_control_init(bool incl_gov, const char * gov, bool incl_perm, const char * perm, bool incl_ca, const char * ca, bool exp_pp_fail) { struct kvp config_vars[] = { + { "INCL_GOV", incl_gov ? "1" : "", 2 }, + { "INCL_PERM", incl_perm ? "1" : "", 2 }, + { "INCL_PERM_CA", incl_ca ? "1" : "", 2 }, { "TEST_GOVERNANCE", gov, 1 }, { "TEST_PERMISSIONS", perm, 1 }, { "TEST_PERMISSIONS_CA", ca, 1 }, @@ -86,16 +89,8 @@ static void access_control_init(const char * gov, const char * perm, const char g_participant1 = dds_create_participant (DDS_DOMAINID1, NULL, NULL); g_participant2 = dds_create_participant (DDS_DOMAINID2, NULL, NULL); - if (exp_pp_fail) - { - CU_ASSERT_FATAL (g_participant1 <= 0); - CU_ASSERT_FATAL (g_participant2 <= 0); - } - else - { - CU_ASSERT_FATAL (g_participant1 > 0); - CU_ASSERT_FATAL (g_participant2 > 0); - } + CU_ASSERT_EQUAL_FATAL (exp_pp_fail, g_participant1 <= 0); + CU_ASSERT_EQUAL_FATAL (exp_pp_fail, g_participant2 <= 0); } static void access_control_fini(bool delete_pp) @@ -121,16 +116,34 @@ static void access_control_fini(bool delete_pp) #define CA_F PF_F COMMON_ETC_PATH("default_permissions_ca.pem") #define CA_FNE PF_F COMMON_ETC_PATH("default_permissions_ca_non_existing.pem") #define CA_DI PF_D COMMON_ETC_PATH("default_permissions_ca.pem") -#define CA_D TEST_PERMISSIONS_CA_CERTIFICATE +#define CA_D PF_D TEST_PERMISSIONS_CA_CERTIFICATE -CU_TheoryDataPoints(ddssec_access_control, config_parameters) = { - CU_DataPoints(const char *, GOV_F, GOV_FNE, GOV_FNE, GOV_F, GOV_F, "", GOV_F, GOV_F, GOV_DI, GOV_F), - CU_DataPoints(const char *, PERM_F, PERM_FNE, PERM_F, PERM_FNE, PERM_F, PERM_F, "", PERM_F, PERM_F, PERM_F), - CU_DataPoints(const char *, CA_F, CA_FNE, CA_F, CA_F, CA_FNE, CA_F, CA_F, "", CA_F, CA_D), - CU_DataPoints(bool, false, true, true, true, true, true, true, true, true, false) +CU_TheoryDataPoints(ddssec_access_control, config_parameters_file) = { + CU_DataPoints(const char *, + /* */"existing files", + /* | */"non-existing files", + /* | | */"non-existing governance file", + /* | | | */"non-existing permissions file", + /* | | | | */"non-existing permissions ca file", + /* | | | | | */"empty governance", + /* | | | | | | */"empty permissions", + /* | | | | | | | */"empty permissions ca", + /* | | | | | | | | */"all empty", + /* | | | | | | | | | */"invalid governance uri type", + /* | | | | | | | | | | */"permissions ca type data", + /* | | | | | | | | | | | */"no governance element", + /* | | | | | | | | | | | | */"no permissions element", + /* | | | | | | | | | | | | | */"no permissions ca element"), + CU_DataPoints(const char *, GOV_F, GOV_FNE, GOV_FNE, GOV_F, GOV_F, "", GOV_F, GOV_F, "", GOV_DI, GOV_F, "", GOV_F, GOV_F), // Governance config + CU_DataPoints(const char *, PERM_F, PERM_FNE, PERM_F, PERM_FNE, PERM_F, PERM_F, "", PERM_F, "", PERM_F, PERM_F, PERM_F, "", PERM_F), // Permissions config + CU_DataPoints(const char *, CA_F, CA_FNE, CA_F, CA_F, CA_FNE, CA_F, CA_F, "", "", CA_F, CA_D, CA_F, CA_F, ""), // Permissions CA + CU_DataPoints(bool, true, true, true, true, true, true, true, true, true, true, true, false, false, false), // include empty config elements + CU_DataPoints(bool, false, true, true, true, true, true, true, true, false, true, false, true, true, true) // expect failure }; -CU_Theory((const char * gov, const char * perm, const char * ca, bool exp_fail), ddssec_access_control, config_parameters) +CU_Theory((const char * test_descr, const char * gov, const char * perm, const char * ca, bool incl_empty_els, bool exp_fail), + ddssec_access_control, config_parameters_file) { - access_control_init (gov, perm, ca, exp_fail); + printf("running test config_parameters_file: %s\n", test_descr); + access_control_init (incl_empty_els || strlen (gov), gov, incl_empty_els || strlen (perm), perm, incl_empty_els || strlen (ca), ca, exp_fail); access_control_fini (!exp_fail); } diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index afab49b..a23f203 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -34,6 +34,22 @@ #include "common/handshake_test_utils.h" #include "common/security_config_test_utils.h" #include "common/test_identity.h" +#include "common/cert_utils.h" +#include "common/security_config_test_utils.h" + +#include "SecurityCoreTests.h" + + +#define ID1 TEST_IDENTITY1_CERTIFICATE +#define ID1K TEST_IDENTITY1_PRIVATE_KEY +#define ID2 TEST_IDENTITY2_CERTIFICATE +#define ID2K TEST_IDENTITY2_PRIVATE_KEY +#define ID3 TEST_IDENTITY3_CERTIFICATE +#define ID3K TEST_IDENTITY3_PRIVATE_KEY +#define CA1 TEST_IDENTITY_CA1_CERTIFICATE +#define CA1K TEST_IDENTITY_CA1_PRIVATE_KEY +#define CA2 TEST_IDENTITY_CA2_CERTIFICATE +#define CA2K TEST_IDENTITY_CA2_PRIVATE_KEY static const char *config = "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" @@ -45,16 +61,16 @@ static const char *config = " " " " " " - " ${TEST_IDENTITY_CERTIFICATE}" - " ${TEST_IDENTITY_PRIVATE_KEY}" - " ${TEST_IDENTITY_CA_CERTIFICATE}" + " data:,${TEST_IDENTITY_CERTIFICATE}" + " data:,${TEST_IDENTITY_PRIVATE_KEY}" + " data:,${TEST_IDENTITY_CA_CERTIFICATE}" " ${TRUSTED_CA_DIR:+}${TRUSTED_CA_DIR}${TRUSTED_CA_DIR:+}" " " " " " " - " file:" COMMON_ETC_PATH("default_governance.p7s") "" + " " " file:" COMMON_ETC_PATH("default_permissions_ca.pem") "" - " file:" COMMON_ETC_PATH("default_permissions.p7s") "" + " " " " " " " " @@ -64,29 +80,59 @@ static const char *config = #define DDS_DOMAINID1 0 #define DDS_DOMAINID2 1 -#define MAX_ADDITIONAL_CONF 255 -static dds_entity_t g_domain1 = 0; -static dds_entity_t g_participant1 = 0; +#define DEF_PERM_CONF "file:" COMMON_ETC_PATH("default_permissions.p7s") -static dds_entity_t g_domain2 = 0; -static dds_entity_t g_participant2 = 0; +static dds_entity_t g_domain1; +static dds_entity_t g_participant1; +static dds_entity_t g_pub; +static dds_entity_t g_pub_tp; +static dds_entity_t g_wr; -static void authentication_init(bool different_ca, const char * trusted_ca_dir, bool exp_pp_fail) +static dds_entity_t g_domain2; +static dds_entity_t g_participant2; +static dds_entity_t g_sub; +static dds_entity_t g_sub_tp; +static dds_entity_t g_rd; + +static uint32_t g_topic_nr = 0; + +static void authentication_init( + const char * id1_cert, const char * id1_key, const char * id1_ca, + const char * id2_cert, const char * id2_key, const char * id2_ca, + const char * trusted_ca_dir, const char * perm_config, + bool exp_pp1_fail, bool exp_pp2_fail) { + if (perm_config == NULL) + perm_config = DEF_PERM_CONF; + + struct kvp governance_vars[] = { + { "DISCOVERY_PROTECTION_KIND", "NONE", 1 }, + { "LIVELINESS_PROTECTION_KIND", "NONE", 1 }, + { "RTPS_PROTECTION_KIND", "NONE", 1 }, + { "METADATA_PROTECTION_KIND", "NONE", 1 }, + { "DATA_PROTECTION_KIND", "NONE", 1 }, + { NULL, NULL, 0 } + }; + char * gov_config_signed = get_governance_config (governance_vars, true); + struct kvp config_vars1[] = { - { "TEST_IDENTITY_CERTIFICATE", TEST_IDENTITY_CERTIFICATE, 1 }, - { "TEST_IDENTITY_PRIVATE_KEY", TEST_IDENTITY_PRIVATE_KEY, 1 }, - { "TEST_IDENTITY_CA_CERTIFICATE", TEST_IDENTITY_CA_CERTIFICATE, 1 }, + { "TEST_IDENTITY_CERTIFICATE", id1_cert, 1 }, + { "TEST_IDENTITY_PRIVATE_KEY", id1_key, 1 }, + { "TEST_IDENTITY_CA_CERTIFICATE", id1_ca, 1 }, { "TRUSTED_CA_DIR", trusted_ca_dir, 3 }, + { "PERM_CONFIG", perm_config, 1 }, + { "GOVERNANCE_CONFIG", gov_config_signed, 1 }, { NULL, NULL, 0 } }; struct kvp config_vars2[] = { - { "TEST_IDENTITY_CERTIFICATE", TEST_IDENTITY2_CERTIFICATE, 1 }, - { "TEST_IDENTITY_PRIVATE_KEY", TEST_IDENTITY2_PRIVATE_KEY, 1 }, - { "TEST_IDENTITY_CA_CERTIFICATE", TEST_IDENTITY_CA2_CERTIFICATE, 1 }, + { "TEST_IDENTITY_CERTIFICATE", id2_cert, 1 }, + { "TEST_IDENTITY_PRIVATE_KEY", id2_key, 1 }, + { "TEST_IDENTITY_CA_CERTIFICATE", id2_ca, 1 }, { "TRUSTED_CA_DIR", trusted_ca_dir, 3 }, + { "PERM_CONFIG", perm_config, 1 }, + { "GOVERNANCE_CONFIG", gov_config_signed, 1 }, { NULL, NULL, 0 } }; @@ -95,57 +141,301 @@ static void authentication_init(bool different_ca, const char * trusted_ca_dir, CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars1), 0); CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars2), 0); g_domain1 = dds_create_domain (DDS_DOMAINID1, conf1); - g_domain2 = dds_create_domain (DDS_DOMAINID2, different_ca ? conf2 : conf1); - dds_free (conf1); - dds_free (conf2); - + g_domain2 = dds_create_domain (DDS_DOMAINID2, conf2); g_participant1 = dds_create_participant (DDS_DOMAINID1, NULL, NULL); g_participant2 = dds_create_participant (DDS_DOMAINID2, NULL, NULL); - if (exp_pp_fail) - { - CU_ASSERT_FATAL (g_participant1 <= 0); - CU_ASSERT_FATAL (g_participant2 <= 0); - } - else - { - CU_ASSERT_FATAL (g_participant1 > 0); - CU_ASSERT_FATAL (g_participant2 > 0); - } + CU_ASSERT_EQUAL_FATAL (exp_pp1_fail, g_participant1 <= 0); + CU_ASSERT_EQUAL_FATAL (exp_pp2_fail, g_participant2 <= 0); + + ddsrt_free (gov_config_signed); + ddsrt_free (conf1); + ddsrt_free (conf2); } -static void authentication_fini(bool delete_pp) +static char *create_topic_name(const char *prefix, uint32_t nr, char *name, size_t size) { - if (delete_pp) + ddsrt_pid_t pid = ddsrt_getpid (); + ddsrt_tid_t tid = ddsrt_gettid (); + (void)snprintf(name, size, "%s%d_pid%" PRIdPID "_tid%" PRIdTID "", prefix, nr, pid, tid); + return name; +} + +static void sync_writer_to_reader() +{ + dds_attach_t triggered; + dds_return_t ret; + dds_entity_t waitset_wr = dds_create_waitset (g_participant1); + CU_ASSERT_FATAL (waitset_wr > 0); + dds_publication_matched_status_t pub_matched; + + /* Sync writer to reader. */ + ret = dds_waitset_attach (waitset_wr, g_wr, g_wr); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + while (true) { - CU_ASSERT_EQUAL_FATAL (dds_delete (g_participant1), DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL (dds_delete (g_participant2), DDS_RETCODE_OK); + ret = dds_waitset_wait (waitset_wr, &triggered, 1, DDS_SECS(5)); + CU_ASSERT_FATAL (ret >= 1); + CU_ASSERT_EQUAL_FATAL (g_wr, (dds_entity_t)(intptr_t) triggered); + ret = dds_get_publication_matched_status(g_wr, &pub_matched); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + if (pub_matched.total_count >= 1) + break; + }; + dds_delete (waitset_wr); +} + +static void reader_wait_for_data() +{ + dds_attach_t triggered; + dds_return_t ret; + dds_entity_t waitset_rd = dds_create_waitset (g_participant2); + CU_ASSERT_FATAL (waitset_rd > 0); + + ret = dds_waitset_attach (waitset_rd, g_rd, g_rd); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + ret = dds_waitset_wait (waitset_rd, &triggered, 1, DDS_SECS(5)); + CU_ASSERT_EQUAL_FATAL (ret, 1); + CU_ASSERT_EQUAL_FATAL (g_rd, (dds_entity_t)(intptr_t)triggered); + dds_delete (waitset_rd); +} + +static void rd_wr_init() +{ + char name[100]; + dds_qos_t * qos = dds_create_qos (); + CU_ASSERT_FATAL (qos != NULL); + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, -1); + dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL); + dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); + + create_topic_name("ddssec_authentication_", g_topic_nr++, name, sizeof (name)); + g_pub = dds_create_publisher (g_participant1, NULL, NULL); + CU_ASSERT_FATAL (g_pub > 0); + g_sub = dds_create_subscriber (g_participant2, NULL, NULL); + CU_ASSERT_FATAL (g_sub > 0); + g_pub_tp = dds_create_topic (g_participant1, &SecurityCoreTests_Type1_desc, name, NULL, NULL); + CU_ASSERT_FATAL (g_pub_tp > 0); + g_sub_tp = dds_create_topic (g_participant2, &SecurityCoreTests_Type1_desc, name, NULL, NULL); + CU_ASSERT_FATAL (g_sub_tp > 0); + g_wr = dds_create_writer (g_pub, g_pub_tp, qos, NULL); + CU_ASSERT_FATAL (g_wr > 0); + dds_set_status_mask (g_wr, DDS_PUBLICATION_MATCHED_STATUS); + g_rd = dds_create_reader (g_sub, g_sub_tp, qos, NULL); + CU_ASSERT_FATAL (g_rd > 0); + dds_set_status_mask (g_rd, DDS_DATA_AVAILABLE_STATUS); + sync_writer_to_reader(); + dds_delete_qos (qos); +} + +static void write_read(dds_duration_t dur, bool exp_write_fail, bool exp_read_fail) +{ + SecurityCoreTests_Type1 sample = { 1, 1 }; + SecurityCoreTests_Type1 rd_sample; + void * samples[] = { &rd_sample }; + dds_sample_info_t info[1]; + dds_return_t ret; + dds_time_t tend = dds_time () + dur; + bool write_fail = false, read_fail = false; + + rd_wr_init (); + do + { + ret = dds_write (g_wr, &sample); + if (ret != DDS_RETCODE_OK) + write_fail = true; + while (true) + { + if ((ret = dds_take (g_rd, samples, info, 1, 1)) == 0) + { + reader_wait_for_data (); + continue; + } + else if (ret < 0) + { + read_fail = true; + break; + } + CU_ASSERT_EQUAL_FATAL (ret, 1); + break; + } + dds_sleepfor (DDS_MSECS (1)); } + while (dds_time() < tend && !write_fail && !read_fail); + CU_ASSERT_EQUAL_FATAL (write_fail, exp_write_fail); + CU_ASSERT_EQUAL_FATAL (read_fail, exp_read_fail); +} + +static void authentication_fini(bool delete_pp1, bool delete_pp2) +{ + if (delete_pp1) + CU_ASSERT_EQUAL_FATAL (dds_delete (g_participant1), DDS_RETCODE_OK); + if (delete_pp2) + CU_ASSERT_EQUAL_FATAL (dds_delete (g_participant2), DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain1), DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain2), DDS_RETCODE_OK); } -CU_Test(ddssec_authentication, different_ca) +#define FM_CA "error: unable to get local issuer certificate" +#define FM_INVK "Failed to finalize verify context" +CU_TheoryDataPoints(ddssec_authentication, id_ca_certs) = { + CU_DataPoints(const char *, + /* */"valid ID1-ID1", + /* | */"non-trusted remote CA ID1(CA1)-ID2(CA2)", + /* | | */"valid ID1-ID3", + /* | | | */"invalid ca ID1(CA1)-ID1(CA2)", + /* | | | | */"invalid remote key ID3(K1)"), + CU_DataPoints(const char *, ID1, ID2, ID3, ID1, ID3), /* Identity for domain 2 */ + CU_DataPoints(const char *, ID1K, ID2K, ID3K, ID1K, ID1K), /* Private key for domain 2 identity */ + CU_DataPoints(const char *, CA1, CA2, CA1, CA2, CA1), /* CA for domain 2 identity */ + CU_DataPoints(bool, false, false, false, false, false), /* expect create participant1 fails */ + CU_DataPoints(bool, false, false, false, true, false), /* expect create participant2 fails */ + CU_DataPoints(bool, false, false, false, true, false), /* expect validate local failed for domain 2 */ + CU_DataPoints(const char *, NULL, NULL, NULL, FM_CA, NULL), /* expected error message for validate local failed */ + CU_DataPoints(bool, false, true, false, false, true), /* expect handshake request failed */ + CU_DataPoints(const char *, NULL, NULL, NULL, NULL, FM_INVK), /* expected error message for handshake request failed */ + CU_DataPoints(bool, false, true, false, true, true), /* expect handshake reply failed */ + CU_DataPoints(const char *, NULL, FM_CA, NULL, FM_CA, NULL) /* expected error message for handshake reply failed */ +}; +#undef FM_CA +#undef FM_INVK + +static void validate_hs(struct Handshake *hs, bool exp_fail_hs_req, const char * fail_hs_req_msg, bool exp_fail_hs_reply, const char * fail_hs_reply_msg) { - authentication_init (true, NULL, false); - validate_handshake (DDS_DOMAINID1, true, NULL, true, "error: unable to get local issuer certificate"); - validate_handshake (DDS_DOMAINID2, true, NULL, true, "error: unable to get local issuer certificate"); - authentication_fini (true); + DDS_Security_ValidationResult_t exp_result = hs->node_type == HSN_REQUESTER ? DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE : DDS_SECURITY_VALIDATION_OK; + if (hs->node_type == HSN_REQUESTER) + { + CU_ASSERT_EQUAL_FATAL (hs->finalResult, exp_fail_hs_req ? DDS_SECURITY_VALIDATION_FAILED : exp_result); + if (exp_fail_hs_req) + { + if (fail_hs_req_msg == NULL) + { + CU_ASSERT_EQUAL_FATAL (hs->err_msg, NULL); + } + else + { + CU_ASSERT_FATAL (hs->err_msg != NULL); + CU_ASSERT_FATAL (strstr(hs->err_msg, fail_hs_req_msg) != NULL); + } + } + } + else if (hs->node_type == HSN_REPLIER) + { + CU_ASSERT_EQUAL_FATAL (hs->finalResult, exp_fail_hs_reply ? DDS_SECURITY_VALIDATION_FAILED : exp_result); + if (exp_fail_hs_reply) + { + if (fail_hs_reply_msg == NULL) + { + CU_ASSERT_EQUAL_FATAL (hs->err_msg, NULL); + } + else + { + CU_ASSERT_FATAL (hs->err_msg != NULL); + CU_ASSERT_FATAL (strstr(hs->err_msg, fail_hs_reply_msg) != NULL); + } + } + } } +CU_Theory((const char * test_descr, const char * id2, const char *key2, const char *ca2, + bool exp_fail_pp1, bool exp_fail_pp2, + bool exp_fail_local, const char * fail_local_msg, + bool exp_fail_hs_req, const char * fail_hs_req_msg, + bool exp_fail_hs_reply, const char * fail_hs_reply_msg), + ddssec_authentication, id_ca_certs) +{ + struct Handshake *hs_list; + int nhs; + printf("running test id_ca_certs: %s\n", test_descr); + authentication_init (ID1, ID1K, CA1, id2, key2, ca2, NULL, NULL, exp_fail_pp1, exp_fail_pp2); + + // Domain 1 + validate_handshake (DDS_DOMAINID1, false, NULL, &hs_list, &nhs); + for (int n = 0; n < nhs; n++) + validate_hs (&hs_list[n], exp_fail_hs_req, fail_hs_req_msg, exp_fail_hs_reply, fail_hs_reply_msg); + handshake_list_fini (hs_list, nhs); + + // Domain 2 + validate_handshake (DDS_DOMAINID2, exp_fail_local, fail_local_msg, &hs_list, &nhs); + for (int n = 0; n < nhs; n++) + validate_hs (&hs_list[n], exp_fail_hs_req, fail_hs_req_msg, exp_fail_hs_reply, fail_hs_reply_msg); + handshake_list_fini (hs_list, nhs); + + authentication_fini (!exp_fail_pp1, !exp_fail_pp2); +} CU_TheoryDataPoints(ddssec_authentication, trusted_ca_dir) = { CU_DataPoints(const char *, "", ".", "/nonexisting", NULL), CU_DataPoints(bool, false, false, true, false) }; - CU_Theory((const char * ca_dir, bool exp_fail), ddssec_authentication, trusted_ca_dir) { printf("Testing custom CA dir: %s\n", ca_dir); - authentication_init (false, ca_dir, exp_fail); + authentication_init (ID1, ID1K, CA1, ID1, ID1K, CA1, ca_dir, NULL, exp_fail, exp_fail); if (!exp_fail) { - validate_handshake (DDS_DOMAINID1, false, NULL, false, NULL); - validate_handshake (DDS_DOMAINID2, false, NULL, false, NULL); + validate_handshake_nofail (DDS_DOMAINID1); + validate_handshake_nofail (DDS_DOMAINID2); } - authentication_fini (!exp_fail); + authentication_fini (!exp_fail, !exp_fail); } + +#define M(n) ((n)*60) +#define H(n) (M(n)*60) +#define D(n) (H(n)*24) +CU_TheoryDataPoints(ddssec_authentication, expired_cert) = { + CU_DataPoints(const char *, + /* */"all valid 1d", + /* | */"ca expired", + /* | | */"id1 expired", + /* | | | */"id2 expired", + /* | | | | */"ca and id1 1min valid", + /* | | | | | */"id1 and id2 1s valid, delay 1100ms", + /* | | | | | | */"id1 valid after 1s, delay 1100ms", + /* | | | | | | | *//*"ca and id1 expire during session"*/), + CU_DataPoints(int32_t, 0, -M(1), 0, 0, 0, 0, 0, /*0*/ ), /* CA1 not before */ + CU_DataPoints(int32_t, D(1), 0, D(1), D(1), M(1), D(1), D(1), /*2*/ ), /* CA1 not after */ + CU_DataPoints(int32_t, 0, 0, -D(1), 0, 0, 0, 1, /*0*/ ), /* ID1 not before */ + CU_DataPoints(int32_t, D(1), D(1), 0, D(1), M(1), 1, D(1), /*2*/ ), /* ID1 not after */ + CU_DataPoints(bool, false, true, true, false, false, true, false, /*false*/ ), /* expect validate local ID1 fail */ + CU_DataPoints(int32_t, 0, 0, 0, -D(1), 0, 0, 0, /*0*/ ), /* ID2 not before */ + CU_DataPoints(int32_t, D(1), D(1), D(1), 0, D(1), 1, D(1), /*D(1)*/ ), /* ID2 not after */ + CU_DataPoints(bool, false, true, false, true, false, true, false, /*false*/ ), /* expect validate local ID2 fail */ + CU_DataPoints(uint32_t, 0, 0, 0, 0, 0, 1100, 1100, /*0*/ ), /* delay (ms) after generating certificate */ + CU_DataPoints(uint32_t, 1, 0, 0, 0, 1, 0, 1, /*3500*/ ), /* write/read data during x ms */ + CU_DataPoints(bool, false, false, false, false, false, false, false, /*true*/ ), /* expect read data failure */ +}; +CU_Theory( + (const char * test_descr, int32_t ca_not_before, int32_t ca_not_after, + int32_t id1_not_before, int32_t id1_not_after, bool id1_local_fail, + int32_t id2_not_before, int32_t id2_not_after, bool id2_local_fail, + uint32_t delay, uint32_t write_read_dur, bool exp_read_fail), + ddssec_authentication, expired_cert) +{ + char *ca, *id1, *id2, *id1_subj, *id2_subj; + printf("running test expired_cert: %s\n", test_descr); + ca = generate_ca ("ca1", CA1K, ca_not_before, ca_not_after); + id1 = generate_identity (ca, CA1K, "id1", ID1K, id1_not_before, id1_not_after, &id1_subj); + id2 = generate_identity (ca, CA1K, "id2", ID1K, id2_not_before, id2_not_after, &id2_subj); + dds_sleepfor (DDS_MSECS (delay)); + + char * grants[] = { get_permissions_grant ("id1", id1_subj), get_permissions_grant ("id2", id2_subj) }; + char * perm_config = get_permissions_config (grants, 2, true); + authentication_init (id1, ID1K, ca, id2, ID1K, ca, NULL, perm_config, id1_local_fail, id2_local_fail); + validate_handshake (DDS_DOMAINID1, id1_local_fail, NULL, NULL, NULL); + validate_handshake (DDS_DOMAINID2, id2_local_fail, NULL, NULL, NULL); + if (write_read_dur > 0) + write_read (DDS_MSECS (write_read_dur), false, exp_read_fail); + authentication_fini (!id1_local_fail, !id2_local_fail); + ddsrt_free (grants[0]); + ddsrt_free (grants[1]); + ddsrt_free (perm_config); + ddsrt_free (ca); + ddsrt_free (id1_subj); + ddsrt_free (id2_subj); + ddsrt_free (id1); + ddsrt_free (id2); +} +#undef D +#undef H +#undef M + diff --git a/src/security/core/tests/common/cert_utils.c b/src/security/core/tests/common/cert_utils.c new file mode 100644 index 0000000..f2e7386 --- /dev/null +++ b/src/security/core/tests/common/cert_utils.c @@ -0,0 +1,142 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/string.h" +#include "CUnit/Test.h" +#include "cert_utils.h" + +#define MAX_EMAIL 255 +#define EMAIL_HOST "cycloneddssecurity.adlinktech.com" + +static X509 * get_x509(int not_valid_before, int not_valid_after, const char * cn, const char * email) +{ + X509 * cert = X509_new (); + CU_ASSERT_FATAL (cert != NULL); + ASN1_INTEGER_set (X509_get_serialNumber (cert), 1); + X509_gmtime_adj (X509_get_notBefore (cert), not_valid_before); + X509_gmtime_adj (X509_get_notAfter (cert), not_valid_after); + + X509_NAME * name = X509_get_subject_name (cert); + X509_NAME_add_entry_by_txt (name, "C", MBSTRING_ASC, (unsigned char *) "NL", -1, -1, 0); + X509_NAME_add_entry_by_txt (name, "O", MBSTRING_ASC, (unsigned char *) "Example Organization", -1, -1, 0); + X509_NAME_add_entry_by_txt (name, "CN", MBSTRING_ASC, (unsigned char *) cn, -1, -1, 0); + X509_NAME_add_entry_by_txt (name, "emailAddress", MBSTRING_ASC, (unsigned char *) email, -1, -1, 0); + return cert; +} + +static char * get_x509_data(X509 * cert) +{ + // Create BIO for writing output + BIO *output_bio = BIO_new (BIO_s_mem ()); + if (!PEM_write_bio_X509 (output_bio, cert)) { + printf ("Error writing certificate\n"); + CU_ASSERT_FATAL (false); + } + + // Get string + char *output_tmp = NULL; + size_t output_sz = (size_t) BIO_get_mem_data (output_bio, &output_tmp); + char * output = ddsrt_malloc (output_sz + 1); + memcpy (output, output_tmp, output_sz); + output[output_sz] = 0; + BIO_free (output_bio); + + return output; +} + +static EVP_PKEY * get_priv_key(const char * priv_key_str) +{ + BIO *pkey_bio = BIO_new_mem_buf (priv_key_str, -1); + EVP_PKEY *priv_key = PEM_read_bio_PrivateKey (pkey_bio, NULL, NULL, 0); + CU_ASSERT_FATAL (priv_key != NULL); + BIO_free (pkey_bio); + return priv_key; +} + +static X509 * get_cert(const char * cert_str) +{ + BIO *cert_bio = BIO_new_mem_buf (cert_str, -1); + X509 *cert = PEM_read_bio_X509 (cert_bio, NULL, NULL, 0); + CU_ASSERT_FATAL (cert != NULL); + BIO_free (cert_bio); + return cert; +} + +char * generate_ca(const char *ca_name, const char * ca_priv_key_str, int not_valid_before, int not_valid_after) +{ + EVP_PKEY *ca_priv_key = get_priv_key (ca_priv_key_str); + + char * email = malloc (MAX_EMAIL); + snprintf(email, MAX_EMAIL, "%s@%s" , ca_name, EMAIL_HOST); + X509 * ca_cert = get_x509 (not_valid_before, not_valid_after, ca_name, email); + ddsrt_free (email); + + X509_set_pubkey (ca_cert, ca_priv_key); + X509_set_issuer_name (ca_cert, X509_get_subject_name (ca_cert)); /* self-signed */ + X509_sign (ca_cert, ca_priv_key, EVP_sha1 ()); + char * output = get_x509_data (ca_cert); + + EVP_PKEY_free (ca_priv_key); + X509_free (ca_cert); + + return output; +} + +char * generate_identity(const char * ca_cert_str, const char * ca_priv_key_str, const char * name, const char * priv_key_str, int not_valid_before, int not_valid_after, char ** subject) +{ + X509 *ca_cert = get_cert (ca_cert_str); + EVP_PKEY *ca_key_pkey = get_priv_key (ca_priv_key_str); + EVP_PKEY *id_pkey = get_priv_key (priv_key_str); + EVP_PKEY *ca_cert_pkey = X509_get_pubkey (ca_cert); + X509_REQ *csr = X509_REQ_new (); + X509_REQ_set_pubkey (csr, id_pkey); + X509_REQ_sign (csr, id_pkey, EVP_sha256 ()); + + char * email = malloc (MAX_EMAIL); + snprintf(email, MAX_EMAIL, "%s@%s" , name, EMAIL_HOST); + X509 * cert = get_x509 (not_valid_before, not_valid_after, name, email); + ddsrt_free (email); + + EVP_PKEY *csr_pkey = X509_REQ_get_pubkey (csr); + X509_set_pubkey (cert, csr_pkey); + X509_set_issuer_name (cert, X509_get_subject_name (ca_cert)); + X509_sign (cert, ca_key_pkey, EVP_sha256 ()); + char * output = get_x509_data (cert); + + if (subject) + { + X509_NAME *subj_name = X509_get_subject_name (cert); + char * subj_openssl = X509_NAME_oneline (subj_name, NULL, 0); + *subject = ddsrt_strdup (subj_openssl); + OPENSSL_free (subj_openssl); + } + + X509_REQ_free (csr); + EVP_PKEY_free (id_pkey); + EVP_PKEY_free (ca_cert_pkey); + EVP_PKEY_free (ca_key_pkey); + EVP_PKEY_free (csr_pkey); + X509_free (cert); + X509_free (ca_cert); + + return output; +} diff --git a/src/security/core/tests/common/cert_utils.h b/src/security/core/tests/common/cert_utils.h new file mode 100644 index 0000000..f6f9e92 --- /dev/null +++ b/src/security/core/tests/common/cert_utils.h @@ -0,0 +1,20 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef SECURITY_CORE_TEST_CERT_UTILS_H_ +#define SECURITY_CORE_TEST_CERT_UTILS_H_ + +#include + +char * generate_ca(const char *ca_name, const char * ca_priv_key_str, int not_valid_before, int not_valid_after); +char * generate_identity(const char * ca_cert_str, const char * ca_priv_key_str, const char * name, const char * priv_key_str, int not_valid_before, int not_valid_after, char ** subject); + +#endif /* SECURITY_CORE_TEST_CERT_UTILS_H_ */ diff --git a/src/security/core/tests/common/cryptography_wrapper.c b/src/security/core/tests/common/cryptography_wrapper.c index fcb3ed9..7af5c1b 100644 --- a/src/security/core/tests/common/cryptography_wrapper.c +++ b/src/security/core/tests/common/cryptography_wrapper.c @@ -56,9 +56,16 @@ struct dds_security_cryptography_impl { struct dds_security_crypto_key_factory_impl factory_wrap; struct dds_security_crypto_key_exchange_impl exchange_wrap; enum crypto_plugin_mode mode; + bool protection_kinds_set; + bool disc_protection_kinds_set; DDS_Security_ProtectionKind rtps_protection_kind; DDS_Security_ProtectionKind metadata_protection_kind; DDS_Security_BasicProtectionKind payload_protection_kind; + DDS_Security_ProtectionKind disc_protection_kind; + DDS_Security_ProtectionKind liveliness_protection_kind; + const char * pp_secret; + const char * groupdata_secret; + const char * ep_secret; const char * encrypted_secret; }; @@ -74,6 +81,7 @@ void set_protection_kinds( impl->rtps_protection_kind = rtps_protection_kind; impl->metadata_protection_kind = metadata_protection_kind; impl->payload_protection_kind = payload_protection_kind; + impl->protection_kinds_set = true; } void set_encrypted_secret(struct dds_security_cryptography_impl * impl, const char * secret) @@ -82,6 +90,25 @@ void set_encrypted_secret(struct dds_security_cryptography_impl * impl, const ch impl->encrypted_secret = secret; } +void set_disc_protection_kinds( + struct dds_security_cryptography_impl * impl, + DDS_Security_ProtectionKind disc_protection_kind, + DDS_Security_ProtectionKind liveliness_protection_kind) +{ + assert(impl); + impl->disc_protection_kind = disc_protection_kind; + impl->liveliness_protection_kind = liveliness_protection_kind; + impl->disc_protection_kinds_set = true; +} + +void set_entity_data_secret(struct dds_security_cryptography_impl * impl, const char * pp_secret, const char * groupdata_secret, const char * ep_secret) +{ + assert(impl); + impl->pp_secret = pp_secret; + impl->groupdata_secret = groupdata_secret; + impl->ep_secret = ep_secret; +} + static unsigned char * find_buffer_match(const unsigned char *input, size_t input_len, const unsigned char *match, size_t match_len) { if (match_len <= input_len && match_len > 0 && input_len > 0) @@ -434,9 +461,11 @@ static DDS_Security_boolean encode_serialized_payload( if (!impl->instance->encode_serialized_payload (impl->instance, encoded_buffer, extra_inline_qos, plain_buffer, check_handle (sending_datawriter_crypto), ex)) return false; - if (impl->parent->encrypted_secret && (impl->parent->payload_protection_kind == DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT - || expect_encrypted_buffer (impl->parent->metadata_protection_kind) - || expect_encrypted_buffer (impl->parent->rtps_protection_kind))) + if (impl->parent->protection_kinds_set + && impl->parent->encrypted_secret + && (impl->parent->payload_protection_kind == DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT + || expect_encrypted_buffer (impl->parent->metadata_protection_kind) + || expect_encrypted_buffer (impl->parent->rtps_protection_kind))) { if (find_buffer_match (encoded_buffer->_buffer, encoded_buffer->_length, (const unsigned char *) impl->parent->encrypted_secret, strlen (impl->parent->encrypted_secret)) != NULL) { @@ -445,7 +474,7 @@ static DDS_Security_boolean encode_serialized_payload( return false; } } - return check_buffers (encoded_buffer, plain_buffer, impl->parent->payload_protection_kind == DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT, ex); + return !impl->parent->protection_kinds_set || check_buffers (encoded_buffer, plain_buffer, impl->parent->payload_protection_kind == DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT, ex); } default: return true; @@ -458,16 +487,15 @@ static DDS_Security_boolean check_buffer_submsg( const DDS_Security_OctetSeq *plain_rtps_submessage, DDS_Security_SecurityException *ex) { - bool exp_enc = expect_encrypted_buffer (impl->parent->metadata_protection_kind) || expect_encrypted_buffer (impl->parent->rtps_protection_kind); - if (exp_enc - && impl->parent->encrypted_secret - && find_buffer_match (encoded_rtps_submessage->_buffer, encoded_rtps_submessage->_length, (const unsigned char *) impl->parent->encrypted_secret, strlen (impl->parent->encrypted_secret)) != NULL) + bool exp_enc = impl->parent->protection_kinds_set && (expect_encrypted_buffer (impl->parent->metadata_protection_kind) || expect_encrypted_buffer (impl->parent->rtps_protection_kind)); + if (exp_enc && impl->parent->encrypted_secret && find_buffer_match (encoded_rtps_submessage->_buffer, encoded_rtps_submessage->_length, (const unsigned char *) impl->parent->encrypted_secret, strlen (impl->parent->encrypted_secret)) != NULL) { ex->code = 1; ex->message = ddsrt_strdup ("Expect encryption, but found secret in submessage after encoding"); return false; } - return expect_encrypted_buffer (impl->parent->metadata_protection_kind) ? check_buffers (encoded_rtps_submessage, plain_rtps_submessage, true, ex) : true; + + return impl->parent->protection_kinds_set && expect_encrypted_buffer (impl->parent->metadata_protection_kind) ? check_buffers (encoded_rtps_submessage, plain_rtps_submessage, true, ex) : true; } static DDS_Security_boolean encode_datawriter_submessage( @@ -486,7 +514,33 @@ static DDS_Security_boolean encode_datawriter_submessage( if (!impl->instance->encode_datawriter_submessage (impl->instance, encoded_rtps_submessage, plain_rtps_submessage, check_handle (sending_datawriter_crypto), receiving_datareader_crypto_list, receiving_datareader_crypto_list_index, ex)) return false; - return check_buffer_submsg(impl, encoded_rtps_submessage, plain_rtps_submessage, ex); + if (!check_buffer_submsg(impl, encoded_rtps_submessage, plain_rtps_submessage, ex)) + return false; + + if (impl->parent->disc_protection_kinds_set && expect_encrypted_buffer (impl->parent->disc_protection_kind)) + { + if (impl->parent->pp_secret && find_buffer_match (plain_rtps_submessage->_buffer, plain_rtps_submessage->_length, (const unsigned char *) impl->parent->pp_secret, strlen (impl->parent->pp_secret)) != NULL) + { + ex->code = 1; + ex->message = ddsrt_strdup ("Expect discovery encryption, but found participant userdata secret in submessage after encoding"); + return false; + } + if (impl->parent->groupdata_secret && find_buffer_match (plain_rtps_submessage->_buffer, plain_rtps_submessage->_length, (const unsigned char *) impl->parent->groupdata_secret, strlen (impl->parent->groupdata_secret)) != NULL) + { + ex->code = 1; + ex->message = ddsrt_strdup ("Expect discovery encryption, but found publisher/subscriber groupdata secret in submessage after encoding"); + return false; + } + if (impl->parent->ep_secret && find_buffer_match (plain_rtps_submessage->_buffer, plain_rtps_submessage->_length, (const unsigned char *) impl->parent->ep_secret, strlen (impl->parent->ep_secret)) != NULL) + { + ex->code = 1; + ex->message = ddsrt_strdup ("Expect discovery encryption, but found reader/writer userdata secret in submessage after encoding"); + return false; + } + } + return true; + + default: return true; } @@ -529,7 +583,8 @@ static DDS_Security_boolean encode_rtps_message( if (!impl->instance->encode_rtps_message (impl->instance, encoded_rtps_message, plain_rtps_message, check_handle (sending_participant_crypto), receiving_participant_crypto_list, receiving_participant_crypto_list_index, ex)) return false; - if (impl->parent->encrypted_secret + if (impl->parent->protection_kinds_set + && impl->parent->encrypted_secret && expect_encrypted_buffer (impl->parent->rtps_protection_kind) && find_buffer_match (encoded_rtps_message->_buffer, encoded_rtps_message->_length, (const unsigned char *) impl->parent->encrypted_secret, strlen (impl->parent->encrypted_secret)) != NULL) { @@ -537,7 +592,7 @@ static DDS_Security_boolean encode_rtps_message( ex->message = ddsrt_strdup ("Expect encryption, but found secret in RTPS message after encoding"); return false; } - return expect_encrypted_buffer (impl->parent->rtps_protection_kind) ? + return impl->parent->protection_kinds_set && expect_encrypted_buffer (impl->parent->rtps_protection_kind) ? check_buffers (encoded_rtps_message, plain_rtps_message, true, ex) : true; default: return true; diff --git a/src/security/core/tests/common/cryptography_wrapper.h b/src/security/core/tests/common/cryptography_wrapper.h index 42ed1ef..44e0501 100644 --- a/src/security/core/tests/common/cryptography_wrapper.h +++ b/src/security/core/tests/common/cryptography_wrapper.h @@ -26,6 +26,13 @@ SECURITY_EXPORT void set_protection_kinds( SECURITY_EXPORT void set_encrypted_secret(struct dds_security_cryptography_impl * impl, const char * secret); +SECURITY_EXPORT void set_disc_protection_kinds( + struct dds_security_cryptography_impl * impl, + DDS_Security_ProtectionKind disc_protection_kind, + DDS_Security_ProtectionKind liveliness_protection_kind); + +SECURITY_EXPORT void set_entity_data_secret(struct dds_security_cryptography_impl * impl, const char * pp_secret, const char * groupdata_secret, const char * ep_secret); + /* Init in all-ok mode: all functions return success without calling the actual plugin */ SECURITY_EXPORT int32_t init_test_cryptography_all_ok(const char *argument, void **context); SECURITY_EXPORT int32_t finalize_test_cryptography_all_ok(void *context); diff --git a/src/security/core/tests/common/handshake_test_utils.c b/src/security/core/tests/common/handshake_test_utils.c index 6d2e494..6385de2 100644 --- a/src/security/core/tests/common/handshake_test_utils.c +++ b/src/security/core/tests/common/handshake_test_utils.c @@ -31,6 +31,33 @@ int numRemote = 0; struct Handshake handshakeList[MAX_HANDSHAKES]; int numHandshake = 0; +static char * get_validation_result_str(DDS_Security_ValidationResult_t result) +{ + switch (result) + { + case DDS_SECURITY_VALIDATION_OK: return "OK"; + case DDS_SECURITY_VALIDATION_PENDING_RETRY: return "PENDING_RETRY"; + case DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_REQUEST: return "PENDING_HANDSHAKE_REQUEST"; + case DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE: return "PENDING_HANDSHAKE_MESSAGE"; + case DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE: return "OK_FINAL_MESSAGE"; + case DDS_SECURITY_VALIDATION_FAILED: return "FAILED"; + } + abort (); + return ""; +} + +static char * get_node_type_str(enum hs_node_type node_type) +{ + switch (node_type) + { + case HSN_UNDEFINED: return "UNDEFINED"; + case HSN_REQUESTER: return "REQUESTER"; + case HSN_REPLIER: return "REPLIER"; + } + abort (); + return ""; +} + static void add_local_identity(DDS_Security_IdentityHandle handle, DDS_Security_GUID_t *guid) { printf("add local identity %"PRId64"\n", handle); @@ -77,16 +104,18 @@ static void clear_stores(void) numHandshake = 0; } -static void add_handshake(DDS_Security_HandshakeHandle handle, int isRequest, DDS_Security_IdentityHandle lHandle, DDS_Security_IdentityHandle rHandle, DDS_Security_ValidationResult_t result) +static struct Handshake *add_handshake(enum hs_node_type node_type, DDS_Security_IdentityHandle lHandle, DDS_Security_IdentityHandle rHandle) { - printf("add handshake %"PRId64"\n", handle); - handshakeList[numHandshake].handle = handle; - handshakeList[numHandshake].isRequest = isRequest; - handshakeList[numHandshake].handshakeResult = result; + printf("add handshake %"PRId64"-%"PRId64"\n", lHandle, rHandle); + handshakeList[numHandshake].handle = -1; + handshakeList[numHandshake].node_type = node_type; + handshakeList[numHandshake].handshakeResult = DDS_SECURITY_VALIDATION_FAILED; handshakeList[numHandshake].lidx = find_local_identity(lHandle); handshakeList[numHandshake].ridx = find_remote_identity(rHandle); handshakeList[numHandshake].finalResult = DDS_SECURITY_VALIDATION_FAILED; + handshakeList[numHandshake].err_msg = NULL; numHandshake++; + return &handshakeList[numHandshake - 1]; } static int find_handshake(DDS_Security_HandshakeHandle handle) @@ -99,134 +128,144 @@ static int find_handshake(DDS_Security_HandshakeHandle handle) return -1; } -static char * get_validation_result_str(DDS_Security_ValidationResult_t result) -{ - switch (result) - { - case DDS_SECURITY_VALIDATION_OK: - return "ok"; - case DDS_SECURITY_VALIDATION_PENDING_RETRY: - return "pending retry"; - case DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_REQUEST: - return "handshake request"; - case DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE: - return "handshake message"; - case DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE: - return "ok final"; - default: - case DDS_SECURITY_VALIDATION_FAILED: - return "failed"; - } -} - -static bool handle_process_message(dds_domainid_t domain_id, DDS_Security_IdentityHandle handshake) +static void handle_process_message(dds_domainid_t domain_id, DDS_Security_IdentityHandle handshake) { struct message *msg; - bool result = false; if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_PROCESS_HANDSHAKE, 0, 0, handshake, TIMEOUT))) { int idx; if ((idx = find_handshake(msg->hsHandle)) >= 0) { - printf("set handshake %"PRId64" final result to '%s'\n", msg->hsHandle, get_validation_result_str(msg->result)); + printf("set handshake %"PRId64" final result to '%s' (errmsg: %s)\n", msg->hsHandle, get_validation_result_str(msg->result), msg->err_msg); handshakeList[idx].finalResult = msg->result; - result = true; + handshakeList[idx].err_msg = ddsrt_strdup (msg->err_msg); } test_authentication_plugin_release_msg(msg); } - return result; } -static bool handle_begin_handshake_request(dds_domainid_t domain_id, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid, char ** err_msg) +static void handle_begin_handshake_request(dds_domainid_t domain_id, struct Handshake *hs, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid) { struct message *msg; - bool result = false; printf("handle begin handshake request %"PRId64"<->%"PRId64"\n", lid, rid); if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REQUEST, lid, rid, 0, TIMEOUT))) { - add_handshake(msg->hsHandle, 1, msg->lidHandle, msg->ridHandle, msg->result); + hs->handle = msg->hsHandle; + hs->handshakeResult = msg->result; if (msg->result != DDS_SECURITY_VALIDATION_FAILED) - result = handle_process_message(domain_id, msg->hsHandle); - else if (err_msg) - *err_msg = ddsrt_strdup (msg->err_msg); + handle_process_message(domain_id, msg->hsHandle); + else + hs->err_msg = ddsrt_strdup (msg->err_msg); test_authentication_plugin_release_msg(msg); } - return result; } -static bool handle_begin_handshake_reply(dds_domainid_t domain_id, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid, char ** err_msg) +static void handle_begin_handshake_reply(dds_domainid_t domain_id, struct Handshake *hs, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid) { struct message *msg; - bool result = false; printf("handle begin handshake reply %"PRId64"<->%"PRId64"\n", lid, rid); if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REPLY, lid, rid, 0, TIMEOUT))) { - add_handshake(msg->hsHandle, 0, msg->lidHandle, msg->ridHandle, msg->result); + hs->handle = msg->hsHandle; + hs->handshakeResult = msg->result; if (msg->result != DDS_SECURITY_VALIDATION_FAILED) - result = handle_process_message(domain_id, msg->hsHandle); - else if (err_msg) - *err_msg = ddsrt_strdup (msg->err_msg); + handle_process_message(domain_id, msg->hsHandle); + else + hs->err_msg = ddsrt_strdup (msg->err_msg); test_authentication_plugin_release_msg(msg); } - return result; } -static bool handle_validate_remote_identity(dds_domainid_t domain_id, DDS_Security_IdentityHandle lid, int count, bool * is_hs_requester, char ** err_msg_req, char ** err_msg_reply) +static void handle_validate_remote_identity(dds_domainid_t domain_id, DDS_Security_IdentityHandle lid, int count) { - bool result = true; struct message *msg; - assert(is_hs_requester); - while (count-- > 0 && result && (msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_VALIDATE_REMOTE_IDENTITY, lid, 0, 0, TIMEOUT))) + while (count-- > 0 && (msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_VALIDATE_REMOTE_IDENTITY, lid, 0, 0, TIMEOUT))) { + struct Handshake *hs; add_remote_identity(msg->ridHandle, &msg->rguid); + hs = add_handshake(HSN_UNDEFINED, lid, msg->ridHandle); if (msg->result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_REQUEST) { - result = handle_begin_handshake_request(domain_id, lid, msg->ridHandle, err_msg_req); - *is_hs_requester = true; + hs->node_type = HSN_REQUESTER; + handle_begin_handshake_request(domain_id, hs, lid, msg->ridHandle); } else if (msg->result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE) { - result = handle_begin_handshake_reply(domain_id, lid, msg->ridHandle, err_msg_reply); - *is_hs_requester = false; + hs->node_type = HSN_REPLIER; + handle_begin_handshake_reply(domain_id, hs, lid, msg->ridHandle); } else - result = false; - + { + printf("validate remote failed\n"); + } test_authentication_plugin_release_msg(msg); } - return result; } -void validate_handshake(dds_domainid_t domain_id, bool exp_req_fail, const char * exp_req_msg, bool exp_reply_fail, const char * exp_reply_msg) +static void handle_validate_local_identity(dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg) +{ + struct message *msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_VALIDATE_LOCAL_IDENTITY, 0, 0, 0, TIMEOUT); + CU_ASSERT_FATAL (msg != NULL); + CU_ASSERT_FATAL ((msg->result == DDS_SECURITY_VALIDATION_OK) != exp_localid_fail); + if (exp_localid_fail && exp_localid_msg) + { + printf("validate_local_identity failed as expected (msg: %s)\n", msg->err_msg); + CU_ASSERT_FATAL (msg->err_msg && strstr(msg->err_msg, exp_localid_msg) != NULL); + } + else + add_local_identity (msg->lidHandle, &msg->lguid); + test_authentication_plugin_release_msg (msg); +} + +void validate_handshake(dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg, struct Handshake *hs_list[], int *nhs) { - printf("validate handshake for domain %d\n", domain_id); clear_stores(); - struct message *msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_VALIDATE_LOCAL_IDENTITY, 0, 0, 0, TIMEOUT); - CU_ASSERT_FATAL (msg != NULL); - add_local_identity (msg->lidHandle, &msg->lguid); - test_authentication_plugin_release_msg (msg); - bool is_requester = false; - char * err_msg_req = NULL, *err_msg_reply = NULL; - bool ret = handle_validate_remote_identity (domain_id, localIdentityList[0].handle, 1, &is_requester, &err_msg_req, &err_msg_reply); - CU_ASSERT_FATAL ((is_requester && ret != exp_req_fail) || (!is_requester && ret != exp_reply_fail)); - if (ret) + if (nhs) + *nhs = 0; + if (hs_list) + *hs_list = NULL; + + handle_validate_local_identity(domain_id, exp_localid_fail, exp_localid_msg); + if (!exp_localid_fail) { - DDS_Security_ValidationResult_t exp_result = is_requester ? DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE : DDS_SECURITY_VALIDATION_OK; - CU_ASSERT_EQUAL_FATAL (handshakeList[0].finalResult, exp_result); + handle_validate_remote_identity (domain_id, localIdentityList[0].handle, 1); + for (int n = 0; n < numHandshake; n++) + { + struct Handshake *hs = &handshakeList[n]; + printf("Result: hs %"PRId64", node type %s, final result %s\n", hs->handle, get_node_type_str(hs->node_type), get_validation_result_str(hs->finalResult)); + if (hs->err_msg && strlen (hs->err_msg)) + printf("- err_msg: %s\n", hs->err_msg); + } + if (nhs) + *nhs = numHandshake; + if (hs_list) + *hs_list = handshakeList; + else + handshake_list_fini(handshakeList, numHandshake); } - else if (is_requester && exp_req_msg) - { - CU_ASSERT_FATAL (err_msg_req && strstr(err_msg_req, exp_req_msg) != NULL); - } - else if (!is_requester && exp_reply_msg) - { - CU_ASSERT_FATAL (err_msg_reply && strstr(err_msg_reply, exp_reply_msg) != NULL); - } - if (err_msg_req) - ddsrt_free (err_msg_req); - if (err_msg_reply) - ddsrt_free (err_msg_reply); printf ("finished validate handshake for domain %d\n\n", domain_id); } +void validate_handshake_nofail (dds_domainid_t domain_id) +{ + struct Handshake *hs_list; + int nhs; + validate_handshake (domain_id, false, NULL, &hs_list, &nhs); + for (int n = 0; n < nhs; n++) + { + struct Handshake hs = hs_list[n]; + DDS_Security_ValidationResult_t exp_result = hs.node_type == HSN_REQUESTER ? DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE : DDS_SECURITY_VALIDATION_OK; + CU_ASSERT_EQUAL_FATAL (hs.finalResult, exp_result); + } + handshake_list_fini (hs_list, nhs); +} + +void handshake_list_fini(struct Handshake *hs_list, int nhs) +{ + for (int n = 0; n < nhs; n++) + { + struct Handshake hs = hs_list[n]; + ddsrt_free (hs.err_msg); + } +} \ No newline at end of file diff --git a/src/security/core/tests/common/handshake_test_utils.h b/src/security/core/tests/common/handshake_test_utils.h index 9ca8afb..0ae3a59 100644 --- a/src/security/core/tests/common/handshake_test_utils.h +++ b/src/security/core/tests/common/handshake_test_utils.h @@ -27,6 +27,13 @@ union guid { unsigned u[4]; }; +enum hs_node_type +{ + HSN_UNDEFINED, + HSN_REQUESTER, + HSN_REPLIER +}; + struct Identity { DDS_Security_IdentityHandle handle; @@ -36,13 +43,16 @@ struct Identity struct Handshake { DDS_Security_HandshakeHandle handle; - int isRequest; + enum hs_node_type node_type; int lidx; int ridx; DDS_Security_ValidationResult_t handshakeResult; DDS_Security_ValidationResult_t finalResult; + char * err_msg; }; -void validate_handshake(dds_domainid_t domain_id, bool exp_req_fail, const char * exp_req_msg, bool exp_reply_fail, const char * exp_reply_msg); +void validate_handshake(dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg, struct Handshake *hs_list[], int *nhs); +void validate_handshake_nofail (dds_domainid_t domain_id); +void handshake_list_fini(struct Handshake *hs_list, int nhs); #endif /* SECURITY_CORE_HANDSHAKE_TEST_UTILS_H_ */ diff --git a/src/security/core/tests/common/security_config_test_utils.c b/src/security/core/tests/common/security_config_test_utils.c index c6e939b..ef9f0f8 100644 --- a/src/security/core/tests/common/security_config_test_utils.c +++ b/src/security/core/tests/common/security_config_test_utils.c @@ -25,6 +25,7 @@ #include "dds/ddsrt/expand_vars.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" +#include "dds/ddsrt/io.h" #include "common/config_env.h" #include "security_config_test_utils.h" @@ -59,6 +60,33 @@ static const char *governance_xml = " " ""; +static const char *permissions_xml_grant = + " " + " ${SUBJECT_NAME}" + " 2015-09-15T01:00:002115-09-15T01:00:00" + " " + " 0230" + " " + " *" + " *" + " " + " " + " *" + " *" + " " + " " + " DENY" + " "; + +static const char *permissions_xml = + "" + "" + " " + " ${GRANTS}" + " " + ""; + + const char * expand_lookup_vars(const char *name, void * data) { struct kvp *vars = (struct kvp *)data; @@ -157,18 +185,59 @@ static char * smime_sign(char * ca_cert_path, char * ca_priv_key_path, const cha return output; } -static char *get_signed_governance_data(const char *gov_xml) +static char *get_signed_data(const char *data) { return smime_sign ( COMMON_ETC_PATH("default_permissions_ca.pem"), COMMON_ETC_PATH("default_permissions_ca_key.pem"), - gov_xml); + data); } -char * get_governance_config(struct kvp *config_vars) +static char * prefix_data (char * config_signed, bool add_prefix) { - char * config = ddsrt_expand_vars(governance_xml, &expand_lookup_vars, config_vars); - char * config_signed = get_signed_governance_data(config); - ddsrt_free (config); + if (add_prefix) + { + char * tmp = config_signed; + ddsrt_asprintf (&config_signed, "data:,%s", tmp); + ddsrt_free (tmp); + } return config_signed; } + +char * get_governance_config(struct kvp *config_vars, bool add_prefix) +{ + char * config = ddsrt_expand_vars (governance_xml, &expand_lookup_vars, config_vars); + char * config_signed = get_signed_data (config); + ddsrt_free (config); + return prefix_data (config_signed, add_prefix); +} + +char * get_permissions_grant(const char * name, const char * subject) +{ + struct kvp vars[] = { + { "GRANT_NAME", name, 1 }, + { "SUBJECT_NAME", subject, 1 }, + { NULL, NULL, 0 } + }; + return ddsrt_expand_vars (permissions_xml_grant, &expand_lookup_vars, vars); +} + +char * get_permissions_config(char * grants[], size_t ngrants, bool add_prefix) +{ + char *grants_str = NULL; + for (size_t n = 0; n < ngrants; n++) + { + char * tmp = grants_str; + ddsrt_asprintf (&grants_str, "%s%s", grants_str ? grants_str : "", grants[n]); + ddsrt_free (tmp); + } + struct kvp vars[] = { + { "GRANTS", grants_str, 1 }, + { NULL, NULL, 0} + }; + char *config = ddsrt_expand_vars (permissions_xml, &expand_lookup_vars, vars); + char *config_signed = get_signed_data (config); + ddsrt_free (grants_str); + ddsrt_free (config); + return prefix_data (config_signed, add_prefix); +} diff --git a/src/security/core/tests/common/security_config_test_utils.h b/src/security/core/tests/common/security_config_test_utils.h index ab14b7f..056b4d5 100644 --- a/src/security/core/tests/common/security_config_test_utils.h +++ b/src/security/core/tests/common/security_config_test_utils.h @@ -25,6 +25,8 @@ const char * expand_lookup_vars (const char *name, void * data); const char * expand_lookup_vars_env (const char *name, void * data); int32_t expand_lookup_unmatched (const struct kvp * lookup_table); -char * get_governance_config (struct kvp *config_vars); +char * get_governance_config (struct kvp *config_vars, bool add_prefix); +char * get_permissions_grant(const char * name, const char * subject); +char * get_permissions_config(char * grants[], size_t ngrants, bool add_prefix); #endif /* SECURITY_CORE_TEST_SECURITY_CONFIG_TEST_UTILS_H_ */ diff --git a/src/security/core/tests/common/test_identity.h b/src/security/core/tests/common/test_identity.h index 2fbcd3b..30bb916 100644 --- a/src/security/core/tests/common/test_identity.h +++ b/src/security/core/tests/common/test_identity.h @@ -17,7 +17,178 @@ #define TEST_IDENTITY_PRIVATE_KEY_DUMMY "testtext_PrivateKey_testtext" #define TEST_IDENTITY_CA_CERTIFICATE_DUMMY "testtext_IdentityCA_testtext" -#define TEST_IDENTITY_CERTIFICATE "data:,-----BEGIN CERTIFICATE-----\n\ +// Identity CAs +#define TEST_IDENTITY_CA1_CERTIFICATE "-----BEGIN CERTIFICATE-----\n\ +MIIEYzCCA0ugAwIBAgIUOp5yaGGuh0vaQTZHVPkX5jHoc/4wDQYJKoZIhvcNAQEL\n\ +BQAwgcAxCzAJBgNVBAYTAk5MMQswCQYDVQQIDAJPVjEWMBQGA1UEBwwNTG9jYWxp\n\ +dHkgTmFtZTETMBEGA1UECwwKRXhhbXBsZSBPVTEjMCEGA1UECgwaRXhhbXBsZSBJ\n\ +RCBDQSBPcmdhbml6YXRpb24xFjAUBgNVBAMMDUV4YW1wbGUgSUQgQ0ExOjA4Bgkq\n\ +hkiG9w0BCQEWK2F1dGhvcml0eUBjeWNsb25lZGRzc2VjdXJpdHkuYWRsaW5rdGVj\n\ +aC5jb20wHhcNMjAwMjI3MTkyMjA1WhcNMzAwMjI0MTkyMjA1WjCBwDELMAkGA1UE\n\ +BhMCTkwxCzAJBgNVBAgMAk9WMRYwFAYDVQQHDA1Mb2NhbGl0eSBOYW1lMRMwEQYD\n\ +VQQLDApFeGFtcGxlIE9VMSMwIQYDVQQKDBpFeGFtcGxlIElEIENBIE9yZ2FuaXph\n\ +dGlvbjEWMBQGA1UEAwwNRXhhbXBsZSBJRCBDQTE6MDgGCSqGSIb3DQEJARYrYXV0\n\ +aG9yaXR5QGN5Y2xvbmVkZHNzZWN1cml0eS5hZGxpbmt0ZWNoLmNvbTCCASIwDQYJ\n\ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBALKhk7JXUpqJphyOC6oOI00LH49WTtO2\n\ +GCgDyJhcRYYAm7APMtmEDH+zptvd34N4eSu03Dc65cB/XN4Lbi2TjolVvKz0hHjz\n\ +tzmQT5jTgb1UkJX4NjKGw+RrYe9Ls0kfoAL2kvb12kmd1Oj4TIKMZP9TCrz7Vw8m\n\ +cZKQxZ56bLys6cU2XdiTp3v+Ef/vMll4+DINj4ZAMWL3CkT+q1G6ZxHRpFlsIyhc\n\ +Q1wX6gxUoY6cQdBA7TehKCCEWz4L1KM1A18ZmCHmjTniU0ssLoiAzsQs4b6Fnw8Z\n\ +MLFj8ocwzN5g66gJJWGofakXqX/V24KbGl54WX2X7FYU0tGzR234DXcCAwEAAaNT\n\ +MFEwHQYDVR0OBBYEFGeCcK8B74QWCuuCjlSUzOBBUTF5MB8GA1UdIwQYMBaAFGeC\n\ +cK8B74QWCuuCjlSUzOBBUTF5MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL\n\ +BQADggEBAJQeMc4XzMFnpQKCb58rzRs3Wt9FmZZS4O596sHxMEewTkEHm5gLYMzF\n\ +9JYEdUiLoTurQuIr0KgPi+Q3kliQdLfrVPbdWTmlUDZARR5ir5d1gGHST6qnb3Xi\n\ +mG+7nwle9R/hLrtPio+gYRgwJEiS55f6p0/E1wDcc+6numvjCRQ/CGIiJfwD/R+d\n\ +pv93YLEfuliZttfBc/apIu6OL4chxF+3QgSw1ltV5nXXqDTGHMRZENkp3Yiolumc\n\ +6smL4uA7Q812pVcENi3MLjdJgBS/8DcSBQHspVuXugaKKPDMkJnD0IyLWc8vLXh4\n\ +O7JdDrmusJAZA9RsTkinl3DuPfF34Sk=\n\ +-----END CERTIFICATE-----" + +#define TEST_IDENTITY_CA1_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n\ +MIIEowIBAAKCAQEAsqGTsldSmommHI4Lqg4jTQsfj1ZO07YYKAPImFxFhgCbsA8y\n\ +2YQMf7Om293fg3h5K7TcNzrlwH9c3gtuLZOOiVW8rPSEePO3OZBPmNOBvVSQlfg2\n\ +MobD5Gth70uzSR+gAvaS9vXaSZ3U6PhMgoxk/1MKvPtXDyZxkpDFnnpsvKzpxTZd\n\ +2JOne/4R/+8yWXj4Mg2PhkAxYvcKRP6rUbpnEdGkWWwjKFxDXBfqDFShjpxB0EDt\n\ +N6EoIIRbPgvUozUDXxmYIeaNOeJTSywuiIDOxCzhvoWfDxkwsWPyhzDM3mDrqAkl\n\ +Yah9qRepf9XbgpsaXnhZfZfsVhTS0bNHbfgNdwIDAQABAoIBAAylo+9cf1yxojEj\n\ +XXAM0DMENpfPZIVYvx0WJ32iCsoSAPPWH6OG1du0vHuUmd6VCP8vLug6I0odulV+\n\ +Oa7AY7cVeuZD6Z0mpDJPJVOMpgLhmdsEV9H7+KKTd7uZgHgM5SdQjdcuUOYlZo2Y\n\ +BtK3Xe810ezPXrqT3jaiSVuPD2PMO/LH3S+MSynHUZdou+NEr0S5FyX7HT2SUvPg\n\ +nEG5KUSE32/1Rnho9BacWKQ/HAoBiS+jMRHOPwu1Q/qS/QLw8HRDEuEoXlVYoNMc\n\ +il0r3M25COZVJVJecBqXHAWZqCBsqmNXs2hU1bh8VVKl/CMkG3W+IAR7XzMmw6bi\n\ +ZYAvgQECgYEA3pIeB8WptYv7hU0I1FZMfyhwLZDRSTZMlObTIXXsdSVKEllBwKAW\n\ +N0G84cyl7q+tOio63tbk1rQRi21O0wTrt16j+0SqDIYy59QhqXhiKAko+nf7cSpy\n\ +8h+k+HF5HpxsxcwYPiwO1SywPJ4TuDLIRHXXqschRzNtATrqCBtNeBsCgYEAzXX5\n\ +cQfMORsg0Z/K0d/U8JLdK0dnqsjwKt+9L7BAGOSv9Xxf4OT+vK3AlzkTUUOztXy7\n\ +3YzpSrHy1Dzu57Dv83BgCFPJxa7jKX4/n+SFYjqxcQVSziQAJjyaa0JsxYkxWC0K\n\ +IXg8MXYcgwHL6k/PYblQCJw8Lgtf8J2DtXhZTdUCgYAvt/4uRmfLX7bObqS8+b+u\n\ +55mde1YTr0ueBRsxKlpHB3apFm/tf6UjtblsY/cThKDMPq+ehU5M5hB45zemMIDl\n\ +MKpRvfgDdWZGpAmPjxrkYIpjoQPM0IASf0xcY9/G+1yqz8ZG1iVb+RfT90RdEq4z\n\ +V1yk5cqxvEnboKj6kff7DwKBgQCXnqbcVZ/MyIs4ho4awO4YNpkGNiR3cN9jFEc9\n\ +aPh0Jlb/drAee37M6AAG2LS7tJVqqcjNXw5N8/G509mNmxIH+Pa1TnfI7R1v4l27\n\ +dd1EtwF44S/RNdnyXaiq3JL+VxbV9i7SsjLhYUL7HplHqWvltuYr5He4luZO3z5x\n\ +7YUhnQKBgHmjhmSEPPxZLjPcYJ/z2opXalPJ5OObJ6nM6X4T5LvfhSnANdeeM6yj\n\ +gigRY8UlnNYzC5iSt17/VuMeta7I8GaVNUu7WU72Q7sYYlrXevdgl/0OFYayXHlB\n\ +sSo6yb9za+C2+5olHEZvs7dIzwDcveoEatds/X4VNrULEwaGbZR0\n\ +-----END RSA PRIVATE KEY-----" + +#define TEST_IDENTITY_CA2_CERTIFICATE "-----BEGIN CERTIFICATE-----\n\ +MIIEbTCCA1WgAwIBAgIUL0mSpPRgzveYTJ8UHSmOIwkIjjYwDQYJKoZIhvcNAQEL\n\ +BQAwgcUxCzAJBgNVBAYTAk5MMQswCQYDVQQIDAJPVjEWMBQGA1UEBwwNTG9jYWxp\n\ +dHkgTmFtZTETMBEGA1UECwwKRXhhbXBsZSBPVTElMCMGA1UECgwcRXhhbXBsZSBJ\n\ +RCBDQSAyIE9yZ2FuaXphdGlvbjEYMBYGA1UEAwwPRXhhbXBsZSBJRCBDQSAyMTsw\n\ +OQYJKoZIhvcNAQkBFixhdXRob3JpdHkyQGN5Y2xvbmVkZHNzZWN1cml0eS5hZGxp\n\ +bmt0ZWNoLmNvbTAeFw0yMDAyMjcxNjI3MjRaFw0zMDAyMjQxNjI3MjRaMIHFMQsw\n\ +CQYDVQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2FsaXR5IE5hbWUx\n\ +EzARBgNVBAsMCkV4YW1wbGUgT1UxJTAjBgNVBAoMHEV4YW1wbGUgSUQgQ0EgMiBP\n\ +cmdhbml6YXRpb24xGDAWBgNVBAMMD0V4YW1wbGUgSUQgQ0EgMjE7MDkGCSqGSIb3\n\ +DQEJARYsYXV0aG9yaXR5MkBjeWNsb25lZGRzc2VjdXJpdHkuYWRsaW5rdGVjaC5j\n\ +b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDk+ewDf871kPgBqXkm\n\ +UEXdf/vqWWoKx3KfJ4N3Gq4vt/cDOMs0xakpqr5uxm787AvbOui4P8QmT8naLhAA\n\ +TvHtNGg2LV0ZQtLcVVFsXXsBYDUEbLJYmCBtJU8zSfLLzgtN+z9nVqLthAcVyGhZ\n\ +iEkCfXKS4XzwjFUxgrXUM1VSiHHz8DbreQFDTF8mVavZ75HjieuHz1OcSaoIHCIF\n\ +mhPDlxRR/qZpc3Y52NZMNRHVPj4Tmc3N4H2eneeoG7nVn0MgNuqbssezeQtUOOoH\n\ +DgPGp3xzd8XQxaF5hVIM9E7aL77kw5v4gwccjL5xWC72zzxC3c1ltmbaEcwhHGsu\n\ +MR4lAgMBAAGjUzBRMB0GA1UdDgQWBBTTpmGTY5teWrZBA8Sd7kL5Lg/JmjAfBgNV\n\ +HSMEGDAWgBTTpmGTY5teWrZBA8Sd7kL5Lg/JmjAPBgNVHRMBAf8EBTADAQH/MA0G\n\ +CSqGSIb3DQEBCwUAA4IBAQCbelDJr9sVsYgQSp4yzSOSop5DSOWCweBF56NatcbY\n\ +3HUYc4iaH4NcB04WFkUl2XmqVCAM0zbmV0q4HoQikTK5PBHmwxuuD2HhPDWtMeFR\n\ +W96BjzGVpV27yaNIPvLwjTVV+A72r4vRvufiFhrMCovRwlWgHY6+gXKfrtyljTZ0\n\ +m1mENHOJOQWDXFAXP5yiehSMKy/izKvQ1G1hLErYMMc+sdgF/9X2KaudnTakTW0d\n\ +44kXUFKSU7mqV44D12unxCNODclznd31tiJ+70U39AXlR2BzwBzyFzPCh5JYtMog\n\ +TwbdLY3LN40gpkDUxIIH115D7ujUKNd8s2gmSHOCm1ar\n\ +-----END CERTIFICATE-----" + +#define TEST_IDENTITY_CA2_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n\ +MIIEogIBAAKCAQEA5PnsA3/O9ZD4Aal5JlBF3X/76llqCsdynyeDdxquL7f3AzjL\n\ +NMWpKaq+bsZu/OwL2zrouD/EJk/J2i4QAE7x7TRoNi1dGULS3FVRbF17AWA1BGyy\n\ +WJggbSVPM0nyy84LTfs/Z1ai7YQHFchoWYhJAn1ykuF88IxVMYK11DNVUohx8/A2\n\ +63kBQ0xfJlWr2e+R44nrh89TnEmqCBwiBZoTw5cUUf6maXN2OdjWTDUR1T4+E5nN\n\ +zeB9np3nqBu51Z9DIDbqm7LHs3kLVDjqBw4Dxqd8c3fF0MWheYVSDPRO2i++5MOb\n\ ++IMHHIy+cVgu9s88Qt3NZbZm2hHMIRxrLjEeJQIDAQABAoIBABBUirKNMPNujWGA\n\ +9rT20KTFde/2xItUQiZ7qPKbooSguCswp71xw2jHVqGL4WqEYywVfXd2hMS+uASp\n\ +eFatSq/CJxSGE7ezflpcc1wpJpaoh99y6R1MbDOcj5N22KwUW9YJ7zGtih0qZ170\n\ +VgzcnWhiDgPPtRtqxsCrM9CYgKNMGU6M9CFPX3PKDudKVU5fmi9bhtCqQaLhImbs\n\ +aQO3y4yI0af4KSQSur+eqeB/z7V39BEo1LfqaVQd1e9ItEYnTg8TaSaCshS4H8UG\n\ +Yx/pGhnxgn8+5LFL2K635Mb99OLb0hUwIOAbuoAuTlKijit0uGEJe/+DjbkcgZ5d\n\ +VB9I8UECgYEA/56Em8M6N6mTUN3WN+U8NSLltjSIL8kemK30dJ56aUsTiy4h0jNa\n\ +Jda7BeRPQcf9pnQpgFkV7XoKIbfTIqOhqD8XAvJL4//+VMmH2q/R2Xf6e0/CIEUe\n\ +3K74QyRVazx+tt+NOafCwjU9bA7ebjwQVsb+dPAS6kOWxTCZFzCgFk0CgYEA5VE+\n\ +U/C8D9zmJjL1uc4XkBNAg/dQNybQ9DX2Ku5dKME6yg4u7Lxnl3X9asvtQAsUeOPa\n\ +dKGkQ8NZfnSvXYd04n/FTRohFCaYz3RWIbo/q4KCsnJk6uAUM9YFeQGqZdEjO3Mu\n\ +Yk1uhHFl+C4Q/InzYEs+QwtMOS7XVMa5vm6OQzkCgYAR+xKU6ly0AaetLo2dDPD5\n\ +Q+UotfVGdz1BvCrP8T3nHjLXvXz/jkEvHDW3qmGw3OKIzO8Gaj3SoJ0J1iZx71S1\n\ +wwpZWLXh6eX4DN0Tkv6N75SdC/U50+Lh3yTzhCDGFFFNh9glUBmxE5Gogjs/QdZc\n\ +ZE8N5r1N4Uc/w7VhHjiEmQKBgHMA2pQ4P+horRdtKSTEwbZkoU9NYXI3SkWfJlSD\n\ +dD7zISuiD1B0cDNaXfwIR3R92geCpdUmF35QYvpzRFtQioLo9ybiusIjVTF9M5D4\n\ +mePGsQsTKZ9NP3R7mgUEm9MyHkw7SIDOOmW7hRsA503vVRnuwkvXR6PJ5P3EJ/Tj\n\ +9v6pAoGAfVTCJkf0aZ7KjV5GQ33l8uH9dEBzRJ4xOjGpeVBTm+L5N4ejcrQ4p9t0\n\ +JQr8hQHEp7tnHZ9H8DuIIQVDUJdrRa1qO+TNQiOdPLRNofXHuFDNIoj4+bP5ISnL\n\ +dImrEylWjCLbiiOpIbBmAQLb55xYsFzkdRCW3AlmldSVUW96yfU=\n\ +-----END RSA PRIVATE KEY-----" + +// Permissions CAs +#define TEST_PERMISSIONS_CA_CERTIFICATE "-----BEGIN CERTIFICATE-----\n\ +MIIEbzCCA1egAwIBAgIUfoby6818hlJQ+41KUHiM6BZll/0wDQYJKoZIhvcNAQEL\n\ +BQAwgcYxCzAJBgNVBAYTAk5MMQswCQYDVQQIDAJPVjEWMBQGA1UEBwwNTG9jYWxp\n\ +dHkgTmFtZTETMBEGA1UECwwKRXhhbXBsZSBPVTEgMB4GA1UECgwXRXhhbXBsZSBD\n\ +QSBPcmdhbml6YXRpb24xHzAdBgNVBAMMFkV4YW1wbGUgUGVybWlzc2lvbnMgQ0Ex\n\ +OjA4BgkqhkiG9w0BCQEWK2F1dGhvcml0eUBjeWNsb25lZGRzc2VjdXJpdHkuYWRs\n\ +aW5rdGVjaC5jb20wHhcNMjAwMjI3MTM0ODA5WhcNMzAwMjI0MTM0ODA5WjCBxjEL\n\ +MAkGA1UEBhMCTkwxCzAJBgNVBAgMAk9WMRYwFAYDVQQHDA1Mb2NhbGl0eSBOYW1l\n\ +MRMwEQYDVQQLDApFeGFtcGxlIE9VMSAwHgYDVQQKDBdFeGFtcGxlIENBIE9yZ2Fu\n\ +aXphdGlvbjEfMB0GA1UEAwwWRXhhbXBsZSBQZXJtaXNzaW9ucyBDQTE6MDgGCSqG\n\ +SIb3DQEJARYrYXV0aG9yaXR5QGN5Y2xvbmVkZHNzZWN1cml0eS5hZGxpbmt0ZWNo\n\ +LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNWwyrW3J+TCyaZ\n\ +H77q+29GGqFsYP5rv9cpcL/TMDNccsPYY+1RA1K+zMRYo1LG8VdJNtJlhxE+tmEb\n\ +KxsVUTtoj8zbLVU4P4g0gIh6U7LMv5lUEZ3XYKWvYrbZTFMof2rXQYGXPO7pFnvb\n\ +NAbnMiLmagRKxKJ91kq4utuMG3U6rkCA7i2S8cEISNO3gIpFa0IZJ8yS8wDlKa/L\n\ +GxL90BYasLsSA6tw/69OIiUUYqpMRD+xxyyTkMO37VjmdiFLHa/dxO8HH0t3Q0U0\n\ +AgZP9uwYTgZpN+2UEFnjv3BDIydc3Wa0UaSdxLtHXMPvg3sRuH9CTqr4Le7/3uTY\n\ +ehYKgd0CAwEAAaNTMFEwHQYDVR0OBBYEFFi4pK986ZSB0BLiMm8ivu6AUxYPMB8G\n\ +A1UdIwQYMBaAFFi4pK986ZSB0BLiMm8ivu6AUxYPMA8GA1UdEwEB/wQFMAMBAf8w\n\ +DQYJKoZIhvcNAQELBQADggEBAHYLaJVWrLHg+62jC8yIz9dbECIroX9Gb7Ll937H\n\ +Mum6Hj4wlImrifMVV3iORWBrBLvtTtn0Zno3mwfjLRQtkjOih71eJT+6//B7CT7n\n\ +oULJYVq8IRGErbKtmXULnxTajFApzO0v4hSu7rWj/Jfhil0TX7QgKNpgKzjYodWz\n\ +3oGGtchxvw3+v9wdIWD5Cj0bk/VMCQCaBV0anvyga7d4k8/zPF7nW2Z9jNfKsVD1\n\ +piFa+Yd4zN6XOPPKiFXfLD7ht9i2gG25iS+d95tKg1DfjnRD7u0BJSOAPerxGtN/\n\ +wf43qY1XzUoE2FBJ9QJGOA/02ffaUMOwSzICF/ShctH+Knk=\n\ +-----END CERTIFICATE-----" + +#define TEST_PERMISSIONS_CA_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n\ +MIIEpAIBAAKCAQEA01bDKtbcn5MLJpkfvur7b0YaoWxg/mu/1ylwv9MwM1xyw9hj\n\ +7VEDUr7MxFijUsbxV0k20mWHET62YRsrGxVRO2iPzNstVTg/iDSAiHpTssy/mVQR\n\ +nddgpa9ittlMUyh/atdBgZc87ukWe9s0BucyIuZqBErEon3WSri624wbdTquQIDu\n\ +LZLxwQhI07eAikVrQhknzJLzAOUpr8sbEv3QFhqwuxIDq3D/r04iJRRiqkxEP7HH\n\ +LJOQw7ftWOZ2IUsdr93E7wcfS3dDRTQCBk/27BhOBmk37ZQQWeO/cEMjJ1zdZrRR\n\ +pJ3Eu0dcw++DexG4f0JOqvgt7v/e5Nh6FgqB3QIDAQABAoIBABFHMKGZ+2OYc/rt\n\ +3eiP8YqBYr/7ylpCmOaQXsVwEKrCTiew00qdqvXi337V+FRWK3kFZVQCNO61/9ck\n\ +j3uhXIjM3aTT7nrfJGKQWEnQJnOhxbBVbTNIXoBtPFbSoSjTUMd9Xb+oi7TEna/2\n\ +leRSloi/6b78FeNrAlANlklIxR3qTjRSxjGYVfukCWsKq3uFfWM4Wp9N1B1gsyRo\n\ +/SH2jOu0XTLNdajggtBKcFoqxVIiaetERKVRRid7pW0zwuYS5Zwv5Wtl3XMbUuAn\n\ +VGesMeCKAGpwkLjmvXKBE5setnd7cWBKdVKddYDkzbDvU7X6QEHFnac6m6OQ2P62\n\ +QfkO94ECgYEA70tV55AreDnPQEpf698ZjA8pYvF90GfGx/Y4oYWU/s0IlD6Pfbsr\n\ +qkRu+1I+SUNZWARhirXmJzuOmJYUQRteCEq+6RPJzn5Jl9MtipOBAjI0h589dbAB\n\ +8m/BRk+bEZKCXLgVa0TyZ/gd/wDBxB+qd+bPep8nAl4krMWK9W1+DLECgYEA4hfP\n\ +EwUPMwHrGlq0oRUA08ssQ8XxVCKWeS3cLAJjO6EdJyIUm/8S/UZPBPeSkGyZeld+\n\ +fY7z9ZV0HA338p5BYYDCqgJC6b5Ud5UV0yLkq01v6b0H3nSjTPcbA61l9laN0vhm\n\ +QJ/xTiAHgsGBbOx2VtwDoE8T1AbAaamcapqNYu0CgYAXCiPdRc5JpxdDU2Xk6fgl\n\ +uhf8BNBeTn+fJR/SvW/ZEJiw3U0nh+vuWuRsokCJAUkK5nEVz+m3AU77dgfBNQda\n\ +uQeknVki3pnrWlPaMdWMBpV0MWrTd/zYANaVFHkTug1/K+I0D9FfHU6WDNabMYlS\n\ +PhDf947j9XiGggadFsu6IQKBgQC6dgpIVFbZqU5cuMvZQToicaA68Kd7zN6uZ7z5\n\ +6qouRkyFtpyqnq3pha+rmAYe6AGXnUrrgBcAxdYxQO/o/s1K/WcN0LmgjmCZErIi\n\ +I9fU0xNmAIjZ1PXMhsqXuMyrYWyrvkKOL5pR5SZsluwHieh68A5pim3+4eaT/dbL\n\ +MFVEbQKBgQDfkeApSfKATXJpYIV/tiGjmRkkYoZ6NVar92npjlb72jaA4V0gHmuD\n\ +9ttypXOJPB/5zMa5uL6drp3CLv/GcWekUiUUXuyKQpcxZWqxf/leh9gTgGDAH/k4\n\ +4+zX4HLEzTmoOc0cqzi4w6pTIj29BOV5QpnnyUGyvj8NGNSdFvZFSQ==\n\ +-----END RSA PRIVATE KEY-----" + + +// Identities + +// created with TEST_IDENTITY_CA1_CERTIFICATE +#define TEST_IDENTITY1_CERTIFICATE "-----BEGIN CERTIFICATE-----\n\ MIIEDTCCAvUCFHZ4yXyk/9yeMxgHs6Ib0bLKhXYuMA0GCSqGSIb3DQEBCwUAMIHA\n\ MQswCQYDVQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2FsaXR5IE5h\n\ bWUxEzARBgNVBAsMCkV4YW1wbGUgT1UxIzAhBgNVBAoMGkV4YW1wbGUgSUQgQ0Eg\n\ @@ -42,7 +213,7 @@ VwzWIaZ06idvCtPKTfP71jJypV3+I2g5PNqranbuMv5nNAKZq1QlSB07f2Z1VIu6\n\ 6jeSZSADfm73qnE2Kj1PiZkPn0Wu+K24GXCvdILATcUS\n\ -----END CERTIFICATE-----" -#define TEST_IDENTITY_PRIVATE_KEY "data:,-----BEGIN RSA PRIVATE KEY-----\n\ +#define TEST_IDENTITY1_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n\ MIIEpQIBAAKCAQEA5mEhLZIP2ko1bRJyJCwbnvhIpXFv6GOhnvuS5v8tsTju40O6\n\ 2NNQmKT/my1QVKiUu7OoWZtLNBebgxgJ851eQ4TBRXy/f2jGkLPYM22dohLTblVC\n\ pGutn+Itw3QRM3nkne7Sk8O6FP6NH6Y+7gkjxy5kI3GvhuICuBIzAV4dHK+hPlCn\n\ @@ -71,35 +242,8 @@ yNw1+km1Zy6EWdFEMciEFlbRwWVmDfE/um9LZsSWbmuWAOTww9GBDhc=\n\ -----END RSA PRIVATE KEY-----" -#define TEST_IDENTITY_CA_CERTIFICATE "data:,-----BEGIN CERTIFICATE-----\n\ -MIIEYzCCA0ugAwIBAgIUOp5yaGGuh0vaQTZHVPkX5jHoc/4wDQYJKoZIhvcNAQEL\n\ -BQAwgcAxCzAJBgNVBAYTAk5MMQswCQYDVQQIDAJPVjEWMBQGA1UEBwwNTG9jYWxp\n\ -dHkgTmFtZTETMBEGA1UECwwKRXhhbXBsZSBPVTEjMCEGA1UECgwaRXhhbXBsZSBJ\n\ -RCBDQSBPcmdhbml6YXRpb24xFjAUBgNVBAMMDUV4YW1wbGUgSUQgQ0ExOjA4Bgkq\n\ -hkiG9w0BCQEWK2F1dGhvcml0eUBjeWNsb25lZGRzc2VjdXJpdHkuYWRsaW5rdGVj\n\ -aC5jb20wHhcNMjAwMjI3MTkyMjA1WhcNMzAwMjI0MTkyMjA1WjCBwDELMAkGA1UE\n\ -BhMCTkwxCzAJBgNVBAgMAk9WMRYwFAYDVQQHDA1Mb2NhbGl0eSBOYW1lMRMwEQYD\n\ -VQQLDApFeGFtcGxlIE9VMSMwIQYDVQQKDBpFeGFtcGxlIElEIENBIE9yZ2FuaXph\n\ -dGlvbjEWMBQGA1UEAwwNRXhhbXBsZSBJRCBDQTE6MDgGCSqGSIb3DQEJARYrYXV0\n\ -aG9yaXR5QGN5Y2xvbmVkZHNzZWN1cml0eS5hZGxpbmt0ZWNoLmNvbTCCASIwDQYJ\n\ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBALKhk7JXUpqJphyOC6oOI00LH49WTtO2\n\ -GCgDyJhcRYYAm7APMtmEDH+zptvd34N4eSu03Dc65cB/XN4Lbi2TjolVvKz0hHjz\n\ -tzmQT5jTgb1UkJX4NjKGw+RrYe9Ls0kfoAL2kvb12kmd1Oj4TIKMZP9TCrz7Vw8m\n\ -cZKQxZ56bLys6cU2XdiTp3v+Ef/vMll4+DINj4ZAMWL3CkT+q1G6ZxHRpFlsIyhc\n\ -Q1wX6gxUoY6cQdBA7TehKCCEWz4L1KM1A18ZmCHmjTniU0ssLoiAzsQs4b6Fnw8Z\n\ -MLFj8ocwzN5g66gJJWGofakXqX/V24KbGl54WX2X7FYU0tGzR234DXcCAwEAAaNT\n\ -MFEwHQYDVR0OBBYEFGeCcK8B74QWCuuCjlSUzOBBUTF5MB8GA1UdIwQYMBaAFGeC\n\ -cK8B74QWCuuCjlSUzOBBUTF5MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL\n\ -BQADggEBAJQeMc4XzMFnpQKCb58rzRs3Wt9FmZZS4O596sHxMEewTkEHm5gLYMzF\n\ -9JYEdUiLoTurQuIr0KgPi+Q3kliQdLfrVPbdWTmlUDZARR5ir5d1gGHST6qnb3Xi\n\ -mG+7nwle9R/hLrtPio+gYRgwJEiS55f6p0/E1wDcc+6numvjCRQ/CGIiJfwD/R+d\n\ -pv93YLEfuliZttfBc/apIu6OL4chxF+3QgSw1ltV5nXXqDTGHMRZENkp3Yiolumc\n\ -6smL4uA7Q812pVcENi3MLjdJgBS/8DcSBQHspVuXugaKKPDMkJnD0IyLWc8vLXh4\n\ -O7JdDrmusJAZA9RsTkinl3DuPfF34Sk=\n\ ------END CERTIFICATE-----" - - -#define TEST_IDENTITY2_CERTIFICATE "data:,-----BEGIN CERTIFICATE-----\n\ +// created with TEST_IDENTITY_CA2_CERTIFICATE +#define TEST_IDENTITY2_CERTIFICATE "-----BEGIN CERTIFICATE-----\n\ MIIEDjCCAvYCFDEZQzcfGKK8IKNyH+AdNSjdyVgnMA0GCSqGSIb3DQEBCwUAMIHF\n\ MQswCQYDVQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2FsaXR5IE5h\n\ bWUxEzARBgNVBAsMCkV4YW1wbGUgT1UxJTAjBgNVBAoMHEV4YW1wbGUgSUQgQ0Eg\n\ @@ -124,7 +268,7 @@ AuPUgPJObxJhxJSC4p5qy37pYZHiNH1wG/+BDHgZo3wNwFsWqxabKziGB8XU3INc\n\ USI3GDWM2jjElMSnDCj4ChM5wFbwWrqwdOEzeGWBWbo3hQ==\n\ -----END CERTIFICATE-----" -#define TEST_IDENTITY2_PRIVATE_KEY "data:,-----BEGIN RSA PRIVATE KEY-----\n\ +#define TEST_IDENTITY2_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n\ MIIEpQIBAAKCAQEAwBAz143TONNN1kAsJOKOiDSirH+SqdZW1VaNX9zfg7I+9S4f\n\ 8M1EfoKvR8jvpSKigsP2d+8d7nZfyhkfxao1bubuDt0yWK4MkPfJWl0tGZNOCXjQ\n\ RLwxOqZ1vbLy63vQwl/mdTPQRCz2Ve+dPSu7QHYJ/K5uI+1otJ/IOhUGREtt/N6p\n\ @@ -153,32 +297,58 @@ mi1HgIUzXZTRBNamYCltJWYnN0hOlSL6vcHgeJ9y1gSDh0QqB2BG8HY=\n\ -----END RSA PRIVATE KEY-----" -#define TEST_IDENTITY_CA2_CERTIFICATE "data:,-----BEGIN CERTIFICATE-----\n\ -MIIEbTCCA1WgAwIBAgIUL0mSpPRgzveYTJ8UHSmOIwkIjjYwDQYJKoZIhvcNAQEL\n\ -BQAwgcUxCzAJBgNVBAYTAk5MMQswCQYDVQQIDAJPVjEWMBQGA1UEBwwNTG9jYWxp\n\ -dHkgTmFtZTETMBEGA1UECwwKRXhhbXBsZSBPVTElMCMGA1UECgwcRXhhbXBsZSBJ\n\ -RCBDQSAyIE9yZ2FuaXphdGlvbjEYMBYGA1UEAwwPRXhhbXBsZSBJRCBDQSAyMTsw\n\ -OQYJKoZIhvcNAQkBFixhdXRob3JpdHkyQGN5Y2xvbmVkZHNzZWN1cml0eS5hZGxp\n\ -bmt0ZWNoLmNvbTAeFw0yMDAyMjcxNjI3MjRaFw0zMDAyMjQxNjI3MjRaMIHFMQsw\n\ -CQYDVQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2FsaXR5IE5hbWUx\n\ -EzARBgNVBAsMCkV4YW1wbGUgT1UxJTAjBgNVBAoMHEV4YW1wbGUgSUQgQ0EgMiBP\n\ -cmdhbml6YXRpb24xGDAWBgNVBAMMD0V4YW1wbGUgSUQgQ0EgMjE7MDkGCSqGSIb3\n\ -DQEJARYsYXV0aG9yaXR5MkBjeWNsb25lZGRzc2VjdXJpdHkuYWRsaW5rdGVjaC5j\n\ -b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDk+ewDf871kPgBqXkm\n\ -UEXdf/vqWWoKx3KfJ4N3Gq4vt/cDOMs0xakpqr5uxm787AvbOui4P8QmT8naLhAA\n\ -TvHtNGg2LV0ZQtLcVVFsXXsBYDUEbLJYmCBtJU8zSfLLzgtN+z9nVqLthAcVyGhZ\n\ -iEkCfXKS4XzwjFUxgrXUM1VSiHHz8DbreQFDTF8mVavZ75HjieuHz1OcSaoIHCIF\n\ -mhPDlxRR/qZpc3Y52NZMNRHVPj4Tmc3N4H2eneeoG7nVn0MgNuqbssezeQtUOOoH\n\ -DgPGp3xzd8XQxaF5hVIM9E7aL77kw5v4gwccjL5xWC72zzxC3c1ltmbaEcwhHGsu\n\ -MR4lAgMBAAGjUzBRMB0GA1UdDgQWBBTTpmGTY5teWrZBA8Sd7kL5Lg/JmjAfBgNV\n\ -HSMEGDAWgBTTpmGTY5teWrZBA8Sd7kL5Lg/JmjAPBgNVHRMBAf8EBTADAQH/MA0G\n\ -CSqGSIb3DQEBCwUAA4IBAQCbelDJr9sVsYgQSp4yzSOSop5DSOWCweBF56NatcbY\n\ -3HUYc4iaH4NcB04WFkUl2XmqVCAM0zbmV0q4HoQikTK5PBHmwxuuD2HhPDWtMeFR\n\ -W96BjzGVpV27yaNIPvLwjTVV+A72r4vRvufiFhrMCovRwlWgHY6+gXKfrtyljTZ0\n\ -m1mENHOJOQWDXFAXP5yiehSMKy/izKvQ1G1hLErYMMc+sdgF/9X2KaudnTakTW0d\n\ -44kXUFKSU7mqV44D12unxCNODclznd31tiJ+70U39AXlR2BzwBzyFzPCh5JYtMog\n\ -TwbdLY3LN40gpkDUxIIH115D7ujUKNd8s2gmSHOCm1ar\n\ +// created with TEST_IDENTITY_CA1_CERTIFICATE +#define TEST_IDENTITY3_CERTIFICATE "-----BEGIN CERTIFICATE-----\n\ +MIIEDTCCAvUCFHZ4yXyk/9yeMxgHs6Ib0bLKhXYvMA0GCSqGSIb3DQEBCwUAMIHA\n\ +MQswCQYDVQQGEwJOTDELMAkGA1UECAwCT1YxFjAUBgNVBAcMDUxvY2FsaXR5IE5h\n\ +bWUxEzARBgNVBAsMCkV4YW1wbGUgT1UxIzAhBgNVBAoMGkV4YW1wbGUgSUQgQ0Eg\n\ +T3JnYW5pemF0aW9uMRYwFAYDVQQDDA1FeGFtcGxlIElEIENBMTowOAYJKoZIhvcN\n\ +AQkBFithdXRob3JpdHlAY3ljbG9uZWRkc3NlY3VyaXR5LmFkbGlua3RlY2guY29t\n\ +MB4XDTIwMDMwNTEzMTczN1oXDTMwMDMwMzEzMTczN1owgcQxCzAJBgNVBAYTAk5M\n\ +MQswCQYDVQQIDAJPVjEWMBQGA1UEBwwNTG9jYWxpdHkgTmFtZTEhMB8GA1UECwwY\n\ +T3JnYW5pemF0aW9uYWwgVW5pdCBOYW1lMR0wGwYDVQQKDBRFeGFtcGxlIE9yZ2Fu\n\ +aXphdGlvbjEWMBQGA1UEAwwNQ2Fyb2wgRXhhbXBsZTE2MDQGCSqGSIb3DQEJARYn\n\ +Y2Fyb2xAY3ljbG9uZWRkc3NlY3VyaXR5LmFkbGlua3RlY2guY29tMIIBIjANBgkq\n\ +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0QduVwXptfjiwkvbn5aXuIpwZ9aWOqmj\n\ +e36qNknnS0mng1zPhzi4RLAl6CUxa6E5bkfjGZxFfYefDNk3ynzerEotFa1f5++b\n\ +aY73hs2ecfz+9ofjqR2fsroxOFwFF9JLbeWTDPS2mf5yE0Ci2+ctq6Ep4jDeHNui\n\ +WpSOY8OoIEWq4PD/R/VGJSiHSG+OjOUN7gwuxta0yglFeyHBdzr8mDZiejj1KYBD\n\ +AzuQrtaibHNtGBo3VGFvPKs85mK/Swv1GoXxcy1uBU1Yup9JLq3Ds8R5YYecSlXk\n\ +77EmZl4dgoScbt4NKTPuo8t803Ph3PYQCggILhlaEwjpfd1YTFLxOQIDAQABMA0G\n\ +CSqGSIb3DQEBCwUAA4IBAQAtV57Zc5dV9+z51zTOtghNZrFGJ48xJhnXddMVJ1Yh\n\ +08uoODRSRJHXNxMrlSRMeZ+CNkvd/QmqzOYvok3EqusOXFNU9qfmc3DToU/DDqkf\n\ +PMEpc9lPLTjmm6MfQgjyT5pDDNPUV9Io1s2o492ozr87ULyVf6I2bNu2NnVv2IzE\n\ +j9Mz/L7TkcgJgbdDl+21CR3NRA1PpxFB/PcM+zy4C2XoFv/qcF5pkcBpkyNjva9m\n\ +xmjSJWMoIVzXk6apPsRGCJLFJ3uuj+9K6POo/xgAkrbgvZF0i0yAJSTvSQmg6x2S\n\ +FMxE89kC7Npg+fQF15aaNEn4tuQiz0WW9pq1wSTXjoqj\n\ -----END CERTIFICATE-----" +#define TEST_IDENTITY3_PRIVATE_KEY "-----BEGIN RSA PRIVATE KEY-----\n\ +MIIEpAIBAAKCAQEA0QduVwXptfjiwkvbn5aXuIpwZ9aWOqmje36qNknnS0mng1zP\n\ +hzi4RLAl6CUxa6E5bkfjGZxFfYefDNk3ynzerEotFa1f5++baY73hs2ecfz+9ofj\n\ +qR2fsroxOFwFF9JLbeWTDPS2mf5yE0Ci2+ctq6Ep4jDeHNuiWpSOY8OoIEWq4PD/\n\ +R/VGJSiHSG+OjOUN7gwuxta0yglFeyHBdzr8mDZiejj1KYBDAzuQrtaibHNtGBo3\n\ +VGFvPKs85mK/Swv1GoXxcy1uBU1Yup9JLq3Ds8R5YYecSlXk77EmZl4dgoScbt4N\n\ +KTPuo8t803Ph3PYQCggILhlaEwjpfd1YTFLxOQIDAQABAoIBAGSpyHh+L3vj/QgG\n\ +0iB7vFsxyEopbDWaBlHtwPjeBFYchWBcrNB4/zyM++RdLPyhKvAyDGsD9+8pBe6B\n\ +GT4Zfn7IRgf/c4VVvalLIWc41IoehYaiEIAb9RF0W0nB/u3m505oVbXSj7F/eN5O\n\ +rV9raHIT7gCw+fY5y2kFy8C9s9S9+VzzYOzIZPWSh6Plc/eI2niSVt+MDufDeVOR\n\ +Ug6Z54lpXkwqv0Pz8F7ELyRGBvUW5UAvgyprvXgSYz1VNeHr3fmLX/O4rGktk02x\n\ +bAFxvaNV/JEK1fLFWLZ8TJVGsni+uYu/zkvXdxw7gphdoM77UKeZ00udg7orYUhW\n\ +6MwsuRUCgYEA7KzanZVPfbL4TMCpS6EJUO8H9lebH0srzqKNJD3/NL2JPebRNjZA\n\ +niH6vXD773/8IYlFTAXe0npVApZETKVzP4LNvsSVtjNvqXKdRM0cT47Dc4Y16kn/\n\ +X9Pd/ff+HH93T8Pcpguovw8QU7nxlf5dCvlnWrCj84Dw1ZToS2NLWAcCgYEA4hiy\n\ +nz6xvbkkUc5oHWxJIHxSLrOvMsyLMNp9UlUxgrxGqth0yQsFZwinPzs/y8aUVKyi\n\ +bHJlL35fpHeuna0V054E5vyeOOM7eLLFToDITS1m91hsl6amMW8iup/HTZhSemt7\n\ +tEn4mWlINXyP47MWfOr4oQ1KDzDCA3JFfzjInL8CgYBRulL3zcKYbn/tyS3s7twP\n\ +taszNwdbJBMplNpWZI5HQRguZxFhvhRMRwGV/3kQOErxrbxfRzutxQ6sCQXmzc9h\n\ +ZCL2OF5Wf6aUhf6m7olTM8JslzDxCcKE7d2fwM5gOugRhFoigK4x49rIftJc8Gxi\n\ +yMMW/x5ujN0ddAFPXyd6awKBgQCypX8lsnzwgsR+2w+LCA+z2md5PULWaaYlgM36\n\ +6xPG0AsqXQPSAqJPKhg0LxWWZp63VPy1oaHv5/OcWXCgZ63SWo5XEQ3Xtzw7f03F\n\ +XJ5n1NMB511Oaj/w2XZgbXUmC5BH6HuDFduXJAgJMxXifZPsOiEf6Ac3f3gdDwJ4\n\ +pp5kswKBgQDNUI3uzqw8J3e81tTAn2U8eyHuQxi8swv6K4Dx+sqCKpxkFcYvDLQl\n\ +qI+v234hvmZN3CmGPCY01aZl3NUUFKx9fvwweYG/vicCsA2XKwnmaSWTTrT62vlY\n\ +S1cWlJlUjw59ZhAqgD1pe4r0suRQ6e1OT/pByTKz1BxE/lwZftpauA==\n\ +-----END RSA PRIVATE KEY-----" #endif /* PLUGIN_SECURITY_CORE_TEST_IDENTITY_H_ */ diff --git a/src/security/core/tests/handshake.c b/src/security/core/tests/handshake.c index 5534434..62ca589 100644 --- a/src/security/core/tests/handshake.c +++ b/src/security/core/tests/handshake.c @@ -43,9 +43,9 @@ static const char *config = " " " " " " - " "TEST_IDENTITY_CERTIFICATE"" - " "TEST_IDENTITY_PRIVATE_KEY"" - " "TEST_IDENTITY_CA_CERTIFICATE"" + " data:,"TEST_IDENTITY1_CERTIFICATE"" + " data:,"TEST_IDENTITY1_PRIVATE_KEY"" + " data:,"TEST_IDENTITY_CA1_CERTIFICATE"" " " " " " " @@ -91,6 +91,6 @@ static void handshake_fini(void) CU_Test(ddssec_handshake, happy_day, .init = handshake_init, .fini = handshake_fini) { - validate_handshake (DDS_DOMAINID_PART1, false, NULL, false, NULL); - validate_handshake (DDS_DOMAINID_PART2, false, NULL, false, NULL); + validate_handshake_nofail (DDS_DOMAINID_PART1); + validate_handshake_nofail (DDS_DOMAINID_PART2); } diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index 10769e0..7ed18b5 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -59,9 +59,9 @@ static const char *config = " " " " " " - " "TEST_IDENTITY_CERTIFICATE"" - " "TEST_IDENTITY_PRIVATE_KEY"" - " "TEST_IDENTITY_CA_CERTIFICATE"" + " data:,"TEST_IDENTITY1_CERTIFICATE"" + " data:,"TEST_IDENTITY1_PRIVATE_KEY"" + " data:,"TEST_IDENTITY_CA1_CERTIFICATE"" " " " ." " " @@ -89,6 +89,10 @@ const char * g_pk_encrypt = "ENCRYPT"; const char * g_pk_sign_oa = "SIGN_WITH_ORIGIN_AUTHENTICATION"; const char * g_pk_encrypt_oa = "ENCRYPT_WITH_ORIGIN_AUTHENTICATION"; +const char * g_pp_secret = "ppsecret"; +const char * g_groupdata_secret = "groupsecret"; +const char * g_ep_secret = "epsecret"; + uint32_t g_topic_nr = 0; static dds_entity_t g_pub_domains[MAX_DOMAINS]; @@ -106,6 +110,9 @@ struct domain_sec_config { DDS_Security_ProtectionKind metadata_pk; DDS_Security_BasicProtectionKind payload_pk; const char * payload_secret; + const char * pp_userdata_secret; + const char * groupdata_secret; + const char * ep_userdata_secret; }; typedef void (*set_crypto_params_fn)(struct dds_security_cryptography_impl *, const struct domain_sec_config *); @@ -170,6 +177,7 @@ static dds_qos_t *get_qos() dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, -1); dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL); dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); + dds_qset_userdata (qos, g_ep_secret, strlen (g_ep_secret)); return qos; } @@ -183,12 +191,15 @@ static char *create_topic_name(const char *prefix, uint32_t nr, char *name, size static dds_entity_t create_pp (dds_domainid_t domain_id, const struct domain_sec_config * domain_config, set_crypto_params_fn set_crypto_params) { - dds_entity_t pp = dds_create_participant (domain_id, NULL, NULL); + dds_qos_t *qos = dds_create_qos (); + dds_qset_userdata (qos, g_pp_secret, strlen (g_pp_secret)); + dds_entity_t pp = dds_create_participant (domain_id, qos, NULL); CU_ASSERT_FATAL (pp > 0); + dds_delete_qos (qos); struct dds_security_cryptography_impl * crypto_context = get_crypto_context (pp); CU_ASSERT_FATAL (crypto_context != NULL); - if (set_crypto_params) - set_crypto_params (crypto_context, domain_config); + assert (set_crypto_params); + set_crypto_params (crypto_context, domain_config); return pp; } @@ -204,8 +215,11 @@ static void create_dom_pp_pubsub(dds_domainid_t domain_id_base, const char * dom { size_t pp_index = d * n_pp + p; pps[pp_index] = create_pp (domain_id_base + (uint32_t)d, domain_sec_config, set_crypto_params); - pubsubs[pp_index] = pubsub_create (pps[pp_index], NULL, NULL); + dds_qos_t *qos = dds_create_qos (); + dds_qset_groupdata (qos, g_groupdata_secret, strlen (g_groupdata_secret)); + pubsubs[pp_index] = pubsub_create (pps[pp_index], qos, NULL); CU_ASSERT_FATAL (pubsubs[pp_index] > 0); + dds_delete_qos (qos); } } } @@ -230,7 +244,7 @@ static void test_init(const struct domain_sec_config * domain_config, size_t n_s print_config_vars(governance_vars); printf("\n"); - char * gov_config_signed = get_governance_config (governance_vars); + char * gov_config_signed = get_governance_config (governance_vars, false); struct kvp config_vars[] = { { "GOVERNANCE_DATA", gov_config_signed, 1 }, @@ -417,13 +431,21 @@ static void set_encryption_parameters_basic(struct dds_security_cryptography_imp static void set_encryption_parameters_secret(struct dds_security_cryptography_impl * crypto_context, const struct domain_sec_config *domain_config) { set_encrypted_secret (crypto_context, domain_config->payload_secret); + set_encryption_parameters_basic (crypto_context, domain_config); +} + +static void set_encryption_parameters_disc(struct dds_security_cryptography_impl * crypto_context, const struct domain_sec_config *domain_config) +{ + set_entity_data_secret (crypto_context, domain_config->pp_userdata_secret, domain_config->groupdata_secret, domain_config->ep_userdata_secret); + set_encryption_parameters_basic (crypto_context, domain_config); + set_disc_protection_kinds (crypto_context, domain_config->discovery_pk, domain_config->liveliness_pk); } static void test_discovery_liveliness_protection(DDS_Security_ProtectionKind discovery_pk, DDS_Security_ProtectionKind liveliness_pk) { struct domain_sec_config domain_config = { discovery_pk, liveliness_pk, PK_N, PK_N, BPK_N, NULL }; /* FIXME: add more asserts in wrapper or test instead of just testing communication */ - test_write_read (&domain_config, 1, 1, 1, 1, 1, 1, NULL); + test_write_read (&domain_config, 1, 1, 1, 1, 1, 1, &set_encryption_parameters_disc); } static void test_data_protection_kind(DDS_Security_ProtectionKind rtps_pk, DDS_Security_ProtectionKind metadata_pk, DDS_Security_BasicProtectionKind payload_pk) From e6500b65280ac2acdaa9994e9aa6a210cd3cba5c Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Thu, 26 Mar 2020 13:40:28 +0100 Subject: [PATCH 158/238] Add domaingv pointer to security plugins, as a preparation for supporting the permissions_expiry callback (which needs the gv to enumerate participants. Signed-off-by: Dennis Potman --- .../ddsi/include/dds/ddsi/ddsi_security_omg.h | 4 +- src/core/ddsi/src/ddsi_security_omg.c | 207 ++++---- src/core/ddsi/src/q_entity.c | 2 +- src/security/api/CMakeLists.txt | 1 + .../include/dds/security/dds_security_api.h | 22 +- .../dds_security_api_access_control.h | 469 ++++++++---------- .../dds_security_api_authentication.h | 271 ++++------ .../security/dds_security_api_cryptography.h | 417 +++++++--------- .../access_control/src/access_control.c | 27 +- .../access_control/src/access_control.h | 3 +- .../authentication/CMakeLists.txt | 1 + .../authentication/src/authentication.c | 5 +- .../authentication/src/authentication.h | 2 +- .../cryptographic/CMakeLists.txt | 1 + .../cryptographic/src/cryptography.c | 5 +- .../cryptographic/src/cryptography.h | 17 +- .../builtin_plugins/tests/common/src/loader.c | 2 +- .../src/listeners_access_control_utests.c | 3 +- .../dds/security/core/dds_security_plugins.h | 29 +- src/security/core/src/dds_security_plugins.c | 41 +- .../tests/common/access_control_wrapper.c | 6 +- .../tests/common/access_control_wrapper.h | 5 +- .../tests/common/authentication_wrapper.c | 23 +- .../tests/common/authentication_wrapper.h | 9 +- .../core/tests/common/cryptography_wrapper.c | 18 +- .../core/tests/common/cryptography_wrapper.h | 7 +- 26 files changed, 682 insertions(+), 915 deletions(-) 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 ff81274..f87629a 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h @@ -1092,7 +1092,7 @@ secure_conn_write( * @retval DDS_RETCODE_OK All plugins are successfully loaded * @retval DDS_RETCODE_ERROR One or more security plugins are not loaded. */ -dds_return_t q_omg_security_load( struct dds_security_context *security_context, const dds_qos_t *qos ); +dds_return_t q_omg_security_load( struct dds_security_context *security_context, const dds_qos_t *qos, struct ddsi_domaingv *gv ); void q_omg_security_init( struct ddsi_domaingv *gv ); @@ -1389,7 +1389,7 @@ decode_rtps_message( return NN_RTPS_MSG_STATE_PLAIN; } -inline dds_return_t q_omg_security_load( UNUSED_ARG( struct dds_security_context *security_context ), UNUSED_ARG( const dds_qos_t *property_seq) ) +inline dds_return_t q_omg_security_load( UNUSED_ARG( struct dds_security_context *security_context ), UNUSED_ARG( const dds_qos_t *property_seq), UNUSED_ARG ( struct ddsi_domaingv *gv ) ) { return DDS_RETCODE_ERROR; } diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 057cdf4..096608c 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -53,11 +53,11 @@ */ #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__) +#define EXCEPTION_LOG(gv,e,cat,...) \ + q_omg_log_exception(&gv->logconfig, cat, e, __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) -#define EXCEPTION_ERROR(s, e, ...) EXCEPTION_LOG(s, e, DDS_LC_ERROR, __VA_ARGS__) -#define EXCEPTION_WARNING(s, e, ...) EXCEPTION_LOG(s, e, DDS_LC_WARNING, __VA_ARGS__) +#define EXCEPTION_ERROR(gv,e,...) EXCEPTION_LOG(gv, e, DDS_LC_ERROR, __VA_ARGS__) +#define EXCEPTION_WARNING(gv,e,...) EXCEPTION_LOG(gv, e, DDS_LC_WARNING, __VA_ARGS__) #define SECURITY_ATTR_IS_VALID(attr) \ @@ -212,8 +212,6 @@ struct dds_security_context { struct pending_match_index security_matches; struct participant_sec_index partiticpant_index; - - const struct ddsrt_log_cfg *logcfg; }; typedef struct dds_security_context dds_security_context; @@ -357,7 +355,7 @@ static struct pending_match * find_or_create_pending_entity_match(struct pending return match; } -static void unregister_and_free_pending_match(dds_security_context *sc, struct pending_match *match) +static void unregister_and_free_pending_match(const struct ddsi_domaingv * gv, dds_security_context *sc, struct pending_match *match) { if (match->crypto_handle != 0) { @@ -382,7 +380,7 @@ static void unregister_and_free_pending_match(dds_security_context *sc, struct p 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)); + EXCEPTION_ERROR(gv, &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); } @@ -407,7 +405,7 @@ static void pending_match_expiry_cb(struct xevent *xev, void *varg, ddsrt_mtime_ { 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); + unregister_and_free_pending_match(index->gv, index->gv->security_context, match); match = ddsrt_fibheap_min(&pending_match_expiry_fhdef, &index->expiry_timers); } if (match) @@ -430,7 +428,7 @@ static void clear_pending_matches_by_local_guid(dds_security_context *sc, struct 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); + unregister_and_free_pending_match(index->gv, sc, match); } match = next; } @@ -450,7 +448,7 @@ static void clear_pending_matches_by_remote_guid(dds_security_context *sc, struc 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); + unregister_and_free_pending_match(index->gv, sc, match); match = next; } ddsrt_mutex_unlock(&index->lock); @@ -505,7 +503,7 @@ static struct proxypp_pp_match * proxypp_pp_match_new(struct participant *pp, DD return pm; } -static void proxypp_pp_match_free(struct dds_security_context *sc, struct proxypp_pp_match *pm) +static void proxypp_pp_match_free(struct ddsi_domaingv *gv, struct dds_security_context *sc, struct proxypp_pp_match *pm) { DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; @@ -517,8 +515,9 @@ static void proxypp_pp_match_free(struct dds_security_context *sc, struct proxyp * matching local and remote participant. */ #if 0 - EXCEPTION_ERROR(sc, &exception, "Failed to return remote permissions handle"); + EXCEPTION_ERROR(gv, &exception, "Failed to return remote permissions handle"); #else + DDSRT_UNUSED_ARG (gv); DDS_Security_Exception_reset(&exception); #endif } @@ -552,7 +551,7 @@ static void proxypp_pp_unrelate(struct dds_security_context *sc, struct proxy_pa if ((pm = ddsrt_avl_lookup_dpath(&proxypp_pp_treedef, &proxypp->sec_attr->participants, &pp_crypto_handle, &dpath)) != NULL) { ddsrt_avl_delete_dpath(&proxypp_pp_treedef, &proxypp->sec_attr->participants, pm, &dpath); - proxypp_pp_match_free(sc, pm); + proxypp_pp_match_free(proxypp->e.gv, sc, pm); } ddsrt_mutex_unlock(&proxypp->sec_attr->lock); } @@ -715,8 +714,6 @@ void q_omg_security_init (struct ddsi_domaingv *gv) pending_match_index_init(gv, &sc->security_matches); ddsrt_mutex_init (&sc->omg_security_lock); - sc->logcfg = &gv->logconfig; - gv->security_context = sc; ddsi_handshake_admin_init(gv); @@ -725,16 +722,16 @@ void q_omg_security_init (struct ddsi_domaingv *gv) /** * Releases all plugins */ -static void release_plugins (dds_security_context *sc) +static void release_plugins (struct ddsi_domaingv *gv, dds_security_context *sc) { if (dds_security_plugin_release (&sc->auth_plugin, sc->authentication_context)) - DDS_CERROR (sc->logcfg, "Error occurred releasing %s plugin", sc->auth_plugin.name); + GVERROR ("Error occurred releasing %s plugin", sc->auth_plugin.name); if (dds_security_plugin_release (&sc->crypto_plugin, sc->crypto_context)) - DDS_CERROR (sc->logcfg, "Error occurred releasing %s plugin", sc->crypto_plugin.name); + GVERROR ("Error occurred releasing %s plugin", sc->crypto_plugin.name); if (dds_security_plugin_release (&sc->ac_plugin, sc->access_control_context)) - DDS_CERROR (sc->logcfg, "Error occurred releasing %s plugin", sc->ac_plugin.name); + GVERROR ("Error occurred releasing %s plugin", sc->ac_plugin.name); sc->authentication_context = NULL; sc->access_control_context = NULL; @@ -758,9 +755,9 @@ void q_omg_security_free (struct ddsi_domaingv *gv) ddsrt_avl_cfree(&participant_index_treedef, &sc->partiticpant_index.participants, 0); ddsrt_mutex_destroy(&sc->partiticpant_index.lock); - if (sc->authentication_context != NULL && sc->access_control_context != NULL && sc->crypto_context != NULL){ - release_plugins (sc); - } + if (sc->authentication_context != NULL && sc->access_control_context != NULL && sc->crypto_context != NULL) + release_plugins (gv, sc); + ddsi_handshake_admin_deinit(gv); ddsrt_mutex_destroy (&sc->omg_security_lock); ddsrt_free(sc); @@ -801,7 +798,7 @@ static void deinit_plugin_suite_config (dds_security_plugin_suite_config *suite_ deinit_plugin_config (&suite_config->cryptography); } -dds_return_t q_omg_security_load (dds_security_context *sc, const dds_qos_t *qos) +dds_return_t q_omg_security_load (dds_security_context *sc, const dds_qos_t *qos, struct ddsi_domaingv *gv) { dds_security_plugin_suite_config psc; memset (&psc, 0, sizeof (psc)); @@ -812,31 +809,28 @@ dds_return_t q_omg_security_load (dds_security_context *sc, const dds_qos_t *qos dds_qos_to_security_plugin_configuration (qos, &psc); /* Check configuration content */ - if (dds_security_check_plugin_configuration (&psc, sc->logcfg) != DDS_RETCODE_OK) + if (dds_security_check_plugin_configuration (&psc, gv) != DDS_RETCODE_OK) goto error; - if (dds_security_load_security_library (&psc.authentication, &sc->auth_plugin, (void **) &sc->authentication_context, sc->logcfg) != DDS_RETCODE_OK) + if (dds_security_load_security_library (&psc.authentication, &sc->auth_plugin, (void **) &sc->authentication_context, gv) != DDS_RETCODE_OK) { - DDS_CERROR (sc->logcfg, "Could not load %s plugin.\n", sc->auth_plugin.name); + GVERROR ("Could not load %s plugin.\n", sc->auth_plugin.name); goto error; } - if (dds_security_load_security_library (&psc.access_control, &sc->ac_plugin, (void **) &sc->access_control_context, sc->logcfg) != DDS_RETCODE_OK) + if (dds_security_load_security_library (&psc.access_control, &sc->ac_plugin, (void **) &sc->access_control_context, gv) != DDS_RETCODE_OK) { - DDS_CERROR (sc->logcfg, "Could not load %s library\n", sc->ac_plugin.name); + GVERROR ("Could not load %s library\n", sc->ac_plugin.name); goto error; } - if (dds_security_load_security_library (&psc.cryptography, &sc->crypto_plugin, (void **) &sc->crypto_context, sc->logcfg) != DDS_RETCODE_OK) + if (dds_security_load_security_library (&psc.cryptography, &sc->crypto_plugin, (void **) &sc->crypto_context, gv) != DDS_RETCODE_OK) { - DDS_CERROR (sc->logcfg, "Could not load %s library\n", sc->crypto_plugin.name); + GVERROR ("Could not load %s library\n", sc->crypto_plugin.name); goto error; } /* now check if all plugin functions are implemented */ - if (dds_security_verify_plugin_functions ( - sc->authentication_context, &sc->auth_plugin, - sc->crypto_context, &sc->crypto_plugin, - sc->access_control_context, &sc->ac_plugin, - sc->logcfg) != DDS_RETCODE_OK) + if (dds_security_verify_plugin_functions (sc->authentication_context, &sc->auth_plugin, sc->crypto_context, &sc->crypto_plugin, + sc->access_control_context, &sc->ac_plugin, gv) != DDS_RETCODE_OK) { goto error_verify; } @@ -845,12 +839,12 @@ dds_return_t q_omg_security_load (dds_security_context *sc, const dds_qos_t *qos #if LISTENERS_IMPLEMENTED if (!access_control_context->set_listener (access_control_context, &listener_ac, &ex)) { - DDS_CERROR (sc->logcfg, "Could not set access_control listener: %s\n", ex.message ? ex.message : ""); + GVERROR ("Could not set access_control listener: %s\n", ex.message ? ex.message : ""); goto error_set_ac_listener; } if (!authentication_context->set_listener (authentication_context, &listener_auth, &ex)) { - DDS_CERROR (sc->logcfg, "Could not set authentication listener: %s\n", ex.message ? ex.message : ""); + GVERROR ("Could not set authentication listener: %s\n", ex.message ? ex.message : ""); goto err_set_auth_listener; } #endif @@ -861,7 +855,7 @@ dds_return_t q_omg_security_load (dds_security_context *sc, const dds_qos_t *qos deinit_plugin_suite_config (&psc); ddsrt_mutex_unlock (&sc->omg_security_lock); - DDS_CLOG (DDS_LC_TRACE, sc->logcfg, "DDS Security plugins have been loaded\n"); + GVTRACE ("DDS Security plugins have been loaded\n"); return DDS_RETCODE_OK; #if LISTENERS_IMPLEMENTED @@ -870,7 +864,7 @@ error_set_auth_listener: error_set_ac_listener: #endif error_verify: - release_plugins (sc); + release_plugins (gv, sc); error: deinit_plugin_suite_config (&psc); ddsrt_mutex_unlock (&sc->omg_security_lock); @@ -907,6 +901,7 @@ dds_return_t q_omg_security_check_create_participant(struct participant *pp, uin { dds_return_t ret = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY; struct dds_security_context *sc = q_omg_security_get_secure_context(pp); + struct ddsi_domaingv *gv = pp->e.gv; DDS_Security_IdentityHandle identity_handle = DDS_SECURITY_HANDLE_NIL; DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; DDS_Security_ValidationResult_t result = 0; @@ -933,7 +928,7 @@ dds_return_t q_omg_security_check_create_participant(struct participant *pp, uin (DDS_Security_GUID_t *) &candidate_guid, &exception); if (result != DDS_SECURITY_VALIDATION_OK) { - EXCEPTION_ERROR(sc, &exception, "Error occurred while validating local permission"); + EXCEPTION_ERROR(gv, &exception, "Error occurred while validating local permission"); goto validation_failed; } pp->e.guid = nn_ntoh_guid(adjusted_guid); @@ -946,7 +941,7 @@ dds_return_t q_omg_security_check_create_participant(struct participant *pp, uin /* Get the identity token and add this to the plist of the participant */ if (!sc->authentication_context->get_identity_token(sc->authentication_context, &identity_token, identity_handle, &exception)) { - EXCEPTION_ERROR(sc, &exception, "Error occurred while retrieving the identity token"); + EXCEPTION_ERROR(gv, &exception, "Error occurred while retrieving the identity token"); goto validation_failed; } assert(exception.code == 0); @@ -958,23 +953,24 @@ dds_return_t q_omg_security_check_create_participant(struct participant *pp, uin sec_attr->permissions_handle = sc->access_control_context->validate_local_permissions( sc->access_control_context, sc->authentication_context, identity_handle, (DDS_Security_DomainId)domain_id, &par_qos, &exception); + if (sec_attr->permissions_handle == DDS_SECURITY_HANDLE_NIL) { - EXCEPTION_ERROR(sc, &exception, "Error occurred while validating local permissions"); + EXCEPTION_ERROR(gv, &exception, "Error occurred while validating local permissions"); goto not_allowed; } /* ask to access control security plugin for create participant permissions related to this identity*/ if (!sc->access_control_context->check_create_participant(sc->access_control_context, sec_attr->permissions_handle, (DDS_Security_DomainId) domain_id, &par_qos, &exception)) { - EXCEPTION_ERROR(sc, &exception, "It is not allowed to create participant"); + EXCEPTION_ERROR(gv, &exception, "It is not allowed to create participant"); goto not_allowed; } /* Get the identity token and add this to the plist of the participant */ if (!sc->access_control_context->get_permissions_token(sc->access_control_context, &permissions_token, sec_attr->permissions_handle, &exception)) { - EXCEPTION_ERROR(sc, &exception, "Error occurred while retrieving the permissions token"); + EXCEPTION_ERROR(gv, &exception, "Error occurred while retrieving the permissions token"); goto not_allowed; } @@ -983,19 +979,19 @@ dds_return_t q_omg_security_check_create_participant(struct participant *pp, uin if (!sc->access_control_context->get_permissions_credential_token(sc->access_control_context, &credential_token, sec_attr->permissions_handle, &exception)) { - EXCEPTION_ERROR(sc, &exception, "Error occurred while retrieving the permissions credential token"); + EXCEPTION_ERROR(gv, &exception, "Error occurred while retrieving the permissions credential token"); goto no_credentials; } if (!sc->authentication_context->set_permissions_credential_and_token(sc->authentication_context, sec_attr->local_identity_handle, &credential_token, &permissions_token, &exception)) { - EXCEPTION_ERROR(sc, &exception, "Error occurred while setting the permissions credential token"); + EXCEPTION_ERROR(gv, &exception, "Error occurred while setting the permissions credential token"); goto no_credentials; } if (!sc->access_control_context->get_participant_sec_attributes(sc->access_control_context, sec_attr->permissions_handle, &sec_attr->attr, &exception)) { - EXCEPTION_ERROR(sc, &exception, "Failed to get participant security attributes"); + EXCEPTION_ERROR(gv, &exception, "Failed to get participant security attributes"); goto no_sec_attr; } @@ -1003,7 +999,7 @@ dds_return_t q_omg_security_check_create_participant(struct participant *pp, uin sec_attr->crypto_handle = sc->crypto_context->crypto_key_factory->register_local_participant( sc->crypto_context->crypto_key_factory, sec_attr->local_identity_handle, sec_attr->permissions_handle, NULL, &sec_attr->attr, &exception); if (!sec_attr->crypto_handle) { - EXCEPTION_ERROR(sc, &exception, "Failed to register participant with crypto key factory"); + EXCEPTION_ERROR(gv, &exception, "Failed to register participant with crypto key factory"); goto no_crypto; } @@ -1089,21 +1085,21 @@ static void cleanup_participant_sec_attributes(void *arg) if (attr->permissions_handle != DDS_SECURITY_HANDLE_NIL) { if (!sc->access_control_context->return_permissions_handle(sc->access_control_context, attr->permissions_handle, &exception)) - EXCEPTION_ERROR(sc, &exception, "Failed to return local permissions handle"); + EXCEPTION_ERROR(gv, &exception, "Failed to return local permissions handle"); } if (attr->local_identity_handle != DDS_SECURITY_HANDLE_NIL) { if (!sc->authentication_context->return_identity_handle(sc->authentication_context, attr->local_identity_handle, &exception)) - EXCEPTION_ERROR(sc, &exception, "Failed to return local identity handle"); + EXCEPTION_ERROR(gv, &exception, "Failed to return local identity handle"); } if (attr->plugin_attr) { if (!sc->access_control_context->return_participant_sec_attributes(sc->access_control_context, &attr->attr, &exception)) - EXCEPTION_ERROR(sc, &exception, "Failed to return participant security attributes"); + EXCEPTION_ERROR(gv, &exception, "Failed to return participant security attributes"); } if (!sc->crypto_context->crypto_key_factory->unregister_participant(sc->crypto_context->crypto_key_factory, attr->crypto_handle, &exception)) - EXCEPTION_ERROR(sc, &exception, "Failed to unregister participant"); + EXCEPTION_ERROR(gv, &exception, "Failed to unregister participant"); ddsrt_avl_cfree(&pp_proxypp_treedef, &attr->proxy_participants, NULL); ddsrt_mutex_unlock(&attr->lock); @@ -1286,7 +1282,7 @@ bool q_omg_security_check_create_topic(const struct ddsi_domaingv *gv, const dds { /*log if the topic discovery is not protected*/ if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, topic_name)) - EXCEPTION_ERROR(sc, &exception, "Local topic permission denied"); + EXCEPTION_ERROR(gv, &exception, "Local topic permission denied"); else DDS_Security_Exception_reset(&exception); } @@ -1320,7 +1316,7 @@ bool q_omg_security_check_create_writer(struct participant *pp, uint32_t domain_ { /*log if the topic discovery is not protected*/ if (!is_topic_discovery_protected( pp->sec_attr->permissions_handle, sc->access_control_context, topic_name)) - EXCEPTION_ERROR(sc, &exception, "Local topic permission denied"); + EXCEPTION_ERROR(pp->e.gv, &exception, "Local topic permission denied"); else DDS_Security_Exception_reset(&exception); } @@ -1350,7 +1346,7 @@ void q_omg_security_register_writer(struct writer *wr) wr->sec_attr = writer_sec_attributes_new(); if (!sc->access_control_context->get_datawriter_sec_attributes(sc->access_control_context, pp->sec_attr->permissions_handle, wr->topic->name, &partitions, NULL, &wr->sec_attr->attr, &exception)) { - EXCEPTION_ERROR(sc, &exception, "Failed to retrieve writer security attributes"); + EXCEPTION_ERROR(pp->e.gv, &exception, "Failed to retrieve writer security attributes"); goto no_attr; } wr->sec_attr->plugin_attr = true; @@ -1367,7 +1363,7 @@ void q_omg_security_register_writer(struct writer *wr) DDS_Security_PropertySeq_freebuf(&properties); if (wr->sec_attr->crypto_handle == DDS_SECURITY_HANDLE_NIL) { - EXCEPTION_ERROR(sc, &exception, "Failed to register writer with crypto"); + EXCEPTION_ERROR(pp->e.gv, &exception, "Failed to register writer with crypto"); goto not_registered; } } @@ -1392,12 +1388,12 @@ void q_omg_security_deregister_writer(struct writer *wr) 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)) - EXCEPTION_ERROR(sc, &exception, "Failed to unregister writer with crypto"); + EXCEPTION_ERROR(wr->e.gv, &exception, "Failed to unregister writer with crypto"); } if (wr->sec_attr->plugin_attr) { if (!sc->access_control_context->return_datawriter_sec_attributes(sc->access_control_context, &wr->sec_attr->attr, &exception)) - EXCEPTION_ERROR(sc, &exception, "Failed to return writer security attributes"); + EXCEPTION_ERROR(wr->e.gv, &exception, "Failed to return writer security attributes"); } writer_sec_attributes_free(wr->sec_attr); wr->sec_attr = NULL; @@ -1441,7 +1437,7 @@ bool q_omg_security_check_create_reader(struct participant *pp, uint32_t domain_ { /*log if the topic discovery is not protected*/ if (!is_topic_discovery_protected( pp->sec_attr->permissions_handle, sc->access_control_context, topic_name)) - EXCEPTION_ERROR(sc, &exception, "Reader is not permitted"); + EXCEPTION_ERROR(pp->e.gv, &exception, "Reader is not permitted"); else DDS_Security_Exception_reset(&exception); } @@ -1472,7 +1468,7 @@ void q_omg_security_register_reader(struct reader *rd) if (!sc->access_control_context->get_datareader_sec_attributes(sc->access_control_context, pp->sec_attr->permissions_handle, rd->topic->name, &partitions, NULL, &rd->sec_attr->attr, &exception)) { - EXCEPTION_ERROR(sc, &exception, "Failed to retrieve reader security attributes"); + EXCEPTION_ERROR(pp->e.gv, &exception, "Failed to retrieve reader security attributes"); goto no_attr; } rd->sec_attr->plugin_attr = true; @@ -1489,7 +1485,7 @@ void q_omg_security_register_reader(struct reader *rd) DDS_Security_PropertySeq_freebuf(&properties); if (rd->sec_attr->crypto_handle == DDS_SECURITY_HANDLE_NIL) { - EXCEPTION_ERROR(sc, &exception, "Failed to register reader with crypto"); + EXCEPTION_ERROR(pp->e.gv, &exception, "Failed to register reader with crypto"); goto not_registered; } } @@ -1514,14 +1510,14 @@ void q_omg_security_deregister_reader(struct reader *rd) { if (!sc->crypto_context->crypto_key_factory->unregister_datareader(sc->crypto_context->crypto_key_factory, rd->sec_attr->crypto_handle, &exception)) { - EXCEPTION_ERROR(sc, &exception, "Failed to unregister reader with crypto"); + EXCEPTION_ERROR(rd->e.gv, &exception, "Failed to unregister reader with crypto"); } } if (rd->sec_attr->plugin_attr) { if (!sc->access_control_context->return_datareader_sec_attributes(sc->access_control_context, &rd->sec_attr->attr, &exception)) { - EXCEPTION_ERROR(sc, &exception, "Failed to return reader security attributes"); + EXCEPTION_ERROR(rd->e.gv, &exception, "Failed to return reader security attributes"); } } reader_sec_attributes_free(rd->sec_attr); @@ -1567,6 +1563,7 @@ static int64_t check_remote_participant_permissions(uint32_t domain_id, struct p DDS_Security_PermissionsToken permissions_token = DDS_SECURITY_TOKEN_INIT; DDS_Security_AuthenticatedPeerCredentialToken peer_credential_token = DDS_SECURITY_TOKEN_INIT; int64_t permissions_hdl = DDS_SECURITY_HANDLE_NIL; + struct ddsi_domaingv *gv = pp->e.gv; if (proxypp->plist->present & PP_PERMISSIONS_TOKEN) q_omg_shallow_copyin_DataHolder(&permissions_token, &proxypp->plist->permissions_token); @@ -1576,21 +1573,20 @@ static int64_t check_remote_participant_permissions(uint32_t domain_id, struct p handshake = ddsi_handshake_find(pp, proxypp); if (!handshake) { - ELOG(DDS_LC_ERROR, pp, "Could not find handshake local participant "PGUIDFMT" and remote participant "PGUIDFMT, - PGUID(pp->e.guid), PGUID(proxypp->e.guid)); - goto no_handshake; + GVTRACE("Could not find handshake local participant "PGUIDFMT" and remote participant "PGUIDFMT, PGUID(pp->e.guid), PGUID(proxypp->e.guid)); + goto no_handshake; } if (!sc->authentication_context->get_authenticated_peer_credential_token(sc->authentication_context, &peer_credential_token, ddsi_handshake_get_handle(handshake), &exception)) { if (q_omg_participant_is_access_protected(pp)) { - EXCEPTION_ERROR(sc, &exception, "Could not authenticate_peer_credential_token for local participan1152t "PGUIDFMT" and remote participant "PGUIDFMT, + EXCEPTION_ERROR(gv, &exception, "Could not authenticate_peer_credential_token for local participan1152t "PGUIDFMT" and remote participant "PGUIDFMT, PGUID(pp->e.guid), PGUID(proxypp->e.guid)); goto no_credentials; } /* Failing is allowed due to the non-protection of access. */ - EXCEPTION_WARNING(sc, &exception, "Could not authenticate_peer_credential_token for local participant "PGUIDFMT" and remote participant "PGUIDFMT , + EXCEPTION_WARNING(gv, &exception, "Could not authenticate_peer_credential_token for local participant "PGUIDFMT" and remote participant "PGUIDFMT , PGUID(pp->e.guid), PGUID(proxypp->e.guid)); } @@ -1600,11 +1596,11 @@ static int64_t check_remote_participant_permissions(uint32_t domain_id, struct p { if (q_omg_participant_is_access_protected(pp)) { - EXCEPTION_ERROR(sc, &exception, "Could not get remote participant "PGUIDFMT" permissions from plugin", PGUID(proxypp->e.guid)); + EXCEPTION_ERROR(gv, &exception, "Could not get remote participant "PGUIDFMT" permissions from plugin", PGUID(proxypp->e.guid)); goto no_permissions; } /* Failing is allowed due to the non-protection of access. */ - EXCEPTION_WARNING(sc, &exception, "Could not get remote participant "PGUIDFMT" permissions from plugin", PGUID(proxypp->e.guid)); + EXCEPTION_WARNING(gv, &exception, "Could not get remote participant "PGUIDFMT" permissions from plugin", PGUID(proxypp->e.guid)); } /* Only check remote participant if joining access is protected. */ @@ -1615,11 +1611,9 @@ static int64_t check_remote_participant_permissions(uint32_t domain_id, struct p q_omg_shallow_copy_ParticipantBuiltinTopicDataSecure(&participant_data, &(proxypp->e.guid), proxypp->plist); if (!sc->access_control_context->check_remote_participant(sc->access_control_context, permissions_hdl, (DDS_Security_DomainId)domain_id, &participant_data, &exception)) { - EXCEPTION_WARNING(sc, &exception, "Plugin does not allow remote participant "PGUIDFMT, PGUID(proxypp->e.guid)); + EXCEPTION_WARNING(gv, &exception, "Plugin does not allow remote participant "PGUIDFMT, PGUID(proxypp->e.guid)); if (!sc->access_control_context->return_permissions_handle(sc->access_control_context, permissions_hdl, &exception)) - { - EXCEPTION_ERROR(sc, &exception, "Failed to return remote permissions handle"); - } + EXCEPTION_ERROR(gv, &exception, "Failed to return remote permissions handle"); permissions_hdl = DDS_SECURITY_HANDLE_NIL; } q_omg_shallow_free_ParticipantBuiltinTopicDataSecure(&participant_data); @@ -1627,9 +1621,7 @@ static int64_t check_remote_participant_permissions(uint32_t domain_id, struct p no_permissions: if (!sc->authentication_context->return_authenticated_peer_credential_token(sc->authentication_context, &peer_credential_token, &exception)) - { - EXCEPTION_ERROR(sc, &exception, "Failed to return peer credential token"); - } + EXCEPTION_ERROR(gv, &exception, "Failed to return peer credential token"); no_credentials: ddsi_handshake_release(handshake); no_handshake: @@ -1646,7 +1638,7 @@ static void send_participant_crypto_tokens(struct participant *pp, struct proxy_ r = sc->crypto_context->crypto_key_exchange->create_local_participant_crypto_tokens(sc->crypto_context->crypto_key_exchange, &tokens, local_crypto, remote_crypto, &exception); if (!r) - EXCEPTION_ERROR(sc, &exception, "Failed to create local participant crypto tokens "PGUIDFMT" for remote participant "PGUIDFMT, PGUID(pp->e.guid), PGUID(proxypp->e.guid)); + EXCEPTION_ERROR(pp->e.gv, &exception, "Failed to create local participant crypto tokens "PGUIDFMT" for remote participant "PGUIDFMT, PGUID(pp->e.guid), PGUID(proxypp->e.guid)); else if (tokens._length > 0) { nn_dataholderseq_t tholder; @@ -1656,7 +1648,7 @@ static void send_participant_crypto_tokens(struct participant *pp, struct proxy_ q_omg_shallow_free_nn_dataholderseq(&tholder); if (!sc->crypto_context->crypto_key_exchange->return_crypto_tokens(sc->crypto_context->crypto_key_exchange, &tokens, &exception)) - EXCEPTION_ERROR(sc, &exception, "Failed to return local participant crypto tokens "PGUIDFMT" for remote participant "PGUIDFMT, PGUID(pp->e.guid), PGUID(proxypp->e.guid)); + EXCEPTION_ERROR(pp->e.gv, &exception, "Failed to return local participant crypto tokens "PGUIDFMT" for remote participant "PGUIDFMT, PGUID(pp->e.guid), PGUID(proxypp->e.guid)); } } @@ -1758,7 +1750,7 @@ bool q_omg_security_register_remote_participant(struct participant *pp, struct p sc->crypto_context->crypto_key_factory, pp->sec_attr->crypto_handle, proxypp->sec_attr->remote_identity_handle, permissions_handle, shared_secret, &exception); if (crypto_handle == DDS_SECURITY_HANDLE_NIL) { - EXCEPTION_ERROR(sc, &exception, "Failed to register matched remote participant "PGUIDFMT" with participant "PGUIDFMT, PGUID(proxypp->e.guid), PGUID(pp->e.guid)); + EXCEPTION_ERROR(gv, &exception, "Failed to register matched remote participant "PGUIDFMT" with participant "PGUIDFMT, PGUID(proxypp->e.guid), PGUID(pp->e.guid)); ret = false; goto register_failed; } @@ -1779,7 +1771,7 @@ bool q_omg_security_register_remote_participant(struct participant *pp, struct p { 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)); + EXCEPTION_ERROR(gv, &exception, " Failed to set remote participant crypto tokens "PGUIDFMT" --> "PGUIDFMT, PGUID(proxypp->e.guid), PGUID(pp->e.guid)); else 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); @@ -1832,7 +1824,8 @@ void q_omg_security_deregister_remote_participant(struct proxy_participant *prox struct ddsi_domaingv *gv = proxypp->e.gv; DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; - if (proxypp->sec_attr) { + if (proxypp->sec_attr) + { dds_security_context *sc = proxypp->sec_attr->sc; struct proxypp_pp_match *pm; struct participant *pp; @@ -1841,12 +1834,10 @@ void q_omg_security_deregister_remote_participant(struct proxy_participant *prox while (pm) { struct proxypp_pp_match *next = ddsrt_avl_find_succ(&proxypp_pp_treedef, &proxypp->sec_attr->participants, pm); - ddsrt_avl_delete(&proxypp_pp_treedef, &proxypp->sec_attr->participants, pm); - pp = entidx_lookup_participant_guid(gv->entity_index, &pm->pp_guid); - if (pp) + if ((pp = entidx_lookup_participant_guid(gv->entity_index, &pm->pp_guid)) != NULL) pp_proxypp_unrelate(sc, pp, &proxypp->e.guid); - proxypp_pp_match_free(sc, pm); + proxypp_pp_match_free(gv, sc, pm); pm = next; } @@ -1854,14 +1845,14 @@ void q_omg_security_deregister_remote_participant(struct proxy_participant *prox 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)) - EXCEPTION_ERROR(sc, &exception, "2:Failed to return remote crypto handle"); + if (!sc->crypto_context->crypto_key_factory->unregister_participant(sc->crypto_context->crypto_key_factory, proxypp->sec_attr->crypto_handle, &exception)) + EXCEPTION_ERROR(gv, &exception, "2:Failed to return remote crypto handle"); } if (proxypp->sec_attr->remote_identity_handle != DDS_SECURITY_HANDLE_NIL) { - if (!sc->authentication_context->return_identity_handle(sc->authentication_context, proxypp->sec_attr->remote_identity_handle, &exception)) - EXCEPTION_ERROR(sc, &exception, "Failed to return remote identity handle"); + if (!sc->authentication_context->return_identity_handle(sc->authentication_context, proxypp->sec_attr->remote_identity_handle, &exception)) + EXCEPTION_ERROR(gv, &exception, "Failed to return remote identity handle"); } ddsrt_mutex_destroy(&proxypp->sec_attr->lock); @@ -1960,7 +1951,7 @@ void q_omg_security_set_participant_crypto_tokens(struct participant *pp, struct 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(gv, &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); @@ -2054,7 +2045,7 @@ bool q_omg_security_check_remote_writer_permissions(const struct proxy_writer *p if (!ok) { if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, publication_data.topic_name)) - EXCEPTION_ERROR(sc, &exception, "Access control does not allow remote writer "PGUIDFMT": %s", PGUID(pwr->e.guid)); + EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote writer "PGUIDFMT": %s", PGUID(pwr->e.guid)); else DDS_Security_Exception_reset(&exception); } @@ -2076,7 +2067,7 @@ static void send_reader_crypto_tokens(struct reader *rd, struct proxy_writer *pw r = sc->crypto_context->crypto_key_exchange->create_local_datareader_crypto_tokens(sc->crypto_context->crypto_key_exchange, &tokens, local_crypto, remote_crypto, &exception); if (!r) - EXCEPTION_ERROR(sc, &exception,"Failed to create local reader crypto tokens "PGUIDFMT" for remote writer "PGUIDFMT, PGUID(rd->e.guid), PGUID(pwr->e.guid)); + EXCEPTION_ERROR(gv, &exception,"Failed to create local reader crypto tokens "PGUIDFMT" for remote writer "PGUIDFMT, PGUID(rd->e.guid), PGUID(pwr->e.guid)); else if (tokens._length > 0) { nn_dataholderseq_t tholder; @@ -2086,7 +2077,7 @@ static void send_reader_crypto_tokens(struct reader *rd, struct proxy_writer *pw q_omg_shallow_free_nn_dataholderseq(&tholder); if (!sc->crypto_context->crypto_key_exchange->return_crypto_tokens(sc->crypto_context->crypto_key_exchange, &tokens, &exception)) - EXCEPTION_ERROR(sc, &exception, "Failed to return local reader crypto tokens "PGUIDFMT" for remote writer "PGUIDFMT, PGUID(rd->e.guid), PGUID(pwr->e.guid)); + EXCEPTION_ERROR(gv, &exception, "Failed to return local reader crypto tokens "PGUIDFMT" for remote writer "PGUIDFMT, PGUID(rd->e.guid), PGUID(pwr->e.guid)); } } @@ -2121,7 +2112,7 @@ static bool q_omg_security_register_remote_writer_match(struct proxy_writer *pwr allowed = true; } else - EXCEPTION_ERROR(sc, &exception, "Failed to register remote writer "PGUIDFMT" with reader "PGUIDFMT, PGUID(pwr->e.guid), PGUID(rd->e.guid)); + EXCEPTION_ERROR(gv, &exception, "Failed to register remote writer "PGUIDFMT" with reader "PGUIDFMT, PGUID(pwr->e.guid), PGUID(rd->e.guid)); } else { @@ -2133,7 +2124,7 @@ static bool q_omg_security_register_remote_writer_match(struct proxy_writer *pwr *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)); + EXCEPTION_ERROR(gv, &exception, "Failed to register remote writer "PGUIDFMT" with reader "PGUIDFMT, PGUID(pwr->e.guid), PGUID(rd->e.guid)); else { pending_match->crypto_handle = *crypto_handle; @@ -2142,7 +2133,7 @@ static bool q_omg_security_register_remote_writer_match(struct proxy_writer *pwr { 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)); + EXCEPTION_ERROR(gv, &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)); @@ -2227,7 +2218,7 @@ void q_omg_security_deregister_remote_writer_match(const struct ddsi_domaingv *g if (m->crypto_handle != 0) { 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)); + EXCEPTION_ERROR(gv, &exception, "Failed to unregister remote writer "PGUIDFMT" for reader "PGUIDFMT, PGUID(m->pwr_guid), PGUID(*rd_guid)); } } @@ -2289,7 +2280,7 @@ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *p else { if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, subscription_data.topic_name)) - EXCEPTION_ERROR(sc, &exception, "Access control does not allow remote reader "PGUIDFMT": %s", PGUID(prd->e.guid)); + EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote reader "PGUIDFMT": %s", PGUID(prd->e.guid)); else DDS_Security_Exception_reset(&exception); } @@ -2383,7 +2374,7 @@ void q_omg_security_deregister_remote_reader_match(const struct ddsi_domaingv *g if (m->crypto_handle != 0) { 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)); + EXCEPTION_ERROR(gv, &exception, "Failed to unregister remote reader "PGUIDFMT" for writer "PGUIDFMT, PGUID(m->prd_guid), PGUID(*wr_guid)); } } @@ -2408,7 +2399,7 @@ static void send_writer_crypto_tokens(struct writer *wr, struct proxy_reader *pr r = sc->crypto_context->crypto_key_exchange->create_local_datawriter_crypto_tokens(sc->crypto_context->crypto_key_exchange, &tokens, local_crypto, remote_crypto, &exception); if (!r) - EXCEPTION_ERROR(sc, &exception,"Failed to create local writer crypto tokens "PGUIDFMT" for remote reader "PGUIDFMT, PGUID(wr->e.guid), PGUID(prd->e.guid)); + EXCEPTION_ERROR(gv, &exception,"Failed to create local writer crypto tokens "PGUIDFMT" for remote reader "PGUIDFMT, PGUID(wr->e.guid), PGUID(prd->e.guid)); else if (tokens._length > 0) { nn_dataholderseq_t tholder; @@ -2418,7 +2409,7 @@ static void send_writer_crypto_tokens(struct writer *wr, struct proxy_reader *pr q_omg_shallow_free_nn_dataholderseq(&tholder); if (!sc->crypto_context->crypto_key_exchange->return_crypto_tokens(sc->crypto_context->crypto_key_exchange, &tokens, &exception)) - EXCEPTION_ERROR(sc, &exception, "Failed to return local writer crypto tokens "PGUIDFMT" for remote reader "PGUIDFMT, PGUID(wr->e.guid), PGUID(prd->e.guid)); + EXCEPTION_ERROR(gv, &exception, "Failed to return local writer crypto tokens "PGUIDFMT" for remote reader "PGUIDFMT, PGUID(wr->e.guid), PGUID(prd->e.guid)); } } @@ -2454,7 +2445,7 @@ static bool q_omg_security_register_remote_reader_match(struct proxy_reader *prd allowed = true; } else - EXCEPTION_ERROR(sc, &exception, "Failed to register remote reader "PGUIDFMT" with writer "PGUIDFMT, PGUID(prd->e.guid), PGUID(wr->e.guid)); + EXCEPTION_ERROR(gv, &exception, "Failed to register remote reader "PGUIDFMT" with writer "PGUIDFMT, PGUID(prd->e.guid), PGUID(wr->e.guid)); } else { @@ -2466,7 +2457,7 @@ static bool q_omg_security_register_remote_reader_match(struct proxy_reader *prd *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)); + EXCEPTION_ERROR(gv, &exception, "Failed to register remote reader "PGUIDFMT" with writer "PGUIDFMT, PGUID(prd->e.guid), PGUID(wr->e.guid)); else { pending_match->crypto_handle = *crypto_handle; @@ -2476,7 +2467,7 @@ static bool q_omg_security_register_remote_reader_match(struct proxy_reader *prd { 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)); + EXCEPTION_ERROR(gv, &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)); @@ -2575,7 +2566,7 @@ void q_omg_security_set_remote_writer_crypto_tokens(struct reader *rd, const dds 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)) - EXCEPTION_ERROR(sc, &exception, "Failed to set remote writer crypto tokens "PGUIDFMT" for reader "PGUIDFMT, PGUID(pwr->e.guid), PGUID(rd->e.guid)); + EXCEPTION_ERROR(gv, &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)); @@ -2614,7 +2605,7 @@ void q_omg_security_set_remote_reader_crypto_tokens(struct writer *wr, const dds 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)); + EXCEPTION_ERROR(gv, &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)); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index dfd2433..2669c09 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -858,7 +858,7 @@ static dds_return_t check_and_load_security_config (struct ddsi_domaingv * const GVLOGDISC ("new_participant("PGUIDFMT"): security is already loaded for this domain\n", PGUID (*ppguid)); return DDS_RETCODE_OK; } - else if (q_omg_security_load (gv->security_context, qos) < 0) + else if (q_omg_security_load (gv->security_context, qos, gv) < 0) { GVERROR ("Could not load security\n"); return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY; diff --git a/src/security/api/CMakeLists.txt b/src/security/api/CMakeLists.txt index 02586c6..fe9e0b4 100644 --- a/src/security/api/CMakeLists.txt +++ b/src/security/api/CMakeLists.txt @@ -17,6 +17,7 @@ target_include_directories( security_api INTERFACE "$" "$" + "$" ) install( diff --git a/src/security/api/include/dds/security/dds_security_api.h b/src/security/api/include/dds/security/dds_security_api.h index ba29184..55ab6a0 100644 --- a/src/security/api/include/dds/security/dds_security_api.h +++ b/src/security/api/include/dds/security/dds_security_api.h @@ -13,8 +13,7 @@ #ifndef DDS_SECURITY_API_H #define DDS_SECURITY_API_H - -/* Various security plugins. */ +#include "dds/ddsi/ddsi_domaingv.h" #include "dds_security_api_access_control.h" #include "dds_security_api_authentication.h" #include "dds_security_api_cryptography.h" @@ -24,25 +23,12 @@ extern "C" { #endif - -/** - * Integration functions for Security plugins - * - */ - -typedef int (*plugin_init)( - const char *argument, - void **context - ); - -typedef int (*plugin_finalize)( - void *context - ); - +/* Integration functions for Security plugins */ +typedef int (*plugin_init)(const char *argument, void **context, struct ddsi_domaingv *gv); +typedef int (*plugin_finalize)(void *context); #if defined (__cplusplus) } #endif - #endif /* DDS_SECURITY_API_H */ diff --git a/src/security/api/include/dds/security/dds_security_api_access_control.h b/src/security/api/include/dds/security/dds_security_api_access_control.h index 8b908b5..5bc7f26 100644 --- a/src/security/api/include/dds/security/dds_security_api_access_control.h +++ b/src/security/api/include/dds/security/dds_security_api_access_control.h @@ -16,359 +16,278 @@ #include "dds_security_api_types.h" #include "dds_security_api_authentication.h" -#if defined (__cplusplus) -extern "C" { +#if defined(__cplusplus) +extern "C" +{ #endif - - -/** - * AccessControl Component - */ +/* AccessControl Component */ struct dds_security_access_control; typedef struct dds_security_access_control dds_security_access_control; + +/* AccessControlListener Interface */ struct dds_security_access_control_listener; typedef struct dds_security_access_control_listener dds_security_access_control_listener; - -/** - * AccessControlListener Interface - * */ - - -typedef DDS_Security_boolean -(*DDS_Security_access_control_listener_on_revoke_permissions) - ( dds_security_access_control_listener *instance, - const dds_security_access_control *plugin, - const DDS_Security_PermissionsHandle handle); +typedef DDS_Security_boolean (*DDS_Security_access_control_listener_on_revoke_permissions)( + const dds_security_access_control *plugin, + const DDS_Security_PermissionsHandle handle); struct dds_security_access_control_listener { DDS_Security_access_control_listener_on_revoke_permissions on_revoke_permissions; }; +/* AccessControl Interface */ +typedef DDS_Security_PermissionsHandle (*DDS_Security_access_control_validate_local_permissions)( + dds_security_access_control *instance, + const dds_security_authentication *auth_plugin, + const DDS_Security_IdentityHandle identity, + const DDS_Security_DomainId domain_id, + const DDS_Security_Qos *participant_qos, + DDS_Security_SecurityException *ex); -/** - * AccessControl Interface - */ +typedef DDS_Security_PermissionsHandle (*DDS_Security_access_control_validate_remote_permissions)( + dds_security_access_control *instance, + const dds_security_authentication *auth_plugin, + const DDS_Security_IdentityHandle local_identity_handle, + const DDS_Security_IdentityHandle remote_identity_handle, + const DDS_Security_PermissionsToken *remote_permissions_token, + const DDS_Security_AuthenticatedPeerCredentialToken *remote_credential_token, + DDS_Security_SecurityException *ex); -typedef DDS_Security_PermissionsHandle -(*DDS_Security_access_control_validate_local_permissions) - ( dds_security_access_control *instance, - const dds_security_authentication *auth_plugin, - const DDS_Security_IdentityHandle identity, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_check_create_participant)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_Qos *participant_qos, + DDS_Security_SecurityException *ex); -typedef DDS_Security_PermissionsHandle -(*DDS_Security_access_control_validate_remote_permissions) - ( dds_security_access_control *instance, - const dds_security_authentication *auth_plugin, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityHandle remote_identity_handle, - const DDS_Security_PermissionsToken *remote_permissions_token, - const DDS_Security_AuthenticatedPeerCredentialToken *remote_credential_token, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_check_create_datawriter)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_char *topic_name, + const DDS_Security_Qos *writer_qos, + const DDS_Security_PartitionQosPolicy *partition, + const DDS_Security_DataTags *data_tag, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_check_create_participant) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_check_create_datareader)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_char *topic_name, + const DDS_Security_Qos *reader_qos, + const DDS_Security_PartitionQosPolicy *partition, + const DDS_Security_DataTags *data_tag, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_check_create_datawriter) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_char *topic_name, - const DDS_Security_Qos *writer_qos, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTags *data_tag, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_check_create_topic)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_char *topic_name, + const DDS_Security_Qos *topic_qos, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_check_create_datareader) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_char *topic_name, - const DDS_Security_Qos *reader_qos, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTags *data_tag, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_check_local_datawriter_register_instance)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_Entity *writer, + const DDS_Security_DynamicData *key, + DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_check_local_datawriter_dispose_instance)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_Entity *writer, + const DDS_Security_DynamicData key, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_check_create_topic) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_char *topic_name, - const DDS_Security_Qos *topic_qos, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_check_remote_participant)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_ParticipantBuiltinTopicDataSecure *participant_data, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_check_local_datawriter_register_instance) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *writer, - const DDS_Security_DynamicData *key, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_check_remote_datawriter)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_check_local_datawriter_dispose_instance) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *writer, - const DDS_Security_DynamicData key, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_check_remote_datareader)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, + DDS_Security_boolean *relay_only, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_check_remote_participant) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_ParticipantBuiltinTopicDataSecure *participant_data, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_check_remote_topic)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_DomainId domain_id, + const DDS_Security_TopicBuiltinTopicData *topic_data, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_check_remote_datawriter) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_check_local_datawriter_match)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle writer_permissions_handle, + const DDS_Security_PermissionsHandle reader_permissions_handle, + const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, + const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_check_remote_datareader) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, - DDS_Security_boolean *relay_only, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_check_local_datareader_match)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle reader_permissions_handle, + const DDS_Security_PermissionsHandle writer_permissions_handle, + const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, + const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_check_remote_topic) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_DomainId domain_id, - const DDS_Security_TopicBuiltinTopicData *topic_data, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_check_remote_datawriter_register_instance)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_Entity *reader, + const DDS_Security_InstanceHandle publication_handle, + const DDS_Security_DynamicData key, + const DDS_Security_InstanceHandle instance_handle, + DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_check_remote_datawriter_dispose_instance)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_Entity *reader, + const DDS_Security_InstanceHandle publication_handle, + const DDS_Security_DynamicData key, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_check_local_datawriter_match) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle writer_permissions_handle, - const DDS_Security_PermissionsHandle reader_permissions_handle, - const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, - const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_get_permissions_token)( + dds_security_access_control *instance, + DDS_Security_PermissionsToken *permissions_token, + const DDS_Security_PermissionsHandle handle, + DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_get_permissions_credential_token)( + dds_security_access_control *instance, + DDS_Security_PermissionsCredentialToken *permissions_credential_token, + const DDS_Security_PermissionsHandle handle, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_check_local_datareader_match) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle reader_permissions_handle, - const DDS_Security_PermissionsHandle writer_permissions_handle, - const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, - const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_set_listener)( + dds_security_access_control *instance, + const dds_security_access_control_listener *listener, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_check_remote_datawriter_register_instance) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *reader, - const DDS_Security_InstanceHandle publication_handle, - const DDS_Security_DynamicData key, - const DDS_Security_InstanceHandle instance_handle, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_return_permissions_token)( + dds_security_access_control *instance, + const DDS_Security_PermissionsToken *token, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_check_remote_datawriter_dispose_instance) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_Entity *reader, - const DDS_Security_InstanceHandle publication_handle, - const DDS_Security_DynamicData key, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_return_permissions_credential_token)( + dds_security_access_control *instance, + const DDS_Security_PermissionsCredentialToken *permissions_credential_token, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_get_permissions_token) - ( dds_security_access_control *instance, - DDS_Security_PermissionsToken *permissions_token, - const DDS_Security_PermissionsHandle handle, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_get_participant_sec_attributes)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + DDS_Security_ParticipantSecurityAttributes *attributes, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_get_permissions_credential_token) - ( dds_security_access_control *instance, - DDS_Security_PermissionsCredentialToken *permissions_credential_token, - const DDS_Security_PermissionsHandle handle, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_get_topic_sec_attributes)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_char *topic_name, + DDS_Security_TopicSecurityAttributes *attributes, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_set_listener) - ( dds_security_access_control *instance, - const dds_security_access_control_listener *listener, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_get_datawriter_sec_attributes)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_char *topic_name, + const DDS_Security_PartitionQosPolicy *partition, + const DDS_Security_DataTagQosPolicy *data_tag, + DDS_Security_EndpointSecurityAttributes *attributes, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_return_permissions_token) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsToken *token, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_get_datareader_sec_attributes)( + dds_security_access_control *instance, + const DDS_Security_PermissionsHandle permissions_handle, + const DDS_Security_char *topic_name, + const DDS_Security_PartitionQosPolicy *partition, + const DDS_Security_DataTagQosPolicy *data_tag, + DDS_Security_EndpointSecurityAttributes *attributes, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_return_permissions_credential_token) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsCredentialToken *permissions_credential_token, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_return_participant_sec_attributes)( + dds_security_access_control *instance, + const DDS_Security_ParticipantSecurityAttributes *attributes, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_get_participant_sec_attributes) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - DDS_Security_ParticipantSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_return_topic_sec_attributes)( + dds_security_access_control *instance, + const DDS_Security_TopicSecurityAttributes *attributes, + DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_return_datawriter_sec_attributes)( + dds_security_access_control *instance, + const DDS_Security_EndpointSecurityAttributes *attributes, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_access_control_get_topic_sec_attributes) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_char *topic_name, - DDS_Security_TopicSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - - -typedef DDS_Security_boolean -(*DDS_Security_access_control_get_datawriter_sec_attributes) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_char *topic_name, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTagQosPolicy *data_tag, - DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - - -typedef DDS_Security_boolean -(*DDS_Security_access_control_get_datareader_sec_attributes) - ( dds_security_access_control *instance, - const DDS_Security_PermissionsHandle permissions_handle, - const DDS_Security_char *topic_name, - const DDS_Security_PartitionQosPolicy *partition, - const DDS_Security_DataTagQosPolicy *data_tag, - DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - - -typedef DDS_Security_boolean -(*DDS_Security_access_control_return_participant_sec_attributes) - ( dds_security_access_control *instance, - const DDS_Security_ParticipantSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - -typedef DDS_Security_boolean -(*DDS_Security_access_control_return_topic_sec_attributes) - ( dds_security_access_control *instance, - const DDS_Security_TopicSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - -typedef DDS_Security_boolean -(*DDS_Security_access_control_return_datawriter_sec_attributes) - ( dds_security_access_control *instance, - const DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - - -typedef DDS_Security_boolean -(*DDS_Security_access_control_return_datareader_sec_attributes) - ( dds_security_access_control *instance, - const DDS_Security_EndpointSecurityAttributes *attributes, - DDS_Security_SecurityException *ex); - -typedef DDS_Security_boolean -(*DDS_Security_access_control_return_permissions_handle) - ( dds_security_access_control *instance, - DDS_Security_PermissionsHandle permissions_handle, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_return_datareader_sec_attributes)( + dds_security_access_control *instance, + const DDS_Security_EndpointSecurityAttributes *attributes, + DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_access_control_return_permissions_handle)( + dds_security_access_control *instance, + DDS_Security_PermissionsHandle permissions_handle, + DDS_Security_SecurityException *ex); struct dds_security_access_control { + struct ddsi_domaingv *gv; + DDS_Security_access_control_validate_local_permissions validate_local_permissions; - DDS_Security_access_control_validate_remote_permissions validate_remote_permissions; - DDS_Security_access_control_check_create_participant check_create_participant; - DDS_Security_access_control_check_create_datawriter check_create_datawriter; - DDS_Security_access_control_check_create_datareader check_create_datareader; - DDS_Security_access_control_check_create_topic check_create_topic; - DDS_Security_access_control_check_local_datawriter_register_instance check_local_datawriter_register_instance; - DDS_Security_access_control_check_local_datawriter_dispose_instance check_local_datawriter_dispose_instance; - DDS_Security_access_control_check_remote_participant check_remote_participant; - DDS_Security_access_control_check_remote_datawriter check_remote_datawriter; - DDS_Security_access_control_check_remote_datareader check_remote_datareader; - DDS_Security_access_control_check_remote_topic check_remote_topic; - DDS_Security_access_control_check_local_datawriter_match check_local_datawriter_match; - DDS_Security_access_control_check_local_datareader_match check_local_datareader_match; - DDS_Security_access_control_check_remote_datawriter_register_instance check_remote_datawriter_register_instance; - DDS_Security_access_control_check_remote_datawriter_dispose_instance check_remote_datawriter_dispose_instance; - DDS_Security_access_control_get_permissions_token get_permissions_token; - DDS_Security_access_control_get_permissions_credential_token get_permissions_credential_token; - DDS_Security_access_control_set_listener set_listener; - DDS_Security_access_control_return_permissions_token return_permissions_token; - DDS_Security_access_control_return_permissions_credential_token return_permissions_credential_token; - DDS_Security_access_control_get_participant_sec_attributes get_participant_sec_attributes; - DDS_Security_access_control_get_topic_sec_attributes get_topic_sec_attributes; - DDS_Security_access_control_get_datawriter_sec_attributes get_datawriter_sec_attributes; - DDS_Security_access_control_get_datareader_sec_attributes get_datareader_sec_attributes; - DDS_Security_access_control_return_participant_sec_attributes return_participant_sec_attributes; - DDS_Security_access_control_return_topic_sec_attributes return_topic_sec_attributes; - DDS_Security_access_control_return_datawriter_sec_attributes return_datawriter_sec_attributes; - DDS_Security_access_control_return_datareader_sec_attributes return_datareader_sec_attributes; - DDS_Security_access_control_return_permissions_handle return_permissions_handle; - }; - -#if defined (__cplusplus) +#if defined(__cplusplus) } #endif diff --git a/src/security/api/include/dds/security/dds_security_api_authentication.h b/src/security/api/include/dds/security/dds_security_api_authentication.h index 4913985..c0d9298 100644 --- a/src/security/api/include/dds/security/dds_security_api_authentication.h +++ b/src/security/api/include/dds/security/dds_security_api_authentication.h @@ -15,223 +15,170 @@ #include "dds_security_api_types.h" -#if defined (__cplusplus) -extern "C" { +#if defined(__cplusplus) +extern "C" +{ #endif - -/** - * Authentication Component - */ +/* Authentication Component */ struct dds_security_authentication; typedef struct dds_security_authentication dds_security_authentication; struct dds_security_authentication_listener; typedef struct dds_security_authentication_listener dds_security_authentication_listener; +/* AuthenticationListener interface */ +typedef DDS_Security_boolean (*DDS_Security_authentication_listener_on_revoke_identity)( + dds_security_authentication_listener *context, + const dds_security_authentication *plugin, + const DDS_Security_IdentityHandle handle); -/** - * AuthenticationListener interface - */ - -typedef DDS_Security_boolean -(*DDS_Security_authentication_listener_on_revoke_identity) - ( dds_security_authentication_listener *context, - const dds_security_authentication *plugin, - const DDS_Security_IdentityHandle handle - ); - -typedef DDS_Security_boolean -(*DDS_Security_authentication_listener_on_status_changed) - ( dds_security_authentication_listener *context, - const dds_security_authentication *plugin, - const DDS_Security_IdentityHandle handle, - const DDS_Security_AuthStatusKind status_kind - ); - +typedef DDS_Security_boolean (*DDS_Security_authentication_listener_on_status_changed)( + dds_security_authentication_listener *context, + const dds_security_authentication *plugin, + const DDS_Security_IdentityHandle handle, + const DDS_Security_AuthStatusKind status_kind); struct dds_security_authentication_listener { DDS_Security_authentication_listener_on_revoke_identity on_revoke_identity; - DDS_Security_authentication_listener_on_status_changed on_status_changed; }; -typedef DDS_Security_ValidationResult_t -(*DDS_Security_authentication_validate_local_identity) - ( dds_security_authentication *instance, - DDS_Security_IdentityHandle *local_identity_handle, - DDS_Security_GUID_t *adjusted_participant_guid, - const DDS_Security_DomainId domain_id, - const DDS_Security_Qos *participant_qos, - const DDS_Security_GUID_t *candidate_participant_guid, - DDS_Security_SecurityException *ex - ); +typedef DDS_Security_ValidationResult_t (*DDS_Security_authentication_validate_local_identity)( + dds_security_authentication *instance, + DDS_Security_IdentityHandle *local_identity_handle, + DDS_Security_GUID_t *adjusted_participant_guid, + const DDS_Security_DomainId domain_id, + const DDS_Security_Qos *participant_qos, + const DDS_Security_GUID_t *candidate_participant_guid, + DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_authentication_get_identity_token)( + dds_security_authentication *instance, + DDS_Security_IdentityToken *identity_token, + const DDS_Security_IdentityHandle handle, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_authentication_get_identity_token) - ( dds_security_authentication *instance, - DDS_Security_IdentityToken *identity_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_authentication_get_identity_status_token)( + dds_security_authentication *instance, + DDS_Security_IdentityStatusToken *identity_status_token, + const DDS_Security_IdentityHandle handle, + DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_authentication_set_permissions_credential_and_token)( + dds_security_authentication *instance, + const DDS_Security_IdentityHandle handle, + const DDS_Security_PermissionsCredentialToken *permissions_credential, + const DDS_Security_PermissionsToken *permissions_token, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_authentication_get_identity_status_token) - ( dds_security_authentication *instance, - DDS_Security_IdentityStatusToken *identity_status_token, - const DDS_Security_IdentityHandle handle, - DDS_Security_SecurityException *ex); +typedef DDS_Security_ValidationResult_t (*DDS_Security_authentication_validate_remote_identity)( + dds_security_authentication *instance, + DDS_Security_IdentityHandle *remote_identity_handle, + DDS_Security_AuthRequestMessageToken *local_auth_request_token, + const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, + const DDS_Security_IdentityHandle local_identity_handle, + const DDS_Security_IdentityToken *remote_identity_token, + const DDS_Security_GUID_t *remote_participant_guid, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_authentication_set_permissions_credential_and_token) - ( dds_security_authentication *instance, - const DDS_Security_IdentityHandle handle, - const DDS_Security_PermissionsCredentialToken *permissions_credential, - const DDS_Security_PermissionsToken *permissions_token, - DDS_Security_SecurityException *ex); +typedef DDS_Security_ValidationResult_t (*DDS_Security_authentication_begin_handshake_request)( + dds_security_authentication *instance, + DDS_Security_HandshakeHandle *handshake_handle, + DDS_Security_HandshakeMessageToken *handshake_message, + const DDS_Security_IdentityHandle initiator_identity_handle, + const DDS_Security_IdentityHandle replier_identity_handle, + const DDS_Security_OctetSeq *serialized_local_participant_data, + DDS_Security_SecurityException *ex); +typedef DDS_Security_ValidationResult_t (*DDS_Security_authentication_begin_handshake_reply)( + dds_security_authentication *instance, + DDS_Security_HandshakeHandle *handshake_handle, + DDS_Security_HandshakeMessageToken *handshake_message_out, + const DDS_Security_HandshakeMessageToken *handshake_message_in, + const DDS_Security_IdentityHandle initiator_identity_handle, + const DDS_Security_IdentityHandle replier_identity_handle, + const DDS_Security_OctetSeq *serialized_local_participant_data, + DDS_Security_SecurityException *ex); -typedef DDS_Security_ValidationResult_t -(*DDS_Security_authentication_validate_remote_identity) - ( dds_security_authentication *instance, - DDS_Security_IdentityHandle *remote_identity_handle, - DDS_Security_AuthRequestMessageToken *local_auth_request_token, - const DDS_Security_AuthRequestMessageToken *remote_auth_request_token, - const DDS_Security_IdentityHandle local_identity_handle, - const DDS_Security_IdentityToken *remote_identity_token, - const DDS_Security_GUID_t *remote_participant_guid, - DDS_Security_SecurityException *ex); +typedef DDS_Security_ValidationResult_t (*DDS_Security_authentication_process_handshake)( + dds_security_authentication *instance, + DDS_Security_HandshakeMessageToken *handshake_message_out, + const DDS_Security_HandshakeMessageToken *handshake_message_in, + const DDS_Security_HandshakeHandle handshake_handle, + DDS_Security_SecurityException *ex); +typedef DDS_Security_SharedSecretHandle (*DDS_Security_authentication_get_shared_secret)( + dds_security_authentication *instance, + const DDS_Security_HandshakeHandle handshake_handle, + DDS_Security_SecurityException *ex); -typedef DDS_Security_ValidationResult_t -(*DDS_Security_authentication_begin_handshake_request) - ( dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_authentication_get_authenticated_peer_credential_token)( + dds_security_authentication *instance, + DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, + const DDS_Security_HandshakeHandle handshake_handle, + DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_authentication_set_listener)( + dds_security_authentication *instance, + const dds_security_authentication_listener *listener, + DDS_Security_SecurityException *ex); -typedef DDS_Security_ValidationResult_t -(*DDS_Security_authentication_begin_handshake_reply) - ( dds_security_authentication *instance, - DDS_Security_HandshakeHandle *handshake_handle, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_IdentityHandle initiator_identity_handle, - const DDS_Security_IdentityHandle replier_identity_handle, - const DDS_Security_OctetSeq *serialized_local_participant_data, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_authentication_return_identity_token)( + dds_security_authentication *instance, + const DDS_Security_IdentityToken *token, + DDS_Security_SecurityException *ex); -typedef DDS_Security_ValidationResult_t -(*DDS_Security_authentication_process_handshake) - ( dds_security_authentication *instance, - DDS_Security_HandshakeMessageToken *handshake_message_out, - const DDS_Security_HandshakeMessageToken *handshake_message_in, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_authentication_return_identity_status_token)( + dds_security_authentication *instance, + const DDS_Security_IdentityStatusToken *token, + DDS_Security_SecurityException *ex); -typedef DDS_Security_SharedSecretHandle -(*DDS_Security_authentication_get_shared_secret) - ( dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_authentication_return_authenticated_peer_credential_token)( + dds_security_authentication *instance, + const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_authentication_get_authenticated_peer_credential_token) - ( dds_security_authentication *instance, - DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_authentication_return_handshake_handle)( + dds_security_authentication *instance, + const DDS_Security_HandshakeHandle handshake_handle, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_authentication_set_listener) - ( dds_security_authentication *instance, - const dds_security_authentication_listener *listener, - DDS_Security_SecurityException *ex); - -typedef DDS_Security_boolean -(*DDS_Security_authentication_return_identity_token) - ( dds_security_authentication *instance, - const DDS_Security_IdentityToken *token, - DDS_Security_SecurityException *ex); - - -typedef DDS_Security_boolean -(*DDS_Security_authentication_return_identity_status_token) - ( dds_security_authentication *instance, - const DDS_Security_IdentityStatusToken *token, - DDS_Security_SecurityException *ex); - -typedef DDS_Security_boolean -(*DDS_Security_authentication_return_authenticated_peer_credential_token) - ( dds_security_authentication *instance, - const DDS_Security_AuthenticatedPeerCredentialToken *peer_credential_token, - DDS_Security_SecurityException *ex); - -typedef DDS_Security_boolean -(*DDS_Security_authentication_return_handshake_handle) - ( dds_security_authentication *instance, - const DDS_Security_HandshakeHandle handshake_handle, - DDS_Security_SecurityException *ex); - -typedef DDS_Security_boolean -(*DDS_Security_authentication_return_identity_handle) - ( dds_security_authentication *instance, - const DDS_Security_IdentityHandle identity_handle, - DDS_Security_SecurityException *ex); - -typedef DDS_Security_boolean -(*DDS_Security_authentication_return_sharedsecret_handle) - ( dds_security_authentication *instance, - const DDS_Security_SharedSecretHandle sharedsecret_handle, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_authentication_return_identity_handle)( + dds_security_authentication *instance, + const DDS_Security_IdentityHandle identity_handle, + DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_authentication_return_sharedsecret_handle)( + dds_security_authentication *instance, + const DDS_Security_SharedSecretHandle sharedsecret_handle, + DDS_Security_SecurityException *ex); struct dds_security_authentication { + struct ddsi_domaingv *gv; DDS_Security_authentication_validate_local_identity validate_local_identity; - DDS_Security_authentication_get_identity_token get_identity_token; - DDS_Security_authentication_get_identity_status_token get_identity_status_token; - DDS_Security_authentication_set_permissions_credential_and_token set_permissions_credential_and_token; - DDS_Security_authentication_validate_remote_identity validate_remote_identity; - DDS_Security_authentication_begin_handshake_request begin_handshake_request; - DDS_Security_authentication_begin_handshake_reply begin_handshake_reply; - DDS_Security_authentication_process_handshake process_handshake; - DDS_Security_authentication_get_shared_secret get_shared_secret; - DDS_Security_authentication_get_authenticated_peer_credential_token get_authenticated_peer_credential_token; - DDS_Security_authentication_set_listener set_listener; - DDS_Security_authentication_return_identity_token return_identity_token; - DDS_Security_authentication_return_identity_status_token return_identity_status_token; - DDS_Security_authentication_return_authenticated_peer_credential_token return_authenticated_peer_credential_token; - DDS_Security_authentication_return_handshake_handle return_handshake_handle; - DDS_Security_authentication_return_identity_handle return_identity_handle; - DDS_Security_authentication_return_sharedsecret_handle return_sharedsecret_handle; }; - -#if defined (__cplusplus) +#if defined(__cplusplus) } #endif diff --git a/src/security/api/include/dds/security/dds_security_api_cryptography.h b/src/security/api/include/dds/security/dds_security_api_cryptography.h index 5203d3d..2f3144e 100644 --- a/src/security/api/include/dds/security/dds_security_api_cryptography.h +++ b/src/security/api/include/dds/security/dds_security_api_cryptography.h @@ -15,14 +15,12 @@ #include "dds_security_api_types.h" -#if defined (__cplusplus) -extern "C" { +#if defined(__cplusplus) +extern "C" +{ #endif -/** - * Crypto Component - */ - +/* Crypto Component */ struct dds_security_crypto_key_factory; typedef struct dds_security_crypto_key_factory dds_security_crypto_key_factory; @@ -32,305 +30,240 @@ typedef struct dds_security_crypto_key_exchange dds_security_crypto_key_exchange struct dds_security_crypto_transform; typedef struct dds_security_crypto_transform dds_security_crypto_transform; -/** - * CryptoKeyFactory interface - */ +/* CryptoKeyFactory interface */ +typedef DDS_Security_ParticipantCryptoHandle (*DDS_Security_crypto_key_factory_register_local_participant)( + dds_security_crypto_key_factory *instance, + const DDS_Security_IdentityHandle participant_identity, + const DDS_Security_PermissionsHandle participant_permissions, + const DDS_Security_PropertySeq *participant_properties, + const DDS_Security_ParticipantSecurityAttributes *participant_security_attributes, + DDS_Security_SecurityException *ex); -typedef DDS_Security_ParticipantCryptoHandle -(*DDS_Security_crypto_key_factory_register_local_participant) - ( dds_security_crypto_key_factory *instance, - const DDS_Security_IdentityHandle participant_identity, - const DDS_Security_PermissionsHandle participant_permissions, - const DDS_Security_PropertySeq *participant_properties, - const DDS_Security_ParticipantSecurityAttributes *participant_security_attributes, - DDS_Security_SecurityException *ex); +typedef DDS_Security_ParticipantCryptoHandle (*DDS_Security_crypto_key_factory_register_matched_remote_participant)( + dds_security_crypto_key_factory *instance, + const DDS_Security_ParticipantCryptoHandle local_participant_crypto_handle, + const DDS_Security_IdentityHandle remote_participant_identity, + const DDS_Security_PermissionsHandle remote_participant_permissions, + const DDS_Security_SharedSecretHandle shared_secret, + DDS_Security_SecurityException *ex); -typedef DDS_Security_ParticipantCryptoHandle -(*DDS_Security_crypto_key_factory_register_matched_remote_participant) - ( dds_security_crypto_key_factory *instance, - const DDS_Security_ParticipantCryptoHandle local_participant_crypto_handle, - const DDS_Security_IdentityHandle remote_participant_identity, - const DDS_Security_PermissionsHandle remote_participant_permissions, - const DDS_Security_SharedSecretHandle shared_secret, - DDS_Security_SecurityException *ex); +typedef DDS_Security_DatawriterCryptoHandle (*DDS_Security_crypto_key_factory_register_local_datawriter)( + dds_security_crypto_key_factory *instance, + const DDS_Security_ParticipantCryptoHandle participant_crypto, + const DDS_Security_PropertySeq *datawriter_properties, + const DDS_Security_EndpointSecurityAttributes *datawriter_security_attributes, + DDS_Security_SecurityException *ex); +typedef DDS_Security_DatareaderCryptoHandle (*DDS_Security_crypto_key_factory_register_matched_remote_datareader)( + dds_security_crypto_key_factory *instance, + const DDS_Security_DatawriterCryptoHandle local_datawriter_crypto_handle, + const DDS_Security_ParticipantCryptoHandle remote_participant_crypto, + const DDS_Security_SharedSecretHandle shared_secret, + const DDS_Security_boolean relay_only, + DDS_Security_SecurityException *ex); -typedef DDS_Security_DatawriterCryptoHandle -(*DDS_Security_crypto_key_factory_register_local_datawriter) - ( dds_security_crypto_key_factory *instance, - const DDS_Security_ParticipantCryptoHandle participant_crypto, - const DDS_Security_PropertySeq *datawriter_properties, - const DDS_Security_EndpointSecurityAttributes *datawriter_security_attributes, - DDS_Security_SecurityException *ex); +typedef DDS_Security_DatareaderCryptoHandle (*DDS_Security_crypto_key_factory_register_local_datareader)( + dds_security_crypto_key_factory *instance, + const DDS_Security_ParticipantCryptoHandle participant_crypto_handle, + const DDS_Security_PropertySeq *datareader_properties, + const DDS_Security_EndpointSecurityAttributes *datareader_security_attributes, + DDS_Security_SecurityException *ex); -typedef DDS_Security_DatareaderCryptoHandle -(*DDS_Security_crypto_key_factory_register_matched_remote_datareader) - ( dds_security_crypto_key_factory *instance, - const DDS_Security_DatawriterCryptoHandle local_datawriter_crypto_handle, - const DDS_Security_ParticipantCryptoHandle remote_participant_crypto, - const DDS_Security_SharedSecretHandle shared_secret, - const DDS_Security_boolean relay_only, - DDS_Security_SecurityException *ex); +typedef DDS_Security_DatawriterCryptoHandle (*DDS_Security_crypto_key_factory_register_matched_remote_datawriter)( + dds_security_crypto_key_factory *instance, + const DDS_Security_DatareaderCryptoHandle local_datareader_crypto_handle, + const DDS_Security_ParticipantCryptoHandle remote_participant_crypt, + const DDS_Security_SharedSecretHandle shared_secret, + DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_crypto_key_factory_unregister_participant)( + dds_security_crypto_key_factory *instance, + const DDS_Security_ParticipantCryptoHandle participant_crypto_handle, + DDS_Security_SecurityException *ex); -typedef DDS_Security_DatareaderCryptoHandle -(*DDS_Security_crypto_key_factory_register_local_datareader) - ( dds_security_crypto_key_factory *instance, - const DDS_Security_ParticipantCryptoHandle participant_crypto_handle, - const DDS_Security_PropertySeq *datareader_properties, - const DDS_Security_EndpointSecurityAttributes *datareader_security_attributes, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_crypto_key_factory_unregister_datawriter)( + dds_security_crypto_key_factory *instance, + const DDS_Security_DatawriterCryptoHandle datawriter_crypto_handle, + DDS_Security_SecurityException *ex); -typedef DDS_Security_DatawriterCryptoHandle -(*DDS_Security_crypto_key_factory_register_matched_remote_datawriter) - ( dds_security_crypto_key_factory *instance, - const DDS_Security_DatareaderCryptoHandle local_datareader_crypto_handle, - const DDS_Security_ParticipantCryptoHandle remote_participant_crypt, - const DDS_Security_SharedSecretHandle shared_secret, - DDS_Security_SecurityException *ex); - -typedef DDS_Security_boolean -(*DDS_Security_crypto_key_factory_unregister_participant) - ( dds_security_crypto_key_factory *instance, - const DDS_Security_ParticipantCryptoHandle participant_crypto_handle, - DDS_Security_SecurityException *ex); - -typedef DDS_Security_boolean -(*DDS_Security_crypto_key_factory_unregister_datawriter) - ( dds_security_crypto_key_factory *instance, - const DDS_Security_DatawriterCryptoHandle datawriter_crypto_handle, - DDS_Security_SecurityException *ex); - -typedef DDS_Security_boolean -(*DDS_Security_crypto_key_factory_unregister_datareader) - ( dds_security_crypto_key_factory *instance, - const DDS_Security_DatareaderCryptoHandle datareader_crypto_handle, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_crypto_key_factory_unregister_datareader)( + dds_security_crypto_key_factory *instance, + const DDS_Security_DatareaderCryptoHandle datareader_crypto_handle, + DDS_Security_SecurityException *ex); struct dds_security_crypto_key_factory { - DDS_Security_crypto_key_factory_register_local_participant register_local_participant; - DDS_Security_crypto_key_factory_register_matched_remote_participant register_matched_remote_participant; - DDS_Security_crypto_key_factory_register_local_datawriter register_local_datawriter; - DDS_Security_crypto_key_factory_register_matched_remote_datareader register_matched_remote_datareader; - DDS_Security_crypto_key_factory_register_local_datareader register_local_datareader; - DDS_Security_crypto_key_factory_register_matched_remote_datawriter register_matched_remote_datawriter; - DDS_Security_crypto_key_factory_unregister_participant unregister_participant; - DDS_Security_crypto_key_factory_unregister_datawriter unregister_datawriter; - DDS_Security_crypto_key_factory_unregister_datareader unregister_datareader; -} ; +}; +/* CryptoKeyExchange Interface */ +typedef DDS_Security_boolean (*DDS_Security_crypto_key_exchange_create_local_participant_crypto_tokens)( + dds_security_crypto_key_exchange *instance, + DDS_Security_ParticipantCryptoTokenSeq *local_participant_crypto_tokens, + const DDS_Security_ParticipantCryptoHandle local_participant_crypto, + const DDS_Security_ParticipantCryptoHandle remote_participant_crypto, + DDS_Security_SecurityException *ex); -/** - * CryptoKeyExchange Interface - */ -typedef DDS_Security_boolean -(*DDS_Security_crypto_key_exchange_create_local_participant_crypto_tokens) - ( dds_security_crypto_key_exchange *instance, - DDS_Security_ParticipantCryptoTokenSeq *local_participant_crypto_tokens, - const DDS_Security_ParticipantCryptoHandle local_participant_crypto, - const DDS_Security_ParticipantCryptoHandle remote_participant_crypto, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_crypto_key_exchange_set_remote_participant_crypto_tokens)( + dds_security_crypto_key_exchange *instance, + const DDS_Security_ParticipantCryptoHandle local_participant_crypto, + const DDS_Security_ParticipantCryptoHandle remote_participant_crypto, + const DDS_Security_ParticipantCryptoTokenSeq *remote_participant_tokens, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_crypto_key_exchange_set_remote_participant_crypto_tokens) - ( dds_security_crypto_key_exchange *instance, - const DDS_Security_ParticipantCryptoHandle local_participant_crypto, - const DDS_Security_ParticipantCryptoHandle remote_participant_crypto, - const DDS_Security_ParticipantCryptoTokenSeq *remote_participant_tokens, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_crypto_key_exchange_create_local_datawriter_crypto_tokens)( + dds_security_crypto_key_exchange *instance, + DDS_Security_DatawriterCryptoTokenSeq *local_datawriter_crypto_tokens, + const DDS_Security_DatawriterCryptoHandle local_datawriter_crypto, + const DDS_Security_DatareaderCryptoHandle remote_datareader_crypto, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_crypto_key_exchange_create_local_datawriter_crypto_tokens) - ( dds_security_crypto_key_exchange *instance, - DDS_Security_DatawriterCryptoTokenSeq *local_datawriter_crypto_tokens, - const DDS_Security_DatawriterCryptoHandle local_datawriter_crypto, - const DDS_Security_DatareaderCryptoHandle remote_datareader_crypto, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_crypto_key_exchange_set_remote_datawriter_crypto_tokens)( + dds_security_crypto_key_exchange *instance, + const DDS_Security_DatareaderCryptoHandle local_datareader_crypto, + const DDS_Security_DatawriterCryptoHandle remote_datawriter_crypto, + const DDS_Security_DatawriterCryptoTokenSeq *remote_datawriter_tokens, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_crypto_key_exchange_set_remote_datawriter_crypto_tokens) - ( dds_security_crypto_key_exchange *instance, - const DDS_Security_DatareaderCryptoHandle local_datareader_crypto, - const DDS_Security_DatawriterCryptoHandle remote_datawriter_crypto, - const DDS_Security_DatawriterCryptoTokenSeq *remote_datawriter_tokens, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_crypto_key_exchange_create_local_datareader_crypto_tokens)( + dds_security_crypto_key_exchange *instance, + DDS_Security_DatareaderCryptoTokenSeq *local_datareader_cryto_tokens, + const DDS_Security_DatareaderCryptoHandle local_datareader_crypto, + const DDS_Security_DatawriterCryptoHandle remote_datawriter_crypto, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_crypto_key_exchange_create_local_datareader_crypto_tokens) - ( dds_security_crypto_key_exchange *instance, - DDS_Security_DatareaderCryptoTokenSeq *local_datareader_cryto_tokens, - const DDS_Security_DatareaderCryptoHandle local_datareader_crypto, - const DDS_Security_DatawriterCryptoHandle remote_datawriter_crypto, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_crypto_key_exchange_set_remote_datareader_crypto_tokens)( + dds_security_crypto_key_exchange *instance, + const DDS_Security_DatawriterCryptoHandle local_datawriter_crypto, + const DDS_Security_DatareaderCryptoHandle remote_datareader_crypto, + const DDS_Security_DatareaderCryptoTokenSeq *remote_datareader_tokens, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_crypto_key_exchange_set_remote_datareader_crypto_tokens) - ( dds_security_crypto_key_exchange *instance, - const DDS_Security_DatawriterCryptoHandle local_datawriter_crypto, - const DDS_Security_DatareaderCryptoHandle remote_datareader_crypto, - const DDS_Security_DatareaderCryptoTokenSeq *remote_datareader_tokens, - DDS_Security_SecurityException *ex); - -typedef DDS_Security_boolean -(*DDS_Security_crypto_key_exchange_return_crypto_tokens) - ( dds_security_crypto_key_exchange *instance, - DDS_Security_CryptoTokenSeq *crypto_tokens, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_crypto_key_exchange_return_crypto_tokens)( + dds_security_crypto_key_exchange *instance, + DDS_Security_CryptoTokenSeq *crypto_tokens, + DDS_Security_SecurityException *ex); struct dds_security_crypto_key_exchange { DDS_Security_crypto_key_exchange_create_local_participant_crypto_tokens create_local_participant_crypto_tokens; - DDS_Security_crypto_key_exchange_set_remote_participant_crypto_tokens set_remote_participant_crypto_tokens; - DDS_Security_crypto_key_exchange_create_local_datawriter_crypto_tokens create_local_datawriter_crypto_tokens; - DDS_Security_crypto_key_exchange_set_remote_datawriter_crypto_tokens set_remote_datawriter_crypto_tokens; - DDS_Security_crypto_key_exchange_create_local_datareader_crypto_tokens create_local_datareader_crypto_tokens; - DDS_Security_crypto_key_exchange_set_remote_datareader_crypto_tokens set_remote_datareader_crypto_tokens; - DDS_Security_crypto_key_exchange_return_crypto_tokens return_crypto_tokens; -} ; +}; +/* CryptoTransform Interface */ +typedef DDS_Security_boolean (*DDS_Security_crypto_transform_encode_serialized_payload)( + dds_security_crypto_transform *instance, + DDS_Security_OctetSeq *encoded_buffer, + DDS_Security_OctetSeq *extra_inline_qos, + const DDS_Security_OctetSeq *plain_buffer, + const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, + DDS_Security_SecurityException *ex); -/** - * CryptoTransform Interface - */ +typedef DDS_Security_boolean (*DDS_Security_crypto_transform_encode_datawriter_submessage)( + dds_security_crypto_transform *instance, + DDS_Security_OctetSeq *encoded_rtps_submessage, + const DDS_Security_OctetSeq *plain_rtps_submessage, + const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, + const DDS_Security_DatareaderCryptoHandleSeq *receiving_datareader_crypto_list, + DDS_Security_long *receiving_datareader_crypto_list_index, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_crypto_transform_encode_serialized_payload) - ( dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *encoded_buffer, - DDS_Security_OctetSeq *extra_inline_qos, - const DDS_Security_OctetSeq *plain_buffer, - const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_crypto_transform_encode_datareader_submessage)( + dds_security_crypto_transform *instance, + DDS_Security_OctetSeq *encoded_rtps_submessage, + const DDS_Security_OctetSeq *plain_rtps_submessage, + const DDS_Security_DatareaderCryptoHandle sending_datareader_crypto, + const DDS_Security_DatawriterCryptoHandleSeq *receiving_datawriter_crypto_list, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_crypto_transform_encode_datawriter_submessage) - ( dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *encoded_rtps_submessage, - const DDS_Security_OctetSeq *plain_rtps_submessage, - const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, - const DDS_Security_DatareaderCryptoHandleSeq *receiving_datareader_crypto_list, - DDS_Security_long *receiving_datareader_crypto_list_index, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_crypto_transform_encode_rtps_message)( + dds_security_crypto_transform *instance, + DDS_Security_OctetSeq *encoded_rtps_message, + const DDS_Security_OctetSeq *plain_rtps_message, + const DDS_Security_ParticipantCryptoHandle sending_participant_crypto, + const DDS_Security_ParticipantCryptoHandleSeq *receiving_participant_crypto_list, + DDS_Security_long *receiving_participant_crypto_list_index, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_crypto_transform_encode_datareader_submessage) - ( dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *encoded_rtps_submessage, - const DDS_Security_OctetSeq *plain_rtps_submessage, - const DDS_Security_DatareaderCryptoHandle sending_datareader_crypto, - const DDS_Security_DatawriterCryptoHandleSeq *receiving_datawriter_crypto_list, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_crypto_transform_decode_rtps_message)( + dds_security_crypto_transform *instance, + DDS_Security_OctetSeq *plain_buffer, + const DDS_Security_OctetSeq *encoded_buffer, + const DDS_Security_ParticipantCryptoHandle receiving_participant_crypto, + const DDS_Security_ParticipantCryptoHandle sending_participant_crypto, + DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_crypto_transform_preprocess_secure_submsg)( + dds_security_crypto_transform *instance, + DDS_Security_DatawriterCryptoHandle *datawriter_crypto, + DDS_Security_DatareaderCryptoHandle *datareader_crypto, + DDS_Security_SecureSubmessageCategory_t *secure_submessage_category, + const DDS_Security_OctetSeq *encoded_rtps_submessage, + const DDS_Security_ParticipantCryptoHandle receiving_participant_crypto, + const DDS_Security_ParticipantCryptoHandle sending_participant_crypto, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_crypto_transform_encode_rtps_message) - ( dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *encoded_rtps_message, - const DDS_Security_OctetSeq *plain_rtps_message, - const DDS_Security_ParticipantCryptoHandle sending_participant_crypto, - const DDS_Security_ParticipantCryptoHandleSeq *receiving_participant_crypto_list, - DDS_Security_long *receiving_participant_crypto_list_index, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_crypto_transform_decode_datawriter_submessage)( + dds_security_crypto_transform *instance, + DDS_Security_OctetSeq *plain_rtps_submessage, + const DDS_Security_OctetSeq *encoded_rtps_submessage, + const DDS_Security_DatareaderCryptoHandle receiving_datareader_crypto, + const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, + DDS_Security_SecurityException *ex); -typedef DDS_Security_boolean -(*DDS_Security_crypto_transform_decode_rtps_message) - ( dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *plain_buffer, - const DDS_Security_OctetSeq *encoded_buffer, - const DDS_Security_ParticipantCryptoHandle receiving_participant_crypto, - const DDS_Security_ParticipantCryptoHandle sending_participant_crypto, - DDS_Security_SecurityException *ex); - -typedef DDS_Security_boolean -(*DDS_Security_crypto_transform_preprocess_secure_submsg) - ( dds_security_crypto_transform *instance, - DDS_Security_DatawriterCryptoHandle *datawriter_crypto, - DDS_Security_DatareaderCryptoHandle *datareader_crypto, - DDS_Security_SecureSubmessageCategory_t *secure_submessage_category, - const DDS_Security_OctetSeq *encoded_rtps_submessage, - const DDS_Security_ParticipantCryptoHandle receiving_participant_crypto, - const DDS_Security_ParticipantCryptoHandle sending_participant_crypto, - DDS_Security_SecurityException *ex); - -typedef DDS_Security_boolean -(*DDS_Security_crypto_transform_decode_datawriter_submessage) - ( dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *plain_rtps_submessage, - const DDS_Security_OctetSeq *encoded_rtps_submessage, - const DDS_Security_DatareaderCryptoHandle receiving_datareader_crypto, - const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, - DDS_Security_SecurityException *ex); - -typedef DDS_Security_boolean -(*DDS_Security_crypto_transform_decode_datareader_submessage) - ( dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *plain_rtps_message, - const DDS_Security_OctetSeq *encoded_rtps_message, - const DDS_Security_DatawriterCryptoHandle receiving_datawriter_crypto, - const DDS_Security_DatareaderCryptoHandle sending_datareader_crypto, - DDS_Security_SecurityException *ex); - - -typedef DDS_Security_boolean -(*DDS_Security_crypto_transform_decode_serialized_payload) - ( dds_security_crypto_transform *instance, - DDS_Security_OctetSeq *plain_buffer, - const DDS_Security_OctetSeq *encoded_buffer, - const DDS_Security_OctetSeq *inline_qos, - const DDS_Security_DatareaderCryptoHandle receiving_datareader_crypto, - const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, - DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_crypto_transform_decode_datareader_submessage)( + dds_security_crypto_transform *instance, + DDS_Security_OctetSeq *plain_rtps_message, + const DDS_Security_OctetSeq *encoded_rtps_message, + const DDS_Security_DatawriterCryptoHandle receiving_datawriter_crypto, + const DDS_Security_DatareaderCryptoHandle sending_datareader_crypto, + DDS_Security_SecurityException *ex); +typedef DDS_Security_boolean (*DDS_Security_crypto_transform_decode_serialized_payload)( + dds_security_crypto_transform *instance, + DDS_Security_OctetSeq *plain_buffer, + const DDS_Security_OctetSeq *encoded_buffer, + const DDS_Security_OctetSeq *inline_qos, + const DDS_Security_DatareaderCryptoHandle receiving_datareader_crypto, + const DDS_Security_DatawriterCryptoHandle sending_datawriter_crypto, + DDS_Security_SecurityException *ex); struct dds_security_crypto_transform { DDS_Security_crypto_transform_encode_serialized_payload encode_serialized_payload; - DDS_Security_crypto_transform_encode_datawriter_submessage encode_datawriter_submessage; - DDS_Security_crypto_transform_encode_datareader_submessage encode_datareader_submessage; - DDS_Security_crypto_transform_encode_rtps_message encode_rtps_message; - DDS_Security_crypto_transform_decode_rtps_message decode_rtps_message; - DDS_Security_crypto_transform_preprocess_secure_submsg preprocess_secure_submsg; - DDS_Security_crypto_transform_decode_datawriter_submessage decode_datawriter_submessage; - DDS_Security_crypto_transform_decode_datareader_submessage decode_datareader_submessage; - DDS_Security_crypto_transform_decode_serialized_payload decode_serialized_payload; -} ; - - - +}; typedef struct dds_security_cryptography { - dds_security_crypto_transform *crypto_transform; - dds_security_crypto_key_factory *crypto_key_factory; - dds_security_crypto_key_exchange *crypto_key_exchange; + struct ddsi_domaingv *gv; + + dds_security_crypto_transform *crypto_transform; + dds_security_crypto_key_factory *crypto_key_factory; + dds_security_crypto_key_exchange *crypto_key_exchange; } dds_security_cryptography; - -#if defined (__cplusplus) +#if defined(__cplusplus) } #endif diff --git a/src/security/builtin_plugins/access_control/src/access_control.c b/src/security/builtin_plugins/access_control/src/access_control.c index 1728a9b..df27ea7 100644 --- a/src/security/builtin_plugins/access_control/src/access_control.c +++ b/src/security/builtin_plugins/access_control/src/access_control.c @@ -20,13 +20,14 @@ #include "dds/ddsrt/string.h" #include "dds/ddsrt/sync.h" #include "dds/ddsrt/types.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_utils.h" +#include "dds/security/core/dds_security_timed_cb.h" #include "access_control.h" #include "access_control_utils.h" #include "access_control_objects.h" #include "access_control_parser.h" -#include "dds/security/core/dds_security_timed_cb.h" #if OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10100000L #define REMOVE_THREAD_STATE() ERR_remove_thread_state(NULL); @@ -82,7 +83,6 @@ typedef struct dds_security_access_control_impl struct dds_security_timed_cb_data *timed_callbacks; struct dds_security_timed_dispatcher_t *dispatcher; - } dds_security_access_control_impl; static bool get_sec_attributes(dds_security_access_control_impl *ac, const DDS_Security_PermissionsHandle permissions_handle, const char *topic_name, @@ -162,12 +162,9 @@ validate_local_permissions( } #endif - permissions_handle = ACCESS_CONTROL_OBJECT_HANDLE(rights); - - if (permissions_handle != DDS_SECURITY_HANDLE_NIL) + if ((permissions_handle = ACCESS_CONTROL_OBJECT_HANDLE(rights)) != DDS_SECURITY_HANDLE_NIL) { assert (rights->permissions_expiry != DDS_TIME_INVALID); - if (rights->permissions_expiry != 0) add_validity_end_trigger(ac, permissions_handle, rights->permissions_expiry); } @@ -228,10 +225,12 @@ validate_remote_permissions( remote_rights = check_and_create_remote_participant_rights(remote_identity_handle, local_rights, remote_permissions_token, remote_credential_token, ex); #endif - permissions_handle = ACCESS_CONTROL_OBJECT_HANDLE(remote_rights); - - if (permissions_handle != DDS_SECURITY_HANDLE_NIL) - add_validity_end_trigger(ac, permissions_handle, remote_rights->permissions_expiry); + if ((permissions_handle = ACCESS_CONTROL_OBJECT_HANDLE(remote_rights)) != DDS_SECURITY_HANDLE_NIL) + { + assert (remote_rights->permissions_expiry != DDS_TIME_INVALID); + if (remote_rights->permissions_expiry != 0) + add_validity_end_trigger(ac, permissions_handle, remote_rights->permissions_expiry); + } if (remote_rights) access_control_table_insert(ac->remote_permissions, (AccessControlObject *)remote_rights); @@ -1475,14 +1474,13 @@ return_permissions_handle( return true; } -int init_access_control(const char *argument, void **context) +int init_access_control(const char *argument, void **context, struct ddsi_domaingv *gv) { DDSRT_UNUSED_ARG(argument); dds_security_access_control_impl *access_control = ddsrt_malloc(sizeof(*access_control)); memset(access_control, 0, sizeof(*access_control)); - - + access_control->base.gv = gv; access_control->timed_callbacks = dds_security_timed_cb_new(); access_control->dispatcher = dds_security_timed_dispatcher_new(access_control->timed_callbacks); access_control->base.validate_local_permissions = &validate_local_permissions; @@ -1881,7 +1879,6 @@ validity_callback(struct dds_security_timed_dispatcher_t *d, void *arg) { validity_cb_info *info = arg; - DDSRT_UNUSED_ARG(d); assert(d); assert(arg); @@ -1892,7 +1889,7 @@ validity_callback(struct dds_security_timed_dispatcher_t *d, { dds_security_access_control_listener *ac_listener = (dds_security_access_control_listener *)listener; if (ac_listener->on_revoke_permissions) - ac_listener->on_revoke_permissions(ac_listener, (dds_security_access_control *)info->ac, info->hdl); + ac_listener->on_revoke_permissions((dds_security_access_control *)info->ac, info->hdl); } } ddsrt_free(arg); diff --git a/src/security/builtin_plugins/access_control/src/access_control.h b/src/security/builtin_plugins/access_control/src/access_control.h index b98d2d7..e89ca00 100644 --- a/src/security/builtin_plugins/access_control/src/access_control.h +++ b/src/security/builtin_plugins/access_control/src/access_control.h @@ -12,10 +12,11 @@ #ifndef ACCESS_CONTROL_H #define ACCESS_CONTROL_H +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/security/dds_security_api.h" #include "dds/security/export.h" -SECURITY_EXPORT int init_access_control(const char *argument, void **context); +SECURITY_EXPORT int init_access_control(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int finalize_access_control(void *context); #endif /* ACCESS_CONTROL_H */ diff --git a/src/security/builtin_plugins/authentication/CMakeLists.txt b/src/security/builtin_plugins/authentication/CMakeLists.txt index d6cb40c..c6716e7 100644 --- a/src/security/builtin_plugins/authentication/CMakeLists.txt +++ b/src/security/builtin_plugins/authentication/CMakeLists.txt @@ -43,6 +43,7 @@ target_include_directories(dds_security_auth "$>" "$>" "$" + "$" ) install( diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index 127357a..937aa7e 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -41,6 +41,7 @@ #include "dds/ddsrt/string.h" #include "dds/ddsrt/sync.h" #include "dds/ddsrt/hopscotch.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_timed_cb.h" #include "dds/security/core/dds_security_utils.h" @@ -2229,14 +2230,14 @@ DDS_Security_boolean return_sharedsecret_handle(dds_security_authentication *ins return true; } -int32_t init_authentication(const char *argument, void **context) +int32_t init_authentication(const char *argument, void **context, struct ddsi_domaingv *gv) { DDSRT_UNUSED_ARG(argument); dds_security_authentication_impl *authentication; authentication = (dds_security_authentication_impl *)ddsrt_malloc(sizeof(dds_security_authentication_impl)); memset(authentication, 0, sizeof(dds_security_authentication_impl)); - + authentication->base.gv = gv; authentication->timed_callbacks = dds_security_timed_cb_new(); authentication->dispatcher = dds_security_timed_dispatcher_new(authentication->timed_callbacks); diff --git a/src/security/builtin_plugins/authentication/src/authentication.h b/src/security/builtin_plugins/authentication/src/authentication.h index 4e56a12..900d1eb 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.h +++ b/src/security/builtin_plugins/authentication/src/authentication.h @@ -17,7 +17,7 @@ #include "dds/security/dds_security_api.h" #include "dds/security/export.h" -SECURITY_EXPORT int32_t init_authentication(const char *argument, void **context); +SECURITY_EXPORT int32_t init_authentication(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int32_t finalize_authentication(void *context); DDS_Security_ValidationResult_t validate_local_identity(dds_security_authentication *instance, DDS_Security_IdentityHandle *local_identity_handle, DDS_Security_GUID_t *adjusted_participant_guid, diff --git a/src/security/builtin_plugins/cryptographic/CMakeLists.txt b/src/security/builtin_plugins/cryptographic/CMakeLists.txt index e7d97f5..180e7f3 100644 --- a/src/security/builtin_plugins/cryptographic/CMakeLists.txt +++ b/src/security/builtin_plugins/cryptographic/CMakeLists.txt @@ -42,6 +42,7 @@ target_include_directories(dds_security_crypto "$>" "$>" "$" + "$" ) install( diff --git a/src/security/builtin_plugins/cryptographic/src/cryptography.c b/src/security/builtin_plugins/cryptographic/src/cryptography.c index a8aee67..6e4f780 100644 --- a/src/security/builtin_plugins/cryptographic/src/cryptography.c +++ b/src/security/builtin_plugins/cryptographic/src/cryptography.c @@ -11,6 +11,7 @@ */ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/types.h" +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/security/dds_security_api.h" #include "cryptography.h" #include "crypto_key_exchange.h" @@ -24,6 +25,7 @@ typedef struct dds_security_cryptography_impl { dds_security_cryptography base; + struct ddsi_domaingv *gv; } dds_security_cryptography_impl; dds_security_crypto_key_factory *cryptography_get_crypto_key_factory (const struct dds_security_cryptography *crypto) @@ -45,7 +47,7 @@ dds_security_crypto_transform *cryptography_get_crypto_transform (const struct d } -int init_crypto (const char *argument, void **context) +int init_crypto (const char *argument, void **context, struct ddsi_domaingv *gv) { dds_security_cryptography_impl *cryptography; dds_security_crypto_key_exchange *crypto_key_exchange; @@ -56,6 +58,7 @@ int init_crypto (const char *argument, void **context) /* allocate new instance */ cryptography = ddsrt_malloc (sizeof(*cryptography)); + cryptography->base.gv = gv; /* assign the sub components */ crypto_key_exchange = dds_security_crypto_key_exchange__alloc ((dds_security_cryptography *)cryptography); diff --git a/src/security/builtin_plugins/cryptographic/src/cryptography.h b/src/security/builtin_plugins/cryptographic/src/cryptography.h index eb114d4..a74b771 100644 --- a/src/security/builtin_plugins/cryptographic/src/cryptography.h +++ b/src/security/builtin_plugins/cryptographic/src/cryptography.h @@ -12,22 +12,15 @@ #ifndef CRYPTOGRAPHY_H #define CRYPTOGRAPHY_H +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/security/dds_security_api.h" #include "dds/security/export.h" -SECURITY_EXPORT int init_crypto(const char *argument, void **context); +SECURITY_EXPORT int init_crypto(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int finalize_crypto(void *instance); -dds_security_crypto_key_factory * -cryptography_get_crypto_key_factory( - const dds_security_cryptography *crypto); - -dds_security_crypto_key_exchange * -cryptography_get_crypto_key_exchange( - const dds_security_cryptography *crypto); - -dds_security_crypto_transform * -cryptography_get_crypto_transform( - const dds_security_cryptography *crypto); +dds_security_crypto_key_factory *cryptography_get_crypto_key_factory(const dds_security_cryptography *crypto); +dds_security_crypto_key_exchange * cryptography_get_crypto_key_exchange(const dds_security_cryptography *crypto); +dds_security_crypto_transform *cryptography_get_crypto_transform(const dds_security_cryptography *crypto); #endif /* CRYPTOGRAPHY_H */ diff --git a/src/security/builtin_plugins/tests/common/src/loader.c b/src/security/builtin_plugins/tests/common/src/loader.c index c6584f2..023e2c5 100644 --- a/src/security/builtin_plugins/tests/common/src/loader.c +++ b/src/security/builtin_plugins/tests/common/src/loader.c @@ -64,7 +64,7 @@ load_plugin( } char * init_parameters = ""; - (void)info->func_init(init_parameters, &plugin); + (void)info->func_init(init_parameters, &plugin, NULL); if (plugin) { info->context = plugin; } else { diff --git a/src/security/builtin_plugins/tests/listeners_access_control/src/listeners_access_control_utests.c b/src/security/builtin_plugins/tests/listeners_access_control/src/listeners_access_control_utests.c index f215738..bd7eab6 100644 --- a/src/security/builtin_plugins/tests/listeners_access_control/src/listeners_access_control_utests.c +++ b/src/security/builtin_plugins/tests/listeners_access_control/src/listeners_access_control_utests.c @@ -568,9 +568,8 @@ CU_Clean(ddssec_builtin_listeners_access_control) return 0; } -static DDS_Security_boolean on_revoke_permissions_cb(dds_security_access_control_listener *instance, const dds_security_access_control *plugin, const DDS_Security_PermissionsHandle handle) +static DDS_Security_boolean on_revoke_permissions_cb(const dds_security_access_control *plugin, const DDS_Security_PermissionsHandle handle) { - DDSRT_UNUSED_ARG(instance); DDSRT_UNUSED_ARG(plugin); if (permission_handle_for_callback1 == DDS_SECURITY_HANDLE_NIL) permission_handle_for_callback1 = handle; diff --git a/src/security/core/include/dds/security/core/dds_security_plugins.h b/src/security/core/include/dds/security/core/dds_security_plugins.h index 3a28e43..ffc48f5 100644 --- a/src/security/core/include/dds/security/core/dds_security_plugins.h +++ b/src/security/core/include/dds/security/core/dds_security_plugins.h @@ -14,10 +14,11 @@ #ifndef SECURITY_CORE_PLUGINS_H_ #define SECURITY_CORE_PLUGINS_H_ +#include #include "dds/export.h" #include "dds/ddsrt/retcode.h" #include "dds/ddsrt/dynlib.h" -#include +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/security/dds_security_api.h" struct ddsrt_log_cfg; @@ -47,24 +48,14 @@ typedef struct dds_security_plugin_suite_config{ dds_security_plugin_config access_control; } dds_security_plugin_suite_config; -DDS_EXPORT dds_return_t dds_security_plugin_release( - const dds_security_plugin *security_plugin, - void *context ); - -DDS_EXPORT dds_return_t dds_security_check_plugin_configuration( - const dds_security_plugin_suite_config *security_suite_config, - const struct ddsrt_log_cfg *logcfg); - -DDS_EXPORT dds_return_t dds_security_load_security_library( - const dds_security_plugin_config *plugin_config, - dds_security_plugin *security_plugin, void **security_plugin_context, - const struct ddsrt_log_cfg *logcfg); - +DDS_EXPORT dds_return_t dds_security_plugin_release(const dds_security_plugin *security_plugin, void *context); +DDS_EXPORT dds_return_t dds_security_check_plugin_configuration(const dds_security_plugin_suite_config *security_suite_config, struct ddsi_domaingv *gv); +DDS_EXPORT dds_return_t dds_security_load_security_library(const dds_security_plugin_config *plugin_config, dds_security_plugin *security_plugin, + void **security_plugin_context, struct ddsi_domaingv *gv); DDS_EXPORT dds_return_t dds_security_verify_plugin_functions( - dds_security_authentication *authentication_context, dds_security_plugin *auth_plugin, - dds_security_cryptography *crypto_context, dds_security_plugin *crypto_plugin, - dds_security_access_control *access_control_context, dds_security_plugin *ac_plugin, - const struct ddsrt_log_cfg *logcfg); + dds_security_authentication *authentication_context, dds_security_plugin *auth_plugin, + dds_security_cryptography *crypto_context, dds_security_plugin *crypto_plugin, + dds_security_access_control *access_control_context, dds_security_plugin *ac_plugin, + struct ddsi_domaingv *gv); #endif /* SECURITY_CORE_PLUGINS_H_ */ - diff --git a/src/security/core/src/dds_security_plugins.c b/src/security/core/src/dds_security_plugins.c index bfc75a4..15c5fb5 100644 --- a/src/security/core/src/dds_security_plugins.c +++ b/src/security/core/src/dds_security_plugins.c @@ -19,40 +19,40 @@ #include "dds/ddsrt/dynlib.h" #include "dds/ddsrt/io.h" -static bool check_plugin_configuration (const dds_security_plugin_config *config, const char *name, const struct ddsrt_log_cfg *logcfg) +static bool check_plugin_configuration (const dds_security_plugin_config *config, const char *name, struct ddsi_domaingv *gv) { if (config->library_path == NULL || *config->library_path == 0) { - DDS_CERROR (logcfg, "%s security plugin library path is undefined or empty\n", name); + GVERROR ("%s security plugin library path is undefined or empty\n", name); return false; } if (config->library_init == NULL || *config->library_init == 0) { - DDS_CERROR (logcfg, "%s security plugin init function is undefined or empty\n", name); + GVERROR ("%s security plugin init function is undefined or empty\n", name); return false; } if (config->library_finalize == NULL || *config->library_finalize == 0) { - DDS_CERROR (logcfg, "%s security plugin finalize function is undefined or empty\n", name); + GVERROR ("%s security plugin finalize function is undefined or empty\n", name); return false; } return true; } -dds_return_t dds_security_check_plugin_configuration (const dds_security_plugin_suite_config *security_suite_config, const struct ddsrt_log_cfg *logcfg) +dds_return_t dds_security_check_plugin_configuration (const dds_security_plugin_suite_config *security_suite_config, struct ddsi_domaingv *gv) { - if (check_plugin_configuration (&security_suite_config->access_control, "AccessControl", logcfg) && - check_plugin_configuration (&security_suite_config->authentication, "Authentication", logcfg) && - check_plugin_configuration (&security_suite_config->cryptography, "Cryptography", logcfg)) + if (check_plugin_configuration (&security_suite_config->access_control, "AccessControl", gv) && + check_plugin_configuration (&security_suite_config->authentication, "Authentication", gv) && + check_plugin_configuration (&security_suite_config->cryptography, "Cryptography", gv)) return DDS_RETCODE_OK; else return DDS_RETCODE_ERROR; } -static bool verify_function (const void *function_ptr, dds_security_plugin *plugin, const char *function_name, const struct ddsrt_log_cfg *logcfg) +static bool verify_function (const void *function_ptr, dds_security_plugin *plugin, const char *function_name, struct ddsi_domaingv *gv) { if (function_ptr != NULL) return true; else { - DDS_CERROR (logcfg, "Could not find the function for %s: %s\n", plugin->name, function_name); + GVERROR ("Could not find the function for %s: %s\n", plugin->name, function_name); return false; } } @@ -62,12 +62,12 @@ struct verify_plugin_functions_tab { const char *name; }; -static bool verify_plugin_functions (const void *context, dds_security_plugin *plugin, const struct verify_plugin_functions_tab *entries, size_t nentries, const struct ddsrt_log_cfg *logcfg) +static bool verify_plugin_functions (const void *context, dds_security_plugin *plugin, const struct verify_plugin_functions_tab *entries, size_t nentries, struct ddsi_domaingv *gv) { for (size_t i = 0; i < nentries; i++) { const char *p = (const char *) context + entries[i].off; - if (!verify_function (*((void **) p), plugin, entries[i].name, logcfg)) + if (!verify_function (*((void **) p), plugin, entries[i].name, gv)) return false; } return true; @@ -77,7 +77,7 @@ dds_return_t dds_security_verify_plugin_functions( dds_security_authentication *authentication_context, dds_security_plugin *auth_plugin, dds_security_cryptography *crypto_context, dds_security_plugin *crypto_plugin, dds_security_access_control *access_control_context, dds_security_plugin *ac_plugin, - const struct ddsrt_log_cfg *logcfg) + struct ddsi_domaingv *gv) { #define FGEN(context, name) { offsetof (context, name), #name } #define F(name) FGEN (dds_security_authentication, name) @@ -170,7 +170,7 @@ dds_return_t dds_security_verify_plugin_functions( F (decode_serialized_payload) }; #undef F -#define C(context, plugin, table) verify_plugin_functions (context, plugin, table, sizeof (table) / sizeof (table[0]), logcfg) +#define C(context, plugin, table) verify_plugin_functions (context, plugin, table, sizeof (table) / sizeof (table[0]), gv) if (C (authentication_context, auth_plugin, auth) && C (access_control_context, ac_plugin, ac) && C (crypto_context->crypto_key_factory, crypto_plugin, cryptoF) && @@ -189,7 +189,8 @@ dds_return_t dds_security_verify_plugin_functions( /** * All fields of the library properties are supposed to be non-empty */ -dds_return_t dds_security_load_security_library (const dds_security_plugin_config *plugin_config, dds_security_plugin *security_plugin, void **security_plugin_context, const struct ddsrt_log_cfg *logcfg) +dds_return_t dds_security_load_security_library (const dds_security_plugin_config *plugin_config, dds_security_plugin *security_plugin, + void **security_plugin_context, struct ddsi_domaingv *gv) { dds_return_t lib_ret; char *init_parameters = ""; @@ -211,30 +212,30 @@ dds_return_t dds_security_load_security_library (const dds_security_plugin_confi { char buffer[256]; ddsrt_dlerror (buffer, sizeof (buffer)); - DDS_CERROR (logcfg, "Could not load %s library: %s\n", security_plugin->name, buffer); + GVERROR ("Could not load %s library: %s\n", security_plugin->name, buffer); goto load_error; } void *tmp; if (ddsrt_dlsym (security_plugin->lib_handle, plugin_config->library_init, &tmp) != DDS_RETCODE_OK) { - DDS_CERROR (logcfg, "Could not find the function: %s\n", plugin_config->library_init); + GVERROR ("Could not find the function: %s\n", plugin_config->library_init); goto library_error; } security_plugin->func_init = (plugin_init) tmp; if (ddsrt_dlsym (security_plugin->lib_handle, plugin_config->library_finalize, &tmp) != DDS_RETCODE_OK) { - DDS_CERROR (logcfg, "Could not find the function: %s\n", plugin_config->library_finalize); + GVERROR ("Could not find the function: %s\n", plugin_config->library_finalize); goto library_error; } security_plugin->func_finalize = (plugin_finalize) tmp; if (security_plugin->func_init != 0) { - if (security_plugin->func_init (init_parameters, (void **) security_plugin_context) != DDS_RETCODE_OK) + if (security_plugin->func_init (init_parameters, (void **) security_plugin_context, gv) != DDS_RETCODE_OK) { - DDS_CERROR (logcfg, "Error occured while initializing %s plugin\n", security_plugin->name); + GVERROR ("Error occured while initializing %s plugin\n", security_plugin->name); goto library_error; } } diff --git a/src/security/core/tests/common/access_control_wrapper.c b/src/security/core/tests/common/access_control_wrapper.c index 83b88f6..3ba5b68 100644 --- a/src/security/core/tests/common/access_control_wrapper.c +++ b/src/security/core/tests/common/access_control_wrapper.c @@ -514,10 +514,11 @@ static struct dds_security_access_control_impl * init_test_access_control_common return impl; } -int32_t init_test_access_control_all_ok(const char *argument, void **context) +int32_t init_test_access_control_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv) { DDSRT_UNUSED_ARG(argument); DDSRT_UNUSED_ARG(context); + DDSRT_UNUSED_ARG(gv); struct dds_security_access_control_impl *impl = init_test_access_control_common(); impl->mode = PLUGIN_MODE_ALL_OK; *context = impl; @@ -531,10 +532,11 @@ int32_t finalize_test_access_control_all_ok(void *context) return 0; } -int32_t init_test_access_control_missing_func(const char *argument, void **context) +int32_t init_test_access_control_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv) { DDSRT_UNUSED_ARG(argument); DDSRT_UNUSED_ARG(context); + DDSRT_UNUSED_ARG(gv); struct dds_security_access_control_impl *impl = init_test_access_control_common(); impl->base.check_create_datareader = NULL; impl->mode = PLUGIN_MODE_MISSING_FUNC; diff --git a/src/security/core/tests/common/access_control_wrapper.h b/src/security/core/tests/common/access_control_wrapper.h index 70c9c2c..a7c2e7c 100644 --- a/src/security/core/tests/common/access_control_wrapper.h +++ b/src/security/core/tests/common/access_control_wrapper.h @@ -12,15 +12,16 @@ #ifndef SECURITY_CORE_TEST_ACCESS_CONTROL_WRAPPER_H_ #define SECURITY_CORE_TEST_ACCESS_CONTROL_WRAPPER_H_ +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/security/dds_security_api.h" #include "dds/security/access_control_wrapper_export.h" /* Init in all-ok mode: all functions return success without calling the actual plugin */ -SECURITY_EXPORT int32_t init_test_access_control_all_ok(const char *argument, void **context); +SECURITY_EXPORT int32_t init_test_access_control_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int32_t finalize_test_access_control_all_ok(void *context); /* Init in missing function mode: one of the function pointers is null */ -SECURITY_EXPORT int32_t init_test_access_control_missing_func(const char *argument, void **context); +SECURITY_EXPORT int32_t init_test_access_control_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int32_t finalize_test_access_control_missing_func(void *context); #endif /* SECURITY_CORE_TEST_ACCESS_CONTROL_WRAPPER_H_ */ diff --git a/src/security/core/tests/common/authentication_wrapper.c b/src/security/core/tests/common/authentication_wrapper.c index 0ab9882..a2d3709 100644 --- a/src/security/core/tests/common/authentication_wrapper.c +++ b/src/security/core/tests/common/authentication_wrapper.c @@ -22,7 +22,7 @@ #include "test_identity.h" #include "plugin_wrapper_msg_q.h" -int32_t init_authentication(const char *argument, void **context); +int32_t init_authentication(const char *argument, void **context, struct ddsi_domaingv *gv); int32_t finalize_authentication(void *context); enum auth_plugin_mode { @@ -41,7 +41,6 @@ struct dds_security_authentication_impl dds_security_authentication base; dds_security_authentication *instance; struct message_queue msg_queue; - const struct ddsi_domaingv *gv; enum auth_plugin_mode mode; }; @@ -439,7 +438,7 @@ static struct dds_security_authentication_impl * get_impl_for_domain(dds_domaini { for (size_t i = 0; i < auth_impl_idx; i++) { - if (auth_impl[i] && auth_impl[i]->gv->config.domainId == domain_id) + if (auth_impl[i] && auth_impl[i]->instance->gv->config.domainId == domain_id) { return auth_impl[i]; } @@ -483,10 +482,11 @@ static struct dds_security_authentication_impl * init_test_authentication_common return impl; } -int32_t init_test_authentication_all_ok(const char *argument, void **context) +int32_t init_test_authentication_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv) { DDSRT_UNUSED_ARG(argument); DDSRT_UNUSED_ARG(context); + DDSRT_UNUSED_ARG(gv); struct dds_security_authentication_impl *impl = init_test_authentication_common(); impl->mode = PLUGIN_MODE_ALL_OK; *context = impl; @@ -500,10 +500,11 @@ int32_t finalize_test_authentication_all_ok(void *context) return 0; } -int32_t init_test_authentication_missing_func(const char *argument, void **context) +int32_t init_test_authentication_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv) { DDSRT_UNUSED_ARG(argument); DDSRT_UNUSED_ARG(context); + DDSRT_UNUSED_ARG(gv); struct dds_security_authentication_impl *impl = init_test_authentication_common(); impl->base.get_shared_secret = NULL; impl->mode = PLUGIN_MODE_MISSING_FUNC; @@ -518,10 +519,11 @@ int32_t finalize_test_authentication_missing_func(void *context) return 0; } -int32_t init_test_authentication_init_error(const char *argument, void **context) +int32_t init_test_authentication_init_error(const char *argument, void **context, struct ddsi_domaingv *gv) { DDSRT_UNUSED_ARG(argument); DDSRT_UNUSED_ARG(context); + DDSRT_UNUSED_ARG(gv); return 1; } @@ -535,19 +537,14 @@ int32_t finalize_test_authentication_init_error(void *context) * Init and fini functions for using wrapped mode for the authentication plugin. * These functions assumes that there are no concurrent calls, as the static * variables used here are not protected by a lock. */ -int32_t init_test_authentication_wrapped(const char *argument, void **context) +int32_t init_test_authentication_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv) { int32_t ret; struct dds_security_authentication_impl *impl = init_test_authentication_common(); impl->mode = PLUGIN_MODE_WRAPPED; init_message_queue(&impl->msg_queue); - struct thread_state1 * const ts1 = lookup_thread_state (); - struct ddsi_domaingv const * const gv = ddsrt_atomic_ldvoidp (&ts1->gv); - impl->gv = gv; - - ret = init_authentication(argument, (void **)&impl->instance); - + ret = init_authentication(argument, (void **)&impl->instance, gv); auth_impl_idx++; auth_impl = ddsrt_realloc(auth_impl, auth_impl_idx * sizeof(*auth_impl)); auth_impl[auth_impl_idx - 1] = impl; diff --git a/src/security/core/tests/common/authentication_wrapper.h b/src/security/core/tests/common/authentication_wrapper.h index be4854a..d784454 100644 --- a/src/security/core/tests/common/authentication_wrapper.h +++ b/src/security/core/tests/common/authentication_wrapper.h @@ -12,24 +12,25 @@ #ifndef SECURITY_CORE_TEST_AUTHENTICATION_WRAPPER_H_ #define SECURITY_CORE_TEST_AUTHENTICATION_WRAPPER_H_ +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/security/dds_security_api.h" #include "dds/security/authentication_wrapper_export.h" #include "plugin_wrapper_msg_q.h" /* Init in wrapper mode */ -SECURITY_EXPORT int32_t init_test_authentication_wrapped(const char *argument, void **context); +SECURITY_EXPORT int32_t init_test_authentication_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int32_t finalize_test_authentication_wrapped(void *context); /* Init in all-ok mode: all functions return success without calling the actual plugin */ -SECURITY_EXPORT int32_t init_test_authentication_all_ok(const char *argument, void **context); +SECURITY_EXPORT int32_t init_test_authentication_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int32_t finalize_test_authentication_all_ok(void *context); /* Init in missing function mode: one of the function pointers is null */ -SECURITY_EXPORT int32_t init_test_authentication_missing_func(const char *argument, void **context); +SECURITY_EXPORT int32_t init_test_authentication_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int32_t finalize_test_authentication_missing_func(void *context); /* Init function fails */ -SECURITY_EXPORT int32_t init_test_authentication_init_error(const char *argument, void **context); +SECURITY_EXPORT int32_t init_test_authentication_init_error(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int32_t finalize_test_authentication_init_error(void *context); SECURITY_EXPORT struct message * test_authentication_plugin_take_msg(dds_domainid_t domain_id, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, dds_duration_t timeout); diff --git a/src/security/core/tests/common/cryptography_wrapper.c b/src/security/core/tests/common/cryptography_wrapper.c index 7af5c1b..a3d1508 100644 --- a/src/security/core/tests/common/cryptography_wrapper.c +++ b/src/security/core/tests/common/cryptography_wrapper.c @@ -22,7 +22,7 @@ #include "dds/security/core/dds_security_utils.h" #include "cryptography_wrapper.h" -int32_t init_crypto(const char *argument, void **context); +int32_t init_crypto(const char *argument, void **context, struct ddsi_domaingv *gv); int32_t finalize_crypto(void *context); enum crypto_plugin_mode { @@ -700,14 +700,14 @@ static DDS_Security_boolean decode_serialized_payload( /** * Init and finalize functions */ -static struct dds_security_cryptography_impl * init_test_cryptography_common(const char *argument, bool wrapped) +static struct dds_security_cryptography_impl * init_test_cryptography_common(const char *argument, bool wrapped, struct ddsi_domaingv *gv) { struct dds_security_cryptography_impl *impl = (struct dds_security_cryptography_impl*) ddsrt_malloc(sizeof(*impl)); memset(impl, 0, sizeof(*impl)); if (wrapped) { - if (init_crypto(argument, (void **)&impl->instance) != DDS_SECURITY_SUCCESS) + if (init_crypto(argument, (void **)&impl->instance, gv) != DDS_SECURITY_SUCCESS) return NULL; impl->transform_wrap.instance = impl->instance->crypto_transform; @@ -763,9 +763,9 @@ static int32_t finalize_test_cryptography_common(struct dds_security_cryptograph return DDS_SECURITY_SUCCESS; } -int32_t init_test_cryptography_all_ok(const char *argument, void **context) +int32_t init_test_cryptography_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv) { - struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, false); + struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, false, gv); if (!impl) return DDS_SECURITY_FAILED; impl->mode = PLUGIN_MODE_ALL_OK; @@ -780,9 +780,9 @@ int32_t finalize_test_cryptography_all_ok(void *context) return finalize_test_cryptography_common(impl, false); } -int32_t init_test_cryptography_missing_func(const char *argument, void **context) +int32_t init_test_cryptography_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv) { - struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, false); + struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, false, gv); if (!impl) return DDS_SECURITY_FAILED; impl->base.crypto_key_exchange->set_remote_participant_crypto_tokens = NULL; @@ -798,9 +798,9 @@ int32_t finalize_test_cryptography_missing_func(void *context) return finalize_test_cryptography_common(impl, false); } -int32_t init_test_cryptography_wrapped(const char *argument, void **context) +int32_t init_test_cryptography_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv) { - struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, true); + struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, true, gv); if (!impl) return DDS_SECURITY_FAILED; impl->mode = PLUGIN_MODE_WRAPPED; diff --git a/src/security/core/tests/common/cryptography_wrapper.h b/src/security/core/tests/common/cryptography_wrapper.h index 44e0501..f379727 100644 --- a/src/security/core/tests/common/cryptography_wrapper.h +++ b/src/security/core/tests/common/cryptography_wrapper.h @@ -12,6 +12,7 @@ #ifndef SECURITY_CORE_TEST_CRYPTO_WRAPPER_H_ #define SECURITY_CORE_TEST_CRYPTO_WRAPPER_H_ +#include "dds/ddsi/ddsi_domaingv.h" #include "dds/security/dds_security_api.h" #include "dds/security/dds_security_api_defs.h" #include "dds/security/cryptography_wrapper_export.h" @@ -34,15 +35,15 @@ SECURITY_EXPORT void set_disc_protection_kinds( SECURITY_EXPORT void set_entity_data_secret(struct dds_security_cryptography_impl * impl, const char * pp_secret, const char * groupdata_secret, const char * ep_secret); /* Init in all-ok mode: all functions return success without calling the actual plugin */ -SECURITY_EXPORT int32_t init_test_cryptography_all_ok(const char *argument, void **context); +SECURITY_EXPORT int32_t init_test_cryptography_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int32_t finalize_test_cryptography_all_ok(void *context); /* Init in missing function mode: one of the function pointers is null */ -SECURITY_EXPORT int32_t init_test_cryptography_missing_func(const char *argument, void **context); +SECURITY_EXPORT int32_t init_test_cryptography_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int32_t finalize_test_cryptography_missing_func(void *context); /* Init in wrapper mode */ -SECURITY_EXPORT int32_t init_test_cryptography_wrapped(const char *argument, void **context); +SECURITY_EXPORT int32_t init_test_cryptography_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int32_t finalize_test_cryptography_wrapped(void *context); #endif /* SECURITY_CORE_TEST_CRYPTO_WRAPPER_H_ */ From d53cdce8fe27b587c14232dcd8920192ff3b83c2 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Thu, 26 Mar 2020 18:48:54 +0100 Subject: [PATCH 159/238] Access Control on_revoke_permissions implementation in DDSI Implement handler for access control on_revoke_permissions. This callback function disconnects and deletes all proxy participant that are using the revoked permissions handle (in case of remote permissions expire) and proxy participant that are connected with a participant for which the permissions expire (local permissions expire). Signed-off-by: Dennis Potman --- src/core/ddsi/src/ddsi_security_omg.c | 113 +++++++++++++++--- .../dds_security_api_authentication.h | 1 - .../authentication/src/authentication.c | 2 +- .../src/listeners_authentication_utests.c | 15 +-- .../core/tests/secure_communication.c | 6 +- 5 files changed, 103 insertions(+), 34 deletions(-) diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 096608c..7766fcd 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -212,6 +212,8 @@ struct dds_security_context { struct pending_match_index security_matches; struct participant_sec_index partiticpant_index; + struct dds_security_access_control_listener ac_listener; + struct dds_security_authentication_listener auth_listener; }; typedef struct dds_security_context dds_security_context; @@ -525,34 +527,44 @@ static void proxypp_pp_match_free(struct ddsi_domaingv *gv, struct dds_security_ ddsrt_free(pm); } -static void pp_proxypp_unrelate(struct dds_security_context *sc, struct participant *pp, const ddsi_guid_t *proxypp_guid) +static void pp_proxypp_unrelate_locked(struct dds_security_context *sc, struct participant *pp, const ddsi_guid_t *proxypp_guid) { struct pp_proxypp_match *pm; ddsrt_avl_dpath_t dpath; - ddsrt_mutex_lock(&pp->sec_attr->lock); if ((pm = ddsrt_avl_clookup_dpath(&pp_proxypp_treedef, &pp->sec_attr->proxy_participants, proxypp_guid, &dpath)) != NULL) { ddsrt_avl_cdelete_dpath(&pp_proxypp_treedef, &pp->sec_attr->proxy_participants, pm, &dpath); pp_proxypp_match_free(sc, pm); } +} + +static void pp_proxypp_unrelate(struct dds_security_context *sc, struct participant *pp, const ddsi_guid_t *proxypp_guid) +{ + ddsrt_mutex_lock(&pp->sec_attr->lock); + pp_proxypp_unrelate_locked (sc, pp, proxypp_guid); ddsrt_mutex_unlock(&pp->sec_attr->lock); } +static void proxypp_pp_unrelate_locked(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); + struct proxypp_pp_match *pm; + ddsrt_avl_dpath_t dpath; + + if ((pm = ddsrt_avl_lookup_dpath(&proxypp_pp_treedef, &proxypp->sec_attr->participants, &pp_crypto_handle, &dpath)) != NULL) + { + ddsrt_avl_delete_dpath(&proxypp_pp_treedef, &proxypp->sec_attr->participants, pm, &dpath); + proxypp_pp_match_free(proxypp->e.gv, sc, pm); + } +} + 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; - ddsrt_avl_dpath_t dpath; - 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) - { - ddsrt_avl_delete_dpath(&proxypp_pp_treedef, &proxypp->sec_attr->participants, pm, &dpath); - proxypp_pp_match_free(proxypp->e.gv, sc, pm); - } + proxypp_pp_unrelate_locked(sc, proxypp, pp_guid, pp_crypto_handle); ddsrt_mutex_unlock(&proxypp->sec_attr->lock); } } @@ -798,6 +810,70 @@ static void deinit_plugin_suite_config (dds_security_plugin_suite_config *suite_ deinit_plugin_config (&suite_config->cryptography); } +static DDS_Security_boolean on_revoke_permissions_cb(const dds_security_access_control *plugin, const DDS_Security_PermissionsHandle handle) +{ + struct ddsi_domaingv *gv = plugin->gv; + struct entidx_enum_participant epp; + struct entidx_enum_proxy_participant eproxypp; + struct participant *pp; + struct proxy_participant *proxypp; + bool local_perm = false; + thread_state_awake (lookup_thread_state (), gv); + + /* Find participants using this permissions handle */ + entidx_enum_participant_init (&epp, gv->entity_index); + while ((pp = entidx_enum_participant_next (&epp)) != NULL) + { + struct dds_security_context *sc = q_omg_security_get_secure_context(pp); + ddsrt_mutex_lock (&pp->sec_attr->lock); + if (pp->sec_attr->permissions_handle == handle) + { + uint32_t i = 0; + ddsrt_avl_citer_t it; + local_perm = true; + for (struct pp_proxypp_match *ppm = ddsrt_avl_citer_first (&pp_proxypp_treedef, &pp->sec_attr->proxy_participants, &it); ppm; ppm = ddsrt_avl_citer_next (&it), i++) + pp_proxypp_unrelate_locked (sc, pp, &ppm->proxypp_guid); + } + ddsrt_mutex_unlock (&pp->sec_attr->lock); + } + entidx_enum_participant_fini (&epp); + + /* Find proxy participants using this permissions handle */ + if (!local_perm) + { + entidx_enum_proxy_participant_init (&eproxypp, gv->entity_index); + while ((proxypp = entidx_enum_proxy_participant_next (&eproxypp)) != NULL) + { + ddsrt_mutex_lock (&proxypp->sec_attr->lock); + uint32_t i = 0; + ddsrt_avl_iter_t it; + bool del_proxypp = true; + for (struct proxypp_pp_match *ppm = ddsrt_avl_iter_first (&proxypp_pp_treedef, &proxypp->sec_attr->participants, &it); ppm; ppm = ddsrt_avl_iter_next (&it), i++) + { + if (ppm->permissions_handle == handle) + proxypp_pp_unrelate_locked (proxypp->sec_attr->sc, proxypp, &ppm->pp_guid, ppm->pp_crypto_handle); + else + del_proxypp = false; + } + ddsrt_mutex_unlock (&proxypp->sec_attr->lock); + if (del_proxypp) + delete_proxy_participant_by_guid (gv, &proxypp->e.guid, ddsrt_time_wallclock (), false); + } + entidx_enum_proxy_participant_fini (&eproxypp); + } + + thread_state_asleep (lookup_thread_state ()); + return true; +} + +static DDS_Security_boolean on_revoke_identity_cb(const dds_security_authentication *plugin, const DDS_Security_IdentityHandle handle) +{ + (void)plugin; + (void)handle; + return true; +} + + dds_return_t q_omg_security_load (dds_security_context *sc, const dds_qos_t *qos, struct ddsi_domaingv *gv) { dds_security_plugin_suite_config psc; @@ -836,18 +912,19 @@ dds_return_t q_omg_security_load (dds_security_context *sc, const dds_qos_t *qos } /* Add listeners */ -#if LISTENERS_IMPLEMENTED - if (!access_control_context->set_listener (access_control_context, &listener_ac, &ex)) + DDS_Security_SecurityException ex = DDS_SECURITY_EXCEPTION_INIT; + sc->ac_listener.on_revoke_permissions = on_revoke_permissions_cb; + if (!sc->access_control_context->set_listener (sc->access_control_context, &sc->ac_listener, &ex)) { GVERROR ("Could not set access_control listener: %s\n", ex.message ? ex.message : ""); goto error_set_ac_listener; } - if (!authentication_context->set_listener (authentication_context, &listener_auth, &ex)) + sc->auth_listener.on_revoke_identity = on_revoke_identity_cb; + if (!sc->authentication_context->set_listener (sc->authentication_context, &sc->auth_listener, &ex)) { GVERROR ("Could not set authentication listener: %s\n", ex.message ? ex.message : ""); - goto err_set_auth_listener; + goto error_set_auth_listener; } -#endif #if HANDSHAKE_IMPLEMENTED (void) q_handshake_initialize (); @@ -858,11 +935,9 @@ dds_return_t q_omg_security_load (dds_security_context *sc, const dds_qos_t *qos GVTRACE ("DDS Security plugins have been loaded\n"); return DDS_RETCODE_OK; -#if LISTENERS_IMPLEMENTED error_set_auth_listener: - access_control_context->set_listener (access_control_context, NULL, &ex); + sc->access_control_context->set_listener (sc->access_control_context, NULL, &ex); error_set_ac_listener: -#endif error_verify: release_plugins (gv, sc); error: diff --git a/src/security/api/include/dds/security/dds_security_api_authentication.h b/src/security/api/include/dds/security/dds_security_api_authentication.h index c0d9298..5909dac 100644 --- a/src/security/api/include/dds/security/dds_security_api_authentication.h +++ b/src/security/api/include/dds/security/dds_security_api_authentication.h @@ -29,7 +29,6 @@ typedef struct dds_security_authentication_listener dds_security_authentication_ /* AuthenticationListener interface */ typedef DDS_Security_boolean (*DDS_Security_authentication_listener_on_revoke_identity)( - dds_security_authentication_listener *context, const dds_security_authentication *plugin, const DDS_Security_IdentityHandle handle); diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index 937aa7e..0ff0864 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -639,7 +639,7 @@ static void validity_callback(struct dds_security_timed_dispatcher_t *d, dds_sec assert(listener); dds_security_authentication_listener *auth_listener = (dds_security_authentication_listener *)listener; if (auth_listener->on_revoke_identity) - auth_listener->on_revoke_identity(auth_listener, (dds_security_authentication *)info->auth, info->hdl); + auth_listener->on_revoke_identity((dds_security_authentication *)info->auth, info->hdl); } ddsrt_free(arg); } diff --git a/src/security/builtin_plugins/tests/listeners_authentication/src/listeners_authentication_utests.c b/src/security/builtin_plugins/tests/listeners_authentication/src/listeners_authentication_utests.c index 779b254..7575837 100644 --- a/src/security/builtin_plugins/tests/listeners_authentication/src/listeners_authentication_utests.c +++ b/src/security/builtin_plugins/tests/listeners_authentication/src/listeners_authentication_utests.c @@ -1811,7 +1811,7 @@ fill_handshake_message_token( } CU_ASSERT_FATAL (rc == DDS_SECURITY_VALIDATION_OK); assert(rc == DDS_SECURITY_VALIDATION_OK); // for Clang's static analyzer - + set_binary_property_value(signature, "signature", sign, (uint32_t)signlen); ddsrt_free(sign); @@ -1911,18 +1911,13 @@ fill_handshake_message_token( } -static DDS_Security_boolean -on_revoke_identity_cb( dds_security_authentication_listener *instance, - const dds_security_authentication *plugin, - const DDS_Security_IdentityHandle handle) +static DDS_Security_boolean on_revoke_identity_cb(const dds_security_authentication *plugin, const DDS_Security_IdentityHandle handle) { - DDSRT_UNUSED_ARG( instance ); - DDSRT_UNUSED_ARG( plugin ); - if (identity_handle_for_callback1 == DDS_SECURITY_HANDLE_NIL) { + DDSRT_UNUSED_ARG (plugin); + if (identity_handle_for_callback1 == DDS_SECURITY_HANDLE_NIL) identity_handle_for_callback1 = handle; - } else if (identity_handle_for_callback2 == DDS_SECURITY_HANDLE_NIL) { + else if (identity_handle_for_callback2 == DDS_SECURITY_HANDLE_NIL) identity_handle_for_callback2 = handle; - } printf( "Listener called for handle: %lld Local:%lld Remote:%lld\n", (long long) handle, (long long) local_identity_handle, (long long) remote_identity_handle2); return true; diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index 7ed18b5..92b40a4 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -445,13 +445,13 @@ static void test_discovery_liveliness_protection(DDS_Security_ProtectionKind dis { struct domain_sec_config domain_config = { discovery_pk, liveliness_pk, PK_N, PK_N, BPK_N, NULL }; /* FIXME: add more asserts in wrapper or test instead of just testing communication */ - test_write_read (&domain_config, 1, 1, 1, 1, 1, 1, &set_encryption_parameters_disc); + test_write_read (&domain_config, 1, 1, 1, 1, 1, 1, set_encryption_parameters_disc); } static void test_data_protection_kind(DDS_Security_ProtectionKind rtps_pk, DDS_Security_ProtectionKind metadata_pk, DDS_Security_BasicProtectionKind payload_pk) { struct domain_sec_config domain_config = { PK_N, PK_N, rtps_pk, metadata_pk, payload_pk, NULL }; - test_write_read (&domain_config, 1, 1, 1, 1, 1, 1, &set_encryption_parameters_basic); + test_write_read (&domain_config, 1, 1, 1, 1, 1, 1, set_encryption_parameters_basic); } static void test_multiple_readers(size_t n_dom, size_t n_pp, size_t n_rd, DDS_Security_ProtectionKind metadata_pk, DDS_Security_BasicProtectionKind payload_pk) @@ -486,7 +486,7 @@ static void test_payload_secret(DDS_Security_ProtectionKind rtps_pk, DDS_Securit memcpy (sample.text + n * strlen (secret), secret, strlen (secret)); sample.text[payload_sz - 1] = '\0'; - test_init (&domain_config, 1, 1, 1, 1, &set_encryption_parameters_secret); + test_init (&domain_config, 1, 1, 1, 1, set_encryption_parameters_secret); create_topic_name ("ddssec_secure_communication_", g_topic_nr++, name, sizeof name); qos = get_qos (); create_eps (&writers, &writer_topics, 1, 1, 1, name, &SecurityCoreTests_Type2_desc, g_pub_participants, qos, &dds_create_writer, DDS_PUBLICATION_MATCHED_STATUS); From 736d0a027a8fc9baeb76ae2ebedfd6060a79511f Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Thu, 26 Mar 2020 13:42:11 +0100 Subject: [PATCH 160/238] Add access control tests for permissions expiry and move some reused test functions to common utils file. Signed-off-by: Dennis Potman --- src/security/core/tests/CMakeLists.txt | 2 +- src/security/core/tests/access_control.c | 308 +++++++++++++++--- src/security/core/tests/authentication.c | 151 ++------- .../tests/common/etc/default_permissions.p7s | 57 +++- .../tests/common/etc/default_permissions.xml | 33 ++ .../tests/common/security_config_test_utils.c | 48 ++- .../tests/common/security_config_test_utils.h | 4 +- .../{handshake_test_utils.c => test_utils.c} | 128 +++++++- .../{handshake_test_utils.h => test_utils.h} | 15 +- src/security/core/tests/handshake.c | 2 +- 10 files changed, 543 insertions(+), 205 deletions(-) rename src/security/core/tests/common/{handshake_test_utils.c => test_utils.c} (68%) rename src/security/core/tests/common/{handshake_test_utils.h => test_utils.h} (65%) diff --git a/src/security/core/tests/CMakeLists.txt b/src/security/core/tests/CMakeLists.txt index 639b84b..35337ab 100644 --- a/src/security/core/tests/CMakeLists.txt +++ b/src/security/core/tests/CMakeLists.txt @@ -74,7 +74,7 @@ if(ENABLE_SSL) list(APPEND security_core_test_sources "common/security_config_test_utils.c" - "common/handshake_test_utils.c" + "common/test_utils.c" "common/cert_utils.c" "authentication.c" "access_control.c" diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index 061dfef..508828c 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -21,6 +21,7 @@ #include "dds/ddsrt/environ.h" #include "dds/ddsrt/process.h" #include "dds/ddsrt/heap.h" +#include "dds/ddsrt/io.h" #include "dds/ddsrt/string.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/ddsi_domaingv.h" @@ -33,6 +34,9 @@ #include "common/access_control_wrapper.h" #include "common/security_config_test_utils.h" #include "common/test_identity.h" +#include "common/test_utils.h" +#include "common/cert_utils.h" +#include "SecurityCoreTests.h" static const char *config = "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" @@ -43,16 +47,16 @@ static const char *config = " " " " " " - " " - " data:," TEST_IDENTITY1_CERTIFICATE "" - " data:," TEST_IDENTITY1_PRIVATE_KEY "" - " data:," TEST_IDENTITY_CA1_CERTIFICATE "" + " " + " data:,${TEST_IDENTITY_CERTIFICATE}" + " data:,${TEST_IDENTITY_PRIVATE_KEY}" + " data:,${TEST_IDENTITY_CA_CERTIFICATE}" " " " " " " - " ${INCL_GOV:+}${TEST_GOVERNANCE}${INCL_GOV:+}" + " ${INCL_GOV:+}" " ${INCL_PERM_CA:+}${TEST_PERMISSIONS_CA}${INCL_PERM_CA:+}" - " ${INCL_PERM:+}${TEST_PERMISSIONS}${INCL_PERM:+}" + " ${INCL_PERM:+}" " " " " " " @@ -60,48 +64,49 @@ static const char *config = " " ""; -#define DDS_DOMAINID1 0 -#define DDS_DOMAINID2 1 +#define MAX_DOMAINS 10 +#define DDS_DOMAINID -static dds_entity_t g_domain1 = 0; -static dds_entity_t g_participant1 = 0; +static dds_entity_t g_domain[MAX_DOMAINS]; +static dds_entity_t g_participant[MAX_DOMAINS]; +static dds_entity_t g_pubsub[MAX_DOMAINS]; +static dds_entity_t g_topic[MAX_DOMAINS]; +static uint32_t g_topic_nr = 0; -static dds_entity_t g_domain2 = 0; -static dds_entity_t g_participant2 = 0; - -static void access_control_init(bool incl_gov, const char * gov, bool incl_perm, const char * perm, bool incl_ca, const char * ca, bool exp_pp_fail) +static void access_control_init( + const char * id_certs[], const char * id_keys[], const char * id_ca[], bool exp_pp_fail[], size_t n_nodes, + bool incl_gov, const char * gov, + bool incl_perm, const char * perm, + bool incl_ca, const char * ca) { - struct kvp config_vars[] = { - { "INCL_GOV", incl_gov ? "1" : "", 2 }, - { "INCL_PERM", incl_perm ? "1" : "", 2 }, - { "INCL_PERM_CA", incl_ca ? "1" : "", 2 }, - { "TEST_GOVERNANCE", gov, 1 }, - { "TEST_PERMISSIONS", perm, 1 }, - { "TEST_PERMISSIONS_CA", ca, 1 }, - { NULL, NULL, 0 } - }; - - char *conf = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars); - CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars), 0); - g_domain1 = dds_create_domain (DDS_DOMAINID1, conf); - g_domain2 = dds_create_domain (DDS_DOMAINID2, conf); - dds_free (conf); - - g_participant1 = dds_create_participant (DDS_DOMAINID1, NULL, NULL); - g_participant2 = dds_create_participant (DDS_DOMAINID2, NULL, NULL); - CU_ASSERT_EQUAL_FATAL (exp_pp_fail, g_participant1 <= 0); - CU_ASSERT_EQUAL_FATAL (exp_pp_fail, g_participant2 <= 0); + CU_ASSERT_FATAL (n_nodes <= MAX_DOMAINS); + for (size_t i = 0; i < n_nodes; i++) + { + struct kvp config_vars[] = { + { "TEST_IDENTITY_CERTIFICATE", id_certs[i], 1 }, + { "TEST_IDENTITY_PRIVATE_KEY", id_keys[i], 1 }, + { "TEST_IDENTITY_CA_CERTIFICATE", id_ca[i], 1 }, + { "INCL_GOV", incl_gov ? "1" : "", 2 }, + { "INCL_PERM", incl_perm ? "1" : "", 2 }, + { "INCL_PERM_CA", incl_ca ? "1" : "", 2 }, + { "TEST_GOVERNANCE", gov, 1 }, + { "TEST_PERMISSIONS", perm, 1 }, + { "TEST_PERMISSIONS_CA", ca, 1 }, + { NULL, NULL, 0 } + }; + char *conf = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars); + CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars), 0); + g_domain[i] = dds_create_domain (DDS_DOMAINID + (dds_domainid_t)i, conf); + dds_free (conf); + g_participant[i] = dds_create_participant (DDS_DOMAINID + (dds_domainid_t)i, NULL, NULL); + CU_ASSERT_EQUAL_FATAL (exp_pp_fail[i], g_participant[i] <= 0); + } } -static void access_control_fini(bool delete_pp) +static void access_control_fini(size_t n) { - if (delete_pp) - { - CU_ASSERT_EQUAL_FATAL (dds_delete (g_participant1), DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL (dds_delete (g_participant2), DDS_RETCODE_OK); - } - CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain1), DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain2), DDS_RETCODE_OK); + for (size_t i = 0; i < n; i++) + CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain[i]), DDS_RETCODE_OK); } @@ -144,6 +149,221 @@ CU_Theory((const char * test_descr, const char * gov, const char * perm, const c ddssec_access_control, config_parameters_file) { printf("running test config_parameters_file: %s\n", test_descr); - access_control_init (incl_empty_els || strlen (gov), gov, incl_empty_els || strlen (perm), perm, incl_empty_els || strlen (ca), ca, exp_fail); - access_control_fini (!exp_fail); + access_control_init ( + (const char *[]) { TEST_IDENTITY1_CERTIFICATE, TEST_IDENTITY1_CERTIFICATE }, + (const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY }, + (const char *[]) { TEST_IDENTITY_CA1_CERTIFICATE, TEST_IDENTITY_CA1_CERTIFICATE }, + (bool []) { exp_fail, exp_fail }, 2, + incl_empty_els || strlen (gov), gov, + incl_empty_els || strlen (perm), perm, + incl_empty_els || strlen (ca), ca); + access_control_fini (2); } + +#define S(n) (n) +#define M(n) (S(n)*60) +#define H(n) (M(n)*60) +#define D(n) (H(n)*24) +CU_TheoryDataPoints(ddssec_access_control, permissions_expiry) = { + CU_DataPoints(const char *, + /* */"valid 1 minute from now", + /* | */"valid -1 minute until now", + /* | | */"1s valid, create pp after 1100ms", + /* | | | */"node 2 permissions expired", + /* | | | | */"node 1 3s valid, write/read for 1s delayed 3s", + /* | | | | | */"node 2 3s valid, write/read for 1s delayed 3s"), + CU_DataPoints(int32_t, 0, -M(1), 0, 0, 0, 0), /* node 1 permissions not before (offset from local time) */ + CU_DataPoints(int32_t, M(1), 0, S(1), D(1), S(3), D(1)), /* node 1 permissions not after (offset from local time) */ + CU_DataPoints(int32_t, 0, -M(1), 0, -D(1), 0, 0), /* node 2 permissions not before (offset from local time) */ + CU_DataPoints(int32_t, M(1), 0, S(1), 0, D(1), S(3)), /* node 2 permissions not after (offset from local time) */ + CU_DataPoints(uint32_t, 0, 0, 1100, 0, 0, 0), /* delay (ms) after generating permissions */ + CU_DataPoints(bool, false, true, true, false, false, false), /* expect pp 1 create failure */ + CU_DataPoints(bool, false, true, true, true, false, false), /* expect pp 2 create failure */ + CU_DataPoints(uint32_t, 0, 0, 0, 0, 3000, 3000), /* delay (ms) after creating readers/writers */ + CU_DataPoints(uint32_t, 1, 0, 0, 0, 1000, 1000), /* write/read data during x ms */ + CU_DataPoints(bool, false, false, false, false, true, true), /* expect read data failure */ +}; +CU_Theory( + (const char * test_descr, + int32_t perm1_not_before, int32_t perm1_not_after, int32_t perm2_not_before, int32_t perm2_not_after, + uint32_t delay_perm, bool exp_pp1_fail, bool exp_pp2_fail, uint32_t delay_wr_rd, uint32_t write_read_dur, bool exp_read_fail), + ddssec_access_control, permissions_expiry, .timeout=20) +{ + printf("running test permissions_expiry: %s\n", test_descr); + + char topic_name[100]; + create_topic_name("ddssec_access_control_", g_topic_nr++, topic_name, sizeof (topic_name)); + + /* create ca and id1/id2 certs that will not expire during this test */ + char *ca, *id1, *id2, *id1_subj, *id2_subj; + ca = generate_ca ("ca1", TEST_IDENTITY_CA1_PRIVATE_KEY, 0, D(1)); + id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, D(1), &id1_subj); + id2 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id2", TEST_IDENTITY1_PRIVATE_KEY, 0, D(1), &id2_subj); + + /* localtime will be converted to gmtime in get_permissions_grant */ + dds_time_t now = dds_time (); + char * perm_topic = get_permissions_topic(topic_name); + char * grants[] = { + get_permissions_grant ("id1", id1_subj, now + DDS_SECS(perm1_not_before), now + DDS_SECS(perm1_not_after), perm_topic, perm_topic, NULL), + get_permissions_grant ("id2", id2_subj, now + DDS_SECS(perm2_not_before), now + DDS_SECS(perm2_not_after), perm_topic, perm_topic, NULL) }; + char * perm_config = get_permissions_config (grants, 2, true); + dds_sleepfor (DDS_MSECS (delay_perm)); + + access_control_init ( + (const char *[]) { id1, id2 }, + (const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY }, + (const char *[]) { ca, ca }, + (bool []) { exp_pp1_fail, exp_pp2_fail }, 2, + true, PF_F COMMON_ETC_PATH("default_governance.p7s"), + true, perm_config, + true, PF_F COMMON_ETC_PATH("default_permissions_ca.pem")); + + if (write_read_dur > 0) + { + dds_entity_t wr = 0, rd = 0; + rd_wr_init (g_participant[0], &g_pubsub[0], &g_topic[0], &wr, g_participant[1], &g_pubsub[1], &g_topic[1], &rd, topic_name); + dds_sleepfor (DDS_MSECS (delay_wr_rd)); + write_read_for (wr, g_participant[1], rd, DDS_MSECS (write_read_dur), false, exp_read_fail); + } + + access_control_fini (2); + + ddsrt_free (perm_topic); + ddsrt_free (grants[0]); + ddsrt_free (grants[1]); + ddsrt_free (perm_config); + ddsrt_free (ca); + ddsrt_free (id1_subj); + ddsrt_free (id2_subj); + ddsrt_free (id1); + ddsrt_free (id2); +} +#undef D +#undef H +#undef M + + +#define N_NODES 4 +#define PERM_EXP_BASE 3 +CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) +{ + char topic_name[100]; + create_topic_name("ddssec_access_control_", g_topic_nr++, topic_name, sizeof (topic_name)); + + dds_time_t t_perm = dds_time (); + char *ca = generate_ca ("ca1", TEST_IDENTITY_CA1_PRIVATE_KEY, 0, 3600); + char *perm_topic = get_permissions_topic (topic_name); + + // 1st node used as reader, other nodes as writer + const char *id[N_NODES], *pk[N_NODES], *ca_list[N_NODES]; + char * id_subj[N_NODES], *grants[N_NODES]; + bool exp_fail[N_NODES]; + for (int i = 0; i < N_NODES; i++) + { + char *id_name; + ddsrt_asprintf (&id_name, "id_%d", i); + pk[i] = TEST_IDENTITY1_PRIVATE_KEY; + ca_list[i] = ca; + id[i] = generate_identity (ca_list[i], TEST_IDENTITY_CA1_PRIVATE_KEY, id_name, pk[i], 0, 3600, &id_subj[i]); + exp_fail[i] = false; + dds_duration_t v = DDS_SECS(i == 0 ? 3600 : PERM_EXP_BASE + i); /* 1st node is reader and should not expire */ + grants[i] = get_permissions_grant (id_name, id_subj[i], t_perm, t_perm + v, perm_topic, perm_topic, NULL); + ddsrt_free (id_name); + } + + char * perm_config = get_permissions_config (grants, N_NODES, true); + access_control_init ( + id, pk, ca_list, exp_fail, N_NODES, + true, PF_F COMMON_ETC_PATH("default_governance.p7s"), + true, perm_config, + true, PF_F COMMON_ETC_PATH("default_permissions_ca.pem")); + + dds_qos_t * qos = dds_create_qos (); + CU_ASSERT_FATAL (qos != NULL); + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, -1); + dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL); + dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); + dds_entity_t sub_tp = dds_create_topic (g_participant[0], &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL); + CU_ASSERT_FATAL (sub_tp > 0); + dds_entity_t sub = dds_create_subscriber (g_participant[0], NULL, NULL); + CU_ASSERT_FATAL (sub > 0); + dds_entity_t rd = dds_create_reader (sub, sub_tp, qos, NULL); + CU_ASSERT_FATAL (rd > 0); + dds_set_status_mask (rd, DDS_DATA_AVAILABLE_STATUS); + + dds_entity_t wr[N_NODES - 1]; + for (int i = 1; i < N_NODES; i++) + { + dds_entity_t pub = dds_create_publisher (g_participant[i], NULL, NULL); + CU_ASSERT_FATAL (pub > 0); + dds_entity_t pub_tp = dds_create_topic (g_participant[i], &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL); + CU_ASSERT_FATAL (pub_tp > 0); + wr[i - 1] = dds_create_writer (pub, pub_tp, qos, NULL); + CU_ASSERT_FATAL (wr[i - 1] > 0); + dds_set_status_mask (wr[i - 1], DDS_PUBLICATION_MATCHED_STATUS); + sync_writer_to_readers(g_participant[i], wr[i - 1], 1); + } + dds_delete_qos (qos); + + SecurityCoreTests_Type1 sample = { 1, 1 }; + SecurityCoreTests_Type1 rd_sample; + void * samples[] = { &rd_sample }; + dds_sample_info_t info[1]; + dds_return_t ret; + + for (int i = 1; i < N_NODES; i++) + { + // sleep until 1s before next writer pp permission expires + dds_duration_t delay = DDS_SECS (PERM_EXP_BASE + i - 1) - (dds_time () - t_perm); + if (delay > 0) + dds_sleepfor (delay); + + printf ("run %d\n", i); + + for (int w = 1; w < N_NODES; w++) + { + sample.id = w; + ret = dds_write (wr[w - 1], &sample); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + printf ("write %d\n", w); + } + + // Expect reader to receive data from writers with non-expired permissions + int n_samples = 0, n_invalid = 0, n_wait = 0; + while (n_samples + n_invalid < N_NODES - 1 && n_wait < 5) + { + ret = dds_take (rd, samples, info, 1, 1); + CU_ASSERT_FATAL (ret >= 0); + if (ret == 0) + { + reader_wait_for_data (g_participant[0], rd, DDS_MSECS (100)); + n_wait++; + } + else if (info[0].instance_state == DDS_IST_ALIVE) + { + printf ("recv sample %d\n", rd_sample.id); + n_samples++; + } + else + { + printf ("recv inv sample\n"); + n_invalid++; + } + } + CU_ASSERT_EQUAL (n_samples, N_NODES - i); + CU_ASSERT (n_invalid < i); + } + + access_control_fini (N_NODES); + + for (int i = 0; i < N_NODES; i++) + { + ddsrt_free (grants[i]); + ddsrt_free (id_subj[i]); + ddsrt_free ((char *)id[i]); + } + ddsrt_free (ca); + ddsrt_free (perm_topic); + ddsrt_free (perm_config); +} +#undef N_NODES diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index a23f203..1e53a8f 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -19,7 +19,6 @@ #include "dds/version.h" #include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/environ.h" -#include "dds/ddsrt/process.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsi/q_config.h" @@ -31,15 +30,12 @@ #include "common/config_env.h" #include "common/authentication_wrapper.h" -#include "common/handshake_test_utils.h" +#include "common/test_utils.h" #include "common/security_config_test_utils.h" #include "common/test_identity.h" #include "common/cert_utils.h" #include "common/security_config_test_utils.h" -#include "SecurityCoreTests.h" - - #define ID1 TEST_IDENTITY1_CERTIFICATE #define ID1K TEST_IDENTITY1_PRIVATE_KEY #define ID2 TEST_IDENTITY2_CERTIFICATE @@ -152,119 +148,6 @@ static void authentication_init( ddsrt_free (conf2); } -static char *create_topic_name(const char *prefix, uint32_t nr, char *name, size_t size) -{ - ddsrt_pid_t pid = ddsrt_getpid (); - ddsrt_tid_t tid = ddsrt_gettid (); - (void)snprintf(name, size, "%s%d_pid%" PRIdPID "_tid%" PRIdTID "", prefix, nr, pid, tid); - return name; -} - -static void sync_writer_to_reader() -{ - dds_attach_t triggered; - dds_return_t ret; - dds_entity_t waitset_wr = dds_create_waitset (g_participant1); - CU_ASSERT_FATAL (waitset_wr > 0); - dds_publication_matched_status_t pub_matched; - - /* Sync writer to reader. */ - ret = dds_waitset_attach (waitset_wr, g_wr, g_wr); - CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); - while (true) - { - ret = dds_waitset_wait (waitset_wr, &triggered, 1, DDS_SECS(5)); - CU_ASSERT_FATAL (ret >= 1); - CU_ASSERT_EQUAL_FATAL (g_wr, (dds_entity_t)(intptr_t) triggered); - ret = dds_get_publication_matched_status(g_wr, &pub_matched); - CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); - if (pub_matched.total_count >= 1) - break; - }; - dds_delete (waitset_wr); -} - -static void reader_wait_for_data() -{ - dds_attach_t triggered; - dds_return_t ret; - dds_entity_t waitset_rd = dds_create_waitset (g_participant2); - CU_ASSERT_FATAL (waitset_rd > 0); - - ret = dds_waitset_attach (waitset_rd, g_rd, g_rd); - CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); - ret = dds_waitset_wait (waitset_rd, &triggered, 1, DDS_SECS(5)); - CU_ASSERT_EQUAL_FATAL (ret, 1); - CU_ASSERT_EQUAL_FATAL (g_rd, (dds_entity_t)(intptr_t)triggered); - dds_delete (waitset_rd); -} - -static void rd_wr_init() -{ - char name[100]; - dds_qos_t * qos = dds_create_qos (); - CU_ASSERT_FATAL (qos != NULL); - dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, -1); - dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL); - dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); - - create_topic_name("ddssec_authentication_", g_topic_nr++, name, sizeof (name)); - g_pub = dds_create_publisher (g_participant1, NULL, NULL); - CU_ASSERT_FATAL (g_pub > 0); - g_sub = dds_create_subscriber (g_participant2, NULL, NULL); - CU_ASSERT_FATAL (g_sub > 0); - g_pub_tp = dds_create_topic (g_participant1, &SecurityCoreTests_Type1_desc, name, NULL, NULL); - CU_ASSERT_FATAL (g_pub_tp > 0); - g_sub_tp = dds_create_topic (g_participant2, &SecurityCoreTests_Type1_desc, name, NULL, NULL); - CU_ASSERT_FATAL (g_sub_tp > 0); - g_wr = dds_create_writer (g_pub, g_pub_tp, qos, NULL); - CU_ASSERT_FATAL (g_wr > 0); - dds_set_status_mask (g_wr, DDS_PUBLICATION_MATCHED_STATUS); - g_rd = dds_create_reader (g_sub, g_sub_tp, qos, NULL); - CU_ASSERT_FATAL (g_rd > 0); - dds_set_status_mask (g_rd, DDS_DATA_AVAILABLE_STATUS); - sync_writer_to_reader(); - dds_delete_qos (qos); -} - -static void write_read(dds_duration_t dur, bool exp_write_fail, bool exp_read_fail) -{ - SecurityCoreTests_Type1 sample = { 1, 1 }; - SecurityCoreTests_Type1 rd_sample; - void * samples[] = { &rd_sample }; - dds_sample_info_t info[1]; - dds_return_t ret; - dds_time_t tend = dds_time () + dur; - bool write_fail = false, read_fail = false; - - rd_wr_init (); - do - { - ret = dds_write (g_wr, &sample); - if (ret != DDS_RETCODE_OK) - write_fail = true; - while (true) - { - if ((ret = dds_take (g_rd, samples, info, 1, 1)) == 0) - { - reader_wait_for_data (); - continue; - } - else if (ret < 0) - { - read_fail = true; - break; - } - CU_ASSERT_EQUAL_FATAL (ret, 1); - break; - } - dds_sleepfor (DDS_MSECS (1)); - } - while (dds_time() < tend && !write_fail && !read_fail); - CU_ASSERT_EQUAL_FATAL (write_fail, exp_write_fail); - CU_ASSERT_EQUAL_FATAL (read_fail, exp_read_fail); -} - static void authentication_fini(bool delete_pp1, bool delete_pp2) { if (delete_pp1) @@ -276,7 +159,7 @@ static void authentication_fini(bool delete_pp1, bool delete_pp2) } #define FM_CA "error: unable to get local issuer certificate" -#define FM_INVK "Failed to finalize verify context" +#define FM_INVK "Failed to finalize digest context" CU_TheoryDataPoints(ddssec_authentication, id_ca_certs) = { CU_DataPoints(const char *, /* */"valid ID1-ID1", @@ -341,7 +224,7 @@ CU_Theory((const char * test_descr, const char * id2, const char *key2, const ch bool exp_fail_local, const char * fail_local_msg, bool exp_fail_hs_req, const char * fail_hs_req_msg, bool exp_fail_hs_reply, const char * fail_hs_reply_msg), - ddssec_authentication, id_ca_certs) + ddssec_authentication, id_ca_certs, .timeout=30) { struct Handshake *hs_list; int nhs; @@ -393,12 +276,12 @@ CU_TheoryDataPoints(ddssec_authentication, expired_cert) = { /* | | | | | | */"id1 valid after 1s, delay 1100ms", /* | | | | | | | *//*"ca and id1 expire during session"*/), CU_DataPoints(int32_t, 0, -M(1), 0, 0, 0, 0, 0, /*0*/ ), /* CA1 not before */ - CU_DataPoints(int32_t, D(1), 0, D(1), D(1), M(1), D(1), D(1), /*2*/ ), /* CA1 not after */ - CU_DataPoints(int32_t, 0, 0, -D(1), 0, 0, 0, 1, /*0*/ ), /* ID1 not before */ - CU_DataPoints(int32_t, D(1), D(1), 0, D(1), M(1), 1, D(1), /*2*/ ), /* ID1 not after */ + CU_DataPoints(int32_t, D(1), 0, D(1), D(1), M(1), D(1), D(1), /*2*/ ), /* CA1 not after (offset from local time) */ + CU_DataPoints(int32_t, 0, 0, -D(1), 0, 0, 0, 1, /*0*/ ), /* ID1 not before (offset from local time) */ + CU_DataPoints(int32_t, D(1), D(1), 0, D(1), M(1), 1, D(1), /*2*/ ), /* ID1 not after (offset from local time) */ CU_DataPoints(bool, false, true, true, false, false, true, false, /*false*/ ), /* expect validate local ID1 fail */ - CU_DataPoints(int32_t, 0, 0, 0, -D(1), 0, 0, 0, /*0*/ ), /* ID2 not before */ - CU_DataPoints(int32_t, D(1), D(1), D(1), 0, D(1), 1, D(1), /*D(1)*/ ), /* ID2 not after */ + CU_DataPoints(int32_t, 0, 0, 0, -D(1), 0, 0, 0, /*0*/ ), /* ID2 not before (offset from local time) */ + CU_DataPoints(int32_t, D(1), D(1), D(1), 0, D(1), 1, D(1), /*D(1)*/ ), /* ID2 not after (offset from local time) */ CU_DataPoints(bool, false, true, false, true, false, true, false, /*false*/ ), /* expect validate local ID2 fail */ CU_DataPoints(uint32_t, 0, 0, 0, 0, 0, 1100, 1100, /*0*/ ), /* delay (ms) after generating certificate */ CU_DataPoints(uint32_t, 1, 0, 0, 0, 1, 0, 1, /*3500*/ ), /* write/read data during x ms */ @@ -409,22 +292,32 @@ CU_Theory( int32_t id1_not_before, int32_t id1_not_after, bool id1_local_fail, int32_t id2_not_before, int32_t id2_not_after, bool id2_local_fail, uint32_t delay, uint32_t write_read_dur, bool exp_read_fail), - ddssec_authentication, expired_cert) + ddssec_authentication, expired_cert, .timeout=30) { - char *ca, *id1, *id2, *id1_subj, *id2_subj; printf("running test expired_cert: %s\n", test_descr); + + char topic_name[100]; + create_topic_name("ddssec_authentication_", g_topic_nr++, topic_name, sizeof (topic_name)); + + char *ca, *id1, *id2, *id1_subj, *id2_subj; ca = generate_ca ("ca1", CA1K, ca_not_before, ca_not_after); id1 = generate_identity (ca, CA1K, "id1", ID1K, id1_not_before, id1_not_after, &id1_subj); id2 = generate_identity (ca, CA1K, "id2", ID1K, id2_not_before, id2_not_after, &id2_subj); dds_sleepfor (DDS_MSECS (delay)); - char * grants[] = { get_permissions_grant ("id1", id1_subj), get_permissions_grant ("id2", id2_subj) }; + dds_time_t now = dds_time (); + char * grants[] = { + get_permissions_grant ("id1", id1_subj, now - DDS_SECS(D(1)), now + DDS_SECS(D(1)), NULL, NULL, NULL), + get_permissions_grant ("id2", id2_subj, now - DDS_SECS(D(1)), now + DDS_SECS(D(1)), NULL, NULL, NULL) }; char * perm_config = get_permissions_config (grants, 2, true); authentication_init (id1, ID1K, ca, id2, ID1K, ca, NULL, perm_config, id1_local_fail, id2_local_fail); validate_handshake (DDS_DOMAINID1, id1_local_fail, NULL, NULL, NULL); validate_handshake (DDS_DOMAINID2, id2_local_fail, NULL, NULL, NULL); if (write_read_dur > 0) - write_read (DDS_MSECS (write_read_dur), false, exp_read_fail); + { + rd_wr_init (g_participant1, &g_pub, &g_pub_tp, &g_wr, g_participant2, &g_sub, &g_sub_tp, &g_rd, topic_name); + write_read_for (g_wr, g_participant2, g_rd, DDS_MSECS (write_read_dur), false, exp_read_fail); + } authentication_fini (!id1_local_fail, !id2_local_fail); ddsrt_free (grants[0]); ddsrt_free (grants[1]); diff --git a/src/security/core/tests/common/etc/default_permissions.p7s b/src/security/core/tests/common/etc/default_permissions.p7s index ddc97bc..4c8985b 100644 --- a/src/security/core/tests/common/etc/default_permissions.p7s +++ b/src/security/core/tests/common/etc/default_permissions.p7s @@ -1,9 +1,9 @@ MIME-Version: 1.0 -Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----A38CC2CF99C9B2ECE7711B9937B56A67" +Content-Type: multipart/signed; protocol="application/x-pkcs7-signature"; micalg="sha-256"; boundary="----82330497FB128B8C3833F86AA2902BC0" This is an S/MIME signed message -------A38CC2CF99C9B2ECE7711B9937B56A67 +------82330497FB128B8C3833F86AA2902BC0 Content-Type: text/plain @@ -76,10 +76,43 @@ Content-Type: text/plain DENY + + emailAddress=carol@cycloneddssecurity.adlinktech.com,CN=Carol Example,O=Example Organization,OU=Organizational Unit Name,L=Locality Name,ST=OV,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + * + + + + + * + + + * + + + + DENY + -------A38CC2CF99C9B2ECE7711B9937B56A67 +------82330497FB128B8C3833F86AA2902BC0 Content-Type: application/x-pkcs7-signature; name="smime.p7s" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="smime.p7s" @@ -115,16 +148,16 @@ DBdFeGFtcGxlIENBIE9yZ2FuaXphdGlvbjEfMB0GA1UEAwwWRXhhbXBsZSBQZXJt aXNzaW9ucyBDQTE6MDgGCSqGSIb3DQEJARYrYXV0aG9yaXR5QGN5Y2xvbmVkZHNz ZWN1cml0eS5hZGxpbmt0ZWNoLmNvbQIUfoby6818hlJQ+41KUHiM6BZll/0wDQYJ YIZIAWUDBAIBBQCggeQwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG -9w0BCQUxDxcNMjAwMzI1MDczMTM5WjAvBgkqhkiG9w0BCQQxIgQg3FQPbVj9xFlc -/eoZaddhdX1BXlKZyENrbh7DcCwklVwweQYJKoZIhvcNAQkPMWwwajALBglghkgB +9w0BCQUxDxcNMjAwMzI3MTMyMzM3WjAvBgkqhkiG9w0BCQQxIgQgZQWM3IUTViCR +9e+lYi65rV0rszQ5ZMG9iWStIWhT3UQweQYJKoZIhvcNAQkPMWwwajALBglghkgB ZQMEASowCwYJYIZIAWUDBAEWMAsGCWCGSAFlAwQBAjAKBggqhkiG9w0DBzAOBggq hkiG9w0DAgICAIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwIC -ASgwDQYJKoZIhvcNAQEBBQAEggEAWJxDp9TDqXKazAlIj9SZ8mQXhhGoTDeqZbxE -Bs561dHUmQVtA2S85TWGiCffKqWj3wlF5GwZNneYEV1deE3LZFa0o1+/VpeIBSGO -Qs1xKS7zx8IkGok3k88bh+eohDrgpzdLWkZeJ4P7J/3JmCMFdTXuCpuQYhRIrXO0 -pq4ueV2qGyCN6GZS2PC88GV0xeoS62Vj1Xze8omfgDI7KCPhKz6gJSEFUUqIzg7p -Zhqm15qorUoBVXcvMwaG95/xZVfcZzMbmJB/nhwd9KYu9ImkGj6ssSbgr3VR4OkQ -gQUib4aVQJQgBaWEPrgSjRkAp9rMB7R9IW6p2auMA/Gd/kbd7g== +ASgwDQYJKoZIhvcNAQEBBQAEggEAaZ687ayhsPnVPmsrPM4ECEU9/+PZAuFFV094 +Cqa9YLmsnO0jFElZLu2XRx1oNVp8TxG6OVckDINAxQjMO15+k0oqsAqdJFbgFLA/ +YidfEpuhFUjOy938Y46X6tbFj527GfLS8m3vIoYX+E+db1QcGv22RHb/KKSk6Htc +rbgEFV0pmyNK2foHp9ruBdu/nD7mXRo7h/xZdch60zDyeG40bsoKL63wC62sxQ/X +Mjxc1gmyXXr6AAEVzCVGIr9XHgaTNrThLfoWSRGcrLJI4cwevJ+jLJBBj347FmXi +x8nk6a09p7r9fSASX4vRiLDmDbuFwXolfNLS7Op3UKgkhJBm/A== -------A38CC2CF99C9B2ECE7711B9937B56A67-- +------82330497FB128B8C3833F86AA2902BC0-- diff --git a/src/security/core/tests/common/etc/default_permissions.xml b/src/security/core/tests/common/etc/default_permissions.xml index 5802a3e..d59a629 100644 --- a/src/security/core/tests/common/etc/default_permissions.xml +++ b/src/security/core/tests/common/etc/default_permissions.xml @@ -68,5 +68,38 @@ DENY + + emailAddress=carol@cycloneddssecurity.adlinktech.com,CN=Carol Example,O=Example Organization,OU=Organizational Unit Name,L=Locality Name,ST=OV,C=NL + + + 2015-09-15T01:00:00 + 2115-09-15T01:00:00 + + + + + 0 + 230 + + + + + * + + + * + + + + + * + + + * + + + + DENY + diff --git a/src/security/core/tests/common/security_config_test_utils.c b/src/security/core/tests/common/security_config_test_utils.c index ef9f0f8..51a0a9f 100644 --- a/src/security/core/tests/common/security_config_test_utils.c +++ b/src/security/core/tests/common/security_config_test_utils.c @@ -60,22 +60,25 @@ static const char *governance_xml = " " ""; +static const char *topic_xml = + "${TOPIC_NAME}"; + static const char *permissions_xml_grant = " " " ${SUBJECT_NAME}" - " 2015-09-15T01:00:002115-09-15T01:00:00" + " ${NOT_BEFORE:-2015-09-15T01:00:00}${NOT_AFTER:-2115-09-15T01:00:00}" " " " 0230" " " - " *" + " ${PUB_TOPICS:-*}" " *" " " " " - " *" + " ${SUB_TOPICS:-*}" " *" " " " " - " DENY" + " ${DEFAULT_POLICY:-DENY}" " "; static const char *permissions_xml = @@ -212,11 +215,46 @@ char * get_governance_config(struct kvp *config_vars, bool add_prefix) return prefix_data (config_signed, add_prefix); } -char * get_permissions_grant(const char * name, const char * subject) + +char * get_permissions_topic(const char * name) { + struct kvp vars[] = { + { "TOPIC_NAME", name, 1 }, + { NULL, NULL, 0 } + }; + return ddsrt_expand_vars (topic_xml, &expand_lookup_vars, vars); +} + +static char * get_xml_datetime(dds_time_t t, char * buf, size_t len) +{ + struct tm tm; + time_t sec = (time_t)(t / DDS_NSECS_IN_SEC); +#if _WIN32 + (void)gmtime_s(&tm, &sec); +#else + (void)gmtime_r(&sec, &tm); +#endif /* _WIN32 */ + + strftime(buf, len, "%FT%TZ", &tm); + return buf; +} + +char * get_permissions_grant(const char * name, const char * subject, + dds_time_t not_before, dds_time_t not_after, const char * pub_topics, const char * sub_topics, const char * default_policy) +{ + char not_before_str[] = "0000-00-00T00:00:00Z"; + char not_after_str[] = "0000-00-00T00:00:00Z"; + get_xml_datetime(not_before, not_before_str, sizeof(not_before_str)); + get_xml_datetime(not_after, not_after_str, sizeof(not_after_str)); + struct kvp vars[] = { { "GRANT_NAME", name, 1 }, { "SUBJECT_NAME", subject, 1 }, + { "NOT_BEFORE", not_before_str, 1 }, + { "NOT_AFTER", not_after_str, 1 }, + { "PUB_TOPICS", pub_topics, 1 }, + { "SUB_TOPICS", sub_topics, 1 }, + { "DEFAULT_POLICY", default_policy, 1 }, { NULL, NULL, 0 } }; return ddsrt_expand_vars (permissions_xml_grant, &expand_lookup_vars, vars); diff --git a/src/security/core/tests/common/security_config_test_utils.h b/src/security/core/tests/common/security_config_test_utils.h index 056b4d5..87f8e4b 100644 --- a/src/security/core/tests/common/security_config_test_utils.h +++ b/src/security/core/tests/common/security_config_test_utils.h @@ -26,7 +26,9 @@ const char * expand_lookup_vars_env (const char *name, void * data); int32_t expand_lookup_unmatched (const struct kvp * lookup_table); char * get_governance_config (struct kvp *config_vars, bool add_prefix); -char * get_permissions_grant(const char * name, const char * subject); +char * get_permissions_topic(const char * name); +char * get_permissions_grant(const char * name, const char * subject, + dds_time_t not_before, dds_time_t not_after, const char * pub_topics, const char * sub_topics, const char * default_policy); char * get_permissions_config(char * grants[], size_t ngrants, bool add_prefix); #endif /* SECURITY_CORE_TEST_SECURITY_CONFIG_TEST_UTILS_H_ */ diff --git a/src/security/core/tests/common/handshake_test_utils.c b/src/security/core/tests/common/test_utils.c similarity index 68% rename from src/security/core/tests/common/handshake_test_utils.c rename to src/security/core/tests/common/test_utils.c index 6385de2..476490c 100644 --- a/src/security/core/tests/common/handshake_test_utils.c +++ b/src/security/core/tests/common/test_utils.c @@ -14,13 +14,16 @@ #include "CUnit/Test.h" #include "dds/dds.h" +#include "dds/ddsrt/process.h" #include "dds/ddsrt/string.h" +#include "dds/ddsrt/threads.h" #include "dds/ddsrt/heap.h" #include "dds/security/dds_security_api.h" #include "authentication_wrapper.h" -#include "handshake_test_utils.h" +#include "test_utils.h" +#include "SecurityCoreTests.h" -#define TIMEOUT DDS_SECS(2) +#define HS_TIMEOUT DDS_SECS(2) struct Identity localIdentityList[MAX_LOCAL_IDENTITIES]; int numLocal = 0; @@ -131,7 +134,7 @@ static int find_handshake(DDS_Security_HandshakeHandle handle) static void handle_process_message(dds_domainid_t domain_id, DDS_Security_IdentityHandle handshake) { struct message *msg; - if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_PROCESS_HANDSHAKE, 0, 0, handshake, TIMEOUT))) + if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_PROCESS_HANDSHAKE, 0, 0, handshake, HS_TIMEOUT))) { int idx; if ((idx = find_handshake(msg->hsHandle)) >= 0) @@ -148,7 +151,7 @@ static void handle_begin_handshake_request(dds_domainid_t domain_id, struct Hand { struct message *msg; printf("handle begin handshake request %"PRId64"<->%"PRId64"\n", lid, rid); - if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REQUEST, lid, rid, 0, TIMEOUT))) + if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REQUEST, lid, rid, 0, HS_TIMEOUT))) { hs->handle = msg->hsHandle; hs->handshakeResult = msg->result; @@ -164,7 +167,7 @@ static void handle_begin_handshake_reply(dds_domainid_t domain_id, struct Handsh { struct message *msg; printf("handle begin handshake reply %"PRId64"<->%"PRId64"\n", lid, rid); - if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REPLY, lid, rid, 0, TIMEOUT))) + if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REPLY, lid, rid, 0, HS_TIMEOUT))) { hs->handle = msg->hsHandle; hs->handshakeResult = msg->result; @@ -179,7 +182,7 @@ static void handle_begin_handshake_reply(dds_domainid_t domain_id, struct Handsh static void handle_validate_remote_identity(dds_domainid_t domain_id, DDS_Security_IdentityHandle lid, int count) { struct message *msg; - while (count-- > 0 && (msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_VALIDATE_REMOTE_IDENTITY, lid, 0, 0, TIMEOUT))) + while (count-- > 0 && (msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_VALIDATE_REMOTE_IDENTITY, lid, 0, 0, HS_TIMEOUT))) { struct Handshake *hs; add_remote_identity(msg->ridHandle, &msg->rguid); @@ -204,7 +207,7 @@ static void handle_validate_remote_identity(dds_domainid_t domain_id, DDS_Securi static void handle_validate_local_identity(dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg) { - struct message *msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_VALIDATE_LOCAL_IDENTITY, 0, 0, 0, TIMEOUT); + struct message *msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_VALIDATE_LOCAL_IDENTITY, 0, 0, 0, HS_TIMEOUT); CU_ASSERT_FATAL (msg != NULL); CU_ASSERT_FATAL ((msg->result == DDS_SECURITY_VALIDATION_OK) != exp_localid_fail); if (exp_localid_fail && exp_localid_msg) @@ -268,4 +271,113 @@ void handshake_list_fini(struct Handshake *hs_list, int nhs) struct Handshake hs = hs_list[n]; ddsrt_free (hs.err_msg); } -} \ No newline at end of file +} + +void sync_writer_to_readers(dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_count) +{ + dds_attach_t triggered; + dds_entity_t ws = dds_create_waitset (pp_wr); + CU_ASSERT_FATAL (ws > 0); + dds_publication_matched_status_t pub_matched; + + dds_return_t ret = dds_waitset_attach (ws, wr, wr); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + while (true) + { + ret = dds_waitset_wait (ws, &triggered, 1, DDS_SECS(5)); + CU_ASSERT_FATAL (ret >= 1); + CU_ASSERT_EQUAL_FATAL (wr, (dds_entity_t)(intptr_t) triggered); + ret = dds_get_publication_matched_status(wr, &pub_matched); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + if (pub_matched.total_count >= exp_count) + break; + }; + dds_delete (ws); + CU_ASSERT_EQUAL_FATAL (pub_matched.total_count, exp_count); +} + +char *create_topic_name(const char *prefix, uint32_t nr, char *name, size_t size) +{ + ddsrt_pid_t pid = ddsrt_getpid (); + ddsrt_tid_t tid = ddsrt_gettid (); + (void)snprintf(name, size, "%s%d_pid%" PRIdPID "_tid%" PRIdTID "", prefix, nr, pid, tid); + return name; +} + +bool reader_wait_for_data(dds_entity_t pp, dds_entity_t rd, dds_duration_t dur) +{ + dds_attach_t triggered; + dds_entity_t ws = dds_create_waitset (pp); + CU_ASSERT_FATAL (ws > 0); + dds_return_t ret = dds_waitset_attach (ws, rd, rd); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + ret = dds_waitset_wait (ws, &triggered, 1, dur); + if (ret > 0) + CU_ASSERT_EQUAL_FATAL (rd, (dds_entity_t)(intptr_t)triggered); + dds_delete (ws); + return ret > 0; +} + +void rd_wr_init( + dds_entity_t pp_wr, dds_entity_t *pub, dds_entity_t *pub_tp, dds_entity_t *wr, + dds_entity_t pp_rd, dds_entity_t *sub, dds_entity_t *sub_tp, dds_entity_t *rd, + const char * topic_name) +{ + dds_qos_t * qos = dds_create_qos (); + CU_ASSERT_FATAL (qos != NULL); + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, -1); + dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL); + dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); + + *pub = dds_create_publisher (pp_wr, NULL, NULL); + CU_ASSERT_FATAL (*pub > 0); + *sub = dds_create_subscriber (pp_rd, NULL, NULL); + CU_ASSERT_FATAL (*sub > 0); + *pub_tp = dds_create_topic (pp_wr, &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL); + CU_ASSERT_FATAL (*pub_tp > 0); + *sub_tp = dds_create_topic (pp_rd, &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL); + CU_ASSERT_FATAL (*sub_tp > 0); + *wr = dds_create_writer (*pub, *pub_tp, qos, NULL); + CU_ASSERT_FATAL (*wr > 0); + dds_set_status_mask (*wr, DDS_PUBLICATION_MATCHED_STATUS); + *rd = dds_create_reader (*sub, *sub_tp, qos, NULL); + CU_ASSERT_FATAL (*rd > 0); + dds_set_status_mask (*rd, DDS_DATA_AVAILABLE_STATUS); + sync_writer_to_readers(pp_wr, *wr, 1); + dds_delete_qos (qos); +} + +void write_read_for(dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_duration_t dur, bool exp_write_fail, bool exp_read_fail) +{ + SecurityCoreTests_Type1 sample = { 1, 1 }; + SecurityCoreTests_Type1 rd_sample; + void * samples[] = { &rd_sample }; + dds_sample_info_t info[1]; + dds_return_t ret; + dds_time_t tend = dds_time () + dur; + bool write_fail = false, read_fail = false; + + do + { + if (dds_write (wr, &sample) != DDS_RETCODE_OK) + write_fail = true; + + while (!write_fail) + { + if ((ret = dds_take (rd, samples, info, 1, 1)) > 0) + { + CU_ASSERT_EQUAL_FATAL (ret, 1); + break; + } + if (ret < 0 || !reader_wait_for_data (pp_rd, rd, DDS_MSECS (100))) + { + read_fail = true; + break; + } + } + dds_sleepfor (DDS_MSECS (1)); + } + while (dds_time() < tend && !write_fail && !read_fail); + CU_ASSERT_EQUAL (write_fail, exp_write_fail); + CU_ASSERT_EQUAL (read_fail, exp_read_fail); +} diff --git a/src/security/core/tests/common/handshake_test_utils.h b/src/security/core/tests/common/test_utils.h similarity index 65% rename from src/security/core/tests/common/handshake_test_utils.h rename to src/security/core/tests/common/test_utils.h index 0ae3a59..a1c30b4 100644 --- a/src/security/core/tests/common/handshake_test_utils.h +++ b/src/security/core/tests/common/test_utils.h @@ -9,8 +9,8 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#ifndef SECURITY_CORE_HANDSHAKE_TEST_UTILS_H_ -#define SECURITY_CORE_HANDSHAKE_TEST_UTILS_H_ +#ifndef SECURITY_CORE_TEST_UTILS_H_ +#define SECURITY_CORE_TEST_UTILS_H_ #include "dds/dds.h" #include "dds/ddsrt/sync.h" @@ -20,7 +20,6 @@ #define MAX_LOCAL_IDENTITIES 8 #define MAX_REMOTE_IDENTITIES 8 #define MAX_HANDSHAKES 32 -#define TIMEOUT DDS_SECS(2) union guid { DDS_Security_GUID_t g; @@ -54,5 +53,13 @@ struct Handshake void validate_handshake(dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg, struct Handshake *hs_list[], int *nhs); void validate_handshake_nofail (dds_domainid_t domain_id); void handshake_list_fini(struct Handshake *hs_list, int nhs); +char *create_topic_name(const char *prefix, uint32_t nr, char *name, size_t size); +void sync_writer_to_readers(dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_count); +bool reader_wait_for_data(dds_entity_t pp, dds_entity_t rd, dds_duration_t dur); +void rd_wr_init( + dds_entity_t pp_wr, dds_entity_t *pub, dds_entity_t *pub_tp, dds_entity_t *wr, + dds_entity_t pp_rd, dds_entity_t *sub, dds_entity_t *sub_tp, dds_entity_t *rd, + const char *topic_name); +void write_read_for(dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_duration_t dur, bool exp_write_fail, bool exp_read_fail); -#endif /* SECURITY_CORE_HANDSHAKE_TEST_UTILS_H_ */ +#endif /* SECURITY_CORE_TEST_UTILS_H_ */ diff --git a/src/security/core/tests/handshake.c b/src/security/core/tests/handshake.c index 62ca589..66a77f9 100644 --- a/src/security/core/tests/handshake.c +++ b/src/security/core/tests/handshake.c @@ -30,7 +30,7 @@ #include "common/config_env.h" #include "common/authentication_wrapper.h" #include "common/plugin_wrapper_msg_q.h" -#include "common/handshake_test_utils.h" +#include "common/test_utils.h" #include "common/test_identity.h" static const char *config = From e3056402fc01f7415a94f6ef87cc4f219548b51f Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Mon, 30 Mar 2020 09:32:21 +0200 Subject: [PATCH 161/238] Implement on_revoke_identity_cb Impement the revoke identity callback in ddsi that is called when the identity certificate of a participant expires. In case the identity handle that expires is from a local participant, all proxy pp connections will be dropped for this participant. In case the identity that expires is from a remote participant, the corresponding proxy participant is deleted. Signed-off-by: Dennis Potman --- src/core/ddsi/src/ddsi_security_omg.c | 51 +++++++++++++++++++++--- src/security/core/tests/authentication.c | 27 +++++++------ 2 files changed, 60 insertions(+), 18 deletions(-) diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 7766fcd..3cf463e 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -817,7 +817,7 @@ static DDS_Security_boolean on_revoke_permissions_cb(const dds_security_access_c struct entidx_enum_proxy_participant eproxypp; struct participant *pp; struct proxy_participant *proxypp; - bool local_perm = false; + bool local = false; thread_state_awake (lookup_thread_state (), gv); /* Find participants using this permissions handle */ @@ -830,7 +830,7 @@ static DDS_Security_boolean on_revoke_permissions_cb(const dds_security_access_c { uint32_t i = 0; ddsrt_avl_citer_t it; - local_perm = true; + local = true; for (struct pp_proxypp_match *ppm = ddsrt_avl_citer_first (&pp_proxypp_treedef, &pp->sec_attr->proxy_participants, &it); ppm; ppm = ddsrt_avl_citer_next (&it), i++) pp_proxypp_unrelate_locked (sc, pp, &ppm->proxypp_guid); } @@ -839,7 +839,7 @@ static DDS_Security_boolean on_revoke_permissions_cb(const dds_security_access_c entidx_enum_participant_fini (&epp); /* Find proxy participants using this permissions handle */ - if (!local_perm) + if (!local) { entidx_enum_proxy_participant_init (&eproxypp, gv->entity_index); while ((proxypp = entidx_enum_proxy_participant_next (&eproxypp)) != NULL) @@ -868,8 +868,49 @@ static DDS_Security_boolean on_revoke_permissions_cb(const dds_security_access_c static DDS_Security_boolean on_revoke_identity_cb(const dds_security_authentication *plugin, const DDS_Security_IdentityHandle handle) { - (void)plugin; - (void)handle; + struct ddsi_domaingv *gv = plugin->gv; + struct entidx_enum_participant epp; + struct entidx_enum_proxy_participant eproxypp; + struct participant *pp; + struct proxy_participant *proxypp; + bool local = false; + thread_state_awake (lookup_thread_state (), gv); + + /* Find participants using this identity handle */ + entidx_enum_participant_init (&epp, gv->entity_index); + while ((pp = entidx_enum_participant_next (&epp)) != NULL) + { + struct dds_security_context *sc = q_omg_security_get_secure_context(pp); + ddsrt_mutex_lock (&pp->sec_attr->lock); + if (pp->sec_attr->local_identity_handle == handle) + { + uint32_t i = 0; + ddsrt_avl_citer_t it; + local = true; + for (struct pp_proxypp_match *ppm = ddsrt_avl_citer_first (&pp_proxypp_treedef, &pp->sec_attr->proxy_participants, &it); ppm; ppm = ddsrt_avl_citer_next (&it), i++) + pp_proxypp_unrelate_locked (sc, pp, &ppm->proxypp_guid); + } + ddsrt_mutex_unlock (&pp->sec_attr->lock); + } + entidx_enum_participant_fini (&epp); + + /* Find proxy participants using this permissions handle */ + if (!local) + { + entidx_enum_proxy_participant_init (&eproxypp, gv->entity_index); + while ((proxypp = entidx_enum_proxy_participant_next (&eproxypp)) != NULL) + { + bool del_pp; + ddsrt_mutex_lock (&proxypp->sec_attr->lock); + del_pp = proxypp->sec_attr->remote_identity_handle == handle; + ddsrt_mutex_unlock (&proxypp->sec_attr->lock); + if (del_pp) + delete_proxy_participant_by_guid (gv, &proxypp->e.guid, ddsrt_time_wallclock (), false); + } + entidx_enum_proxy_participant_fini (&eproxypp); + } + + thread_state_asleep (lookup_thread_state ()); return true; } diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index 1e53a8f..ab12143 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -262,7 +262,8 @@ CU_Theory((const char * ca_dir, bool exp_fail), ddssec_authentication, trusted_c authentication_fini (!exp_fail, !exp_fail); } -#define M(n) ((n)*60) +#define S(n) (n) +#define M(n) (S(n)*60) #define H(n) (M(n)*60) #define D(n) (H(n)*24) CU_TheoryDataPoints(ddssec_authentication, expired_cert) = { @@ -274,18 +275,18 @@ CU_TheoryDataPoints(ddssec_authentication, expired_cert) = { /* | | | | */"ca and id1 1min valid", /* | | | | | */"id1 and id2 1s valid, delay 1100ms", /* | | | | | | */"id1 valid after 1s, delay 1100ms", - /* | | | | | | | *//*"ca and id1 expire during session"*/), - CU_DataPoints(int32_t, 0, -M(1), 0, 0, 0, 0, 0, /*0*/ ), /* CA1 not before */ - CU_DataPoints(int32_t, D(1), 0, D(1), D(1), M(1), D(1), D(1), /*2*/ ), /* CA1 not after (offset from local time) */ - CU_DataPoints(int32_t, 0, 0, -D(1), 0, 0, 0, 1, /*0*/ ), /* ID1 not before (offset from local time) */ - CU_DataPoints(int32_t, D(1), D(1), 0, D(1), M(1), 1, D(1), /*2*/ ), /* ID1 not after (offset from local time) */ - CU_DataPoints(bool, false, true, true, false, false, true, false, /*false*/ ), /* expect validate local ID1 fail */ - CU_DataPoints(int32_t, 0, 0, 0, -D(1), 0, 0, 0, /*0*/ ), /* ID2 not before (offset from local time) */ - CU_DataPoints(int32_t, D(1), D(1), D(1), 0, D(1), 1, D(1), /*D(1)*/ ), /* ID2 not after (offset from local time) */ - CU_DataPoints(bool, false, true, false, true, false, true, false, /*false*/ ), /* expect validate local ID2 fail */ - CU_DataPoints(uint32_t, 0, 0, 0, 0, 0, 1100, 1100, /*0*/ ), /* delay (ms) after generating certificate */ - CU_DataPoints(uint32_t, 1, 0, 0, 0, 1, 0, 1, /*3500*/ ), /* write/read data during x ms */ - CU_DataPoints(bool, false, false, false, false, false, false, false, /*true*/ ), /* expect read data failure */ + /* | | | | | | | */"id1 expire during session"), + CU_DataPoints(int32_t, 0, -M(1), 0, 0, 0, 0, 0, 0 ), /* CA1 not before */ + CU_DataPoints(int32_t, D(1), 0, D(1), D(1), M(1), D(1), D(1), D(1) ), /* CA1 not after (offset from local time) */ + CU_DataPoints(int32_t, 0, 0, -D(1), 0, 0, 0, S(1), 0 ), /* ID1 not before (offset from local time) */ + CU_DataPoints(int32_t, D(1), D(1), 0, D(1), M(1), S(1), D(1), S(2) ), /* ID1 not after (offset from local time) */ + CU_DataPoints(bool, false, true, true, false, false, true, false, false ), /* expect validate local ID1 fail */ + CU_DataPoints(int32_t, 0, 0, 0, -D(1), 0, 0, 0, 0 ), /* ID2 not before (offset from local time) */ + CU_DataPoints(int32_t, D(1), D(1), D(1), 0, D(1), S(1), D(1), D(1) ), /* ID2 not after (offset from local time) */ + CU_DataPoints(bool, false, true, false, true, false, true, false, false ), /* expect validate local ID2 fail */ + CU_DataPoints(uint32_t, 0, 0, 0, 0, 0, 1100, 1100, 0 ), /* delay (ms) after generating certificate */ + CU_DataPoints(uint32_t, 1, 0, 0, 0, 1, 0, 1, 3500 ), /* write/read data during x ms */ + CU_DataPoints(bool, false, false, false, false, false, false, false, true ), /* expect read data failure */ }; CU_Theory( (const char * test_descr, int32_t ca_not_before, int32_t ca_not_after, From 5e721c99e5894bae869f726b0fc763e3cacefb35 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Mon, 30 Mar 2020 14:23:18 +0200 Subject: [PATCH 162/238] Change test timing and time-outs in access-control and authentication expiry tests and add timestamps to test logging to get more stable test results on Travis and enable analysing timeing issues. Signed-off-by: Dennis Potman --- src/security/core/tests/access_control.c | 96 +++++++------- src/security/core/tests/authentication.c | 13 +- src/security/core/tests/common/test_utils.c | 140 +++++++++++--------- src/security/core/tests/common/test_utils.h | 1 + 4 files changed, 140 insertions(+), 110 deletions(-) diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index 508828c..981a196 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -148,7 +148,7 @@ CU_TheoryDataPoints(ddssec_access_control, config_parameters_file) = { CU_Theory((const char * test_descr, const char * gov, const char * perm, const char * ca, bool incl_empty_els, bool exp_fail), ddssec_access_control, config_parameters_file) { - printf("running test config_parameters_file: %s\n", test_descr); + print_test_msg ("running test config_parameters_file: %s\n", test_descr); access_control_init ( (const char *[]) { TEST_IDENTITY1_CERTIFICATE, TEST_IDENTITY1_CERTIFICATE }, (const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY }, @@ -170,29 +170,28 @@ CU_TheoryDataPoints(ddssec_access_control, permissions_expiry) = { /* | */"valid -1 minute until now", /* | | */"1s valid, create pp after 1100ms", /* | | | */"node 2 permissions expired", - /* | | | | */"node 1 3s valid, write/read for 1s delayed 3s", - /* | | | | | */"node 2 3s valid, write/read for 1s delayed 3s"), + /* | | | | */"node 1 3s valid, write/read for 10s", + /* | | | | | */"node 2 3s valid, write/read for 10s"), CU_DataPoints(int32_t, 0, -M(1), 0, 0, 0, 0), /* node 1 permissions not before (offset from local time) */ - CU_DataPoints(int32_t, M(1), 0, S(1), D(1), S(3), D(1)), /* node 1 permissions not after (offset from local time) */ + CU_DataPoints(int32_t, M(1), 0, S(1), D(1), S(4), D(1)), /* node 1 permissions not after (offset from local time) */ CU_DataPoints(int32_t, 0, -M(1), 0, -D(1), 0, 0), /* node 2 permissions not before (offset from local time) */ - CU_DataPoints(int32_t, M(1), 0, S(1), 0, D(1), S(3)), /* node 2 permissions not after (offset from local time) */ + CU_DataPoints(int32_t, M(1), 0, S(1), 0, D(1), S(4)), /* node 2 permissions not after (offset from local time) */ CU_DataPoints(uint32_t, 0, 0, 1100, 0, 0, 0), /* delay (ms) after generating permissions */ CU_DataPoints(bool, false, true, true, false, false, false), /* expect pp 1 create failure */ CU_DataPoints(bool, false, true, true, true, false, false), /* expect pp 2 create failure */ - CU_DataPoints(uint32_t, 0, 0, 0, 0, 3000, 3000), /* delay (ms) after creating readers/writers */ - CU_DataPoints(uint32_t, 1, 0, 0, 0, 1000, 1000), /* write/read data during x ms */ + CU_DataPoints(uint32_t, 1, 0, 0, 0, 10000, 10000), /* write/read data during x ms */ CU_DataPoints(bool, false, false, false, false, true, true), /* expect read data failure */ }; CU_Theory( (const char * test_descr, int32_t perm1_not_before, int32_t perm1_not_after, int32_t perm2_not_before, int32_t perm2_not_after, - uint32_t delay_perm, bool exp_pp1_fail, bool exp_pp2_fail, uint32_t delay_wr_rd, uint32_t write_read_dur, bool exp_read_fail), + uint32_t delay_perm, bool exp_pp1_fail, bool exp_pp2_fail, uint32_t write_read_dur, bool exp_read_fail), ddssec_access_control, permissions_expiry, .timeout=20) { - printf("running test permissions_expiry: %s\n", test_descr); + print_test_msg ("running test permissions_expiry: %s\n", test_descr); char topic_name[100]; - create_topic_name("ddssec_access_control_", g_topic_nr++, topic_name, sizeof (topic_name)); + create_topic_name ("ddssec_access_control_", g_topic_nr++, topic_name, sizeof (topic_name)); /* create ca and id1/id2 certs that will not expire during this test */ char *ca, *id1, *id2, *id1_subj, *id2_subj; @@ -202,7 +201,7 @@ CU_Theory( /* localtime will be converted to gmtime in get_permissions_grant */ dds_time_t now = dds_time (); - char * perm_topic = get_permissions_topic(topic_name); + char * perm_topic = get_permissions_topic (topic_name); char * grants[] = { get_permissions_grant ("id1", id1_subj, now + DDS_SECS(perm1_not_before), now + DDS_SECS(perm1_not_after), perm_topic, perm_topic, NULL), get_permissions_grant ("id2", id2_subj, now + DDS_SECS(perm2_not_before), now + DDS_SECS(perm2_not_after), perm_topic, perm_topic, NULL) }; @@ -222,7 +221,6 @@ CU_Theory( { dds_entity_t wr = 0, rd = 0; rd_wr_init (g_participant[0], &g_pubsub[0], &g_topic[0], &wr, g_participant[1], &g_pubsub[1], &g_topic[1], &rd, topic_name); - dds_sleepfor (DDS_MSECS (delay_wr_rd)); write_read_for (wr, g_participant[1], rd, DDS_MSECS (write_read_dur), false, exp_read_fail); } @@ -243,12 +241,14 @@ CU_Theory( #undef M -#define N_NODES 4 +#define N_RD 1 // N_RD > 1 not yet implemented +#define N_WR 3 +#define N_NODES (N_RD + N_WR) #define PERM_EXP_BASE 3 CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) { char topic_name[100]; - create_topic_name("ddssec_access_control_", g_topic_nr++, topic_name, sizeof (topic_name)); + create_topic_name ("ddssec_access_control_", g_topic_nr++, topic_name, sizeof (topic_name)); dds_time_t t_perm = dds_time (); char *ca = generate_ca ("ca1", TEST_IDENTITY_CA1_PRIVATE_KEY, 0, 3600); @@ -266,7 +266,7 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) ca_list[i] = ca; id[i] = generate_identity (ca_list[i], TEST_IDENTITY_CA1_PRIVATE_KEY, id_name, pk[i], 0, 3600, &id_subj[i]); exp_fail[i] = false; - dds_duration_t v = DDS_SECS(i == 0 ? 3600 : PERM_EXP_BASE + i); /* 1st node is reader and should not expire */ + dds_duration_t v = DDS_SECS(i < N_RD ? 3600 : PERM_EXP_BASE + 2 * i); /* 1st node is reader and should not expire */ grants[i] = get_permissions_grant (id_name, id_subj[i], t_perm, t_perm + v, perm_topic, perm_topic, NULL); ddsrt_free (id_name); } @@ -274,34 +274,39 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) char * perm_config = get_permissions_config (grants, N_NODES, true); access_control_init ( id, pk, ca_list, exp_fail, N_NODES, - true, PF_F COMMON_ETC_PATH("default_governance.p7s"), + true, PF_F COMMON_ETC_PATH ("default_governance.p7s"), true, perm_config, - true, PF_F COMMON_ETC_PATH("default_permissions_ca.pem")); + true, PF_F COMMON_ETC_PATH ("default_permissions_ca.pem")); dds_qos_t * qos = dds_create_qos (); CU_ASSERT_FATAL (qos != NULL); dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, -1); dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL); dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); - dds_entity_t sub_tp = dds_create_topic (g_participant[0], &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL); - CU_ASSERT_FATAL (sub_tp > 0); - dds_entity_t sub = dds_create_subscriber (g_participant[0], NULL, NULL); - CU_ASSERT_FATAL (sub > 0); - dds_entity_t rd = dds_create_reader (sub, sub_tp, qos, NULL); - CU_ASSERT_FATAL (rd > 0); - dds_set_status_mask (rd, DDS_DATA_AVAILABLE_STATUS); - dds_entity_t wr[N_NODES - 1]; - for (int i = 1; i < N_NODES; i++) + dds_entity_t rd[N_RD]; + for (int i = 0; i < N_RD; i++) { - dds_entity_t pub = dds_create_publisher (g_participant[i], NULL, NULL); + dds_entity_t sub = dds_create_subscriber (g_participant[i], NULL, NULL); + CU_ASSERT_FATAL (sub > 0); + dds_entity_t sub_tp = dds_create_topic (g_participant[i], &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL); + CU_ASSERT_FATAL (sub_tp > 0); + rd[i] = dds_create_reader (sub, sub_tp, qos, NULL); + CU_ASSERT_FATAL (rd[i] > 0); + dds_set_status_mask (rd[i], DDS_DATA_AVAILABLE_STATUS); + } + + dds_entity_t wr[N_WR]; + for (int i = 0; i < N_WR; i++) + { + dds_entity_t pub = dds_create_publisher (g_participant[i + N_RD], NULL, NULL); CU_ASSERT_FATAL (pub > 0); - dds_entity_t pub_tp = dds_create_topic (g_participant[i], &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL); + dds_entity_t pub_tp = dds_create_topic (g_participant[i + N_RD], &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL); CU_ASSERT_FATAL (pub_tp > 0); - wr[i - 1] = dds_create_writer (pub, pub_tp, qos, NULL); - CU_ASSERT_FATAL (wr[i - 1] > 0); - dds_set_status_mask (wr[i - 1], DDS_PUBLICATION_MATCHED_STATUS); - sync_writer_to_readers(g_participant[i], wr[i - 1], 1); + wr[i] = dds_create_writer (pub, pub_tp, qos, NULL); + CU_ASSERT_FATAL (wr[i] > 0); + dds_set_status_mask (wr[i], DDS_PUBLICATION_MATCHED_STATUS); + sync_writer_to_readers (g_participant[i + N_RD], wr[i], N_RD); } dds_delete_qos (qos); @@ -311,47 +316,48 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) dds_sample_info_t info[1]; dds_return_t ret; - for (int i = 1; i < N_NODES; i++) + for (int i = 0; i < N_WR; i++) { // sleep until 1s before next writer pp permission expires - dds_duration_t delay = DDS_SECS (PERM_EXP_BASE + i - 1) - (dds_time () - t_perm); + dds_duration_t delay = DDS_SECS (PERM_EXP_BASE + 2 * i) - (dds_time () - t_perm); if (delay > 0) dds_sleepfor (delay); - printf ("run %d\n", i); + print_test_msg ("run %d\n", i); - for (int w = 1; w < N_NODES; w++) + for (int w = 0; w < N_WR; w++) { sample.id = w; - ret = dds_write (wr[w - 1], &sample); + ret = dds_write (wr[w], &sample); CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); - printf ("write %d\n", w); + print_test_msg ("write %d\n", w); } // Expect reader to receive data from writers with non-expired permissions int n_samples = 0, n_invalid = 0, n_wait = 0; - while (n_samples + n_invalid < N_NODES - 1 && n_wait < 5) + while (n_samples + n_invalid < N_WR && n_wait < 5) { - ret = dds_take (rd, samples, info, 1, 1); + ret = dds_take (rd[0], samples, info, 1, 1); CU_ASSERT_FATAL (ret >= 0); if (ret == 0) { - reader_wait_for_data (g_participant[0], rd, DDS_MSECS (100)); + reader_wait_for_data (g_participant[0], rd[0], DDS_MSECS (200)); + print_test_msg ("wait for data\n"); n_wait++; } else if (info[0].instance_state == DDS_IST_ALIVE) { - printf ("recv sample %d\n", rd_sample.id); + print_test_msg ("recv sample %d\n", rd_sample.id); n_samples++; } else { - printf ("recv inv sample\n"); + print_test_msg ("recv inv sample\n"); n_invalid++; } } - CU_ASSERT_EQUAL (n_samples, N_NODES - i); - CU_ASSERT (n_invalid < i); + CU_ASSERT_EQUAL (n_samples, N_WR - i); + CU_ASSERT (n_invalid <= i); } access_control_fini (N_NODES); diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index ab12143..7a9a21a 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -228,7 +228,7 @@ CU_Theory((const char * test_descr, const char * id2, const char *key2, const ch { struct Handshake *hs_list; int nhs; - printf("running test id_ca_certs: %s\n", test_descr); + print_test_msg ("running test id_ca_certs: %s\n", test_descr); authentication_init (ID1, ID1K, CA1, id2, key2, ca2, NULL, NULL, exp_fail_pp1, exp_fail_pp2); // Domain 1 @@ -252,7 +252,7 @@ CU_TheoryDataPoints(ddssec_authentication, trusted_ca_dir) = { }; CU_Theory((const char * ca_dir, bool exp_fail), ddssec_authentication, trusted_ca_dir) { - printf("Testing custom CA dir: %s\n", ca_dir); + print_test_msg ("Testing custom CA dir: %s\n", ca_dir); authentication_init (ID1, ID1K, CA1, ID1, ID1K, CA1, ca_dir, NULL, exp_fail, exp_fail); if (!exp_fail) { @@ -275,17 +275,17 @@ CU_TheoryDataPoints(ddssec_authentication, expired_cert) = { /* | | | | */"ca and id1 1min valid", /* | | | | | */"id1 and id2 1s valid, delay 1100ms", /* | | | | | | */"id1 valid after 1s, delay 1100ms", - /* | | | | | | | */"id1 expire during session"), + /* | | | | | | | */"id1 expires during session"), CU_DataPoints(int32_t, 0, -M(1), 0, 0, 0, 0, 0, 0 ), /* CA1 not before */ CU_DataPoints(int32_t, D(1), 0, D(1), D(1), M(1), D(1), D(1), D(1) ), /* CA1 not after (offset from local time) */ CU_DataPoints(int32_t, 0, 0, -D(1), 0, 0, 0, S(1), 0 ), /* ID1 not before (offset from local time) */ - CU_DataPoints(int32_t, D(1), D(1), 0, D(1), M(1), S(1), D(1), S(2) ), /* ID1 not after (offset from local time) */ + CU_DataPoints(int32_t, D(1), D(1), 0, D(1), M(1), S(1), D(1), S(4) ), /* ID1 not after (offset from local time) */ CU_DataPoints(bool, false, true, true, false, false, true, false, false ), /* expect validate local ID1 fail */ CU_DataPoints(int32_t, 0, 0, 0, -D(1), 0, 0, 0, 0 ), /* ID2 not before (offset from local time) */ CU_DataPoints(int32_t, D(1), D(1), D(1), 0, D(1), S(1), D(1), D(1) ), /* ID2 not after (offset from local time) */ CU_DataPoints(bool, false, true, false, true, false, true, false, false ), /* expect validate local ID2 fail */ CU_DataPoints(uint32_t, 0, 0, 0, 0, 0, 1100, 1100, 0 ), /* delay (ms) after generating certificate */ - CU_DataPoints(uint32_t, 1, 0, 0, 0, 1, 0, 1, 3500 ), /* write/read data during x ms */ + CU_DataPoints(uint32_t, 1, 0, 0, 0, 1, 0, 1, 10000 ), /* write/read data during x ms */ CU_DataPoints(bool, false, false, false, false, false, false, false, true ), /* expect read data failure */ }; CU_Theory( @@ -295,11 +295,12 @@ CU_Theory( uint32_t delay, uint32_t write_read_dur, bool exp_read_fail), ddssec_authentication, expired_cert, .timeout=30) { - printf("running test expired_cert: %s\n", test_descr); + print_test_msg ("running test expired_cert: %s\n", test_descr); char topic_name[100]; create_topic_name("ddssec_authentication_", g_topic_nr++, topic_name, sizeof (topic_name)); + print_test_msg ("generate ids (id1: %d-%d, id2: %d-%d):\n", id1_not_before, id1_not_after, id2_not_before, id2_not_after); char *ca, *id1, *id2, *id1_subj, *id2_subj; ca = generate_ca ("ca1", CA1K, ca_not_before, ca_not_after); id1 = generate_identity (ca, CA1K, "id1", ID1K, id1_not_before, id1_not_after, &id1_subj); diff --git a/src/security/core/tests/common/test_utils.c b/src/security/core/tests/common/test_utils.c index 476490c..bf8c300 100644 --- a/src/security/core/tests/common/test_utils.c +++ b/src/security/core/tests/common/test_utils.c @@ -34,7 +34,7 @@ int numRemote = 0; struct Handshake handshakeList[MAX_HANDSHAKES]; int numHandshake = 0; -static char * get_validation_result_str(DDS_Security_ValidationResult_t result) +static char * get_validation_result_str (DDS_Security_ValidationResult_t result) { switch (result) { @@ -49,7 +49,7 @@ static char * get_validation_result_str(DDS_Security_ValidationResult_t result) return ""; } -static char * get_node_type_str(enum hs_node_type node_type) +static char * get_node_type_str (enum hs_node_type node_type) { switch (node_type) { @@ -61,17 +61,27 @@ static char * get_node_type_str(enum hs_node_type node_type) return ""; } -static void add_local_identity(DDS_Security_IdentityHandle handle, DDS_Security_GUID_t *guid) +void print_test_msg (const char *msg, ...) { - printf("add local identity %"PRId64"\n", handle); + va_list args; + dds_time_t t = dds_time (); + printf ("%d.%06d ", (int32_t) (t / DDS_NSECS_IN_SEC), (int32_t) (t % DDS_NSECS_IN_SEC) / 1000); + va_start (args, msg); + vprintf (msg, args); + va_end (args); +} + +static void add_local_identity (DDS_Security_IdentityHandle handle, DDS_Security_GUID_t *guid) +{ + print_test_msg ("add local identity %"PRId64"\n", handle); localIdentityList[numLocal].handle = handle; - memcpy(&localIdentityList[numLocal].guid, guid, sizeof(DDS_Security_GUID_t)); + memcpy (&localIdentityList[numLocal].guid, guid, sizeof(DDS_Security_GUID_t)); numLocal++; } -static int find_local_identity(DDS_Security_IdentityHandle handle) +static int find_local_identity (DDS_Security_IdentityHandle handle) { - for (int i = 0; i < (int)numLocal; i++) + for (int i = 0; i < (int) numLocal; i++) { if (localIdentityList[i].handle == handle) return i; @@ -79,7 +89,7 @@ static int find_local_identity(DDS_Security_IdentityHandle handle) return -1; } -static int find_remote_identity(DDS_Security_IdentityHandle handle) +static int find_remote_identity (DDS_Security_IdentityHandle handle) { for (int i = 0; i < numRemote; i++) { @@ -89,13 +99,13 @@ static int find_remote_identity(DDS_Security_IdentityHandle handle) return -1; } -static void add_remote_identity(DDS_Security_IdentityHandle handle, DDS_Security_GUID_t *guid) +static void add_remote_identity (DDS_Security_IdentityHandle handle, DDS_Security_GUID_t *guid) { - if (find_remote_identity(handle) < 0) + if (find_remote_identity (handle) < 0) { - printf("add remote identity %"PRId64"\n", handle); + print_test_msg ("add remote identity %"PRId64"\n", handle); remoteIdentityList[numRemote].handle = handle; - memcpy(&remoteIdentityList[numRemote].guid, guid, sizeof(DDS_Security_GUID_t)); + memcpy (&remoteIdentityList[numRemote].guid, guid, sizeof(DDS_Security_GUID_t)); numRemote++; } } @@ -107,21 +117,21 @@ static void clear_stores(void) numHandshake = 0; } -static struct Handshake *add_handshake(enum hs_node_type node_type, DDS_Security_IdentityHandle lHandle, DDS_Security_IdentityHandle rHandle) +static struct Handshake *add_handshake (enum hs_node_type node_type, DDS_Security_IdentityHandle lHandle, DDS_Security_IdentityHandle rHandle) { - printf("add handshake %"PRId64"-%"PRId64"\n", lHandle, rHandle); + print_test_msg ("add handshake %"PRId64"-%"PRId64"\n", lHandle, rHandle); handshakeList[numHandshake].handle = -1; handshakeList[numHandshake].node_type = node_type; handshakeList[numHandshake].handshakeResult = DDS_SECURITY_VALIDATION_FAILED; - handshakeList[numHandshake].lidx = find_local_identity(lHandle); - handshakeList[numHandshake].ridx = find_remote_identity(rHandle); + handshakeList[numHandshake].lidx = find_local_identity (lHandle); + handshakeList[numHandshake].ridx = find_remote_identity (rHandle); handshakeList[numHandshake].finalResult = DDS_SECURITY_VALIDATION_FAILED; handshakeList[numHandshake].err_msg = NULL; numHandshake++; return &handshakeList[numHandshake - 1]; } -static int find_handshake(DDS_Security_HandshakeHandle handle) +static int find_handshake (DDS_Security_HandshakeHandle handle) { for (int i = 0; i < numHandshake; i++) { @@ -131,123 +141,123 @@ static int find_handshake(DDS_Security_HandshakeHandle handle) return -1; } -static void handle_process_message(dds_domainid_t domain_id, DDS_Security_IdentityHandle handshake) +static void handle_process_message (dds_domainid_t domain_id, DDS_Security_IdentityHandle handshake) { struct message *msg; - if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_PROCESS_HANDSHAKE, 0, 0, handshake, HS_TIMEOUT))) + if ((msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_PROCESS_HANDSHAKE, 0, 0, handshake, HS_TIMEOUT))) { int idx; - if ((idx = find_handshake(msg->hsHandle)) >= 0) + if ((idx = find_handshake (msg->hsHandle)) >= 0) { - printf("set handshake %"PRId64" final result to '%s' (errmsg: %s)\n", msg->hsHandle, get_validation_result_str(msg->result), msg->err_msg); + print_test_msg ("set handshake %"PRId64" final result to '%s' (errmsg: %s)\n", msg->hsHandle, get_validation_result_str (msg->result), msg->err_msg); handshakeList[idx].finalResult = msg->result; handshakeList[idx].err_msg = ddsrt_strdup (msg->err_msg); } - test_authentication_plugin_release_msg(msg); + test_authentication_plugin_release_msg (msg); } } -static void handle_begin_handshake_request(dds_domainid_t domain_id, struct Handshake *hs, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid) +static void handle_begin_handshake_request (dds_domainid_t domain_id, struct Handshake *hs, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid) { struct message *msg; - printf("handle begin handshake request %"PRId64"<->%"PRId64"\n", lid, rid); - if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REQUEST, lid, rid, 0, HS_TIMEOUT))) + print_test_msg ("handle begin handshake request %"PRId64"<->%"PRId64"\n", lid, rid); + if ((msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REQUEST, lid, rid, 0, HS_TIMEOUT))) { hs->handle = msg->hsHandle; hs->handshakeResult = msg->result; if (msg->result != DDS_SECURITY_VALIDATION_FAILED) - handle_process_message(domain_id, msg->hsHandle); + handle_process_message (domain_id, msg->hsHandle); else hs->err_msg = ddsrt_strdup (msg->err_msg); - test_authentication_plugin_release_msg(msg); + test_authentication_plugin_release_msg (msg); } } -static void handle_begin_handshake_reply(dds_domainid_t domain_id, struct Handshake *hs, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid) +static void handle_begin_handshake_reply (dds_domainid_t domain_id, struct Handshake *hs, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid) { struct message *msg; - printf("handle begin handshake reply %"PRId64"<->%"PRId64"\n", lid, rid); - if ((msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REPLY, lid, rid, 0, HS_TIMEOUT))) + print_test_msg ("handle begin handshake reply %"PRId64"<->%"PRId64"\n", lid, rid); + if ((msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REPLY, lid, rid, 0, HS_TIMEOUT))) { hs->handle = msg->hsHandle; hs->handshakeResult = msg->result; if (msg->result != DDS_SECURITY_VALIDATION_FAILED) - handle_process_message(domain_id, msg->hsHandle); + handle_process_message (domain_id, msg->hsHandle); else hs->err_msg = ddsrt_strdup (msg->err_msg); - test_authentication_plugin_release_msg(msg); + test_authentication_plugin_release_msg (msg); } } -static void handle_validate_remote_identity(dds_domainid_t domain_id, DDS_Security_IdentityHandle lid, int count) +static void handle_validate_remote_identity (dds_domainid_t domain_id, DDS_Security_IdentityHandle lid, int count) { struct message *msg; - while (count-- > 0 && (msg = test_authentication_plugin_take_msg(domain_id, MESSAGE_KIND_VALIDATE_REMOTE_IDENTITY, lid, 0, 0, HS_TIMEOUT))) + while (count-- > 0 && (msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_VALIDATE_REMOTE_IDENTITY, lid, 0, 0, HS_TIMEOUT))) { struct Handshake *hs; - add_remote_identity(msg->ridHandle, &msg->rguid); - hs = add_handshake(HSN_UNDEFINED, lid, msg->ridHandle); + add_remote_identity (msg->ridHandle, &msg->rguid); + hs = add_handshake (HSN_UNDEFINED, lid, msg->ridHandle); if (msg->result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_REQUEST) { hs->node_type = HSN_REQUESTER; - handle_begin_handshake_request(domain_id, hs, lid, msg->ridHandle); + handle_begin_handshake_request (domain_id, hs, lid, msg->ridHandle); } else if (msg->result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE) { hs->node_type = HSN_REPLIER; - handle_begin_handshake_reply(domain_id, hs, lid, msg->ridHandle); + handle_begin_handshake_reply (domain_id, hs, lid, msg->ridHandle); } else { - printf("validate remote failed\n"); + print_test_msg ("validate remote failed\n"); } - test_authentication_plugin_release_msg(msg); + test_authentication_plugin_release_msg (msg); } } -static void handle_validate_local_identity(dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg) +static void handle_validate_local_identity (dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg) { struct message *msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_VALIDATE_LOCAL_IDENTITY, 0, 0, 0, HS_TIMEOUT); CU_ASSERT_FATAL (msg != NULL); CU_ASSERT_FATAL ((msg->result == DDS_SECURITY_VALIDATION_OK) != exp_localid_fail); if (exp_localid_fail && exp_localid_msg) { - printf("validate_local_identity failed as expected (msg: %s)\n", msg->err_msg); - CU_ASSERT_FATAL (msg->err_msg && strstr(msg->err_msg, exp_localid_msg) != NULL); + print_test_msg ("validate_local_identity failed as expected (msg: %s)\n", msg->err_msg); + CU_ASSERT_FATAL (msg->err_msg && strstr (msg->err_msg, exp_localid_msg) != NULL); } else add_local_identity (msg->lidHandle, &msg->lguid); test_authentication_plugin_release_msg (msg); } -void validate_handshake(dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg, struct Handshake *hs_list[], int *nhs) +void validate_handshake (dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg, struct Handshake *hs_list[], int *nhs) { - clear_stores(); + clear_stores (); if (nhs) *nhs = 0; if (hs_list) *hs_list = NULL; - handle_validate_local_identity(domain_id, exp_localid_fail, exp_localid_msg); + handle_validate_local_identity (domain_id, exp_localid_fail, exp_localid_msg); if (!exp_localid_fail) { handle_validate_remote_identity (domain_id, localIdentityList[0].handle, 1); for (int n = 0; n < numHandshake; n++) { struct Handshake *hs = &handshakeList[n]; - printf("Result: hs %"PRId64", node type %s, final result %s\n", hs->handle, get_node_type_str(hs->node_type), get_validation_result_str(hs->finalResult)); + print_test_msg ("Result: hs %"PRId64", node type %s, final result %s\n", hs->handle, get_node_type_str (hs->node_type), get_validation_result_str (hs->finalResult)); if (hs->err_msg && strlen (hs->err_msg)) - printf("- err_msg: %s\n", hs->err_msg); + print_test_msg ("- err_msg: %s\n", hs->err_msg); } if (nhs) *nhs = numHandshake; if (hs_list) *hs_list = handshakeList; else - handshake_list_fini(handshakeList, numHandshake); + handshake_list_fini (handshakeList, numHandshake); } - printf ("finished validate handshake for domain %d\n\n", domain_id); + print_test_msg ("finished validate handshake for domain %d\n\n", domain_id); } void validate_handshake_nofail (dds_domainid_t domain_id) @@ -264,7 +274,7 @@ void validate_handshake_nofail (dds_domainid_t domain_id) handshake_list_fini (hs_list, nhs); } -void handshake_list_fini(struct Handshake *hs_list, int nhs) +void handshake_list_fini (struct Handshake *hs_list, int nhs) { for (int n = 0; n < nhs; n++) { @@ -273,7 +283,7 @@ void handshake_list_fini(struct Handshake *hs_list, int nhs) } } -void sync_writer_to_readers(dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_count) +void sync_writer_to_readers (dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_count) { dds_attach_t triggered; dds_entity_t ws = dds_create_waitset (pp_wr); @@ -296,7 +306,7 @@ void sync_writer_to_readers(dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_co CU_ASSERT_EQUAL_FATAL (pub_matched.total_count, exp_count); } -char *create_topic_name(const char *prefix, uint32_t nr, char *name, size_t size) +char *create_topic_name (const char *prefix, uint32_t nr, char *name, size_t size) { ddsrt_pid_t pid = ddsrt_getpid (); ddsrt_tid_t tid = ddsrt_gettid (); @@ -304,7 +314,7 @@ char *create_topic_name(const char *prefix, uint32_t nr, char *name, size_t size return name; } -bool reader_wait_for_data(dds_entity_t pp, dds_entity_t rd, dds_duration_t dur) +bool reader_wait_for_data (dds_entity_t pp, dds_entity_t rd, dds_duration_t dur) { dds_attach_t triggered; dds_entity_t ws = dds_create_waitset (pp); @@ -359,6 +369,7 @@ void write_read_for(dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_du do { + print_test_msg("write\n"); if (dds_write (wr, &sample) != DDS_RETCODE_OK) write_fail = true; @@ -366,18 +377,29 @@ void write_read_for(dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_du { if ((ret = dds_take (rd, samples, info, 1, 1)) > 0) { + print_test_msg ("take sample\n"); + if (info[0].instance_state != DDS_IST_ALIVE || !info[0].valid_data) + { + print_test_msg ("invalid sample instance_state=%d valid_data=%d\n", info[0].instance_state, info[0].valid_data); + read_fail = true; + } + else + CU_ASSERT_EQUAL_FATAL (rd_sample.value, 1); CU_ASSERT_EQUAL_FATAL (ret, 1); break; } - if (ret < 0 || !reader_wait_for_data (pp_rd, rd, DDS_MSECS (100))) + if (ret < 0 || !reader_wait_for_data (pp_rd, rd, DDS_MSECS (1000))) { + print_test_msg ("take no sample\n"); read_fail = true; break; } } - dds_sleepfor (DDS_MSECS (1)); + if (write_fail || read_fail) + break; + dds_sleepfor (DDS_MSECS (100)); } - while (dds_time() < tend && !write_fail && !read_fail); - CU_ASSERT_EQUAL (write_fail, exp_write_fail); - CU_ASSERT_EQUAL (read_fail, exp_read_fail); + while (dds_time() < tend); + CU_ASSERT_EQUAL_FATAL (write_fail, exp_write_fail); + CU_ASSERT_EQUAL_FATAL (read_fail, exp_read_fail); } diff --git a/src/security/core/tests/common/test_utils.h b/src/security/core/tests/common/test_utils.h index a1c30b4..b396f60 100644 --- a/src/security/core/tests/common/test_utils.h +++ b/src/security/core/tests/common/test_utils.h @@ -50,6 +50,7 @@ struct Handshake char * err_msg; }; +void print_test_msg (const char *msg, ...); void validate_handshake(dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg, struct Handshake *hs_list[], int *nhs); void validate_handshake_nofail (dds_domainid_t domain_id); void handshake_list_fini(struct Handshake *hs_list, int nhs); From bfb48e6e585dbee98072f9731a22997b8daf2ee9 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Wed, 1 Apr 2020 17:05:02 +0200 Subject: [PATCH 163/238] Address issues from review: replaced proxypp_pp_unrelate by deleting the (proxy)participant and added a code comment with the rationale for this approach Signed-off-by: Dennis Potman --- src/core/ddsi/src/ddsi_security_omg.c | 181 ++++++++++++++------------ 1 file changed, 96 insertions(+), 85 deletions(-) diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 3cf463e..be0d57e 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -810,111 +810,122 @@ static void deinit_plugin_suite_config (dds_security_plugin_suite_config *suite_ deinit_plugin_config (&suite_config->cryptography); } +typedef bool (*expired_pp_check_fn_t)(const struct participant * pp, DDS_Security_Handle handle); +typedef bool (*expired_proxypp_check_fn_t)(const struct proxy_participant * proxypp, DDS_Security_Handle handle); + +static bool delete_pp_by_handle (DDS_Security_Handle handle, expired_pp_check_fn_t expired_pp_check_fn, struct ddsi_domaingv *gv) +{ + struct participant *pp; + struct entidx_enum_participant epp; + bool result = false; + entidx_enum_participant_init (&epp, gv->entity_index); + while ((pp = entidx_enum_participant_next (&epp)) != NULL) + { + if (q_omg_participant_is_secure (pp) && expired_pp_check_fn (pp, handle)) + { + delete_participant (gv, &pp->e.guid); + result = true; + } + } + entidx_enum_participant_fini (&epp); + return result; +} + +static bool delete_proxypp_by_handle (const DDS_Security_Handle handle, expired_proxypp_check_fn_t expired_proxypp_check_fn, struct ddsi_domaingv *gv) +{ + struct proxy_participant *proxypp; + struct entidx_enum_proxy_participant eproxypp; + bool result = false; + entidx_enum_proxy_participant_init (&eproxypp, gv->entity_index); + while ((proxypp = entidx_enum_proxy_participant_next (&eproxypp)) != NULL) + { + if (q_omg_proxy_participant_is_secure(proxypp) && expired_proxypp_check_fn (proxypp, handle)) + { + delete_proxy_participant_by_guid (gv, &proxypp->e.guid, ddsrt_time_wallclock (), false); + result = true; + } + } + entidx_enum_proxy_participant_fini (&eproxypp); + return result; +} + +static bool pp_expired_by_perm (const struct participant * pp, DDS_Security_Handle handle) +{ + return pp->sec_attr->permissions_handle == handle; +} + +static bool proxypp_expired_by_perm (const struct proxy_participant * proxypp, DDS_Security_Handle handle) +{ + bool result = false; + uint32_t i = 0; + ddsrt_avl_iter_t it; + ddsrt_mutex_lock (&proxypp->sec_attr->lock); + for (struct proxypp_pp_match *ppm = ddsrt_avl_iter_first (&proxypp_pp_treedef, &proxypp->sec_attr->participants, &it); ppm; ppm = ddsrt_avl_iter_next (&it), i++) + { + if (ppm->permissions_handle == handle) + { + result = true; + break; + } + } + ddsrt_mutex_unlock (&proxypp->sec_attr->lock); + return result; +} + +static bool pp_expired_by_id (const struct participant * pp, DDS_Security_Handle handle) +{ + return pp->sec_attr->local_identity_handle == handle; +} + +static bool proxypp_expired_by_id (const struct proxy_participant * proxypp, DDS_Security_Handle handle) +{ + return proxypp->sec_attr->remote_identity_handle == handle; +} + +/* When a local identity (i.e. the identity of a local participant) or + a local permissions handle (bound to a local participant) expires, + the participant will be deleted. Strictly speaking, as described in the DDS + Security specification, the communication for this partcipant should be + stopped. A possible interpretation is that the participant and its + depending endpoints remain alive in 'expired' state and e.g. unread data + that was received earlier could still be retrieved by the application. + As we considered this as an edge case that would not be used widely, + the current implementation simply deletes the DDSI participant and leaves + the participant entity in the API in an invalid state, which could result + in error codes when calling API functions on these entities. This approach + dramatically simplifies the code for handling the revocation of permission + and identity handles. + + For remote identity revocation, in case any of the permission handles + in a pp-match of a proxy participant is expired, the proxy participant + is deleted, as the expired permission grant for a (remote) participant + applies to the participant as a whole (bound to its subject of the + identity certificate used by the participant) */ static DDS_Security_boolean on_revoke_permissions_cb(const dds_security_access_control *plugin, const DDS_Security_PermissionsHandle handle) { struct ddsi_domaingv *gv = plugin->gv; - struct entidx_enum_participant epp; - struct entidx_enum_proxy_participant eproxypp; - struct participant *pp; - struct proxy_participant *proxypp; - bool local = false; thread_state_awake (lookup_thread_state (), gv); - /* Find participants using this permissions handle */ - entidx_enum_participant_init (&epp, gv->entity_index); - while ((pp = entidx_enum_participant_next (&epp)) != NULL) - { - struct dds_security_context *sc = q_omg_security_get_secure_context(pp); - ddsrt_mutex_lock (&pp->sec_attr->lock); - if (pp->sec_attr->permissions_handle == handle) - { - uint32_t i = 0; - ddsrt_avl_citer_t it; - local = true; - for (struct pp_proxypp_match *ppm = ddsrt_avl_citer_first (&pp_proxypp_treedef, &pp->sec_attr->proxy_participants, &it); ppm; ppm = ddsrt_avl_citer_next (&it), i++) - pp_proxypp_unrelate_locked (sc, pp, &ppm->proxypp_guid); - } - ddsrt_mutex_unlock (&pp->sec_attr->lock); - } - entidx_enum_participant_fini (&epp); - - /* Find proxy participants using this permissions handle */ - if (!local) - { - entidx_enum_proxy_participant_init (&eproxypp, gv->entity_index); - while ((proxypp = entidx_enum_proxy_participant_next (&eproxypp)) != NULL) - { - ddsrt_mutex_lock (&proxypp->sec_attr->lock); - uint32_t i = 0; - ddsrt_avl_iter_t it; - bool del_proxypp = true; - for (struct proxypp_pp_match *ppm = ddsrt_avl_iter_first (&proxypp_pp_treedef, &proxypp->sec_attr->participants, &it); ppm; ppm = ddsrt_avl_iter_next (&it), i++) - { - if (ppm->permissions_handle == handle) - proxypp_pp_unrelate_locked (proxypp->sec_attr->sc, proxypp, &ppm->pp_guid, ppm->pp_crypto_handle); - else - del_proxypp = false; - } - ddsrt_mutex_unlock (&proxypp->sec_attr->lock); - if (del_proxypp) - delete_proxy_participant_by_guid (gv, &proxypp->e.guid, ddsrt_time_wallclock (), false); - } - entidx_enum_proxy_participant_fini (&eproxypp); - } + if (!delete_pp_by_handle (handle, pp_expired_by_perm, gv)) + delete_proxypp_by_handle (handle, proxypp_expired_by_perm, gv); thread_state_asleep (lookup_thread_state ()); return true; } +/* See comment above on_revoke_permissions_cb */ static DDS_Security_boolean on_revoke_identity_cb(const dds_security_authentication *plugin, const DDS_Security_IdentityHandle handle) { struct ddsi_domaingv *gv = plugin->gv; - struct entidx_enum_participant epp; - struct entidx_enum_proxy_participant eproxypp; - struct participant *pp; - struct proxy_participant *proxypp; - bool local = false; thread_state_awake (lookup_thread_state (), gv); - /* Find participants using this identity handle */ - entidx_enum_participant_init (&epp, gv->entity_index); - while ((pp = entidx_enum_participant_next (&epp)) != NULL) - { - struct dds_security_context *sc = q_omg_security_get_secure_context(pp); - ddsrt_mutex_lock (&pp->sec_attr->lock); - if (pp->sec_attr->local_identity_handle == handle) - { - uint32_t i = 0; - ddsrt_avl_citer_t it; - local = true; - for (struct pp_proxypp_match *ppm = ddsrt_avl_citer_first (&pp_proxypp_treedef, &pp->sec_attr->proxy_participants, &it); ppm; ppm = ddsrt_avl_citer_next (&it), i++) - pp_proxypp_unrelate_locked (sc, pp, &ppm->proxypp_guid); - } - ddsrt_mutex_unlock (&pp->sec_attr->lock); - } - entidx_enum_participant_fini (&epp); - - /* Find proxy participants using this permissions handle */ - if (!local) - { - entidx_enum_proxy_participant_init (&eproxypp, gv->entity_index); - while ((proxypp = entidx_enum_proxy_participant_next (&eproxypp)) != NULL) - { - bool del_pp; - ddsrt_mutex_lock (&proxypp->sec_attr->lock); - del_pp = proxypp->sec_attr->remote_identity_handle == handle; - ddsrt_mutex_unlock (&proxypp->sec_attr->lock); - if (del_pp) - delete_proxy_participant_by_guid (gv, &proxypp->e.guid, ddsrt_time_wallclock (), false); - } - entidx_enum_proxy_participant_fini (&eproxypp); - } + if (!delete_pp_by_handle (handle, pp_expired_by_id, gv)) + delete_proxypp_by_handle (handle, proxypp_expired_by_id, gv); thread_state_asleep (lookup_thread_state ()); return true; } - dds_return_t q_omg_security_load (dds_security_context *sc, const dds_qos_t *qos, struct ddsi_domaingv *gv) { dds_security_plugin_suite_config psc; From dae562c6028ef11c5ac6ee6b8190b9e53687ead8 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Wed, 1 Apr 2020 18:47:34 +0200 Subject: [PATCH 164/238] Improve delays/timing in permissions_expiry_multiple test Signed-off-by: Dennis Potman --- src/security/core/tests/access_control.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index 981a196..9fdf1ae 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -255,6 +255,7 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) char *perm_topic = get_permissions_topic (topic_name); // 1st node used as reader, other nodes as writer + print_test_msg ("creating permissions grants\n"); const char *id[N_NODES], *pk[N_NODES], *ca_list[N_NODES]; char * id_subj[N_NODES], *grants[N_NODES]; bool exp_fail[N_NODES]; @@ -266,8 +267,11 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) ca_list[i] = ca; id[i] = generate_identity (ca_list[i], TEST_IDENTITY_CA1_PRIVATE_KEY, id_name, pk[i], 0, 3600, &id_subj[i]); exp_fail[i] = false; - dds_duration_t v = DDS_SECS(i < N_RD ? 3600 : PERM_EXP_BASE + 2 * i); /* 1st node is reader and should not expire */ - grants[i] = get_permissions_grant (id_name, id_subj[i], t_perm, t_perm + v, perm_topic, perm_topic, NULL); + dds_duration_t v = DDS_SECS(i < N_RD ? 3600 : PERM_EXP_BASE + 2 * i); /* readers should not expire */ + dds_time_t t_exp = ddsrt_time_add_duration (t_perm, v); + if (i >= N_RD) + print_test_msg ("w[%d] grant expires at %d.%06d\n", i - N_RD, (int32_t) (t_exp / DDS_NSECS_IN_SEC), (int32_t) (t_exp % DDS_NSECS_IN_SEC) / 1000); + grants[i] = get_permissions_grant (id_name, id_subj[i], t_perm, t_exp, perm_topic, perm_topic, NULL); ddsrt_free (id_name); } @@ -316,16 +320,16 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) dds_sample_info_t info[1]; dds_return_t ret; - for (int i = 0; i < N_WR; i++) + for (int run = 0; run < N_WR; run++) { - // sleep until 1s before next writer pp permission expires - dds_duration_t delay = DDS_SECS (PERM_EXP_BASE + 2 * i) - (dds_time () - t_perm); + // sleep until 1s after next writer pp permission expires + dds_duration_t delay = DDS_SECS (PERM_EXP_BASE + 2 * run + 1) - (dds_time () - t_perm); if (delay > 0) dds_sleepfor (delay); - print_test_msg ("run %d\n", i); + print_test_msg ("run %d\n", run); - for (int w = 0; w < N_WR; w++) + for (int w = run; w < N_WR; w++) { sample.id = w; ret = dds_write (wr[w], &sample); @@ -356,8 +360,8 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) n_invalid++; } } - CU_ASSERT_EQUAL (n_samples, N_WR - i); - CU_ASSERT (n_invalid <= i); + CU_ASSERT_EQUAL (n_samples, N_WR - run); + CU_ASSERT (n_invalid <= run); } access_control_fini (N_NODES); From 680c2ebf8cd1584d4bf6ae7d2dbd26b8fe8587e7 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Wed, 15 Apr 2020 19:37:22 +0200 Subject: [PATCH 165/238] Call delete_proxy_participant_by_guid with implicit flag set when revoking permission or identity Signed-off-by: Dennis Potman --- src/core/ddsi/src/ddsi_security_omg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index be0d57e..fce2dbf 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -841,7 +841,7 @@ static bool delete_proxypp_by_handle (const DDS_Security_Handle handle, expired_ { if (q_omg_proxy_participant_is_secure(proxypp) && expired_proxypp_check_fn (proxypp, handle)) { - delete_proxy_participant_by_guid (gv, &proxypp->e.guid, ddsrt_time_wallclock (), false); + (void) delete_proxy_participant_by_guid (gv, &proxypp->e.guid, ddsrt_time_wallclock (), true); result = true; } } From c89f858b7373052f80781be1f25dd9fc070e292d Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Wed, 15 Apr 2020 20:36:05 +0200 Subject: [PATCH 166/238] Fix memory leak that can occur when decoding rtps message with origin authentication being used Signed-off-by: Dennis Potman --- src/core/ddsi/src/ddsi_security_omg.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index fce2dbf..aae4ebf 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -3248,7 +3248,10 @@ static bool q_omg_security_decode_rtps_message (struct proxy_participant *proxyp if (!sc->crypto_context->crypto_transform->decode_rtps_message (sc->crypto_context->crypto_transform, &plain_buffer, &encoded_buffer, pm->pp_crypto_handle, proxypp->sec_attr->crypto_handle, &ex)) { if (ex.code == DDS_SECURITY_ERR_INVALID_CRYPTO_RECEIVER_SIGN_CODE) + { + DDS_Security_Exception_reset (&ex); continue; /* Could be caused by 'with_origin_authentication' being used, so try next match */ + } GVTRACE ("decoding rtps message from remote participant "PGUIDFMT" failed: %s\n", PGUID (proxypp->e.guid), ex.message ? ex.message : "Unknown error"); DDS_Security_Exception_reset (&ex); ddsrt_mutex_unlock (&proxypp->sec_attr->lock); From e8dfbabd0c8a72a421cefd834462100397348e84 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 7 Apr 2020 21:25:12 +0200 Subject: [PATCH 167/238] Add locking when intializing remote key material The initialization of remote participant's key material was not protected by the remote_participant_crypto lock, which could result in using partially initialized remote key material. This caused intermittent test failures with assertions on key_size in crypto_cipher_decrypt_data. This commit fixes this issue by adding locking for the remote key material. Signed-off-by: Dennis Potman --- .../cryptographic/src/crypto_key_exchange.c | 2 +- .../cryptographic/src/crypto_key_factory.c | 56 +++++++++++++++---- .../cryptographic/src/crypto_key_factory.h | 1 + .../cryptographic/src/crypto_objects.c | 55 ++++++++++++------ .../cryptographic/src/crypto_objects.h | 19 ++++++- .../cryptographic/src/crypto_transform.c | 12 ++-- 6 files changed, 108 insertions(+), 37 deletions(-) diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_key_exchange.c b/src/security/builtin_plugins/cryptographic/src/crypto_key_exchange.c index 59d19af..9ea8ade 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_key_exchange.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_key_exchange.c @@ -179,7 +179,7 @@ create_local_participant_crypto_tokens( } factory = cryptography_get_crypto_key_factory(impl->crypto); - if (!crypto_factory_get_participant_crypto_tokens(factory, local_id, remote_id, &pp_key_material, NULL, ex)) + if (!crypto_factory_get_participant_crypto_tokens(factory, local_id, remote_id, &pp_key_material, NULL, NULL, ex)) goto fail_invalid_arg; serialize_master_key_material(pp_key_material->local_P2P_key_material, &buffer, &length); CRYPTO_OBJECT_RELEASE(pp_key_material); diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c index ab75a63..cef6830 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c @@ -20,6 +20,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" #include "dds/ddsrt/types.h" +#include "dds/ddsi/q_gc.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/dds_security_serialize.h" @@ -841,12 +842,14 @@ unregister_participant( if ((rmt_pp_crypto = (remote_participant_crypto *)crypto_object_table_find(implementation->crypto_objects, handles[i])) != NULL) { - if ((keymat = crypto_remote_participant_remove_keymat(rmt_pp_crypto, participant_crypto_handle)) != NULL) + ddsrt_mutex_lock(&rmt_pp_crypto->lock); + if ((keymat = crypto_remote_participant_remove_keymat_locked(rmt_pp_crypto, participant_crypto_handle)) != NULL) { if (keymat->remote_key_material && keymat->remote_key_material->receiver_specific_key_id != 0) - crypto_remove_specific_key_relation(rmt_pp_crypto, keymat->remote_key_material->receiver_specific_key_id); + crypto_remove_specific_key_relation_locked(rmt_pp_crypto, keymat->remote_key_material->receiver_specific_key_id); CRYPTO_OBJECT_RELEASE(keymat); } + ddsrt_mutex_unlock(&rmt_pp_crypto->lock); CRYPTO_OBJECT_RELEASE(rmt_pp_crypto); } } @@ -862,12 +865,14 @@ unregister_participant( num = crypto_remote_participnant_get_matching(rmt_pp_crypto, &handles); for (i = 0; i < num; i++) { - if ((keymat = crypto_remote_participant_remove_keymat(rmt_pp_crypto, handles[i])) != NULL) + ddsrt_mutex_lock(&rmt_pp_crypto->lock); + if ((keymat = crypto_remote_participant_remove_keymat_locked(rmt_pp_crypto, handles[i])) != NULL) { if (keymat->remote_key_material && keymat->remote_key_material->receiver_specific_key_id != 0) - crypto_remove_specific_key_relation(rmt_pp_crypto, keymat->remote_key_material->receiver_specific_key_id); + crypto_remove_specific_key_relation_locked(rmt_pp_crypto, keymat->remote_key_material->receiver_specific_key_id); CRYPTO_OBJECT_RELEASE(keymat); } + ddsrt_mutex_unlock(&rmt_pp_crypto->lock); if ((loc_pp_crypto = (local_participant_crypto *)crypto_object_table_find(implementation->crypto_objects, handles[i])) != NULL) { @@ -1063,8 +1068,8 @@ crypto_factory_get_participant_crypto_tokens( DDS_Security_ParticipantCryptoHandle local_id, DDS_Security_ParticipantCryptoHandle remote_id, participant_key_material **pp_key_material, + master_key_material **remote_key_matarial, DDS_Security_ProtectionKind *protection_kind, - DDS_Security_SecurityException *ex) { assert (pp_key_material != NULL); @@ -1085,14 +1090,19 @@ crypto_factory_get_participant_crypto_tokens( goto err_remote; } - if (!(*pp_key_material = (participant_key_material *)crypto_remote_participant_lookup_keymat(remote_crypto, local_id))) + ddsrt_mutex_lock(&remote_crypto->lock); + if (!(*pp_key_material = (participant_key_material *)crypto_remote_participant_lookup_keymat_locked(remote_crypto, local_id))) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); + ddsrt_mutex_unlock(&remote_crypto->lock); goto err_remote; } + if (remote_key_matarial != NULL) + *remote_key_matarial = (*pp_key_material)->remote_key_material; if (protection_kind != NULL) *protection_kind = remote_crypto->rtps_protection_kind; + ddsrt_mutex_unlock(&remote_crypto->lock); result = true; err_remote: @@ -1101,6 +1111,12 @@ err_no_remote: return result; } +static void gc_remote_key_material (struct gcreq *gcreq) +{ + CRYPTO_OBJECT_RELEASE (gcreq->arg); + gcreq_free (gcreq); +} + bool crypto_factory_set_participant_crypto_tokens( const dds_security_crypto_key_factory *factory, @@ -1128,30 +1144,46 @@ crypto_factory_set_participant_crypto_tokens( goto err_inv_remote; } - key_material = crypto_remote_participant_lookup_keymat(remote_crypto, local_id); + ddsrt_mutex_lock(&remote_crypto->lock); + key_material = crypto_remote_participant_lookup_keymat_locked(remote_crypto, local_id); if (key_material) { - if (!key_material->remote_key_material) - key_material->remote_key_material = crypto_master_key_material_new(CRYPTO_TRANSFORMATION_KIND_NONE); - crypto_token_copy(key_material->remote_key_material, remote_key_mat); + /* Because setting crypto tokens is not done very often, we're not using an + atomic pointer (which makes the code less readable) and do not introduce an + additional lock for the remote key material. Instead it is protected by the + remote_participant_crypto lock. For cleaning up the old remote key + material, the garbage collector is used so that any pointer to the remote + key material can be safely used until thread state sleep. */ + master_key_material *remote_key_mat_old = key_material->remote_key_material; + master_key_material *remote_key_mat_new = crypto_master_key_material_new(CRYPTO_TRANSFORMATION_KIND_NONE); + crypto_token_copy(remote_key_mat_new, remote_key_mat); + key_material->remote_key_material = remote_key_mat_new; + if (remote_key_mat_old != NULL) + { + struct gcreq *gcreq = gcreq_new(impl->crypto->gv->gcreq_queue, gc_remote_key_material); + gcreq->arg = remote_key_mat_old; + gcreq_enqueue(gcreq); + } uint32_t specific_key = key_material->remote_key_material->receiver_specific_key_id; if (specific_key != 0) { - key_relation *relation = crypto_find_specific_key_relation(remote_crypto, specific_key); + key_relation *relation = crypto_find_specific_key_relation_locked(remote_crypto, specific_key); if (!relation) { local_participant_crypto *local_crypto = (local_participant_crypto *)crypto_object_table_find(impl->crypto_objects, local_id); relation = crypto_key_relation_new(0, specific_key, CRYPTO_OBJECT(local_crypto), CRYPTO_OBJECT(remote_crypto), key_material->remote_key_material); - crypto_insert_specific_key_relation(remote_crypto, relation); + crypto_insert_specific_key_relation_locked(remote_crypto, relation); CRYPTO_OBJECT_RELEASE(local_crypto); } CRYPTO_OBJECT_RELEASE(relation); } + ddsrt_mutex_unlock(&remote_crypto->lock); CRYPTO_OBJECT_RELEASE(key_material); } else { + ddsrt_mutex_unlock(&remote_crypto->lock); DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_CODE, 0, DDS_SECURITY_ERR_INVALID_CRYPTO_HANDLE_MESSAGE); goto err_inv_remote; diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.h b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.h index a908e2c..66538f4 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.h +++ b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.h @@ -40,6 +40,7 @@ bool crypto_factory_get_participant_crypto_tokens( DDS_Security_ParticipantCryptoHandle local_id, DDS_Security_ParticipantCryptoHandle remote_id, participant_key_material **pp_key_material, + master_key_material **remote_key_matarial, DDS_Security_ProtectionKind *protection_kind, DDS_Security_SecurityException *ex); diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_objects.c b/src/security/builtin_plugins/cryptographic/src/crypto_objects.c index 17929af..9a9cf05 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_objects.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_objects.c @@ -472,28 +472,29 @@ void crypto_remote_participant_add_keymat(remote_participant_crypto *rmt_pp_cryp ddsrt_mutex_unlock(&rmt_pp_crypto->lock); } -participant_key_material * crypto_remote_participant_remove_keymat(remote_participant_crypto *rmt_pp_crypto, DDS_Security_ParticipantCryptoHandle loc_pp_handle) +participant_key_material * crypto_remote_participant_remove_keymat_locked(remote_participant_crypto *rmt_pp_crypto, DDS_Security_ParticipantCryptoHandle loc_pp_handle) { participant_key_material *keymat; ddsrt_avl_dpath_t dpath; - ddsrt_mutex_lock(&rmt_pp_crypto->lock); keymat = ddsrt_avl_clookup_dpath(&rmt_pp_keymat_treedef, &rmt_pp_crypto->key_material_table, &loc_pp_handle, &dpath); if (keymat) ddsrt_avl_cdelete_dpath(&rmt_pp_keymat_treedef, &rmt_pp_crypto->key_material_table, keymat, &dpath); - ddsrt_mutex_unlock(&rmt_pp_crypto->lock); return keymat; } +participant_key_material * crypto_remote_participant_lookup_keymat_locked(remote_participant_crypto *rmt_pp_crypto, DDS_Security_ParticipantCryptoHandle loc_pp_handle) +{ + return CRYPTO_OBJECT_KEEP(ddsrt_avl_clookup(&rmt_pp_keymat_treedef, &rmt_pp_crypto->key_material_table, &loc_pp_handle)); +} + participant_key_material * crypto_remote_participant_lookup_keymat(remote_participant_crypto *rmt_pp_crypto, DDS_Security_ParticipantCryptoHandle loc_pp_handle) { participant_key_material *keymat; - ddsrt_mutex_lock(&rmt_pp_crypto->lock); - keymat = CRYPTO_OBJECT_KEEP(ddsrt_avl_clookup(&rmt_pp_keymat_treedef, &rmt_pp_crypto->key_material_table, &loc_pp_handle)); + keymat = crypto_remote_participant_lookup_keymat_locked(rmt_pp_crypto, loc_pp_handle); ddsrt_mutex_unlock(&rmt_pp_crypto->lock); - return keymat; } @@ -727,32 +728,52 @@ key_relation * crypto_find_endpoint_relation( return relation; } +void crypto_insert_specific_key_relation_locked( + remote_participant_crypto *rpc, + key_relation *relation) +{ + ddsrt_avl_insert(&specific_key_treedef, &rpc->specific_key_index, CRYPTO_OBJECT_KEEP(relation)); +} + void crypto_insert_specific_key_relation( remote_participant_crypto *rpc, key_relation *relation) { ddsrt_mutex_lock(&rpc->lock); - ddsrt_avl_insert(&specific_key_treedef, &rpc->specific_key_index, CRYPTO_OBJECT_KEEP(relation)); + crypto_insert_specific_key_relation_locked(rpc, relation); ddsrt_mutex_unlock(&rpc->lock); } +void crypto_remove_specific_key_relation_locked( + remote_participant_crypto *rpc, + uint32_t key_id) +{ + key_relation *relation; + ddsrt_avl_dpath_t dpath; + relation = ddsrt_avl_lookup_dpath(&specific_key_treedef, &rpc->specific_key_index, &key_id, &dpath); + if (relation) + { + ddsrt_avl_delete_dpath(&specific_key_treedef, &rpc->specific_key_index, relation, &dpath); + CRYPTO_OBJECT_RELEASE(relation); + } +} + void crypto_remove_specific_key_relation( remote_participant_crypto *rpc, uint32_t key_id) { - key_relation *relation; - ddsrt_avl_dpath_t dpath; - ddsrt_mutex_lock(&rpc->lock); - relation = ddsrt_avl_lookup_dpath(&specific_key_treedef, &rpc->specific_key_index, &key_id, &dpath); - if (relation) - { - ddsrt_avl_delete_dpath(&specific_key_treedef, &rpc->specific_key_index, relation, &dpath); - CRYPTO_OBJECT_RELEASE(relation); - } + crypto_remove_specific_key_relation_locked(rpc, key_id); ddsrt_mutex_unlock(&rpc->lock); } +key_relation * crypto_find_specific_key_relation_locked( + remote_participant_crypto *rpc, + uint32_t key_id) +{ + return CRYPTO_OBJECT_KEEP(ddsrt_avl_lookup(&specific_key_treedef, &rpc->specific_key_index, &key_id)); +} + key_relation * crypto_find_specific_key_relation( remote_participant_crypto *rpc, uint32_t key_id) @@ -760,7 +781,7 @@ key_relation * crypto_find_specific_key_relation( key_relation *relation; ddsrt_mutex_lock(&rpc->lock); - relation = CRYPTO_OBJECT_KEEP(ddsrt_avl_lookup(&specific_key_treedef, &rpc->specific_key_index, &key_id)); + relation = crypto_find_specific_key_relation_locked(rpc, key_id); ddsrt_mutex_unlock(&rpc->lock); return relation; diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_objects.h b/src/security/builtin_plugins/cryptographic/src/crypto_objects.h index 0ef700b..ebb34ed 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_objects.h +++ b/src/security/builtin_plugins/cryptographic/src/crypto_objects.h @@ -261,16 +261,28 @@ crypto_find_endpoint_relation( CryptoObject *lch, uint32_t key_id); +void crypto_insert_specific_key_relation_locked( + remote_participant_crypto *rpc, + key_relation *relation); + void crypto_insert_specific_key_relation( remote_participant_crypto *rpc, key_relation *relation); +void crypto_remove_specific_key_relation_locked( + remote_participant_crypto *rpc, + uint32_t key_id); + void crypto_remove_specific_key_relation( remote_participant_crypto *rpc, uint32_t key_id); +key_relation * crypto_find_specific_key_relation_locked( + remote_participant_crypto *rpc, + uint32_t key_id); + key_relation * crypto_find_specific_key_relation( remote_participant_crypto *rpc, @@ -403,10 +415,15 @@ crypto_remote_participant_add_keymat( participant_key_material *keymat); participant_key_material * -crypto_remote_participant_remove_keymat( +crypto_remote_participant_remove_keymat_locked( remote_participant_crypto *rmt_pp_crypte, DDS_Security_ParticipantCryptoHandle loc_pp_handle); +participant_key_material * +crypto_remote_participant_lookup_keymat_locked( + remote_participant_crypto *rmt_pp_crypto, + DDS_Security_ParticipantCryptoHandle loc_pp_handle); + participant_key_material * crypto_remote_participant_lookup_keymat( remote_participant_crypto *rmt_pp_crypte, diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_transform.c b/src/security/builtin_plugins/cryptographic/src/crypto_transform.c index 21c3e1c..a2f6893 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_transform.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_transform.c @@ -996,7 +996,7 @@ add_receiver_specific_mac( return false; /* get remote crypto tokens */ - if (!crypto_factory_get_participant_crypto_tokens(factory, sending_participant_crypto, receiving_participant_crypto, &pp_key_material, &remote_protection_kind, ex)) + if (!crypto_factory_get_participant_crypto_tokens(factory, sending_participant_crypto, receiving_participant_crypto, &pp_key_material, NULL, &remote_protection_kind, ex)) { CRYPTO_OBJECT_RELEASE(session); return false; @@ -1841,6 +1841,7 @@ decode_rtps_message(dds_security_crypto_transform *instance, uint32_t decoded_body_size; static const char *context = "decode_rtps_message"; participant_key_material *pp_key_material; + master_key_material *remote_key_material; DDS_Security_ProtectionKind remote_protection_kind; bool result = false; @@ -1872,10 +1873,9 @@ decode_rtps_message(dds_security_crypto_transform *instance, transform_kind = CRYPTO_TRANSFORM_KIND(header.transform_identifier.transformation_kind); /* Retrieve key material from sending_participant_crypto and receiving_participant_crypto from factory */ - if (!crypto_factory_get_participant_crypto_tokens(factory, receiving_participant_crypto, sending_participant_crypto, &pp_key_material, &remote_protection_kind, ex)) + if (!crypto_factory_get_participant_crypto_tokens(factory, receiving_participant_crypto, sending_participant_crypto, &pp_key_material, &remote_key_material, &remote_protection_kind, ex)) goto fail_tokens; - - if (!pp_key_material->remote_key_material) + if (remote_key_material == NULL) goto fail_remote_keys_not_ready; if (has_origin_authentication(remote_protection_kind)) @@ -1886,8 +1886,8 @@ decode_rtps_message(dds_security_crypto_transform *instance, /* calculate the session key */ decoded_body = DDS_Security_OctetSeq_allocbuf(contents._length); - if (!initialize_remote_session_info(&remote_session, &header, pp_key_material->remote_key_material->master_salt, - pp_key_material->remote_key_material->master_sender_key, pp_key_material->remote_key_material->transformation_kind, ex)) + if (!initialize_remote_session_info(&remote_session, &header, remote_key_material->master_salt, + remote_key_material->master_sender_key, remote_key_material->transformation_kind, ex)) { DDS_Security_Exception_set(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_CODE, 0, "decode_rtps_message: " DDS_SECURITY_ERR_INVALID_CRYPTO_ARGUMENT_MESSAGE); From d22032c9460e691f6a9f1b98ff50bcfbc7d8820c Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 18 Apr 2020 12:17:10 +0200 Subject: [PATCH 168/238] Restore SEDP tracing format Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_ddsi_discovery.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 98db5b0..df4f133 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -1368,6 +1368,8 @@ static void handle_SEDP (const struct receiver_state *rst, seqno_t seq, struct d ddsi_plist_t decoded_data; if (ddsi_serdata_to_sample (serdata, &decoded_data, NULL, NULL)) { + struct ddsi_domaingv * const gv = rst->gv; + GVLOGDISC ("SEDP ST%x", serdata->statusinfo); switch (serdata->statusinfo & (NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER)) { case 0: From 080514d45a21cc1d7f6dcc441514d52b71bc77a7 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 18 Apr 2020 12:17:24 +0200 Subject: [PATCH 169/238] Remove redundant check for endpoint GUID in SEDP The conversion of incoming discovery data (in "parameter list" format) check for the presence of the entity GUID parameter for the particular type of endpoint and use it as the key field in subsequent processing. If the parameter is absent, deserialisation fails and the handlers are never called and the old check is therefore no longer necessary. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_ddsi_discovery.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index df4f133..1bc06c4 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -1162,9 +1162,7 @@ static void handle_SEDP_alive (const struct receiver_state *rst, seqno_t seq, dd #endif assert (datap); - - if (!(datap->present & PP_ENDPOINT_GUID)) - E (" no guid?\n", err); + assert (datap->present & PP_ENDPOINT_GUID); GVLOGDISC (" "PGUIDFMT, PGUID (datap->endpoint_guid)); ppguid.prefix = datap->endpoint_guid.prefix; @@ -1350,11 +1348,7 @@ static void handle_SEDP_dead (const struct receiver_state *rst, ddsi_plist_t *da { struct ddsi_domaingv * const gv = rst->gv; int res; - if (!(datap->present & PP_ENDPOINT_GUID)) - { - GVLOGDISC (" no guid?\n"); - return; - } + assert (datap->present & PP_ENDPOINT_GUID); GVLOGDISC (" "PGUIDFMT, PGUID (datap->endpoint_guid)); if (is_writer_entityid (datap->endpoint_guid.entityid)) res = delete_proxy_writer (gv, &datap->endpoint_guid, timestamp, 0); From 19bc6f33cc1956db668b2468be3dc47880fbb40a Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 14 Apr 2020 20:25:20 +0200 Subject: [PATCH 170/238] Access control tests Add test cases for the join_access_control governance setting and for the access control plugin check_create_ and check_remote_ hooks, using a wrapper plugin that simulates failure for each of these, to test the DDSI integration with the access control plugin. This commit also contains fixes for: - an assert on DDS_RETCODE_OK in dds_create_reader and dds_create_writer that cased the application to terminate in case creation of a reader or writer is not allowed by security - do not match a proxy reader that has the 'relay_only' set to true, which is currently unsupported Signed-off-by: Dennis Potman --- src/core/ddsc/src/dds_reader.c | 43 +- src/core/ddsc/src/dds_writer.c | 48 +- .../include/dds/ddsi/ddsi_security_util.h | 31 +- src/core/ddsi/include/dds/ddsi/q_entity.h | 5 +- src/core/ddsi/src/ddsi_security_omg.c | 56 +- src/core/ddsi/src/ddsi_security_util.c | 18 + src/core/ddsi/src/q_entity.c | 50 +- .../include/dds/security/dds_security_api.h | 2 +- src/security/core/tests/CMakeLists.txt | 4 +- src/security/core/tests/access_control.c | 265 +++++-- src/security/core/tests/authentication.c | 5 +- .../tests/common/access_control_wrapper.c | 728 +++++++++++++----- .../tests/common/access_control_wrapper.h | 32 +- .../tests/common/authentication_wrapper.c | 24 +- .../tests/common/authentication_wrapper.h | 16 +- .../core/tests/common/cryptography_wrapper.c | 20 +- .../core/tests/common/cryptography_wrapper.h | 12 +- .../tests/common/security_config_test_utils.c | 9 +- .../tests/common/security_config_test_utils.h | 2 +- src/security/core/tests/common/test_utils.c | 80 +- src/security/core/tests/common/test_utils.h | 9 +- 21 files changed, 1022 insertions(+), 437 deletions(-) diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index 2bd7995..bffe59a 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -30,6 +30,7 @@ #include "dds__builtin.h" #include "dds/ddsi/ddsi_sertopic.h" #include "dds/ddsi/ddsi_entity_index.h" +#include "dds/ddsi/ddsi_security_omg.h" DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_reader) @@ -430,6 +431,7 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe /* Merge qos from topic and subscriber, dds_copy_qos only fails when it is passed a null argument, but that isn't the case here */ + struct ddsi_domaingv *gv = &sub->m_entity.m_domain->gv; rqos = dds_create_qos (); if (qos) ddsi_xqos_mergein_missing (rqos, qos, DDS_READER_QOS_MASK); @@ -437,25 +439,43 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe ddsi_xqos_mergein_missing (rqos, sub->m_entity.m_qos, ~(uint64_t)0); if (tp->m_ktopic->qos) ddsi_xqos_mergein_missing (rqos, tp->m_ktopic->qos, ~(uint64_t)0); - ddsi_xqos_mergein_missing (rqos, &sub->m_entity.m_domain->gv.default_xqos_rd, ~(uint64_t)0); + ddsi_xqos_mergein_missing (rqos, &gv->default_xqos_rd, ~(uint64_t)0); - if ((rc = ddsi_xqos_valid (&sub->m_entity.m_domain->gv.logconfig, rqos)) < 0 || - (rc = validate_reader_qos(rqos)) != DDS_RETCODE_OK) - { - dds_delete_qos (rqos); + if ((rc = ddsi_xqos_valid (&gv->logconfig, rqos)) < 0 || (rc = validate_reader_qos(rqos)) != DDS_RETCODE_OK) goto err_bad_qos; - } /* Additional checks required for built-in topics: we don't want to run into a resource limit on a built-in topic, it is a needless complication */ if (pseudo_topic && !dds__validate_builtin_reader_qos (tp->m_entity.m_domain, pseudo_topic, rqos)) { - dds_delete_qos (rqos); rc = DDS_RETCODE_INCONSISTENT_POLICY; goto err_bad_qos; } + thread_state_awake (lookup_thread_state (), gv); + const struct ddsi_guid * ppguid = dds_entity_participant_guid (&sub->m_entity); + struct participant * pp = entidx_lookup_participant_guid (gv->entity_index, ppguid); + if (pp == NULL) + { + GVLOGDISC ("new_reader - participant "PGUIDFMT" not found\n", PGUID (*ppguid)); + rc = DDS_RETCODE_BAD_PARAMETER; + goto err_pp_not_found; + } + +#ifdef DDSI_INCLUDE_SECURITY + /* Check if DDS Security is enabled */ + if (q_omg_participant_is_secure (pp)) + { + /* ask to access control security plugin for create reader permissions */ + if (!q_omg_security_check_create_reader (pp, gv->config.domainId, tp->m_stopic->name, rqos)) + { + rc = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY; + goto err_not_allowed; + } + } +#endif + /* Create reader and associated read cache (if not provided by caller) */ struct dds_reader * const rd = dds_alloc (sizeof (*rd)); const dds_entity_t reader = dds_entity_init (&rd->m_entity, &sub->m_entity, DDS_KIND_READER, false, rqos, listener, DDS_READER_STATUS_MASK); @@ -474,8 +494,7 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe it; and then invoke those listeners that are in the pending set */ dds_entity_init_complete (&rd->m_entity); - thread_state_awake (lookup_thread_state (), &sub->m_entity.m_domain->gv); - rc = new_reader (&rd->m_rd, &rd->m_entity.m_domain->gv, &rd->m_entity.m_guid, NULL, dds_entity_participant_guid (&sub->m_entity), tp->m_stopic, rqos, &rd->m_rhc->common.rhc, dds_reader_status_cb, rd); + rc = new_reader (&rd->m_rd, &rd->m_entity.m_guid, NULL, pp, tp->m_stopic, rqos, &rd->m_rhc->common.rhc, dds_reader_status_cb, rd); assert (rc == DDS_RETCODE_OK); /* FIXME: can be out-of-resources at the very least */ thread_state_asleep (lookup_thread_state ()); @@ -487,7 +506,13 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe dds_subscriber_unlock (sub); return reader; +#ifdef DDSI_INCLUDE_SECURITY +err_not_allowed: +#endif +err_pp_not_found: + thread_state_asleep (lookup_thread_state ()); err_bad_qos: + dds_delete_qos (rqos); dds_topic_allow_set_qos (tp); err_pp_mismatch: dds_topic_unpin (tp); diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index caedd81..12d2676 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -20,6 +20,7 @@ #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_xmsg.h" #include "dds/ddsi/ddsi_entity_index.h" +#include "dds/ddsi/ddsi_security_omg.h" #include "dds__writer.h" #include "dds__listener.h" #include "dds__init.h" @@ -312,6 +313,7 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit dds_topic_defer_set_qos (tp); /* Merge Topic & Publisher qos */ + struct ddsi_domaingv *gv = &pub->m_entity.m_domain->gv; wqos = dds_create_qos (); if (qos) ddsi_xqos_mergein_missing (wqos, qos, DDS_WRITER_QOS_MASK); @@ -319,29 +321,47 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit ddsi_xqos_mergein_missing (wqos, pub->m_entity.m_qos, ~(uint64_t)0); if (tp->m_ktopic->qos) ddsi_xqos_mergein_missing (wqos, tp->m_ktopic->qos, ~(uint64_t)0); - ddsi_xqos_mergein_missing (wqos, &pub->m_entity.m_domain->gv.default_xqos_wr, ~(uint64_t)0); + ddsi_xqos_mergein_missing (wqos, &gv->default_xqos_wr, ~(uint64_t)0); - if ((rc = ddsi_xqos_valid (&pub->m_entity.m_domain->gv.logconfig, wqos)) < 0 || - (rc = validate_writer_qos(wqos)) != DDS_RETCODE_OK) - { - dds_delete_qos(wqos); + if ((rc = ddsi_xqos_valid (&gv->logconfig, wqos)) < 0 || (rc = validate_writer_qos(wqos)) != DDS_RETCODE_OK) goto err_bad_qos; + + thread_state_awake (lookup_thread_state (), gv); + const struct ddsi_guid *ppguid = dds_entity_participant_guid (&pub->m_entity); + struct participant *pp = entidx_lookup_participant_guid (gv->entity_index, ppguid); + if (pp == NULL) + { + GVLOGDISC ("new_writer - participant "PGUIDFMT" not found\n", PGUID (*ppguid)); + rc = DDS_RETCODE_BAD_PARAMETER; + goto err_pp_not_found; } +#ifdef DDSI_INCLUDE_SECURITY + /* Check if DDS Security is enabled */ + if (q_omg_participant_is_secure (pp)) + { + /* ask to access control security plugin for create writer permissions */ + if (!q_omg_security_check_create_writer (pp, gv->config.domainId, tp->m_stopic->name, wqos)) + { + rc = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY; + goto err_not_allowed; + } + } +#endif + /* Create writer */ - ddsi_tran_conn_t conn = pub->m_entity.m_domain->gv.xmit_conn; + ddsi_tran_conn_t conn = gv->xmit_conn; struct dds_writer * const wr = dds_alloc (sizeof (*wr)); const dds_entity_t writer = dds_entity_init (&wr->m_entity, &pub->m_entity, DDS_KIND_WRITER, false, wqos, listener, DDS_WRITER_STATUS_MASK); wr->m_topic = tp; dds_entity_add_ref_locked (&tp->m_entity); - wr->m_xp = nn_xpack_new (conn, get_bandwidth_limit (wqos->transport_priority), pub->m_entity.m_domain->gv.config.xpack_send_async); + wr->m_xp = nn_xpack_new (conn, get_bandwidth_limit (wqos->transport_priority), gv->config.xpack_send_async); wrinfo = whc_make_wrinfo (wr, wqos); - wr->m_whc = whc_new (&pub->m_entity.m_domain->gv, wrinfo); + wr->m_whc = whc_new (gv, wrinfo); whc_free_wrinfo (wrinfo); - wr->whc_batch = pub->m_entity.m_domain->gv.config.whc_batch; + wr->whc_batch = gv->config.whc_batch; - thread_state_awake (lookup_thread_state (), &pub->m_entity.m_domain->gv); - rc = new_writer (&wr->m_wr, &wr->m_entity.m_domain->gv, &wr->m_entity.m_guid, NULL, dds_entity_participant_guid (&pub->m_entity), tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); + rc = new_writer (&wr->m_wr, &wr->m_entity.m_guid, NULL, pp, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr); assert(rc == DDS_RETCODE_OK); thread_state_asleep (lookup_thread_state ()); @@ -355,7 +375,13 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit dds_publisher_unlock (pub); return writer; +#ifdef DDSI_INCLUDE_SECURITY +err_not_allowed: +#endif +err_pp_not_found: + thread_state_asleep (lookup_thread_state ()); err_bad_qos: + dds_delete_qos(wqos); dds_topic_allow_set_qos (tp); err_pp_mismatch: dds_topic_unpin (tp); diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_security_util.h b/src/core/ddsi/include/dds/ddsi/ddsi_security_util.h index 7c03496..188675e 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_util.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_util.h @@ -22,64 +22,37 @@ extern "C" { #endif void g_omg_shallow_copy_StringSeq(DDS_Security_StringSeq *dst, const ddsi_stringseq_t *src); - void g_omg_shallow_free_StringSeq(DDS_Security_StringSeq *obj); - void q_omg_copy_PropertySeq(DDS_Security_PropertySeq *dst, const dds_propertyseq_t *src); - void q_omg_shallow_copyin_PropertySeq(DDS_Security_PropertySeq *dst, const dds_propertyseq_t *src); - void q_omg_shallow_copyout_PropertySeq(dds_propertyseq_t *dst, const DDS_Security_PropertySeq *src); - void q_omg_shallow_free_PropertySeq(DDS_Security_PropertySeq *obj); - void q_omg_shallow_copyin_BinaryPropertySeq(DDS_Security_BinaryPropertySeq *dst, const dds_binarypropertyseq_t *src); - void q_omg_shallow_copyout_BinaryPropertySeq(dds_binarypropertyseq_t *dst, const DDS_Security_BinaryPropertySeq *src); - void q_omg_shallow_free_BinaryPropertySeq(DDS_Security_BinaryPropertySeq *obj); - void q_omg_shallow_copy_PropertyQosPolicy(DDS_Security_PropertyQosPolicy *dst, const dds_property_qospolicy_t *src); - void q_omg_shallow_copy_security_qos(DDS_Security_Qos *dst, const struct dds_qos *src); - void q_omg_shallow_free_PropertyQosPolicy(DDS_Security_PropertyQosPolicy *obj); - void q_omg_shallow_free_security_qos(DDS_Security_Qos *obj); - void q_omg_security_dataholder_copyin(nn_dataholder_t *dh, const DDS_Security_DataHolder *holder); - void q_omg_security_dataholder_copyout(DDS_Security_DataHolder *holder, const nn_dataholder_t *dh); - void q_omg_shallow_copyin_DataHolder(DDS_Security_DataHolder *dst, const nn_dataholder_t *src); - void q_omg_shallow_copyout_DataHolder(nn_dataholder_t *dst, const DDS_Security_DataHolder *src); - void q_omg_shallow_free_DataHolder(DDS_Security_DataHolder *obj); - void q_omg_shallow_free_nn_dataholder(nn_dataholder_t *holder); - void q_omg_shallow_copyin_DataHolderSeq(DDS_Security_DataHolderSeq *dst, const nn_dataholderseq_t *src); - void q_omg_copyin_DataHolderSeq(DDS_Security_DataHolderSeq *dst, const nn_dataholderseq_t *src); - void q_omg_shallow_copyout_DataHolderSeq(nn_dataholderseq_t *dst, const DDS_Security_DataHolderSeq *src); - void q_omg_shallow_free_DataHolderSeq(DDS_Security_DataHolderSeq *obj); - void q_omg_shallow_free_nn_dataholderseq(nn_dataholderseq_t *obj); - void q_omg_shallow_copy_ParticipantBuiltinTopicDataSecure(DDS_Security_ParticipantBuiltinTopicDataSecure *dst, const ddsi_guid_t *guid, const ddsi_plist_t *plist); - void q_omg_shallow_free_ParticipantBuiltinTopicDataSecure(DDS_Security_ParticipantBuiltinTopicDataSecure *obj); - void q_omg_shallow_copy_SubscriptionBuiltinTopicDataSecure(DDS_Security_SubscriptionBuiltinTopicDataSecure *dst, const ddsi_guid_t *guid, const struct dds_qos *qos, const nn_security_info_t *secinfo); - void q_omg_shallow_free_SubscriptionBuiltinTopicDataSecure(DDS_Security_SubscriptionBuiltinTopicDataSecure *obj); - void q_omg_shallow_copy_PublicationBuiltinTopicDataSecure(DDS_Security_PublicationBuiltinTopicDataSecure *dst, const ddsi_guid_t *guid, const struct dds_qos *qos, const nn_security_info_t *secinfo); - void q_omg_shallow_free_PublicationBuiltinTopicDataSecure(DDS_Security_PublicationBuiltinTopicDataSecure *obj); +void q_omg_shallow_copy_TopicBuiltinTopicData(DDS_Security_TopicBuiltinTopicData *dst, const char *topic_name, const char *type_name); +void q_omg_shallow_free_TopicBuiltinTopicData(DDS_Security_TopicBuiltinTopicData *obj); #if defined (__cplusplus) } diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index a6f6543..9d2765e 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -642,9 +642,8 @@ DDS_EXPORT struct writer *get_builtin_writer (const struct participant *pp, unsi GUID "ppguid". May return NULL if participant unknown or writer/reader already known. */ -dds_return_t new_writer (struct writer **wr_out, struct ddsi_domaingv *gv, struct ddsi_guid *wrguid, const struct ddsi_guid *group_guid, const struct ddsi_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg); - -dds_return_t new_reader (struct reader **rd_out, struct ddsi_domaingv *gv, struct ddsi_guid *rdguid, const struct ddsi_guid *group_guid, const struct ddsi_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct ddsi_rhc * rhc, status_cb_t status_cb, void *status_cb_arg); +dds_return_t new_writer (struct writer **wr_out, struct ddsi_guid *wrguid, const struct ddsi_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg); +dds_return_t new_reader (struct reader **rd_out, struct ddsi_guid *rdguid, const struct ddsi_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct ddsi_rhc * rhc, status_cb_t status_cb, void *status_cb_arg); void update_reader_qos (struct reader *rd, const struct dds_qos *xqos); void update_writer_qos (struct writer *wr, const struct dds_qos *xqos); diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index aae4ebf..c7f2b10 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -2136,7 +2136,8 @@ bool q_omg_security_check_remote_writer_permissions(const struct proxy_writer *p struct dds_security_context *sc = q_omg_security_get_secure_context(pp); DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; DDS_Security_PublicationBuiltinTopicDataSecure publication_data; - bool ok = true; + DDS_Security_TopicBuiltinTopicData topic_data; + bool result = true; if (!sc) return true; @@ -2167,19 +2168,32 @@ bool q_omg_security_check_remote_writer_permissions(const struct proxy_writer *p else { q_omg_shallow_copy_PublicationBuiltinTopicDataSecure(&publication_data, &pwr->e.guid, pwr->c.xqos, &pwr->c.security_info); - ok = sc->access_control_context->check_remote_datawriter(sc->access_control_context, permissions_handle, (int)domain_id, &publication_data, &exception); - q_omg_shallow_free_PublicationBuiltinTopicDataSecure(&publication_data); - if (!ok) + result = sc->access_control_context->check_remote_datawriter(sc->access_control_context, permissions_handle, (int)domain_id, &publication_data, &exception); + if (!result) { if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, publication_data.topic_name)) EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote writer "PGUIDFMT": %s", PGUID(pwr->e.guid)); else DDS_Security_Exception_reset(&exception); } + else + { + q_omg_shallow_copy_TopicBuiltinTopicData(&topic_data, publication_data.topic_name, publication_data.type_name); + result = sc->access_control_context->check_remote_topic(sc->access_control_context, permissions_handle, (int)domain_id, &topic_data, &exception); + q_omg_shallow_free_TopicBuiltinTopicData(&topic_data); + if (!result) + { + if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, publication_data.topic_name)) + EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote topic %s: %s", publication_data.topic_name); + else + DDS_Security_Exception_reset(&exception); + } + } + q_omg_shallow_free_PublicationBuiltinTopicDataSecure(&publication_data); } } - return ok; + return result; } static void send_reader_crypto_tokens(struct reader *rd, struct proxy_writer *pwr, DDS_Security_DatareaderCryptoHandle local_crypto, DDS_Security_DatawriterCryptoHandle remote_crypto) @@ -2363,7 +2377,10 @@ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *p 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; - bool ok = true; + DDS_Security_SubscriptionBuiltinTopicDataSecure subscription_data; + DDS_Security_TopicBuiltinTopicData topic_data; + DDS_Security_boolean sec_relay_only; + bool result = true; /* relay_only is meaningless in all cases except the one where the access control plugin says otherwise */ *relay_only = false; @@ -2396,25 +2413,34 @@ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *p } else { - DDS_Security_SubscriptionBuiltinTopicDataSecure subscription_data; - DDS_Security_boolean sec_relay_only; - q_omg_shallow_copy_SubscriptionBuiltinTopicDataSecure(&subscription_data, &prd->e.guid, prd->c.xqos, &prd->c.security_info); - ok = sc->access_control_context->check_remote_datareader(sc->access_control_context, permissions_handle, (int)domain_id, &subscription_data, &sec_relay_only, &exception); - q_omg_shallow_free_SubscriptionBuiltinTopicDataSecure(&subscription_data); - if (ok) - *relay_only = !!sec_relay_only; - else + result = sc->access_control_context->check_remote_datareader(sc->access_control_context, permissions_handle, (int)domain_id, &subscription_data, &sec_relay_only, &exception); + if (!result) { if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, subscription_data.topic_name)) EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote reader "PGUIDFMT": %s", PGUID(prd->e.guid)); else DDS_Security_Exception_reset(&exception); } + else + { + *relay_only = !!sec_relay_only; + q_omg_shallow_copy_TopicBuiltinTopicData(&topic_data, subscription_data.topic_name, subscription_data.type_name); + result = sc->access_control_context->check_remote_topic(sc->access_control_context, permissions_handle, (int)domain_id, &topic_data, &exception); + q_omg_shallow_free_TopicBuiltinTopicData(&topic_data); + if (!result) + { + if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, subscription_data.topic_name)) + EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote topic %s: %s", subscription_data.topic_name); + else + DDS_Security_Exception_reset(&exception); + } + } + q_omg_shallow_free_SubscriptionBuiltinTopicDataSecure(&subscription_data); } } - return ok; + return result; } void q_omg_get_proxy_endpoint_security_info(const struct entity_common *entity, nn_security_info_t *proxypp_sec_info, const ddsi_plist_t *plist, nn_security_info_t *info) diff --git a/src/core/ddsi/src/ddsi_security_util.c b/src/core/ddsi/src/ddsi_security_util.c index 388fb4e..11f39b5 100644 --- a/src/core/ddsi/src/ddsi_security_util.c +++ b/src/core/ddsi/src/ddsi_security_util.c @@ -703,6 +703,24 @@ q_omg_shallow_free_PublicationBuiltinTopicDataSecure( g_omg_shallow_free_StringSeq(&obj->partition.name); } +void +q_omg_shallow_copy_TopicBuiltinTopicData( + DDS_Security_TopicBuiltinTopicData *dst, + const char *topic_name, + const char *type_name) +{ + memset(dst, 0, sizeof(DDS_Security_TopicBuiltinTopicData)); + dst->name = (DDS_Security_string)topic_name; + dst->type_name = (DDS_Security_string)type_name; +} + +void +q_omg_shallow_free_TopicBuiltinTopicData( + DDS_Security_TopicBuiltinTopicData *obj) +{ + DDSRT_UNUSED_ARG(obj); +} + #endif /* DDSI_INCLUDE_SECURITY */ diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 2669c09..c1f4573 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -2771,6 +2771,7 @@ void connect_reader_with_proxy_writer_secure(struct reader *rd, struct proxy_wri static void connect_writer_with_proxy_reader (struct writer *wr, struct proxy_reader *prd, ddsrt_mtime_t tnow) { + struct ddsi_domaingv *gv = wr->e.gv; const int isb0 = (is_builtin_entityid (wr->e.guid.entityid, NN_VENDORID_ECLIPSE) != 0); const int isb1 = (is_builtin_entityid (prd->e.guid.entityid, prd->c.vendor) != 0); dds_qos_policy_id_t reason; @@ -2790,13 +2791,15 @@ static void connect_writer_with_proxy_reader (struct writer *wr, struct proxy_re if (!q_omg_security_check_remote_reader_permissions (prd, wr->e.gv->config.domainId, wr->c.pp, &relay_only)) { - EELOGDISC (&wr->e, "connect_writer_with_proxy_reader (wr "PGUIDFMT") with (prd "PGUIDFMT") not allowed by security\n", - PGUID (wr->e.guid), PGUID (prd->e.guid)); + GVLOGDISC ("connect_writer_with_proxy_reader (wr "PGUIDFMT") with (prd "PGUIDFMT") not allowed by security\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); + } + else if (relay_only) + { + GVWARNING ("connect_writer_with_proxy_reader (wr "PGUIDFMT") with (prd "PGUIDFMT") relay_only not supported\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); } else if (!q_omg_security_match_remote_reader_enabled (wr, prd, relay_only, &crypto_handle)) { - EELOGDISC (&wr->e, "connect_writer_with_proxy_reader (wr "PGUIDFMT") with (prd "PGUIDFMT") waiting for approval by security\n", - PGUID (wr->e.guid), PGUID (prd->e.guid)); + GVLOGDISC ("connect_writer_with_proxy_reader (wr "PGUIDFMT") with (prd "PGUIDFMT") waiting for approval by security\n", PGUID (wr->e.guid), PGUID (prd->e.guid)); } else { @@ -3801,28 +3804,11 @@ static dds_return_t new_writer_guid (struct writer **wr_out, const struct ddsi_g return 0; } -dds_return_t new_writer (struct writer **wr_out, struct ddsi_domaingv *gv, struct ddsi_guid *wrguid, const struct ddsi_guid *group_guid, const struct ddsi_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg) +dds_return_t new_writer (struct writer **wr_out, struct ddsi_guid *wrguid, const struct ddsi_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg) { - struct participant *pp; dds_return_t rc; uint32_t kind; - if ((pp = entidx_lookup_participant_guid (gv->entity_index, ppguid)) == NULL) - { - GVLOGDISC ("new_writer - participant "PGUIDFMT" not found\n", PGUID (*ppguid)); - return DDS_RETCODE_BAD_PARAMETER; - } - -#ifdef DDSI_INCLUDE_SECURITY - /* Check if DDS Security is enabled */ - if (q_omg_participant_is_secure (pp)) - { - /* ask to access control security plugin for create writer permissions */ - if (!q_omg_security_check_create_writer (pp, gv->config.domainId, topic->name, xqos)) - return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY; - } -#endif - /* participant can't be freed while we're mucking around cos we are awake and do not touch the thread's vtime (entidx_lookup already verifies we're awake) */ @@ -4367,10 +4353,9 @@ static dds_return_t new_reader_guid dds_return_t new_reader ( struct reader **rd_out, - struct ddsi_domaingv *gv, struct ddsi_guid *rdguid, const struct ddsi_guid *group_guid, - const struct ddsi_guid *ppguid, + struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct ddsi_rhc * rhc, @@ -4378,26 +4363,9 @@ dds_return_t new_reader void * status_cbarg ) { - struct participant * pp; dds_return_t rc; uint32_t kind; - if ((pp = entidx_lookup_participant_guid (gv->entity_index, ppguid)) == NULL) - { - GVLOGDISC ("new_reader - participant "PGUIDFMT" not found\n", PGUID (*ppguid)); - return DDS_RETCODE_BAD_PARAMETER; - } - -#ifdef DDSI_INCLUDE_SECURITY - /* Check if DDS Security is enabled */ - if (q_omg_participant_is_secure (pp)) - { - /* ask to access control security plugin for create writer permissions */ - if (!q_omg_security_check_create_reader (pp, gv->config.domainId, topic->name, xqos)) - return DDS_RETCODE_NOT_ALLOWED_BY_SECURITY; - } -#endif - rdguid->prefix = pp->e.guid.prefix; kind = topic->topickind_no_key ? NN_ENTITYID_KIND_READER_NO_KEY : NN_ENTITYID_KIND_READER_WITH_KEY; if ((rc = pp_allocate_entityid (&rdguid->entityid, kind, pp)) < 0) diff --git a/src/security/api/include/dds/security/dds_security_api.h b/src/security/api/include/dds/security/dds_security_api.h index 55ab6a0..d242b02 100644 --- a/src/security/api/include/dds/security/dds_security_api.h +++ b/src/security/api/include/dds/security/dds_security_api.h @@ -25,7 +25,7 @@ extern "C" { /* Integration functions for Security plugins */ typedef int (*plugin_init)(const char *argument, void **context, struct ddsi_domaingv *gv); -typedef int (*plugin_finalize)(void *context); +typedef int (*plugin_finalize)(void *context); #if defined (__cplusplus) } diff --git a/src/security/core/tests/CMakeLists.txt b/src/security/core/tests/CMakeLists.txt index 35337ab..299487e 100644 --- a/src/security/core/tests/CMakeLists.txt +++ b/src/security/core/tests/CMakeLists.txt @@ -68,7 +68,7 @@ set(security_core_test_sources ) if(ENABLE_SSL) - add_wrapper(access_control "") + add_wrapper(access_control dds_security_ac) add_wrapper(authentication dds_security_auth) add_wrapper(cryptography dds_security_crypto) @@ -108,7 +108,7 @@ configure_file("common/config_env.h.in" "common/config_env.h") target_link_libraries(cunit_security_core PRIVATE ddsc security_api SecurityCoreTests) if(ENABLE_SSL) - target_link_libraries(cunit_security_core PRIVATE dds_security_auth dds_security_ac dds_security_crypto dds_security_authentication_wrapper dds_security_cryptography_wrapper) + target_link_libraries(cunit_security_core PRIVATE dds_security_auth dds_security_ac dds_security_crypto dds_security_access_control_wrapper dds_security_authentication_wrapper dds_security_cryptography_wrapper) target_link_libraries(cunit_security_core PRIVATE OpenSSL::SSL) endif() target_include_directories(cunit_security_core PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index 9fdf1ae..3b04fc6 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -47,13 +47,13 @@ static const char *config = " " " " " " - " " + " " " data:,${TEST_IDENTITY_CERTIFICATE}" " data:,${TEST_IDENTITY_PRIVATE_KEY}" " data:,${TEST_IDENTITY_CA_CERTIFICATE}" " " " " - " " + " " " ${INCL_GOV:+}" " ${INCL_PERM_CA:+}${TEST_PERMISSIONS_CA}${INCL_PERM_CA:+}" " ${INCL_PERM:+}" @@ -65,19 +65,22 @@ static const char *config = ""; #define MAX_DOMAINS 10 -#define DDS_DOMAINID +#define DDS_DOMAINID 0 + +#define PF_F "file:" +#define PF_D "data:," static dds_entity_t g_domain[MAX_DOMAINS]; static dds_entity_t g_participant[MAX_DOMAINS]; -static dds_entity_t g_pubsub[MAX_DOMAINS]; -static dds_entity_t g_topic[MAX_DOMAINS]; static uint32_t g_topic_nr = 0; static void access_control_init( - const char * id_certs[], const char * id_keys[], const char * id_ca[], bool exp_pp_fail[], size_t n_nodes, - bool incl_gov, const char * gov, - bool incl_perm, const char * perm, - bool incl_ca, const char * ca) + size_t n_nodes, + const char * id_certs[], const char * id_keys[], const char * id_ca[], bool exp_pp_fail[], + const char * ac_init_fns[], const char * ac_fini_fns[], + bool incl_gov[], const char * gov[], + bool incl_perm[], const char * perm[], + bool incl_ca[], const char * ca[]) { CU_ASSERT_FATAL (n_nodes <= MAX_DOMAINS); for (size_t i = 0; i < n_nodes; i++) @@ -86,12 +89,14 @@ static void access_control_init( { "TEST_IDENTITY_CERTIFICATE", id_certs[i], 1 }, { "TEST_IDENTITY_PRIVATE_KEY", id_keys[i], 1 }, { "TEST_IDENTITY_CA_CERTIFICATE", id_ca[i], 1 }, - { "INCL_GOV", incl_gov ? "1" : "", 2 }, - { "INCL_PERM", incl_perm ? "1" : "", 2 }, - { "INCL_PERM_CA", incl_ca ? "1" : "", 2 }, - { "TEST_GOVERNANCE", gov, 1 }, - { "TEST_PERMISSIONS", perm, 1 }, - { "TEST_PERMISSIONS_CA", ca, 1 }, + { "ACCESS_CONTROL_INIT", ac_init_fns ? ac_init_fns[i] : NULL, 1 }, + { "ACCESS_CONTROL_FINI", ac_fini_fns ? ac_fini_fns[i] : NULL, 1 }, + { "INCL_GOV", incl_gov[i] ? "1" : "", 2 }, + { "INCL_PERM", incl_perm[i] ? "1" : "", 2 }, + { "INCL_PERM_CA", incl_ca[i] ? "1" : "", 2 }, + { "TEST_GOVERNANCE", gov[i], 1 }, + { "TEST_PERMISSIONS", perm[i], 1 }, + { "TEST_PERMISSIONS_CA", ca[i], 1 }, { NULL, NULL, 0 } }; char *conf = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars); @@ -109,9 +114,6 @@ static void access_control_fini(size_t n) CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain[i]), DDS_RETCODE_OK); } - -#define PF_F "file:" -#define PF_D "data:," #define GOV_F PF_F COMMON_ETC_PATH("default_governance.p7s") #define GOV_FNE PF_F COMMON_ETC_PATH("default_governance_non_existing.p7s") #define GOV_DI PF_D COMMON_ETC_PATH("default_governance.p7s") @@ -149,14 +151,18 @@ CU_Theory((const char * test_descr, const char * gov, const char * perm, const c ddssec_access_control, config_parameters_file) { print_test_msg ("running test config_parameters_file: %s\n", test_descr); + bool has_gov = incl_empty_els || strlen (gov); + bool has_perm = incl_empty_els || strlen (perm); + bool has_ca = incl_empty_els || strlen (ca); access_control_init ( + 2, (const char *[]) { TEST_IDENTITY1_CERTIFICATE, TEST_IDENTITY1_CERTIFICATE }, (const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY }, (const char *[]) { TEST_IDENTITY_CA1_CERTIFICATE, TEST_IDENTITY_CA1_CERTIFICATE }, - (bool []) { exp_fail, exp_fail }, 2, - incl_empty_els || strlen (gov), gov, - incl_empty_els || strlen (perm), perm, - incl_empty_els || strlen (ca), ca); + (bool []) { exp_fail, exp_fail }, NULL, NULL, + (bool []) { has_gov, has_gov }, (const char *[]) { gov, gov }, + (bool []) { has_perm, has_perm }, (const char *[]) { perm, perm }, + (bool []) { has_ca, has_ca }, (const char *[]) { ca, ca }); access_control_fini (2); } @@ -170,8 +176,8 @@ CU_TheoryDataPoints(ddssec_access_control, permissions_expiry) = { /* | */"valid -1 minute until now", /* | | */"1s valid, create pp after 1100ms", /* | | | */"node 2 permissions expired", - /* | | | | */"node 1 3s valid, write/read for 10s", - /* | | | | | */"node 2 3s valid, write/read for 10s"), + /* | | | | */"node 1 4s valid, write/read for 10s", + /* | | | | | */"node 2 4s valid, write/read for 10s"), CU_DataPoints(int32_t, 0, -M(1), 0, 0, 0, 0), /* node 1 permissions not before (offset from local time) */ CU_DataPoints(int32_t, M(1), 0, S(1), D(1), S(4), D(1)), /* node 1 permissions not after (offset from local time) */ CU_DataPoints(int32_t, 0, -M(1), 0, -D(1), 0, 0), /* node 2 permissions not before (offset from local time) */ @@ -179,14 +185,18 @@ CU_TheoryDataPoints(ddssec_access_control, permissions_expiry) = { CU_DataPoints(uint32_t, 0, 0, 1100, 0, 0, 0), /* delay (ms) after generating permissions */ CU_DataPoints(bool, false, true, true, false, false, false), /* expect pp 1 create failure */ CU_DataPoints(bool, false, true, true, true, false, false), /* expect pp 2 create failure */ - CU_DataPoints(uint32_t, 1, 0, 0, 0, 10000, 10000), /* write/read data during x ms */ + CU_DataPoints(uint32_t, 1, 0, 0, 0, 10000, 10000), /* write/read data during x ms */ CU_DataPoints(bool, false, false, false, false, true, true), /* expect read data failure */ }; +#undef S +#undef D +#undef H +#undef M CU_Theory( (const char * test_descr, int32_t perm1_not_before, int32_t perm1_not_after, int32_t perm2_not_before, int32_t perm2_not_after, uint32_t delay_perm, bool exp_pp1_fail, bool exp_pp2_fail, uint32_t write_read_dur, bool exp_read_fail), - ddssec_access_control, permissions_expiry, .timeout=20) + ddssec_access_control, permissions_expiry, .timeout=30) { print_test_msg ("running test permissions_expiry: %s\n", test_descr); @@ -195,32 +205,38 @@ CU_Theory( /* create ca and id1/id2 certs that will not expire during this test */ char *ca, *id1, *id2, *id1_subj, *id2_subj; - ca = generate_ca ("ca1", TEST_IDENTITY_CA1_PRIVATE_KEY, 0, D(1)); - id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, D(1), &id1_subj); - id2 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id2", TEST_IDENTITY1_PRIVATE_KEY, 0, D(1), &id2_subj); + ca = generate_ca ("ca1", TEST_IDENTITY_CA1_PRIVATE_KEY, 0, 3600); + id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id1_subj); + id2 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id2", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id2_subj); /* localtime will be converted to gmtime in get_permissions_grant */ dds_time_t now = dds_time (); char * perm_topic = get_permissions_topic (topic_name); char * grants[] = { - get_permissions_grant ("id1", id1_subj, now + DDS_SECS(perm1_not_before), now + DDS_SECS(perm1_not_after), perm_topic, perm_topic, NULL), - get_permissions_grant ("id2", id2_subj, now + DDS_SECS(perm2_not_before), now + DDS_SECS(perm2_not_after), perm_topic, perm_topic, NULL) }; + get_permissions_grant ("id1", id1_subj, NULL, now + DDS_SECS(perm1_not_before), now + DDS_SECS(perm1_not_after), perm_topic, perm_topic, NULL), + get_permissions_grant ("id2", id2_subj, NULL, now + DDS_SECS(perm2_not_before), now + DDS_SECS(perm2_not_after), perm_topic, perm_topic, NULL) }; char * perm_config = get_permissions_config (grants, 2, true); dds_sleepfor (DDS_MSECS (delay_perm)); + const char * def_gov = PF_F COMMON_ETC_PATH("default_governance.p7s"); + const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); access_control_init ( + 2, (const char *[]) { id1, id2 }, (const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY }, (const char *[]) { ca, ca }, - (bool []) { exp_pp1_fail, exp_pp2_fail }, 2, - true, PF_F COMMON_ETC_PATH("default_governance.p7s"), - true, perm_config, - true, PF_F COMMON_ETC_PATH("default_permissions_ca.pem")); + (bool []) { exp_pp1_fail, exp_pp2_fail }, NULL, NULL, + (bool []) { true, true }, (const char *[]) { def_gov, def_gov }, + (bool []) { true, true }, (const char *[]) { perm_config, perm_config }, + (bool []) { true, true }, (const char *[]) { def_perm_ca, def_perm_ca }); if (write_read_dur > 0) { dds_entity_t wr = 0, rd = 0; - rd_wr_init (g_participant[0], &g_pubsub[0], &g_topic[0], &wr, g_participant[1], &g_pubsub[1], &g_topic[1], &rd, topic_name); + dds_entity_t pub, sub; + dds_entity_t topic0, topic1; + rd_wr_init (g_participant[0], &pub, &topic0, &wr, g_participant[1], &sub, &topic1, &rd, topic_name); + sync_writer_to_readers(g_participant[0], wr, 1); write_read_for (wr, g_participant[1], rd, DDS_MSECS (write_read_dur), false, exp_read_fail); } @@ -236,9 +252,6 @@ CU_Theory( ddsrt_free (id1); ddsrt_free (id2); } -#undef D -#undef H -#undef M #define N_RD 1 // N_RD > 1 not yet implemented @@ -256,9 +269,10 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) // 1st node used as reader, other nodes as writer print_test_msg ("creating permissions grants\n"); - const char *id[N_NODES], *pk[N_NODES], *ca_list[N_NODES]; + const char *id[N_NODES], *pk[N_NODES], *ca_list[N_NODES], *gov[N_NODES], *perm_conf[N_NODES], *perm_ca[N_NODES]; char * id_subj[N_NODES], *grants[N_NODES]; - bool exp_fail[N_NODES]; + bool exp_fail[N_NODES], incl_el[N_NODES]; + for (int i = 0; i < N_NODES; i++) { char *id_name; @@ -267,20 +281,25 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) ca_list[i] = ca; id[i] = generate_identity (ca_list[i], TEST_IDENTITY_CA1_PRIVATE_KEY, id_name, pk[i], 0, 3600, &id_subj[i]); exp_fail[i] = false; + gov[i] = PF_F COMMON_ETC_PATH ("default_governance.p7s"); + perm_ca[i] = PF_F COMMON_ETC_PATH ("default_permissions_ca.pem"); + incl_el[i] = true; dds_duration_t v = DDS_SECS(i < N_RD ? 3600 : PERM_EXP_BASE + 2 * i); /* readers should not expire */ dds_time_t t_exp = ddsrt_time_add_duration (t_perm, v); if (i >= N_RD) print_test_msg ("w[%d] grant expires at %d.%06d\n", i - N_RD, (int32_t) (t_exp / DDS_NSECS_IN_SEC), (int32_t) (t_exp % DDS_NSECS_IN_SEC) / 1000); - grants[i] = get_permissions_grant (id_name, id_subj[i], t_perm, t_exp, perm_topic, perm_topic, NULL); + grants[i] = get_permissions_grant (id_name, id_subj[i], NULL, t_perm, t_exp, perm_topic, perm_topic, NULL); ddsrt_free (id_name); } - char * perm_config = get_permissions_config (grants, N_NODES, true); + char * perm_config_str = get_permissions_config (grants, N_NODES, true); + for (int i = 0; i < N_NODES; i++) + perm_conf[i] = perm_config_str; + access_control_init ( - id, pk, ca_list, exp_fail, N_NODES, - true, PF_F COMMON_ETC_PATH ("default_governance.p7s"), - true, perm_config, - true, PF_F COMMON_ETC_PATH ("default_permissions_ca.pem")); + N_NODES, + id, pk, ca_list, exp_fail, NULL, NULL, + incl_el, gov, incl_el, perm_conf, incl_el, perm_ca); dds_qos_t * qos = dds_create_qos (); CU_ASSERT_FATAL (qos != NULL); @@ -374,6 +393,156 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) } ddsrt_free (ca); ddsrt_free (perm_topic); - ddsrt_free (perm_config); + ddsrt_free (perm_config_str); } +#undef N_RD +#undef N_WR #undef N_NODES +#undef PERM_EXP_BASE + +#define na false +CU_TheoryDataPoints(ddssec_access_control, hooks) = { + CU_DataPoints(const char *, + /* */"init_test_access_control_local_participant_not_allowed", + /* | */"init_test_access_control_local_topic_not_allowed", + /* | | */"init_test_access_control_local_publishing_not_allowed", + /* | | | */"init_test_access_control_local_subscribing_not_allowed", + /* | | | | */"init_test_access_control_remote_permissions_invalidate", + /* | | | | | */"init_test_access_control_remote_participant_not_allowed", + /* | | | | | | */"init_test_access_control_remote_topic_not_allowed", + /* | | | | | | | */"init_test_access_control_remote_writer_not_allowed", + /* | | | | | | | | */"init_test_access_control_remote_reader_not_allowed", + /* | | | | | | | | | */"init_test_access_control_remote_reader_relay_only"), + CU_DataPoints(bool, true, false, false, false, false, false, false, false, false, false), // exp_pp_fail + CU_DataPoints(bool, na, true, false, false, false, false, false, false, false, false), // exp_local_topic_fail + CU_DataPoints(bool, na, false, false, false, false, false, false, false, false, false), // exp_remote_topic_fail + CU_DataPoints(bool, na, na, true, false, false, false, false, false, false, false), // exp_wr_fail + CU_DataPoints(bool, na, na, false, true, false, false, false, false, false, false), // exp_rd_fail + CU_DataPoints(bool, na, na, na, na, true, true, true, false, true, true), // exp_wr_rd_sync_fail + CU_DataPoints(bool, na, na, false, na, true, true, true, true, false, false), // exp_rd_wr_sync_fail +}; +#undef na +CU_Theory( + (const char * init_fn, bool exp_pp_fail, bool exp_local_topic_fail, bool exp_remote_topic_fail, bool exp_wr_fail, bool exp_rd_fail, bool exp_wr_rd_sync_fail, bool exp_rd_wr_sync_fail), + ddssec_access_control, hooks, .timeout=40) +{ + print_test_msg ("running test access_control_hooks: %s\n", init_fn); + + const char * def_gov = PF_F COMMON_ETC_PATH("default_governance.p7s"); + const char * def_perm = PF_F COMMON_ETC_PATH("default_permissions.p7s"); + const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); + + access_control_init ( + 2, + (const char *[]) { TEST_IDENTITY1_CERTIFICATE, TEST_IDENTITY1_CERTIFICATE }, + (const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY }, + (const char *[]) { TEST_IDENTITY_CA1_CERTIFICATE, TEST_IDENTITY_CA1_CERTIFICATE }, + (bool []) { exp_pp_fail, false }, + (const char *[]) { init_fn, "init_test_access_control_wrapped" }, (const char *[]) { "finalize_test_access_control_not_allowed", "finalize_test_access_control_wrapped" }, + (bool []) { true, true, true }, (const char *[]) { def_gov, def_gov }, + (bool []) { true, true, true }, (const char *[]) { def_perm, def_perm }, + (bool []) { true, true, true }, (const char *[]) { def_perm_ca, def_perm_ca }); + + if (!exp_pp_fail) + { + dds_entity_t lwr = 0, rwr = 0, lrd = 0, rrd = 0; + dds_entity_t ltopic[2], rtopic[2]; + dds_entity_t lpub, lsub, rpub, rsub; + char topic_name[100]; + + // Local writer, remote reader + create_topic_name (AC_WRAPPER_TOPIC_PREFIX, g_topic_nr++, topic_name, sizeof (topic_name)); + rd_wr_init_fail ( + g_participant[0], &lpub, <opic[0], &lwr, + g_participant[1], &rsub, &rtopic[0], &rrd, + topic_name, exp_local_topic_fail, exp_wr_fail, exp_remote_topic_fail, false); + if (!exp_local_topic_fail && !exp_remote_topic_fail && !exp_wr_fail) + sync_writer_to_readers (g_participant[0], lwr, exp_wr_rd_sync_fail ? 0 : 1); + + // Local reader, remote writer + create_topic_name (AC_WRAPPER_TOPIC_PREFIX, g_topic_nr++, topic_name, sizeof (topic_name)); + rd_wr_init_fail ( + g_participant[1], &rpub, &rtopic[1], &rwr, + g_participant[0], &lsub, <opic[1], &lrd, + topic_name, exp_remote_topic_fail, false, exp_local_topic_fail, exp_rd_fail); + if (!exp_local_topic_fail && !exp_remote_topic_fail && !exp_rd_fail) + sync_reader_to_writers (g_participant[0], lrd, exp_rd_wr_sync_fail ? 0 : 1); + } + + access_control_fini (2); +} + +#define na false +CU_TheoryDataPoints(ddssec_access_control, join_access_control) = { + CU_DataPoints(const char *, + /* */"no join access control", + /* | */"join access control pp1, valid", + /* | | */"join access control pp1 and pp2, valid", + /* | | | */"join access control pp1, invalid", + /* | | | | */"join access control pp1 and pp2, invalid"), + CU_DataPoints(bool, false, true, true, true, true), /* join access control pp 1 enabled */ + CU_DataPoints(bool, false, false, true, false, true), /* join access control pp 2 enabled */ + CU_DataPoints(bool, false, false, false, true, true), /* permissions pp 1 invalid */ + CU_DataPoints(bool, false, false, false, false, true), /* permissions pp 2 invalid */ + CU_DataPoints(bool, false, false, false, true, true), /* expect pp 1 create failure */ + CU_DataPoints(bool, false, false, false, false, true), /* expect pp 2 create failure */ + CU_DataPoints(bool, false, false, false, na, na), /* expect handshake failure */ +}; +#undef na +CU_Theory( + (const char * test_descr, bool join_ac_pp1, bool join_ac_pp2, bool perm_inv_pp1, bool perm_inv_pp2, bool exp_pp1_fail, bool exp_pp2_fail, bool exp_hs_fail), + ddssec_access_control, join_access_control, .timeout=30) +{ + print_test_msg ("running test join_access_control: %s\n", test_descr); + + char topic_name[100]; + create_topic_name ("ddssec_access_control_", g_topic_nr++, topic_name, sizeof (topic_name)); + + /* create ca and id1/id2 certs that will not expire during this test */ + char *ca, *id1, *id2, *id1_subj, *id2_subj; + ca = generate_ca ("ca1", TEST_IDENTITY_CA1_PRIVATE_KEY, 0, 3600); + id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id1_subj); + id2 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id2", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id2_subj); + + /* localtime will be converted to gmtime in get_permissions_grant */ + dds_time_t now = dds_time (); + char * perm_topic = get_permissions_topic (topic_name); + char * grants[] = { + get_permissions_grant ("id1", id1_subj, perm_inv_pp1 ? "99" : NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL), + get_permissions_grant ("id2", id2_subj, perm_inv_pp2 ? "99" : NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL) }; + char * perm_config = get_permissions_config (grants, 2, true); + + struct kvp governance_vars_pp1[] = { { "ENABLE_JOIN_AC", join_ac_pp1 ? "true" : "false", 1 }, { NULL, NULL, 0 } }; + struct kvp governance_vars_pp2[] = { { "ENABLE_JOIN_AC", join_ac_pp2 ? "true" : "false", 1 }, { NULL, NULL, 0 } }; + + char * gov_config_pp1 = get_governance_config (governance_vars_pp1, true); + char * gov_config_pp2 = get_governance_config (governance_vars_pp2, true); + const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); + + access_control_init ( + 2, + (const char *[]) { id1, id2 }, + (const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY }, + (const char *[]) { ca, ca }, + (bool []) { exp_pp1_fail, exp_pp2_fail }, NULL, NULL, + (bool []) { true, true }, (const char *[]) { gov_config_pp1, gov_config_pp2 }, + (bool []) { true, true }, (const char *[]) { perm_config, perm_config }, + (bool []) { true, true }, (const char *[]) { def_perm_ca, def_perm_ca }); + + if (!exp_pp1_fail && !exp_pp2_fail) + validate_handshake (DDS_DOMAINID, exp_hs_fail, NULL, NULL, NULL); + + access_control_fini (2); + + ddsrt_free (gov_config_pp1); + ddsrt_free (gov_config_pp2); + ddsrt_free (perm_topic); + ddsrt_free (grants[0]); + ddsrt_free (grants[1]); + ddsrt_free (perm_config); + ddsrt_free (ca); + ddsrt_free (id1_subj); + ddsrt_free (id2_subj); + ddsrt_free (id1); + ddsrt_free (id2); +} diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index 7a9a21a..fe6aa6a 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -309,8 +309,8 @@ CU_Theory( dds_time_t now = dds_time (); char * grants[] = { - get_permissions_grant ("id1", id1_subj, now - DDS_SECS(D(1)), now + DDS_SECS(D(1)), NULL, NULL, NULL), - get_permissions_grant ("id2", id2_subj, now - DDS_SECS(D(1)), now + DDS_SECS(D(1)), NULL, NULL, NULL) }; + get_permissions_grant ("id1", id1_subj, NULL, now - DDS_SECS(D(1)), now + DDS_SECS(D(1)), NULL, NULL, NULL), + get_permissions_grant ("id2", id2_subj, NULL, now - DDS_SECS(D(1)), now + DDS_SECS(D(1)), NULL, NULL, NULL) }; char * perm_config = get_permissions_config (grants, 2, true); authentication_init (id1, ID1K, ca, id2, ID1K, ca, NULL, perm_config, id1_local_fail, id2_local_fail); validate_handshake (DDS_DOMAINID1, id1_local_fail, NULL, NULL, NULL); @@ -318,6 +318,7 @@ CU_Theory( if (write_read_dur > 0) { rd_wr_init (g_participant1, &g_pub, &g_pub_tp, &g_wr, g_participant2, &g_sub, &g_sub_tp, &g_rd, topic_name); + sync_writer_to_readers(g_participant1, g_wr, 1); write_read_for (g_wr, g_participant2, g_rd, DDS_MSECS (write_read_dur), false, exp_read_fail); } authentication_fini (!id1_local_fail, !id2_local_fail); diff --git a/src/security/core/tests/common/access_control_wrapper.c b/src/security/core/tests/common/access_control_wrapper.c index 3ba5b68..aead7e6 100644 --- a/src/security/core/tests/common/access_control_wrapper.c +++ b/src/security/core/tests/common/access_control_wrapper.c @@ -20,18 +20,49 @@ #include "dds/security/core/dds_security_utils.h" #include "access_control_wrapper.h" +int init_access_control(const char *argument, void **context, struct ddsi_domaingv *gv); +int finalize_access_control(void *context); + enum ac_plugin_mode { PLUGIN_MODE_ALL_OK, + PLUGIN_MODE_WRAPPED, + PLUGIN_MODE_NOT_ALLOWED, PLUGIN_MODE_MISSING_FUNC }; +enum ac_plugin_not_allowed { + NOT_ALLOWED_ID_LOCAL_PP, + NOT_ALLOWED_ID_LOCAL_TOPIC, + NOT_ALLOWED_ID_LOCAL_PUB, + NOT_ALLOWED_ID_LOCAL_SUB, + NOT_ALLOWED_ID_REMOTE_PERM, + NOT_ALLOWED_ID_REMOTE_PP, + NOT_ALLOWED_ID_REMOTE_TOPIC, + NOT_ALLOWED_ID_REMOTE_WRITER, + NOT_ALLOWED_ID_REMOTE_READER, + NOT_ALLOWED_ID_REMOTE_READER_RELAY_ONLY +}; + +#define NOT_ALLOWED_LOCAL_PP (1u << NOT_ALLOWED_ID_LOCAL_PP) +#define NOT_ALLOWED_LOCAL_TOPIC (1u << NOT_ALLOWED_ID_LOCAL_TOPIC) +#define NOT_ALLOWED_LOCAL_PUB (1u << NOT_ALLOWED_ID_LOCAL_PUB) +#define NOT_ALLOWED_LOCAL_SUB (1u << NOT_ALLOWED_ID_LOCAL_SUB) +#define NOT_ALLOWED_REMOTE_PERM (1u << NOT_ALLOWED_ID_REMOTE_PERM) +#define NOT_ALLOWED_REMOTE_PP (1u << NOT_ALLOWED_ID_REMOTE_PP) +#define NOT_ALLOWED_REMOTE_TOPIC (1u << NOT_ALLOWED_ID_REMOTE_TOPIC) +#define NOT_ALLOWED_REMOTE_WRITER (1u << NOT_ALLOWED_ID_REMOTE_WRITER) +#define NOT_ALLOWED_REMOTE_READER (1u << NOT_ALLOWED_ID_REMOTE_READER) +#define NOT_ALLOWED_REMOTE_READER_RELAY_ONLY (1u << NOT_ALLOWED_ID_REMOTE_READER_RELAY_ONLY) + /** * Implementation structure for storing encapsulated members of the instance * while giving only the interface definition to user */ struct dds_security_access_control_impl { dds_security_access_control base; + dds_security_access_control *instance; enum ac_plugin_mode mode; + uint32_t not_allowed_mask; }; static DDS_Security_PermissionsHandle validate_local_permissions( @@ -42,14 +73,16 @@ static DDS_Security_PermissionsHandle validate_local_permissions( const DDS_Security_Qos *participant_qos, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(auth_plugin); - DDSRT_UNUSED_ARG(auth_plugin); - DDSRT_UNUSED_ARG(identity); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(participant_qos); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return 1; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->validate_local_permissions(impl->instance, auth_plugin, identity, domain_id, participant_qos, ex); + + default: + return 1; + } } static DDS_Security_PermissionsHandle validate_remote_permissions( @@ -61,31 +94,54 @@ static DDS_Security_PermissionsHandle validate_remote_permissions( const DDS_Security_AuthenticatedPeerCredentialToken *remote_credential_token, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(auth_plugin); - DDSRT_UNUSED_ARG(local_identity_handle); - DDSRT_UNUSED_ARG(remote_identity_handle); - DDSRT_UNUSED_ARG(remote_permissions_token); - DDSRT_UNUSED_ARG(remote_credential_token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return 0; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_NOT_ALLOWED: + if (impl->not_allowed_mask & NOT_ALLOWED_REMOTE_PERM) + { + ex->code = 1; + ex->message = ddsrt_strdup ("not_allowed: validate_remote_permissions"); + return 0; + } + /* fall through */ + case PLUGIN_MODE_WRAPPED: + return impl->instance->validate_remote_permissions(impl->instance, auth_plugin, local_identity_handle, remote_identity_handle, + remote_permissions_token, remote_credential_token, ex); + + default: + return 0; + } } -static DDS_Security_boolean check_create_participant( dds_security_access_control *instance, +static DDS_Security_boolean check_create_participant( + dds_security_access_control *instance, const DDS_Security_PermissionsHandle permissions_handle, const DDS_Security_DomainId domain_id, const DDS_Security_Qos *participant_qos, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(participant_qos); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_NOT_ALLOWED: + if (impl->not_allowed_mask & NOT_ALLOWED_LOCAL_PP) + { + ex->code = 1; + ex->message = ddsrt_strdup ("not_allowed: check_create_participant"); + return false; + } + /* fall through */ + case PLUGIN_MODE_WRAPPED: + return impl->instance->check_create_participant(impl->instance, permissions_handle, domain_id, participant_qos, ex); + + default: + return true; + } } -static DDS_Security_boolean check_create_datawriter( dds_security_access_control *instance, +static DDS_Security_boolean check_create_datawriter( + dds_security_access_control *instance, const DDS_Security_PermissionsHandle permissions_handle, const DDS_Security_DomainId domain_id, const char *topic_name, @@ -94,18 +150,30 @@ static DDS_Security_boolean check_create_datawriter( dds_security_access_control const DDS_Security_DataTags *data_tag, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(writer_qos); - DDSRT_UNUSED_ARG(partition); - DDSRT_UNUSED_ARG(data_tag); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_NOT_ALLOWED: + if (impl->not_allowed_mask & NOT_ALLOWED_LOCAL_PUB) + { + if (topic_name && strncmp (topic_name, AC_WRAPPER_TOPIC_PREFIX, strlen (AC_WRAPPER_TOPIC_PREFIX)) == 0) + { + ex->code = 1; + ex->message = ddsrt_strdup ("not_allowed: check_create_datawriter"); + return false; + } + } + /* fall through */ + case PLUGIN_MODE_WRAPPED: + return impl->instance->check_create_datawriter(impl->instance, permissions_handle, domain_id, topic_name, writer_qos, partition, data_tag, ex); + + default: + return true; + } } -static DDS_Security_boolean check_create_datareader( dds_security_access_control *instance, +static DDS_Security_boolean check_create_datareader( + dds_security_access_control *instance, const DDS_Security_PermissionsHandle permissions_handle, const DDS_Security_DomainId domain_id, const char *topic_name, @@ -114,31 +182,50 @@ static DDS_Security_boolean check_create_datareader( dds_security_access_control const DDS_Security_DataTags *data_tag, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(reader_qos); - DDSRT_UNUSED_ARG(partition); - DDSRT_UNUSED_ARG(data_tag); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_NOT_ALLOWED: + if (impl->not_allowed_mask & NOT_ALLOWED_LOCAL_SUB) + { + ex->code = 1; + ex->message = ddsrt_strdup ("not_allowed: check_create_datareader"); + return false; + } + /* fall through */ + case PLUGIN_MODE_WRAPPED: + return impl->instance->check_create_datareader(impl->instance, permissions_handle, domain_id, topic_name, reader_qos, partition, data_tag, ex); + + default: + return true; + } } -static DDS_Security_boolean check_create_topic( dds_security_access_control *instance, +static DDS_Security_boolean check_create_topic( + dds_security_access_control *instance, const DDS_Security_PermissionsHandle permissions_handle, const DDS_Security_DomainId domain_id, const char *topic_name, const DDS_Security_Qos *qos, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(qos); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_NOT_ALLOWED: + if (impl->not_allowed_mask & NOT_ALLOWED_LOCAL_TOPIC) + { + ex->code = 1; + ex->message = ddsrt_strdup ("not_allowed: check_create_topic"); + return false; + } + /* fall through */ + case PLUGIN_MODE_WRAPPED: + return impl->instance->check_create_topic(impl->instance, permissions_handle, domain_id, topic_name, qos, ex); + + default: + return true; + } } static DDS_Security_boolean check_local_datawriter_register_instance( @@ -148,12 +235,16 @@ static DDS_Security_boolean check_local_datawriter_register_instance( const DDS_Security_DynamicData *key, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(writer); - DDSRT_UNUSED_ARG(key); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->check_local_datawriter_register_instance(impl->instance, permissions_handle, writer, key, ex); + + default: + return true; + } } static DDS_Security_boolean check_local_datawriter_dispose_instance( @@ -163,69 +254,137 @@ static DDS_Security_boolean check_local_datawriter_dispose_instance( const DDS_Security_DynamicData key, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(writer); - DDSRT_UNUSED_ARG(key); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->check_local_datawriter_dispose_instance(impl->instance, permissions_handle, writer, key, ex); + + default: + return true; + } } -static DDS_Security_boolean check_remote_participant( dds_security_access_control *instance, +static DDS_Security_boolean check_remote_participant( + dds_security_access_control *instance, const DDS_Security_PermissionsHandle permissions_handle, const DDS_Security_DomainId domain_id, const DDS_Security_ParticipantBuiltinTopicDataSecure *participant_data, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(participant_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_NOT_ALLOWED: + if (impl->not_allowed_mask & NOT_ALLOWED_REMOTE_PP) + { + ex->code = 1; + ex->message = ddsrt_strdup ("not_allowed: check_remote_participant"); + return false; + } + /* fall through */ + case PLUGIN_MODE_WRAPPED: + return impl->instance->check_remote_participant(impl->instance, permissions_handle, domain_id, participant_data, ex); + + default: + return true; + } } -static DDS_Security_boolean check_remote_datawriter( dds_security_access_control *instance, +static DDS_Security_boolean check_remote_datawriter( + dds_security_access_control *instance, const DDS_Security_PermissionsHandle permissions_handle, const DDS_Security_DomainId domain_id, const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(publication_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_NOT_ALLOWED: + if (impl->not_allowed_mask & NOT_ALLOWED_REMOTE_WRITER) + { + ex->code = 1; + ex->message = ddsrt_strdup ("not_allowed: check_remote_datawriter"); + return false; + } + /* fall through */ + case PLUGIN_MODE_WRAPPED: + return impl->instance->check_remote_datawriter(impl->instance, permissions_handle, domain_id, publication_data, ex); + + default: + return true; + } } -static DDS_Security_boolean check_remote_datareader( dds_security_access_control *instance, +static DDS_Security_boolean check_remote_datareader( + dds_security_access_control *instance, const DDS_Security_PermissionsHandle permissions_handle, const DDS_Security_DomainId domain_id, const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, - DDS_Security_boolean *relay_only, DDS_Security_SecurityException *ex) + DDS_Security_boolean *relay_only, + DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(subscription_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - *relay_only = false; - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_NOT_ALLOWED: + if (impl->not_allowed_mask & NOT_ALLOWED_REMOTE_READER) + { + if (subscription_data->topic_name && strncmp (subscription_data->topic_name, AC_WRAPPER_TOPIC_PREFIX, strlen (AC_WRAPPER_TOPIC_PREFIX)) == 0) + { + ex->code = 1; + ex->message = ddsrt_strdup ("not_allowed: check_remote_datareader"); + return false; + } + } + /* fall through */ + case PLUGIN_MODE_WRAPPED: + { + bool ret; + if ((ret = impl->instance->check_remote_datareader(impl->instance, permissions_handle, domain_id, subscription_data, relay_only, ex))) + { + /* Only relay_only for the user reader, not the builtin ones. */ + if (impl->mode == PLUGIN_MODE_NOT_ALLOWED && impl->not_allowed_mask & NOT_ALLOWED_REMOTE_READER_RELAY_ONLY) + { + if (subscription_data->topic_name && strncmp (subscription_data->topic_name, AC_WRAPPER_TOPIC_PREFIX, strlen (AC_WRAPPER_TOPIC_PREFIX)) == 0) + *relay_only = true; + } + } + return ret; + } + + default: + *relay_only = false; + return true; + } } -static DDS_Security_boolean check_remote_topic( dds_security_access_control *instance, +static DDS_Security_boolean check_remote_topic( + dds_security_access_control *instance, const DDS_Security_PermissionsHandle permissions_handle, const DDS_Security_DomainId domain_id, const DDS_Security_TopicBuiltinTopicData *topic_data, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(domain_id); - DDSRT_UNUSED_ARG(topic_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_NOT_ALLOWED: + if (impl->not_allowed_mask & NOT_ALLOWED_REMOTE_TOPIC) + { + ex->code = 1; + ex->message = ddsrt_strdup ("not_allowed: check_remote_topic"); + return false; + } + /* fall through */ + case PLUGIN_MODE_WRAPPED: + return impl->instance->check_remote_topic(impl->instance, permissions_handle, domain_id, topic_data, ex); + + default: + return true; + } } static DDS_Security_boolean check_local_datawriter_match( @@ -236,13 +395,16 @@ static DDS_Security_boolean check_local_datawriter_match( const DDS_Security_SubscriptionBuiltinTopicDataSecure *subscription_data, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(writer_permissions_handle); - DDSRT_UNUSED_ARG(reader_permissions_handle); - DDSRT_UNUSED_ARG(publication_data); - DDSRT_UNUSED_ARG(subscription_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->check_local_datawriter_match(impl->instance, writer_permissions_handle, reader_permissions_handle, publication_data, subscription_data, ex); + + default: + return true; + } } static DDS_Security_boolean check_local_datareader_match( @@ -253,13 +415,16 @@ static DDS_Security_boolean check_local_datareader_match( const DDS_Security_PublicationBuiltinTopicDataSecure *publication_data, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(reader_permissions_handle); - DDSRT_UNUSED_ARG(writer_permissions_handle); - DDSRT_UNUSED_ARG(subscription_data); - DDSRT_UNUSED_ARG(publication_data); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->check_local_datareader_match(impl->instance, reader_permissions_handle, writer_permissions_handle, subscription_data, publication_data, ex); + + default: + return true; + } } static DDS_Security_boolean check_remote_datawriter_register_instance( @@ -271,14 +436,16 @@ static DDS_Security_boolean check_remote_datawriter_register_instance( const DDS_Security_InstanceHandle instance_handle, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(reader); - DDSRT_UNUSED_ARG(publication_handle); - DDSRT_UNUSED_ARG(key); - DDSRT_UNUSED_ARG(instance_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->check_remote_datawriter_register_instance(impl->instance, permissions_handle, reader, publication_handle, key, instance_handle, ex); + + default: + return true; + } } static DDS_Security_boolean check_remote_datawriter_dispose_instance( @@ -289,13 +456,16 @@ static DDS_Security_boolean check_remote_datawriter_dispose_instance( const DDS_Security_DynamicData key, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(reader); - DDSRT_UNUSED_ARG(publication_handle); - DDSRT_UNUSED_ARG(key); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->check_remote_datawriter_dispose_instance(impl->instance, permissions_handle, reader, publication_handle, key, ex); + + default: + return true; + } } static DDS_Security_boolean get_permissions_token( @@ -304,12 +474,18 @@ static DDS_Security_boolean get_permissions_token( const DDS_Security_PermissionsHandle handle, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - memset(permissions_token, 0, sizeof(*permissions_token)); - permissions_token->class_id = ddsrt_strdup(""); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->get_permissions_token(impl->instance, permissions_token, handle, ex); + + default: + memset(permissions_token, 0, sizeof(*permissions_token)); + permissions_token->class_id = ddsrt_strdup (""); + return true; + } } static DDS_Security_boolean get_permissions_credential_token( @@ -318,31 +494,51 @@ static DDS_Security_boolean get_permissions_credential_token( const DDS_Security_PermissionsHandle handle, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_credential_token); - DDSRT_UNUSED_ARG(handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->get_permissions_credential_token(impl->instance, permissions_credential_token, handle, ex); + + default: + return true; + } } -static DDS_Security_boolean set_listener( dds_security_access_control *instance, +static DDS_Security_boolean set_listener( + dds_security_access_control *instance, const dds_security_access_control_listener *listener, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(listener); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->set_listener (impl->instance, listener, ex); + + default: + return true; + } } -static DDS_Security_boolean return_permissions_token( dds_security_access_control *instance, +static DDS_Security_boolean return_permissions_token( + dds_security_access_control *instance, const DDS_Security_PermissionsToken *token, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - ddsrt_free (token->class_id); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->return_permissions_token (impl->instance, token, ex); + + default: + ddsrt_free (token->class_id); + return true; + } } static DDS_Security_boolean return_permissions_credential_token( @@ -350,10 +546,16 @@ static DDS_Security_boolean return_permissions_credential_token( const DDS_Security_PermissionsCredentialToken *permissions_credential_token, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_credential_token); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->return_permissions_credential_token(impl->instance, permissions_credential_token, ex); + + default: + return true; + } } static DDS_Security_boolean get_participant_sec_attributes( @@ -362,25 +564,35 @@ static DDS_Security_boolean get_participant_sec_attributes( DDS_Security_ParticipantSecurityAttributes *attributes, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->get_participant_sec_attributes(impl->instance, permissions_handle, attributes, ex); + + default: + return true; + } } -static DDS_Security_boolean get_topic_sec_attributes( dds_security_access_control *instance, +static DDS_Security_boolean get_topic_sec_attributes( + dds_security_access_control *instance, const DDS_Security_PermissionsHandle permissions_handle, const char *topic_name, DDS_Security_TopicSecurityAttributes *attributes, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->get_topic_sec_attributes(impl->instance, permissions_handle, topic_name, attributes, ex); + + default: + return true; + } } static DDS_Security_boolean get_datawriter_sec_attributes( @@ -392,14 +604,16 @@ static DDS_Security_boolean get_datawriter_sec_attributes( DDS_Security_EndpointSecurityAttributes *attributes, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(partition); - DDSRT_UNUSED_ARG(data_tag); - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->get_datawriter_sec_attributes(impl->instance, permissions_handle, topic_name, partition, data_tag, attributes, ex); + + default: + return true; + } } static DDS_Security_boolean get_datareader_sec_attributes( @@ -411,14 +625,16 @@ static DDS_Security_boolean get_datareader_sec_attributes( DDS_Security_EndpointSecurityAttributes *attributes, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(topic_name); - DDSRT_UNUSED_ARG(partition); - DDSRT_UNUSED_ARG(data_tag); - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->get_datareader_sec_attributes(impl->instance, permissions_handle, topic_name, partition, data_tag, attributes, ex); + + default: + return true; + } } static DDS_Security_boolean return_participant_sec_attributes( @@ -426,10 +642,16 @@ static DDS_Security_boolean return_participant_sec_attributes( const DDS_Security_ParticipantSecurityAttributes *attributes, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->return_participant_sec_attributes(impl->instance, attributes, ex); + + default: + return true; + } } static DDS_Security_boolean return_topic_sec_attributes( @@ -437,10 +659,16 @@ static DDS_Security_boolean return_topic_sec_attributes( const DDS_Security_TopicSecurityAttributes *attributes, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->return_topic_sec_attributes(impl->instance, attributes, ex); + + default: + return true; + } } static DDS_Security_boolean return_datawriter_sec_attributes( @@ -448,10 +676,16 @@ static DDS_Security_boolean return_datawriter_sec_attributes( const DDS_Security_EndpointSecurityAttributes *attributes, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->return_datawriter_sec_attributes(impl->instance, attributes, ex); + + default: + return true; + } } static DDS_Security_boolean return_datareader_sec_attributes( @@ -459,10 +693,16 @@ static DDS_Security_boolean return_datareader_sec_attributes( const DDS_Security_EndpointSecurityAttributes *attributes, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(attributes); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->return_datareader_sec_attributes(impl->instance, attributes, ex); + + default: + return true; + } } static DDS_Security_boolean return_permissions_handle( @@ -470,17 +710,29 @@ static DDS_Security_boolean return_permissions_handle( const DDS_Security_PermissionsHandle permissions_handle, DDS_Security_SecurityException *ex) { - DDSRT_UNUSED_ARG(permissions_handle); - DDSRT_UNUSED_ARG(ex); - DDSRT_UNUSED_ARG(instance); - return true; + struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; + switch (impl->mode) + { + case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_NOT_ALLOWED: + return impl->instance->return_permissions_handle(impl->instance, permissions_handle, ex); + + default: + return true; + } } - -static struct dds_security_access_control_impl * init_test_access_control_common() +static struct dds_security_access_control_impl * init_test_access_control_common(const char *argument, bool wrapped, struct ddsi_domaingv *gv) { struct dds_security_access_control_impl *impl = ddsrt_malloc(sizeof(*impl)); memset(impl, 0, sizeof(*impl)); + + if (wrapped) + { + if (init_access_control(argument, (void **)&impl->instance, gv) != DDS_SECURITY_SUCCESS) + return NULL; + } + impl->base.validate_local_permissions = &validate_local_permissions; impl->base.validate_remote_permissions = &validate_remote_permissions; impl->base.check_create_participant = &check_create_participant; @@ -514,40 +766,90 @@ static struct dds_security_access_control_impl * init_test_access_control_common return impl; } -int32_t init_test_access_control_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv) +static int finalize_test_access_control_common(struct dds_security_access_control_impl * impl, bool wrapped) +{ + int32_t ret; + if (wrapped && (ret = finalize_access_control(impl->instance)) != DDS_SECURITY_SUCCESS) + return ret; + ddsrt_free(impl); + return DDS_SECURITY_SUCCESS; +} + +int init_test_access_control_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv) { - DDSRT_UNUSED_ARG(argument); DDSRT_UNUSED_ARG(context); - DDSRT_UNUSED_ARG(gv); - struct dds_security_access_control_impl *impl = init_test_access_control_common(); + struct dds_security_access_control_impl *impl = init_test_access_control_common(argument, false, gv); impl->mode = PLUGIN_MODE_ALL_OK; *context = impl; return 0; } -int32_t finalize_test_access_control_all_ok(void *context) +int finalize_test_access_control_all_ok(void *context) { - assert(((struct dds_security_access_control_impl *)context)->mode == PLUGIN_MODE_ALL_OK); - ddsrt_free(context); - return 0; + struct dds_security_access_control_impl* impl = (struct dds_security_access_control_impl*) context; + assert(impl->mode == PLUGIN_MODE_ALL_OK); + return finalize_test_access_control_common(impl, false); } -int32_t init_test_access_control_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv) +int init_test_access_control_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv) +{ + struct dds_security_access_control_impl *impl = init_test_access_control_common(argument, true, gv); + if (!impl) + return DDS_SECURITY_FAILED; + impl->mode = PLUGIN_MODE_WRAPPED; + *context = impl; + return DDS_SECURITY_SUCCESS; +} + +int finalize_test_access_control_wrapped(void *context) +{ + struct dds_security_access_control_impl* impl = (struct dds_security_access_control_impl*) context; + assert(impl->mode == PLUGIN_MODE_WRAPPED); + return finalize_test_access_control_common(impl, true); +} + +int init_test_access_control_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv) { - DDSRT_UNUSED_ARG(argument); DDSRT_UNUSED_ARG(context); - DDSRT_UNUSED_ARG(gv); - struct dds_security_access_control_impl *impl = init_test_access_control_common(); + struct dds_security_access_control_impl *impl = init_test_access_control_common(argument, false, gv); impl->base.check_create_datareader = NULL; impl->mode = PLUGIN_MODE_MISSING_FUNC; *context = impl; return 0; } -int32_t finalize_test_access_control_missing_func(void *context) +int finalize_test_access_control_missing_func(void *context) { - assert(((struct dds_security_access_control_impl *)context)->mode == PLUGIN_MODE_MISSING_FUNC); - ddsrt_free(context); - return 0; + struct dds_security_access_control_impl* impl = (struct dds_security_access_control_impl*) context; + assert(impl->mode == PLUGIN_MODE_MISSING_FUNC); + return finalize_test_access_control_common(impl, false); } +#define INIT_NOT_ALLOWED(name_, mask_) \ + int init_test_access_control_##name_ (const char *argument, void **context, struct ddsi_domaingv *gv) \ + { \ + DDSRT_UNUSED_ARG(context); \ + struct dds_security_access_control_impl *impl = init_test_access_control_common(argument, true, gv); \ + impl->mode = PLUGIN_MODE_NOT_ALLOWED; \ + impl->not_allowed_mask = mask_; \ + *context = impl; \ + return 0; \ + } + +INIT_NOT_ALLOWED(local_participant_not_allowed, NOT_ALLOWED_LOCAL_PP) +INIT_NOT_ALLOWED(local_topic_not_allowed, NOT_ALLOWED_LOCAL_TOPIC) +INIT_NOT_ALLOWED(local_publishing_not_allowed, NOT_ALLOWED_LOCAL_PUB) +INIT_NOT_ALLOWED(local_subscribing_not_allowed, NOT_ALLOWED_LOCAL_SUB) +INIT_NOT_ALLOWED(remote_permissions_invalidate, NOT_ALLOWED_REMOTE_PERM) +INIT_NOT_ALLOWED(remote_participant_not_allowed, NOT_ALLOWED_REMOTE_PP) +INIT_NOT_ALLOWED(remote_topic_not_allowed, NOT_ALLOWED_REMOTE_TOPIC) +INIT_NOT_ALLOWED(remote_writer_not_allowed, NOT_ALLOWED_REMOTE_WRITER) +INIT_NOT_ALLOWED(remote_reader_not_allowed, NOT_ALLOWED_REMOTE_READER) +INIT_NOT_ALLOWED(remote_reader_relay_only, NOT_ALLOWED_REMOTE_READER_RELAY_ONLY) + +int finalize_test_access_control_not_allowed(void *context) +{ + struct dds_security_access_control_impl* impl = (struct dds_security_access_control_impl*) context; + assert(impl->mode == PLUGIN_MODE_NOT_ALLOWED); + return finalize_test_access_control_common(impl, true); +} diff --git a/src/security/core/tests/common/access_control_wrapper.h b/src/security/core/tests/common/access_control_wrapper.h index a7c2e7c..3fb04bf 100644 --- a/src/security/core/tests/common/access_control_wrapper.h +++ b/src/security/core/tests/common/access_control_wrapper.h @@ -16,12 +16,36 @@ #include "dds/security/dds_security_api.h" #include "dds/security/access_control_wrapper_export.h" +/* Topic name prefix expected by this wrapper when running in not-allowed + mode. This prefix is used to exclude built-in topics from being disallowed. */ +#define AC_WRAPPER_TOPIC_PREFIX "ddssec_access_control_" + /* Init in all-ok mode: all functions return success without calling the actual plugin */ -SECURITY_EXPORT int32_t init_test_access_control_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv); -SECURITY_EXPORT int32_t finalize_test_access_control_all_ok(void *context); +SECURITY_EXPORT int init_test_access_control_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv); +SECURITY_EXPORT int finalize_test_access_control_all_ok(void *context); /* Init in missing function mode: one of the function pointers is null */ -SECURITY_EXPORT int32_t init_test_access_control_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv); -SECURITY_EXPORT int32_t finalize_test_access_control_missing_func(void *context); +SECURITY_EXPORT int init_test_access_control_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv); +SECURITY_EXPORT int finalize_test_access_control_missing_func(void *context); + +SECURITY_EXPORT int init_test_access_control_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv); +SECURITY_EXPORT int finalize_test_access_control_wrapped(void *context); + +/* Init functions for not-allowed modes */ +#define INIT_NOT_ALLOWED_DECL(name_) \ + SECURITY_EXPORT int init_test_access_control_##name_ (const char *argument, void **context, struct ddsi_domaingv *gv); + +INIT_NOT_ALLOWED_DECL(local_participant_not_allowed) +INIT_NOT_ALLOWED_DECL(local_topic_not_allowed) +INIT_NOT_ALLOWED_DECL(local_publishing_not_allowed) +INIT_NOT_ALLOWED_DECL(local_subscribing_not_allowed) +INIT_NOT_ALLOWED_DECL(remote_permissions_invalidate) +INIT_NOT_ALLOWED_DECL(remote_participant_not_allowed) +INIT_NOT_ALLOWED_DECL(remote_topic_not_allowed) +INIT_NOT_ALLOWED_DECL(remote_writer_not_allowed) +INIT_NOT_ALLOWED_DECL(remote_reader_not_allowed) +INIT_NOT_ALLOWED_DECL(remote_reader_relay_only) + +SECURITY_EXPORT int finalize_test_access_control_not_allowed(void *context); #endif /* SECURITY_CORE_TEST_ACCESS_CONTROL_WRAPPER_H_ */ diff --git a/src/security/core/tests/common/authentication_wrapper.c b/src/security/core/tests/common/authentication_wrapper.c index a2d3709..86290df 100644 --- a/src/security/core/tests/common/authentication_wrapper.c +++ b/src/security/core/tests/common/authentication_wrapper.c @@ -22,8 +22,8 @@ #include "test_identity.h" #include "plugin_wrapper_msg_q.h" -int32_t init_authentication(const char *argument, void **context, struct ddsi_domaingv *gv); -int32_t finalize_authentication(void *context); +int init_authentication(const char *argument, void **context, struct ddsi_domaingv *gv); +int finalize_authentication(void *context); enum auth_plugin_mode { PLUGIN_MODE_ALL_OK, @@ -482,7 +482,7 @@ static struct dds_security_authentication_impl * init_test_authentication_common return impl; } -int32_t init_test_authentication_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv) +int init_test_authentication_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv) { DDSRT_UNUSED_ARG(argument); DDSRT_UNUSED_ARG(context); @@ -493,14 +493,14 @@ int32_t init_test_authentication_all_ok(const char *argument, void **context, st return 0; } -int32_t finalize_test_authentication_all_ok(void *context) +int finalize_test_authentication_all_ok(void *context) { assert(((struct dds_security_authentication_impl *)context)->mode == PLUGIN_MODE_ALL_OK); ddsrt_free(context); return 0; } -int32_t init_test_authentication_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv) +int init_test_authentication_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv) { DDSRT_UNUSED_ARG(argument); DDSRT_UNUSED_ARG(context); @@ -512,14 +512,14 @@ int32_t init_test_authentication_missing_func(const char *argument, void **conte return 0; } -int32_t finalize_test_authentication_missing_func(void *context) +int finalize_test_authentication_missing_func(void *context) { assert(((struct dds_security_authentication_impl *)context)->mode == PLUGIN_MODE_MISSING_FUNC); ddsrt_free(context); return 0; } -int32_t init_test_authentication_init_error(const char *argument, void **context, struct ddsi_domaingv *gv) +int init_test_authentication_init_error(const char *argument, void **context, struct ddsi_domaingv *gv) { DDSRT_UNUSED_ARG(argument); DDSRT_UNUSED_ARG(context); @@ -527,7 +527,7 @@ int32_t init_test_authentication_init_error(const char *argument, void **context return 1; } -int32_t finalize_test_authentication_init_error(void *context) +int finalize_test_authentication_init_error(void *context) { DDSRT_UNUSED_ARG(context); return 0; @@ -537,9 +537,9 @@ int32_t finalize_test_authentication_init_error(void *context) * Init and fini functions for using wrapped mode for the authentication plugin. * These functions assumes that there are no concurrent calls, as the static * variables used here are not protected by a lock. */ -int32_t init_test_authentication_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv) +int init_test_authentication_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv) { - int32_t ret; + int ret; struct dds_security_authentication_impl *impl = init_test_authentication_common(); impl->mode = PLUGIN_MODE_WRAPPED; @@ -553,9 +553,9 @@ int32_t init_test_authentication_wrapped(const char *argument, void **context, s return ret; } -int32_t finalize_test_authentication_wrapped(void *context) +int finalize_test_authentication_wrapped(void *context) { - int32_t ret; + int ret; struct dds_security_authentication_impl *impl = context; assert(impl->mode == PLUGIN_MODE_WRAPPED); deinit_message_queue(&impl->msg_queue); diff --git a/src/security/core/tests/common/authentication_wrapper.h b/src/security/core/tests/common/authentication_wrapper.h index d784454..f58121d 100644 --- a/src/security/core/tests/common/authentication_wrapper.h +++ b/src/security/core/tests/common/authentication_wrapper.h @@ -18,20 +18,20 @@ #include "plugin_wrapper_msg_q.h" /* Init in wrapper mode */ -SECURITY_EXPORT int32_t init_test_authentication_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv); -SECURITY_EXPORT int32_t finalize_test_authentication_wrapped(void *context); +SECURITY_EXPORT int init_test_authentication_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv); +SECURITY_EXPORT int finalize_test_authentication_wrapped(void *context); /* Init in all-ok mode: all functions return success without calling the actual plugin */ -SECURITY_EXPORT int32_t init_test_authentication_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv); -SECURITY_EXPORT int32_t finalize_test_authentication_all_ok(void *context); +SECURITY_EXPORT int init_test_authentication_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv); +SECURITY_EXPORT int finalize_test_authentication_all_ok(void *context); /* Init in missing function mode: one of the function pointers is null */ -SECURITY_EXPORT int32_t init_test_authentication_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv); -SECURITY_EXPORT int32_t finalize_test_authentication_missing_func(void *context); +SECURITY_EXPORT int init_test_authentication_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv); +SECURITY_EXPORT int finalize_test_authentication_missing_func(void *context); /* Init function fails */ -SECURITY_EXPORT int32_t init_test_authentication_init_error(const char *argument, void **context, struct ddsi_domaingv *gv); -SECURITY_EXPORT int32_t finalize_test_authentication_init_error(void *context); +SECURITY_EXPORT int init_test_authentication_init_error(const char *argument, void **context, struct ddsi_domaingv *gv); +SECURITY_EXPORT int finalize_test_authentication_init_error(void *context); SECURITY_EXPORT struct message * test_authentication_plugin_take_msg(dds_domainid_t domain_id, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, dds_duration_t timeout); SECURITY_EXPORT void test_authentication_plugin_release_msg(struct message *msg); diff --git a/src/security/core/tests/common/cryptography_wrapper.c b/src/security/core/tests/common/cryptography_wrapper.c index a3d1508..034d81d 100644 --- a/src/security/core/tests/common/cryptography_wrapper.c +++ b/src/security/core/tests/common/cryptography_wrapper.c @@ -22,8 +22,8 @@ #include "dds/security/core/dds_security_utils.h" #include "cryptography_wrapper.h" -int32_t init_crypto(const char *argument, void **context, struct ddsi_domaingv *gv); -int32_t finalize_crypto(void *context); +int init_crypto(const char *argument, void **context, struct ddsi_domaingv *gv); +int finalize_crypto(void *context); enum crypto_plugin_mode { PLUGIN_MODE_ALL_OK, @@ -754,16 +754,16 @@ static struct dds_security_cryptography_impl * init_test_cryptography_common(con return impl; } -static int32_t finalize_test_cryptography_common(struct dds_security_cryptography_impl * impl, bool wrapped) +static int finalize_test_cryptography_common(struct dds_security_cryptography_impl * impl, bool wrapped) { - int32_t ret; + int ret; if (wrapped && (ret = finalize_crypto(impl->instance)) != DDS_SECURITY_SUCCESS) return ret; ddsrt_free(impl); return DDS_SECURITY_SUCCESS; } -int32_t init_test_cryptography_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv) +int init_test_cryptography_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv) { struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, false, gv); if (!impl) @@ -773,14 +773,14 @@ int32_t init_test_cryptography_all_ok(const char *argument, void **context, stru return DDS_SECURITY_SUCCESS; } -int32_t finalize_test_cryptography_all_ok(void *context) +int finalize_test_cryptography_all_ok(void *context) { struct dds_security_cryptography_impl* impl = (struct dds_security_cryptography_impl*) context; assert(impl->mode == PLUGIN_MODE_ALL_OK); return finalize_test_cryptography_common(impl, false); } -int32_t init_test_cryptography_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv) +int init_test_cryptography_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv) { struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, false, gv); if (!impl) @@ -791,14 +791,14 @@ int32_t init_test_cryptography_missing_func(const char *argument, void **context return DDS_SECURITY_SUCCESS; } -int32_t finalize_test_cryptography_missing_func(void *context) +int finalize_test_cryptography_missing_func(void *context) { struct dds_security_cryptography_impl* impl = (struct dds_security_cryptography_impl*) context; assert(impl->mode == PLUGIN_MODE_MISSING_FUNC); return finalize_test_cryptography_common(impl, false); } -int32_t init_test_cryptography_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv) +int init_test_cryptography_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv) { struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, true, gv); if (!impl) @@ -808,7 +808,7 @@ int32_t init_test_cryptography_wrapped(const char *argument, void **context, str return DDS_SECURITY_SUCCESS; } -int32_t finalize_test_cryptography_wrapped(void *context) +int finalize_test_cryptography_wrapped(void *context) { struct dds_security_cryptography_impl* impl = (struct dds_security_cryptography_impl*) context; assert(impl->mode == PLUGIN_MODE_WRAPPED); diff --git a/src/security/core/tests/common/cryptography_wrapper.h b/src/security/core/tests/common/cryptography_wrapper.h index f379727..0c50adc 100644 --- a/src/security/core/tests/common/cryptography_wrapper.h +++ b/src/security/core/tests/common/cryptography_wrapper.h @@ -35,15 +35,15 @@ SECURITY_EXPORT void set_disc_protection_kinds( SECURITY_EXPORT void set_entity_data_secret(struct dds_security_cryptography_impl * impl, const char * pp_secret, const char * groupdata_secret, const char * ep_secret); /* Init in all-ok mode: all functions return success without calling the actual plugin */ -SECURITY_EXPORT int32_t init_test_cryptography_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv); -SECURITY_EXPORT int32_t finalize_test_cryptography_all_ok(void *context); +SECURITY_EXPORT int init_test_cryptography_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv); +SECURITY_EXPORT int finalize_test_cryptography_all_ok(void *context); /* Init in missing function mode: one of the function pointers is null */ -SECURITY_EXPORT int32_t init_test_cryptography_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv); -SECURITY_EXPORT int32_t finalize_test_cryptography_missing_func(void *context); +SECURITY_EXPORT int init_test_cryptography_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv); +SECURITY_EXPORT int finalize_test_cryptography_missing_func(void *context); /* Init in wrapper mode */ -SECURITY_EXPORT int32_t init_test_cryptography_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv); -SECURITY_EXPORT int32_t finalize_test_cryptography_wrapped(void *context); +SECURITY_EXPORT int init_test_cryptography_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv); +SECURITY_EXPORT int finalize_test_cryptography_wrapped(void *context); #endif /* SECURITY_CORE_TEST_CRYPTO_WRAPPER_H_ */ diff --git a/src/security/core/tests/common/security_config_test_utils.c b/src/security/core/tests/common/security_config_test_utils.c index 51a0a9f..d66ff2d 100644 --- a/src/security/core/tests/common/security_config_test_utils.c +++ b/src/security/core/tests/common/security_config_test_utils.c @@ -50,8 +50,8 @@ static const char *governance_xml = " *" " ${ENABLE_DISC_PROTECTION:-false}" " ${ENABLE_LIVELINESS_PROTECTION:-false}" - " ${ENABLE_READ_AC:-false}" - " ${ENABLE_WRITE_AC:-false}" + " ${ENABLE_READ_AC:-true}" + " ${ENABLE_WRITE_AC:-true}" " ${METADATA_PROTECTION_KIND:-NONE}" " ${DATA_PROTECTION_KIND:-NONE}" " " @@ -68,7 +68,7 @@ static const char *permissions_xml_grant = " ${SUBJECT_NAME}" " ${NOT_BEFORE:-2015-09-15T01:00:00}${NOT_AFTER:-2115-09-15T01:00:00}" " " - " 0230" + " ${DOMAIN_ID:+}${DOMAIN_ID:-0230}${DOMAIN_ID:+}" " " " ${PUB_TOPICS:-*}" " *" @@ -239,7 +239,7 @@ static char * get_xml_datetime(dds_time_t t, char * buf, size_t len) return buf; } -char * get_permissions_grant(const char * name, const char * subject, +char * get_permissions_grant(const char * name, const char * subject, const char * domain_id, dds_time_t not_before, dds_time_t not_after, const char * pub_topics, const char * sub_topics, const char * default_policy) { char not_before_str[] = "0000-00-00T00:00:00Z"; @@ -252,6 +252,7 @@ char * get_permissions_grant(const char * name, const char * subject, { "SUBJECT_NAME", subject, 1 }, { "NOT_BEFORE", not_before_str, 1 }, { "NOT_AFTER", not_after_str, 1 }, + { "DOMAIN_ID", domain_id, 3 }, { "PUB_TOPICS", pub_topics, 1 }, { "SUB_TOPICS", sub_topics, 1 }, { "DEFAULT_POLICY", default_policy, 1 }, diff --git a/src/security/core/tests/common/security_config_test_utils.h b/src/security/core/tests/common/security_config_test_utils.h index 87f8e4b..3cf20de 100644 --- a/src/security/core/tests/common/security_config_test_utils.h +++ b/src/security/core/tests/common/security_config_test_utils.h @@ -27,7 +27,7 @@ int32_t expand_lookup_unmatched (const struct kvp * lookup_table); char * get_governance_config (struct kvp *config_vars, bool add_prefix); char * get_permissions_topic(const char * name); -char * get_permissions_grant(const char * name, const char * subject, +char * get_permissions_grant(const char * name, const char * subject, const char * domain_id, dds_time_t not_before, dds_time_t not_after, const char * pub_topics, const char * sub_topics, const char * default_policy); char * get_permissions_config(char * grants[], size_t ngrants, bool add_prefix); diff --git a/src/security/core/tests/common/test_utils.c b/src/security/core/tests/common/test_utils.c index bf8c300..a75c6b9 100644 --- a/src/security/core/tests/common/test_utils.c +++ b/src/security/core/tests/common/test_utils.c @@ -294,10 +294,11 @@ void sync_writer_to_readers (dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_c CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); while (true) { - ret = dds_waitset_wait (ws, &triggered, 1, DDS_SECS(5)); - CU_ASSERT_FATAL (ret >= 1); - CU_ASSERT_EQUAL_FATAL (wr, (dds_entity_t)(intptr_t) triggered); - ret = dds_get_publication_matched_status(wr, &pub_matched); + ret = dds_waitset_wait (ws, &triggered, 1, DDS_SECS(2)); + CU_ASSERT_EQUAL_FATAL (exp_count > 0, ret >= 1); + if (exp_count > 0) + CU_ASSERT_EQUAL_FATAL (wr, (dds_entity_t)(intptr_t) triggered); + ret = dds_get_publication_matched_status (wr, &pub_matched); CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); if (pub_matched.total_count >= exp_count) break; @@ -306,6 +307,30 @@ void sync_writer_to_readers (dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_c CU_ASSERT_EQUAL_FATAL (pub_matched.total_count, exp_count); } +void sync_reader_to_writers (dds_entity_t pp_rd, dds_entity_t rd, uint32_t exp_count) +{ + dds_attach_t triggered; + dds_entity_t ws = dds_create_waitset (pp_rd); + CU_ASSERT_FATAL (ws > 0); + dds_subscription_matched_status_t sub_matched; + + dds_return_t ret = dds_waitset_attach (ws, rd, rd); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + while (true) + { + ret = dds_waitset_wait (ws, &triggered, 1, DDS_SECS(2)); + CU_ASSERT_EQUAL_FATAL (exp_count > 0, ret >= 1); + if (exp_count > 0) + CU_ASSERT_EQUAL_FATAL (rd, (dds_entity_t)(intptr_t) triggered); + ret = dds_get_subscription_matched_status (rd, &sub_matched); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + if (sub_matched.total_count >= exp_count) + break; + }; + dds_delete (ws); + CU_ASSERT_EQUAL_FATAL (sub_matched.total_count, exp_count); +} + char *create_topic_name (const char *prefix, uint32_t nr, char *name, size_t size) { ddsrt_pid_t pid = ddsrt_getpid (); @@ -328,10 +353,12 @@ bool reader_wait_for_data (dds_entity_t pp, dds_entity_t rd, dds_duration_t dur) return ret > 0; } -void rd_wr_init( +void rd_wr_init_fail( dds_entity_t pp_wr, dds_entity_t *pub, dds_entity_t *pub_tp, dds_entity_t *wr, dds_entity_t pp_rd, dds_entity_t *sub, dds_entity_t *sub_tp, dds_entity_t *rd, - const char * topic_name) + const char * topic_name, + bool exp_pubtp_fail, bool exp_wr_fail, + bool exp_subtp_fail, bool exp_rd_fail) { dds_qos_t * qos = dds_create_qos (); CU_ASSERT_FATAL (qos != NULL); @@ -344,19 +371,37 @@ void rd_wr_init( *sub = dds_create_subscriber (pp_rd, NULL, NULL); CU_ASSERT_FATAL (*sub > 0); *pub_tp = dds_create_topic (pp_wr, &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL); - CU_ASSERT_FATAL (*pub_tp > 0); + CU_ASSERT_EQUAL_FATAL (exp_pubtp_fail, *pub_tp <= 0); *sub_tp = dds_create_topic (pp_rd, &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL); - CU_ASSERT_FATAL (*sub_tp > 0); - *wr = dds_create_writer (*pub, *pub_tp, qos, NULL); - CU_ASSERT_FATAL (*wr > 0); - dds_set_status_mask (*wr, DDS_PUBLICATION_MATCHED_STATUS); - *rd = dds_create_reader (*sub, *sub_tp, qos, NULL); - CU_ASSERT_FATAL (*rd > 0); - dds_set_status_mask (*rd, DDS_DATA_AVAILABLE_STATUS); - sync_writer_to_readers(pp_wr, *wr, 1); + CU_ASSERT_EQUAL_FATAL (exp_subtp_fail, *sub_tp <= 0); + if (!exp_pubtp_fail) + { + *wr = dds_create_writer (*pub, *pub_tp, qos, NULL); + CU_ASSERT_EQUAL_FATAL (exp_wr_fail, *wr <= 0); + if (exp_wr_fail) + goto fail; + dds_set_status_mask (*wr, DDS_PUBLICATION_MATCHED_STATUS); + } + if (!exp_subtp_fail) + { + *rd = dds_create_reader (*sub, *sub_tp, qos, NULL); + CU_ASSERT_EQUAL_FATAL (exp_rd_fail, *rd <= 0); + if (exp_rd_fail) + goto fail; + dds_set_status_mask (*rd, DDS_SUBSCRIPTION_MATCHED_STATUS); + } +fail: dds_delete_qos (qos); } +void rd_wr_init( + dds_entity_t pp_wr, dds_entity_t *pub, dds_entity_t *pub_tp, dds_entity_t *wr, + dds_entity_t pp_rd, dds_entity_t *sub, dds_entity_t *sub_tp, dds_entity_t *rd, + const char * topic_name) +{ + rd_wr_init_fail (pp_wr, pub, pub_tp, wr, pp_rd, sub, sub_tp, rd, topic_name, false, false, false, false); +} + void write_read_for(dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_duration_t dur, bool exp_write_fail, bool exp_read_fail) { SecurityCoreTests_Type1 sample = { 1, 1 }; @@ -367,9 +412,10 @@ void write_read_for(dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_du dds_time_t tend = dds_time () + dur; bool write_fail = false, read_fail = false; + dds_set_status_mask (rd, DDS_DATA_AVAILABLE_STATUS); do { - print_test_msg("write\n"); + print_test_msg ("write\n"); if (dds_write (wr, &sample) != DDS_RETCODE_OK) write_fail = true; @@ -399,7 +445,7 @@ void write_read_for(dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_du break; dds_sleepfor (DDS_MSECS (100)); } - while (dds_time() < tend); + while (dds_time () < tend); CU_ASSERT_EQUAL_FATAL (write_fail, exp_write_fail); CU_ASSERT_EQUAL_FATAL (read_fail, exp_read_fail); } diff --git a/src/security/core/tests/common/test_utils.h b/src/security/core/tests/common/test_utils.h index b396f60..ac1e8a7 100644 --- a/src/security/core/tests/common/test_utils.h +++ b/src/security/core/tests/common/test_utils.h @@ -56,11 +56,18 @@ void validate_handshake_nofail (dds_domainid_t domain_id); void handshake_list_fini(struct Handshake *hs_list, int nhs); char *create_topic_name(const char *prefix, uint32_t nr, char *name, size_t size); void sync_writer_to_readers(dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_count); +void sync_reader_to_writers (dds_entity_t pp_rd, dds_entity_t rd, uint32_t exp_count); bool reader_wait_for_data(dds_entity_t pp, dds_entity_t rd, dds_duration_t dur); void rd_wr_init( dds_entity_t pp_wr, dds_entity_t *pub, dds_entity_t *pub_tp, dds_entity_t *wr, dds_entity_t pp_rd, dds_entity_t *sub, dds_entity_t *sub_tp, dds_entity_t *rd, - const char *topic_name); + const char * topic_name); +void rd_wr_init_fail( + dds_entity_t pp_wr, dds_entity_t *pub, dds_entity_t *pub_tp, dds_entity_t *wr, + dds_entity_t pp_rd, dds_entity_t *sub, dds_entity_t *sub_tp, dds_entity_t *rd, + const char * topic_name, + bool exp_pubtp_fail, bool exp_wr_fail, + bool exp_subtp_fail, bool exp_rd_fail); void write_read_for(dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_duration_t dur, bool exp_write_fail, bool exp_read_fail); #endif /* SECURITY_CORE_TEST_UTILS_H_ */ From e8c349f96d3a42d9ce204d39ef7edd7311cbbbc9 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Fri, 17 Apr 2020 09:02:09 +0200 Subject: [PATCH 171/238] Fix condition for setting identity subject in remote rights Signed-off-by: Dennis Potman --- .../access_control/src/access_control_objects.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/security/builtin_plugins/access_control/src/access_control_objects.c b/src/security/builtin_plugins/access_control/src/access_control_objects.c index 8988061..d418c21 100644 --- a/src/security/builtin_plugins/access_control/src/access_control_objects.c +++ b/src/security/builtin_plugins/access_control/src/access_control_objects.c @@ -272,10 +272,10 @@ ac_remote_participant_access_rights_new( { rights->permissions->ref_cnt++; if (rights->permissions->remote_permissions_token_class_id == NULL) - { rights->permissions->remote_permissions_token_class_id = ddsrt_strdup(remote_permissions_token->class_id); - rights->identity_subject_name = ddsrt_strdup(identity_subject); - } + else + assert (strcmp (rights->permissions->remote_permissions_token_class_id, remote_permissions_token->class_id) == 0); + rights->identity_subject_name = ddsrt_strdup(identity_subject); } else { From 7e6039763baef71ad0ca741b045ada3f111968e9 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 21 Apr 2020 09:37:09 +0200 Subject: [PATCH 172/238] Replace pp null check by assert in dds_create_writer and dds_create_reader, and rewrite logic in q_omg_security_check_remote_writer_permissions Signed-off-by: Dennis Potman --- src/core/ddsc/src/dds_reader.c | 14 +++---- src/core/ddsc/src/dds_writer.c | 13 +++--- src/core/ddsi/src/ddsi_security_omg.c | 58 +++++++++++++-------------- 3 files changed, 38 insertions(+), 47 deletions(-) diff --git a/src/core/ddsc/src/dds_reader.c b/src/core/ddsc/src/dds_reader.c index bffe59a..5af47a0 100644 --- a/src/core/ddsc/src/dds_reader.c +++ b/src/core/ddsc/src/dds_reader.c @@ -456,12 +456,11 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe thread_state_awake (lookup_thread_state (), gv); const struct ddsi_guid * ppguid = dds_entity_participant_guid (&sub->m_entity); struct participant * pp = entidx_lookup_participant_guid (gv->entity_index, ppguid); - if (pp == NULL) - { - GVLOGDISC ("new_reader - participant "PGUIDFMT" not found\n", PGUID (*ppguid)); - rc = DDS_RETCODE_BAD_PARAMETER; - goto err_pp_not_found; - } + + /* When deleting a participant, the child handles (that include the subscriber) + are removed before removing the DDSI participant. So at this point, within + the subscriber lock, we can assert that the participant exists. */ + assert (pp != NULL); #ifdef DDSI_INCLUDE_SECURITY /* Check if DDS Security is enabled */ @@ -508,9 +507,8 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe #ifdef DDSI_INCLUDE_SECURITY err_not_allowed: -#endif -err_pp_not_found: thread_state_asleep (lookup_thread_state ()); +#endif err_bad_qos: dds_delete_qos (rqos); dds_topic_allow_set_qos (tp); diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index 12d2676..bebebcc 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -329,12 +329,10 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit thread_state_awake (lookup_thread_state (), gv); const struct ddsi_guid *ppguid = dds_entity_participant_guid (&pub->m_entity); struct participant *pp = entidx_lookup_participant_guid (gv->entity_index, ppguid); - if (pp == NULL) - { - GVLOGDISC ("new_writer - participant "PGUIDFMT" not found\n", PGUID (*ppguid)); - rc = DDS_RETCODE_BAD_PARAMETER; - goto err_pp_not_found; - } + /* When deleting a participant, the child handles (that include the publisher) + are removed before removing the DDSI participant. So at this point, within + the publisher lock, we can assert that the participant exists. */ + assert (pp != NULL); #ifdef DDSI_INCLUDE_SECURITY /* Check if DDS Security is enabled */ @@ -377,9 +375,8 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit #ifdef DDSI_INCLUDE_SECURITY err_not_allowed: -#endif -err_pp_not_found: thread_state_asleep (lookup_thread_state ()); +#endif err_bad_qos: dds_delete_qos(wqos); dds_topic_allow_set_qos (tp); diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index c7f2b10..c073166 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -2137,7 +2137,6 @@ bool q_omg_security_check_remote_writer_permissions(const struct proxy_writer *p DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; DDS_Security_PublicationBuiltinTopicDataSecure publication_data; DDS_Security_TopicBuiltinTopicData topic_data; - bool result = true; if (!sc) return true; @@ -2156,42 +2155,39 @@ bool q_omg_security_check_remote_writer_permissions(const struct proxy_writer *p } } - if (SECURITY_INFO_IS_WRITE_PROTECTED(pwr->c.security_info)) - { - DDS_Security_PermissionsHandle permissions_handle; + if (!SECURITY_INFO_IS_WRITE_PROTECTED(pwr->c.security_info)) + return true; - if ((permissions_handle = get_permissions_handle(pp, pwr->c.proxypp)) == 0) - { - GVTRACE("Secure remote writer "PGUIDFMT" proxypp does not have permissions handle yet\n", PGUID(pwr->e.guid)); - return false; - } + DDS_Security_PermissionsHandle permissions_handle; + if ((permissions_handle = get_permissions_handle(pp, pwr->c.proxypp)) == 0) + { + GVTRACE("Secure remote writer "PGUIDFMT" proxypp does not have permissions handle yet\n", PGUID(pwr->e.guid)); + return false; + } + + q_omg_shallow_copy_PublicationBuiltinTopicDataSecure(&publication_data, &pwr->e.guid, pwr->c.xqos, &pwr->c.security_info); + bool result = sc->access_control_context->check_remote_datawriter(sc->access_control_context, permissions_handle, (int)domain_id, &publication_data, &exception); + if (!result) + { + if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, publication_data.topic_name)) + EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote writer "PGUIDFMT": %s", PGUID(pwr->e.guid)); else + DDS_Security_Exception_reset(&exception); + } + else + { + q_omg_shallow_copy_TopicBuiltinTopicData(&topic_data, publication_data.topic_name, publication_data.type_name); + result = sc->access_control_context->check_remote_topic(sc->access_control_context, permissions_handle, (int)domain_id, &topic_data, &exception); + q_omg_shallow_free_TopicBuiltinTopicData(&topic_data); + if (!result) { - q_omg_shallow_copy_PublicationBuiltinTopicDataSecure(&publication_data, &pwr->e.guid, pwr->c.xqos, &pwr->c.security_info); - result = sc->access_control_context->check_remote_datawriter(sc->access_control_context, permissions_handle, (int)domain_id, &publication_data, &exception); - if (!result) - { - if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, publication_data.topic_name)) - EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote writer "PGUIDFMT": %s", PGUID(pwr->e.guid)); - else - DDS_Security_Exception_reset(&exception); - } + if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, publication_data.topic_name)) + EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote topic %s: %s", publication_data.topic_name); else - { - q_omg_shallow_copy_TopicBuiltinTopicData(&topic_data, publication_data.topic_name, publication_data.type_name); - result = sc->access_control_context->check_remote_topic(sc->access_control_context, permissions_handle, (int)domain_id, &topic_data, &exception); - q_omg_shallow_free_TopicBuiltinTopicData(&topic_data); - if (!result) - { - if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, publication_data.topic_name)) - EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote topic %s: %s", publication_data.topic_name); - else - DDS_Security_Exception_reset(&exception); - } - } - q_omg_shallow_free_PublicationBuiltinTopicDataSecure(&publication_data); + DDS_Security_Exception_reset(&exception); } } + q_omg_shallow_free_PublicationBuiltinTopicDataSecure(&publication_data); return result; } From b86e8ce0d3d112da105641c912952c7770b8299e Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 21 Apr 2020 21:43:27 +0200 Subject: [PATCH 173/238] Refactoring logic in q_omg_security_check_remote_reader_permissions Signed-off-by: Dennis Potman --- src/core/ddsi/src/ddsi_security_omg.c | 64 +++++++++++++-------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index c073166..9ad902d 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -2145,7 +2145,7 @@ bool q_omg_security_check_remote_writer_permissions(const struct proxy_writer *p { if (q_omg_participant_allow_unauthenticated(pp)) { - GVTRACE (" allow non-secure remote writer "PGUIDFMT, PGUID (pwr->e.guid)); + GVTRACE(" allow non-secure remote writer "PGUIDFMT, PGUID(pwr->e.guid)); return true; } else @@ -2376,7 +2376,6 @@ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *p DDS_Security_SubscriptionBuiltinTopicDataSecure subscription_data; DDS_Security_TopicBuiltinTopicData topic_data; DDS_Security_boolean sec_relay_only; - bool result = true; /* relay_only is meaningless in all cases except the one where the access control plugin says otherwise */ *relay_only = false; @@ -2388,7 +2387,7 @@ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *p { if (q_omg_participant_allow_unauthenticated(pp)) { - GVTRACE (" allow non-secure remote reader "PGUIDFMT, PGUID (prd->e.guid)); + GVTRACE(" allow non-secure remote reader "PGUIDFMT, PGUID(prd->e.guid)); return true; } else @@ -2398,43 +2397,40 @@ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *p } } - if (SECURITY_INFO_IS_READ_PROTECTED(prd->c.security_info)) - { - DDS_Security_PermissionsHandle permissions_handle; + if (!SECURITY_INFO_IS_READ_PROTECTED(prd->c.security_info)) + return true; - if ((permissions_handle = get_permissions_handle(pp, prd->c.proxypp)) == 0) - { - GVTRACE("Secure remote reader "PGUIDFMT" proxypp does not have permissions handle yet\n", PGUID(prd->e.guid)); - return false; - } + DDS_Security_PermissionsHandle permissions_handle; + if ((permissions_handle = get_permissions_handle(pp, prd->c.proxypp)) == 0) + { + GVTRACE("Secure remote reader "PGUIDFMT" proxypp does not have permissions handle yet\n", PGUID(prd->e.guid)); + return false; + } + + q_omg_shallow_copy_SubscriptionBuiltinTopicDataSecure(&subscription_data, &prd->e.guid, prd->c.xqos, &prd->c.security_info); + bool result = sc->access_control_context->check_remote_datareader(sc->access_control_context, permissions_handle, (int)domain_id, &subscription_data, &sec_relay_only, &exception); + if (!result) + { + if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, subscription_data.topic_name)) + EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote reader "PGUIDFMT": %s", PGUID(prd->e.guid)); else + DDS_Security_Exception_reset(&exception); + } + else + { + *relay_only = !!sec_relay_only; + q_omg_shallow_copy_TopicBuiltinTopicData(&topic_data, subscription_data.topic_name, subscription_data.type_name); + result = sc->access_control_context->check_remote_topic(sc->access_control_context, permissions_handle, (int)domain_id, &topic_data, &exception); + q_omg_shallow_free_TopicBuiltinTopicData(&topic_data); + if (!result) { - q_omg_shallow_copy_SubscriptionBuiltinTopicDataSecure(&subscription_data, &prd->e.guid, prd->c.xqos, &prd->c.security_info); - result = sc->access_control_context->check_remote_datareader(sc->access_control_context, permissions_handle, (int)domain_id, &subscription_data, &sec_relay_only, &exception); - if (!result) - { - if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, subscription_data.topic_name)) - EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote reader "PGUIDFMT": %s", PGUID(prd->e.guid)); - else - DDS_Security_Exception_reset(&exception); - } + if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, subscription_data.topic_name)) + EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote topic %s: %s", subscription_data.topic_name); else - { - *relay_only = !!sec_relay_only; - q_omg_shallow_copy_TopicBuiltinTopicData(&topic_data, subscription_data.topic_name, subscription_data.type_name); - result = sc->access_control_context->check_remote_topic(sc->access_control_context, permissions_handle, (int)domain_id, &topic_data, &exception); - q_omg_shallow_free_TopicBuiltinTopicData(&topic_data); - if (!result) - { - if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, subscription_data.topic_name)) - EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote topic %s: %s", subscription_data.topic_name); - else - DDS_Security_Exception_reset(&exception); - } - } - q_omg_shallow_free_SubscriptionBuiltinTopicDataSecure(&subscription_data); + DDS_Security_Exception_reset(&exception); } } + q_omg_shallow_free_SubscriptionBuiltinTopicDataSecure(&subscription_data); return result; } From 2aa0195d530fd2c72da79893dd28aa1c0ccb5d21 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Wed, 22 Apr 2020 14:17:42 +0200 Subject: [PATCH 174/238] Log category for not-allowed message depends on topic discovery protection state Signed-off-by: Dennis Potman --- .../ddsi/include/dds/ddsi/ddsi_security_omg.h | 1 + src/core/ddsi/src/ddsi_security_omg.c | 81 +++++++++---------- 2 files changed, 37 insertions(+), 45 deletions(-) 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 f87629a..e7c3214 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h @@ -113,6 +113,7 @@ struct dds_security_authentication *q_omg_participant_get_authentication(const s DDS_EXPORT struct dds_security_cryptography *q_omg_participant_get_cryptography(const struct participant *pp); +void q_omg_vlog_exception(const struct ddsrt_log_cfg *lc, uint32_t cat, DDS_Security_SecurityException *exception, const char *file, uint32_t line, const char *func, const char *fmt, va_list ap); void q_omg_log_exception(const struct ddsrt_log_cfg *lc, uint32_t cat, DDS_Security_SecurityException *exception, const char *file, uint32_t line, const char *func, const char *fmt, ...); /** diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 9ad902d..b4e46d4 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -55,6 +55,8 @@ #define EXCEPTION_LOG(gv,e,cat,...) \ q_omg_log_exception(&gv->logconfig, cat, e, __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) +#define EXCEPTION_VLOG(gv,e,cat,fmt,va_list) \ + q_omg_vlog_exception(&gv->logconfig, cat, e, __FILE__, __LINE__, DDS_FUNCTION, fmt, va_list) #define EXCEPTION_ERROR(gv,e,...) EXCEPTION_LOG(gv, e, DDS_LC_ERROR, __VA_ARGS__) #define EXCEPTION_WARNING(gv,e,...) EXCEPTION_LOG(gv, e, DDS_LC_WARNING, __VA_ARGS__) @@ -296,15 +298,12 @@ static struct dds_security_context * q_omg_security_get_secure_context_from_prox return NULL; } -void q_omg_log_exception(const struct ddsrt_log_cfg *lc, uint32_t cat, DDS_Security_SecurityException *exception, const char *file, uint32_t line, const char *func, const char *fmt, ...) +void q_omg_vlog_exception(const struct ddsrt_log_cfg *lc, uint32_t cat, DDS_Security_SecurityException *exception, const char *file, uint32_t line, const char *func, const char *fmt, va_list ap) { char logbuffer[512]; - va_list ap; int l; - va_start (ap, fmt); l = vsnprintf(logbuffer, sizeof(logbuffer), fmt, ap); - va_end (ap); if ((size_t) l >= sizeof(logbuffer)) { logbuffer[sizeof(logbuffer)-1] = '\0'; @@ -313,6 +312,14 @@ void q_omg_log_exception(const struct ddsrt_log_cfg *lc, uint32_t cat, DDS_Secur DDS_Security_Exception_reset(exception); } +void q_omg_log_exception(const struct ddsrt_log_cfg *lc, uint32_t cat, DDS_Security_SecurityException *exception, const char *file, uint32_t line, const char *func, const char *fmt, ...) +{ + va_list ap; + va_start (ap, fmt); + q_omg_vlog_exception(lc, cat, exception, file, line, func, fmt, ap); + va_end (ap); +} + static void free_pending_match(struct pending_match *match) { if (match) @@ -1390,6 +1397,20 @@ static bool is_topic_discovery_protected(DDS_Security_PermissionsHandle permissi return false; } +static void handle_not_allowed(const struct ddsi_domaingv *gv, DDS_Security_PermissionsHandle permissions_handle, dds_security_access_control * ac_ctx, + DDS_Security_SecurityException * exception, const char * topic_name, const char * fmt, ...) +{ + /* In case topic has discovery protection enabled: don't log in log category error, as the message + will contain the topic name which may be considered as sensitive information */ + va_list ap; + bool discovery_protected = is_topic_discovery_protected(permissions_handle, ac_ctx, topic_name); + va_start (ap, fmt); + EXCEPTION_VLOG(gv, exception, discovery_protected ? DDS_LC_TRACE : DDS_LC_ERROR, fmt, ap); + va_end (ap); + if (discovery_protected) + DDS_Security_Exception_reset(exception); +} + bool q_omg_security_check_create_topic(const struct ddsi_domaingv *gv, const ddsi_guid_t *pp_guid, const char *topic_name, const struct dds_qos *qos) { bool result = true; @@ -1406,13 +1427,7 @@ bool q_omg_security_check_create_topic(const struct ddsi_domaingv *gv, const dds q_omg_shallow_copy_security_qos(&topic_qos, qos); result = sc->access_control_context->check_create_topic(sc->access_control_context, pp->sec_attr->permissions_handle, (DDS_Security_DomainId)gv->config.domainId, topic_name, &topic_qos, &exception); if (!result) - { - /*log if the topic discovery is not protected*/ - if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, topic_name)) - EXCEPTION_ERROR(gv, &exception, "Local topic permission denied"); - else - DDS_Security_Exception_reset(&exception); - } + handle_not_allowed(gv, pp->sec_attr->permissions_handle, sc->access_control_context, &exception, topic_name, "Local topic permission denied"); q_omg_shallow_free_security_qos(&topic_qos); } thread_state_asleep (lookup_thread_state ()); @@ -1440,13 +1455,7 @@ bool q_omg_security_check_create_writer(struct participant *pp, uint32_t domain_ result = sc->access_control_context->check_create_datawriter(sc->access_control_context, pp->sec_attr->permissions_handle, (DDS_Security_DomainId)domain_id, topic_name, &security_qos, &partitions, NULL, &exception); if (!result) - { - /*log if the topic discovery is not protected*/ - if (!is_topic_discovery_protected( pp->sec_attr->permissions_handle, sc->access_control_context, topic_name)) - EXCEPTION_ERROR(pp->e.gv, &exception, "Local topic permission denied"); - else - DDS_Security_Exception_reset(&exception); - } + handle_not_allowed(pp->e.gv, pp->sec_attr->permissions_handle, sc->access_control_context, &exception, topic_name, "Local topic permission denied"); q_omg_shallow_free_security_qos(&security_qos); g_omg_shallow_free_StringSeq(&partitions.name); @@ -1561,13 +1570,7 @@ bool q_omg_security_check_create_reader(struct participant *pp, uint32_t domain_ result = sc->access_control_context->check_create_datareader(sc->access_control_context, pp->sec_attr->permissions_handle, (DDS_Security_DomainId)domain_id, topic_name, &security_qos, &partitions, NULL, &exception); if (!result) - { - /*log if the topic discovery is not protected*/ - if (!is_topic_discovery_protected( pp->sec_attr->permissions_handle, sc->access_control_context, topic_name)) - EXCEPTION_ERROR(pp->e.gv, &exception, "Reader is not permitted"); - else - DDS_Security_Exception_reset(&exception); - } + handle_not_allowed(pp->e.gv, pp->sec_attr->permissions_handle, sc->access_control_context, &exception, topic_name, "Reader is not permitted"); q_omg_shallow_free_security_qos(&security_qos); g_omg_shallow_free_StringSeq(&partitions.name); @@ -2169,10 +2172,8 @@ bool q_omg_security_check_remote_writer_permissions(const struct proxy_writer *p bool result = sc->access_control_context->check_remote_datawriter(sc->access_control_context, permissions_handle, (int)domain_id, &publication_data, &exception); if (!result) { - if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, publication_data.topic_name)) - EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote writer "PGUIDFMT": %s", PGUID(pwr->e.guid)); - else - DDS_Security_Exception_reset(&exception); + handle_not_allowed(gv, pp->sec_attr->permissions_handle, sc->access_control_context, &exception, publication_data.topic_name, + "Access control does not allow remote writer "PGUIDFMT": %s", PGUID(pwr->e.guid)); } else { @@ -2180,12 +2181,8 @@ bool q_omg_security_check_remote_writer_permissions(const struct proxy_writer *p result = sc->access_control_context->check_remote_topic(sc->access_control_context, permissions_handle, (int)domain_id, &topic_data, &exception); q_omg_shallow_free_TopicBuiltinTopicData(&topic_data); if (!result) - { - if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, publication_data.topic_name)) - EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote topic %s: %s", publication_data.topic_name); - else - DDS_Security_Exception_reset(&exception); - } + handle_not_allowed(gv, pp->sec_attr->permissions_handle, sc->access_control_context, &exception, publication_data.topic_name, + "Access control does not allow remote topic %s: %s", publication_data.topic_name); } q_omg_shallow_free_PublicationBuiltinTopicDataSecure(&publication_data); @@ -2411,10 +2408,8 @@ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *p bool result = sc->access_control_context->check_remote_datareader(sc->access_control_context, permissions_handle, (int)domain_id, &subscription_data, &sec_relay_only, &exception); if (!result) { - if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, subscription_data.topic_name)) - EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote reader "PGUIDFMT": %s", PGUID(prd->e.guid)); - else - DDS_Security_Exception_reset(&exception); + handle_not_allowed(gv, pp->sec_attr->permissions_handle, sc->access_control_context, &exception, subscription_data.topic_name, + "Access control does not allow remote reader "PGUIDFMT": %s", PGUID(prd->e.guid)); } else { @@ -2423,12 +2418,8 @@ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *p result = sc->access_control_context->check_remote_topic(sc->access_control_context, permissions_handle, (int)domain_id, &topic_data, &exception); q_omg_shallow_free_TopicBuiltinTopicData(&topic_data); if (!result) - { - if (!is_topic_discovery_protected(pp->sec_attr->permissions_handle, sc->access_control_context, subscription_data.topic_name)) - EXCEPTION_ERROR(gv, &exception, "Access control does not allow remote topic %s: %s", subscription_data.topic_name); - else - DDS_Security_Exception_reset(&exception); - } + handle_not_allowed(gv, pp->sec_attr->permissions_handle, sc->access_control_context, &exception, subscription_data.topic_name, + "Access control does not allow remote topic %s: %s", subscription_data.topic_name); } q_omg_shallow_free_SubscriptionBuiltinTopicDataSecure(&subscription_data); From 4ac06895f0b0969c32ebfec31bec6964bf32f015 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Wed, 22 Apr 2020 15:21:46 +0200 Subject: [PATCH 175/238] Fix format strings for handle_not_allowed calls and add format attribute check Signed-off-by: Dennis Potman --- src/core/ddsi/src/ddsi_security_omg.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index b4e46d4..3e8066a 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -55,8 +55,8 @@ #define EXCEPTION_LOG(gv,e,cat,...) \ q_omg_log_exception(&gv->logconfig, cat, e, __FILE__, __LINE__, DDS_FUNCTION, __VA_ARGS__) -#define EXCEPTION_VLOG(gv,e,cat,fmt,va_list) \ - q_omg_vlog_exception(&gv->logconfig, cat, e, __FILE__, __LINE__, DDS_FUNCTION, fmt, va_list) +#define EXCEPTION_VLOG(gv,e,cat,fmt,ap) \ + q_omg_vlog_exception(&gv->logconfig, cat, e, __FILE__, __LINE__, DDS_FUNCTION, fmt, ap) #define EXCEPTION_ERROR(gv,e,...) EXCEPTION_LOG(gv, e, DDS_LC_ERROR, __VA_ARGS__) #define EXCEPTION_WARNING(gv,e,...) EXCEPTION_LOG(gv, e, DDS_LC_WARNING, __VA_ARGS__) @@ -1397,8 +1397,17 @@ static bool is_topic_discovery_protected(DDS_Security_PermissionsHandle permissi return false; } +static void handle_not_allowed( + const struct ddsi_domaingv *gv, + DDS_Security_PermissionsHandle permissions_handle, + dds_security_access_control * ac_ctx, + DDS_Security_SecurityException * exception, + const char * topic_name, + const char * fmt, + ...) ddsrt_attribute_format ((printf, 6, 7)); + static void handle_not_allowed(const struct ddsi_domaingv *gv, DDS_Security_PermissionsHandle permissions_handle, dds_security_access_control * ac_ctx, - DDS_Security_SecurityException * exception, const char * topic_name, const char * fmt, ...) + DDS_Security_SecurityException * exception, const char * topic_name, const char * fmt, ...) { /* In case topic has discovery protection enabled: don't log in log category error, as the message will contain the topic name which may be considered as sensitive information */ @@ -2173,7 +2182,7 @@ bool q_omg_security_check_remote_writer_permissions(const struct proxy_writer *p if (!result) { handle_not_allowed(gv, pp->sec_attr->permissions_handle, sc->access_control_context, &exception, publication_data.topic_name, - "Access control does not allow remote writer "PGUIDFMT": %s", PGUID(pwr->e.guid)); + "Access control does not allow remote writer "PGUIDFMT, PGUID(pwr->e.guid)); } else { @@ -2182,7 +2191,7 @@ bool q_omg_security_check_remote_writer_permissions(const struct proxy_writer *p q_omg_shallow_free_TopicBuiltinTopicData(&topic_data); if (!result) handle_not_allowed(gv, pp->sec_attr->permissions_handle, sc->access_control_context, &exception, publication_data.topic_name, - "Access control does not allow remote topic %s: %s", publication_data.topic_name); + "Access control does not allow remote topic %s", publication_data.topic_name); } q_omg_shallow_free_PublicationBuiltinTopicDataSecure(&publication_data); @@ -2409,7 +2418,7 @@ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *p if (!result) { handle_not_allowed(gv, pp->sec_attr->permissions_handle, sc->access_control_context, &exception, subscription_data.topic_name, - "Access control does not allow remote reader "PGUIDFMT": %s", PGUID(prd->e.guid)); + "Access control does not allow remote reader "PGUIDFMT, PGUID(prd->e.guid)); } else { @@ -2419,7 +2428,7 @@ bool q_omg_security_check_remote_reader_permissions(const struct proxy_reader *p q_omg_shallow_free_TopicBuiltinTopicData(&topic_data); if (!result) handle_not_allowed(gv, pp->sec_attr->permissions_handle, sc->access_control_context, &exception, subscription_data.topic_name, - "Access control does not allow remote topic %s: %s", subscription_data.topic_name); + "Access control does not allow remote topic %s", subscription_data.topic_name); } q_omg_shallow_free_SubscriptionBuiltinTopicDataSecure(&subscription_data); From 623a5c02bdfe6a54d25440de1acd5f5c8a56bc88 Mon Sep 17 00:00:00 2001 From: Marcel Jordense Date: Fri, 1 May 2020 10:57:38 +0200 Subject: [PATCH 176/238] Correct handshake tokens verification w.r.t. optional fields Signed-off-by: Marcel Jordense --- docs/manual/options.md | 14 +- etc/cyclonedds.rnc | 10 + etc/cyclonedds.xsd | 12 + .../ddsi/include/dds/ddsi/ddsi_domaingv.h | 1 + src/core/ddsi/include/dds/ddsi/q_config.h | 1 + src/core/ddsi/src/ddsi_security_omg.c | 5 + src/core/ddsi/src/q_config.c | 4 +- .../authentication/src/authentication.c | 332 +++++++++--------- .../dds/security/core/dds_security_utils.h | 12 +- src/security/core/src/dds_security_utils.c | 12 +- 10 files changed, 227 insertions(+), 176 deletions(-) diff --git a/docs/manual/options.md b/docs/manual/options.md index b343bf1..85a1a3c 100644 --- a/docs/manual/options.md +++ b/docs/manual/options.md @@ -262,7 +262,7 @@ The default value is: "". #### //CycloneDDS/Domain/DDSSecurity/Authentication -Children: [IdentityCA](#cycloneddsdomainddssecurityauthenticationidentityca), [IdentityCertificate](#cycloneddsdomainddssecurityauthenticationidentitycertificate), [Library](#cycloneddsdomainddssecurityauthenticationlibrary), [Password](#cycloneddsdomainddssecurityauthenticationpassword), [PrivateKey](#cycloneddsdomainddssecurityauthenticationprivatekey), [TrustedCADirectory](#cycloneddsdomainddssecurityauthenticationtrustedcadirectory) +Children: [IdentityCA](#cycloneddsdomainddssecurityauthenticationidentityca), [IdentityCertificate](#cycloneddsdomainddssecurityauthenticationidentitycertificate), [IncludeOptionalFields](#cycloneddsdomainddssecurityauthenticationincludeoptionalfields), [Library](#cycloneddsdomainddssecurityauthenticationlibrary), [Password](#cycloneddsdomainddssecurityauthenticationpassword), [PrivateKey](#cycloneddsdomainddssecurityauthenticationprivatekey), [TrustedCADirectory](#cycloneddsdomainddssecurityauthenticationtrustedcadirectory) This element configures the Authentication plugin of the DDS Security @@ -311,6 +311,18 @@ MIIDjjCCAnYCCQDCEu9...6rmT87dhTo=
    -----END CERTIFICATE----- +##### //CycloneDDS/Domain/DDSSecurity/Authentication/IncludeOptionalFields +Boolean + +The authentication handshake tokens may contain optional fields to be +included for finding interoperability problems. + +If this parameter is set to true the optional fields are included in the +handshake token exchange. + +The default value is: "false". + + ##### //CycloneDDS/Domain/DDSSecurity/Authentication/Library Attributes: [finalizeFunction](#cycloneddsdomainddssecurityauthenticationlibraryfinalizefunction), [initFunction](#cycloneddsdomainddssecurityauthenticationlibraryinitfunction), [path](#cycloneddsdomainddssecurityauthenticationlibrarypath) diff --git a/etc/cyclonedds.rnc b/etc/cyclonedds.rnc index 1ee2c4d..7e49b53 100644 --- a/etc/cyclonedds.rnc +++ b/etc/cyclonedds.rnc @@ -268,6 +268,16 @@ MIIDjjCCAnYCCQDCEu9...6rmT87dhTo=
    text } & [ a:documentation [ xml:lang="en" """ +

    The authentication handshake tokens may contain optional fields to be +included for finding interoperability problems. + +If this parameter is set to true the optional fields are included in the +handshake token exchange.

    The default value is: +"false".

    """ ] ] + element IncludeOptionalFields { + xsd:boolean + }? + & [ a:documentation [ xml:lang="en" """

    This element specifies the library to be loaded as the DDS Security Access Control plugin.

    """ ] ] element Library { diff --git a/etc/cyclonedds.xsd b/etc/cyclonedds.xsd index d552a5c..0af9bc2 100644 --- a/etc/cyclonedds.xsd +++ b/etc/cyclonedds.xsd @@ -327,6 +327,7 @@ specification.</p> + @@ -419,6 +420,17 @@ MIIDjjCCAnYCCQDCEu9...6rmT87dhTo=<br> -----END CERTIFICATE-----</IdentityCertificate></p> + + + +<p>The authentication handshake tokens may contain optional fields to be +included for finding interoperability problems. + +If this parameter is set to true the optional fields are included in the +handshake token exchange.</p><p>The default value is: +&quot;false&quot;.</p> + + diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h b/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h index 68f040e..8446aaf 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_domaingv.h @@ -330,6 +330,7 @@ struct ddsi_domaingv { #ifdef DDSI_INCLUDE_SECURITY struct dds_security_context *security_context; struct ddsi_hsadmin *hsadmin; + bool handshake_include_optional; #endif }; diff --git a/src/core/ddsi/include/dds/ddsi/q_config.h b/src/core/ddsi/include/dds/ddsi/q_config.h index dfc16bd..d9628e2 100644 --- a/src/core/ddsi/include/dds/ddsi/q_config.h +++ b/src/core/ddsi/include/dds/ddsi/q_config.h @@ -174,6 +174,7 @@ typedef struct authentication_properties_type{ char *private_key; char *password; char *trusted_ca_dir; + bool include_optional_fields; } authentication_properties_type; typedef struct access_control_properties_type{ diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 3e8066a..36d5a3c 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -735,6 +735,11 @@ void q_omg_security_init (struct ddsi_domaingv *gv) ddsrt_mutex_init (&sc->omg_security_lock); gv->security_context = sc; + if (gv->config.omg_security_configuration) + gv->handshake_include_optional = gv->config.omg_security_configuration->cfg.authentication_properties.include_optional_fields; + else + gv->handshake_include_optional = false; + ddsi_handshake_admin_init(gv); } diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 515a4c6..9dcf5ec 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -353,7 +353,9 @@ The value of the password property shall be interpreted as the Base64 encoding o If the password property is not present, then the value supplied in the private_key property must contain the unencrypted private key.

    ") }, { LEAF ("TrustedCADirectory"), 1, "", RELOFF (config_omg_security_listelem, cfg.authentication_properties.trusted_ca_dir), 0, uf_string, ff_free, pf_string, BLURB("

    Trusted CA Directory which contains trusted CA certificates as separated files.

    ") }, - + { LEAF ("IncludeOptionalFields"), 1, "false", RELOFF (config_omg_security_listelem, cfg.authentication_properties.include_optional_fields), 0, uf_boolean, 0, pf_boolean, + BLURB("

    The authentication handshake tokens may contain optional fields to be included for finding interoperability problems.\n\ +If this parameter is set to true the optional fields are included in the handshake token exchange.

    ") }, END_MARKER }; diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index 0ff0864..490654b 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -200,6 +200,7 @@ typedef struct dds_security_authentication_impl struct dds_security_timed_cb_data *timed_callbacks; struct dds_security_timed_dispatcher_t *dispatcher; X509Seq trustedCAList; + bool include_optional; } dds_security_authentication_impl; /* data type for timer dispatcher */ @@ -1123,9 +1124,9 @@ DDS_Security_ValidationResult_t begin_handshake_request(dds_security_authenticat LocalIdentityInfo *localIdent; RemoteIdentityInfo *remoteIdent; EVP_PKEY *dhkey; - DDS_Security_BinaryProperty_t *tokens, *c_id, *c_perm, *c_pdata, *c_dsign_algo, *c_kagree_algo, *hash_c1, *dh1, *challenge; unsigned char *certData, *dhPubKeyData = NULL; uint32_t certDataSize, dhPubKeyDataSize; + uint32_t tsz = impl->include_optional ? 8 : 7; int created = 0; if (!instance || !handshake_handle || !handshake_message || !serialized_local_participant_data) @@ -1183,36 +1184,30 @@ DDS_Security_ValidationResult_t begin_handshake_request(dds_security_authenticat if (localIdent->pdata._length == 0) DDS_Security_OctetSeq_copy(&localIdent->pdata, serialized_local_participant_data); - tokens = DDS_Security_BinaryPropertySeq_allocbuf(8); - c_id = &tokens[0]; - c_perm = &tokens[1]; - c_pdata = &tokens[2]; - c_dsign_algo = &tokens[3]; - c_kagree_algo = &tokens[4]; - hash_c1 = &tokens[5]; - dh1 = &tokens[6]; - challenge = &tokens[7]; + DDS_Security_BinaryProperty_t *tokens = DDS_Security_BinaryPropertySeq_allocbuf(tsz); + uint32_t idx = 0; - DDS_Security_BinaryProperty_set_by_ref(c_id, "c.id", certData, certDataSize); - DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", localIdent->permissionsDocument ? localIdent->permissionsDocument : ""); - DDS_Security_BinaryProperty_set_by_value(c_pdata, "c.pdata", serialized_local_participant_data->_buffer, serialized_local_participant_data->_length); - DDS_Security_BinaryProperty_set_by_string(c_dsign_algo, "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); - DDS_Security_BinaryProperty_set_by_string(c_kagree_algo, "c.kagree_algo", get_kagree_algo(localIdent->kagreeAlgoKind)); + DDS_Security_BinaryProperty_set_by_ref(&tokens[idx++], "c.id", certData, certDataSize); + DDS_Security_BinaryProperty_set_by_string(&tokens[idx++], "c.perm", localIdent->permissionsDocument ? localIdent->permissionsDocument : ""); + DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "c.pdata", serialized_local_participant_data->_buffer, serialized_local_participant_data->_length); + DDS_Security_BinaryProperty_set_by_string(&tokens[idx++], "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); + DDS_Security_BinaryProperty_set_by_string(&tokens[idx++], "c.kagree_algo", get_kagree_algo(localIdent->kagreeAlgoKind)); /* Todo: including hash_c1 is optional (conform spec); add a configuration option to leave it out */ { DDS_Security_BinaryPropertySeq bseq = { ._length = 5, ._buffer = tokens }; get_hash_binary_property_seq(&bseq, handshake->hash_c1); - DDS_Security_BinaryProperty_set_by_value(hash_c1, "hash_c1", handshake->hash_c1, sizeof(HashValue_t)); + if (impl->include_optional) + DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "hash_c1", handshake->hash_c1, sizeof(HashValue_t)); } /* Set the DH public key associated with the local participant in dh1 property */ assert(dhPubKeyData); assert(dhPubKeyDataSize < 1200); - DDS_Security_BinaryProperty_set_by_ref(dh1, "dh1", dhPubKeyData, dhPubKeyDataSize); + DDS_Security_BinaryProperty_set_by_ref(&tokens[idx++], "dh1", dhPubKeyData, dhPubKeyDataSize); /* Set the challenge in challenge1 property */ - DDS_Security_BinaryProperty_set_by_value(challenge, "challenge1", relation->lchallenge->value, sizeof(AuthenticationChallenge)); + DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "challenge1", relation->lchallenge->value, sizeof(AuthenticationChallenge)); (void)ddsrt_hh_add(impl->objectHash, handshake); @@ -1221,7 +1216,7 @@ DDS_Security_ValidationResult_t begin_handshake_request(dds_security_authenticat handshake_message->class_id = ddsrt_strdup(AUTH_HANDSHAKE_REQUEST_TOKEN_ID); handshake_message->properties._length = 0; handshake_message->properties._buffer = NULL; - handshake_message->binary_properties._length = 8; + handshake_message->binary_properties._length = tsz; handshake_message->binary_properties._buffer = tokens; *handshake_handle = HANDSHAKE_HANDLE(handshake); @@ -1372,10 +1367,26 @@ static X509 *load_X509_certificate_from_binprop (const DDS_Security_BinaryProper return cert; } +static DDS_Security_BinaryProperty_t * +create_dhkey_property(const char *name, EVP_PKEY *pkey, AuthenticationAlgoKind_t kagreeAlgoKind, DDS_Security_SecurityException *ex) +{ + DDS_Security_BinaryProperty_t *prop; + unsigned char *data; + uint32_t len; + + if (dh_public_key_to_oct(pkey, kagreeAlgoKind, &data, &len, ex) != DDS_SECURITY_VALIDATION_OK) + return NULL; + + prop = DDS_Security_BinaryProperty_alloc(); + DDS_Security_BinaryProperty_set_by_ref(prop, name, data, len); + return prop; +} + static DDS_Security_ValidationResult_t validate_handshake_token_impl (const DDS_Security_HandshakeMessageToken *token, enum handshake_token_type token_type, - HandshakeInfo *handshake, EVP_PKEY **pdhkey_reply, X509Seq *trusted_ca_list, EVP_PKEY **pdhkey_req, X509 **identityCert, DDS_Security_SecurityException *ex) + HandshakeInfo *handshake, X509Seq *trusted_ca_list, const DDS_Security_BinaryProperty_t *dh1_ref, const DDS_Security_BinaryProperty_t *dh2_ref, DDS_Security_SecurityException *ex) { IdentityRelation * const relation = handshake->relation; + X509 *identityCert = NULL; const DDS_Security_BinaryProperty_t *c_pdata = NULL; AuthenticationAlgoKind_t dsignAlgoKind = AUTH_ALGO_KIND_UNKNOWN, kagreeAlgoKind = AUTH_ALGO_KIND_UNKNOWN; const DDS_Security_BinaryProperty_t *dh1 = NULL, *dh2 = NULL; @@ -1385,10 +1396,8 @@ static DDS_Security_ValidationResult_t validate_handshake_token_impl (const DDS_ const char *token_class_id = NULL; assert (relation); - assert (pdhkey_req == NULL || *pdhkey_req == NULL); - assert (pdhkey_reply == NULL || *pdhkey_reply == NULL); - assert (pdhkey_req == NULL || token_type == HS_TOKEN_REQ); - assert (pdhkey_reply == NULL || token_type == HS_TOKEN_REPLY); + assert (dh1_ref != NULL || token_type == HS_TOKEN_REQ); + assert (dh2_ref != NULL || token_type == HS_TOKEN_REQ || token_type == HS_TOKEN_REPLY); switch (token_type) { @@ -1407,9 +1416,14 @@ static DDS_Security_ValidationResult_t validate_handshake_token_impl (const DDS_ if ((c_id = find_required_nonempty_binprop (token, "c.id", ex)) == NULL) return DDS_SECURITY_VALIDATION_FAILED; - if ((*identityCert = load_X509_certificate_from_binprop (c_id, relation->localIdentity->identityCA, trusted_ca_list, ex)) == NULL) + if ((identityCert = load_X509_certificate_from_binprop (c_id, relation->localIdentity->identityCA, trusted_ca_list, ex)) == NULL) return DDS_SECURITY_VALIDATION_FAILED; + /* TODO: check if an identity certificate was already associated with the remote identity and when that is the case both should be the same */ + if (relation->remoteIdentity->identityCert) + X509_free (relation->remoteIdentity->identityCert); + relation->remoteIdentity->identityCert = identityCert; + if ((c_perm = find_required_binprop (token, "c.perm", ex)) == NULL) return DDS_SECURITY_VALIDATION_FAILED; if (c_perm->value._length > 0) @@ -1420,7 +1434,7 @@ static DDS_Security_ValidationResult_t validate_handshake_token_impl (const DDS_ if ((c_pdata = find_required_binprop (token, "c.pdata", ex)) == NULL) return DDS_SECURITY_VALIDATION_FAILED; - if (validate_pdata (&c_pdata->value, *identityCert, ex) != DDS_SECURITY_VALIDATION_OK) + if (validate_pdata (&c_pdata->value, identityCert, ex) != DDS_SECURITY_VALIDATION_OK) return DDS_SECURITY_VALIDATION_FAILED; if ((c_dsign_algo = find_required_nonempty_binprop (token, "c.dsign_algo", ex)) == NULL) @@ -1438,29 +1452,55 @@ static DDS_Security_ValidationResult_t validate_handshake_token_impl (const DDS_ (void) compute_hash_value ((token_type == HS_TOKEN_REQ) ? handshake->hash_c1 : handshake->hash_c2, binary_properties, 5, NULL); } - if ((dh1 = find_required_nonempty_binprop (token, "dh1", ex)) == NULL) - return DDS_SECURITY_VALIDATION_FAILED; - if ((challenge1 = find_required_binprop_exactsize (token, "challenge1", sizeof (AuthenticationChallenge), ex)) == NULL) - return DDS_SECURITY_VALIDATION_FAILED; if (token_type == HS_TOKEN_REQ) { - if (dh_oct_to_public_key (pdhkey_req, kagreeAlgoKind, dh1->value._buffer, dh1->value._length, ex) != DDS_SECURITY_VALIDATION_OK) + EVP_PKEY *pdhkey_req = NULL; + + if ((dh1 = find_required_nonempty_binprop (token, "dh1", ex)) == NULL) return DDS_SECURITY_VALIDATION_FAILED; + if (dh_oct_to_public_key (&pdhkey_req, kagreeAlgoKind, dh1->value._buffer, dh1->value._length, ex) != DDS_SECURITY_VALIDATION_OK) + return DDS_SECURITY_VALIDATION_FAILED; + if (handshake->rdh) + EVP_PKEY_free (handshake->rdh); + handshake->rdh = pdhkey_req; } + else + { + dh1 = DDS_Security_DataHolder_find_binary_property (token, "dh1"); + if (dh1 && !DDS_Security_BinaryProperty_equal(dh1_ref, dh1)) + return set_exception (ex, "process_handshake: %s token property dh1 not correct", (token_type == HS_TOKEN_REPLY) ? "Reply" : "Final"); + dh1 = dh1_ref; + } + + if ((challenge1 = find_required_binprop_exactsize (token, "challenge1", sizeof (AuthenticationChallenge), ex)) == NULL) + return DDS_SECURITY_VALIDATION_FAILED; if (token_type == HS_TOKEN_REPLY || token_type == HS_TOKEN_FINAL) { - if ((dh2 = find_required_nonempty_binprop (token, "dh2", ex)) == NULL) - return DDS_SECURITY_VALIDATION_FAILED; if ((challenge2 = find_required_binprop_exactsize (token, "challenge2", sizeof (AuthenticationChallenge), ex)) == NULL) return DDS_SECURITY_VALIDATION_FAILED; if ((signature = find_required_nonempty_binprop (token, "signature", ex)) == NULL) return DDS_SECURITY_VALIDATION_FAILED; - } - if (token_type == HS_TOKEN_REPLY) - { - if (dh_oct_to_public_key (pdhkey_reply, kagreeAlgoKind, dh2->value._buffer, dh2->value._length, ex) != DDS_SECURITY_VALIDATION_OK) - return DDS_SECURITY_VALIDATION_FAILED; + + if (token_type == HS_TOKEN_REPLY) + { + EVP_PKEY *pdhkey_reply = NULL; + + if ((dh2 = find_required_nonempty_binprop (token, "dh2", ex)) == NULL) + return DDS_SECURITY_VALIDATION_FAILED; + if (dh_oct_to_public_key (&pdhkey_reply, kagreeAlgoKind, dh2->value._buffer, dh2->value._length, ex) != DDS_SECURITY_VALIDATION_OK) + return DDS_SECURITY_VALIDATION_FAILED; + if (handshake->rdh) + EVP_PKEY_free (handshake->rdh); + handshake->rdh = pdhkey_reply; + } + else + { + dh2 = DDS_Security_DataHolder_find_binary_property (token, "dh2"); + if (dh2 && !DDS_Security_BinaryProperty_equal(dh2_ref, dh2)) + return set_exception (ex, "process_handshake: Final token property dh2 not correct"); + dh2 = dh2_ref; + } } /* When validate_remote_identity was provided with a remote_auth_request_token then the future_challenge in @@ -1506,26 +1546,12 @@ static DDS_Security_ValidationResult_t validate_handshake_token_impl (const DDS_ return set_exception (ex, "process_handshake: HandshakeMessageToken property challenge1 does not match future_challenge"); } - if (token_type == HS_TOKEN_REQ) - { - if (!EVP_PKEY_up_ref (*pdhkey_req)) - return set_exception (ex, "process_handshake: failed to increment refcount of DH key"); - handshake->rdh = *pdhkey_req; - } - if (token_type == HS_TOKEN_REQ || token_type == HS_TOKEN_REPLY) { - assert (*identityCert != NULL); assert (dsignAlgoKind != AUTH_ALGO_KIND_UNKNOWN); assert (kagreeAlgoKind != AUTH_ALGO_KIND_UNKNOWN); assert (c_pdata != NULL); - /* TODO: check if an identity certificate was already associated with the remote identity and when that is the case both should be the same */ - if (relation->remoteIdentity->identityCert) - X509_free (relation->remoteIdentity->identityCert); - if (!X509_up_ref (*identityCert)) - return set_exception (ex, "process_handshake: failed to increment refcount of identity certificate"); - relation->remoteIdentity->identityCert = *identityCert; relation->remoteIdentity->dsignAlgoKind = dsignAlgoKind; relation->remoteIdentity->kagreeAlgoKind = kagreeAlgoKind; DDS_Security_OctetSeq_copy (&relation->remoteIdentity->pdata, &c_pdata->value); @@ -1551,6 +1577,7 @@ static DDS_Security_ValidationResult_t validate_handshake_token_impl (const DDS_ result = validate_signature (public_key, (const DDS_Security_BinaryProperty_t *[]) { &hash_c1_val, challenge1, dh1, challenge2, dh2, &hash_c2_val }, 6, signature->value._buffer, signature->value._length, ex); EVP_PKEY_free (public_key); + if (result != DDS_SECURITY_VALIDATION_OK) return result; } @@ -1559,34 +1586,30 @@ static DDS_Security_ValidationResult_t validate_handshake_token_impl (const DDS_ } static DDS_Security_ValidationResult_t validate_handshake_token(const DDS_Security_HandshakeMessageToken *token, enum handshake_token_type token_type, HandshakeInfo *handshake, - EVP_PKEY **pdhkey_reply, X509Seq *trusted_ca_list, DDS_Security_SecurityException *ex) + X509Seq *trusted_ca_list, const DDS_Security_BinaryProperty_t *dh1_ref, const DDS_Security_BinaryProperty_t *dh2_ref, DDS_Security_SecurityException *ex) { - X509 *identityCert = NULL; - EVP_PKEY *pdhkey_req = NULL; - - const DDS_Security_ValidationResult_t ret = validate_handshake_token_impl (token, token_type, handshake, pdhkey_reply, trusted_ca_list, - (token_type == HS_TOKEN_REQ) ? &pdhkey_req : NULL, &identityCert, ex); + const DDS_Security_ValidationResult_t ret = validate_handshake_token_impl (token, token_type, handshake, trusted_ca_list, dh1_ref, dh2_ref, ex); if (ret != DDS_SECURITY_VALIDATION_OK) { - IdentityRelation *relation = handshake->relation; - if (relation->remoteIdentity->identityCert) + if (token_type == HS_TOKEN_REQ || token_type == HS_TOKEN_REPLY) { - X509_free (relation->remoteIdentity->identityCert); - relation->remoteIdentity->identityCert = NULL; + IdentityRelation *relation = handshake->relation; + + if (relation->remoteIdentity->identityCert) + { + X509_free (relation->remoteIdentity->identityCert); + relation->remoteIdentity->identityCert = NULL; + } + + if (handshake->rdh) + { + EVP_PKEY_free (handshake->rdh); + handshake->rdh = NULL; + } } - if (pdhkey_reply && *pdhkey_reply) - EVP_PKEY_free (*pdhkey_reply); } - if (pdhkey_req) - EVP_PKEY_free (pdhkey_req); - if (identityCert) - { - /* free id cert also when validation succeeded, because the refcount was increased - when assigning this cert to relation->remoteIdentity */ - X509_free (identityCert); - } return ret; } @@ -1602,10 +1625,9 @@ DDS_Security_ValidationResult_t begin_handshake_reply(dds_security_authenticatio LocalIdentityInfo *localIdent; RemoteIdentityInfo *remoteIdent; EVP_PKEY *dhkeyLocal = NULL; - DDS_Security_BinaryProperty_t *tokens, *c_id, *c_perm, *c_pdata, *c_dsign_algo, *c_kagree_algo, *hash_c1, *hash_c2, *dh1, *dh2, *challenge1, *challenge2, *signature; - const DDS_Security_BinaryProperty_t *hash_c1_ref, *dh1_ref; unsigned char *certData, *dhPubKeyData; - uint32_t certDataSize, dhPubKeyDataSize, tokenSize; + uint32_t certDataSize, dhPubKeyDataSize; + uint32_t tsz = impl->include_optional ? 12 : 9; int created = 0; if (!instance || !handshake_handle || !handshake_message_out || !handshake_message_in || !serialized_local_participant_data) @@ -1652,7 +1674,7 @@ DDS_Security_ValidationResult_t begin_handshake_reply(dds_security_authenticatio assert(relation); } - if (validate_handshake_token(handshake_message_in, HS_TOKEN_REQ, handshake, NULL, &(impl->trustedCAList), ex) != DDS_SECURITY_VALIDATION_OK) + if (validate_handshake_token(handshake_message_in, HS_TOKEN_REQ, handshake, &(impl->trustedCAList), NULL, NULL, ex) != DDS_SECURITY_VALIDATION_OK) goto err_inv_token; if (get_certificate_contents(localIdent->identityCert, &certData, &certDataSize, ex) != DDS_SECURITY_VALIDATION_OK) goto err_alloc_cid; @@ -1672,58 +1694,44 @@ DDS_Security_ValidationResult_t begin_handshake_reply(dds_security_authenticatio if (localIdent->pdata._length == 0) DDS_Security_OctetSeq_copy(&localIdent->pdata, serialized_local_participant_data); - hash_c1_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "hash_c1"); - tokenSize = hash_c1_ref ? 12 : 11; - - tokens = DDS_Security_BinaryPropertySeq_allocbuf(tokenSize); - c_id = &tokens[0]; - c_perm = &tokens[1]; - c_pdata = &tokens[2]; - c_dsign_algo = &tokens[3]; - c_kagree_algo = &tokens[4]; - signature = &tokens[5]; - hash_c2 = &tokens[6]; - challenge2 = &tokens[7]; - dh2 = &tokens[8]; - challenge1 = &tokens[9]; - dh1 = &tokens[10]; - hash_c1 = hash_c1_ref ? &tokens[11] : NULL; + DDS_Security_BinaryProperty_t *tokens = DDS_Security_BinaryPropertySeq_allocbuf(tsz); + uint32_t idx = 0; /* Store the Identity Certificate associated with the local identify in c.id property */ - DDS_Security_BinaryProperty_set_by_ref(c_id, "c.id", certData, certDataSize); + DDS_Security_BinaryProperty_set_by_ref(&tokens[idx++], "c.id", certData, certDataSize); certData = NULL; - DDS_Security_BinaryProperty_set_by_string(c_perm, "c.perm", localIdent->permissionsDocument ? localIdent->permissionsDocument : ""); - DDS_Security_BinaryProperty_set_by_value(c_pdata, "c.pdata", serialized_local_participant_data->_buffer, serialized_local_participant_data->_length); - DDS_Security_BinaryProperty_set_by_string(c_dsign_algo, "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); - DDS_Security_BinaryProperty_set_by_string(c_kagree_algo, "c.kagree_algo", get_kagree_algo(remoteIdent->kagreeAlgoKind)); + DDS_Security_BinaryProperty_set_by_string(&tokens[idx++], "c.perm", localIdent->permissionsDocument ? localIdent->permissionsDocument : ""); + DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "c.pdata", serialized_local_participant_data->_buffer, serialized_local_participant_data->_length); + DDS_Security_BinaryProperty_set_by_string(&tokens[idx++], "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); + DDS_Security_BinaryProperty_set_by_string(&tokens[idx++], "c.kagree_algo", get_kagree_algo(remoteIdent->kagreeAlgoKind)); - /* Todo: including hash_c2 is optional (conform spec); add a configuration option to leave it out */ - { - DDS_Security_BinaryPropertySeq bseq = { ._length = 5, ._buffer = tokens }; - get_hash_binary_property_seq(&bseq, handshake->hash_c2); - DDS_Security_BinaryProperty_set_by_value(hash_c2, "hash_c2", handshake->hash_c2, sizeof(HashValue_t)); - } + /* Calculate the hash_c2 */ + DDS_Security_BinaryPropertySeq bseq = { ._length = 5, ._buffer = tokens }; + get_hash_binary_property_seq(&bseq, handshake->hash_c2); /* Set the DH public key associated with the local participant in dh2 property */ + DDS_Security_BinaryProperty_t *dh2 = &tokens[idx++]; DDS_Security_BinaryProperty_set_by_ref(dh2, "dh2", dhPubKeyData, dhPubKeyDataSize); - /* Set the DH public key associated with the local participant in hash_c1 property */ - if (hash_c1) - DDS_Security_BinaryProperty_set_by_value(hash_c1, "hash_c1", hash_c1_ref->value._buffer, hash_c1_ref->value._length); - - /* Set the DH public key associated with the local participant in dh1 property */ - if (dh1) - { - dh1_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "dh1"); - if (dh1_ref) - DDS_Security_BinaryProperty_set_by_value(dh1, "dh1", dh1_ref->value._buffer, dh1_ref->value._length); - } + /* Find the dh1 property from the received request token */ + const DDS_Security_BinaryProperty_t *dh1 = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "dh1"); + assert(dh1); assert(relation->rchallenge); + DDS_Security_BinaryProperty_t *challenge1 = &tokens[idx++]; DDS_Security_BinaryProperty_set_by_value(challenge1, "challenge1", relation->rchallenge->value, sizeof(AuthenticationChallenge)); assert(relation->lchallenge); + DDS_Security_BinaryProperty_t *challenge2 = &tokens[idx++]; DDS_Security_BinaryProperty_set_by_value(challenge2, "challenge2", relation->lchallenge->value, sizeof(AuthenticationChallenge)); + /* THe dh1 and hash_c1 and hash_c2 are optional */ + if (impl->include_optional) + { + DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "dh1", dh1->value._buffer, dh1->value._length); + DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "hash_c2", handshake->hash_c2, sizeof(HashValue_t)); + DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "hash_c1", handshake->hash_c1, sizeof(HashValue_t)); + } + /* Calculate the signature */ { unsigned char *sign; @@ -1736,12 +1744,12 @@ DDS_Security_ValidationResult_t begin_handshake_reply(dds_security_authenticatio DDS_Security_BinaryProperty_free(hash_c2_val); if (result != DDS_SECURITY_VALIDATION_OK) goto err_signature; - DDS_Security_BinaryProperty_set_by_ref(signature, "signature", sign, (uint32_t)signlen); + DDS_Security_BinaryProperty_set_by_ref(&tokens[idx++], "signature", sign, (uint32_t)signlen); } (void)ddsrt_hh_add(impl->objectHash, handshake); handshake_message_out->class_id = ddsrt_strdup(AUTH_HANDSHAKE_REPLY_TOKEN_ID); - handshake_message_out->binary_properties._length = tokenSize; + handshake_message_out->binary_properties._length = tsz; handshake_message_out->binary_properties._buffer = tokens; ddsrt_mutex_unlock(&impl->lock); @@ -1750,7 +1758,7 @@ DDS_Security_ValidationResult_t begin_handshake_reply(dds_security_authenticatio return DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE; err_signature: - free_binary_properties(tokens, tokenSize); + free_binary_properties(tokens, tsz); err_get_public_key: err_gen_dh_keys: ddsrt_free(certData); @@ -1827,10 +1835,8 @@ DDS_Security_ValidationResult_t process_handshake(dds_security_authentication *i HandshakeInfo *handshake = NULL; IdentityRelation *relation = NULL; SecurityObject *obj; - EVP_PKEY *dhkeyRemote = NULL; - DDS_Security_BinaryProperty_t *tokens = NULL, *hash_c1 = NULL, *hash_c2 = NULL, *dh1, *dh2, *challenge1, *challenge2, *signature; - const DDS_Security_BinaryProperty_t *hash_c1_ref, *hash_c2_ref, *challenge1_ref, *challenge2_ref, *dh1_ref, *dh2_ref; - uint32_t tokenSize = 0, idx; + DDS_Security_BinaryProperty_t *dh1_gen = NULL, *dh2_gen = NULL; + const uint32_t tsz = impl->include_optional ? 7 : 3; DDS_Security_octet *challenge1_ref_for_shared_secret, *challenge2_ref_for_shared_secret; /* validate provided arguments */ @@ -1857,50 +1863,37 @@ DDS_Security_ValidationResult_t process_handshake(dds_security_authentication *i switch (handshake->created_in) { case CREATEDREQUEST: - /* The source of the handshake_handle is a begin_handshake_request function. So, handshake_message_in is from a remote begin_handshake_reply function */ - /* Verify Message Token contents according to Spec 9.3.2.5.2 (Reply Message) */ - if (validate_handshake_token(handshake_message_in, HS_TOKEN_REPLY, handshake, &dhkeyRemote, &(impl->trustedCAList), ex) != DDS_SECURITY_VALIDATION_OK) + if ((dh1_gen = create_dhkey_property("dh1", handshake->ldh, relation->localIdentity->kagreeAlgoKind, ex)) == NULL) + goto err_inv_token; + + /* The source of the handshake_handle is a begin_handshake_request function. So, handshake_message_in is from a remote begin_handshake_reply function */ + /* Verify Message Token contents according to Spec 9.3.2.5.2 (Reply Message) */ + if (validate_handshake_token(handshake_message_in, HS_TOKEN_REPLY, handshake, &(impl->trustedCAList), dh1_gen, NULL, ex) != DDS_SECURITY_VALIDATION_OK) goto err_inv_token; - handshake->rdh = dhkeyRemote; EVP_PKEY_copy_parameters(handshake->rdh, handshake->ldh); - /* Prepare HandshakeFinalMessageToken */ - hash_c1_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "hash_c1"); - hash_c2_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "hash_c2"); - dh1_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "dh1"); - dh2_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "dh2"); - challenge1_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "challenge1"); - challenge2_ref = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "challenge2"); - tokenSize = 3; /* challenge1, challenge2 and signature are in already */ - if (hash_c1_ref) tokenSize++; - if (hash_c2_ref) tokenSize++; - if (dh1_ref) tokenSize++; - if (dh2_ref) tokenSize++; - tokens = DDS_Security_BinaryPropertySeq_allocbuf(tokenSize); - idx = 0; - signature = &tokens[idx++]; - hash_c2 = hash_c2_ref ? &tokens[idx++] : NULL; - challenge2 = &tokens[idx++]; - dh2 = dh2_ref ? &tokens[idx++] : NULL; - challenge1 = &tokens[idx++]; - dh1 = dh1_ref ? &tokens[idx++] : NULL; - hash_c1 = hash_c1_ref ? &tokens[idx++] : NULL; + /* Find the dh1 property from the received request token */ + const DDS_Security_BinaryProperty_t *dh2 = DDS_Security_DataHolder_find_binary_property(handshake_message_in, "dh2"); + assert(dh2); + + DDS_Security_BinaryProperty_t *tokens = DDS_Security_BinaryPropertySeq_allocbuf(tsz); + uint32_t idx = 0; - if (hash_c1) - DDS_Security_BinaryProperty_set_by_value(hash_c1, "hash_c1", hash_c1_ref->value._buffer, hash_c1_ref->value._length); - if (hash_c2) - DDS_Security_BinaryProperty_set_by_value(hash_c2, "hash_c2", hash_c2_ref->value._buffer, hash_c2_ref->value._length); - if (dh1) - DDS_Security_BinaryProperty_set_by_value(dh1, "dh1", dh1_ref->value._buffer, dh1_ref->value._length); - if (dh2) - DDS_Security_BinaryProperty_set_by_value(dh2, "dh2", dh2_ref->value._buffer, dh2_ref->value._length); assert(relation->lchallenge); - if (challenge1 && challenge1_ref) - DDS_Security_BinaryProperty_set_by_value(challenge1, "challenge1", challenge1_ref->value._buffer, challenge1_ref->value._length); + DDS_Security_BinaryProperty_t *challenge1 = &tokens[idx++]; + DDS_Security_BinaryProperty_set_by_value(challenge1, "challenge1", relation->lchallenge->value, sizeof(AuthenticationChallenge)); assert(relation->rchallenge); - if (challenge2 && challenge2_ref) - DDS_Security_BinaryProperty_set_by_value(challenge2, "challenge2", challenge2_ref->value._buffer, challenge2_ref->value._length); + DDS_Security_BinaryProperty_t *challenge2 = &tokens[idx++]; + DDS_Security_BinaryProperty_set_by_value(challenge2, "challenge2", relation->rchallenge->value, sizeof(AuthenticationChallenge)); + + if (impl->include_optional) + { + DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "dh1", dh1_gen->value._buffer, dh1_gen->value._length); + DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "dh2", dh2->value._buffer, dh2->value._length); + DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "hash_c2", handshake->hash_c2, sizeof(HashValue_t)); + DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "hash_c1", handshake->hash_c1, sizeof(HashValue_t)); + } /* Calculate the signature */ { @@ -1908,17 +1901,17 @@ DDS_Security_ValidationResult_t process_handshake(dds_security_authentication *i size_t signlen; DDS_Security_BinaryProperty_t *hash_c1_val = hash_value_to_binary_property("hash_c1", handshake->hash_c1); DDS_Security_BinaryProperty_t *hash_c2_val = hash_value_to_binary_property("hash_c2", handshake->hash_c2); - const DDS_Security_BinaryProperty_t *binary_properties[HANDSHAKE_SIGNATURE_CONTENT_SIZE] = { hash_c1_val, challenge1, dh1, challenge2, dh2, hash_c2_val }; + const DDS_Security_BinaryProperty_t *binary_properties[HANDSHAKE_SIGNATURE_CONTENT_SIZE] = { hash_c1_val, challenge1, dh1_gen, challenge2, dh2, hash_c2_val }; DDS_Security_ValidationResult_t result = create_signature(relation->localIdentity->privateKey, binary_properties, HANDSHAKE_SIGNATURE_CONTENT_SIZE, &sign, &signlen, ex); DDS_Security_BinaryProperty_free(hash_c1_val); DDS_Security_BinaryProperty_free(hash_c2_val); if (result != DDS_SECURITY_VALIDATION_OK) goto err_signature; - DDS_Security_BinaryProperty_set_by_ref(signature, "signature", sign, (uint32_t)signlen); + DDS_Security_BinaryProperty_set_by_ref(&tokens[idx++], "signature", sign, (uint32_t)signlen); } handshake_message_out->class_id = ddsrt_strdup(AUTH_HANDSHAKE_FINAL_TOKEN_ID); - handshake_message_out->binary_properties._length = tokenSize; + handshake_message_out->binary_properties._length = tsz; handshake_message_out->binary_properties._buffer = tokens; challenge1_ref_for_shared_secret = (DDS_Security_octet *)(handshake->relation->lchallenge); challenge2_ref_for_shared_secret = (DDS_Security_octet *)(handshake->relation->rchallenge); @@ -1926,9 +1919,14 @@ DDS_Security_ValidationResult_t process_handshake(dds_security_authentication *i break; case CREATEDREPLY: + if ((dh1_gen = create_dhkey_property("dh1", handshake->rdh, relation->remoteIdentity->kagreeAlgoKind, ex)) == NULL) + goto err_inv_token; + if ((dh2_gen = create_dhkey_property("dh2", handshake->ldh, relation->remoteIdentity->kagreeAlgoKind, ex)) == NULL) + goto err_inv_token; + /* The source of the handshake_handle is a begin_handshake_reply function So, handshake_message_in is from a remote process_handshake function */ /* Verify Message Token contents according to Spec 9.3.2.5.3 (Final Message) */ - if (validate_handshake_token(handshake_message_in, HS_TOKEN_FINAL, handshake, NULL, NULL, ex) != DDS_SECURITY_VALIDATION_OK) + if (validate_handshake_token(handshake_message_in, HS_TOKEN_FINAL, handshake, NULL, dh1_gen, dh2_gen, ex) != DDS_SECURITY_VALIDATION_OK) goto err_inv_token; challenge2_ref_for_shared_secret = (DDS_Security_octet *)(handshake->relation->lchallenge); challenge1_ref_for_shared_secret = (DDS_Security_octet *)(handshake->relation->rchallenge); @@ -1964,6 +1962,10 @@ DDS_Security_ValidationResult_t process_handshake(dds_security_authentication *i add_validity_end_trigger(impl, IDENTITY_HANDLE(handshake->relation->remoteIdentity), cert_exp); } ddsrt_mutex_unlock(&impl->lock); + + DDS_Security_BinaryProperty_free(dh1_gen); + DDS_Security_BinaryProperty_free(dh2_gen); + return hs_result; err_invalid_expiry: @@ -1975,6 +1977,8 @@ err_signature: if (handshake_message_out->class_id) DDS_Security_DataHolder_deinit(handshake_message_out); err_inv_token: + DDS_Security_BinaryProperty_free(dh1_gen); + DDS_Security_BinaryProperty_free(dh2_gen); err_inv_handle: ddsrt_mutex_unlock(&impl->lock); err_bad_param: @@ -2262,6 +2266,10 @@ int32_t init_authentication(const char *argument, void **context, struct ddsi_do authentication->objectHash = ddsrt_hh_new(32, security_object_hash, security_object_equal); authentication->remoteGuidHash = ddsrt_hh_new(32, remote_guid_hash, remote_guid_equal); memset(&authentication->trustedCAList, 0, sizeof(X509Seq)); + if (gv) + authentication->include_optional = gv->handshake_include_optional; + else + authentication->include_optional = true; OpenSSL_add_all_algorithms(); OpenSSL_add_all_ciphers(); diff --git a/src/security/core/include/dds/security/core/dds_security_utils.h b/src/security/core/include/dds/security/core/dds_security_utils.h index c61829a..21ac8fc 100644 --- a/src/security/core/include/dds/security/core/dds_security_utils.h +++ b/src/security/core/include/dds/security/core/dds_security_utils.h @@ -53,12 +53,12 @@ DDS_Security_BinaryProperty_free( DDS_EXPORT void DDS_Security_BinaryProperty_copy( DDS_Security_BinaryProperty_t *dst, - DDS_Security_BinaryProperty_t *src); + const DDS_Security_BinaryProperty_t *src); DDS_EXPORT bool DDS_Security_BinaryProperty_equal( - DDS_Security_BinaryProperty_t *pa, - DDS_Security_BinaryProperty_t *pb); + const DDS_Security_BinaryProperty_t *pa, + const DDS_Security_BinaryProperty_t *pb); DDS_EXPORT void DDS_Security_BinaryProperty_set_by_value( @@ -111,12 +111,12 @@ DDS_Security_Property_deinit( DDS_EXPORT void DDS_Security_Property_copy( DDS_Security_Property_t *dst, - DDS_Security_Property_t *src); + const DDS_Security_Property_t *src); DDS_EXPORT bool DDS_Security_Property_equal( - DDS_Security_Property_t *pa, - DDS_Security_Property_t *pb); + const DDS_Security_Property_t *pa, + const DDS_Security_Property_t *pb); DDS_EXPORT char * DDS_Security_Property_get_value( diff --git a/src/security/core/src/dds_security_utils.c b/src/security/core/src/dds_security_utils.c index 723a383..0d3742a 100644 --- a/src/security/core/src/dds_security_utils.c +++ b/src/security/core/src/dds_security_utils.c @@ -63,7 +63,7 @@ DDS_Security_BinaryProperty_free( void DDS_Security_BinaryProperty_copy( DDS_Security_BinaryProperty_t *dst, - DDS_Security_BinaryProperty_t *src) + const DDS_Security_BinaryProperty_t *src) { dst->name = src->name ? ddsrt_strdup(src->name) : NULL; dst->propagate = src->propagate; @@ -80,8 +80,8 @@ DDS_Security_BinaryProperty_copy( bool DDS_Security_BinaryProperty_equal( - DDS_Security_BinaryProperty_t *pa, - DDS_Security_BinaryProperty_t *pb) + const DDS_Security_BinaryProperty_t *pa, + const DDS_Security_BinaryProperty_t *pb) { uint32_t i; @@ -248,7 +248,7 @@ DDS_Security_Property_deinit( void DDS_Security_Property_copy( DDS_Security_Property_t *dst, - DDS_Security_Property_t *src) + const DDS_Security_Property_t *src) { dst->name = src->name ? ddsrt_strdup(src->name) : NULL; dst->value = src->value ? ddsrt_strdup(src->value) : NULL; @@ -257,8 +257,8 @@ DDS_Security_Property_copy( bool DDS_Security_Property_equal( - DDS_Security_Property_t *pa, - DDS_Security_Property_t *pb) + const DDS_Security_Property_t *pa, + const DDS_Security_Property_t *pb) { if (pa->name && pb->name) { if (strcmp(pa->name, pb->name) != 0) { From 720c8f8fbf0cd08b96a849eb660b8d72dd3f9bf5 Mon Sep 17 00:00:00 2001 From: Marcel Jordense Date: Fri, 1 May 2020 10:58:07 +0200 Subject: [PATCH 177/238] Correct security (de)serialization of QosProperty contained in c.data field of handshake token Signed-off-by: Marcel Jordense --- .../core/src/dds_security_serialize.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/security/core/src/dds_security_serialize.c b/src/security/core/src/dds_security_serialize.c index d5a37d4..0e92790 100644 --- a/src/security/core/src/dds_security_serialize.c +++ b/src/security/core/src/dds_security_serialize.c @@ -396,7 +396,8 @@ DDS_Security_Serialize_PropertyQosPolicy( DDS_Security_Serialize_uint16(ser, PID_PROPERTY_LIST); DDS_Security_Serialize_mark_len(ser); DDS_Security_Serialize_PropertySeq(ser, &policy->value); - DDS_Security_Serialize_BinaryPropertySeq(ser, &policy->binary_value); + if (policy->binary_value._length > 0) + DDS_Security_Serialize_BinaryPropertySeq(ser, &policy->binary_value); DDS_Security_Serialize_update_len(ser); } @@ -679,10 +680,18 @@ DDS_Security_Deserialize_DataHolder( static int DDS_Security_Deserialize_PropertyQosPolicy( DDS_Security_Deserializer dser, - DDS_Security_PropertyQosPolicy *policy) + DDS_Security_PropertyQosPolicy *policy, + size_t len) { - return DDS_Security_Deserialize_PropertySeq(dser, &policy->value) && - DDS_Security_Deserialize_BinaryPropertySeq(dser, &policy->binary_value); + size_t sl = dser->remain; + + if (!DDS_Security_Deserialize_PropertySeq(dser, &policy->value)) + return 0; + + if (sl - dser->remain > len) + return DDS_Security_Deserialize_BinaryPropertySeq(dser, &policy->binary_value); + + return 1; } static int @@ -742,7 +751,7 @@ DDS_Security_Deserialize_ParticipantBuiltinTopicData( r = DDS_Security_Deserialize_DataHolder(dser, &pdata->permissions_token); break; case PID_PROPERTY_LIST: - r = DDS_Security_Deserialize_PropertyQosPolicy(dser, &pdata->property); + r = DDS_Security_Deserialize_PropertyQosPolicy(dser, &pdata->property, len); break; case PID_PARTICIPANT_SECURITY_INFO: r = DDS_Security_Deserialize_ParticipantSecurityInfo(dser, &pdata->security_info); From 860f261dc6b94ee354f6e2c34f9f7506704b7818 Mon Sep 17 00:00:00 2001 From: Marcel Jordense Date: Fri, 1 May 2020 14:13:05 +0200 Subject: [PATCH 178/238] Correct generation of the crypto key Signed-off-by: Marcel Jordense --- .../cryptographic/src/crypto_key_factory.c | 17 +++++++++-------- .../cryptographic/src/crypto_utils.c | 1 + 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c index cef6830..5416abf 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c @@ -89,8 +89,10 @@ calculate_kx_keys( unsigned char *kx_master_salt, *kx_master_sender_key; size_t shared_secret_size = get_secret_size_from_secret_handle(shared_secret); unsigned char hash[SHA256_DIGEST_LENGTH]; - size_t concatenated_bytes1_size = DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE * 2 + sizeof(KXSALTCOOKIE); - size_t concatenated_bytes2_size = DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE * 2 + sizeof(KXKEYCOOKIE); + size_t KXKEYCOOKIE_SIZE = strlen(KXKEYCOOKIE); + size_t KXSALTCOOKIE_SIZE = strlen(KXSALTCOOKIE); + size_t concatenated_bytes1_size = DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE * 2 + KXSALTCOOKIE_SIZE; + size_t concatenated_bytes2_size = DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE * 2 + KXKEYCOOKIE_SIZE; DDS_Security_octet *concatenated_bytes1, *concatenated_bytes2; memset(ex, 0, sizeof(*ex)); @@ -108,9 +110,8 @@ calculate_kx_keys( /* master_salt */ memcpy(concatenated_bytes1, challenge1, DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE); - memcpy(concatenated_bytes1 + DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE, KXSALTCOOKIE, sizeof(KXSALTCOOKIE)); - memcpy(concatenated_bytes1 + DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE + sizeof(KXSALTCOOKIE), challenge2, - DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE); + memcpy(concatenated_bytes1 + DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE, KXSALTCOOKIE, KXSALTCOOKIE_SIZE); + memcpy(concatenated_bytes1 + DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE + KXSALTCOOKIE_SIZE, challenge2, DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE); SHA256(concatenated_bytes1, concatenated_bytes1_size, hash); if (!(kx_master_salt = crypto_hmac256(hash, SHA256_DIGEST_LENGTH, shared_secret_key, (uint32_t) shared_secret_size, ex))) @@ -118,9 +119,8 @@ calculate_kx_keys( /* master_sender_key */ memcpy(concatenated_bytes2, challenge2, DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE); - memcpy(concatenated_bytes2 + DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE, KXKEYCOOKIE, sizeof(KXKEYCOOKIE)); - memcpy(concatenated_bytes2 + DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE + sizeof(KXKEYCOOKIE), challenge1, - DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE); + memcpy(concatenated_bytes2 + DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE, KXKEYCOOKIE, KXKEYCOOKIE_SIZE); + memcpy(concatenated_bytes2 + DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE + KXKEYCOOKIE_SIZE, challenge1, DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE); SHA256(concatenated_bytes2, concatenated_bytes2_size, hash); if (!(kx_master_sender_key = crypto_hmac256(hash, SHA256_DIGEST_LENGTH, shared_secret_key, (uint32_t) shared_secret_size, ex))) @@ -1158,6 +1158,7 @@ crypto_factory_set_participant_crypto_tokens( master_key_material *remote_key_mat_new = crypto_master_key_material_new(CRYPTO_TRANSFORMATION_KIND_NONE); crypto_token_copy(remote_key_mat_new, remote_key_mat); key_material->remote_key_material = remote_key_mat_new; + if (remote_key_mat_old != NULL) { struct gcreq *gcreq = gcreq_new(impl->crypto->gv->gcreq_queue, gc_remote_key_material); diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_utils.c b/src/security/builtin_plugins/cryptographic/src/crypto_utils.c index 36e9f75..12ca32e 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_utils.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_utils.c @@ -62,6 +62,7 @@ crypto_calculate_key_impl( memcpy(buffer, prefix, strlen(prefix)); memcpy(&buffer[strlen(prefix)], master_salt, key_bytes); memcpy(&buffer[strlen(prefix) + key_bytes], &id, sizeof(id)); + if (HMAC(EVP_sha256(), master_key, (int)key_bytes, buffer, sz, md, NULL) == NULL) { DDS_Security_Exception_set_with_openssl_error(ex, DDS_CRYPTO_PLUGIN_CONTEXT, DDS_SECURITY_ERR_CIPHER_ERROR, 0, "HMAC failed: "); From e1899df62d7c09d452543eada4bdf3d7f79ee4fc Mon Sep 17 00:00:00 2001 From: Marcel Jordense Date: Fri, 8 May 2020 17:09:01 +0200 Subject: [PATCH 179/238] Fix incorrect type of include_optional_fields config parameter Signed-off-by: Marcel Jordense --- src/core/ddsi/include/dds/ddsi/q_config.h | 2 +- src/core/ddsi/src/ddsi_security_omg.c | 2 +- .../authentication/src/authentication.c | 62 ++++++++++--------- .../cryptographic/src/crypto_key_exchange.c | 17 ++--- .../cryptographic/src/crypto_key_factory.c | 4 +- 5 files changed, 46 insertions(+), 41 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_config.h b/src/core/ddsi/include/dds/ddsi/q_config.h index d9628e2..3c78e28 100644 --- a/src/core/ddsi/include/dds/ddsi/q_config.h +++ b/src/core/ddsi/include/dds/ddsi/q_config.h @@ -174,7 +174,7 @@ typedef struct authentication_properties_type{ char *private_key; char *password; char *trusted_ca_dir; - bool include_optional_fields; + int include_optional_fields; } authentication_properties_type; typedef struct access_control_properties_type{ diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 36d5a3c..7824239 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -736,7 +736,7 @@ void q_omg_security_init (struct ddsi_domaingv *gv) gv->security_context = sc; if (gv->config.omg_security_configuration) - gv->handshake_include_optional = gv->config.omg_security_configuration->cfg.authentication_properties.include_optional_fields; + gv->handshake_include_optional = gv->config.omg_security_configuration->cfg.authentication_properties.include_optional_fields != 0; else gv->handshake_include_optional = false; diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index 490654b..316c910 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -1126,7 +1126,7 @@ DDS_Security_ValidationResult_t begin_handshake_request(dds_security_authenticat EVP_PKEY *dhkey; unsigned char *certData, *dhPubKeyData = NULL; uint32_t certDataSize, dhPubKeyDataSize; - uint32_t tsz = impl->include_optional ? 8 : 7; + uint32_t tokcount = impl->include_optional ? 8 : 7; int created = 0; if (!instance || !handshake_handle || !handshake_message || !serialized_local_participant_data) @@ -1184,39 +1184,41 @@ DDS_Security_ValidationResult_t begin_handshake_request(dds_security_authenticat if (localIdent->pdata._length == 0) DDS_Security_OctetSeq_copy(&localIdent->pdata, serialized_local_participant_data); - DDS_Security_BinaryProperty_t *tokens = DDS_Security_BinaryPropertySeq_allocbuf(tsz); - uint32_t idx = 0; + DDS_Security_BinaryProperty_t *tokens = DDS_Security_BinaryPropertySeq_allocbuf(tokcount); + uint32_t tokidx = 0; - DDS_Security_BinaryProperty_set_by_ref(&tokens[idx++], "c.id", certData, certDataSize); - DDS_Security_BinaryProperty_set_by_string(&tokens[idx++], "c.perm", localIdent->permissionsDocument ? localIdent->permissionsDocument : ""); - DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "c.pdata", serialized_local_participant_data->_buffer, serialized_local_participant_data->_length); - DDS_Security_BinaryProperty_set_by_string(&tokens[idx++], "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); - DDS_Security_BinaryProperty_set_by_string(&tokens[idx++], "c.kagree_algo", get_kagree_algo(localIdent->kagreeAlgoKind)); + DDS_Security_BinaryProperty_set_by_ref(&tokens[tokidx++], "c.id", certData, certDataSize); + DDS_Security_BinaryProperty_set_by_string(&tokens[tokidx++], "c.perm", localIdent->permissionsDocument ? localIdent->permissionsDocument : ""); + DDS_Security_BinaryProperty_set_by_value(&tokens[tokidx++], "c.pdata", serialized_local_participant_data->_buffer, serialized_local_participant_data->_length); + DDS_Security_BinaryProperty_set_by_string(&tokens[tokidx++], "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); + DDS_Security_BinaryProperty_set_by_string(&tokens[tokidx++], "c.kagree_algo", get_kagree_algo(localIdent->kagreeAlgoKind)); /* Todo: including hash_c1 is optional (conform spec); add a configuration option to leave it out */ { DDS_Security_BinaryPropertySeq bseq = { ._length = 5, ._buffer = tokens }; get_hash_binary_property_seq(&bseq, handshake->hash_c1); if (impl->include_optional) - DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "hash_c1", handshake->hash_c1, sizeof(HashValue_t)); + DDS_Security_BinaryProperty_set_by_value(&tokens[tokidx++], "hash_c1", handshake->hash_c1, sizeof(HashValue_t)); } /* Set the DH public key associated with the local participant in dh1 property */ assert(dhPubKeyData); assert(dhPubKeyDataSize < 1200); - DDS_Security_BinaryProperty_set_by_ref(&tokens[idx++], "dh1", dhPubKeyData, dhPubKeyDataSize); + DDS_Security_BinaryProperty_set_by_ref(&tokens[tokidx++], "dh1", dhPubKeyData, dhPubKeyDataSize); /* Set the challenge in challenge1 property */ - DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "challenge1", relation->lchallenge->value, sizeof(AuthenticationChallenge)); + DDS_Security_BinaryProperty_set_by_value(&tokens[tokidx++], "challenge1", relation->lchallenge->value, sizeof(AuthenticationChallenge)); (void)ddsrt_hh_add(impl->objectHash, handshake); ddsrt_mutex_unlock(&impl->lock); + assert(tokcount == tokidx); + handshake_message->class_id = ddsrt_strdup(AUTH_HANDSHAKE_REQUEST_TOKEN_ID); handshake_message->properties._length = 0; handshake_message->properties._buffer = NULL; - handshake_message->binary_properties._length = tsz; + handshake_message->binary_properties._length = tokidx; handshake_message->binary_properties._buffer = tokens; *handshake_handle = HANDSHAKE_HANDLE(handshake); @@ -1627,7 +1629,7 @@ DDS_Security_ValidationResult_t begin_handshake_reply(dds_security_authenticatio EVP_PKEY *dhkeyLocal = NULL; unsigned char *certData, *dhPubKeyData; uint32_t certDataSize, dhPubKeyDataSize; - uint32_t tsz = impl->include_optional ? 12 : 9; + uint32_t tokcount = impl->include_optional ? 12 : 9; int created = 0; if (!instance || !handshake_handle || !handshake_message_out || !handshake_message_in || !serialized_local_participant_data) @@ -1694,23 +1696,23 @@ DDS_Security_ValidationResult_t begin_handshake_reply(dds_security_authenticatio if (localIdent->pdata._length == 0) DDS_Security_OctetSeq_copy(&localIdent->pdata, serialized_local_participant_data); - DDS_Security_BinaryProperty_t *tokens = DDS_Security_BinaryPropertySeq_allocbuf(tsz); - uint32_t idx = 0; + DDS_Security_BinaryProperty_t *tokens = DDS_Security_BinaryPropertySeq_allocbuf(tokcount); + uint32_t tokidx = 0; /* Store the Identity Certificate associated with the local identify in c.id property */ - DDS_Security_BinaryProperty_set_by_ref(&tokens[idx++], "c.id", certData, certDataSize); + DDS_Security_BinaryProperty_set_by_ref(&tokens[tokidx++], "c.id", certData, certDataSize); certData = NULL; - DDS_Security_BinaryProperty_set_by_string(&tokens[idx++], "c.perm", localIdent->permissionsDocument ? localIdent->permissionsDocument : ""); - DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "c.pdata", serialized_local_participant_data->_buffer, serialized_local_participant_data->_length); - DDS_Security_BinaryProperty_set_by_string(&tokens[idx++], "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); - DDS_Security_BinaryProperty_set_by_string(&tokens[idx++], "c.kagree_algo", get_kagree_algo(remoteIdent->kagreeAlgoKind)); + DDS_Security_BinaryProperty_set_by_string(&tokens[tokidx++], "c.perm", localIdent->permissionsDocument ? localIdent->permissionsDocument : ""); + DDS_Security_BinaryProperty_set_by_value(&tokens[tokidx++], "c.pdata", serialized_local_participant_data->_buffer, serialized_local_participant_data->_length); + DDS_Security_BinaryProperty_set_by_string(&tokens[tokidx++], "c.dsign_algo", get_dsign_algo(localIdent->dsignAlgoKind)); + DDS_Security_BinaryProperty_set_by_string(&tokens[tokidx++], "c.kagree_algo", get_kagree_algo(remoteIdent->kagreeAlgoKind)); /* Calculate the hash_c2 */ DDS_Security_BinaryPropertySeq bseq = { ._length = 5, ._buffer = tokens }; get_hash_binary_property_seq(&bseq, handshake->hash_c2); /* Set the DH public key associated with the local participant in dh2 property */ - DDS_Security_BinaryProperty_t *dh2 = &tokens[idx++]; + DDS_Security_BinaryProperty_t *dh2 = &tokens[tokidx++]; DDS_Security_BinaryProperty_set_by_ref(dh2, "dh2", dhPubKeyData, dhPubKeyDataSize); /* Find the dh1 property from the received request token */ @@ -1718,18 +1720,18 @@ DDS_Security_ValidationResult_t begin_handshake_reply(dds_security_authenticatio assert(dh1); assert(relation->rchallenge); - DDS_Security_BinaryProperty_t *challenge1 = &tokens[idx++]; + DDS_Security_BinaryProperty_t *challenge1 = &tokens[tokidx++]; DDS_Security_BinaryProperty_set_by_value(challenge1, "challenge1", relation->rchallenge->value, sizeof(AuthenticationChallenge)); assert(relation->lchallenge); - DDS_Security_BinaryProperty_t *challenge2 = &tokens[idx++]; + DDS_Security_BinaryProperty_t *challenge2 = &tokens[tokidx++]; DDS_Security_BinaryProperty_set_by_value(challenge2, "challenge2", relation->lchallenge->value, sizeof(AuthenticationChallenge)); /* THe dh1 and hash_c1 and hash_c2 are optional */ if (impl->include_optional) { - DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "dh1", dh1->value._buffer, dh1->value._length); - DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "hash_c2", handshake->hash_c2, sizeof(HashValue_t)); - DDS_Security_BinaryProperty_set_by_value(&tokens[idx++], "hash_c1", handshake->hash_c1, sizeof(HashValue_t)); + DDS_Security_BinaryProperty_set_by_value(&tokens[tokidx++], "dh1", dh1->value._buffer, dh1->value._length); + DDS_Security_BinaryProperty_set_by_value(&tokens[tokidx++], "hash_c2", handshake->hash_c2, sizeof(HashValue_t)); + DDS_Security_BinaryProperty_set_by_value(&tokens[tokidx++], "hash_c1", handshake->hash_c1, sizeof(HashValue_t)); } /* Calculate the signature */ @@ -1744,12 +1746,14 @@ DDS_Security_ValidationResult_t begin_handshake_reply(dds_security_authenticatio DDS_Security_BinaryProperty_free(hash_c2_val); if (result != DDS_SECURITY_VALIDATION_OK) goto err_signature; - DDS_Security_BinaryProperty_set_by_ref(&tokens[idx++], "signature", sign, (uint32_t)signlen); + DDS_Security_BinaryProperty_set_by_ref(&tokens[tokidx++], "signature", sign, (uint32_t)signlen); } + assert(tokidx == tokcount); + (void)ddsrt_hh_add(impl->objectHash, handshake); handshake_message_out->class_id = ddsrt_strdup(AUTH_HANDSHAKE_REPLY_TOKEN_ID); - handshake_message_out->binary_properties._length = tsz; + handshake_message_out->binary_properties._length = tokidx; handshake_message_out->binary_properties._buffer = tokens; ddsrt_mutex_unlock(&impl->lock); @@ -1758,7 +1762,7 @@ DDS_Security_ValidationResult_t begin_handshake_reply(dds_security_authenticatio return DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE; err_signature: - free_binary_properties(tokens, tsz); + free_binary_properties(tokens, tokcount); err_get_public_key: err_gen_dh_keys: ddsrt_free(certData); diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_key_exchange.c b/src/security/builtin_plugins/cryptographic/src/crypto_key_exchange.c index 9ea8ade..7cadb64 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_key_exchange.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_key_exchange.c @@ -78,18 +78,19 @@ static bool check_crypto_keymaterial( { bool status = false; uint32_t transform_kind = CRYPTO_TRANSFORM_KIND(keymat->transformation_kind); - uint32_t key_sz = CRYPTO_KEY_SIZE_BYTES(transform_kind); if (transform_kind != CRYPTO_TRANSFORMATION_KIND_NONE) { - status = (transform_kind <= CRYPTO_TRANSFORMATION_KIND_AES256_GCM && - keymat->master_salt._length == key_sz && keymat->master_salt._buffer != NULL && check_not_data_empty(&keymat->master_salt) && - keymat->master_sender_key._length == key_sz && keymat->master_sender_key._buffer != NULL && check_not_data_empty(&keymat->master_sender_key)); - - if (status && CRYPTO_TRANSFORM_ID(keymat->receiver_specific_key_id)) + if (transform_kind <= CRYPTO_TRANSFORMATION_KIND_AES256_GCM) { - status = (keymat->master_receiver_specific_key._length == key_sz && - keymat->master_receiver_specific_key._buffer != NULL && check_not_data_empty(&keymat->master_receiver_specific_key)); + uint32_t key_sz = CRYPTO_KEY_SIZE_BYTES(transform_kind); + status = (keymat->master_salt._length == key_sz && keymat->master_salt._buffer != NULL && check_not_data_empty(&keymat->master_salt) && + keymat->master_sender_key._length == key_sz && keymat->master_sender_key._buffer != NULL && check_not_data_empty(&keymat->master_sender_key)); + if (status && CRYPTO_TRANSFORM_ID(keymat->receiver_specific_key_id)) + { + status = (keymat->master_receiver_specific_key._length == key_sz && + keymat->master_receiver_specific_key._buffer != NULL && check_not_data_empty(&keymat->master_receiver_specific_key)); + } } } else diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c index 5416abf..1ce7e49 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c @@ -37,7 +37,9 @@ */ #define KXKEYCOOKIE "key exchange key" +#define KXKEYCOOKIE_SIZE (sizeof(KXKEYCOOKIE) - 1) #define KXSALTCOOKIE "keyexchange salt" +#define KXSALTCOOKIE_SIZE (sizeof(KXSALTCOOKIE) - 1) typedef struct dds_security_crypto_key_factory_impl { @@ -89,8 +91,6 @@ calculate_kx_keys( unsigned char *kx_master_salt, *kx_master_sender_key; size_t shared_secret_size = get_secret_size_from_secret_handle(shared_secret); unsigned char hash[SHA256_DIGEST_LENGTH]; - size_t KXKEYCOOKIE_SIZE = strlen(KXKEYCOOKIE); - size_t KXSALTCOOKIE_SIZE = strlen(KXSALTCOOKIE); size_t concatenated_bytes1_size = DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE * 2 + KXSALTCOOKIE_SIZE; size_t concatenated_bytes2_size = DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE * 2 + KXKEYCOOKIE_SIZE; DDS_Security_octet *concatenated_bytes1, *concatenated_bytes2; From 364f1ce39cb3c63e6e92a49e06035103fe785089 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 11 May 2020 15:06:40 +0200 Subject: [PATCH 180/238] Bump version number to 0.7.0 Signed-off-by: Erik Boasson --- CMakeLists.txt | 2 +- package.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ca28ca1..b999c04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # cmake_minimum_required(VERSION 3.7) -project(CycloneDDS VERSION 0.6.0) +project(CycloneDDS VERSION 0.7.0) # Set a default build type if none was specified set(default_build_type "RelWithDebInfo") diff --git a/package.xml b/package.xml index 913f141..e21d5aa 100644 --- a/package.xml +++ b/package.xml @@ -2,7 +2,7 @@ cyclonedds - 0.6.0 + 0.7.0 Eclipse Cyclone DDS is a very performant and robust open-source DDS implementation. Cyclone DDS is developed completely in the open as an Eclipse IoT project. Eclipse Foundation, Inc. Eclipse Public License 2.0 From fd27604a26cd2f3e1bbef0d8403eeb9340f937a3 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Wed, 22 Apr 2020 16:59:29 +0200 Subject: [PATCH 181/238] Add crypto token exchange test Introduced a test that checks if all crypto tokens send by a node are received correctly by the remote node. To support this test, the crypto wrapper plugin is extended with a token_log mode, that stores all tokens that are exchanged after the security handshake is finished. Signed-off-by: Dennis Potman --- src/security/core/tests/authentication.c | 1 - .../core/tests/common/cryptography_wrapper.c | 258 +++++++++++++++++- .../core/tests/common/cryptography_wrapper.h | 32 +++ src/security/core/tests/common/test_utils.c | 22 ++ src/security/core/tests/common/test_utils.h | 1 + src/security/core/tests/handshake.c | 128 +++++++-- .../core/tests/secure_communication.c | 77 +----- 7 files changed, 412 insertions(+), 107 deletions(-) diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index fe6aa6a..dbd80be 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -34,7 +34,6 @@ #include "common/security_config_test_utils.h" #include "common/test_identity.h" #include "common/cert_utils.h" -#include "common/security_config_test_utils.h" #define ID1 TEST_IDENTITY1_CERTIFICATE #define ID1K TEST_IDENTITY1_PRIVATE_KEY diff --git a/src/security/core/tests/common/cryptography_wrapper.c b/src/security/core/tests/common/cryptography_wrapper.c index 034d81d..1856c09 100644 --- a/src/security/core/tests/common/cryptography_wrapper.c +++ b/src/security/core/tests/common/cryptography_wrapper.c @@ -13,6 +13,7 @@ #include #include "CUnit/Test.h" #include "dds/dds.h" +#include "dds/ddsrt/circlist.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" #include "dds/ddsrt/string.h" @@ -22,13 +23,17 @@ #include "dds/security/core/dds_security_utils.h" #include "cryptography_wrapper.h" -int init_crypto(const char *argument, void **context, struct ddsi_domaingv *gv); -int finalize_crypto(void *context); +#define CRYPTO_TOKEN_CLASS_ID "DDS:Crypto:AES_GCM_GMAC" +#define CRYPTO_TOKEN_PROPERTY_NAME "dds.cryp.keymat" + +int32_t init_crypto(const char *argument, void **context, struct ddsi_domaingv *gv); +int32_t finalize_crypto(void *context); enum crypto_plugin_mode { PLUGIN_MODE_ALL_OK, PLUGIN_MODE_MISSING_FUNC, - PLUGIN_MODE_WRAPPED + PLUGIN_MODE_WRAPPED, + PLUGIN_MODE_TOKEN_LOG }; struct dds_security_crypto_key_exchange_impl { @@ -67,9 +72,13 @@ struct dds_security_cryptography_impl { const char * groupdata_secret; const char * ep_secret; const char * encrypted_secret; + ddsrt_mutex_t token_data_lock; + struct ddsrt_circlist token_data_list; }; static DDS_Security_ParticipantCryptoHandle g_local_participant_handle = 0; +static ddsrt_once_t lock_inited = DDSRT_ONCE_INIT; +static ddsrt_mutex_t g_print_token_lock; void set_protection_kinds( struct dds_security_cryptography_impl * impl, @@ -109,6 +118,144 @@ void set_entity_data_secret(struct dds_security_cryptography_impl * impl, const impl->ep_secret = ep_secret; } +static bool check_crypto_tokens(const DDS_Security_DataHolderSeq *tokens) +{ + bool result = true; + + if (tokens->_length == 0 || tokens->_buffer == NULL) + return false; + + for (uint32_t i = 0; result && (i < tokens->_length); i++) + { + result = (tokens->_buffer[i].class_id != NULL && + strcmp(CRYPTO_TOKEN_CLASS_ID, tokens->_buffer[i].class_id) == 0 && + tokens->_buffer[i].binary_properties._length == 1 && + tokens->_buffer[i].binary_properties._buffer != NULL && + tokens->_buffer[i].binary_properties._buffer[0].name != NULL && + strcmp(CRYPTO_TOKEN_PROPERTY_NAME, tokens->_buffer[i].binary_properties._buffer[0].name) == 0 && + tokens->_buffer[i].binary_properties._buffer[0].value._length > 0 && + tokens->_buffer[i].binary_properties._buffer[0].value._buffer != NULL); + } + return result; +} + +const char *get_crypto_token_type_str (enum crypto_tokens_type type) +{ + switch (type) + { + case LOCAL_PARTICIPANT_TOKENS: return "LOCAL_PARTICIPANT_TOKENS"; + case LOCAL_WRITER_TOKENS: return "LOCAL_WRITER_TOKENS"; + case LOCAL_READER_TOKENS: return "LOCAL_READER_TOKENS"; + case REMOTE_PARTICIPANT_TOKENS: return "REMOTE_PARTICIPANT_TOKENS"; + case REMOTE_WRITER_TOKENS: return "REMOTE_WRITER_TOKENS"; + case REMOTE_READER_TOKENS: return "REMOTE_READER_TOKENS"; + default: assert (0); return ""; + } +} + +static void print_tokens (enum crypto_tokens_type type, const DDS_Security_ParticipantCryptoHandle lch, const DDS_Security_ParticipantCryptoHandle rch, + const DDS_Security_ParticipantCryptoTokenSeq *tokens) +{ + ddsrt_mutex_lock (&g_print_token_lock); + printf ("Token type %s, local %"PRIx64" / remote %"PRIx64", count: %u\n", get_crypto_token_type_str (type), lch, rch, tokens->_length); + for (uint32_t i = 0; i < tokens->_length; i++) + { + printf ("- token: "); + for (uint32_t j = 0; j < tokens->_buffer[i].binary_properties._buffer[0].value._length && j < 32; j++) + printf ("%02x", tokens->_buffer[i].binary_properties._buffer[0].value._buffer[j]); + printf ("\n"); + } + printf ("\n"); + ddsrt_mutex_unlock (&g_print_token_lock); +} + +static void add_tokens (struct ddsrt_circlist *list, enum crypto_tokens_type type, + const DDS_Security_ParticipantCryptoHandle lch, const DDS_Security_ParticipantCryptoHandle rch, + const DDS_Security_ParticipantCryptoTokenSeq *tokens) +{ + struct crypto_token_data *token_data = ddsrt_malloc (sizeof (*token_data)); + token_data->type = type; + token_data->local_handle = lch; + token_data->remote_handle = rch; + token_data->n_tokens = tokens->_length; + assert (tokens->_length <= CRYPTO_TOKEN_MAXLEN); + for (uint32_t i = 0; i < tokens->_length; i++) + { + size_t len = tokens->_buffer[i].binary_properties._buffer[0].value._length; + assert (len <= CRYPTO_TOKEN_SIZE); + memcpy (token_data->data[i], tokens->_buffer[i].binary_properties._buffer[0].value._buffer, len); + token_data->data_len[i] = len; + } + ddsrt_circlist_append(list, &token_data->e); +} + +static void store_tokens (struct dds_security_crypto_key_exchange_impl *impl, enum crypto_tokens_type type, const DDS_Security_ParticipantCryptoHandle lch, + const DDS_Security_ParticipantCryptoHandle rch, const DDS_Security_ParticipantCryptoTokenSeq *tokens) +{ + if (!check_crypto_tokens ((const DDS_Security_DataHolderSeq *) tokens)) + { + printf ("%d ERROR\n", type); + return; + } + + ddsrt_mutex_lock (&impl->parent->token_data_lock); + add_tokens (&impl->parent->token_data_list, type, lch, rch, tokens); + ddsrt_mutex_unlock (&impl->parent->token_data_lock); + + print_tokens (type, lch, rch, tokens); +} + +struct ddsrt_circlist * get_crypto_tokens (struct dds_security_cryptography_impl * impl) +{ + struct ddsrt_circlist *tokens = ddsrt_malloc (sizeof (*tokens)); + ddsrt_circlist_init (tokens); + + ddsrt_mutex_lock (&impl->token_data_lock); + struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->token_data_list), *elem = elem0; + while (elem != NULL) + { + struct crypto_token_data *elem_data = DDSRT_FROM_CIRCLIST (struct crypto_token_data, e, elem); + struct crypto_token_data *token_data = ddsrt_malloc (sizeof (*token_data)); + memcpy (token_data, elem_data, sizeof (*token_data)); + ddsrt_circlist_append (tokens, &token_data->e); + elem = elem->next; + if (elem == elem0) + break; + } + ddsrt_mutex_unlock (&impl->token_data_lock); + + return tokens; +} + +struct crypto_token_data * find_crypto_token (struct dds_security_cryptography_impl * impl, enum crypto_tokens_type type, unsigned char * data, size_t data_len) +{ + assert (data_len <= CRYPTO_TOKEN_SIZE); + ddsrt_mutex_lock (&impl->token_data_lock); + struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->token_data_list), *elem = elem0; + while (elem != NULL) + { + struct crypto_token_data *elem_data = DDSRT_FROM_CIRCLIST (struct crypto_token_data, e, elem); + if (elem_data->type == type) + { + for (uint32_t i = 0; i < elem_data->n_tokens; i++) + { + size_t len = elem_data->data_len[i]; + assert (len <= CRYPTO_TOKEN_SIZE); + if (!memcmp (data, elem_data->data[i], data_len < len ? data_len : len)) + { + ddsrt_mutex_unlock (&impl->token_data_lock); + return elem_data; + } + } + } + elem = elem->next; + if (elem == elem0) + break; + } + ddsrt_mutex_unlock (&impl->token_data_lock); + return NULL; +} + static unsigned char * find_buffer_match(const unsigned char *input, size_t input_len, const unsigned char *match, size_t match_len) { if (match_len <= input_len && match_len > 0 && input_len > 0) @@ -171,8 +318,14 @@ static DDS_Security_boolean create_local_participant_crypto_tokens( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: - return impl->instance->create_local_participant_crypto_tokens (impl->instance, local_participant_crypto_tokens, + case PLUGIN_MODE_TOKEN_LOG: + { + DDS_Security_boolean ret = impl->instance->create_local_participant_crypto_tokens (impl->instance, local_participant_crypto_tokens, local_participant_crypto, remote_participant_crypto, ex); + if (ret && impl->parent->mode == PLUGIN_MODE_TOKEN_LOG) + store_tokens (impl, LOCAL_PARTICIPANT_TOKENS, local_participant_crypto, remote_participant_crypto, local_participant_crypto_tokens); + return ret; + } default: return true; } @@ -189,8 +342,14 @@ static DDS_Security_boolean set_remote_participant_crypto_tokens( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: - return impl->instance->set_remote_participant_crypto_tokens (impl->instance, check_handle (local_participant_crypto), + case PLUGIN_MODE_TOKEN_LOG: + { + DDS_Security_boolean ret = impl->instance->set_remote_participant_crypto_tokens (impl->instance, check_handle (local_participant_crypto), check_handle (remote_participant_crypto), remote_participant_tokens, ex); + if (ret && impl->parent->mode == PLUGIN_MODE_TOKEN_LOG) + store_tokens (impl, REMOTE_PARTICIPANT_TOKENS, local_participant_crypto, remote_participant_crypto, remote_participant_tokens); + return ret; + } default: return true; } @@ -207,8 +366,14 @@ static DDS_Security_boolean create_local_datawriter_crypto_tokens( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: - return impl->instance->create_local_datawriter_crypto_tokens (impl->instance, local_datawriter_crypto_tokens, + case PLUGIN_MODE_TOKEN_LOG: + { + DDS_Security_boolean ret = impl->instance->create_local_datawriter_crypto_tokens (impl->instance, local_datawriter_crypto_tokens, check_handle (local_datawriter_crypto), check_handle (remote_datareader_crypto), ex); + if (ret && impl->parent->mode == PLUGIN_MODE_TOKEN_LOG) + store_tokens (impl, LOCAL_WRITER_TOKENS, local_datawriter_crypto, remote_datareader_crypto, local_datawriter_crypto_tokens); + return ret; + } default: return true; } @@ -225,8 +390,14 @@ static DDS_Security_boolean set_remote_datawriter_crypto_tokens( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: - return impl->instance->set_remote_datawriter_crypto_tokens (impl->instance, check_handle (local_datareader_crypto), + case PLUGIN_MODE_TOKEN_LOG: + { + DDS_Security_boolean ret = impl->instance->set_remote_datawriter_crypto_tokens (impl->instance, check_handle (local_datareader_crypto), check_handle (remote_datawriter_crypto), remote_datawriter_tokens, ex); + if (ret && impl->parent->mode == PLUGIN_MODE_TOKEN_LOG) + store_tokens (impl, REMOTE_WRITER_TOKENS, local_datareader_crypto, remote_datawriter_crypto, remote_datawriter_tokens); + return ret; + } default: return true; } @@ -243,8 +414,14 @@ static DDS_Security_boolean create_local_datareader_crypto_tokens( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: - return impl->instance->create_local_datareader_crypto_tokens (impl->instance, local_datareader_cryto_tokens, + case PLUGIN_MODE_TOKEN_LOG: + { + DDS_Security_boolean ret = impl->instance->create_local_datareader_crypto_tokens (impl->instance, local_datareader_cryto_tokens, check_handle (local_datareader_crypto), check_handle (remote_datawriter_crypto), ex); + if (ret && impl->parent->mode == PLUGIN_MODE_TOKEN_LOG) + store_tokens (impl, LOCAL_READER_TOKENS, local_datareader_crypto, remote_datawriter_crypto, local_datareader_cryto_tokens); + return ret; + } default: return true; } @@ -261,8 +438,14 @@ static DDS_Security_boolean set_remote_datareader_crypto_tokens( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: - return impl->instance->set_remote_datareader_crypto_tokens (impl->instance, check_handle (local_datawriter_crypto), + case PLUGIN_MODE_TOKEN_LOG: + { + DDS_Security_boolean ret = impl->instance->set_remote_datareader_crypto_tokens (impl->instance, check_handle (local_datawriter_crypto), check_handle (remote_datareader_crypto), remote_datareader_tokens, ex); + if (ret && impl->parent->mode == PLUGIN_MODE_TOKEN_LOG) + store_tokens (impl, REMOTE_READER_TOKENS, local_datawriter_crypto, remote_datareader_crypto, remote_datareader_tokens); + return ret; + } default: return true; } @@ -277,6 +460,7 @@ static DDS_Security_boolean return_crypto_tokens( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: return impl->instance->return_crypto_tokens (impl->instance, crypto_tokens, ex); default: return true; @@ -298,6 +482,7 @@ static DDS_Security_ParticipantCryptoHandle register_local_participant( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: return check_handle (impl->instance->register_local_participant (impl->instance, check_handle (participant_identity), check_handle (participant_permissions), participant_properties, participant_security_attributes, ex)); default: @@ -317,6 +502,7 @@ static DDS_Security_ParticipantCryptoHandle register_matched_remote_participant( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: return check_handle (impl->instance->register_matched_remote_participant (impl->instance, local_participant_crypto_handle, remote_participant_identity, remote_participant_permissions, shared_secret, ex)); default: @@ -335,6 +521,7 @@ static DDS_Security_DatawriterCryptoHandle register_local_datawriter( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: return check_handle (impl->instance->register_local_datawriter (impl->instance, check_handle (participant_crypto), datawriter_properties, datawriter_security_attributes, ex)); default: @@ -354,6 +541,7 @@ static DDS_Security_DatareaderCryptoHandle register_matched_remote_datareader( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: return check_handle (impl->instance->register_matched_remote_datareader (impl->instance, check_handle (local_datawriter_crypto_handle), check_handle (remote_participant_crypto), check_handle (shared_secret), relay_only, ex)); default: @@ -372,6 +560,7 @@ static DDS_Security_DatareaderCryptoHandle register_local_datareader( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: return check_handle (impl->instance->register_local_datareader (impl->instance, check_handle (participant_crypto), datareader_properties, datareader_security_attributes, ex)); default: @@ -390,6 +579,7 @@ static DDS_Security_DatawriterCryptoHandle register_matched_remote_datawriter( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: return check_handle (impl->instance->register_matched_remote_datawriter (impl->instance, check_handle (local_datareader_crypto_handle), check_handle (remote_participant_crypt), shared_secret, ex)); default: @@ -406,6 +596,7 @@ static DDS_Security_boolean unregister_participant( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: return impl->instance->unregister_participant (impl->instance, check_handle (participant_crypto_handle), ex); default: return true; @@ -421,6 +612,7 @@ static DDS_Security_boolean unregister_datawriter( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: return impl->instance->unregister_datawriter (impl->instance, check_handle (datawriter_crypto_handle), ex); default: return true; @@ -436,6 +628,7 @@ static DDS_Security_boolean unregister_datareader( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: return impl->instance->unregister_datareader (impl->instance, check_handle (datareader_crypto_handle), ex); default: return true; @@ -457,6 +650,7 @@ static DDS_Security_boolean encode_serialized_payload( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: { if (!impl->instance->encode_serialized_payload (impl->instance, encoded_buffer, extra_inline_qos, plain_buffer, check_handle (sending_datawriter_crypto), ex)) @@ -511,6 +705,7 @@ static DDS_Security_boolean encode_datawriter_submessage( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: if (!impl->instance->encode_datawriter_submessage (impl->instance, encoded_rtps_submessage, plain_rtps_submessage, check_handle (sending_datawriter_crypto), receiving_datareader_crypto_list, receiving_datareader_crypto_list_index, ex)) return false; @@ -558,6 +753,7 @@ static DDS_Security_boolean encode_datareader_submessage( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: if (!impl->instance->encode_datareader_submessage (impl->instance, encoded_rtps_submessage, plain_rtps_submessage, check_handle (sending_datareader_crypto), receiving_datawriter_crypto_list, ex)) return false; @@ -580,6 +776,7 @@ static DDS_Security_boolean encode_rtps_message( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: if (!impl->instance->encode_rtps_message (impl->instance, encoded_rtps_message, plain_rtps_message, check_handle (sending_participant_crypto), receiving_participant_crypto_list, receiving_participant_crypto_list_index, ex)) return false; @@ -611,6 +808,7 @@ static DDS_Security_boolean decode_rtps_message( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: return impl->instance->decode_rtps_message (impl->instance, plain_buffer, encoded_buffer, check_handle (receiving_participant_crypto), check_handle (sending_participant_crypto), ex); default: @@ -632,6 +830,7 @@ static DDS_Security_boolean preprocess_secure_submsg( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: return impl->instance->preprocess_secure_submsg (impl->instance, datawriter_crypto, datareader_crypto, secure_submessage_category, encoded_rtps_submessage, check_handle (receiving_participant_crypto), check_handle (sending_participant_crypto), ex); default: @@ -651,6 +850,7 @@ static DDS_Security_boolean decode_datawriter_submessage( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: return impl->instance->decode_datawriter_submessage (impl->instance, plain_rtps_submessage, encoded_rtps_submessage, check_handle (receiving_datareader_crypto), check_handle (sending_datawriter_crypto), ex); default: @@ -670,6 +870,7 @@ static DDS_Security_boolean decode_datareader_submessage( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: return impl->instance->decode_datareader_submessage (impl->instance, plain_rtps_submessage, encoded_rtps_submessage, check_handle (receiving_datawriter_crypto), check_handle (sending_datareader_crypto), ex); default: @@ -690,6 +891,7 @@ static DDS_Security_boolean decode_serialized_payload( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_TOKEN_LOG: return impl->instance->decode_serialized_payload(impl->instance, plain_buffer, encoded_buffer, inline_qos, check_handle (receiving_datareader_crypto), check_handle (sending_datawriter_crypto), ex); default: @@ -815,3 +1017,41 @@ int finalize_test_cryptography_wrapped(void *context) return finalize_test_cryptography_common(impl, true); } +static void init_print_lock(void) +{ + ddsrt_mutex_init (&g_print_token_lock); +} + +int32_t init_test_cryptography_store_tokens(const char *argument, void **context, struct ddsi_domaingv *gv) +{ + struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, true, gv); + if (!impl) + return DDS_SECURITY_FAILED; + impl->mode = PLUGIN_MODE_TOKEN_LOG; + ddsrt_once (&lock_inited, &init_print_lock); + ddsrt_mutex_init (&impl->token_data_lock); + ddsrt_circlist_init (&impl->token_data_list); + *context = impl; + return DDS_SECURITY_SUCCESS; +} + +int32_t finalize_test_cryptography_store_tokens(void *context) +{ + struct dds_security_cryptography_impl* impl = (struct dds_security_cryptography_impl*) context; + assert(impl->mode == PLUGIN_MODE_TOKEN_LOG); + ddsrt_mutex_lock (&impl->token_data_lock); + while (!ddsrt_circlist_isempty (&impl->token_data_list)) + { + struct ddsrt_circlist_elem *list_elem = ddsrt_circlist_oldest (&impl->token_data_list); + struct crypto_token_data *token_data = DDSRT_FROM_CIRCLIST (struct crypto_token_data, e, list_elem); + ddsrt_circlist_remove (&impl->token_data_list, list_elem); + ddsrt_free (token_data); + } + ddsrt_mutex_unlock (&impl->token_data_lock); + ddsrt_mutex_destroy (&impl->token_data_lock); + /* don't detroy g_print_token_lock as this will result in multiple + calls to mutex_destroy for this lock in case of multiple domains */ + + return finalize_test_cryptography_common(impl, true); +} + diff --git a/src/security/core/tests/common/cryptography_wrapper.h b/src/security/core/tests/common/cryptography_wrapper.h index 0c50adc..b9384c9 100644 --- a/src/security/core/tests/common/cryptography_wrapper.h +++ b/src/security/core/tests/common/cryptography_wrapper.h @@ -12,13 +12,37 @@ #ifndef SECURITY_CORE_TEST_CRYPTO_WRAPPER_H_ #define SECURITY_CORE_TEST_CRYPTO_WRAPPER_H_ +#include "dds/ddsrt/circlist.h" #include "dds/ddsi/ddsi_domaingv.h" #include "dds/security/dds_security_api.h" #include "dds/security/dds_security_api_defs.h" #include "dds/security/cryptography_wrapper_export.h" +#define CRYPTO_TOKEN_MAXLEN 10 +#define CRYPTO_TOKEN_SIZE 256 + struct dds_security_cryptography_impl; +enum crypto_tokens_type { + LOCAL_PARTICIPANT_TOKENS, + LOCAL_WRITER_TOKENS, + LOCAL_READER_TOKENS, + REMOTE_PARTICIPANT_TOKENS, + REMOTE_WRITER_TOKENS, + REMOTE_READER_TOKENS, + TOKEN_TYPE_INVALID +}; + +struct crypto_token_data { + struct ddsrt_circlist_elem e; + enum crypto_tokens_type type; + DDS_Security_ParticipantCryptoHandle local_handle; + DDS_Security_ParticipantCryptoHandle remote_handle; + uint32_t n_tokens; + unsigned char data[CRYPTO_TOKEN_MAXLEN][CRYPTO_TOKEN_SIZE]; + size_t data_len[CRYPTO_TOKEN_MAXLEN]; +}; + SECURITY_EXPORT void set_protection_kinds( struct dds_security_cryptography_impl * impl, DDS_Security_ProtectionKind rtps_protection_kind, @@ -34,6 +58,10 @@ SECURITY_EXPORT void set_disc_protection_kinds( SECURITY_EXPORT void set_entity_data_secret(struct dds_security_cryptography_impl * impl, const char * pp_secret, const char * groupdata_secret, const char * ep_secret); +SECURITY_EXPORT const char *get_crypto_token_type_str (enum crypto_tokens_type type); +SECURITY_EXPORT struct ddsrt_circlist * get_crypto_tokens (struct dds_security_cryptography_impl * impl); +SECURITY_EXPORT struct crypto_token_data * find_crypto_token (struct dds_security_cryptography_impl * impl, enum crypto_tokens_type type, unsigned char * data, size_t data_len); + /* Init in all-ok mode: all functions return success without calling the actual plugin */ SECURITY_EXPORT int init_test_cryptography_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int finalize_test_cryptography_all_ok(void *context); @@ -46,4 +74,8 @@ SECURITY_EXPORT int finalize_test_cryptography_missing_func(void *context); SECURITY_EXPORT int init_test_cryptography_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int finalize_test_cryptography_wrapped(void *context); +/* Init in store-token mode (stores all exchanged security tokens) */ +SECURITY_EXPORT int32_t init_test_cryptography_store_tokens(const char *argument, void **context, struct ddsi_domaingv *gv); +SECURITY_EXPORT int32_t finalize_test_cryptography_store_tokens(void *context); + #endif /* SECURITY_CORE_TEST_CRYPTO_WRAPPER_H_ */ diff --git a/src/security/core/tests/common/test_utils.c b/src/security/core/tests/common/test_utils.c index a75c6b9..3f94a85 100644 --- a/src/security/core/tests/common/test_utils.c +++ b/src/security/core/tests/common/test_utils.c @@ -18,6 +18,10 @@ #include "dds/ddsrt/string.h" #include "dds/ddsrt/threads.h" #include "dds/ddsrt/heap.h" +#include "dds/ddsi/q_entity.h" +#include "dds/ddsi/ddsi_entity_index.h" +#include "dds/ddsi/ddsi_security_omg.h" +#include "dds__entity.h" #include "dds/security/dds_security_api.h" #include "authentication_wrapper.h" #include "test_utils.h" @@ -449,3 +453,21 @@ void write_read_for(dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_du CU_ASSERT_EQUAL_FATAL (write_fail, exp_write_fail); CU_ASSERT_EQUAL_FATAL (read_fail, exp_read_fail); } + +struct dds_security_cryptography_impl * get_crypto_context(dds_entity_t participant) +{ + struct dds_entity *pp_entity = NULL; + struct participant *pp; + struct dds_security_cryptography_impl *context; + dds_return_t ret; + + ret = dds_entity_lock (participant, DDS_KIND_PARTICIPANT, &pp_entity); + CU_ASSERT_EQUAL_FATAL (ret, 0); + thread_state_awake (lookup_thread_state(), &pp_entity->m_domain->gv); + pp = entidx_lookup_participant_guid (pp_entity->m_domain->gv.entity_index, &pp_entity->m_guid); + CU_ASSERT_FATAL (pp != NULL); + context = (struct dds_security_cryptography_impl *) q_omg_participant_get_cryptography (pp); + thread_state_asleep (lookup_thread_state ()); + dds_entity_unlock (pp_entity); + return context; +} diff --git a/src/security/core/tests/common/test_utils.h b/src/security/core/tests/common/test_utils.h index ac1e8a7..919affe 100644 --- a/src/security/core/tests/common/test_utils.h +++ b/src/security/core/tests/common/test_utils.h @@ -69,5 +69,6 @@ void rd_wr_init_fail( bool exp_pubtp_fail, bool exp_wr_fail, bool exp_subtp_fail, bool exp_rd_fail); void write_read_for(dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_duration_t dur, bool exp_write_fail, bool exp_read_fail); +struct dds_security_cryptography_impl * get_crypto_context(dds_entity_t participant); #endif /* SECURITY_CORE_TEST_UTILS_H_ */ diff --git a/src/security/core/tests/handshake.c b/src/security/core/tests/handshake.c index 66a77f9..5947a8f 100644 --- a/src/security/core/tests/handshake.c +++ b/src/security/core/tests/handshake.c @@ -20,6 +20,7 @@ #include "dds/ddsrt/environ.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" +#include "dds/ddsrt/string.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_misc.h" @@ -29,9 +30,11 @@ #include "common/config_env.h" #include "common/authentication_wrapper.h" +#include "common/cryptography_wrapper.h" #include "common/plugin_wrapper_msg_q.h" #include "common/test_utils.h" #include "common/test_identity.h" +#include "common/security_config_test_utils.h" static const char *config = "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" @@ -42,7 +45,7 @@ static const char *config = " " " " " " - " " + " " " data:,"TEST_IDENTITY1_CERTIFICATE"" " data:,"TEST_IDENTITY1_PRIVATE_KEY"" " data:,"TEST_IDENTITY_CA1_CERTIFICATE"" @@ -54,43 +57,120 @@ static const char *config = " file:" COMMON_ETC_PATH("default_permissions.p7s") "" "
    " " " - " " + " " " " "
    " ""; -#define DDS_DOMAINID_PART1 0 -#define DDS_DOMAINID_PART2 1 +#define DDS_DOMAINID1 0 +#define DDS_DOMAINID2 1 -static dds_entity_t g_part1_domain = 0; -static dds_entity_t g_part1_participant = 0; +static dds_entity_t g_domain1 = 0; +static dds_entity_t g_participant1 = 0; -static dds_entity_t g_part2_domain = 0; -static dds_entity_t g_part2_participant = 0; +static dds_entity_t g_domain2 = 0; +static dds_entity_t g_participant2 = 0; -static void handshake_init(void) +static uint32_t g_topic_nr = 0; +static dds_entity_t g_pub = 0, g_pub_tp = 0, g_wr = 0, g_sub = 0, g_sub_tp = 0, g_rd = 0; + +static void handshake_init(const char * auth_init, const char * auth_fini, const char * crypto_init, const char * crypto_fini) { - char *conf_part1 = ddsrt_expand_envvars_sh (config, DDS_DOMAINID_PART1); - char *conf_part2 = ddsrt_expand_envvars_sh (config, DDS_DOMAINID_PART2); - g_part1_domain = dds_create_domain (DDS_DOMAINID_PART1, conf_part1); - g_part2_domain = dds_create_domain (DDS_DOMAINID_PART2, conf_part2); - dds_free (conf_part1); - dds_free (conf_part2); + struct kvp config_vars[] = { + { "AUTH_INIT", auth_init, 1}, + { "AUTH_FINI", auth_fini, 1}, + { "CRYPTO_INIT", crypto_init, 1 }, + { "CRYPTO_FINI", crypto_fini, 1 }, + { NULL, NULL, 0 } + }; - CU_ASSERT_FATAL ((g_part1_participant = dds_create_participant (DDS_DOMAINID_PART1, NULL, NULL)) > 0); - CU_ASSERT_FATAL ((g_part2_participant = dds_create_participant (DDS_DOMAINID_PART2, NULL, NULL)) > 0); + char *conf = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars); + int32_t unmatched = expand_lookup_unmatched (config_vars); + CU_ASSERT_EQUAL_FATAL (unmatched, 0); + g_domain1 = dds_create_domain (DDS_DOMAINID1, conf); + g_domain2 = dds_create_domain (DDS_DOMAINID2, conf); + dds_free (conf); + + g_participant1 = dds_create_participant (DDS_DOMAINID1, NULL, NULL); + CU_ASSERT_FATAL (g_participant1 > 0); + g_participant2 = dds_create_participant (DDS_DOMAINID2, NULL, NULL); + CU_ASSERT_FATAL (g_participant2 > 0); } static void handshake_fini(void) { - CU_ASSERT_EQUAL_FATAL (dds_delete (g_part1_participant), DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL (dds_delete (g_part2_participant), DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL (dds_delete (g_part1_domain), DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL (dds_delete (g_part2_domain), DDS_RETCODE_OK); + dds_return_t ret = dds_delete (g_domain1); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); + ret = dds_delete (g_domain2); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); } -CU_Test(ddssec_handshake, happy_day, .init = handshake_init, .fini = handshake_fini) +CU_Test(ddssec_handshake, happy_day) { - validate_handshake_nofail (DDS_DOMAINID_PART1); - validate_handshake_nofail (DDS_DOMAINID_PART2); + handshake_init ( + "init_test_authentication_wrapped", "finalize_test_authentication_wrapped", + "init_test_cryptography_wrapped", "finalize_test_cryptography_wrapped"); + validate_handshake_nofail (DDS_DOMAINID1); + validate_handshake_nofail (DDS_DOMAINID2); + handshake_fini (); +} + +CU_Test(ddssec_handshake, check_tokens) +{ + handshake_init ( + "init_test_authentication_wrapped", "finalize_test_authentication_wrapped", + "init_test_cryptography_store_tokens", "finalize_test_cryptography_store_tokens"); + validate_handshake_nofail (DDS_DOMAINID1); + validate_handshake_nofail (DDS_DOMAINID2); + + char topic_name[100]; + create_topic_name("ddssec_authentication_", g_topic_nr++, topic_name, sizeof (topic_name)); + rd_wr_init (g_participant1, &g_pub, &g_pub_tp, &g_wr, g_participant2, &g_sub, &g_sub_tp, &g_rd, topic_name); + write_read_for (g_wr, g_participant2, g_rd, DDS_MSECS (100), false, false); + + // Get subscriber and publisher crypto tokens + struct dds_security_cryptography_impl * crypto_context_pub = get_crypto_context (g_participant1); + CU_ASSERT_FATAL (crypto_context_pub != NULL); + struct ddsrt_circlist *pub_tokens = get_crypto_tokens (crypto_context_pub); + + struct dds_security_cryptography_impl * crypto_context_sub = get_crypto_context (g_participant2); + CU_ASSERT_FATAL (crypto_context_sub != NULL); + struct ddsrt_circlist *sub_tokens = get_crypto_tokens (crypto_context_sub); + + // Find all publisher tokens in subscribers token store + while (!ddsrt_circlist_isempty (pub_tokens)) + { + struct ddsrt_circlist_elem *list_elem = ddsrt_circlist_oldest (pub_tokens); + struct crypto_token_data *token_data = DDSRT_FROM_CIRCLIST (struct crypto_token_data, e, list_elem); + enum crypto_tokens_type exp_type = TOKEN_TYPE_INVALID; + for (size_t n = 0; n < token_data->n_tokens; n++) + { + switch (token_data->type) + { + case LOCAL_PARTICIPANT_TOKENS: exp_type = REMOTE_PARTICIPANT_TOKENS; break; + case REMOTE_PARTICIPANT_TOKENS: exp_type = LOCAL_PARTICIPANT_TOKENS; break; + case LOCAL_WRITER_TOKENS: exp_type = REMOTE_WRITER_TOKENS; break; + case REMOTE_WRITER_TOKENS: exp_type = LOCAL_WRITER_TOKENS; break; + case LOCAL_READER_TOKENS: exp_type = REMOTE_READER_TOKENS; break; + case REMOTE_READER_TOKENS: exp_type = LOCAL_READER_TOKENS; break; + default: CU_FAIL ("Unexpected token type"); + } + printf("- find token %s #%"PRIuSIZE", len %"PRIuSIZE"\n", get_crypto_token_type_str (token_data->type), n, token_data->data_len[n]); + struct crypto_token_data *st = find_crypto_token (crypto_context_sub, exp_type, token_data->data[n], token_data->data_len[n]); + CU_ASSERT_FATAL (st != NULL); + } + ddsrt_circlist_remove (pub_tokens, list_elem); + ddsrt_free (token_data); + } + + // Cleanup + while (!ddsrt_circlist_isempty (sub_tokens)) + { + struct ddsrt_circlist_elem *list_elem = ddsrt_circlist_oldest (sub_tokens); + ddsrt_circlist_remove (sub_tokens, list_elem); + ddsrt_free (list_elem); + } + ddsrt_free (sub_tokens); + ddsrt_free (pub_tokens); + handshake_fini (); } diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index 92b40a4..186944c 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -27,14 +27,11 @@ #include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_misc.h" #include "dds/ddsi/ddsi_xqos.h" -#include "dds/ddsi/q_entity.h" -#include "dds/ddsi/ddsi_entity_index.h" -#include "dds/ddsi/ddsi_security_omg.h" -#include "dds__entity.h" #include "dds/security/dds_security_api.h" #include "common/config_env.h" #include "common/test_identity.h" +#include "common/test_utils.h" #include "common/security_config_test_utils.h" #include "common/cryptography_wrapper.h" @@ -119,25 +116,6 @@ typedef void (*set_crypto_params_fn)(struct dds_security_cryptography_impl *, co typedef dds_entity_t (*pubsub_create_fn)(dds_entity_t, const dds_qos_t *qos, const dds_listener_t *listener); typedef dds_entity_t (*ep_create_fn)(dds_entity_t, dds_entity_t, const dds_qos_t *qos, const dds_listener_t *listener); - -static struct dds_security_cryptography_impl * get_crypto_context(dds_entity_t participant) -{ - struct dds_entity *pp_entity = NULL; - struct participant *pp; - struct dds_security_cryptography_impl *context; - dds_return_t ret; - - ret = dds_entity_lock (participant, DDS_KIND_PARTICIPANT, &pp_entity); - CU_ASSERT_EQUAL_FATAL (ret, 0); - thread_state_awake (lookup_thread_state(), &pp_entity->m_domain->gv); - pp = entidx_lookup_participant_guid (pp_entity->m_domain->gv.entity_index, &pp_entity->m_guid); - CU_ASSERT_FATAL (pp != NULL); - context = (struct dds_security_cryptography_impl *) q_omg_participant_get_cryptography (pp); - thread_state_asleep (lookup_thread_state ()); - dds_entity_unlock (pp_entity); - return context; -} - static const char * pk_to_str(DDS_Security_ProtectionKind pk) { switch (pk) @@ -181,14 +159,6 @@ static dds_qos_t *get_qos() return qos; } -static char *create_topic_name(const char *prefix, uint32_t nr, char *name, size_t size) -{ - ddsrt_pid_t pid = ddsrt_getpid (); - ddsrt_tid_t tid = ddsrt_gettid (); - (void)snprintf(name, size, "%s%d_pid%" PRIdPID "_tid%" PRIdTID "", prefix, nr, pid, tid); - return name; -} - static dds_entity_t create_pp (dds_domainid_t domain_id, const struct domain_sec_config * domain_config, set_crypto_params_fn set_crypto_params) { dds_qos_t *qos = dds_create_qos (); @@ -280,45 +250,6 @@ static void test_fini(size_t n_sub_domain, size_t n_pub_domain) printf("Test finished\n"); } -static void sync_writer_to_readers(dds_entity_t pub_participant, dds_entity_t writer, size_t n_exp_rd) -{ - dds_attach_t triggered; - dds_return_t ret; - dds_entity_t waitset_wr = dds_create_waitset (pub_participant); - CU_ASSERT_FATAL (waitset_wr > 0); - dds_publication_matched_status_t pub_matched; - - /* Sync writer to reader. */ - ret = dds_waitset_attach (waitset_wr, writer, writer); - CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); - while (true) - { - ret = dds_waitset_wait (waitset_wr, &triggered, 1, DDS_SECS(5)); - CU_ASSERT_FATAL (ret >= 1); - CU_ASSERT_EQUAL_FATAL (writer, (dds_entity_t)(intptr_t) triggered); - ret = dds_get_publication_matched_status(writer, &pub_matched); - CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); - if (pub_matched.total_count >= n_exp_rd) - break; - }; - dds_delete (waitset_wr); -} - -static void reader_wait_for_data(dds_entity_t sub_participant, dds_entity_t reader) -{ - dds_attach_t triggered; - dds_return_t ret; - dds_entity_t waitset_rd = dds_create_waitset (sub_participant); - CU_ASSERT_FATAL (waitset_rd > 0); - - ret = dds_waitset_attach (waitset_rd, reader, reader); - CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); - ret = dds_waitset_wait (waitset_rd, &triggered, 1, DDS_SECS(5)); - CU_ASSERT_EQUAL_FATAL (ret, 1); - CU_ASSERT_EQUAL_FATAL (reader, (dds_entity_t)(intptr_t)triggered); - dds_delete (waitset_rd); -} - static void create_eps (dds_entity_t **endpoints, dds_entity_t **topics, size_t n_dom, size_t n_pp, size_t n_eps, const char * topic_name, const dds_topic_descriptor_t *topic_descriptor, const dds_entity_t * pps, const dds_qos_t * qos, ep_create_fn ep_create, unsigned status_mask) { @@ -381,7 +312,7 @@ static void test_write_read(struct domain_sec_config *domain_config, for (size_t w = 0; w < n_writers; w++) { size_t wr_index = pp_index * n_writers + w; - sync_writer_to_readers (g_pub_participants[pp_index], writers[wr_index], n_sub_domains * n_sub_participants * n_readers); + sync_writer_to_readers (g_pub_participants[pp_index], writers[wr_index], (uint32_t)(n_sub_domains * n_sub_participants * n_readers)); sample.id = (int32_t) wr_index; printf("writer %"PRId32" writing sample %d\n", writers[wr_index], sample.id); ret = dds_write (writers[wr_index], &sample); @@ -404,7 +335,7 @@ static void test_write_read(struct domain_sec_config *domain_config, ret = dds_take (readers[rd_index], samples, info, 1, 1); if (ret == 0) { - reader_wait_for_data (g_sub_participants[pp_index], readers[rd_index]); + reader_wait_for_data (g_sub_participants[pp_index], readers[rd_index], DDS_SECS(5)); continue; } printf("reader %"PRId32" received sample %d\n", readers[rd_index], rd_sample.id); @@ -500,7 +431,7 @@ static void test_payload_secret(DDS_Security_ProtectionKind rtps_pk, DDS_Securit { if ((ret = dds_take (readers[0], samples, info, 1, 1)) == 0) { - reader_wait_for_data (g_sub_participants[0], readers[0]); + reader_wait_for_data (g_sub_participants[0], readers[0], DDS_SECS(5)); continue; } CU_ASSERT_EQUAL_FATAL (ret, 1); From 9f261423e3ef0727a960001cc4c23f918f5474ea Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Fri, 24 Apr 2020 19:43:55 +0200 Subject: [PATCH 182/238] Add tests for discovery protection Adding a test that checks the effects of using different configuration settings for discovery protection. This test set uses the cryptography wrapper to count the number of invocations of the encode and decode functions during a session and checks the counts with the expected values. Signed-off-by: Dennis Potman --- src/security/core/tests/access_control.c | 153 +++++++++++++++++- src/security/core/tests/authentication.c | 12 +- .../core/tests/common/cryptography_wrapper.c | 90 ++++++++++- .../core/tests/common/cryptography_wrapper.h | 15 ++ .../tests/common/security_config_test_utils.c | 62 +++++-- .../tests/common/security_config_test_utils.h | 6 +- src/security/core/tests/common/test_utils.c | 32 ++++ src/security/core/tests/common/test_utils.h | 11 ++ .../core/tests/secure_communication.c | 71 +------- 9 files changed, 359 insertions(+), 93 deletions(-) diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index 3b04fc6..23c32f3 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -23,15 +23,20 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/io.h" #include "dds/ddsrt/string.h" +#include "dds/ddsi/q_entity.h" +#include "dds/ddsi/ddsi_entity_index.h" +#include "dds/ddsi/ddsi_security_omg.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/q_misc.h" #include "dds/ddsi/ddsi_xqos.h" +#include "dds__entity.h" #include "dds/security/dds_security_api.h" #include "common/config_env.h" #include "common/access_control_wrapper.h" +#include "common/cryptography_wrapper.h" #include "common/security_config_test_utils.h" #include "common/test_identity.h" #include "common/test_utils.h" @@ -59,7 +64,7 @@ static const char *config = " ${INCL_PERM:+}" "
    " " " - " " + " " " " "
    " ""; @@ -114,6 +119,41 @@ static void access_control_fini(size_t n) CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain[i]), DDS_RETCODE_OK); } +static DDS_Security_DatawriterCryptoHandle get_builtin_writer_crypto_handle(dds_entity_t participant, unsigned entityid) +{ + DDS_Security_DatawriterCryptoHandle crypto_handle; + struct dds_entity *pp_entity; + struct participant *pp; + struct writer *wr; + CU_ASSERT_EQUAL_FATAL(dds_entity_pin(participant, &pp_entity), 0); + thread_state_awake(lookup_thread_state(), &pp_entity->m_domain->gv); + pp = entidx_lookup_participant_guid(pp_entity->m_domain->gv.entity_index, &pp_entity->m_guid); + wr = get_builtin_writer(pp, entityid); + CU_ASSERT_FATAL(wr != NULL); + assert(wr != NULL); /* for Clang's static analyzer */ + crypto_handle = wr->sec_attr->crypto_handle; + thread_state_asleep(lookup_thread_state()); + dds_entity_unpin(pp_entity); + return crypto_handle; +} + +// static DDS_Security_DatawriterCryptoHandle get_writer_crypto_handle(dds_entity_t writer) +// { +// DDS_Security_DatawriterCryptoHandle crypto_handle; +// struct dds_entity *wr_entity; +// struct writer *wr; +// CU_ASSERT_EQUAL_FATAL(dds_entity_pin(writer, &wr_entity), 0); +// thread_state_awake(lookup_thread_state(), &wr_entity->m_domain->gv); +// wr = entidx_lookup_writer_guid(wr_entity->m_domain->gv.entity_index, &wr_entity->m_guid); +// CU_ASSERT_FATAL(wr != NULL); +// assert(wr != NULL); /* for Clang's static analyzer */ +// crypto_handle = wr->sec_attr->crypto_handle; +// thread_state_asleep(lookup_thread_state()); +// dds_entity_unpin(wr_entity); +// return crypto_handle; +// } + + #define GOV_F PF_F COMMON_ETC_PATH("default_governance.p7s") #define GOV_FNE PF_F COMMON_ETC_PATH("default_governance_non_existing.p7s") #define GOV_DI PF_D COMMON_ETC_PATH("default_governance.p7s") @@ -512,11 +552,9 @@ CU_Theory( get_permissions_grant ("id2", id2_subj, perm_inv_pp2 ? "99" : NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL) }; char * perm_config = get_permissions_config (grants, 2, true); - struct kvp governance_vars_pp1[] = { { "ENABLE_JOIN_AC", join_ac_pp1 ? "true" : "false", 1 }, { NULL, NULL, 0 } }; - struct kvp governance_vars_pp2[] = { { "ENABLE_JOIN_AC", join_ac_pp2 ? "true" : "false", 1 }, { NULL, NULL, 0 } }; - - char * gov_config_pp1 = get_governance_config (governance_vars_pp1, true); - char * gov_config_pp2 = get_governance_config (governance_vars_pp2, true); + char * gov_topic_rule = get_governance_topic_rule ("*", false, false, true, true, "NONE", "NONE"); + char * gov_config_pp1 = get_governance_config (false, join_ac_pp1, NULL, NULL, NULL, gov_topic_rule, true); + char * gov_config_pp2 = get_governance_config (false, join_ac_pp2, NULL, NULL, NULL, gov_topic_rule, true); const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); access_control_init ( @@ -536,6 +574,109 @@ CU_Theory( ddsrt_free (gov_config_pp1); ddsrt_free (gov_config_pp2); + ddsrt_free (gov_topic_rule); + ddsrt_free (perm_topic); + ddsrt_free (grants[0]); + ddsrt_free (grants[1]); + ddsrt_free (perm_config); + ddsrt_free (ca); + ddsrt_free (id1_subj); + ddsrt_free (id2_subj); + ddsrt_free (id1); + ddsrt_free (id2); +} + +#define na false +#define E ENCRYPT +CU_TheoryDataPoints(ddssec_access_control, discovery_protection) = { + CU_DataPoints(const char *, + /* */"disabled", + /* | */"enabled, protection kind none", + /* | | */"disabled, protection kind encrypt", + /* | | | */"enabled, protection kind encrypt", + /* | | | | */"enabled, protection kind sign", + /* | | | | | */"enabled, protection kind encrypt-with-origin_auth", + /* | | | | | | */"enabled for node 1, disabled for node 2", + /* | | | | | | | */"node 1 and node 2 different protection kinds"), + CU_DataPoints(bool, false, true, false, true, true, true, true, true), /* enable_discovery_protection for pp 1 */ + CU_DataPoints(bool, false, true, false, true, true, true, false, true), /* enable_discovery_protection for pp 2 */ + CU_DataPoints(DDS_Security_ProtectionKind, PK_N, PK_N, PK_E, PK_E, PK_S, PK_EOA, PK_E, PK_E), /* discovery_protection_kind pp 1 */ + CU_DataPoints(DDS_Security_ProtectionKind, PK_N, PK_N, PK_E, PK_E, PK_S, PK_EOA, PK_N, PK_S), /* discovery_protection_kind pp 2 */ + CU_DataPoints(bool, false, false, false, false, false, false, true, true), /* expect rd-wr match fail */ + CU_DataPoints(bool, false, false, true, true, true, true, true, true), /* expect SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER of pp 1 to have a crypto handle */ + CU_DataPoints(bool, na, na, true, true, true, true, false, false), /* expect encode_datawriter_submessage for SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER of pp 1 */ +}; +#undef na +CU_Theory( + (const char * test_descr, bool enable_discovery_protection_pp1, bool enable_discovery_protection_pp2, + DDS_Security_ProtectionKind discovery_protection_kind_pp1, DDS_Security_ProtectionKind discovery_protection_kind_pp2, + bool exp_rd_wr_match_fail, bool exp_secure_pub_wr_handle, bool exp_secure_pub_wr_encode_decode), + ddssec_access_control, discovery_protection, .timeout=30) +{ + print_test_msg ("running test discovery_protection: %s\n", test_descr); + + char topic_name[100]; + create_topic_name ("ddssec_access_control_", g_topic_nr++, topic_name, sizeof (topic_name)); + + /* create ca and id1/id2 certs that will not expire during this test */ + char *ca, *id1, *id2, *id1_subj, *id2_subj; + ca = generate_ca ("ca1", TEST_IDENTITY_CA1_PRIVATE_KEY, 0, 3600); + id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id1_subj); + id2 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id2", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id2_subj); + + /* localtime will be converted to gmtime in get_permissions_grant */ + dds_time_t now = dds_time (); + char * perm_topic = get_permissions_topic (topic_name); + char * grants[] = { + get_permissions_grant ("id1", id1_subj, NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL), + get_permissions_grant ("id2", id2_subj, NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL) }; + char * perm_config = get_permissions_config (grants, 2, true); + + char * gov_topic_rule1 = get_governance_topic_rule (topic_name, enable_discovery_protection_pp1, false, true, true, "ENCRYPT", "NONE"); + char * gov_topic_rule2 = get_governance_topic_rule (topic_name, enable_discovery_protection_pp2, false, true, true, "ENCRYPT", "NONE"); + char * gov_config1 = get_governance_config (false, true, pk_to_str (discovery_protection_kind_pp1), NULL, "ENCRYPT", gov_topic_rule1, true); + char * gov_config2 = get_governance_config (false, true, pk_to_str (discovery_protection_kind_pp2), NULL, "ENCRYPT", gov_topic_rule2, true); + const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); + + access_control_init ( + 2, + (const char *[]) { id1, id2 }, + (const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY }, + (const char *[]) { ca, ca }, + (bool []) { false, false }, NULL, NULL, + (bool []) { true, true }, (const char *[]) { gov_config1, gov_config2 }, + (bool []) { true, true }, (const char *[]) { perm_config, perm_config }, + (bool []) { true, true }, (const char *[]) { def_perm_ca, def_perm_ca }); + validate_handshake (DDS_DOMAINID, false, NULL, NULL, NULL); + + dds_entity_t pub, sub, pub_tp, sub_tp, wr, rd; + rd_wr_init (g_participant[0], &pub, &pub_tp, &wr, g_participant[1], &sub, &sub_tp, &rd, topic_name); + sync_writer_to_readers (g_participant[0], wr, exp_rd_wr_match_fail ? 0 : 1); + if (!exp_rd_wr_match_fail) + write_read_for (wr, g_participant[1], rd, DDS_MSECS (100), false, false); + + DDS_Security_DatawriterCryptoHandle secure_pub_wr_handle = get_builtin_writer_crypto_handle (g_participant[0], NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER); + print_test_msg ("crypto handle for SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER: %ld\n", secure_pub_wr_handle); + CU_ASSERT_EQUAL_FATAL (exp_secure_pub_wr_handle, secure_pub_wr_handle != 0); + + struct dds_security_cryptography_impl * crypto_context_pub = get_crypto_context (g_participant[0]); + CU_ASSERT_FATAL (crypto_context_pub != NULL); + + struct crypto_encode_decode_data *log = get_encode_decode_log (crypto_context_pub, ENCODE_DATAWRITER_SUBMESSAGE, secure_pub_wr_handle); + CU_ASSERT_EQUAL_FATAL (exp_secure_pub_wr_handle && exp_secure_pub_wr_encode_decode, log != NULL); + if (log != NULL) + { + print_test_msg ("encode_datawriter_submessage count for SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER: %u\n", log->count); + CU_ASSERT_FATAL (log->count > 0); + ddsrt_free (log); + } + + access_control_fini (2); + + ddsrt_free (gov_config1); + ddsrt_free (gov_config2); + ddsrt_free (gov_topic_rule1); + ddsrt_free (gov_topic_rule2); ddsrt_free (perm_topic); ddsrt_free (grants[0]); ddsrt_free (grants[1]); diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index dbd80be..0af4138 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -101,15 +101,8 @@ static void authentication_init( if (perm_config == NULL) perm_config = DEF_PERM_CONF; - struct kvp governance_vars[] = { - { "DISCOVERY_PROTECTION_KIND", "NONE", 1 }, - { "LIVELINESS_PROTECTION_KIND", "NONE", 1 }, - { "RTPS_PROTECTION_KIND", "NONE", 1 }, - { "METADATA_PROTECTION_KIND", "NONE", 1 }, - { "DATA_PROTECTION_KIND", "NONE", 1 }, - { NULL, NULL, 0 } - }; - char * gov_config_signed = get_governance_config (governance_vars, true); + char * gov_topic_rule = get_governance_topic_rule ("*", false, false, true, true, "NONE", "NONE"); + char * gov_config_signed = get_governance_config (false, false, NULL, NULL, NULL, gov_topic_rule, true); struct kvp config_vars1[] = { { "TEST_IDENTITY_CERTIFICATE", id1_cert, 1 }, @@ -143,6 +136,7 @@ static void authentication_init( CU_ASSERT_EQUAL_FATAL (exp_pp2_fail, g_participant2 <= 0); ddsrt_free (gov_config_signed); + ddsrt_free (gov_topic_rule); ddsrt_free (conf1); ddsrt_free (conf2); } diff --git a/src/security/core/tests/common/cryptography_wrapper.c b/src/security/core/tests/common/cryptography_wrapper.c index 1856c09..990e2c8 100644 --- a/src/security/core/tests/common/cryptography_wrapper.c +++ b/src/security/core/tests/common/cryptography_wrapper.c @@ -74,6 +74,8 @@ struct dds_security_cryptography_impl { const char * encrypted_secret; ddsrt_mutex_t token_data_lock; struct ddsrt_circlist token_data_list; + ddsrt_mutex_t encode_decode_log_lock; + struct ddsrt_circlist encode_decode_log; }; static DDS_Security_ParticipantCryptoHandle g_local_participant_handle = 0; @@ -211,6 +213,12 @@ struct ddsrt_circlist * get_crypto_tokens (struct dds_security_cryptography_impl ddsrt_circlist_init (tokens); ddsrt_mutex_lock (&impl->token_data_lock); + if (ddsrt_circlist_isempty (&impl->encode_decode_log)) + { + ddsrt_mutex_unlock (&impl->token_data_lock); + return tokens; + } + struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->token_data_list), *elem = elem0; while (elem != NULL) { @@ -231,6 +239,11 @@ struct crypto_token_data * find_crypto_token (struct dds_security_cryptography_i { assert (data_len <= CRYPTO_TOKEN_SIZE); ddsrt_mutex_lock (&impl->token_data_lock); + if (ddsrt_circlist_isempty (&impl->encode_decode_log)) + { + ddsrt_mutex_unlock (&impl->token_data_lock); + return NULL; + } struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->token_data_list), *elem = elem0; while (elem != NULL) { @@ -256,6 +269,60 @@ struct crypto_token_data * find_crypto_token (struct dds_security_cryptography_i return NULL; } +static void log_encode_decode (struct dds_security_cryptography_impl * impl, enum crypto_encode_decode_fn function, DDS_Security_long_long handle) +{ + ddsrt_mutex_lock (&impl->encode_decode_log_lock); + if (!ddsrt_circlist_isempty (&impl->encode_decode_log)) + { + struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->encode_decode_log), *elem = elem0; + while (elem != NULL) + { + struct crypto_encode_decode_data *data = DDSRT_FROM_CIRCLIST (struct crypto_encode_decode_data, e, elem); + if (data->function == function && data->handle == handle) + { + data->count++; + ddsrt_mutex_unlock (&impl->encode_decode_log_lock); + return; + } + elem = elem->next; + if (elem == elem0) + break; + } + } + /* add new entry */ + struct crypto_encode_decode_data *new_data = ddsrt_malloc (sizeof (*new_data)); + new_data->function = function; + new_data->handle = handle; + new_data->count = 1; + ddsrt_circlist_append(&impl->encode_decode_log, &new_data->e); + ddsrt_mutex_unlock (&impl->encode_decode_log_lock); +} + +struct crypto_encode_decode_data * get_encode_decode_log (struct dds_security_cryptography_impl * impl, enum crypto_encode_decode_fn function, DDS_Security_long_long handle) +{ + ddsrt_mutex_lock (&impl->encode_decode_log_lock); + if (!ddsrt_circlist_isempty (&impl->encode_decode_log)) + { + struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->encode_decode_log), *elem = elem0; + while (elem != NULL) + { + struct crypto_encode_decode_data *data = DDSRT_FROM_CIRCLIST (struct crypto_encode_decode_data, e, elem); + if (data->function == function && data->handle == handle) + { + struct crypto_encode_decode_data *result = ddsrt_malloc (sizeof (*result)); + memcpy (result, data, sizeof (*result)); + ddsrt_mutex_unlock (&impl->encode_decode_log_lock); + return result; + } + elem = elem->next; + if (elem == elem0) + break; + } + } + ddsrt_mutex_unlock (&impl->encode_decode_log_lock); + return NULL; +} + static unsigned char * find_buffer_match(const unsigned char *input, size_t input_len, const unsigned char *match, size_t match_len) { if (match_len <= input_len && match_len > 0 && input_len > 0) @@ -705,6 +772,8 @@ static DDS_Security_boolean encode_datawriter_submessage( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + log_encode_decode (impl->parent, ENCODE_DATAWRITER_SUBMESSAGE, sending_datawriter_crypto); + /* fall-through */ case PLUGIN_MODE_TOKEN_LOG: if (!impl->instance->encode_datawriter_submessage (impl->instance, encoded_rtps_submessage, plain_rtps_submessage, check_handle (sending_datawriter_crypto), receiving_datareader_crypto_list, receiving_datareader_crypto_list_index, ex)) @@ -753,6 +822,8 @@ static DDS_Security_boolean encode_datareader_submessage( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + log_encode_decode (impl->parent, ENCODE_DATAREADER_SUBMESSAGE, sending_datareader_crypto); + /* fall-through */ case PLUGIN_MODE_TOKEN_LOG: if (!impl->instance->encode_datareader_submessage (impl->instance, encoded_rtps_submessage, plain_rtps_submessage, check_handle (sending_datareader_crypto), receiving_datawriter_crypto_list, ex)) @@ -850,6 +921,8 @@ static DDS_Security_boolean decode_datawriter_submessage( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + log_encode_decode (impl->parent, DECODE_DATAWRITER_SUBMESSAGE, receiving_datareader_crypto); + /* fall-through */ case PLUGIN_MODE_TOKEN_LOG: return impl->instance->decode_datawriter_submessage (impl->instance, plain_rtps_submessage, encoded_rtps_submessage, check_handle (receiving_datareader_crypto), check_handle (sending_datawriter_crypto), ex); @@ -870,6 +943,8 @@ static DDS_Security_boolean decode_datareader_submessage( switch (impl->parent->mode) { case PLUGIN_MODE_WRAPPED: + log_encode_decode (impl->parent, DECODE_DATAREADER_SUBMESSAGE, receiving_datawriter_crypto); + /* fall-through */ case PLUGIN_MODE_TOKEN_LOG: return impl->instance->decode_datareader_submessage (impl->instance, plain_rtps_submessage, encoded_rtps_submessage, check_handle (receiving_datawriter_crypto), check_handle (sending_datareader_crypto), ex); @@ -1006,6 +1081,8 @@ int init_test_cryptography_wrapped(const char *argument, void **context, struct if (!impl) return DDS_SECURITY_FAILED; impl->mode = PLUGIN_MODE_WRAPPED; + ddsrt_mutex_init (&impl->encode_decode_log_lock); + ddsrt_circlist_init (&impl->encode_decode_log); *context = impl; return DDS_SECURITY_SUCCESS; } @@ -1014,6 +1091,15 @@ int finalize_test_cryptography_wrapped(void *context) { struct dds_security_cryptography_impl* impl = (struct dds_security_cryptography_impl*) context; assert(impl->mode == PLUGIN_MODE_WRAPPED); + ddsrt_mutex_lock (&impl->encode_decode_log_lock); + while (!ddsrt_circlist_isempty (&impl->encode_decode_log)) + { + struct ddsrt_circlist_elem *list_elem = ddsrt_circlist_oldest (&impl->encode_decode_log); + ddsrt_circlist_remove (&impl->encode_decode_log, list_elem); + ddsrt_free (list_elem); + } + ddsrt_mutex_unlock (&impl->encode_decode_log_lock); + ddsrt_mutex_destroy (&impl->encode_decode_log_lock); return finalize_test_cryptography_common(impl, true); } @@ -1043,12 +1129,12 @@ int32_t finalize_test_cryptography_store_tokens(void *context) while (!ddsrt_circlist_isempty (&impl->token_data_list)) { struct ddsrt_circlist_elem *list_elem = ddsrt_circlist_oldest (&impl->token_data_list); - struct crypto_token_data *token_data = DDSRT_FROM_CIRCLIST (struct crypto_token_data, e, list_elem); ddsrt_circlist_remove (&impl->token_data_list, list_elem); - ddsrt_free (token_data); + ddsrt_free (list_elem); } ddsrt_mutex_unlock (&impl->token_data_lock); ddsrt_mutex_destroy (&impl->token_data_lock); + /* don't detroy g_print_token_lock as this will result in multiple calls to mutex_destroy for this lock in case of multiple domains */ diff --git a/src/security/core/tests/common/cryptography_wrapper.h b/src/security/core/tests/common/cryptography_wrapper.h index b9384c9..d802247 100644 --- a/src/security/core/tests/common/cryptography_wrapper.h +++ b/src/security/core/tests/common/cryptography_wrapper.h @@ -43,6 +43,20 @@ struct crypto_token_data { size_t data_len[CRYPTO_TOKEN_MAXLEN]; }; +enum crypto_encode_decode_fn { + ENCODE_DATAWRITER_SUBMESSAGE, + ENCODE_DATAREADER_SUBMESSAGE, + DECODE_DATAWRITER_SUBMESSAGE, + DECODE_DATAREADER_SUBMESSAGE +}; + +struct crypto_encode_decode_data { + struct ddsrt_circlist_elem e; + enum crypto_encode_decode_fn function; + DDS_Security_long_long handle; + uint32_t count; +}; + SECURITY_EXPORT void set_protection_kinds( struct dds_security_cryptography_impl * impl, DDS_Security_ProtectionKind rtps_protection_kind, @@ -61,6 +75,7 @@ SECURITY_EXPORT void set_entity_data_secret(struct dds_security_cryptography_imp SECURITY_EXPORT const char *get_crypto_token_type_str (enum crypto_tokens_type type); SECURITY_EXPORT struct ddsrt_circlist * get_crypto_tokens (struct dds_security_cryptography_impl * impl); SECURITY_EXPORT struct crypto_token_data * find_crypto_token (struct dds_security_cryptography_impl * impl, enum crypto_tokens_type type, unsigned char * data, size_t data_len); +SECURITY_EXPORT struct crypto_encode_decode_data * get_encode_decode_log (struct dds_security_cryptography_impl * impl, enum crypto_encode_decode_fn function, DDS_Security_long_long handle); /* Init in all-ok mode: all functions return success without calling the actual plugin */ SECURITY_EXPORT int init_test_cryptography_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv); diff --git a/src/security/core/tests/common/security_config_test_utils.c b/src/security/core/tests/common/security_config_test_utils.c index d66ff2d..74f3e5e 100644 --- a/src/security/core/tests/common/security_config_test_utils.c +++ b/src/security/core/tests/common/security_config_test_utils.c @@ -29,6 +29,17 @@ #include "common/config_env.h" #include "security_config_test_utils.h" +static const char *topic_rule = + " " + " ${TOPIC_EXPRESSION}" + " ${ENABLE_DISC_PROTECTION}" + " ${ENABLE_LIVELINESS_PROTECTION}" + " ${ENABLE_READ_AC}" + " ${ENABLE_WRITE_AC}" + " ${METADATA_PROTECTION_KIND}" + " ${DATA_PROTECTION_KIND}" + " "; + static const char *governance_xml = "" "" @@ -46,15 +57,7 @@ static const char *governance_xml = " ${LIVELINESS_PROTECTION_KIND:-NONE}" " ${RTPS_PROTECTION_KIND:-NONE}" " " - " " - " *" - " ${ENABLE_DISC_PROTECTION:-false}" - " ${ENABLE_LIVELINESS_PROTECTION:-false}" - " ${ENABLE_READ_AC:-true}" - " ${ENABLE_WRITE_AC:-true}" - " ${METADATA_PROTECTION_KIND:-NONE}" - " ${DATA_PROTECTION_KIND:-NONE}" - " " + " ${TOPIC_RULES}" " " " " " " @@ -207,11 +210,48 @@ static char * prefix_data (char * config_signed, bool add_prefix) return config_signed; } -char * get_governance_config(struct kvp *config_vars, bool add_prefix) +static void print_config_vars(struct kvp *vars) { - char * config = ddsrt_expand_vars (governance_xml, &expand_lookup_vars, config_vars); + for (uint32_t i = 0; vars[i].key != NULL; i++) + printf("%s=%s; ", vars[i].key, vars[i].value); +} + +char * get_governance_topic_rule(const char * topic_expr, bool discovery_protection, bool liveliness_protection, + bool read_ac, bool write_ac, const char * metadata_protection_kind, const char * data_protection_kind) +{ + struct kvp vars[] = { + { "TOPIC_EXPRESSION", topic_expr != NULL ? topic_expr : "*", 1 }, + { "ENABLE_DISC_PROTECTION", discovery_protection ? "true" : "false", 1 }, + { "ENABLE_LIVELINESS_PROTECTION", liveliness_protection ? "true" : "false", 1 }, + { "ENABLE_READ_AC", read_ac ? "true" : "false", 1 }, + { "ENABLE_WRITE_AC", write_ac ? "true" : "false", 1 }, + { "METADATA_PROTECTION_KIND", metadata_protection_kind != NULL ? metadata_protection_kind : "NONE", 1 }, + { "DATA_PROTECTION_KIND", data_protection_kind != NULL ? data_protection_kind : "NONE", 1 }, + { NULL, NULL, 0 } + }; + return ddsrt_expand_vars (topic_rule, &expand_lookup_vars, vars); +} + +char * get_governance_config(bool allow_unauth_pp, bool enable_join_ac, const char * discovery_protection_kind, const char * liveliness_protection_kind, + const char * rtps_protection_kind, const char * topic_rules, bool add_prefix) +{ + struct kvp vars[] = { + { "ALLOW_UNAUTH_PP", allow_unauth_pp ? "true" : "false", 1 }, + { "ENABLE_JOIN_AC", enable_join_ac ? "true" : "false", 1 }, + { "DISCOVERY_PROTECTION_KIND", discovery_protection_kind != NULL ? discovery_protection_kind : "NONE", 1 }, + { "LIVELINESS_PROTECTION_KIND", liveliness_protection_kind != NULL ? liveliness_protection_kind : "NONE", 1 }, + { "RTPS_PROTECTION_KIND", rtps_protection_kind != NULL ? rtps_protection_kind : "NONE", 1 }, + { "TOPIC_RULES", topic_rules != NULL ? topic_rules : get_governance_topic_rule (NULL, false, false, false, false, NULL, NULL), 1 }, + { NULL, NULL, 0 } + }; + char * config = ddsrt_expand_vars (governance_xml, &expand_lookup_vars, vars); char * config_signed = get_signed_data (config); ddsrt_free (config); + + printf("Governance configuration: "); + print_config_vars(vars); + printf("\n"); + return prefix_data (config_signed, add_prefix); } diff --git a/src/security/core/tests/common/security_config_test_utils.h b/src/security/core/tests/common/security_config_test_utils.h index 3cf20de..770c979 100644 --- a/src/security/core/tests/common/security_config_test_utils.h +++ b/src/security/core/tests/common/security_config_test_utils.h @@ -25,7 +25,11 @@ const char * expand_lookup_vars (const char *name, void * data); const char * expand_lookup_vars_env (const char *name, void * data); int32_t expand_lookup_unmatched (const struct kvp * lookup_table); -char * get_governance_config (struct kvp *config_vars, bool add_prefix); +char * get_governance_topic_rule(const char * topic_expr, bool discovery_protection, bool liveliness_protection, + bool read_ac, bool write_ac, const char * metadata_protection_kind, const char * data_protection_kind); +char * get_governance_config(bool allow_unauth_pp, bool enable_join_ac, const char * discovery_protection_kind, const char * liveliness_protection_kind, + const char * rtps_protection_kind, const char * topic_rules, bool add_prefix); + char * get_permissions_topic(const char * name); char * get_permissions_grant(const char * name, const char * subject, const char * domain_id, dds_time_t not_before, dds_time_t not_after, const char * pub_topics, const char * sub_topics, const char * default_policy); diff --git a/src/security/core/tests/common/test_utils.c b/src/security/core/tests/common/test_utils.c index 3f94a85..99a4eaf 100644 --- a/src/security/core/tests/common/test_utils.c +++ b/src/security/core/tests/common/test_utils.c @@ -38,6 +38,12 @@ int numRemote = 0; struct Handshake handshakeList[MAX_HANDSHAKES]; int numHandshake = 0; +const char * g_pk_none = "NONE"; +const char * g_pk_sign = "SIGN"; +const char * g_pk_encrypt = "ENCRYPT"; +const char * g_pk_sign_oa = "SIGN_WITH_ORIGIN_AUTHENTICATION"; +const char * g_pk_encrypt_oa = "ENCRYPT_WITH_ORIGIN_AUTHENTICATION"; + static char * get_validation_result_str (DDS_Security_ValidationResult_t result) { switch (result) @@ -471,3 +477,29 @@ struct dds_security_cryptography_impl * get_crypto_context(dds_entity_t particip dds_entity_unlock (pp_entity); return context; } + +const char * pk_to_str(DDS_Security_ProtectionKind pk) +{ + switch (pk) + { + case DDS_SECURITY_PROTECTION_KIND_NONE: return g_pk_none; + case DDS_SECURITY_PROTECTION_KIND_SIGN: return g_pk_sign; + case DDS_SECURITY_PROTECTION_KIND_ENCRYPT: return g_pk_encrypt; + case DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION: return g_pk_sign_oa; + case DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION: return g_pk_encrypt_oa; + } + assert (false); + return NULL; +} + +const char * bpk_to_str(DDS_Security_BasicProtectionKind bpk) +{ + switch (bpk) + { + case DDS_SECURITY_BASICPROTECTION_KIND_NONE: return g_pk_none; + case DDS_SECURITY_BASICPROTECTION_KIND_SIGN: return g_pk_sign; + case DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT: return g_pk_encrypt; + } + assert (false); + return NULL; +} diff --git a/src/security/core/tests/common/test_utils.h b/src/security/core/tests/common/test_utils.h index 919affe..5fb9ccb 100644 --- a/src/security/core/tests/common/test_utils.h +++ b/src/security/core/tests/common/test_utils.h @@ -17,6 +17,15 @@ #include "dds/security/dds_security_api.h" +#define PK_N DDS_SECURITY_PROTECTION_KIND_NONE +#define PK_S DDS_SECURITY_PROTECTION_KIND_SIGN +#define PK_SOA DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION +#define PK_E DDS_SECURITY_PROTECTION_KIND_ENCRYPT +#define PK_EOA DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION +#define BPK_N DDS_SECURITY_BASICPROTECTION_KIND_NONE +#define BPK_S DDS_SECURITY_BASICPROTECTION_KIND_SIGN +#define BPK_E DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT + #define MAX_LOCAL_IDENTITIES 8 #define MAX_REMOTE_IDENTITIES 8 #define MAX_HANDSHAKES 32 @@ -70,5 +79,7 @@ void rd_wr_init_fail( bool exp_subtp_fail, bool exp_rd_fail); void write_read_for(dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_duration_t dur, bool exp_write_fail, bool exp_read_fail); struct dds_security_cryptography_impl * get_crypto_context(dds_entity_t participant); +const char * pk_to_str(DDS_Security_ProtectionKind pk); +const char * bpk_to_str(DDS_Security_BasicProtectionKind bpk); #endif /* SECURITY_CORE_TEST_UTILS_H_ */ diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index 186944c..fb7386f 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -37,15 +37,6 @@ #include "SecurityCoreTests.h" -#define PK_N DDS_SECURITY_PROTECTION_KIND_NONE -#define PK_S DDS_SECURITY_PROTECTION_KIND_SIGN -#define PK_SOA DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION -#define PK_E DDS_SECURITY_PROTECTION_KIND_ENCRYPT -#define PK_EOA DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION -#define BPK_N DDS_SECURITY_BASICPROTECTION_KIND_NONE -#define BPK_S DDS_SECURITY_BASICPROTECTION_KIND_SIGN -#define BPK_E DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT - static const char *config = "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" "" @@ -80,16 +71,6 @@ static const char *config = #define MAX_DOMAINS 10 #define MAX_PARTICIPANTS 10 -const char * g_pk_none = "NONE"; -const char * g_pk_sign = "SIGN"; -const char * g_pk_encrypt = "ENCRYPT"; -const char * g_pk_sign_oa = "SIGN_WITH_ORIGIN_AUTHENTICATION"; -const char * g_pk_encrypt_oa = "ENCRYPT_WITH_ORIGIN_AUTHENTICATION"; - -const char * g_pp_secret = "ppsecret"; -const char * g_groupdata_secret = "groupsecret"; -const char * g_ep_secret = "epsecret"; - uint32_t g_topic_nr = 0; static dds_entity_t g_pub_domains[MAX_DOMAINS]; @@ -116,37 +97,9 @@ typedef void (*set_crypto_params_fn)(struct dds_security_cryptography_impl *, co typedef dds_entity_t (*pubsub_create_fn)(dds_entity_t, const dds_qos_t *qos, const dds_listener_t *listener); typedef dds_entity_t (*ep_create_fn)(dds_entity_t, dds_entity_t, const dds_qos_t *qos, const dds_listener_t *listener); -static const char * pk_to_str(DDS_Security_ProtectionKind pk) -{ - switch (pk) - { - case DDS_SECURITY_PROTECTION_KIND_NONE: return g_pk_none; - case DDS_SECURITY_PROTECTION_KIND_SIGN: return g_pk_sign; - case DDS_SECURITY_PROTECTION_KIND_ENCRYPT: return g_pk_encrypt; - case DDS_SECURITY_PROTECTION_KIND_SIGN_WITH_ORIGIN_AUTHENTICATION: return g_pk_sign_oa; - case DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION: return g_pk_encrypt_oa; - } - assert (false); - return NULL; -} - -static const char * bpk_to_str(DDS_Security_BasicProtectionKind bpk) -{ - switch (bpk) - { - case DDS_SECURITY_BASICPROTECTION_KIND_NONE: return g_pk_none; - case DDS_SECURITY_BASICPROTECTION_KIND_SIGN: return g_pk_sign; - case DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT: return g_pk_encrypt; - } - assert (false); - return NULL; -} - -static void print_config_vars(struct kvp *vars) -{ - for (uint32_t i = 0; vars[i].key != NULL; i++) - printf("%s=%s; ", vars[i].key, vars[i].value); -} +const char * g_pp_secret = "ppsecret"; +const char * g_groupdata_secret = "groupsecret"; +const char * g_ep_secret = "epsecret"; static dds_qos_t *get_qos() { @@ -201,20 +154,9 @@ static void test_init(const struct domain_sec_config * domain_config, size_t n_s assert (n_pub_domains < MAX_DOMAINS); assert (n_pub_participants < MAX_PARTICIPANTS); - struct kvp governance_vars[] = { - { "DISCOVERY_PROTECTION_KIND", pk_to_str (domain_config->discovery_pk), 1 }, - { "LIVELINESS_PROTECTION_KIND", pk_to_str (domain_config->liveliness_pk), 1 }, - { "RTPS_PROTECTION_KIND", pk_to_str (domain_config->rtps_pk), 1 }, - { "METADATA_PROTECTION_KIND", pk_to_str (domain_config->metadata_pk), 1 }, - { "DATA_PROTECTION_KIND", bpk_to_str (domain_config->payload_pk), 1 }, - { NULL, NULL, 0 } - }; - - printf("Governance configuration: "); - print_config_vars(governance_vars); - printf("\n"); - - char * gov_config_signed = get_governance_config (governance_vars, false); + char * gov_topic_rule = get_governance_topic_rule ("*", false, false, true, true, pk_to_str (domain_config->metadata_pk), bpk_to_str (domain_config->payload_pk)); + char * gov_config_signed = get_governance_config (false, false, pk_to_str (domain_config->discovery_pk), pk_to_str (domain_config->liveliness_pk), + pk_to_str (domain_config->rtps_pk), gov_topic_rule, false); struct kvp config_vars[] = { { "GOVERNANCE_DATA", gov_config_signed, 1 }, @@ -232,6 +174,7 @@ static void test_init(const struct domain_sec_config * domain_config, size_t n_s dds_free (conf_sub); dds_free (gov_config_signed); + dds_free (gov_topic_rule); } static void test_fini(size_t n_sub_domain, size_t n_pub_domain) From 231d8200520437f39d31b6b941aea59029d0d8ea Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 28 Apr 2020 13:24:10 +0200 Subject: [PATCH 183/238] Add security encoding-mismatch test A test that checks that the security handshake fails in case of non-matching encoding settings in the governance xml. All combinations of values for rtps, discovery and liveliness protection are checked. For meta-data and payload encoding, this test checks that a reader and writer do not connect in case of non-matching values. Signed-off-by: Dennis Potman --- src/security/core/tests/access_control.c | 166 ++++++++++++------ src/security/core/tests/authentication.c | 55 +----- src/security/core/tests/common/test_utils.c | 85 ++++++--- src/security/core/tests/common/test_utils.h | 27 +-- src/security/core/tests/handshake.c | 22 ++- .../core/tests/secure_communication.c | 4 +- 6 files changed, 217 insertions(+), 142 deletions(-) diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index 23c32f3..3a388c1 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -113,10 +113,15 @@ static void access_control_init( } } -static void access_control_fini(size_t n) +static void access_control_fini(size_t n, void * res[], size_t nres) { for (size_t i = 0; i < n; i++) CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain[i]), DDS_RETCODE_OK); + if (res != NULL) + { + for (size_t i = 0; i < nres; i++) + ddsrt_free (res[i]); + } } static DDS_Security_DatawriterCryptoHandle get_builtin_writer_crypto_handle(dds_entity_t participant, unsigned entityid) @@ -203,7 +208,7 @@ CU_Theory((const char * test_descr, const char * gov, const char * perm, const c (bool []) { has_gov, has_gov }, (const char *[]) { gov, gov }, (bool []) { has_perm, has_perm }, (const char *[]) { perm, perm }, (bool []) { has_ca, has_ca }, (const char *[]) { ca, ca }); - access_control_fini (2); + access_control_fini (2, NULL, 0); } #define S(n) (n) @@ -276,21 +281,11 @@ CU_Theory( dds_entity_t pub, sub; dds_entity_t topic0, topic1; rd_wr_init (g_participant[0], &pub, &topic0, &wr, g_participant[1], &sub, &topic1, &rd, topic_name); - sync_writer_to_readers(g_participant[0], wr, 1); + sync_writer_to_readers(g_participant[0], wr, 1, DDS_SECS(2)); write_read_for (wr, g_participant[1], rd, DDS_MSECS (write_read_dur), false, exp_read_fail); } - access_control_fini (2); - - ddsrt_free (perm_topic); - ddsrt_free (grants[0]); - ddsrt_free (grants[1]); - ddsrt_free (perm_config); - ddsrt_free (ca); - ddsrt_free (id1_subj); - ddsrt_free (id2_subj); - ddsrt_free (id1); - ddsrt_free (id2); + access_control_fini (2, (void * []) { perm_topic, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 9); } @@ -369,7 +364,7 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) wr[i] = dds_create_writer (pub, pub_tp, qos, NULL); CU_ASSERT_FATAL (wr[i] > 0); dds_set_status_mask (wr[i], DDS_PUBLICATION_MATCHED_STATUS); - sync_writer_to_readers (g_participant[i + N_RD], wr[i], N_RD); + sync_writer_to_readers (g_participant[i + N_RD], wr[i], N_RD, DDS_SECS(2)); } dds_delete_qos (qos); @@ -423,7 +418,7 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) CU_ASSERT (n_invalid <= run); } - access_control_fini (N_NODES); + access_control_fini (N_NODES, NULL, 0); for (int i = 0; i < N_NODES; i++) { @@ -497,7 +492,7 @@ CU_Theory( g_participant[1], &rsub, &rtopic[0], &rrd, topic_name, exp_local_topic_fail, exp_wr_fail, exp_remote_topic_fail, false); if (!exp_local_topic_fail && !exp_remote_topic_fail && !exp_wr_fail) - sync_writer_to_readers (g_participant[0], lwr, exp_wr_rd_sync_fail ? 0 : 1); + sync_writer_to_readers (g_participant[0], lwr, exp_wr_rd_sync_fail ? 0 : 1, DDS_SECS(2)); // Local reader, remote writer create_topic_name (AC_WRAPPER_TOPIC_PREFIX, g_topic_nr++, topic_name, sizeof (topic_name)); @@ -506,10 +501,10 @@ CU_Theory( g_participant[0], &lsub, <opic[1], &lrd, topic_name, exp_remote_topic_fail, false, exp_local_topic_fail, exp_rd_fail); if (!exp_local_topic_fail && !exp_remote_topic_fail && !exp_rd_fail) - sync_reader_to_writers (g_participant[0], lrd, exp_rd_wr_sync_fail ? 0 : 1); + sync_reader_to_writers (g_participant[0], lrd, exp_rd_wr_sync_fail ? 0 : 1, DDS_SECS(2)); } - access_control_fini (2); + access_control_fini (2, NULL, 0); } #define na false @@ -568,26 +563,12 @@ CU_Theory( (bool []) { true, true }, (const char *[]) { def_perm_ca, def_perm_ca }); if (!exp_pp1_fail && !exp_pp2_fail) - validate_handshake (DDS_DOMAINID, exp_hs_fail, NULL, NULL, NULL); + validate_handshake (DDS_DOMAINID, exp_hs_fail, NULL, NULL, NULL, DDS_SECS(2)); - access_control_fini (2); - - ddsrt_free (gov_config_pp1); - ddsrt_free (gov_config_pp2); - ddsrt_free (gov_topic_rule); - ddsrt_free (perm_topic); - ddsrt_free (grants[0]); - ddsrt_free (grants[1]); - ddsrt_free (perm_config); - ddsrt_free (ca); - ddsrt_free (id1_subj); - ddsrt_free (id2_subj); - ddsrt_free (id1); - ddsrt_free (id2); + access_control_fini (2, (void * []) { gov_config_pp1, gov_config_pp2, gov_topic_rule, perm_topic, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 12); } #define na false -#define E ENCRYPT CU_TheoryDataPoints(ddssec_access_control, discovery_protection) = { CU_DataPoints(const char *, /* */"disabled", @@ -647,11 +628,11 @@ CU_Theory( (bool []) { true, true }, (const char *[]) { gov_config1, gov_config2 }, (bool []) { true, true }, (const char *[]) { perm_config, perm_config }, (bool []) { true, true }, (const char *[]) { def_perm_ca, def_perm_ca }); - validate_handshake (DDS_DOMAINID, false, NULL, NULL, NULL); + validate_handshake (DDS_DOMAINID, false, NULL, NULL, NULL, DDS_SECS(2)); dds_entity_t pub, sub, pub_tp, sub_tp, wr, rd; rd_wr_init (g_participant[0], &pub, &pub_tp, &wr, g_participant[1], &sub, &sub_tp, &rd, topic_name); - sync_writer_to_readers (g_participant[0], wr, exp_rd_wr_match_fail ? 0 : 1); + sync_writer_to_readers (g_participant[0], wr, exp_rd_wr_match_fail ? 0 : 1, DDS_SECS(2)); if (!exp_rd_wr_match_fail) write_read_for (wr, g_participant[1], rd, DDS_MSECS (100), false, false); @@ -671,19 +652,100 @@ CU_Theory( ddsrt_free (log); } - access_control_fini (2); - - ddsrt_free (gov_config1); - ddsrt_free (gov_config2); - ddsrt_free (gov_topic_rule1); - ddsrt_free (gov_topic_rule2); - ddsrt_free (perm_topic); - ddsrt_free (grants[0]); - ddsrt_free (grants[1]); - ddsrt_free (perm_config); - ddsrt_free (ca); - ddsrt_free (id1_subj); - ddsrt_free (id2_subj); - ddsrt_free (id1); - ddsrt_free (id2); + access_control_fini (2, (void * []) { gov_config1, gov_config2, gov_topic_rule1, gov_topic_rule2, perm_topic, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 13); +} + +static void test_encoding_mismatch( + bool exp_hs_fail, bool exp_rd_wr_fail, + DDS_Security_ProtectionKind rtps_pk1, DDS_Security_ProtectionKind rtps_pk2, + DDS_Security_ProtectionKind discovery_pk1, DDS_Security_ProtectionKind discovery_pk2, + DDS_Security_ProtectionKind liveliness_pk1, DDS_Security_ProtectionKind liveliness_pk2, + DDS_Security_ProtectionKind metadata_pk1, DDS_Security_ProtectionKind metadata_pk2, + DDS_Security_BasicProtectionKind payload_pk1, DDS_Security_BasicProtectionKind payload_pk2) +{ + char topic_name[100]; + create_topic_name ("ddssec_access_control_", g_topic_nr++, topic_name, sizeof (topic_name)); + + /* create ca and id1/id2 certs that will not expire during this test */ + char *ca, *id1, *id2, *id1_subj, *id2_subj; + ca = generate_ca ("ca1", TEST_IDENTITY_CA1_PRIVATE_KEY, 0, 3600); + id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id1_subj); + id2 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id2", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id2_subj); + + /* localtime will be converted to gmtime in get_permissions_grant */ + dds_time_t now = dds_time (); + char * perm_topic = get_permissions_topic (topic_name); + char * grants[] = { + get_permissions_grant ("id1", id1_subj, NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL), + get_permissions_grant ("id2", id2_subj, NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL) }; + char * perm_config = get_permissions_config (grants, 2, true); + + char * gov_topic_rule1 = get_governance_topic_rule (topic_name, true, true, true, true, pk_to_str (metadata_pk1), bpk_to_str (payload_pk1)); + char * gov_topic_rule2 = get_governance_topic_rule (topic_name, true, true, true, true, pk_to_str (metadata_pk2), bpk_to_str (payload_pk2)); + char * gov_config1 = get_governance_config (false, true, pk_to_str (discovery_pk1), pk_to_str (liveliness_pk1), pk_to_str (rtps_pk1), gov_topic_rule1, true); + char * gov_config2 = get_governance_config (false, true, pk_to_str (discovery_pk2), pk_to_str (liveliness_pk2), pk_to_str (rtps_pk2), gov_topic_rule2, true); + const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); + + access_control_init ( + 2, + (const char *[]) { id1, id2 }, + (const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY }, + (const char *[]) { ca, ca }, + (bool []) { false, false }, NULL, NULL, + (bool []) { true, true }, (const char *[]) { gov_config1, gov_config2 }, + (bool []) { true, true }, (const char *[]) { perm_config, perm_config }, + (bool []) { true, true }, (const char *[]) { def_perm_ca, def_perm_ca }); + + struct Handshake *hs_list; + int nhs; + validate_handshake (DDS_DOMAINID, false, NULL, &hs_list, &nhs, DDS_MSECS(500)); + CU_ASSERT_EQUAL_FATAL (exp_hs_fail, nhs < 1); + handshake_list_fini (hs_list, nhs); + + if (!exp_hs_fail) + { + dds_entity_t pub, sub, pub_tp, sub_tp, wr, rd; + rd_wr_init (g_participant[0], &pub, &pub_tp, &wr, g_participant[1], &sub, &sub_tp, &rd, topic_name); + sync_writer_to_readers (g_participant[0], wr, exp_rd_wr_fail ? 0 : 1, DDS_SECS(1)); + } + + access_control_fini (2, (void * []) { gov_config1, gov_config2, gov_topic_rule1, gov_topic_rule2, perm_topic, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 13); +} + +static DDS_Security_ProtectionKind pk[] = { PK_N, PK_S, PK_E, PK_SOA, PK_EOA }; +static DDS_Security_BasicProtectionKind bpk[] = { BPK_N, BPK_S, BPK_E }; + +CU_Test(ddssec_access_control, encoding_mismatch_rtps, .timeout=30) +{ + for (size_t pk1 = 0; pk1 < sizeof (pk) / sizeof (pk[0]); pk1++) + for (size_t pk2 = pk1 + 1; pk2 < sizeof (pk) / sizeof (pk[0]); pk2++) + test_encoding_mismatch (pk1 != pk2, false, pk[pk1], pk[pk2], PK_N, PK_N, PK_N, PK_N, PK_N, PK_N, BPK_N, BPK_N); +} + +CU_Test(ddssec_access_control, encoding_mismatch_discovery, .timeout=30) +{ + for (size_t pk1 = 0; pk1 < sizeof (pk) / sizeof (pk[0]); pk1++) + for (size_t pk2 = pk1 + 1; pk2 < sizeof (pk) / sizeof (pk[0]); pk2++) + test_encoding_mismatch (pk1 != pk2, false, PK_N, PK_N, pk[pk1], pk[pk2], PK_N, PK_N, PK_N, PK_N, BPK_N, BPK_N); +} + +CU_Test(ddssec_access_control, encoding_mismatch_liveliness, .timeout=30) +{ + for (size_t pk1 = 0; pk1 < sizeof (pk) / sizeof (pk[0]); pk1++) + for (size_t pk2 = pk1 + 1; pk2 < sizeof (pk) / sizeof (pk[0]); pk2++) + test_encoding_mismatch (pk1 != pk2, false, PK_N, PK_N, PK_N, PK_N, pk[pk1], pk[pk2], PK_N, PK_N, BPK_N, BPK_N); +} + +CU_Test(ddssec_access_control, encoding_mismatch_metadata, .timeout=30) +{ + for (size_t pk1 = 0; pk1 < sizeof (pk) / sizeof (pk[0]); pk1++) + for (size_t pk2 = pk1 + 1; pk2 < sizeof (pk) / sizeof (pk[0]); pk2++) + test_encoding_mismatch (false, pk1 != pk2, PK_N, PK_N, PK_N, PK_N, PK_N, PK_N, pk[pk1], pk[pk2], BPK_N, BPK_N); +} + +CU_Test(ddssec_access_control, encoding_mismatch_payload, .timeout=30) +{ + for (size_t pk1 = 0; pk1 < sizeof (bpk) / sizeof (bpk[0]); pk1++) + for (size_t pk2 = pk1 + 1; pk2 < sizeof (bpk) / sizeof (bpk[0]); pk2++) + test_encoding_mismatch (false, pk1 != pk2, PK_N, PK_N, PK_N, PK_N, PK_N, PK_N, PK_N, PK_N, bpk[pk1], bpk[pk2]); } diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index 0af4138..bbfb69b 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -175,43 +175,6 @@ CU_TheoryDataPoints(ddssec_authentication, id_ca_certs) = { #undef FM_CA #undef FM_INVK -static void validate_hs(struct Handshake *hs, bool exp_fail_hs_req, const char * fail_hs_req_msg, bool exp_fail_hs_reply, const char * fail_hs_reply_msg) -{ - DDS_Security_ValidationResult_t exp_result = hs->node_type == HSN_REQUESTER ? DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE : DDS_SECURITY_VALIDATION_OK; - if (hs->node_type == HSN_REQUESTER) - { - CU_ASSERT_EQUAL_FATAL (hs->finalResult, exp_fail_hs_req ? DDS_SECURITY_VALIDATION_FAILED : exp_result); - if (exp_fail_hs_req) - { - if (fail_hs_req_msg == NULL) - { - CU_ASSERT_EQUAL_FATAL (hs->err_msg, NULL); - } - else - { - CU_ASSERT_FATAL (hs->err_msg != NULL); - CU_ASSERT_FATAL (strstr(hs->err_msg, fail_hs_req_msg) != NULL); - } - } - } - else if (hs->node_type == HSN_REPLIER) - { - CU_ASSERT_EQUAL_FATAL (hs->finalResult, exp_fail_hs_reply ? DDS_SECURITY_VALIDATION_FAILED : exp_result); - if (exp_fail_hs_reply) - { - if (fail_hs_reply_msg == NULL) - { - CU_ASSERT_EQUAL_FATAL (hs->err_msg, NULL); - } - else - { - CU_ASSERT_FATAL (hs->err_msg != NULL); - CU_ASSERT_FATAL (strstr(hs->err_msg, fail_hs_reply_msg) != NULL); - } - } - } -} - CU_Theory((const char * test_descr, const char * id2, const char *key2, const char *ca2, bool exp_fail_pp1, bool exp_fail_pp2, bool exp_fail_local, const char * fail_local_msg, @@ -225,15 +188,15 @@ CU_Theory((const char * test_descr, const char * id2, const char *key2, const ch authentication_init (ID1, ID1K, CA1, id2, key2, ca2, NULL, NULL, exp_fail_pp1, exp_fail_pp2); // Domain 1 - validate_handshake (DDS_DOMAINID1, false, NULL, &hs_list, &nhs); + validate_handshake (DDS_DOMAINID1, false, NULL, &hs_list, &nhs, DDS_SECS(2)); for (int n = 0; n < nhs; n++) - validate_hs (&hs_list[n], exp_fail_hs_req, fail_hs_req_msg, exp_fail_hs_reply, fail_hs_reply_msg); + validate_handshake_result (&hs_list[n], exp_fail_hs_req, fail_hs_req_msg, exp_fail_hs_reply, fail_hs_reply_msg); handshake_list_fini (hs_list, nhs); // Domain 2 - validate_handshake (DDS_DOMAINID2, exp_fail_local, fail_local_msg, &hs_list, &nhs); + validate_handshake (DDS_DOMAINID2, exp_fail_local, fail_local_msg, &hs_list, &nhs, DDS_SECS(2)); for (int n = 0; n < nhs; n++) - validate_hs (&hs_list[n], exp_fail_hs_req, fail_hs_req_msg, exp_fail_hs_reply, fail_hs_reply_msg); + validate_handshake_result (&hs_list[n], exp_fail_hs_req, fail_hs_req_msg, exp_fail_hs_reply, fail_hs_reply_msg); handshake_list_fini (hs_list, nhs); authentication_fini (!exp_fail_pp1, !exp_fail_pp2); @@ -249,8 +212,8 @@ CU_Theory((const char * ca_dir, bool exp_fail), ddssec_authentication, trusted_c authentication_init (ID1, ID1K, CA1, ID1, ID1K, CA1, ca_dir, NULL, exp_fail, exp_fail); if (!exp_fail) { - validate_handshake_nofail (DDS_DOMAINID1); - validate_handshake_nofail (DDS_DOMAINID2); + validate_handshake_nofail (DDS_DOMAINID1, DDS_SECS (2)); + validate_handshake_nofail (DDS_DOMAINID2, DDS_SECS (2)); } authentication_fini (!exp_fail, !exp_fail); } @@ -306,12 +269,12 @@ CU_Theory( get_permissions_grant ("id2", id2_subj, NULL, now - DDS_SECS(D(1)), now + DDS_SECS(D(1)), NULL, NULL, NULL) }; char * perm_config = get_permissions_config (grants, 2, true); authentication_init (id1, ID1K, ca, id2, ID1K, ca, NULL, perm_config, id1_local_fail, id2_local_fail); - validate_handshake (DDS_DOMAINID1, id1_local_fail, NULL, NULL, NULL); - validate_handshake (DDS_DOMAINID2, id2_local_fail, NULL, NULL, NULL); + validate_handshake (DDS_DOMAINID1, id1_local_fail, NULL, NULL, NULL, DDS_SECS(2)); + validate_handshake (DDS_DOMAINID2, id2_local_fail, NULL, NULL, NULL, DDS_SECS(2)); if (write_read_dur > 0) { rd_wr_init (g_participant1, &g_pub, &g_pub_tp, &g_wr, g_participant2, &g_sub, &g_sub_tp, &g_rd, topic_name); - sync_writer_to_readers(g_participant1, g_wr, 1); + sync_writer_to_readers(g_participant1, g_wr, 1, DDS_SECS(2)); write_read_for (g_wr, g_participant2, g_rd, DDS_MSECS (write_read_dur), false, exp_read_fail); } authentication_fini (!id1_local_fail, !id2_local_fail); diff --git a/src/security/core/tests/common/test_utils.c b/src/security/core/tests/common/test_utils.c index 99a4eaf..89d22f3 100644 --- a/src/security/core/tests/common/test_utils.c +++ b/src/security/core/tests/common/test_utils.c @@ -27,8 +27,6 @@ #include "test_utils.h" #include "SecurityCoreTests.h" -#define HS_TIMEOUT DDS_SECS(2) - struct Identity localIdentityList[MAX_LOCAL_IDENTITIES]; int numLocal = 0; @@ -151,10 +149,10 @@ static int find_handshake (DDS_Security_HandshakeHandle handle) return -1; } -static void handle_process_message (dds_domainid_t domain_id, DDS_Security_IdentityHandle handshake) +static void handle_process_message (dds_domainid_t domain_id, DDS_Security_IdentityHandle handshake, dds_duration_t timeout) { struct message *msg; - if ((msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_PROCESS_HANDSHAKE, 0, 0, handshake, HS_TIMEOUT))) + if ((msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_PROCESS_HANDSHAKE, 0, 0, handshake, timeout))) { int idx; if ((idx = find_handshake (msg->hsHandle)) >= 0) @@ -167,42 +165,42 @@ static void handle_process_message (dds_domainid_t domain_id, DDS_Security_Ident } } -static void handle_begin_handshake_request (dds_domainid_t domain_id, struct Handshake *hs, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid) +static void handle_begin_handshake_request (dds_domainid_t domain_id, struct Handshake *hs, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid, dds_duration_t timeout) { struct message *msg; print_test_msg ("handle begin handshake request %"PRId64"<->%"PRId64"\n", lid, rid); - if ((msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REQUEST, lid, rid, 0, HS_TIMEOUT))) + if ((msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REQUEST, lid, rid, 0, timeout))) { hs->handle = msg->hsHandle; hs->handshakeResult = msg->result; if (msg->result != DDS_SECURITY_VALIDATION_FAILED) - handle_process_message (domain_id, msg->hsHandle); + handle_process_message (domain_id, msg->hsHandle, timeout); else hs->err_msg = ddsrt_strdup (msg->err_msg); test_authentication_plugin_release_msg (msg); } } -static void handle_begin_handshake_reply (dds_domainid_t domain_id, struct Handshake *hs, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid) +static void handle_begin_handshake_reply (dds_domainid_t domain_id, struct Handshake *hs, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid, dds_duration_t timeout) { struct message *msg; print_test_msg ("handle begin handshake reply %"PRId64"<->%"PRId64"\n", lid, rid); - if ((msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REPLY, lid, rid, 0, HS_TIMEOUT))) + if ((msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REPLY, lid, rid, 0, timeout))) { hs->handle = msg->hsHandle; hs->handshakeResult = msg->result; if (msg->result != DDS_SECURITY_VALIDATION_FAILED) - handle_process_message (domain_id, msg->hsHandle); + handle_process_message (domain_id, msg->hsHandle, timeout); else hs->err_msg = ddsrt_strdup (msg->err_msg); test_authentication_plugin_release_msg (msg); } } -static void handle_validate_remote_identity (dds_domainid_t domain_id, DDS_Security_IdentityHandle lid, int count) +static void handle_validate_remote_identity (dds_domainid_t domain_id, DDS_Security_IdentityHandle lid, int count, dds_duration_t timeout) { struct message *msg; - while (count-- > 0 && (msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_VALIDATE_REMOTE_IDENTITY, lid, 0, 0, HS_TIMEOUT))) + while (count-- > 0 && (msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_VALIDATE_REMOTE_IDENTITY, lid, 0, 0, timeout))) { struct Handshake *hs; add_remote_identity (msg->ridHandle, &msg->rguid); @@ -210,12 +208,12 @@ static void handle_validate_remote_identity (dds_domainid_t domain_id, DDS_Secur if (msg->result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_REQUEST) { hs->node_type = HSN_REQUESTER; - handle_begin_handshake_request (domain_id, hs, lid, msg->ridHandle); + handle_begin_handshake_request (domain_id, hs, lid, msg->ridHandle, timeout); } else if (msg->result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE) { hs->node_type = HSN_REPLIER; - handle_begin_handshake_reply (domain_id, hs, lid, msg->ridHandle); + handle_begin_handshake_reply (domain_id, hs, lid, msg->ridHandle, timeout); } else { @@ -225,9 +223,9 @@ static void handle_validate_remote_identity (dds_domainid_t domain_id, DDS_Secur } } -static void handle_validate_local_identity (dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg) +static void handle_validate_local_identity (dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg, dds_duration_t timeout) { - struct message *msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_VALIDATE_LOCAL_IDENTITY, 0, 0, 0, HS_TIMEOUT); + struct message *msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_VALIDATE_LOCAL_IDENTITY, 0, 0, 0, timeout); CU_ASSERT_FATAL (msg != NULL); CU_ASSERT_FATAL ((msg->result == DDS_SECURITY_VALIDATION_OK) != exp_localid_fail); if (exp_localid_fail && exp_localid_msg) @@ -240,7 +238,7 @@ static void handle_validate_local_identity (dds_domainid_t domain_id, bool exp_l test_authentication_plugin_release_msg (msg); } -void validate_handshake (dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg, struct Handshake *hs_list[], int *nhs) +void validate_handshake (dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg, struct Handshake *hs_list[], int *nhs, dds_duration_t timeout) { clear_stores (); @@ -249,10 +247,10 @@ void validate_handshake (dds_domainid_t domain_id, bool exp_localid_fail, const if (hs_list) *hs_list = NULL; - handle_validate_local_identity (domain_id, exp_localid_fail, exp_localid_msg); + handle_validate_local_identity (domain_id, exp_localid_fail, exp_localid_msg, timeout); if (!exp_localid_fail) { - handle_validate_remote_identity (domain_id, localIdentityList[0].handle, 1); + handle_validate_remote_identity (domain_id, localIdentityList[0].handle, 1, timeout); for (int n = 0; n < numHandshake; n++) { struct Handshake *hs = &handshakeList[n]; @@ -270,11 +268,11 @@ void validate_handshake (dds_domainid_t domain_id, bool exp_localid_fail, const print_test_msg ("finished validate handshake for domain %d\n\n", domain_id); } -void validate_handshake_nofail (dds_domainid_t domain_id) +void validate_handshake_nofail (dds_domainid_t domain_id, dds_duration_t timeout) { struct Handshake *hs_list; int nhs; - validate_handshake (domain_id, false, NULL, &hs_list, &nhs); + validate_handshake (domain_id, false, NULL, &hs_list, &nhs, timeout); for (int n = 0; n < nhs; n++) { struct Handshake hs = hs_list[n]; @@ -284,6 +282,43 @@ void validate_handshake_nofail (dds_domainid_t domain_id) handshake_list_fini (hs_list, nhs); } +void validate_handshake_result(struct Handshake *hs, bool exp_fail_hs_req, const char * fail_hs_req_msg, bool exp_fail_hs_reply, const char * fail_hs_reply_msg) +{ + DDS_Security_ValidationResult_t exp_result = hs->node_type == HSN_REQUESTER ? DDS_SECURITY_VALIDATION_OK_FINAL_MESSAGE : DDS_SECURITY_VALIDATION_OK; + if (hs->node_type == HSN_REQUESTER) + { + CU_ASSERT_EQUAL_FATAL (hs->finalResult, exp_fail_hs_req ? DDS_SECURITY_VALIDATION_FAILED : exp_result); + if (exp_fail_hs_req) + { + if (fail_hs_req_msg == NULL) + { + CU_ASSERT_EQUAL_FATAL (hs->err_msg, NULL); + } + else + { + CU_ASSERT_FATAL (hs->err_msg != NULL); + CU_ASSERT_FATAL (strstr(hs->err_msg, fail_hs_req_msg) != NULL); + } + } + } + else if (hs->node_type == HSN_REPLIER) + { + CU_ASSERT_EQUAL_FATAL (hs->finalResult, exp_fail_hs_reply ? DDS_SECURITY_VALIDATION_FAILED : exp_result); + if (exp_fail_hs_reply) + { + if (fail_hs_reply_msg == NULL) + { + CU_ASSERT_EQUAL_FATAL (hs->err_msg, NULL); + } + else + { + CU_ASSERT_FATAL (hs->err_msg != NULL); + CU_ASSERT_FATAL (strstr(hs->err_msg, fail_hs_reply_msg) != NULL); + } + } + } +} + void handshake_list_fini (struct Handshake *hs_list, int nhs) { for (int n = 0; n < nhs; n++) @@ -293,7 +328,7 @@ void handshake_list_fini (struct Handshake *hs_list, int nhs) } } -void sync_writer_to_readers (dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_count) +void sync_writer_to_readers (dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_count, dds_duration_t timeout) { dds_attach_t triggered; dds_entity_t ws = dds_create_waitset (pp_wr); @@ -304,7 +339,7 @@ void sync_writer_to_readers (dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_c CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); while (true) { - ret = dds_waitset_wait (ws, &triggered, 1, DDS_SECS(2)); + ret = dds_waitset_wait (ws, &triggered, 1, timeout); CU_ASSERT_EQUAL_FATAL (exp_count > 0, ret >= 1); if (exp_count > 0) CU_ASSERT_EQUAL_FATAL (wr, (dds_entity_t)(intptr_t) triggered); @@ -317,7 +352,7 @@ void sync_writer_to_readers (dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_c CU_ASSERT_EQUAL_FATAL (pub_matched.total_count, exp_count); } -void sync_reader_to_writers (dds_entity_t pp_rd, dds_entity_t rd, uint32_t exp_count) +void sync_reader_to_writers (dds_entity_t pp_rd, dds_entity_t rd, uint32_t exp_count, dds_duration_t timeout) { dds_attach_t triggered; dds_entity_t ws = dds_create_waitset (pp_rd); @@ -328,7 +363,7 @@ void sync_reader_to_writers (dds_entity_t pp_rd, dds_entity_t rd, uint32_t exp_c CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); while (true) { - ret = dds_waitset_wait (ws, &triggered, 1, DDS_SECS(2)); + ret = dds_waitset_wait (ws, &triggered, 1, timeout); CU_ASSERT_EQUAL_FATAL (exp_count > 0, ret >= 1); if (exp_count > 0) CU_ASSERT_EQUAL_FATAL (rd, (dds_entity_t)(intptr_t) triggered); diff --git a/src/security/core/tests/common/test_utils.h b/src/security/core/tests/common/test_utils.h index 5fb9ccb..2a68327 100644 --- a/src/security/core/tests/common/test_utils.h +++ b/src/security/core/tests/common/test_utils.h @@ -60,26 +60,27 @@ struct Handshake }; void print_test_msg (const char *msg, ...); -void validate_handshake(dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg, struct Handshake *hs_list[], int *nhs); -void validate_handshake_nofail (dds_domainid_t domain_id); -void handshake_list_fini(struct Handshake *hs_list, int nhs); -char *create_topic_name(const char *prefix, uint32_t nr, char *name, size_t size); -void sync_writer_to_readers(dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_count); -void sync_reader_to_writers (dds_entity_t pp_rd, dds_entity_t rd, uint32_t exp_count); -bool reader_wait_for_data(dds_entity_t pp, dds_entity_t rd, dds_duration_t dur); -void rd_wr_init( +void validate_handshake (dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg, struct Handshake *hs_list[], int *nhs, dds_duration_t timeout); +void validate_handshake_nofail (dds_domainid_t domain_id, dds_duration_t timeout); +void validate_handshake_result (struct Handshake *hs, bool exp_fail_hs_req, const char * fail_hs_req_msg, bool exp_fail_hs_reply, const char * fail_hs_reply_msg); +void handshake_list_fini (struct Handshake *hs_list, int nhs); +char *create_topic_name (const char *prefix, uint32_t nr, char *name, size_t size); +void sync_writer_to_readers (dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_count, dds_duration_t timeout); +void sync_reader_to_writers (dds_entity_t pp_rd, dds_entity_t rd, uint32_t exp_count, dds_duration_t timeout); +bool reader_wait_for_data (dds_entity_t pp, dds_entity_t rd, dds_duration_t dur); +void rd_wr_init ( dds_entity_t pp_wr, dds_entity_t *pub, dds_entity_t *pub_tp, dds_entity_t *wr, dds_entity_t pp_rd, dds_entity_t *sub, dds_entity_t *sub_tp, dds_entity_t *rd, const char * topic_name); -void rd_wr_init_fail( +void rd_wr_init_fail ( dds_entity_t pp_wr, dds_entity_t *pub, dds_entity_t *pub_tp, dds_entity_t *wr, dds_entity_t pp_rd, dds_entity_t *sub, dds_entity_t *sub_tp, dds_entity_t *rd, const char * topic_name, bool exp_pubtp_fail, bool exp_wr_fail, bool exp_subtp_fail, bool exp_rd_fail); -void write_read_for(dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_duration_t dur, bool exp_write_fail, bool exp_read_fail); -struct dds_security_cryptography_impl * get_crypto_context(dds_entity_t participant); -const char * pk_to_str(DDS_Security_ProtectionKind pk); -const char * bpk_to_str(DDS_Security_BasicProtectionKind bpk); +void write_read_for (dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_duration_t dur, bool exp_write_fail, bool exp_read_fail); +struct dds_security_cryptography_impl * get_crypto_context (dds_entity_t participant); +const char * pk_to_str (DDS_Security_ProtectionKind pk); +const char * bpk_to_str (DDS_Security_BasicProtectionKind bpk); #endif /* SECURITY_CORE_TEST_UTILS_H_ */ diff --git a/src/security/core/tests/handshake.c b/src/security/core/tests/handshake.c index 5947a8f..26d6d9a 100644 --- a/src/security/core/tests/handshake.c +++ b/src/security/core/tests/handshake.c @@ -107,11 +107,25 @@ static void handshake_fini(void) CU_Test(ddssec_handshake, happy_day) { + struct Handshake *hs_list; + int nhs; + handshake_init ( "init_test_authentication_wrapped", "finalize_test_authentication_wrapped", "init_test_cryptography_wrapped", "finalize_test_cryptography_wrapped"); - validate_handshake_nofail (DDS_DOMAINID1); - validate_handshake_nofail (DDS_DOMAINID2); + + validate_handshake (DDS_DOMAINID1, false, NULL, &hs_list, &nhs, DDS_SECS(2)); + CU_ASSERT_EQUAL_FATAL (nhs, 1); + for (int n = 0; n < nhs; n++) + validate_handshake_result (&hs_list[n], false, NULL, false, NULL); + handshake_list_fini (hs_list, nhs); + + validate_handshake (DDS_DOMAINID2, false, NULL, &hs_list, &nhs, DDS_SECS(2)); + CU_ASSERT_EQUAL_FATAL (nhs, 1); + for (int n = 0; n < nhs; n++) + validate_handshake_result (&hs_list[n], false, NULL, false, NULL); + handshake_list_fini (hs_list, nhs); + handshake_fini (); } @@ -120,8 +134,8 @@ CU_Test(ddssec_handshake, check_tokens) handshake_init ( "init_test_authentication_wrapped", "finalize_test_authentication_wrapped", "init_test_cryptography_store_tokens", "finalize_test_cryptography_store_tokens"); - validate_handshake_nofail (DDS_DOMAINID1); - validate_handshake_nofail (DDS_DOMAINID2); + validate_handshake_nofail (DDS_DOMAINID1, DDS_SECS (2)); + validate_handshake_nofail (DDS_DOMAINID2, DDS_SECS (2)); char topic_name[100]; create_topic_name("ddssec_authentication_", g_topic_nr++, topic_name, sizeof (topic_name)); diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index fb7386f..7236657 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -255,7 +255,7 @@ static void test_write_read(struct domain_sec_config *domain_config, for (size_t w = 0; w < n_writers; w++) { size_t wr_index = pp_index * n_writers + w; - sync_writer_to_readers (g_pub_participants[pp_index], writers[wr_index], (uint32_t)(n_sub_domains * n_sub_participants * n_readers)); + sync_writer_to_readers (g_pub_participants[pp_index], writers[wr_index], (uint32_t)(n_sub_domains * n_sub_participants * n_readers), DDS_SECS(2)); sample.id = (int32_t) wr_index; printf("writer %"PRId32" writing sample %d\n", writers[wr_index], sample.id); ret = dds_write (writers[wr_index], &sample); @@ -366,7 +366,7 @@ static void test_payload_secret(DDS_Security_ProtectionKind rtps_pk, DDS_Securit create_eps (&writers, &writer_topics, 1, 1, 1, name, &SecurityCoreTests_Type2_desc, g_pub_participants, qos, &dds_create_writer, DDS_PUBLICATION_MATCHED_STATUS); create_eps (&readers, &reader_topics, 1, 1, 1, name, &SecurityCoreTests_Type2_desc, g_sub_participants, qos, &dds_create_reader, DDS_DATA_AVAILABLE_STATUS); dds_delete_qos (qos); - sync_writer_to_readers (g_pub_participants[0], writers[0], 1); + sync_writer_to_readers (g_pub_participants[0], writers[0], 1, DDS_SECS(2)); ret = dds_write (writers[0], &sample); CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); From 0348bb274164fa96272f74ea5ef43de0a69f5585 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 28 Apr 2020 14:45:20 +0200 Subject: [PATCH 184/238] Security liveliness protection tests Add testing liveness protection to the existing discovery protection test. The test checks if the P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER is using the encode_decode_submessage function of the crypto plugin to secure liveliness messages. Signed-off-by: Dennis Potman --- src/security/core/tests/access_control.c | 52 +++++++++++++------ .../core/tests/secure_communication.c | 4 +- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index 3a388c1..a4f44f6 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -569,7 +569,7 @@ CU_Theory( } #define na false -CU_TheoryDataPoints(ddssec_access_control, discovery_protection) = { +CU_TheoryDataPoints(ddssec_access_control, discovery_liveliness_protection) = { CU_DataPoints(const char *, /* */"disabled", /* | */"enabled, protection kind none", @@ -588,14 +588,19 @@ CU_TheoryDataPoints(ddssec_access_control, discovery_protection) = { CU_DataPoints(bool, na, na, true, true, true, true, false, false), /* expect encode_datawriter_submessage for SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER of pp 1 */ }; #undef na -CU_Theory( - (const char * test_descr, bool enable_discovery_protection_pp1, bool enable_discovery_protection_pp2, - DDS_Security_ProtectionKind discovery_protection_kind_pp1, DDS_Security_ProtectionKind discovery_protection_kind_pp2, - bool exp_rd_wr_match_fail, bool exp_secure_pub_wr_handle, bool exp_secure_pub_wr_encode_decode), - ddssec_access_control, discovery_protection, .timeout=30) -{ - print_test_msg ("running test discovery_protection: %s\n", test_descr); +enum test_discovery_liveliness +{ + TEST_DISCOVERY, + TEST_LIVELINESS +}; + +static void test_discovery_liveliness_protection(enum test_discovery_liveliness kind, + bool enable_protection_pp1, bool enable_protection_pp2, + DDS_Security_ProtectionKind protection_kind_pp1, DDS_Security_ProtectionKind protection_kind_pp2, + bool exp_rd_wr_match_fail, bool exp_secure_pub_wr_handle, bool exp_secure_pub_wr_encode_decode) +{ + bool dp = kind == TEST_DISCOVERY, lp = kind == TEST_LIVELINESS; char topic_name[100]; create_topic_name ("ddssec_access_control_", g_topic_nr++, topic_name, sizeof (topic_name)); @@ -613,10 +618,10 @@ CU_Theory( get_permissions_grant ("id2", id2_subj, NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL) }; char * perm_config = get_permissions_config (grants, 2, true); - char * gov_topic_rule1 = get_governance_topic_rule (topic_name, enable_discovery_protection_pp1, false, true, true, "ENCRYPT", "NONE"); - char * gov_topic_rule2 = get_governance_topic_rule (topic_name, enable_discovery_protection_pp2, false, true, true, "ENCRYPT", "NONE"); - char * gov_config1 = get_governance_config (false, true, pk_to_str (discovery_protection_kind_pp1), NULL, "ENCRYPT", gov_topic_rule1, true); - char * gov_config2 = get_governance_config (false, true, pk_to_str (discovery_protection_kind_pp2), NULL, "ENCRYPT", gov_topic_rule2, true); + char * gov_topic_rule1 = get_governance_topic_rule (topic_name, dp && enable_protection_pp1, lp && enable_protection_pp1, true, true, "ENCRYPT", "NONE"); + char * gov_topic_rule2 = get_governance_topic_rule (topic_name, dp && enable_protection_pp2, lp && enable_protection_pp2, true, true, "ENCRYPT", "NONE"); + char * gov_config1 = get_governance_config (false, true, dp ? pk_to_str (protection_kind_pp1) : NULL, lp ? pk_to_str (protection_kind_pp1) : NULL, "ENCRYPT", gov_topic_rule1, true); + char * gov_config2 = get_governance_config (false, true, dp ? pk_to_str (protection_kind_pp2) : NULL, lp ? pk_to_str (protection_kind_pp2) : NULL, "ENCRYPT", gov_topic_rule2, true); const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); access_control_init ( @@ -636,8 +641,10 @@ CU_Theory( if (!exp_rd_wr_match_fail) write_read_for (wr, g_participant[1], rd, DDS_MSECS (100), false, false); - DDS_Security_DatawriterCryptoHandle secure_pub_wr_handle = get_builtin_writer_crypto_handle (g_participant[0], NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER); - print_test_msg ("crypto handle for SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER: %ld\n", secure_pub_wr_handle); + unsigned builtin_wr = dp ? NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER : NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER; + const char * builtin_wr_descr = dp ? "SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER" : "P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER"; + DDS_Security_DatawriterCryptoHandle secure_pub_wr_handle = get_builtin_writer_crypto_handle (g_participant[0], builtin_wr); + print_test_msg ("crypto handle for %s: %ld\n", builtin_wr_descr, secure_pub_wr_handle); CU_ASSERT_EQUAL_FATAL (exp_secure_pub_wr_handle, secure_pub_wr_handle != 0); struct dds_security_cryptography_impl * crypto_context_pub = get_crypto_context (g_participant[0]); @@ -647,7 +654,7 @@ CU_Theory( CU_ASSERT_EQUAL_FATAL (exp_secure_pub_wr_handle && exp_secure_pub_wr_encode_decode, log != NULL); if (log != NULL) { - print_test_msg ("encode_datawriter_submessage count for SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER: %u\n", log->count); + print_test_msg ("encode_datawriter_submessage count for %s: %u\n", builtin_wr_descr, log->count); CU_ASSERT_FATAL (log->count > 0); ddsrt_free (log); } @@ -655,6 +662,21 @@ CU_Theory( access_control_fini (2, (void * []) { gov_config1, gov_config2, gov_topic_rule1, gov_topic_rule2, perm_topic, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 13); } +CU_Theory( + (const char * test_descr, bool enable_discovery_protection_pp1, bool enable_discovery_protection_pp2, + DDS_Security_ProtectionKind discovery_protection_kind_pp1, DDS_Security_ProtectionKind discovery_protection_kind_pp2, + bool exp_rd_wr_match_fail, bool exp_secure_pub_wr_handle, bool exp_secure_pub_wr_encode_decode), + ddssec_access_control, discovery_liveliness_protection, .timeout=40) +{ + enum test_discovery_liveliness kinds[2] = { TEST_DISCOVERY, TEST_LIVELINESS }; + for (size_t i = 0; i < sizeof (kinds) / sizeof (kinds[0]); i++) + { + print_test_msg ("running test %s_protection: %s\n", kinds[i] == TEST_DISCOVERY ? "discovery" : "liveliness", test_descr); + test_discovery_liveliness_protection (kinds[i], enable_discovery_protection_pp1, enable_discovery_protection_pp2, + discovery_protection_kind_pp1, discovery_protection_kind_pp2, exp_rd_wr_match_fail, exp_secure_pub_wr_handle, exp_secure_pub_wr_encode_decode); + } +} + static void test_encoding_mismatch( bool exp_hs_fail, bool exp_rd_wr_fail, DDS_Security_ProtectionKind rtps_pk1, DDS_Security_ProtectionKind rtps_pk2, diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index 7236657..4b3e790 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -154,8 +154,8 @@ static void test_init(const struct domain_sec_config * domain_config, size_t n_s assert (n_pub_domains < MAX_DOMAINS); assert (n_pub_participants < MAX_PARTICIPANTS); - char * gov_topic_rule = get_governance_topic_rule ("*", false, false, true, true, pk_to_str (domain_config->metadata_pk), bpk_to_str (domain_config->payload_pk)); - char * gov_config_signed = get_governance_config (false, false, pk_to_str (domain_config->discovery_pk), pk_to_str (domain_config->liveliness_pk), + char * gov_topic_rule = get_governance_topic_rule ("*", true, true, true, true, pk_to_str (domain_config->metadata_pk), bpk_to_str (domain_config->payload_pk)); + char * gov_config_signed = get_governance_config (false, true, pk_to_str (domain_config->discovery_pk), pk_to_str (domain_config->liveliness_pk), pk_to_str (domain_config->rtps_pk), gov_topic_rule, false); struct kvp config_vars[] = { From 45adb6f0c7c4c1cfa1f365f304e2ac7671bcb3a7 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 28 Apr 2020 21:25:57 +0200 Subject: [PATCH 185/238] Extend access-control tests with validate_local_permissions Add validate_local_permissions to the set of access control plugin hooks tests, and add discovery_protection_enabled as an additional parameter for the access control hook tests. Signed-off-by: Dennis Potman --- src/security/core/tests/access_control.c | 122 ++++++++++-------- .../tests/common/access_control_wrapper.c | 36 ++++-- .../tests/common/access_control_wrapper.h | 7 +- 3 files changed, 92 insertions(+), 73 deletions(-) diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index a4f44f6..4e5b54e 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -439,72 +439,80 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) CU_TheoryDataPoints(ddssec_access_control, hooks) = { CU_DataPoints(const char *, /* */"init_test_access_control_local_participant_not_allowed", - /* | */"init_test_access_control_local_topic_not_allowed", - /* | | */"init_test_access_control_local_publishing_not_allowed", - /* | | | */"init_test_access_control_local_subscribing_not_allowed", - /* | | | | */"init_test_access_control_remote_permissions_invalidate", - /* | | | | | */"init_test_access_control_remote_participant_not_allowed", - /* | | | | | | */"init_test_access_control_remote_topic_not_allowed", - /* | | | | | | | */"init_test_access_control_remote_writer_not_allowed", - /* | | | | | | | | */"init_test_access_control_remote_reader_not_allowed", - /* | | | | | | | | | */"init_test_access_control_remote_reader_relay_only"), - CU_DataPoints(bool, true, false, false, false, false, false, false, false, false, false), // exp_pp_fail - CU_DataPoints(bool, na, true, false, false, false, false, false, false, false, false), // exp_local_topic_fail - CU_DataPoints(bool, na, false, false, false, false, false, false, false, false, false), // exp_remote_topic_fail - CU_DataPoints(bool, na, na, true, false, false, false, false, false, false, false), // exp_wr_fail - CU_DataPoints(bool, na, na, false, true, false, false, false, false, false, false), // exp_rd_fail - CU_DataPoints(bool, na, na, na, na, true, true, true, false, true, true), // exp_wr_rd_sync_fail - CU_DataPoints(bool, na, na, false, na, true, true, true, true, false, false), // exp_rd_wr_sync_fail + /* | */"init_test_access_control_local_permissions_not_allowed", + /* | | */"init_test_access_control_local_topic_not_allowed", + /* | | | */"init_test_access_control_local_writer_not_allowed", + /* | | | | */"init_test_access_control_local_reader_not_allowed", + /* | | | | | */"init_test_access_control_remote_permissions_not_allowed", + /* | | | | | | */"init_test_access_control_remote_participant_not_allowed", + /* | | | | | | | */"init_test_access_control_remote_topic_not_allowed", + /* | | | | | | | | */"init_test_access_control_remote_writer_not_allowed", + /* | | | | | | | | | */"init_test_access_control_remote_reader_not_allowed", + /* | | | | | | | | | | */"init_test_access_control_remote_reader_relay_only"), + CU_DataPoints(bool, true, true, false, false, false, false, false, false, false, false, false), // exp_pp_fail + CU_DataPoints(bool, na, na, true, false, false, false, false, false, false, false, false), // exp_local_topic_fail + CU_DataPoints(bool, na, na, false, false, false, false, false, false, false, false, false), // exp_remote_topic_fail + CU_DataPoints(bool, na, na, na, true, false, false, false, false, false, false, false), // exp_wr_fail + CU_DataPoints(bool, na, na, na, false, true, false, false, false, false, false, false), // exp_rd_fail + CU_DataPoints(bool, na, na, na, na, na, true, true, true, false, true, true), // exp_wr_rd_sync_fail + CU_DataPoints(bool, na, na, na, false, na, true, true, true, true, false, false), // exp_rd_wr_sync_fail }; #undef na + CU_Theory( (const char * init_fn, bool exp_pp_fail, bool exp_local_topic_fail, bool exp_remote_topic_fail, bool exp_wr_fail, bool exp_rd_fail, bool exp_wr_rd_sync_fail, bool exp_rd_wr_sync_fail), - ddssec_access_control, hooks, .timeout=40) + ddssec_access_control, hooks, .timeout=60) { - print_test_msg ("running test access_control_hooks: %s\n", init_fn); - - const char * def_gov = PF_F COMMON_ETC_PATH("default_governance.p7s"); - const char * def_perm = PF_F COMMON_ETC_PATH("default_permissions.p7s"); - const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); - - access_control_init ( - 2, - (const char *[]) { TEST_IDENTITY1_CERTIFICATE, TEST_IDENTITY1_CERTIFICATE }, - (const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY }, - (const char *[]) { TEST_IDENTITY_CA1_CERTIFICATE, TEST_IDENTITY_CA1_CERTIFICATE }, - (bool []) { exp_pp_fail, false }, - (const char *[]) { init_fn, "init_test_access_control_wrapped" }, (const char *[]) { "finalize_test_access_control_not_allowed", "finalize_test_access_control_wrapped" }, - (bool []) { true, true, true }, (const char *[]) { def_gov, def_gov }, - (bool []) { true, true, true }, (const char *[]) { def_perm, def_perm }, - (bool []) { true, true, true }, (const char *[]) { def_perm_ca, def_perm_ca }); - - if (!exp_pp_fail) + for (int i = 0; i <= 1; i++) { - dds_entity_t lwr = 0, rwr = 0, lrd = 0, rrd = 0; - dds_entity_t ltopic[2], rtopic[2]; - dds_entity_t lpub, lsub, rpub, rsub; - char topic_name[100]; + bool discovery_protection = (i == 0); + print_test_msg ("running test access_control_hooks: %s with discovery protection %s\n", init_fn, discovery_protection ? "enabled" : "disabled"); - // Local writer, remote reader - create_topic_name (AC_WRAPPER_TOPIC_PREFIX, g_topic_nr++, topic_name, sizeof (topic_name)); - rd_wr_init_fail ( - g_participant[0], &lpub, <opic[0], &lwr, - g_participant[1], &rsub, &rtopic[0], &rrd, - topic_name, exp_local_topic_fail, exp_wr_fail, exp_remote_topic_fail, false); - if (!exp_local_topic_fail && !exp_remote_topic_fail && !exp_wr_fail) - sync_writer_to_readers (g_participant[0], lwr, exp_wr_rd_sync_fail ? 0 : 1, DDS_SECS(2)); + char * gov_topic_rule = get_governance_topic_rule ("*", discovery_protection, false, true, true, NULL, NULL); + char * gov_config = get_governance_config (false, true, "ENCRYPT", NULL, NULL, gov_topic_rule, true); - // Local reader, remote writer - create_topic_name (AC_WRAPPER_TOPIC_PREFIX, g_topic_nr++, topic_name, sizeof (topic_name)); - rd_wr_init_fail ( - g_participant[1], &rpub, &rtopic[1], &rwr, - g_participant[0], &lsub, <opic[1], &lrd, - topic_name, exp_remote_topic_fail, false, exp_local_topic_fail, exp_rd_fail); - if (!exp_local_topic_fail && !exp_remote_topic_fail && !exp_rd_fail) - sync_reader_to_writers (g_participant[0], lrd, exp_rd_wr_sync_fail ? 0 : 1, DDS_SECS(2)); + const char * def_perm = PF_F COMMON_ETC_PATH("default_permissions.p7s"); + const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); + + access_control_init ( + 2, + (const char *[]) { TEST_IDENTITY1_CERTIFICATE, TEST_IDENTITY1_CERTIFICATE }, + (const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY }, + (const char *[]) { TEST_IDENTITY_CA1_CERTIFICATE, TEST_IDENTITY_CA1_CERTIFICATE }, + (bool []) { exp_pp_fail, false }, + (const char *[]) { init_fn, "init_test_access_control_wrapped" }, (const char *[]) { "finalize_test_access_control_not_allowed", "finalize_test_access_control_wrapped" }, + (bool []) { true, true, true }, (const char *[]) { gov_config, gov_config }, + (bool []) { true, true, true }, (const char *[]) { def_perm, def_perm }, + (bool []) { true, true, true }, (const char *[]) { def_perm_ca, def_perm_ca }); + + if (!exp_pp_fail) + { + dds_entity_t lwr = 0, rwr = 0, lrd = 0, rrd = 0; + dds_entity_t ltopic[2], rtopic[2]; + dds_entity_t lpub, lsub, rpub, rsub; + char topic_name[100]; + + // Local writer, remote reader + create_topic_name (AC_WRAPPER_TOPIC_PREFIX, g_topic_nr++, topic_name, sizeof (topic_name)); + rd_wr_init_fail ( + g_participant[0], &lpub, <opic[0], &lwr, + g_participant[1], &rsub, &rtopic[0], &rrd, + topic_name, exp_local_topic_fail, exp_wr_fail, exp_remote_topic_fail, false); + if (!exp_local_topic_fail && !exp_remote_topic_fail && !exp_wr_fail) + sync_writer_to_readers (g_participant[0], lwr, exp_wr_rd_sync_fail ? 0 : 1, DDS_SECS(2)); + + // Local reader, remote writer + create_topic_name (AC_WRAPPER_TOPIC_PREFIX, g_topic_nr++, topic_name, sizeof (topic_name)); + rd_wr_init_fail ( + g_participant[1], &rpub, &rtopic[1], &rwr, + g_participant[0], &lsub, <opic[1], &lrd, + topic_name, exp_remote_topic_fail, false, exp_local_topic_fail, exp_rd_fail); + if (!exp_local_topic_fail && !exp_remote_topic_fail && !exp_rd_fail) + sync_reader_to_writers (g_participant[0], lrd, exp_rd_wr_sync_fail ? 0 : 1, DDS_SECS(1)); + } + + access_control_fini (2, (void * []) { gov_topic_rule, gov_config }, 2); } - - access_control_fini (2, NULL, 0); } #define na false diff --git a/src/security/core/tests/common/access_control_wrapper.c b/src/security/core/tests/common/access_control_wrapper.c index aead7e6..327dae3 100644 --- a/src/security/core/tests/common/access_control_wrapper.c +++ b/src/security/core/tests/common/access_control_wrapper.c @@ -33,26 +33,28 @@ enum ac_plugin_mode { enum ac_plugin_not_allowed { NOT_ALLOWED_ID_LOCAL_PP, NOT_ALLOWED_ID_LOCAL_TOPIC, - NOT_ALLOWED_ID_LOCAL_PUB, - NOT_ALLOWED_ID_LOCAL_SUB, - NOT_ALLOWED_ID_REMOTE_PERM, + NOT_ALLOWED_ID_LOCAL_WRITER, + NOT_ALLOWED_ID_LOCAL_READER, + NOT_ALLOWED_ID_LOCAL_PERM, NOT_ALLOWED_ID_REMOTE_PP, NOT_ALLOWED_ID_REMOTE_TOPIC, NOT_ALLOWED_ID_REMOTE_WRITER, NOT_ALLOWED_ID_REMOTE_READER, - NOT_ALLOWED_ID_REMOTE_READER_RELAY_ONLY + NOT_ALLOWED_ID_REMOTE_READER_RELAY_ONLY, + NOT_ALLOWED_ID_REMOTE_PERM, }; #define NOT_ALLOWED_LOCAL_PP (1u << NOT_ALLOWED_ID_LOCAL_PP) #define NOT_ALLOWED_LOCAL_TOPIC (1u << NOT_ALLOWED_ID_LOCAL_TOPIC) -#define NOT_ALLOWED_LOCAL_PUB (1u << NOT_ALLOWED_ID_LOCAL_PUB) -#define NOT_ALLOWED_LOCAL_SUB (1u << NOT_ALLOWED_ID_LOCAL_SUB) -#define NOT_ALLOWED_REMOTE_PERM (1u << NOT_ALLOWED_ID_REMOTE_PERM) +#define NOT_ALLOWED_LOCAL_WRITER (1u << NOT_ALLOWED_ID_LOCAL_WRITER) +#define NOT_ALLOWED_LOCAL_READER (1u << NOT_ALLOWED_ID_LOCAL_READER) +#define NOT_ALLOWED_LOCAL_PERM (1u << NOT_ALLOWED_ID_LOCAL_PERM) #define NOT_ALLOWED_REMOTE_PP (1u << NOT_ALLOWED_ID_REMOTE_PP) #define NOT_ALLOWED_REMOTE_TOPIC (1u << NOT_ALLOWED_ID_REMOTE_TOPIC) #define NOT_ALLOWED_REMOTE_WRITER (1u << NOT_ALLOWED_ID_REMOTE_WRITER) #define NOT_ALLOWED_REMOTE_READER (1u << NOT_ALLOWED_ID_REMOTE_READER) #define NOT_ALLOWED_REMOTE_READER_RELAY_ONLY (1u << NOT_ALLOWED_ID_REMOTE_READER_RELAY_ONLY) +#define NOT_ALLOWED_REMOTE_PERM (1u << NOT_ALLOWED_ID_REMOTE_PERM) /** * Implementation structure for storing encapsulated members of the instance @@ -76,8 +78,15 @@ static DDS_Security_PermissionsHandle validate_local_permissions( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { - case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: + if (impl->not_allowed_mask & NOT_ALLOWED_LOCAL_PERM) + { + ex->code = 1; + ex->message = ddsrt_strdup ("not_allowed: validate_local_permissions"); + return 0; + } + /* fall through */ + case PLUGIN_MODE_WRAPPED: return impl->instance->validate_local_permissions(impl->instance, auth_plugin, identity, domain_id, participant_qos, ex); default: @@ -154,7 +163,7 @@ static DDS_Security_boolean check_create_datawriter( switch (impl->mode) { case PLUGIN_MODE_NOT_ALLOWED: - if (impl->not_allowed_mask & NOT_ALLOWED_LOCAL_PUB) + if (impl->not_allowed_mask & NOT_ALLOWED_LOCAL_WRITER) { if (topic_name && strncmp (topic_name, AC_WRAPPER_TOPIC_PREFIX, strlen (AC_WRAPPER_TOPIC_PREFIX)) == 0) { @@ -186,7 +195,7 @@ static DDS_Security_boolean check_create_datareader( switch (impl->mode) { case PLUGIN_MODE_NOT_ALLOWED: - if (impl->not_allowed_mask & NOT_ALLOWED_LOCAL_SUB) + if (impl->not_allowed_mask & NOT_ALLOWED_LOCAL_READER) { ex->code = 1; ex->message = ddsrt_strdup ("not_allowed: check_create_datareader"); @@ -838,14 +847,15 @@ int finalize_test_access_control_missing_func(void *context) INIT_NOT_ALLOWED(local_participant_not_allowed, NOT_ALLOWED_LOCAL_PP) INIT_NOT_ALLOWED(local_topic_not_allowed, NOT_ALLOWED_LOCAL_TOPIC) -INIT_NOT_ALLOWED(local_publishing_not_allowed, NOT_ALLOWED_LOCAL_PUB) -INIT_NOT_ALLOWED(local_subscribing_not_allowed, NOT_ALLOWED_LOCAL_SUB) -INIT_NOT_ALLOWED(remote_permissions_invalidate, NOT_ALLOWED_REMOTE_PERM) +INIT_NOT_ALLOWED(local_writer_not_allowed, NOT_ALLOWED_LOCAL_WRITER) +INIT_NOT_ALLOWED(local_reader_not_allowed, NOT_ALLOWED_LOCAL_READER) +INIT_NOT_ALLOWED(local_permissions_not_allowed, NOT_ALLOWED_LOCAL_PERM) INIT_NOT_ALLOWED(remote_participant_not_allowed, NOT_ALLOWED_REMOTE_PP) INIT_NOT_ALLOWED(remote_topic_not_allowed, NOT_ALLOWED_REMOTE_TOPIC) INIT_NOT_ALLOWED(remote_writer_not_allowed, NOT_ALLOWED_REMOTE_WRITER) INIT_NOT_ALLOWED(remote_reader_not_allowed, NOT_ALLOWED_REMOTE_READER) INIT_NOT_ALLOWED(remote_reader_relay_only, NOT_ALLOWED_REMOTE_READER_RELAY_ONLY) +INIT_NOT_ALLOWED(remote_permissions_not_allowed, NOT_ALLOWED_REMOTE_PERM) int finalize_test_access_control_not_allowed(void *context) { diff --git a/src/security/core/tests/common/access_control_wrapper.h b/src/security/core/tests/common/access_control_wrapper.h index 3fb04bf..6f733fc 100644 --- a/src/security/core/tests/common/access_control_wrapper.h +++ b/src/security/core/tests/common/access_control_wrapper.h @@ -37,14 +37,15 @@ SECURITY_EXPORT int finalize_test_access_control_wrapped(void *context); INIT_NOT_ALLOWED_DECL(local_participant_not_allowed) INIT_NOT_ALLOWED_DECL(local_topic_not_allowed) -INIT_NOT_ALLOWED_DECL(local_publishing_not_allowed) -INIT_NOT_ALLOWED_DECL(local_subscribing_not_allowed) -INIT_NOT_ALLOWED_DECL(remote_permissions_invalidate) +INIT_NOT_ALLOWED_DECL(local_writer_not_allowed) +INIT_NOT_ALLOWED_DECL(local_reader_not_allowed) +INIT_NOT_ALLOWED_DECL(local_permissions_not_allowed) INIT_NOT_ALLOWED_DECL(remote_participant_not_allowed) INIT_NOT_ALLOWED_DECL(remote_topic_not_allowed) INIT_NOT_ALLOWED_DECL(remote_writer_not_allowed) INIT_NOT_ALLOWED_DECL(remote_reader_not_allowed) INIT_NOT_ALLOWED_DECL(remote_reader_relay_only) +INIT_NOT_ALLOWED_DECL(remote_permissions_not_allowed) SECURITY_EXPORT int finalize_test_access_control_not_allowed(void *context); From 155f8c059d560ee3cf75e991bf5f5a84465933dc Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Wed, 29 Apr 2020 20:53:14 +0200 Subject: [PATCH 186/238] Add read-write protection tests Introduced a test that checks for the correct matching behavious for combinations of the read/write access control settings in the governance xml (enable read/write access control in the topic rules) and in the permissions xml (the publish/subscribe grants for a topic). Signed-off-by: Dennis Potman --- src/security/core/tests/access_control.c | 123 ++++++++++++--- src/security/core/tests/authentication.c | 5 +- .../tests/common/security_config_test_utils.c | 142 +++++++++++++----- .../tests/common/security_config_test_utils.h | 14 +- 4 files changed, 210 insertions(+), 74 deletions(-) diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index 4e5b54e..c508d55 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -90,6 +90,7 @@ static void access_control_init( CU_ASSERT_FATAL (n_nodes <= MAX_DOMAINS); for (size_t i = 0; i < n_nodes; i++) { + print_test_msg ("init domain %"PRIuSIZE"\n", i); struct kvp config_vars[] = { { "TEST_IDENTITY_CERTIFICATE", id_certs[i], 1 }, { "TEST_IDENTITY_PRIVATE_KEY", id_keys[i], 1 }, @@ -256,10 +257,10 @@ CU_Theory( /* localtime will be converted to gmtime in get_permissions_grant */ dds_time_t now = dds_time (); - char * perm_topic = get_permissions_topic (topic_name); + char * rules_xml = get_permissions_rules (NULL, topic_name, topic_name, NULL, NULL); char * grants[] = { - get_permissions_grant ("id1", id1_subj, NULL, now + DDS_SECS(perm1_not_before), now + DDS_SECS(perm1_not_after), perm_topic, perm_topic, NULL), - get_permissions_grant ("id2", id2_subj, NULL, now + DDS_SECS(perm2_not_before), now + DDS_SECS(perm2_not_after), perm_topic, perm_topic, NULL) }; + get_permissions_grant ("id1", id1_subj, now + DDS_SECS(perm1_not_before), now + DDS_SECS(perm1_not_after), rules_xml, NULL), + get_permissions_grant ("id2", id2_subj, now + DDS_SECS(perm2_not_before), now + DDS_SECS(perm2_not_after), rules_xml, NULL) }; char * perm_config = get_permissions_config (grants, 2, true); dds_sleepfor (DDS_MSECS (delay_perm)); @@ -285,7 +286,7 @@ CU_Theory( write_read_for (wr, g_participant[1], rd, DDS_MSECS (write_read_dur), false, exp_read_fail); } - access_control_fini (2, (void * []) { perm_topic, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 9); + access_control_fini (2, (void * []) { rules_xml, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 9); } @@ -300,7 +301,7 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) dds_time_t t_perm = dds_time (); char *ca = generate_ca ("ca1", TEST_IDENTITY_CA1_PRIVATE_KEY, 0, 3600); - char *perm_topic = get_permissions_topic (topic_name); + char *rules_xml = get_permissions_rules (NULL, topic_name, topic_name, NULL, NULL); // 1st node used as reader, other nodes as writer print_test_msg ("creating permissions grants\n"); @@ -323,7 +324,7 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) dds_time_t t_exp = ddsrt_time_add_duration (t_perm, v); if (i >= N_RD) print_test_msg ("w[%d] grant expires at %d.%06d\n", i - N_RD, (int32_t) (t_exp / DDS_NSECS_IN_SEC), (int32_t) (t_exp % DDS_NSECS_IN_SEC) / 1000); - grants[i] = get_permissions_grant (id_name, id_subj[i], NULL, t_perm, t_exp, perm_topic, perm_topic, NULL); + grants[i] = get_permissions_grant (id_name, id_subj[i], t_perm, t_exp, rules_xml, NULL); ddsrt_free (id_name); } @@ -427,7 +428,7 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) ddsrt_free ((char *)id[i]); } ddsrt_free (ca); - ddsrt_free (perm_topic); + ddsrt_free (rules_xml); ddsrt_free (perm_config_str); } #undef N_RD @@ -547,12 +548,12 @@ CU_Theory( id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id1_subj); id2 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id2", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id2_subj); - /* localtime will be converted to gmtime in get_permissions_grant */ dds_time_t now = dds_time (); - char * perm_topic = get_permissions_topic (topic_name); + char * rules1_xml = get_permissions_rules (perm_inv_pp1 ? "99" : NULL, topic_name, topic_name, NULL, NULL); + char * rules2_xml = get_permissions_rules (perm_inv_pp2 ? "99" : NULL, topic_name, topic_name, NULL, NULL); char * grants[] = { - get_permissions_grant ("id1", id1_subj, perm_inv_pp1 ? "99" : NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL), - get_permissions_grant ("id2", id2_subj, perm_inv_pp2 ? "99" : NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL) }; + get_permissions_grant ("id1", id1_subj, now, now + DDS_SECS(3600), rules1_xml, NULL), + get_permissions_grant ("id2", id2_subj, now, now + DDS_SECS(3600), rules2_xml, NULL) }; char * perm_config = get_permissions_config (grants, 2, true); char * gov_topic_rule = get_governance_topic_rule ("*", false, false, true, true, "NONE", "NONE"); @@ -573,7 +574,7 @@ CU_Theory( if (!exp_pp1_fail && !exp_pp2_fail) validate_handshake (DDS_DOMAINID, exp_hs_fail, NULL, NULL, NULL, DDS_SECS(2)); - access_control_fini (2, (void * []) { gov_config_pp1, gov_config_pp2, gov_topic_rule, perm_topic, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 12); + access_control_fini (2, (void * []) { gov_config_pp1, gov_config_pp2, gov_topic_rule, rules1_xml, rules2_xml, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 13); } #define na false @@ -618,12 +619,9 @@ static void test_discovery_liveliness_protection(enum test_discovery_liveliness id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id1_subj); id2 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id2", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id2_subj); - /* localtime will be converted to gmtime in get_permissions_grant */ - dds_time_t now = dds_time (); - char * perm_topic = get_permissions_topic (topic_name); char * grants[] = { - get_permissions_grant ("id1", id1_subj, NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL), - get_permissions_grant ("id2", id2_subj, NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL) }; + get_permissions_default_grant ("id1", id1_subj, topic_name), + get_permissions_default_grant ("id2", id2_subj, topic_name) }; char * perm_config = get_permissions_config (grants, 2, true); char * gov_topic_rule1 = get_governance_topic_rule (topic_name, dp && enable_protection_pp1, lp && enable_protection_pp1, true, true, "ENCRYPT", "NONE"); @@ -667,7 +665,7 @@ static void test_discovery_liveliness_protection(enum test_discovery_liveliness ddsrt_free (log); } - access_control_fini (2, (void * []) { gov_config1, gov_config2, gov_topic_rule1, gov_topic_rule2, perm_topic, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 13); + access_control_fini (2, (void * []) { gov_config1, gov_config2, gov_topic_rule1, gov_topic_rule2, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 12); } CU_Theory( @@ -702,12 +700,9 @@ static void test_encoding_mismatch( id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id1_subj); id2 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id2", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id2_subj); - /* localtime will be converted to gmtime in get_permissions_grant */ - dds_time_t now = dds_time (); - char * perm_topic = get_permissions_topic (topic_name); char * grants[] = { - get_permissions_grant ("id1", id1_subj, NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL), - get_permissions_grant ("id2", id2_subj, NULL, now, now + DDS_SECS(3600), perm_topic, perm_topic, NULL) }; + get_permissions_default_grant ("id1", id1_subj, topic_name), + get_permissions_default_grant ("id2", id2_subj, topic_name) }; char * perm_config = get_permissions_config (grants, 2, true); char * gov_topic_rule1 = get_governance_topic_rule (topic_name, true, true, true, true, pk_to_str (metadata_pk1), bpk_to_str (payload_pk1)); @@ -739,7 +734,7 @@ static void test_encoding_mismatch( sync_writer_to_readers (g_participant[0], wr, exp_rd_wr_fail ? 0 : 1, DDS_SECS(1)); } - access_control_fini (2, (void * []) { gov_config1, gov_config2, gov_topic_rule1, gov_topic_rule2, perm_topic, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 13); + access_control_fini (2, (void * []) { gov_config1, gov_config2, gov_topic_rule1, gov_topic_rule2, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 12); } static DDS_Security_ProtectionKind pk[] = { PK_N, PK_S, PK_E, PK_SOA, PK_EOA }; @@ -779,3 +774,83 @@ CU_Test(ddssec_access_control, encoding_mismatch_payload, .timeout=30) for (size_t pk2 = pk1 + 1; pk2 < sizeof (bpk) / sizeof (bpk[0]); pk2++) test_encoding_mismatch (false, pk1 != pk2, PK_N, PK_N, PK_N, PK_N, PK_N, PK_N, PK_N, PK_N, bpk[pk1], bpk[pk2]); } + + +static void test_readwrite_protection ( + bool allow_pub, bool allow_sub, bool deny_pub, bool deny_sub, bool write_ac, bool read_ac, + bool exp_pub_pp_fail, bool exp_pub_tp_fail, bool exp_wr_fail, + bool exp_sub_pp_fail, bool exp_sub_tp_fail, bool exp_rd_fail, + bool exp_sync_fail, const char * default_policy) +{ + print_test_msg ("running test readwrite_protection: \n"); + print_test_msg ("- allow_pub=%d | allow_sub=%d | deny_pub=%d | deny_sub=%d | write_ac=%d | read_ac=%d | default_policy=%s\n", allow_pub, allow_sub, deny_pub, deny_sub, write_ac, read_ac, default_policy); + print_test_msg ("- exp_pub_pp_fail=%d | exp_pub_tp_fail=%d | exp_wr_fail=%d | exp_sub_pp_fail=%d | exp_sub_tp_fail=%d | exp_rd_fail=%d | exp_sync_fail=%d\n", exp_pub_pp_fail, exp_pub_tp_fail, exp_wr_fail, exp_sub_pp_fail, exp_sub_tp_fail, exp_rd_fail, exp_sync_fail); + + char topic_name[100]; + create_topic_name ("ddssec_access_control_", g_topic_nr++, topic_name, sizeof (topic_name)); + + /* create ca and id1/id2 certs that will not expire during this test */ + char *ca, *id1, *id2, *id1_subj, *id2_subj; + ca = generate_ca ("ca1", TEST_IDENTITY_CA1_PRIVATE_KEY, 0, 3600); + id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id1_subj); + id2 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id2", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id2_subj); + + dds_time_t now = dds_time (); + char * rules_xml = get_permissions_rules (NULL, allow_pub ? topic_name : NULL, allow_sub ? topic_name : NULL, deny_pub ? topic_name : NULL, deny_sub ? topic_name : NULL); + char * grants[] = { + get_permissions_grant ("id1", id1_subj, now, now + DDS_SECS(3600), rules_xml, default_policy), + get_permissions_grant ("id2", id2_subj, now, now + DDS_SECS(3600), rules_xml, default_policy) }; + char * perm_config = get_permissions_config (grants, 2, true); + + char * gov_topic_rule = get_governance_topic_rule (topic_name, false, false, read_ac, write_ac, pk_to_str (PK_E), bpk_to_str (BPK_E)); + char * gov_config = get_governance_config (false, true, NULL, NULL, NULL, gov_topic_rule, true); + const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); + + access_control_init ( + 2, + (const char *[]) { id1, id2 }, + (const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY }, + (const char *[]) { ca, ca }, + (bool []) { exp_pub_pp_fail, exp_sub_pp_fail }, NULL, NULL, + (bool []) { true, true }, (const char *[]) { gov_config, gov_config }, + (bool []) { true, true }, (const char *[]) { perm_config, perm_config }, + (bool []) { true, true }, (const char *[]) { def_perm_ca, def_perm_ca }); + + if (!exp_pub_pp_fail && !exp_sub_pp_fail) + { + dds_entity_t pub, sub, pub_tp, sub_tp, wr, rd; + validate_handshake_nofail (DDS_DOMAINID, DDS_MSECS(500)); + rd_wr_init_fail (g_participant[0], &pub, &pub_tp, &wr, g_participant[1], &sub, &sub_tp, &rd, topic_name, exp_pub_tp_fail, exp_wr_fail, exp_sub_tp_fail, exp_rd_fail); + if (!exp_pub_tp_fail && !exp_wr_fail && !exp_sub_tp_fail && !exp_rd_fail) + sync_writer_to_readers (g_participant[0], wr, exp_sync_fail ? 0 : 1, DDS_SECS(1)); + } + + access_control_fini (2, (void * []) { gov_config, gov_topic_rule, rules_xml, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 11); +} + +CU_Test(ddssec_access_control, readwrite_protection, .timeout=60) +{ + for (int allow_pub = 0; allow_pub <= 1; allow_pub++) + for (int allow_sub = 0; allow_sub <= 1; allow_sub++) + for (int deny_pub = 0; deny_pub <= 1 && !(allow_pub && deny_pub); deny_pub++) + for (int deny_sub = 0; deny_sub <= 1 && !(allow_sub && deny_sub); deny_sub++) + for (int write_ac = 0; write_ac <= 1; write_ac++) + for (int read_ac = 0; read_ac <= 1; read_ac++) + for (int default_deny = 0; default_deny <= 1; default_deny++) + { + /* creating local writer/reader fails if write_ac/read_ac enabled and no allow-pub/sub or a deny-pub/sub rule exists */ + bool exp_wr_fail = write_ac && !allow_pub && (deny_pub || default_deny); + bool exp_rd_fail = read_ac && !allow_sub && (deny_sub || default_deny); + /* if both read_ac and write_ac are enabled, and pub and sub not allowed, topic creation should fail */ + bool exp_tp_fail = write_ac && read_ac && !allow_pub && !allow_sub && (deny_pub || deny_sub || default_deny); + /* participant creation should fail under same conditions as topic creation (as opposed to the DDS Security spec, + table 63, that states that participant creation fails when there is not any topic that has enable_read/write_ac + set to false and join_ac is enabled; it seems that the allow_rule condition is missing there) */ + bool exp_pp_fail = write_ac && read_ac && !allow_pub && !allow_sub && default_deny; + /* join-ac is enabled in this test, so check_remote_pp fails (and therefore the reader/writer sync) in case not any allow rule exists */ + bool exp_sync_fail = !allow_pub && !allow_sub && default_deny; + + test_readwrite_protection (allow_pub, allow_sub, deny_pub, deny_sub, write_ac, read_ac, + exp_pp_fail, exp_tp_fail, exp_wr_fail, exp_pp_fail, exp_tp_fail, exp_rd_fail, exp_sync_fail, default_deny ? "DENY" : "ALLOW"); + } +} diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index bbfb69b..07d637e 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -263,10 +263,9 @@ CU_Theory( id2 = generate_identity (ca, CA1K, "id2", ID1K, id2_not_before, id2_not_after, &id2_subj); dds_sleepfor (DDS_MSECS (delay)); - dds_time_t now = dds_time (); char * grants[] = { - get_permissions_grant ("id1", id1_subj, NULL, now - DDS_SECS(D(1)), now + DDS_SECS(D(1)), NULL, NULL, NULL), - get_permissions_grant ("id2", id2_subj, NULL, now - DDS_SECS(D(1)), now + DDS_SECS(D(1)), NULL, NULL, NULL) }; + get_permissions_default_grant ("id1", id1_subj, topic_name), + get_permissions_default_grant ("id2", id2_subj, topic_name) }; char * perm_config = get_permissions_config (grants, 2, true); authentication_init (id1, ID1K, ca, id2, ID1K, ca, NULL, perm_config, id1_local_fail, id2_local_fail); validate_handshake (DDS_DOMAINID1, id1_local_fail, NULL, NULL, NULL, DDS_SECS(2)); diff --git a/src/security/core/tests/common/security_config_test_utils.c b/src/security/core/tests/common/security_config_test_utils.c index 74f3e5e..8c46848 100644 --- a/src/security/core/tests/common/security_config_test_utils.c +++ b/src/security/core/tests/common/security_config_test_utils.c @@ -27,6 +27,7 @@ #include "dds/ddsrt/string.h" #include "dds/ddsrt/io.h" #include "common/config_env.h" +#include "common/test_utils.h" #include "security_config_test_utils.h" static const char *topic_rule = @@ -63,24 +64,37 @@ static const char *governance_xml = " " ""; -static const char *topic_xml = - "${TOPIC_NAME}"; +static const char *permissions_xml_pub = + " " + " ${TOPIC_NAME}" + " *" + " "; + +static const char *permissions_xml_sub = + " " + " ${TOPIC_NAME}" + " *" + " "; + +static const char *permissions_xml_allow_rule = + " " + " ${DOMAIN_ID:+}${DOMAIN_ID:-0230}${DOMAIN_ID:+}" + " ${PUBLISH}" + " ${SUBSCRIBE}" + " "; + +static const char *permissions_xml_deny_rule = + " " + " ${DOMAIN_ID:+}${DOMAIN_ID:-0230}${DOMAIN_ID:+}" + " ${PUBLISH}" + " ${SUBSCRIBE}" + " "; static const char *permissions_xml_grant = " " " ${SUBJECT_NAME}" " ${NOT_BEFORE:-2015-09-15T01:00:00}${NOT_AFTER:-2115-09-15T01:00:00}" - " " - " ${DOMAIN_ID:+}${DOMAIN_ID:-0230}${DOMAIN_ID:+}" - " " - " ${PUB_TOPICS:-*}" - " *" - " " - " " - " ${SUB_TOPICS:-*}" - " *" - " " - " " + " ${RULES}" " ${DEFAULT_POLICY:-DENY}" " "; @@ -130,6 +144,20 @@ int32_t expand_lookup_unmatched (const struct kvp * lookup_table) return unmatched; } +static char * get_xml_datetime(dds_time_t t, char * buf, size_t len) +{ + struct tm tm; + time_t sec = (time_t)(t / DDS_NSECS_IN_SEC); +#if _WIN32 + (void)gmtime_s(&tm, &sec); +#else + (void)gmtime_r(&sec, &tm); +#endif /* _WIN32 */ + + strftime(buf, len, "%FT%TZ", &tm); + return buf; +} + static char * smime_sign(char * ca_cert_path, char * ca_priv_key_path, const char * data) { // Read CA certificate @@ -232,7 +260,7 @@ char * get_governance_topic_rule(const char * topic_expr, bool discovery_protect return ddsrt_expand_vars (topic_rule, &expand_lookup_vars, vars); } -char * get_governance_config(bool allow_unauth_pp, bool enable_join_ac, const char * discovery_protection_kind, const char * liveliness_protection_kind, +char * get_governance_config (bool allow_unauth_pp, bool enable_join_ac, const char * discovery_protection_kind, const char * liveliness_protection_kind, const char * rtps_protection_kind, const char * topic_rules, bool add_prefix) { struct kvp vars[] = { @@ -248,57 +276,89 @@ char * get_governance_config(bool allow_unauth_pp, bool enable_join_ac, const ch char * config_signed = get_signed_data (config); ddsrt_free (config); - printf("Governance configuration: "); - print_config_vars(vars); + print_test_msg ("governance configuration: "); + print_config_vars (vars); printf("\n"); return prefix_data (config_signed, add_prefix); } - -char * get_permissions_topic(const char * name) +static char * expand_permissions_pubsub (const char * template, const char * topic_name) { struct kvp vars[] = { - { "TOPIC_NAME", name, 1 }, + { "TOPIC_NAME", topic_name, 1 }, { NULL, NULL, 0 } }; - return ddsrt_expand_vars (topic_xml, &expand_lookup_vars, vars); + return ddsrt_expand_vars (template, &expand_lookup_vars, vars); } -static char * get_xml_datetime(dds_time_t t, char * buf, size_t len) +static char * expand_permissions_rule (const char * template, const char * domain_id, const char * pub_xml, const char * sub_xml) { - struct tm tm; - time_t sec = (time_t)(t / DDS_NSECS_IN_SEC); -#if _WIN32 - (void)gmtime_s(&tm, &sec); -#else - (void)gmtime_r(&sec, &tm); -#endif /* _WIN32 */ - - strftime(buf, len, "%FT%TZ", &tm); - return buf; + struct kvp vars[] = { + { "DOMAIN_ID", domain_id, 3 }, + { "PUBLISH", pub_xml, 1 }, + { "SUBSCRIBE", sub_xml, 1 }, + { NULL, NULL, 0 } + }; + return ddsrt_expand_vars (template, &expand_lookup_vars, vars); } -char * get_permissions_grant(const char * name, const char * subject, const char * domain_id, - dds_time_t not_before, dds_time_t not_after, const char * pub_topics, const char * sub_topics, const char * default_policy) +char * get_permissions_rules (const char * domain_id, const char * allow_pub_topic, const char * allow_sub_topic, const char * deny_pub_topic, const char * deny_sub_topic) +{ + char * allow_pub_xml = NULL, * allow_sub_xml = NULL, * deny_pub_xml = NULL, * deny_sub_xml = NULL; + char * allow_rule_xml = NULL, * deny_rule_xml = NULL, * rules_xml; + + if (allow_pub_topic != NULL) allow_pub_xml = expand_permissions_pubsub (permissions_xml_pub, allow_pub_topic); + if (allow_sub_topic != NULL) allow_sub_xml = expand_permissions_pubsub (permissions_xml_sub, allow_sub_topic); + if (deny_pub_topic != NULL) deny_pub_xml = expand_permissions_pubsub (permissions_xml_pub, deny_pub_topic); + if (deny_sub_topic != NULL) deny_sub_xml = expand_permissions_pubsub (permissions_xml_sub, deny_sub_topic); + + if (allow_pub_xml != NULL || allow_sub_xml != NULL) + { + allow_rule_xml = expand_permissions_rule (permissions_xml_allow_rule, domain_id, allow_pub_xml, allow_sub_xml); + if (allow_pub_xml != NULL) ddsrt_free (allow_pub_xml); + if (allow_sub_xml != NULL) ddsrt_free (allow_sub_xml); + } + if (deny_pub_xml != NULL || deny_sub_xml != NULL) + { + deny_rule_xml = expand_permissions_rule (permissions_xml_deny_rule, domain_id, deny_pub_xml, deny_sub_xml); + if (deny_pub_xml != NULL) ddsrt_free (deny_pub_xml); + if (deny_sub_xml != NULL) ddsrt_free (deny_sub_xml); + } + ddsrt_asprintf (&rules_xml, "%s%s", allow_rule_xml != NULL ? allow_rule_xml : "", deny_rule_xml != NULL ? deny_rule_xml : ""); + if (allow_rule_xml != NULL) ddsrt_free (allow_rule_xml); + if (deny_rule_xml != NULL) ddsrt_free (deny_rule_xml); + return rules_xml; +} + +char * get_permissions_grant (const char * grant_name, const char * subject_name, dds_time_t not_before, dds_time_t not_after, const char * rules_xml, const char * default_policy) { char not_before_str[] = "0000-00-00T00:00:00Z"; char not_after_str[] = "0000-00-00T00:00:00Z"; - get_xml_datetime(not_before, not_before_str, sizeof(not_before_str)); - get_xml_datetime(not_after, not_after_str, sizeof(not_after_str)); + get_xml_datetime (not_before, not_before_str, sizeof(not_before_str)); + get_xml_datetime (not_after, not_after_str, sizeof(not_after_str)); struct kvp vars[] = { - { "GRANT_NAME", name, 1 }, - { "SUBJECT_NAME", subject, 1 }, + { "GRANT_NAME", grant_name, 1 }, + { "SUBJECT_NAME", subject_name, 1 }, { "NOT_BEFORE", not_before_str, 1 }, { "NOT_AFTER", not_after_str, 1 }, - { "DOMAIN_ID", domain_id, 3 }, - { "PUB_TOPICS", pub_topics, 1 }, - { "SUB_TOPICS", sub_topics, 1 }, + { "RULES", rules_xml, 1 }, { "DEFAULT_POLICY", default_policy, 1 }, { NULL, NULL, 0 } }; - return ddsrt_expand_vars (permissions_xml_grant, &expand_lookup_vars, vars); + char * res = ddsrt_expand_vars (permissions_xml_grant, &expand_lookup_vars, vars); + CU_ASSERT_FATAL (expand_lookup_unmatched (vars) == 0); + return res; +} + +char * get_permissions_default_grant (const char * grant_name, const char * subject_name, const char * topic_name) +{ + dds_time_t now = dds_time (); + char * rules_xml = get_permissions_rules (NULL, topic_name, topic_name, NULL, NULL); + char * grant_xml = get_permissions_grant (grant_name, subject_name, now, now + DDS_SECS(3600), rules_xml, "DENY"); + ddsrt_free (rules_xml); + return grant_xml; } char * get_permissions_config(char * grants[], size_t ngrants, bool add_prefix) diff --git a/src/security/core/tests/common/security_config_test_utils.h b/src/security/core/tests/common/security_config_test_utils.h index 770c979..e70b98e 100644 --- a/src/security/core/tests/common/security_config_test_utils.h +++ b/src/security/core/tests/common/security_config_test_utils.h @@ -25,14 +25,16 @@ const char * expand_lookup_vars (const char *name, void * data); const char * expand_lookup_vars_env (const char *name, void * data); int32_t expand_lookup_unmatched (const struct kvp * lookup_table); -char * get_governance_topic_rule(const char * topic_expr, bool discovery_protection, bool liveliness_protection, +char * get_governance_topic_rule (const char * topic_expr, bool discovery_protection, bool liveliness_protection, bool read_ac, bool write_ac, const char * metadata_protection_kind, const char * data_protection_kind); -char * get_governance_config(bool allow_unauth_pp, bool enable_join_ac, const char * discovery_protection_kind, const char * liveliness_protection_kind, +char * get_governance_config (bool allow_unauth_pp, bool enable_join_ac, const char * discovery_protection_kind, const char * liveliness_protection_kind, const char * rtps_protection_kind, const char * topic_rules, bool add_prefix); -char * get_permissions_topic(const char * name); -char * get_permissions_grant(const char * name, const char * subject, const char * domain_id, - dds_time_t not_before, dds_time_t not_after, const char * pub_topics, const char * sub_topics, const char * default_policy); -char * get_permissions_config(char * grants[], size_t ngrants, bool add_prefix); +char * get_permissions_rules (const char * domain_id, const char * allow_pub_topic, const char * allow_sub_topic, + const char * deny_pub_topic, const char * deny_sub_topic); +char * get_permissions_grant (const char * grant_name, const char * subject_name, dds_time_t not_before, dds_time_t not_after, + const char * rules_xml, const char * default_policy); +char * get_permissions_default_grant (const char * grant_name, const char * subject_name, const char * topic_name); +char * get_permissions_config (char * grants[], size_t ngrants, bool add_prefix); #endif /* SECURITY_CORE_TEST_SECURITY_CONFIG_TEST_UTILS_H_ */ From 2fc2cdc22533047dc93000fe502d4edb3956f5f4 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Mon, 11 May 2020 21:33:47 +0200 Subject: [PATCH 187/238] Enable matching local non-secure participants with remote secure participants that allow unauthenticated participants Signed-off-by: Dennis Potman --- src/core/ddsi/src/q_entity.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index c1f4573..b8858ca 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -4774,21 +4774,21 @@ void handshake_end_cb(struct ddsi_handshake *handshake, struct participant *pp, } } -static int proxy_participant_check_security_info(struct ddsi_domaingv *gv, struct proxy_participant *proxypp) +static bool proxy_participant_has_pp_match(struct ddsi_domaingv *gv, struct proxy_participant *proxypp) { - int r = 0; + bool match = false; struct participant *pp; struct entidx_enum_participant est; entidx_enum_participant_init (&est, gv->entity_index); - while (((pp = entidx_enum_participant_next (&est)) != NULL) && (r == 0)) { - if (q_omg_is_similar_participant_security_info(pp, proxypp)) { - r = 1; - break; - } + while ((pp = entidx_enum_participant_next (&est)) != NULL && !match) + { + /* remote secure pp can possibly match with local non-secured pp in case allow-unauthenticated pp + is enabled in the remote pp's security settings */ + match = !q_omg_participant_is_secure (pp) || q_omg_is_similar_participant_security_info (pp, proxypp); } - entidx_enum_participant_fini(&est); - return r; + entidx_enum_participant_fini (&est); + return match; } static void proxy_participant_create_handshakes(struct ddsi_domaingv *gv, struct proxy_participant *proxypp) @@ -4955,9 +4955,9 @@ void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *pp { q_omg_security_init_remote_participant (proxypp); /* check if the proxy participant has a match with a local participant */ - if (!proxy_participant_check_security_info (gv, proxypp)) + if (!proxy_participant_has_pp_match (gv, proxypp)) { - // GVWARNING ("Remote secure participant "PGUIDFMT" not allowed\n", PGUID (*ppguid)); + GVWARNING ("Remote secure participant "PGUIDFMT" not allowed\n", PGUID (*ppguid)); free_proxy_participant (proxypp); return; } From 6185a5ab2a0092f0cbc1a6ad8410e4229276f6a4 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Mon, 11 May 2020 21:37:13 +0200 Subject: [PATCH 188/238] Add a test to validate that a non-secure participant can connect with a secure participant that allows unauthenticated participants. The non-secure pp should only be able to read data for a topic that is not secured Signed-off-by: Dennis Potman --- src/security/core/tests/access_control.c | 70 ++----- src/security/core/tests/authentication.c | 176 ++++++++++++------ .../tests/common/security_config_test_utils.c | 18 +- .../tests/common/security_config_test_utils.h | 6 +- src/security/core/tests/common/test_utils.c | 34 ++++ src/security/core/tests/common/test_utils.h | 5 + .../core/tests/secure_communication.c | 5 +- 7 files changed, 182 insertions(+), 132 deletions(-) diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index c508d55..ea08591 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -23,8 +23,6 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/io.h" #include "dds/ddsrt/string.h" -#include "dds/ddsi/q_entity.h" -#include "dds/ddsi/ddsi_entity_index.h" #include "dds/ddsi/ddsi_security_omg.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/ddsi_domaingv.h" @@ -72,9 +70,6 @@ static const char *config = #define MAX_DOMAINS 10 #define DDS_DOMAINID 0 -#define PF_F "file:" -#define PF_D "data:," - static dds_entity_t g_domain[MAX_DOMAINS]; static dds_entity_t g_participant[MAX_DOMAINS]; static uint32_t g_topic_nr = 0; @@ -125,41 +120,6 @@ static void access_control_fini(size_t n, void * res[], size_t nres) } } -static DDS_Security_DatawriterCryptoHandle get_builtin_writer_crypto_handle(dds_entity_t participant, unsigned entityid) -{ - DDS_Security_DatawriterCryptoHandle crypto_handle; - struct dds_entity *pp_entity; - struct participant *pp; - struct writer *wr; - CU_ASSERT_EQUAL_FATAL(dds_entity_pin(participant, &pp_entity), 0); - thread_state_awake(lookup_thread_state(), &pp_entity->m_domain->gv); - pp = entidx_lookup_participant_guid(pp_entity->m_domain->gv.entity_index, &pp_entity->m_guid); - wr = get_builtin_writer(pp, entityid); - CU_ASSERT_FATAL(wr != NULL); - assert(wr != NULL); /* for Clang's static analyzer */ - crypto_handle = wr->sec_attr->crypto_handle; - thread_state_asleep(lookup_thread_state()); - dds_entity_unpin(pp_entity); - return crypto_handle; -} - -// static DDS_Security_DatawriterCryptoHandle get_writer_crypto_handle(dds_entity_t writer) -// { -// DDS_Security_DatawriterCryptoHandle crypto_handle; -// struct dds_entity *wr_entity; -// struct writer *wr; -// CU_ASSERT_EQUAL_FATAL(dds_entity_pin(writer, &wr_entity), 0); -// thread_state_awake(lookup_thread_state(), &wr_entity->m_domain->gv); -// wr = entidx_lookup_writer_guid(wr_entity->m_domain->gv.entity_index, &wr_entity->m_guid); -// CU_ASSERT_FATAL(wr != NULL); -// assert(wr != NULL); /* for Clang's static analyzer */ -// crypto_handle = wr->sec_attr->crypto_handle; -// thread_state_asleep(lookup_thread_state()); -// dds_entity_unpin(wr_entity); -// return crypto_handle; -// } - - #define GOV_F PF_F COMMON_ETC_PATH("default_governance.p7s") #define GOV_FNE PF_F COMMON_ETC_PATH("default_governance_non_existing.p7s") #define GOV_DI PF_D COMMON_ETC_PATH("default_governance.p7s") @@ -469,8 +429,8 @@ CU_Theory( bool discovery_protection = (i == 0); print_test_msg ("running test access_control_hooks: %s with discovery protection %s\n", init_fn, discovery_protection ? "enabled" : "disabled"); - char * gov_topic_rule = get_governance_topic_rule ("*", discovery_protection, false, true, true, NULL, NULL); - char * gov_config = get_governance_config (false, true, "ENCRYPT", NULL, NULL, gov_topic_rule, true); + char * gov_topic_rule = get_governance_topic_rule ("*", discovery_protection, false, true, true, PK_N, BPK_N); + char * gov_config = get_governance_config (false, true, PK_E, PK_N, PK_N, gov_topic_rule, true); const char * def_perm = PF_F COMMON_ETC_PATH("default_permissions.p7s"); const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); @@ -556,9 +516,9 @@ CU_Theory( get_permissions_grant ("id2", id2_subj, now, now + DDS_SECS(3600), rules2_xml, NULL) }; char * perm_config = get_permissions_config (grants, 2, true); - char * gov_topic_rule = get_governance_topic_rule ("*", false, false, true, true, "NONE", "NONE"); - char * gov_config_pp1 = get_governance_config (false, join_ac_pp1, NULL, NULL, NULL, gov_topic_rule, true); - char * gov_config_pp2 = get_governance_config (false, join_ac_pp2, NULL, NULL, NULL, gov_topic_rule, true); + char * gov_topic_rule = get_governance_topic_rule ("*", false, false, true, true, PK_N, BPK_N); + char * gov_config_pp1 = get_governance_config (false, join_ac_pp1, PK_N, PK_N, PK_N, gov_topic_rule, true); + char * gov_config_pp2 = get_governance_config (false, join_ac_pp2, PK_N, PK_N, PK_N, gov_topic_rule, true); const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); access_control_init ( @@ -624,10 +584,10 @@ static void test_discovery_liveliness_protection(enum test_discovery_liveliness get_permissions_default_grant ("id2", id2_subj, topic_name) }; char * perm_config = get_permissions_config (grants, 2, true); - char * gov_topic_rule1 = get_governance_topic_rule (topic_name, dp && enable_protection_pp1, lp && enable_protection_pp1, true, true, "ENCRYPT", "NONE"); - char * gov_topic_rule2 = get_governance_topic_rule (topic_name, dp && enable_protection_pp2, lp && enable_protection_pp2, true, true, "ENCRYPT", "NONE"); - char * gov_config1 = get_governance_config (false, true, dp ? pk_to_str (protection_kind_pp1) : NULL, lp ? pk_to_str (protection_kind_pp1) : NULL, "ENCRYPT", gov_topic_rule1, true); - char * gov_config2 = get_governance_config (false, true, dp ? pk_to_str (protection_kind_pp2) : NULL, lp ? pk_to_str (protection_kind_pp2) : NULL, "ENCRYPT", gov_topic_rule2, true); + char * gov_topic_rule1 = get_governance_topic_rule (topic_name, dp && enable_protection_pp1, lp && enable_protection_pp1, true, true, PK_E, BPK_N); + char * gov_topic_rule2 = get_governance_topic_rule (topic_name, dp && enable_protection_pp2, lp && enable_protection_pp2, true, true, PK_E, BPK_N); + char * gov_config1 = get_governance_config (false, true, dp ? protection_kind_pp1 : PK_N, lp ? protection_kind_pp1 : PK_N, PK_E, gov_topic_rule1, true); + char * gov_config2 = get_governance_config (false, true, dp ? protection_kind_pp2 : PK_N, lp ? protection_kind_pp2 : PK_N, PK_E, gov_topic_rule2, true); const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); access_control_init ( @@ -705,10 +665,10 @@ static void test_encoding_mismatch( get_permissions_default_grant ("id2", id2_subj, topic_name) }; char * perm_config = get_permissions_config (grants, 2, true); - char * gov_topic_rule1 = get_governance_topic_rule (topic_name, true, true, true, true, pk_to_str (metadata_pk1), bpk_to_str (payload_pk1)); - char * gov_topic_rule2 = get_governance_topic_rule (topic_name, true, true, true, true, pk_to_str (metadata_pk2), bpk_to_str (payload_pk2)); - char * gov_config1 = get_governance_config (false, true, pk_to_str (discovery_pk1), pk_to_str (liveliness_pk1), pk_to_str (rtps_pk1), gov_topic_rule1, true); - char * gov_config2 = get_governance_config (false, true, pk_to_str (discovery_pk2), pk_to_str (liveliness_pk2), pk_to_str (rtps_pk2), gov_topic_rule2, true); + char * gov_topic_rule1 = get_governance_topic_rule (topic_name, true, true, true, true, metadata_pk1, payload_pk1); + char * gov_topic_rule2 = get_governance_topic_rule (topic_name, true, true, true, true, metadata_pk2, payload_pk2); + char * gov_config1 = get_governance_config (false, true, discovery_pk1, liveliness_pk1, rtps_pk1, gov_topic_rule1, true); + char * gov_config2 = get_governance_config (false, true, discovery_pk2, liveliness_pk2, rtps_pk2, gov_topic_rule2, true); const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); access_control_init ( @@ -802,8 +762,8 @@ static void test_readwrite_protection ( get_permissions_grant ("id2", id2_subj, now, now + DDS_SECS(3600), rules_xml, default_policy) }; char * perm_config = get_permissions_config (grants, 2, true); - char * gov_topic_rule = get_governance_topic_rule (topic_name, false, false, read_ac, write_ac, pk_to_str (PK_E), bpk_to_str (BPK_E)); - char * gov_config = get_governance_config (false, true, NULL, NULL, NULL, gov_topic_rule, true); + char * gov_topic_rule = get_governance_topic_rule (topic_name, false, false, read_ac, write_ac, PK_E, BPK_E); + char * gov_config = get_governance_config (false, true, PK_N, PK_N, PK_N, gov_topic_rule, true); const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); access_control_init ( diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index 07d637e..79e9cb2 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -20,6 +20,7 @@ #include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/environ.h" #include "dds/ddsrt/heap.h" +#include "dds/ddsrt/io.h" #include "dds/ddsrt/string.h" #include "dds/ddsi/q_config.h" #include "dds/ddsi/ddsi_domaingv.h" @@ -65,7 +66,7 @@ static const char *config = " " " " " file:" COMMON_ETC_PATH("default_permissions_ca.pem") "" - " " + " " " " " " " " @@ -73,10 +74,21 @@ static const char *config = "
    " ""; +static const char *config_non_secure = + "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" + "" + " " + " 0" + " \\${CYCLONEDDS_PID}" + " " + ""; + + #define DDS_DOMAINID1 0 #define DDS_DOMAINID2 1 #define DEF_PERM_CONF "file:" COMMON_ETC_PATH("default_permissions.p7s") +#define DEF_GOV_CONF "file:" COMMON_ETC_PATH("default_governance.p7s") static dds_entity_t g_domain1; static dds_entity_t g_participant1; @@ -92,56 +104,48 @@ static dds_entity_t g_rd; static uint32_t g_topic_nr = 0; -static void authentication_init( - const char * id1_cert, const char * id1_key, const char * id1_ca, - const char * id2_cert, const char * id2_key, const char * id2_ca, - const char * trusted_ca_dir, const char * perm_config, - bool exp_pp1_fail, bool exp_pp2_fail) +static void init_domain_pp (bool pp_secure, bool exp_pp_fail, + dds_domainid_t domain_id, const char *id_cert, const char * id_key, const char * id_ca, const char * gov_config, const char * perm_config, const char * trusted_ca_dir, + dds_entity_t *domain, dds_entity_t *pp) { - if (perm_config == NULL) - perm_config = DEF_PERM_CONF; - - char * gov_topic_rule = get_governance_topic_rule ("*", false, false, true, true, "NONE", "NONE"); - char * gov_config_signed = get_governance_config (false, false, NULL, NULL, NULL, gov_topic_rule, true); - - struct kvp config_vars1[] = { - { "TEST_IDENTITY_CERTIFICATE", id1_cert, 1 }, - { "TEST_IDENTITY_PRIVATE_KEY", id1_key, 1 }, - { "TEST_IDENTITY_CA_CERTIFICATE", id1_ca, 1 }, - { "TRUSTED_CA_DIR", trusted_ca_dir, 3 }, - { "PERM_CONFIG", perm_config, 1 }, - { "GOVERNANCE_CONFIG", gov_config_signed, 1 }, - { NULL, NULL, 0 } - }; - - struct kvp config_vars2[] = { - { "TEST_IDENTITY_CERTIFICATE", id2_cert, 1 }, - { "TEST_IDENTITY_PRIVATE_KEY", id2_key, 1 }, - { "TEST_IDENTITY_CA_CERTIFICATE", id2_ca, 1 }, - { "TRUSTED_CA_DIR", trusted_ca_dir, 3 }, - { "PERM_CONFIG", perm_config, 1 }, - { "GOVERNANCE_CONFIG", gov_config_signed, 1 }, - { NULL, NULL, 0 } - }; - - char *conf1 = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars1); - char *conf2 = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars2); - CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars1), 0); - CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars2), 0); - g_domain1 = dds_create_domain (DDS_DOMAINID1, conf1); - g_domain2 = dds_create_domain (DDS_DOMAINID2, conf2); - g_participant1 = dds_create_participant (DDS_DOMAINID1, NULL, NULL); - g_participant2 = dds_create_participant (DDS_DOMAINID2, NULL, NULL); - CU_ASSERT_EQUAL_FATAL (exp_pp1_fail, g_participant1 <= 0); - CU_ASSERT_EQUAL_FATAL (exp_pp2_fail, g_participant2 <= 0); - - ddsrt_free (gov_config_signed); - ddsrt_free (gov_topic_rule); - ddsrt_free (conf1); - ddsrt_free (conf2); + char *conf; + if (pp_secure) + { + struct kvp config_vars[] = + { + { "TEST_IDENTITY_CERTIFICATE", id_cert, 1 }, + { "TEST_IDENTITY_PRIVATE_KEY", id_key, 1 }, + { "TEST_IDENTITY_CA_CERTIFICATE", id_ca, 1 }, + { "TRUSTED_CA_DIR", trusted_ca_dir, 3 }, + { "PERMISSIONS_CONFIG", perm_config, 1 }, + { "GOVERNANCE_CONFIG", gov_config, 1 }, + { NULL, NULL, 0 } + }; + conf = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars); + CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars), 0); + } + else + { + struct kvp config_vars[] = { { NULL, NULL, 0 } }; + conf = ddsrt_expand_vars_sh (config_non_secure, &expand_lookup_vars_env, config_vars); + CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars), 0); + } + *domain = dds_create_domain (domain_id, conf); + *pp = dds_create_participant (domain_id, NULL, NULL); + CU_ASSERT_EQUAL_FATAL (exp_pp_fail, *pp <= 0); + ddsrt_free (conf); } -static void authentication_fini(bool delete_pp1, bool delete_pp2) +static void authentication_init( + bool pp1_secure, const char * id1_cert, const char * id1_key, const char * id1_ca, bool exp_pp1_fail, const char * gov_conf1, const char * perm_conf1, + bool pp2_secure, const char * id2_cert, const char * id2_key, const char * id2_ca, bool exp_pp2_fail, const char * gov_conf2, const char * perm_conf2, + const char * trusted_ca_dir) +{ + init_domain_pp (pp1_secure, exp_pp1_fail, DDS_DOMAINID1, id1_cert, id1_key, id1_ca, gov_conf1, perm_conf1, trusted_ca_dir, &g_domain1, &g_participant1); + init_domain_pp (pp2_secure, exp_pp2_fail, DDS_DOMAINID2, id2_cert, id2_key, id2_ca, gov_conf2, perm_conf2, trusted_ca_dir, &g_domain2, &g_participant2); +} + +static void authentication_fini(bool delete_pp1, bool delete_pp2, void * res[], size_t nres) { if (delete_pp1) CU_ASSERT_EQUAL_FATAL (dds_delete (g_participant1), DDS_RETCODE_OK); @@ -149,6 +153,11 @@ static void authentication_fini(bool delete_pp1, bool delete_pp2) CU_ASSERT_EQUAL_FATAL (dds_delete (g_participant2), DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain1), DDS_RETCODE_OK); CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain2), DDS_RETCODE_OK); + if (res != NULL) + { + for (size_t i = 0; i < nres; i++) + ddsrt_free (res[i]); + } } #define FM_CA "error: unable to get local issuer certificate" @@ -185,7 +194,10 @@ CU_Theory((const char * test_descr, const char * id2, const char *key2, const ch struct Handshake *hs_list; int nhs; print_test_msg ("running test id_ca_certs: %s\n", test_descr); - authentication_init (ID1, ID1K, CA1, id2, key2, ca2, NULL, NULL, exp_fail_pp1, exp_fail_pp2); + authentication_init ( + true, ID1, ID1K, CA1, exp_fail_pp1, DEF_GOV_CONF, DEF_PERM_CONF, + true, id2, key2, ca2, exp_fail_pp2, DEF_GOV_CONF, DEF_PERM_CONF, + NULL); // Domain 1 validate_handshake (DDS_DOMAINID1, false, NULL, &hs_list, &nhs, DDS_SECS(2)); @@ -199,7 +211,7 @@ CU_Theory((const char * test_descr, const char * id2, const char *key2, const ch validate_handshake_result (&hs_list[n], exp_fail_hs_req, fail_hs_req_msg, exp_fail_hs_reply, fail_hs_reply_msg); handshake_list_fini (hs_list, nhs); - authentication_fini (!exp_fail_pp1, !exp_fail_pp2); + authentication_fini (!exp_fail_pp1, !exp_fail_pp2, NULL, 0); } CU_TheoryDataPoints(ddssec_authentication, trusted_ca_dir) = { @@ -209,13 +221,16 @@ CU_TheoryDataPoints(ddssec_authentication, trusted_ca_dir) = { CU_Theory((const char * ca_dir, bool exp_fail), ddssec_authentication, trusted_ca_dir) { print_test_msg ("Testing custom CA dir: %s\n", ca_dir); - authentication_init (ID1, ID1K, CA1, ID1, ID1K, CA1, ca_dir, NULL, exp_fail, exp_fail); + authentication_init ( + true, ID1, ID1K, CA1, exp_fail, DEF_GOV_CONF, DEF_PERM_CONF, + true, ID1, ID1K, CA1, exp_fail, DEF_GOV_CONF, DEF_PERM_CONF, + ca_dir); if (!exp_fail) { validate_handshake_nofail (DDS_DOMAINID1, DDS_SECS (2)); validate_handshake_nofail (DDS_DOMAINID2, DDS_SECS (2)); } - authentication_fini (!exp_fail, !exp_fail); + authentication_fini (!exp_fail, !exp_fail, NULL, 0); } #define S(n) (n) @@ -267,7 +282,10 @@ CU_Theory( get_permissions_default_grant ("id1", id1_subj, topic_name), get_permissions_default_grant ("id2", id2_subj, topic_name) }; char * perm_config = get_permissions_config (grants, 2, true); - authentication_init (id1, ID1K, ca, id2, ID1K, ca, NULL, perm_config, id1_local_fail, id2_local_fail); + authentication_init ( + true, id1, ID1K, ca, id1_local_fail, DEF_GOV_CONF, perm_config, + true, id2, ID1K, ca, id2_local_fail, DEF_GOV_CONF, perm_config, + NULL); validate_handshake (DDS_DOMAINID1, id1_local_fail, NULL, NULL, NULL, DDS_SECS(2)); validate_handshake (DDS_DOMAINID2, id2_local_fail, NULL, NULL, NULL, DDS_SECS(2)); if (write_read_dur > 0) @@ -276,17 +294,51 @@ CU_Theory( sync_writer_to_readers(g_participant1, g_wr, 1, DDS_SECS(2)); write_read_for (g_wr, g_participant2, g_rd, DDS_MSECS (write_read_dur), false, exp_read_fail); } - authentication_fini (!id1_local_fail, !id2_local_fail); - ddsrt_free (grants[0]); - ddsrt_free (grants[1]); - ddsrt_free (perm_config); - ddsrt_free (ca); - ddsrt_free (id1_subj); - ddsrt_free (id2_subj); - ddsrt_free (id1); - ddsrt_free (id2); + authentication_fini (!id1_local_fail, !id2_local_fail, (void * []){ grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 8); } #undef D #undef H #undef M + +CU_Test(ddssec_authentication, unauthenticated_pp) +{ + char topic_name_secure[100]; + char topic_name_plain[100]; + create_topic_name ("ddssec_authentication_secure_", g_topic_nr++, topic_name_secure, sizeof (topic_name_secure)); + create_topic_name ("ddssec_authentication_plain_", g_topic_nr++, topic_name_plain, sizeof (topic_name_plain)); + + /* create ca and id1 cert that will not expire during this test */ + char *ca, *id1, *id1_subj; + ca = generate_ca ("ca1", TEST_IDENTITY_CA1_PRIVATE_KEY, 0, 3600); + id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id1_subj); + + char * grants[] = { get_permissions_default_grant ("id1", id1_subj, topic_name_secure) }; + char * perm_config = get_permissions_config (grants, 1, true); + + char * topic_rule_sec = get_governance_topic_rule (topic_name_secure, true, true, true, true, PK_E, BPK_N); + char * topic_rule_plain = get_governance_topic_rule (topic_name_plain, false, false, false, false, PK_N, BPK_N); + char * gov_topic_rules; + ddsrt_asprintf(&gov_topic_rules, "%s%s", topic_rule_sec, topic_rule_plain); + char * gov_config = get_governance_config (true, true, PK_N, PK_N, PK_N, gov_topic_rules, true); + + authentication_init ( + true, id1, TEST_IDENTITY1_PRIVATE_KEY, ca, false, gov_config, perm_config, + false, NULL, NULL, NULL, false, NULL, NULL, + NULL); + + print_test_msg ("writing sample for plain topic\n"); + dds_entity_t pub, sub, pub_tp, sub_tp, wr, rd; + rd_wr_init (g_participant1, &pub, &pub_tp, &wr, g_participant2, &sub, &sub_tp, &rd, topic_name_plain); + sync_writer_to_readers(g_participant1, wr, 1, DDS_SECS(5)); + write_read_for (wr, g_participant2, rd, DDS_MSECS (10), false, false); + + print_test_msg ("writing sample for secured topic\n"); + dds_entity_t spub, ssub, spub_tp, ssub_tp, swr, srd; + rd_wr_init (g_participant1, &spub, &spub_tp, &swr, g_participant2, &ssub, &ssub_tp, &srd, topic_name_secure); + sync_writer_to_readers(g_participant1, swr, 0, DDS_SECS(2)); + write_read_for (swr, g_participant2, srd, DDS_MSECS (10), false, true); + + authentication_fini (true, true, (void * []) { gov_config, gov_topic_rules, topic_rule_sec, topic_rule_plain, grants[0], perm_config, ca, id1_subj, id1 }, 9); +} + diff --git a/src/security/core/tests/common/security_config_test_utils.c b/src/security/core/tests/common/security_config_test_utils.c index 8c46848..ea8158b 100644 --- a/src/security/core/tests/common/security_config_test_utils.c +++ b/src/security/core/tests/common/security_config_test_utils.c @@ -245,7 +245,7 @@ static void print_config_vars(struct kvp *vars) } char * get_governance_topic_rule(const char * topic_expr, bool discovery_protection, bool liveliness_protection, - bool read_ac, bool write_ac, const char * metadata_protection_kind, const char * data_protection_kind) + bool read_ac, bool write_ac, DDS_Security_ProtectionKind metadata_protection_kind, DDS_Security_BasicProtectionKind data_protection_kind) { struct kvp vars[] = { { "TOPIC_EXPRESSION", topic_expr != NULL ? topic_expr : "*", 1 }, @@ -253,23 +253,23 @@ char * get_governance_topic_rule(const char * topic_expr, bool discovery_protect { "ENABLE_LIVELINESS_PROTECTION", liveliness_protection ? "true" : "false", 1 }, { "ENABLE_READ_AC", read_ac ? "true" : "false", 1 }, { "ENABLE_WRITE_AC", write_ac ? "true" : "false", 1 }, - { "METADATA_PROTECTION_KIND", metadata_protection_kind != NULL ? metadata_protection_kind : "NONE", 1 }, - { "DATA_PROTECTION_KIND", data_protection_kind != NULL ? data_protection_kind : "NONE", 1 }, + { "METADATA_PROTECTION_KIND", pk_to_str (metadata_protection_kind), 1 }, + { "DATA_PROTECTION_KIND", bpk_to_str (data_protection_kind), 1 }, { NULL, NULL, 0 } }; return ddsrt_expand_vars (topic_rule, &expand_lookup_vars, vars); } -char * get_governance_config (bool allow_unauth_pp, bool enable_join_ac, const char * discovery_protection_kind, const char * liveliness_protection_kind, - const char * rtps_protection_kind, const char * topic_rules, bool add_prefix) +char * get_governance_config (bool allow_unauth_pp, bool enable_join_ac, DDS_Security_ProtectionKind discovery_protection_kind, DDS_Security_ProtectionKind liveliness_protection_kind, + DDS_Security_ProtectionKind rtps_protection_kind, const char * topic_rules, bool add_prefix) { struct kvp vars[] = { { "ALLOW_UNAUTH_PP", allow_unauth_pp ? "true" : "false", 1 }, { "ENABLE_JOIN_AC", enable_join_ac ? "true" : "false", 1 }, - { "DISCOVERY_PROTECTION_KIND", discovery_protection_kind != NULL ? discovery_protection_kind : "NONE", 1 }, - { "LIVELINESS_PROTECTION_KIND", liveliness_protection_kind != NULL ? liveliness_protection_kind : "NONE", 1 }, - { "RTPS_PROTECTION_KIND", rtps_protection_kind != NULL ? rtps_protection_kind : "NONE", 1 }, - { "TOPIC_RULES", topic_rules != NULL ? topic_rules : get_governance_topic_rule (NULL, false, false, false, false, NULL, NULL), 1 }, + { "DISCOVERY_PROTECTION_KIND", pk_to_str (discovery_protection_kind), 1 }, + { "LIVELINESS_PROTECTION_KIND", pk_to_str (liveliness_protection_kind), 1 }, + { "RTPS_PROTECTION_KIND", pk_to_str (rtps_protection_kind), 1 }, + { "TOPIC_RULES", topic_rules != NULL ? topic_rules : get_governance_topic_rule (NULL, false, false, false, false, PK_N, BPK_N), 1 }, { NULL, NULL, 0 } }; char * config = ddsrt_expand_vars (governance_xml, &expand_lookup_vars, vars); diff --git a/src/security/core/tests/common/security_config_test_utils.h b/src/security/core/tests/common/security_config_test_utils.h index e70b98e..eaac17b 100644 --- a/src/security/core/tests/common/security_config_test_utils.h +++ b/src/security/core/tests/common/security_config_test_utils.h @@ -26,9 +26,9 @@ const char * expand_lookup_vars_env (const char *name, void * data); int32_t expand_lookup_unmatched (const struct kvp * lookup_table); char * get_governance_topic_rule (const char * topic_expr, bool discovery_protection, bool liveliness_protection, - bool read_ac, bool write_ac, const char * metadata_protection_kind, const char * data_protection_kind); -char * get_governance_config (bool allow_unauth_pp, bool enable_join_ac, const char * discovery_protection_kind, const char * liveliness_protection_kind, - const char * rtps_protection_kind, const char * topic_rules, bool add_prefix); + bool read_ac, bool write_ac, DDS_Security_ProtectionKind metadata_protection_kind, DDS_Security_BasicProtectionKind data_protection_kind); +char * get_governance_config (bool allow_unauth_pp, bool enable_join_ac, DDS_Security_ProtectionKind discovery_protection_kind, DDS_Security_ProtectionKind liveliness_protection_kind, + DDS_Security_ProtectionKind rtps_protection_kind, const char * topic_rules, bool add_prefix); char * get_permissions_rules (const char * domain_id, const char * allow_pub_topic, const char * allow_sub_topic, const char * deny_pub_topic, const char * deny_sub_topic); diff --git a/src/security/core/tests/common/test_utils.c b/src/security/core/tests/common/test_utils.c index 89d22f3..eff8f51 100644 --- a/src/security/core/tests/common/test_utils.c +++ b/src/security/core/tests/common/test_utils.c @@ -538,3 +538,37 @@ const char * bpk_to_str(DDS_Security_BasicProtectionKind bpk) assert (false); return NULL; } + +DDS_Security_DatawriterCryptoHandle get_builtin_writer_crypto_handle(dds_entity_t participant, unsigned entityid) +{ + DDS_Security_DatawriterCryptoHandle crypto_handle; + struct dds_entity *pp_entity; + struct participant *pp; + struct writer *wr; + CU_ASSERT_EQUAL_FATAL(dds_entity_pin(participant, &pp_entity), 0); + thread_state_awake(lookup_thread_state(), &pp_entity->m_domain->gv); + pp = entidx_lookup_participant_guid(pp_entity->m_domain->gv.entity_index, &pp_entity->m_guid); + wr = get_builtin_writer(pp, entityid); + CU_ASSERT_FATAL(wr != NULL); + assert(wr != NULL); /* for Clang's static analyzer */ + crypto_handle = wr->sec_attr->crypto_handle; + thread_state_asleep(lookup_thread_state()); + dds_entity_unpin(pp_entity); + return crypto_handle; +} + +DDS_Security_DatawriterCryptoHandle get_writer_crypto_handle(dds_entity_t writer) +{ + DDS_Security_DatawriterCryptoHandle crypto_handle; + struct dds_entity *wr_entity; + struct writer *wr; + CU_ASSERT_EQUAL_FATAL(dds_entity_pin(writer, &wr_entity), 0); + thread_state_awake(lookup_thread_state(), &wr_entity->m_domain->gv); + wr = entidx_lookup_writer_guid(wr_entity->m_domain->gv.entity_index, &wr_entity->m_guid); + CU_ASSERT_FATAL(wr != NULL); + assert(wr != NULL); /* for Clang's static analyzer */ + crypto_handle = wr->sec_attr->crypto_handle; + thread_state_asleep(lookup_thread_state()); + dds_entity_unpin(wr_entity); + return crypto_handle; +} diff --git a/src/security/core/tests/common/test_utils.h b/src/security/core/tests/common/test_utils.h index 2a68327..7fe1487 100644 --- a/src/security/core/tests/common/test_utils.h +++ b/src/security/core/tests/common/test_utils.h @@ -26,6 +26,9 @@ #define BPK_S DDS_SECURITY_BASICPROTECTION_KIND_SIGN #define BPK_E DDS_SECURITY_BASICPROTECTION_KIND_ENCRYPT +#define PF_F "file:" +#define PF_D "data:," + #define MAX_LOCAL_IDENTITIES 8 #define MAX_REMOTE_IDENTITIES 8 #define MAX_HANDSHAKES 32 @@ -82,5 +85,7 @@ void write_read_for (dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_d struct dds_security_cryptography_impl * get_crypto_context (dds_entity_t participant); const char * pk_to_str (DDS_Security_ProtectionKind pk); const char * bpk_to_str (DDS_Security_BasicProtectionKind bpk); +DDS_Security_DatawriterCryptoHandle get_builtin_writer_crypto_handle(dds_entity_t participant, unsigned entityid); +DDS_Security_DatawriterCryptoHandle get_writer_crypto_handle(dds_entity_t writer); #endif /* SECURITY_CORE_TEST_UTILS_H_ */ diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index 4b3e790..94f8c13 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -154,9 +154,8 @@ static void test_init(const struct domain_sec_config * domain_config, size_t n_s assert (n_pub_domains < MAX_DOMAINS); assert (n_pub_participants < MAX_PARTICIPANTS); - char * gov_topic_rule = get_governance_topic_rule ("*", true, true, true, true, pk_to_str (domain_config->metadata_pk), bpk_to_str (domain_config->payload_pk)); - char * gov_config_signed = get_governance_config (false, true, pk_to_str (domain_config->discovery_pk), pk_to_str (domain_config->liveliness_pk), - pk_to_str (domain_config->rtps_pk), gov_topic_rule, false); + char * gov_topic_rule = get_governance_topic_rule ("*", true, true, true, true, domain_config->metadata_pk, domain_config->payload_pk); + char * gov_config_signed = get_governance_config (false, true, domain_config->discovery_pk, domain_config->liveliness_pk, domain_config->rtps_pk, gov_topic_rule, false); struct kvp config_vars[] = { { "GOVERNANCE_DATA", gov_config_signed, 1 }, From 9ba54c70e73255ae46d85587936954eeb3ab1f65 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Mon, 11 May 2020 21:49:16 +0200 Subject: [PATCH 189/238] Don't accept plain payload in case payload encryption or payload signing is enabled in the security settings. And fixed a typo in writer not allowed message Signed-off-by: Dennis Potman --- src/core/ddsi/src/ddsi_security_omg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 7824239..a0d186a 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -1469,7 +1469,7 @@ bool q_omg_security_check_create_writer(struct participant *pp, uint32_t domain_ result = sc->access_control_context->check_create_datawriter(sc->access_control_context, pp->sec_attr->permissions_handle, (DDS_Security_DomainId)domain_id, topic_name, &security_qos, &partitions, NULL, &exception); if (!result) - handle_not_allowed(pp->e.gv, pp->sec_attr->permissions_handle, sc->access_control_context, &exception, topic_name, "Local topic permission denied"); + handle_not_allowed(pp->e.gv, pp->sec_attr->permissions_handle, sc->access_control_context, &exception, topic_name, "Writer is not permitted"); q_omg_shallow_free_security_qos(&security_qos); g_omg_shallow_free_StringSeq(&partitions.name); @@ -3340,7 +3340,7 @@ static bool decode_payload (const struct ddsi_domaingv *gv, struct nn_rsample_in if (!q_omg_security_decode_serialized_payload (sampleinfo->pwr, payloadp, *payloadsz, &dst_buf, &dst_len)) { GVTRACE ("decode_payload: failed to decrypt data from "PGUIDFMT"\n", PGUID (sampleinfo->pwr->e.guid)); - return true; + return false; } /* Expect result to always fit into the original buffer. */ From cf75263d1da2b326f5e4e152a2b5c131e3f75c18 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Mon, 11 May 2020 21:53:56 +0200 Subject: [PATCH 190/238] Add a test that validates that a plain message is not read by a remote reader in case payload/submsg/rtps encryption or signing is enabled Signed-off-by: Dennis Potman --- src/security/core/tests/CMakeLists.txt | 1 + .../core/tests/common/cryptography_wrapper.c | 133 ++++++++++++-- .../core/tests/common/cryptography_wrapper.h | 8 +- src/security/core/tests/crypto.c | 170 ++++++++++++++++++ 4 files changed, 298 insertions(+), 14 deletions(-) create mode 100644 src/security/core/tests/crypto.c diff --git a/src/security/core/tests/CMakeLists.txt b/src/security/core/tests/CMakeLists.txt index 299487e..19fc14a 100644 --- a/src/security/core/tests/CMakeLists.txt +++ b/src/security/core/tests/CMakeLists.txt @@ -79,6 +79,7 @@ if(ENABLE_SSL) "authentication.c" "access_control.c" "config.c" + "crypto.c" "handshake.c" "plugin_loading.c" "secure_communication.c" diff --git a/src/security/core/tests/common/cryptography_wrapper.c b/src/security/core/tests/common/cryptography_wrapper.c index 990e2c8..ada7591 100644 --- a/src/security/core/tests/common/cryptography_wrapper.c +++ b/src/security/core/tests/common/cryptography_wrapper.c @@ -33,7 +33,8 @@ enum crypto_plugin_mode { PLUGIN_MODE_ALL_OK, PLUGIN_MODE_MISSING_FUNC, PLUGIN_MODE_WRAPPED, - PLUGIN_MODE_TOKEN_LOG + PLUGIN_MODE_TOKEN_LOG, + PLUGIN_MODE_PLAIN_DATA }; struct dds_security_crypto_key_exchange_impl { @@ -76,6 +77,10 @@ struct dds_security_cryptography_impl { struct ddsrt_circlist token_data_list; ddsrt_mutex_t encode_decode_log_lock; struct ddsrt_circlist encode_decode_log; + bool force_plain_rtps; + bool force_plain_submsg; + bool force_plain_payload; + DDS_Security_DatawriterCryptoHandle force_plain_sender_handle; }; static DDS_Security_ParticipantCryptoHandle g_local_participant_handle = 0; @@ -120,6 +125,16 @@ void set_entity_data_secret(struct dds_security_cryptography_impl * impl, const impl->ep_secret = ep_secret; } +void set_force_plain_data(struct dds_security_cryptography_impl * impl, DDS_Security_DatawriterCryptoHandle handle, bool plain_rtps, bool plain_submsg, bool plain_payload) +{ + assert (impl); + assert (impl->mode == PLUGIN_MODE_PLAIN_DATA); + impl->force_plain_rtps = plain_rtps; + impl->force_plain_submsg = plain_submsg; + impl->force_plain_payload = plain_payload; + impl->force_plain_sender_handle = handle; +} + static bool check_crypto_tokens(const DDS_Security_DataHolderSeq *tokens) { bool result = true; @@ -371,6 +386,20 @@ static bool expect_encrypted_buffer (DDS_Security_ProtectionKind pk) return pk == DDS_SECURITY_PROTECTION_KIND_ENCRYPT || pk == DDS_SECURITY_PROTECTION_KIND_ENCRYPT_WITH_ORIGIN_AUTHENTICATION; } +static void copy_octetseq(DDS_Security_OctetSeq *encoded_submsg, const DDS_Security_OctetSeq *plain_submsg) +{ + encoded_submsg->_length = encoded_submsg->_maximum = plain_submsg->_length; + if (plain_submsg->_length > 0) + { + encoded_submsg->_buffer = ddsrt_malloc(encoded_submsg->_length); + memcpy(encoded_submsg->_buffer, plain_submsg->_buffer, encoded_submsg->_length); + } + else + { + encoded_submsg->_buffer = NULL; + } +} + /** * Crypto key exchange */ @@ -386,6 +415,7 @@ static DDS_Security_boolean create_local_participant_crypto_tokens( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: { DDS_Security_boolean ret = impl->instance->create_local_participant_crypto_tokens (impl->instance, local_participant_crypto_tokens, local_participant_crypto, remote_participant_crypto, ex); @@ -410,6 +440,7 @@ static DDS_Security_boolean set_remote_participant_crypto_tokens( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: { DDS_Security_boolean ret = impl->instance->set_remote_participant_crypto_tokens (impl->instance, check_handle (local_participant_crypto), check_handle (remote_participant_crypto), remote_participant_tokens, ex); @@ -434,6 +465,7 @@ static DDS_Security_boolean create_local_datawriter_crypto_tokens( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: { DDS_Security_boolean ret = impl->instance->create_local_datawriter_crypto_tokens (impl->instance, local_datawriter_crypto_tokens, check_handle (local_datawriter_crypto), check_handle (remote_datareader_crypto), ex); @@ -458,6 +490,7 @@ static DDS_Security_boolean set_remote_datawriter_crypto_tokens( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: { DDS_Security_boolean ret = impl->instance->set_remote_datawriter_crypto_tokens (impl->instance, check_handle (local_datareader_crypto), check_handle (remote_datawriter_crypto), remote_datawriter_tokens, ex); @@ -482,6 +515,7 @@ static DDS_Security_boolean create_local_datareader_crypto_tokens( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: { DDS_Security_boolean ret = impl->instance->create_local_datareader_crypto_tokens (impl->instance, local_datareader_cryto_tokens, check_handle (local_datareader_crypto), check_handle (remote_datawriter_crypto), ex); @@ -506,6 +540,7 @@ static DDS_Security_boolean set_remote_datareader_crypto_tokens( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: { DDS_Security_boolean ret = impl->instance->set_remote_datareader_crypto_tokens (impl->instance, check_handle (local_datawriter_crypto), check_handle (remote_datareader_crypto), remote_datareader_tokens, ex); @@ -528,6 +563,7 @@ static DDS_Security_boolean return_crypto_tokens( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: return impl->instance->return_crypto_tokens (impl->instance, crypto_tokens, ex); default: return true; @@ -550,6 +586,7 @@ static DDS_Security_ParticipantCryptoHandle register_local_participant( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: return check_handle (impl->instance->register_local_participant (impl->instance, check_handle (participant_identity), check_handle (participant_permissions), participant_properties, participant_security_attributes, ex)); default: @@ -570,6 +607,7 @@ static DDS_Security_ParticipantCryptoHandle register_matched_remote_participant( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: return check_handle (impl->instance->register_matched_remote_participant (impl->instance, local_participant_crypto_handle, remote_participant_identity, remote_participant_permissions, shared_secret, ex)); default: @@ -589,6 +627,7 @@ static DDS_Security_DatawriterCryptoHandle register_local_datawriter( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: return check_handle (impl->instance->register_local_datawriter (impl->instance, check_handle (participant_crypto), datawriter_properties, datawriter_security_attributes, ex)); default: @@ -609,6 +648,7 @@ static DDS_Security_DatareaderCryptoHandle register_matched_remote_datareader( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: return check_handle (impl->instance->register_matched_remote_datareader (impl->instance, check_handle (local_datawriter_crypto_handle), check_handle (remote_participant_crypto), check_handle (shared_secret), relay_only, ex)); default: @@ -628,6 +668,7 @@ static DDS_Security_DatareaderCryptoHandle register_local_datareader( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: return check_handle (impl->instance->register_local_datareader (impl->instance, check_handle (participant_crypto), datareader_properties, datareader_security_attributes, ex)); default: @@ -647,6 +688,7 @@ static DDS_Security_DatawriterCryptoHandle register_matched_remote_datawriter( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: return check_handle (impl->instance->register_matched_remote_datawriter (impl->instance, check_handle (local_datareader_crypto_handle), check_handle (remote_participant_crypt), shared_secret, ex)); default: @@ -664,6 +706,7 @@ static DDS_Security_boolean unregister_participant( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: return impl->instance->unregister_participant (impl->instance, check_handle (participant_crypto_handle), ex); default: return true; @@ -680,6 +723,7 @@ static DDS_Security_boolean unregister_datawriter( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: return impl->instance->unregister_datawriter (impl->instance, check_handle (datawriter_crypto_handle), ex); default: return true; @@ -696,6 +740,7 @@ static DDS_Security_boolean unregister_datareader( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: return impl->instance->unregister_datareader (impl->instance, check_handle (datareader_crypto_handle), ex); default: return true; @@ -716,6 +761,13 @@ static DDS_Security_boolean encode_serialized_payload( struct dds_security_crypto_transform_impl *impl = (struct dds_security_crypto_transform_impl *)instance; switch (impl->parent->mode) { + case PLUGIN_MODE_PLAIN_DATA: + if (impl->parent->force_plain_payload && impl->parent->force_plain_sender_handle == sending_datawriter_crypto) + { + copy_octetseq (encoded_buffer, plain_buffer); + return true; + } + /* fall through */ case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: { @@ -771,6 +823,15 @@ static DDS_Security_boolean encode_datawriter_submessage( struct dds_security_crypto_transform_impl *impl = (struct dds_security_crypto_transform_impl *)instance; switch (impl->parent->mode) { + case PLUGIN_MODE_PLAIN_DATA: + if (impl->parent->force_plain_submsg && impl->parent->force_plain_sender_handle == sending_datawriter_crypto) + { + copy_octetseq (encoded_rtps_submessage, plain_rtps_submessage); + assert (receiving_datareader_crypto_list->_length <= INT32_MAX); + *receiving_datareader_crypto_list_index = (int32_t) receiving_datareader_crypto_list->_length; + return true; + } + /* fall through */ case PLUGIN_MODE_WRAPPED: log_encode_decode (impl->parent, ENCODE_DATAWRITER_SUBMESSAGE, sending_datawriter_crypto); /* fall-through */ @@ -821,6 +882,13 @@ static DDS_Security_boolean encode_datareader_submessage( struct dds_security_crypto_transform_impl *impl = (struct dds_security_crypto_transform_impl *)instance; switch (impl->parent->mode) { + case PLUGIN_MODE_PLAIN_DATA: + if (impl->parent->force_plain_submsg && impl->parent->force_plain_sender_handle == sending_datareader_crypto) + { + copy_octetseq (encoded_rtps_submessage, plain_rtps_submessage); + return true; + } + /* fall through */ case PLUGIN_MODE_WRAPPED: log_encode_decode (impl->parent, ENCODE_DATAREADER_SUBMESSAGE, sending_datareader_crypto); /* fall-through */ @@ -846,6 +914,15 @@ static DDS_Security_boolean encode_rtps_message( struct dds_security_crypto_transform_impl *impl = (struct dds_security_crypto_transform_impl *)instance; switch (impl->parent->mode) { + case PLUGIN_MODE_PLAIN_DATA: + if (impl->parent->force_plain_rtps) + { + copy_octetseq (encoded_rtps_message, plain_rtps_message); + assert (receiving_participant_crypto_list->_length <= INT32_MAX); + *receiving_participant_crypto_list_index = (int32_t) receiving_participant_crypto_list->_length; + return true; + } + /* fall through */ case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: if (!impl->instance->encode_rtps_message (impl->instance, encoded_rtps_message, @@ -880,6 +957,7 @@ static DDS_Security_boolean decode_rtps_message( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: return impl->instance->decode_rtps_message (impl->instance, plain_buffer, encoded_buffer, check_handle (receiving_participant_crypto), check_handle (sending_participant_crypto), ex); default: @@ -902,6 +980,7 @@ static DDS_Security_boolean preprocess_secure_submsg( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: return impl->instance->preprocess_secure_submsg (impl->instance, datawriter_crypto, datareader_crypto, secure_submessage_category, encoded_rtps_submessage, check_handle (receiving_participant_crypto), check_handle (sending_participant_crypto), ex); default: @@ -920,6 +999,7 @@ static DDS_Security_boolean decode_datawriter_submessage( struct dds_security_crypto_transform_impl *impl = (struct dds_security_crypto_transform_impl *)instance; switch (impl->parent->mode) { + case PLUGIN_MODE_PLAIN_DATA: case PLUGIN_MODE_WRAPPED: log_encode_decode (impl->parent, DECODE_DATAWRITER_SUBMESSAGE, receiving_datareader_crypto); /* fall-through */ @@ -942,6 +1022,7 @@ static DDS_Security_boolean decode_datareader_submessage( struct dds_security_crypto_transform_impl *impl = (struct dds_security_crypto_transform_impl *)instance; switch (impl->parent->mode) { + case PLUGIN_MODE_PLAIN_DATA: case PLUGIN_MODE_WRAPPED: log_encode_decode (impl->parent, DECODE_DATAREADER_SUBMESSAGE, receiving_datawriter_crypto); /* fall-through */ @@ -967,6 +1048,7 @@ static DDS_Security_boolean decode_serialized_payload( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_TOKEN_LOG: + case PLUGIN_MODE_PLAIN_DATA: return impl->instance->decode_serialized_payload(impl->instance, plain_buffer, encoded_buffer, inline_qos, check_handle (receiving_datareader_crypto), check_handle (sending_datawriter_crypto), ex); default: @@ -1075,22 +1157,14 @@ int finalize_test_cryptography_missing_func(void *context) return finalize_test_cryptography_common(impl, false); } -int init_test_cryptography_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv) +static void init_encode_decode_log(struct dds_security_cryptography_impl *impl) { - struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, true, gv); - if (!impl) - return DDS_SECURITY_FAILED; - impl->mode = PLUGIN_MODE_WRAPPED; ddsrt_mutex_init (&impl->encode_decode_log_lock); ddsrt_circlist_init (&impl->encode_decode_log); - *context = impl; - return DDS_SECURITY_SUCCESS; } -int finalize_test_cryptography_wrapped(void *context) +static void fini_encode_decode_log(struct dds_security_cryptography_impl *impl) { - struct dds_security_cryptography_impl* impl = (struct dds_security_cryptography_impl*) context; - assert(impl->mode == PLUGIN_MODE_WRAPPED); ddsrt_mutex_lock (&impl->encode_decode_log_lock); while (!ddsrt_circlist_isempty (&impl->encode_decode_log)) { @@ -1100,6 +1174,24 @@ int finalize_test_cryptography_wrapped(void *context) } ddsrt_mutex_unlock (&impl->encode_decode_log_lock); ddsrt_mutex_destroy (&impl->encode_decode_log_lock); +} + +int init_test_cryptography_wrapped(const char *argument, void **context, struct ddsi_domaingv *gv) +{ + struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, true, gv); + if (!impl) + return DDS_SECURITY_FAILED; + impl->mode = PLUGIN_MODE_WRAPPED; + init_encode_decode_log(impl); + *context = impl; + return DDS_SECURITY_SUCCESS; +} + +int finalize_test_cryptography_wrapped(void *context) +{ + struct dds_security_cryptography_impl* impl = (struct dds_security_cryptography_impl*) context; + assert(impl->mode == PLUGIN_MODE_WRAPPED); + fini_encode_decode_log(impl); return finalize_test_cryptography_common(impl, true); } @@ -1141,3 +1233,22 @@ int32_t finalize_test_cryptography_store_tokens(void *context) return finalize_test_cryptography_common(impl, true); } +int init_test_cryptography_plain_data(const char *argument, void **context, struct ddsi_domaingv *gv) +{ + struct dds_security_cryptography_impl *impl = init_test_cryptography_common(argument, true, gv); + if (!impl) + return DDS_SECURITY_FAILED; + impl->mode = PLUGIN_MODE_PLAIN_DATA; + init_encode_decode_log(impl); + *context = impl; + return DDS_SECURITY_SUCCESS; +} + +int finalize_test_cryptography_plain_data(void *context) +{ + struct dds_security_cryptography_impl* impl = (struct dds_security_cryptography_impl*) context; + assert(impl->mode == PLUGIN_MODE_PLAIN_DATA); + fini_encode_decode_log(impl); + return finalize_test_cryptography_common(impl, true); +} + diff --git a/src/security/core/tests/common/cryptography_wrapper.h b/src/security/core/tests/common/cryptography_wrapper.h index d802247..98a6658 100644 --- a/src/security/core/tests/common/cryptography_wrapper.h +++ b/src/security/core/tests/common/cryptography_wrapper.h @@ -62,15 +62,13 @@ SECURITY_EXPORT void set_protection_kinds( DDS_Security_ProtectionKind rtps_protection_kind, DDS_Security_ProtectionKind metadata_protection_kind, DDS_Security_BasicProtectionKind payload_protection_kind); - SECURITY_EXPORT void set_encrypted_secret(struct dds_security_cryptography_impl * impl, const char * secret); - SECURITY_EXPORT void set_disc_protection_kinds( struct dds_security_cryptography_impl * impl, DDS_Security_ProtectionKind disc_protection_kind, DDS_Security_ProtectionKind liveliness_protection_kind); - SECURITY_EXPORT void set_entity_data_secret(struct dds_security_cryptography_impl * impl, const char * pp_secret, const char * groupdata_secret, const char * ep_secret); +SECURITY_EXPORT void set_force_plain_data(struct dds_security_cryptography_impl * impl, DDS_Security_DatawriterCryptoHandle wr_handle, bool plain_rtps, bool plain_submsg, bool plain_payload); SECURITY_EXPORT const char *get_crypto_token_type_str (enum crypto_tokens_type type); SECURITY_EXPORT struct ddsrt_circlist * get_crypto_tokens (struct dds_security_cryptography_impl * impl); @@ -93,4 +91,8 @@ SECURITY_EXPORT int finalize_test_cryptography_wrapped(void *context); SECURITY_EXPORT int32_t init_test_cryptography_store_tokens(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int32_t finalize_test_cryptography_store_tokens(void *context); +/* Init in plain-data mode (force plain data for payload, submsg and/or rtps) */ +SECURITY_EXPORT int init_test_cryptography_plain_data(const char *argument, void **context, struct ddsi_domaingv *gv); +SECURITY_EXPORT int finalize_test_cryptography_plain_data(void *context); + #endif /* SECURITY_CORE_TEST_CRYPTO_WRAPPER_H_ */ diff --git a/src/security/core/tests/crypto.c b/src/security/core/tests/crypto.c new file mode 100644 index 0000000..098b0d7 --- /dev/null +++ b/src/security/core/tests/crypto.c @@ -0,0 +1,170 @@ +/* + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include + +#include "dds/dds.h" +#include "CUnit/Test.h" +#include "CUnit/Theory.h" + +#include "dds/version.h" +#include "dds/ddsrt/cdtors.h" +#include "dds/ddsrt/environ.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsi/q_config.h" +#include "dds/ddsi/ddsi_domaingv.h" +#include "dds/ddsi/q_misc.h" +#include "dds/ddsi/ddsi_xqos.h" + +#include "dds/security/dds_security_api.h" + +#include "common/config_env.h" +#include "common/cryptography_wrapper.h" +#include "common/test_utils.h" +#include "common/security_config_test_utils.h" +#include "common/test_identity.h" +#include "common/cert_utils.h" + +static const char *config = + "${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}" + "" + " " + " 0" + " \\${CYCLONEDDS_PID}" + " " + " " + " " + " " + " data:,${TEST_IDENTITY_CERTIFICATE}" + " data:,${TEST_IDENTITY_PRIVATE_KEY}" + " data:,${TEST_IDENTITY_CA_CERTIFICATE}" + " " + " " + " " + " " + " file:" COMMON_ETC_PATH("default_permissions_ca.pem") "" + " " + " " + " " + " " + " " + " " + ""; + +#define DDS_DOMAINID1 0 +#define DDS_DOMAINID2 1 + +static dds_entity_t g_domain1; +static dds_entity_t g_participant1; +static dds_entity_t g_domain2; +static dds_entity_t g_participant2; + +static uint32_t g_topic_nr = 0; + +static void init_domain_pp (dds_domainid_t domain_id, const char *id_cert, const char * id_key, const char * id_ca, + const char * gov_config, const char * perm_config, const char * crypto_init, const char * crypto_fini, dds_entity_t *domain, dds_entity_t *pp) +{ + struct kvp config_vars[] = + { + { "TEST_IDENTITY_CERTIFICATE", id_cert, 1 }, + { "TEST_IDENTITY_PRIVATE_KEY", id_key, 1 }, + { "TEST_IDENTITY_CA_CERTIFICATE", id_ca, 1 }, + { "PERMISSIONS_CONFIG", perm_config, 1 }, + { "GOVERNANCE_CONFIG", gov_config, 1 }, + { "CRYPTO_INIT", crypto_init, 1 }, + { "CRYPTO_FINI", crypto_fini, 1 }, + { NULL, NULL, 0 } + }; + char *conf = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars); + CU_ASSERT_EQUAL_FATAL (expand_lookup_unmatched (config_vars), 0); + *domain = dds_create_domain (domain_id, conf); + *pp = dds_create_participant (domain_id, NULL, NULL); + CU_ASSERT_FATAL (*pp > 0); + ddsrt_free (conf); +} + +static void crypto_init ( + const char * gov_config1, const char * perm_config1, const char * id_cert1, const char * id_key1, const char * crypto_init1, const char * crypto_fini1, + const char * gov_config2, const char * perm_config2, const char * id_cert2, const char * id_key2, const char * crypto_init2, const char * crypto_fini2, + const char * id_ca) +{ + init_domain_pp (DDS_DOMAINID1, id_cert1, id_key1, id_ca, gov_config1, perm_config1, crypto_init1, crypto_fini1, &g_domain1, &g_participant1); + init_domain_pp (DDS_DOMAINID2, id_cert2, id_key2, id_ca, gov_config2, perm_config2, crypto_init2, crypto_fini2, &g_domain2, &g_participant2); +} + +static void crypto_fini (void * res[], size_t nres) +{ + CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain1), DDS_RETCODE_OK); + CU_ASSERT_EQUAL_FATAL (dds_delete (g_domain2), DDS_RETCODE_OK); + if (res != NULL) + { + for (size_t i = 0; i < nres; i++) + ddsrt_free (res[i]); + } +} + +CU_TheoryDataPoints(ddssec_crypto, inject_plain_data) = { + CU_DataPoints(const char *, + /* */"payload encrypt", + /* | */"payload sign", + /* | | */"submessage encrypt", + /* | | | */"submessage sign", + /* | | | | */"rtps encrypt", + /* | | | | | */"rtps sign"), + CU_DataPoints(DDS_Security_BasicProtectionKind, BPK_E, BPK_S, BPK_N, BPK_N, BPK_N, BPK_N), /* payload protection */ + CU_DataPoints(DDS_Security_ProtectionKind, PK_N, PK_N, PK_E, PK_S, PK_N, PK_N), /* submessage protection */ + CU_DataPoints(DDS_Security_ProtectionKind, PK_N, PK_N, PK_N, PK_N, PK_E, PK_S), /* rtps protection */ +}; +CU_Theory((const char * test_descr, DDS_Security_BasicProtectionKind payload_pk, DDS_Security_ProtectionKind submsg_pk, DDS_Security_ProtectionKind rtps_pk), + ddssec_crypto, inject_plain_data, .timeout=30) +{ + print_test_msg ("running test inject_plain_data: %s\n", test_descr); + + char topic_name[100]; + create_topic_name ("ddssec_crypto_", g_topic_nr++, topic_name, sizeof (topic_name)); + + char *ca, *id1, *id1_subj, *id2, *id2_subj; + ca = generate_ca ("ca1", TEST_IDENTITY_CA1_PRIVATE_KEY, 0, 3600); + id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id1_subj); + id2 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id2", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id2_subj); + + char * grants[] = { + get_permissions_default_grant ("id1", id1_subj, topic_name), + get_permissions_default_grant ("id2", id2_subj, topic_name) }; + char * perm_config = get_permissions_config (grants, 2, true); + + char * gov_topic_rule = get_governance_topic_rule (topic_name, false, false, false, false, submsg_pk, payload_pk); + char * gov_config = get_governance_config (false, true, PK_N, PK_N, rtps_pk, gov_topic_rule, true); + + crypto_init ( + gov_config, perm_config, id1, TEST_IDENTITY1_PRIVATE_KEY, "init_test_cryptography_plain_data", "finalize_test_cryptography_plain_data", + gov_config, perm_config, id2, TEST_IDENTITY1_PRIVATE_KEY, "init_test_cryptography_wrapped", "finalize_test_cryptography_wrapped", + ca); + + dds_entity_t pub, sub, pub_tp, sub_tp, wr, rd; + rd_wr_init (g_participant1, &pub, &pub_tp, &wr, g_participant2, &sub, &sub_tp, &rd, topic_name); + + /* set forced plain data for payload/submsg/rtps */ + DDS_Security_DatawriterCryptoHandle wr_handle = get_writer_crypto_handle (wr); + struct dds_security_cryptography_impl * crypto_impl = get_crypto_context (g_participant1); + set_force_plain_data (crypto_impl, wr_handle, rtps_pk != PK_N, submsg_pk != PK_N, payload_pk != BPK_N); + + /* sync and write/take sample */ + sync_writer_to_readers (g_participant1, wr, 1, DDS_SECS (2)); + write_read_for (wr, g_participant2, rd, DDS_MSECS (10), false, true); + + /* reset forced plain data */ + set_force_plain_data (crypto_impl, wr_handle, false, false, false); + + crypto_fini ((void * []) { gov_config, gov_topic_rule, grants[0], grants[1], perm_config, ca, id1_subj, id1, id2_subj, id2 }, 10); +} From edcbe1b22e3bea4c93261df7906bccc5ef7840a1 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 12 May 2020 20:28:11 +0200 Subject: [PATCH 191/238] Add a test that checks if all tokens and attributes are returned to the access control plugin Signed-off-by: Dennis Potman --- .../ddsi/include/dds/ddsi/ddsi_security_omg.h | 4 +- src/core/ddsi/src/ddsi_security_omg.c | 21 ++- src/security/core/tests/access_control.c | 45 ++++- .../tests/common/access_control_wrapper.c | 166 +++++++++++++++++- .../tests/common/access_control_wrapper.h | 9 + src/security/core/tests/common/test_utils.c | 33 ++-- src/security/core/tests/common/test_utils.h | 8 +- src/security/core/tests/crypto.c | 2 +- src/security/core/tests/handshake.c | 4 +- .../core/tests/secure_communication.c | 2 +- 10 files changed, 260 insertions(+), 34 deletions(-) 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 e7c3214..460a4ad 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h @@ -109,8 +109,8 @@ struct reader_sec_attributes { bool plugin_attr; }; -struct dds_security_authentication *q_omg_participant_get_authentication(const struct participant *pp); - +DDS_EXPORT struct dds_security_access_control *q_omg_participant_get_access_control(const struct participant *pp); +DDS_EXPORT struct dds_security_authentication *q_omg_participant_get_authentication(const struct participant *pp); DDS_EXPORT struct dds_security_cryptography *q_omg_participant_get_cryptography(const struct participant *pp); void q_omg_vlog_exception(const struct ddsrt_log_cfg *lc, uint32_t cat, DDS_Security_SecurityException *exception, const char *file, uint32_t line, const char *func, const char *fmt, va_list ap); diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index a0d186a..d064105 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -284,6 +284,13 @@ static struct dds_security_context * q_omg_security_get_secure_context(const str return NULL; } +struct dds_security_access_control *q_omg_participant_get_access_control(const struct participant *pp) +{ + if (pp && pp->e.gv->security_context && q_omg_is_security_loaded(pp->e.gv->security_context)) + return pp->e.gv->security_context->access_control_context; + return NULL; +} + struct dds_security_authentication *q_omg_participant_get_authentication(const struct participant *pp) { if (pp && pp->e.gv->security_context && q_omg_is_security_loaded(pp->e.gv->security_context)) @@ -291,6 +298,13 @@ struct dds_security_authentication *q_omg_participant_get_authentication(const s return NULL; } +struct dds_security_cryptography *q_omg_participant_get_cryptography(const struct participant *pp) +{ + if (pp && pp->e.gv->security_context && q_omg_is_security_loaded(pp->e.gv->security_context)) + return pp->e.gv->security_context->crypto_context; + return NULL; +} + static struct dds_security_context * q_omg_security_get_secure_context_from_proxypp(const struct proxy_participant *proxypp) { if (proxypp && proxypp->e.gv->security_context && q_omg_is_security_loaded(proxypp->e.gv->security_context)) @@ -705,13 +719,6 @@ get_first_matched_proxypp_crypto_handle(struct participant_sec_attributes *attr) return handle; } -struct dds_security_cryptography *q_omg_participant_get_cryptography(const struct participant *pp) -{ - if (pp && pp->e.gv->security_context && q_omg_is_security_loaded(pp->e.gv->security_context)) - return pp->e.gv->security_context->crypto_context; - return NULL; -} - bool q_omg_is_security_loaded (dds_security_context *sc) { return (sc->crypto_context != NULL || sc->authentication_context != NULL || sc->access_control_context != NULL); diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index ea08591..19912ea 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -613,7 +613,7 @@ static void test_discovery_liveliness_protection(enum test_discovery_liveliness print_test_msg ("crypto handle for %s: %ld\n", builtin_wr_descr, secure_pub_wr_handle); CU_ASSERT_EQUAL_FATAL (exp_secure_pub_wr_handle, secure_pub_wr_handle != 0); - struct dds_security_cryptography_impl * crypto_context_pub = get_crypto_context (g_participant[0]); + struct dds_security_cryptography_impl * crypto_context_pub = get_cryptography_context (g_participant[0]); CU_ASSERT_FATAL (crypto_context_pub != NULL); struct crypto_encode_decode_data *log = get_encode_decode_log (crypto_context_pub, ENCODE_DATAWRITER_SUBMESSAGE, secure_pub_wr_handle); @@ -814,3 +814,46 @@ CU_Test(ddssec_access_control, readwrite_protection, .timeout=60) exp_pp_fail, exp_tp_fail, exp_wr_fail, exp_pp_fail, exp_tp_fail, exp_rd_fail, exp_sync_fail, default_deny ? "DENY" : "ALLOW"); } } + + +CU_Test(ddssec_access_control, check_returns) +{ + char topic_name[100]; + create_topic_name ("ddssec_access_control_", g_topic_nr++, topic_name, sizeof (topic_name)); + + char *ca, *id1, *id2, *id1_subj, *id2_subj; + ca = generate_ca ("ca1", TEST_IDENTITY_CA1_PRIVATE_KEY, 0, 3600); + id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id1_subj); + id2 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id2", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id2_subj); + + char * grants[] = { + get_permissions_default_grant ("id1", id1_subj, topic_name), + get_permissions_default_grant ("id2", id2_subj, topic_name) }; + char * perm_config = get_permissions_config (grants, 2, true); + + char * gov_topic_rule = get_governance_topic_rule (NULL, true, true, true, true, PK_E, BPK_E); + char * gov_config = get_governance_config (false, true, PK_E, PK_E, PK_E, gov_topic_rule, true); + const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); + + access_control_init ( + 2, + (const char *[]) { id1, id2 }, + (const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY }, + (const char *[]) { ca, ca }, + (bool []) { false, false }, + (const char *[]) { "init_test_access_control_check_returns", "init_test_access_control_wrapped" }, + (const char *[]) { "finalize_test_access_control_check_returns", "finalize_test_access_control_wrapped" }, + (bool []) { true, true }, (const char *[]) { gov_config, gov_config }, + (bool []) { true, true }, (const char *[]) { perm_config, perm_config }, + (bool []) { true, true }, (const char *[]) { def_perm_ca, def_perm_ca }); + + dds_entity_t pub, sub, pub_tp, sub_tp, wr, rd; + rd_wr_init (g_participant[0], &pub, &pub_tp, &wr, g_participant[1], &sub, &sub_tp, &rd, topic_name); + sync_writer_to_readers (g_participant[0], wr, 1, DDS_SECS (1)); + sync_reader_to_writers (g_participant[1], rd, 1, DDS_SECS (1)); + + struct dds_security_access_control_impl * ac_context = get_access_control_context (g_participant[0]); + CU_ASSERT_FATAL (check_returns (ac_context)); + + access_control_fini (2, (void * []) { gov_config, gov_topic_rule, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 10); +} diff --git a/src/security/core/tests/common/access_control_wrapper.c b/src/security/core/tests/common/access_control_wrapper.c index 327dae3..7a80087 100644 --- a/src/security/core/tests/common/access_control_wrapper.c +++ b/src/security/core/tests/common/access_control_wrapper.c @@ -12,6 +12,7 @@ #include #include #include "dds/dds.h" +#include "dds/ddsrt/circlist.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" #include "dds/ddsrt/string.h" @@ -27,7 +28,8 @@ enum ac_plugin_mode { PLUGIN_MODE_ALL_OK, PLUGIN_MODE_WRAPPED, PLUGIN_MODE_NOT_ALLOWED, - PLUGIN_MODE_MISSING_FUNC + PLUGIN_MODE_MISSING_FUNC, + PLUGIN_MODE_CHECK_RETURNS, }; enum ac_plugin_not_allowed { @@ -56,6 +58,12 @@ enum ac_plugin_not_allowed { #define NOT_ALLOWED_REMOTE_READER_RELAY_ONLY (1u << NOT_ALLOWED_ID_REMOTE_READER_RELAY_ONLY) #define NOT_ALLOWED_REMOTE_PERM (1u << NOT_ALLOWED_ID_REMOTE_PERM) +struct returns_log_data { + struct ddsrt_circlist_elem e; + void * obj; +}; + + /** * Implementation structure for storing encapsulated members of the instance * while giving only the interface definition to user @@ -65,8 +73,75 @@ struct dds_security_access_control_impl { dds_security_access_control *instance; enum ac_plugin_mode mode; uint32_t not_allowed_mask; + ddsrt_mutex_t returns_log_lock; + struct ddsrt_circlist returns_log; + bool invalid_return; }; + +static void init_returns_log(struct dds_security_access_control_impl *impl) +{ + ddsrt_mutex_init (&impl->returns_log_lock); + ddsrt_circlist_init (&impl->returns_log); +} + +static void fini_returns_log(struct dds_security_access_control_impl *impl) +{ + ddsrt_mutex_lock (&impl->returns_log_lock); + while (!ddsrt_circlist_isempty (&impl->returns_log)) + { + struct ddsrt_circlist_elem *list_elem = ddsrt_circlist_oldest (&impl->returns_log); + ddsrt_circlist_remove (&impl->returns_log, list_elem); + ddsrt_free (list_elem); + } + ddsrt_mutex_unlock (&impl->returns_log_lock); + ddsrt_mutex_destroy (&impl->returns_log_lock); +} + +static void register_return_obj (struct dds_security_access_control_impl * impl, void * obj) +{ + assert(impl->mode == PLUGIN_MODE_CHECK_RETURNS); + ddsrt_mutex_lock (&impl->returns_log_lock); + struct returns_log_data * attr_data = ddsrt_malloc (sizeof (*attr_data)); + attr_data->obj = obj; + ddsrt_circlist_append(&impl->returns_log, &attr_data->e); + printf("log obj %p\n", obj); + ddsrt_mutex_unlock (&impl->returns_log_lock); +} + +static void unregister_return_obj (struct dds_security_access_control_impl * impl, void * obj) +{ + assert(impl->mode == PLUGIN_MODE_CHECK_RETURNS); + ddsrt_mutex_lock (&impl->returns_log_lock); + struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->returns_log), *elem = elem0; + while (elem != NULL) + { + struct returns_log_data *data = DDSRT_FROM_CIRCLIST (struct returns_log_data, e, elem); + if (data->obj == obj) + { + ddsrt_circlist_remove (&impl->returns_log, elem); + ddsrt_mutex_unlock (&impl->returns_log_lock); + ddsrt_free (elem); + printf("return obj %p\n", obj); + return; + } + elem = elem->next; + if (elem == elem0) + break; + } + impl->invalid_return = true; + ddsrt_mutex_unlock (&impl->returns_log_lock); +} + +bool check_returns (struct dds_security_access_control_impl * impl) +{ + assert(impl->mode == PLUGIN_MODE_CHECK_RETURNS); + ddsrt_mutex_lock (&impl->returns_log_lock); + bool result = impl->invalid_return || !ddsrt_circlist_isempty (&impl->returns_log); + ddsrt_mutex_unlock (&impl->returns_log_lock); + return result; +} + static DDS_Security_PermissionsHandle validate_local_permissions( dds_security_access_control *instance, const dds_security_authentication *auth_plugin, @@ -87,7 +162,13 @@ static DDS_Security_PermissionsHandle validate_local_permissions( } /* fall through */ case PLUGIN_MODE_WRAPPED: - return impl->instance->validate_local_permissions(impl->instance, auth_plugin, identity, domain_id, participant_qos, ex); + case PLUGIN_MODE_CHECK_RETURNS: + { + DDS_Security_PermissionsHandle handle = impl->instance->validate_local_permissions(impl->instance, auth_plugin, identity, domain_id, participant_qos, ex); + if (impl->mode == PLUGIN_MODE_CHECK_RETURNS) + register_return_obj (impl, (void *) handle); + return handle; + } default: return 1; @@ -115,8 +196,14 @@ static DDS_Security_PermissionsHandle validate_remote_permissions( } /* fall through */ case PLUGIN_MODE_WRAPPED: - return impl->instance->validate_remote_permissions(impl->instance, auth_plugin, local_identity_handle, remote_identity_handle, + case PLUGIN_MODE_CHECK_RETURNS: + { + DDS_Security_PermissionsHandle handle = impl->instance->validate_remote_permissions(impl->instance, auth_plugin, local_identity_handle, remote_identity_handle, remote_permissions_token, remote_credential_token, ex); + if (impl->mode == PLUGIN_MODE_CHECK_RETURNS) + register_return_obj (impl, (void *) handle); + return handle; + } default: return 0; @@ -142,6 +229,7 @@ static DDS_Security_boolean check_create_participant( } /* fall through */ case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_create_participant(impl->instance, permissions_handle, domain_id, participant_qos, ex); default: @@ -174,6 +262,7 @@ static DDS_Security_boolean check_create_datawriter( } /* fall through */ case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_create_datawriter(impl->instance, permissions_handle, domain_id, topic_name, writer_qos, partition, data_tag, ex); default: @@ -203,6 +292,7 @@ static DDS_Security_boolean check_create_datareader( } /* fall through */ case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_create_datareader(impl->instance, permissions_handle, domain_id, topic_name, reader_qos, partition, data_tag, ex); default: @@ -230,6 +320,7 @@ static DDS_Security_boolean check_create_topic( } /* fall through */ case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_create_topic(impl->instance, permissions_handle, domain_id, topic_name, qos, ex); default: @@ -249,6 +340,7 @@ static DDS_Security_boolean check_local_datawriter_register_instance( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: + case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_local_datawriter_register_instance(impl->instance, permissions_handle, writer, key, ex); default: @@ -268,6 +360,7 @@ static DDS_Security_boolean check_local_datawriter_dispose_instance( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: + case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_local_datawriter_dispose_instance(impl->instance, permissions_handle, writer, key, ex); default: @@ -294,6 +387,7 @@ static DDS_Security_boolean check_remote_participant( } /* fall through */ case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_remote_participant(impl->instance, permissions_handle, domain_id, participant_data, ex); default: @@ -320,6 +414,7 @@ static DDS_Security_boolean check_remote_datawriter( } /* fall through */ case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_remote_datawriter(impl->instance, permissions_handle, domain_id, publication_data, ex); default: @@ -350,6 +445,7 @@ static DDS_Security_boolean check_remote_datareader( } /* fall through */ case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_CHECK_RETURNS: { bool ret; if ((ret = impl->instance->check_remote_datareader(impl->instance, permissions_handle, domain_id, subscription_data, relay_only, ex))) @@ -389,6 +485,7 @@ static DDS_Security_boolean check_remote_topic( } /* fall through */ case PLUGIN_MODE_WRAPPED: + case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_remote_topic(impl->instance, permissions_handle, domain_id, topic_data, ex); default: @@ -409,6 +506,7 @@ static DDS_Security_boolean check_local_datawriter_match( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: + case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_local_datawriter_match(impl->instance, writer_permissions_handle, reader_permissions_handle, publication_data, subscription_data, ex); default: @@ -429,6 +527,7 @@ static DDS_Security_boolean check_local_datareader_match( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: + case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_local_datareader_match(impl->instance, reader_permissions_handle, writer_permissions_handle, subscription_data, publication_data, ex); default: @@ -450,6 +549,7 @@ static DDS_Security_boolean check_remote_datawriter_register_instance( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: + case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_remote_datawriter_register_instance(impl->instance, permissions_handle, reader, publication_handle, key, instance_handle, ex); default: @@ -470,6 +570,7 @@ static DDS_Security_boolean check_remote_datawriter_dispose_instance( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: + case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_remote_datawriter_dispose_instance(impl->instance, permissions_handle, reader, publication_handle, key, ex); default: @@ -486,6 +587,9 @@ static DDS_Security_boolean get_permissions_token( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { + case PLUGIN_MODE_CHECK_RETURNS: + register_return_obj (impl, (void*) permissions_token); + /* fall through */ case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->get_permissions_token(impl->instance, permissions_token, handle, ex); @@ -506,6 +610,9 @@ static DDS_Security_boolean get_permissions_credential_token( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { + case PLUGIN_MODE_CHECK_RETURNS: + register_return_obj (impl, (void*) permissions_credential_token); + /* fall through */ case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->get_permissions_credential_token(impl->instance, permissions_credential_token, handle, ex); @@ -525,6 +632,7 @@ static DDS_Security_boolean set_listener( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: + case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->set_listener (impl->instance, listener, ex); default: @@ -540,6 +648,9 @@ static DDS_Security_boolean return_permissions_token( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { + case PLUGIN_MODE_CHECK_RETURNS: + unregister_return_obj (impl, (void*) token); + /* fall through */ case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->return_permissions_token (impl->instance, token, ex); @@ -558,6 +669,9 @@ static DDS_Security_boolean return_permissions_credential_token( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { + case PLUGIN_MODE_CHECK_RETURNS: + unregister_return_obj (impl, (void*) permissions_credential_token); + /* fall through */ case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->return_permissions_credential_token(impl->instance, permissions_credential_token, ex); @@ -576,6 +690,9 @@ static DDS_Security_boolean get_participant_sec_attributes( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { + case PLUGIN_MODE_CHECK_RETURNS: + register_return_obj (impl, (void*) attributes); + /* fall through */ case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->get_participant_sec_attributes(impl->instance, permissions_handle, attributes, ex); @@ -595,6 +712,9 @@ static DDS_Security_boolean get_topic_sec_attributes( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { + case PLUGIN_MODE_CHECK_RETURNS: + register_return_obj (impl, (void*) attributes); + /* fall through */ case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->get_topic_sec_attributes(impl->instance, permissions_handle, topic_name, attributes, ex); @@ -616,6 +736,9 @@ static DDS_Security_boolean get_datawriter_sec_attributes( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { + case PLUGIN_MODE_CHECK_RETURNS: + register_return_obj (impl, (void*) attributes); + /* fall through */ case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->get_datawriter_sec_attributes(impl->instance, permissions_handle, topic_name, partition, data_tag, attributes, ex); @@ -637,6 +760,9 @@ static DDS_Security_boolean get_datareader_sec_attributes( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { + case PLUGIN_MODE_CHECK_RETURNS: + register_return_obj (impl, (void*) attributes); + /* fall through */ case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->get_datareader_sec_attributes(impl->instance, permissions_handle, topic_name, partition, data_tag, attributes, ex); @@ -654,6 +780,9 @@ static DDS_Security_boolean return_participant_sec_attributes( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { + case PLUGIN_MODE_CHECK_RETURNS: + unregister_return_obj (impl, (void*) attributes); + /* fall through */ case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->return_participant_sec_attributes(impl->instance, attributes, ex); @@ -671,6 +800,9 @@ static DDS_Security_boolean return_topic_sec_attributes( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { + case PLUGIN_MODE_CHECK_RETURNS: + unregister_return_obj (impl, (void*) attributes); + /* fall through */ case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->return_topic_sec_attributes(impl->instance, attributes, ex); @@ -688,6 +820,9 @@ static DDS_Security_boolean return_datawriter_sec_attributes( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { + case PLUGIN_MODE_CHECK_RETURNS: + unregister_return_obj (impl, (void*) attributes); + /* fall through */ case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->return_datawriter_sec_attributes(impl->instance, attributes, ex); @@ -705,6 +840,9 @@ static DDS_Security_boolean return_datareader_sec_attributes( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { + case PLUGIN_MODE_CHECK_RETURNS: + unregister_return_obj (impl, (void*) attributes); + /* fall through */ case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->return_datareader_sec_attributes(impl->instance, attributes, ex); @@ -722,6 +860,9 @@ static DDS_Security_boolean return_permissions_handle( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { + case PLUGIN_MODE_CHECK_RETURNS: + unregister_return_obj (impl, (void*) permissions_handle); + /* fall through */ case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->return_permissions_handle(impl->instance, permissions_handle, ex); @@ -863,3 +1004,22 @@ int finalize_test_access_control_not_allowed(void *context) assert(impl->mode == PLUGIN_MODE_NOT_ALLOWED); return finalize_test_access_control_common(impl, true); } + +int init_test_access_control_check_returns(const char *argument, void **context, struct ddsi_domaingv *gv) +{ + struct dds_security_access_control_impl *impl = init_test_access_control_common(argument, true, gv); + if (!impl) + return DDS_SECURITY_FAILED; + impl->mode = PLUGIN_MODE_CHECK_RETURNS; + init_returns_log (impl); + *context = impl; + return DDS_SECURITY_SUCCESS; +} + +int finalize_test_access_control_check_returns(void *context) +{ + struct dds_security_access_control_impl* impl = (struct dds_security_access_control_impl*) context; + assert(impl->mode == PLUGIN_MODE_CHECK_RETURNS); + fini_returns_log (impl); + return finalize_test_access_control_common(impl, true); +} diff --git a/src/security/core/tests/common/access_control_wrapper.h b/src/security/core/tests/common/access_control_wrapper.h index 6f733fc..8dc0ecd 100644 --- a/src/security/core/tests/common/access_control_wrapper.h +++ b/src/security/core/tests/common/access_control_wrapper.h @@ -20,6 +20,10 @@ mode. This prefix is used to exclude built-in topics from being disallowed. */ #define AC_WRAPPER_TOPIC_PREFIX "ddssec_access_control_" +struct dds_security_access_control_impl; + +SECURITY_EXPORT bool check_returns (struct dds_security_access_control_impl * impl); + /* Init in all-ok mode: all functions return success without calling the actual plugin */ SECURITY_EXPORT int init_test_access_control_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int finalize_test_access_control_all_ok(void *context); @@ -49,4 +53,9 @@ INIT_NOT_ALLOWED_DECL(remote_permissions_not_allowed) SECURITY_EXPORT int finalize_test_access_control_not_allowed(void *context); +/* Init in attribute get and return logging mode */ +SECURITY_EXPORT int init_test_access_control_check_returns(const char *argument, void **context, struct ddsi_domaingv *gv); +SECURITY_EXPORT int finalize_test_access_control_check_returns(void *context); + + #endif /* SECURITY_CORE_TEST_ACCESS_CONTROL_WRAPPER_H_ */ diff --git a/src/security/core/tests/common/test_utils.c b/src/security/core/tests/common/test_utils.c index eff8f51..c17f1cd 100644 --- a/src/security/core/tests/common/test_utils.c +++ b/src/security/core/tests/common/test_utils.c @@ -495,23 +495,24 @@ void write_read_for(dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_du CU_ASSERT_EQUAL_FATAL (read_fail, exp_read_fail); } -struct dds_security_cryptography_impl * get_crypto_context(dds_entity_t participant) -{ - struct dds_entity *pp_entity = NULL; - struct participant *pp; - struct dds_security_cryptography_impl *context; - dds_return_t ret; +#define GET_SECURITY_PLUGIN_CONTEXT(name_) \ + struct dds_security_##name_##_impl * get_##name_##_context(dds_entity_t participant) \ + { \ + struct dds_entity *pp_entity = NULL; \ + dds_return_t ret = dds_entity_lock (participant, DDS_KIND_PARTICIPANT, &pp_entity); \ + CU_ASSERT_EQUAL_FATAL (ret, 0); \ + thread_state_awake (lookup_thread_state(), &pp_entity->m_domain->gv); \ + struct participant *pp = entidx_lookup_participant_guid (pp_entity->m_domain->gv.entity_index, &pp_entity->m_guid); \ + CU_ASSERT_FATAL (pp != NULL); \ + struct dds_security_##name_##_impl *context = (struct dds_security_##name_##_impl *) q_omg_participant_get_##name_ (pp); \ + thread_state_asleep (lookup_thread_state ()); \ + dds_entity_unlock (pp_entity); \ + return context; \ + } - ret = dds_entity_lock (participant, DDS_KIND_PARTICIPANT, &pp_entity); - CU_ASSERT_EQUAL_FATAL (ret, 0); - thread_state_awake (lookup_thread_state(), &pp_entity->m_domain->gv); - pp = entidx_lookup_participant_guid (pp_entity->m_domain->gv.entity_index, &pp_entity->m_guid); - CU_ASSERT_FATAL (pp != NULL); - context = (struct dds_security_cryptography_impl *) q_omg_participant_get_cryptography (pp); - thread_state_asleep (lookup_thread_state ()); - dds_entity_unlock (pp_entity); - return context; -} +GET_SECURITY_PLUGIN_CONTEXT(access_control) +GET_SECURITY_PLUGIN_CONTEXT(authentication) +GET_SECURITY_PLUGIN_CONTEXT(cryptography) const char * pk_to_str(DDS_Security_ProtectionKind pk) { diff --git a/src/security/core/tests/common/test_utils.h b/src/security/core/tests/common/test_utils.h index 7fe1487..8b930c3 100644 --- a/src/security/core/tests/common/test_utils.h +++ b/src/security/core/tests/common/test_utils.h @@ -82,10 +82,16 @@ void rd_wr_init_fail ( bool exp_pubtp_fail, bool exp_wr_fail, bool exp_subtp_fail, bool exp_rd_fail); void write_read_for (dds_entity_t wr, dds_entity_t pp_rd, dds_entity_t rd, dds_duration_t dur, bool exp_write_fail, bool exp_read_fail); -struct dds_security_cryptography_impl * get_crypto_context (dds_entity_t participant); const char * pk_to_str (DDS_Security_ProtectionKind pk); const char * bpk_to_str (DDS_Security_BasicProtectionKind bpk); DDS_Security_DatawriterCryptoHandle get_builtin_writer_crypto_handle(dds_entity_t participant, unsigned entityid); DDS_Security_DatawriterCryptoHandle get_writer_crypto_handle(dds_entity_t writer); +#define GET_SECURITY_PLUGIN_CONTEXT_DECL(name_) \ + struct dds_security_##name_##_impl * get_##name_##_context(dds_entity_t participant); +GET_SECURITY_PLUGIN_CONTEXT_DECL(access_control) +GET_SECURITY_PLUGIN_CONTEXT_DECL(authentication) +GET_SECURITY_PLUGIN_CONTEXT_DECL(cryptography) + + #endif /* SECURITY_CORE_TEST_UTILS_H_ */ diff --git a/src/security/core/tests/crypto.c b/src/security/core/tests/crypto.c index 098b0d7..ca41f2f 100644 --- a/src/security/core/tests/crypto.c +++ b/src/security/core/tests/crypto.c @@ -156,7 +156,7 @@ CU_Theory((const char * test_descr, DDS_Security_BasicProtectionKind payload_pk, /* set forced plain data for payload/submsg/rtps */ DDS_Security_DatawriterCryptoHandle wr_handle = get_writer_crypto_handle (wr); - struct dds_security_cryptography_impl * crypto_impl = get_crypto_context (g_participant1); + struct dds_security_cryptography_impl * crypto_impl = get_cryptography_context (g_participant1); set_force_plain_data (crypto_impl, wr_handle, rtps_pk != PK_N, submsg_pk != PK_N, payload_pk != BPK_N); /* sync and write/take sample */ diff --git a/src/security/core/tests/handshake.c b/src/security/core/tests/handshake.c index 26d6d9a..0891d34 100644 --- a/src/security/core/tests/handshake.c +++ b/src/security/core/tests/handshake.c @@ -143,11 +143,11 @@ CU_Test(ddssec_handshake, check_tokens) write_read_for (g_wr, g_participant2, g_rd, DDS_MSECS (100), false, false); // Get subscriber and publisher crypto tokens - struct dds_security_cryptography_impl * crypto_context_pub = get_crypto_context (g_participant1); + struct dds_security_cryptography_impl * crypto_context_pub = get_cryptography_context (g_participant1); CU_ASSERT_FATAL (crypto_context_pub != NULL); struct ddsrt_circlist *pub_tokens = get_crypto_tokens (crypto_context_pub); - struct dds_security_cryptography_impl * crypto_context_sub = get_crypto_context (g_participant2); + struct dds_security_cryptography_impl * crypto_context_sub = get_cryptography_context (g_participant2); CU_ASSERT_FATAL (crypto_context_sub != NULL); struct ddsrt_circlist *sub_tokens = get_crypto_tokens (crypto_context_sub); diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index 94f8c13..52dd62d 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -119,7 +119,7 @@ static dds_entity_t create_pp (dds_domainid_t domain_id, const struct domain_sec dds_entity_t pp = dds_create_participant (domain_id, qos, NULL); CU_ASSERT_FATAL (pp > 0); dds_delete_qos (qos); - struct dds_security_cryptography_impl * crypto_context = get_crypto_context (pp); + struct dds_security_cryptography_impl * crypto_context = get_cryptography_context (pp); CU_ASSERT_FATAL (crypto_context != NULL); assert (set_crypto_params); set_crypto_params (crypto_context, domain_config); From 24594f68fbf018a06539c0be0b3d87b6d741e6ba Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 12 May 2020 21:16:30 +0200 Subject: [PATCH 192/238] Add access control test for testing that communication for an allowed topic keeps working when a writer for a denied topic is created Signed-off-by: Dennis Potman --- src/security/core/tests/access_control.c | 57 +++++++++++++++++++++ src/security/core/tests/common/test_utils.c | 17 +++--- src/security/core/tests/common/test_utils.h | 1 + 3 files changed, 69 insertions(+), 6 deletions(-) diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index 19912ea..db1b27b 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -857,3 +857,60 @@ CU_Test(ddssec_access_control, check_returns) access_control_fini (2, (void * []) { gov_config, gov_topic_rule, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 10); } + + +CU_Test(ddssec_access_control, denied_topic) +{ + char topic_name[100], denied_topic_name[100]; + create_topic_name ("ddssec_access_control_", g_topic_nr++, topic_name, sizeof (topic_name)); + create_topic_name ("ddssec_access_control_", g_topic_nr++, denied_topic_name, sizeof (denied_topic_name)); + + char *ca, *id1, *id2, *id1_subj, *id2_subj; + ca = generate_ca ("ca1", TEST_IDENTITY_CA1_PRIVATE_KEY, 0, 3600); + id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id1_subj); + id2 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id2", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id2_subj); + + dds_time_t now = dds_time (); + char * sub_rules_xml = get_permissions_rules (NULL, NULL, NULL, denied_topic_name, denied_topic_name); + char * grants_pub[] = { get_permissions_grant ("id1", id1_subj, now, now + DDS_SECS(3600), NULL, "ALLOW") }; + char * grants_sub[] = { get_permissions_grant ("id2", id2_subj, now, now + DDS_SECS(3600), sub_rules_xml, "ALLOW") }; + char * perm_config_pub = get_permissions_config (grants_pub, 1, true); + char * perm_config_sub = get_permissions_config (grants_sub, 1, true); + + char * gov_topic_rule = get_governance_topic_rule (NULL, true, true, true, true, PK_E, BPK_E); + char * gov_config = get_governance_config (false, true, PK_E, PK_E, PK_E, gov_topic_rule, true); + const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); + + access_control_init ( + 2, + (const char *[]) { id1, id2 }, + (const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY }, + (const char *[]) { ca, ca }, + (bool []) { false, false }, + NULL, NULL, + (bool []) { true, true }, (const char *[]) { gov_config, gov_config }, + (bool []) { true, true }, (const char *[]) { perm_config_pub, perm_config_sub }, + (bool []) { true, true }, (const char *[]) { def_perm_ca, def_perm_ca }); + + dds_entity_t pub, sub, pub_tp, sub_tp, wr, rd; + rd_wr_init (g_participant[0], &pub, &pub_tp, &wr, g_participant[1], &sub, &sub_tp, &rd, topic_name); + sync_writer_to_readers (g_participant[0], wr, 1, DDS_SECS (1)); + sync_reader_to_writers (g_participant[1], rd, 1, DDS_SECS (1)); + + /* Create a topic that is denied in the subscriber pp security config */ + dds_entity_t denied_pub_tp = dds_create_topic (g_participant[0], &SecurityCoreTests_Type1_desc, denied_topic_name, NULL, NULL); + CU_ASSERT_FATAL (denied_pub_tp > 0); + dds_qos_t * qos = get_default_test_qos (); + dds_entity_t denied_tp_wr = dds_create_writer (pub, denied_pub_tp, qos, NULL); + CU_ASSERT_FATAL (denied_tp_wr > 0); + + /* Check that creating denied topic for subscriber fails */ + dds_entity_t denied_sub_tp = dds_create_topic (g_participant[1], &SecurityCoreTests_Type1_desc, denied_topic_name, NULL, NULL); + CU_ASSERT_FATAL (denied_sub_tp == DDS_RETCODE_NOT_ALLOWED_BY_SECURITY); + + /* Check if communication for allowed topic is still working */ + write_read_for (wr, g_participant[1], rd, DDS_MSECS (10), false, false); + + dds_delete_qos (qos); + access_control_fini (2, (void * []) { gov_config, gov_topic_rule, sub_rules_xml, grants_pub[0], grants_sub[0], perm_config_pub, perm_config_sub, ca, id1_subj, id2_subj, id1, id2 }, 12); +} \ No newline at end of file diff --git a/src/security/core/tests/common/test_utils.c b/src/security/core/tests/common/test_utils.c index c17f1cd..e7e7ed4 100644 --- a/src/security/core/tests/common/test_utils.c +++ b/src/security/core/tests/common/test_utils.c @@ -398,6 +398,16 @@ bool reader_wait_for_data (dds_entity_t pp, dds_entity_t rd, dds_duration_t dur) return ret > 0; } +dds_qos_t * get_default_test_qos (void) +{ + dds_qos_t * qos = dds_create_qos (); + CU_ASSERT_FATAL (qos != NULL); + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, -1); + dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL); + dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); + return qos; +} + void rd_wr_init_fail( dds_entity_t pp_wr, dds_entity_t *pub, dds_entity_t *pub_tp, dds_entity_t *wr, dds_entity_t pp_rd, dds_entity_t *sub, dds_entity_t *sub_tp, dds_entity_t *rd, @@ -405,12 +415,7 @@ void rd_wr_init_fail( bool exp_pubtp_fail, bool exp_wr_fail, bool exp_subtp_fail, bool exp_rd_fail) { - dds_qos_t * qos = dds_create_qos (); - CU_ASSERT_FATAL (qos != NULL); - dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, -1); - dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL); - dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); - + dds_qos_t * qos = get_default_test_qos (); *pub = dds_create_publisher (pp_wr, NULL, NULL); CU_ASSERT_FATAL (*pub > 0); *sub = dds_create_subscriber (pp_rd, NULL, NULL); diff --git a/src/security/core/tests/common/test_utils.h b/src/security/core/tests/common/test_utils.h index 8b930c3..b2dfff5 100644 --- a/src/security/core/tests/common/test_utils.h +++ b/src/security/core/tests/common/test_utils.h @@ -71,6 +71,7 @@ char *create_topic_name (const char *prefix, uint32_t nr, char *name, size_t siz void sync_writer_to_readers (dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_count, dds_duration_t timeout); void sync_reader_to_writers (dds_entity_t pp_rd, dds_entity_t rd, uint32_t exp_count, dds_duration_t timeout); bool reader_wait_for_data (dds_entity_t pp, dds_entity_t rd, dds_duration_t dur); +dds_qos_t * get_default_test_qos (void); void rd_wr_init ( dds_entity_t pp_wr, dds_entity_t *pub, dds_entity_t *pub_tp, dds_entity_t *wr, dds_entity_t pp_rd, dds_entity_t *sub, dds_entity_t *sub_tp, dds_entity_t *rd, From 48e411bb766b8ae99f6f0db6bb83fc18edf229cc Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Wed, 13 May 2020 11:17:15 +0200 Subject: [PATCH 193/238] Fix rd-wr synchronization in access control expiry_multiple test Signed-off-by: Dennis Potman --- src/security/core/tests/access_control.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index db1b27b..c481c5b 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -297,12 +297,7 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) id, pk, ca_list, exp_fail, NULL, NULL, incl_el, gov, incl_el, perm_conf, incl_el, perm_ca); - dds_qos_t * qos = dds_create_qos (); - CU_ASSERT_FATAL (qos != NULL); - dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, -1); - dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL); - dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); - + dds_qos_t * qos = get_default_test_qos (); dds_entity_t rd[N_RD]; for (int i = 0; i < N_RD; i++) { @@ -312,7 +307,7 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) CU_ASSERT_FATAL (sub_tp > 0); rd[i] = dds_create_reader (sub, sub_tp, qos, NULL); CU_ASSERT_FATAL (rd[i] > 0); - dds_set_status_mask (rd[i], DDS_DATA_AVAILABLE_STATUS); + dds_set_status_mask (rd[i], DDS_SUBSCRIPTION_MATCHED_STATUS); } dds_entity_t wr[N_WR]; @@ -328,6 +323,11 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) sync_writer_to_readers (g_participant[i + N_RD], wr[i], N_RD, DDS_SECS(2)); } dds_delete_qos (qos); + for (int i = 0; i < N_RD; i++) + { + sync_reader_to_writers (g_participant[i], rd[i], N_WR, DDS_SECS (2)); + dds_set_status_mask (rd[i], DDS_DATA_AVAILABLE_STATUS); + } SecurityCoreTests_Type1 sample = { 1, 1 }; SecurityCoreTests_Type1 rd_sample; From 32bba389c854754c4d69eaf813c3fe4763d5c9c0 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Wed, 13 May 2020 16:37:41 +0200 Subject: [PATCH 194/238] Add test descriptions as code comment in security core tests Signed-off-by: Dennis Potman --- src/security/core/tests/access_control.c | 34 ++++++++++++++++--- src/security/core/tests/authentication.c | 14 ++++++-- src/security/core/tests/crypto.c | 4 +++ src/security/core/tests/handshake.c | 5 +++ .../core/tests/secure_communication.c | 11 ++++++ 5 files changed, 61 insertions(+), 7 deletions(-) diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index c481c5b..ed91c66 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -153,6 +153,10 @@ CU_TheoryDataPoints(ddssec_access_control, config_parameters_file) = { CU_DataPoints(bool, true, true, true, true, true, true, true, true, true, true, true, false, false, false), // include empty config elements CU_DataPoints(bool, false, true, true, true, true, true, true, true, false, true, false, true, true, true) // expect failure }; +/* Testing configuration parameters for the access control security plugin, + using configuration from file. The test cases include using non-existing + files, empty configuration files, mixing configudation from file and inline + in the cyclone XML configuration. */ CU_Theory((const char * test_descr, const char * gov, const char * perm, const char * ca, bool incl_empty_els, bool exp_fail), ddssec_access_control, config_parameters_file) { @@ -198,6 +202,9 @@ CU_TheoryDataPoints(ddssec_access_control, permissions_expiry) = { #undef D #undef H #undef M +/* Testing expiry of the (signed) permissions XML. Test cases include using + permissions config that is valid for 1 minute, was valid in the past minute, + expires before data is written, expires during writing data. */ CU_Theory( (const char * test_descr, int32_t perm1_not_before, int32_t perm1_not_after, int32_t perm2_not_before, int32_t perm2_not_after, @@ -254,6 +261,9 @@ CU_Theory( #define N_WR 3 #define N_NODES (N_RD + N_WR) #define PERM_EXP_BASE 3 +/* Tests permissions configuration expiry using multiple writers, to validate + that a reader still received data from writers that still have valid + permissions config */ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) { char topic_name[100]; @@ -419,7 +429,10 @@ CU_TheoryDataPoints(ddssec_access_control, hooks) = { CU_DataPoints(bool, na, na, na, false, na, true, true, true, true, false, false), // exp_rd_wr_sync_fail }; #undef na - +/* Test that the security implementation in DDSI is correctly handling denial of + creating enities, e.g. local participant not allowed, local writer not allowed, + remote topic not allowed, etc. This test is initializing the wrapper plugin in a + not-allowed mode to force denial of a specified entity. */ CU_Theory( (const char * init_fn, bool exp_pp_fail, bool exp_local_topic_fail, bool exp_remote_topic_fail, bool exp_wr_fail, bool exp_rd_fail, bool exp_wr_rd_sync_fail, bool exp_rd_wr_sync_fail), ddssec_access_control, hooks, .timeout=60) @@ -493,6 +506,8 @@ CU_TheoryDataPoints(ddssec_access_control, join_access_control) = { CU_DataPoints(bool, false, false, false, na, na), /* expect handshake failure */ }; #undef na +/* Testing handshake result using join access control setting enabled/disabled and + valid/invalid permissions for 2 participants. */ CU_Theory( (const char * test_descr, bool join_ac_pp1, bool join_ac_pp2, bool perm_inv_pp1, bool perm_inv_pp2, bool exp_pp1_fail, bool exp_pp2_fail, bool exp_hs_fail), ddssec_access_control, join_access_control, .timeout=30) @@ -627,7 +642,9 @@ static void test_discovery_liveliness_protection(enum test_discovery_liveliness access_control_fini (2, (void * []) { gov_config1, gov_config2, gov_topic_rule1, gov_topic_rule2, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 12); } - +/* Testing discovery and liveliness protection by checking that encode_datawriter_submessage + is called for SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER and/or P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER + depending on the discovery and liveliness protection settings in security configuration. */ CU_Theory( (const char * test_descr, bool enable_discovery_protection_pp1, bool enable_discovery_protection_pp2, DDS_Security_ProtectionKind discovery_protection_kind_pp1, DDS_Security_ProtectionKind discovery_protection_kind_pp2, @@ -697,6 +714,9 @@ static void test_encoding_mismatch( access_control_fini (2, (void * []) { gov_config1, gov_config2, gov_topic_rule1, gov_topic_rule2, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 12); } +/* Testing handshake result for any combination of protection kind values for rtps, discovery, + liveliness, metadata (submsg) and payload encoding. In all cases where there is an encoding + mismatch, the security handshake is expect to fail */ static DDS_Security_ProtectionKind pk[] = { PK_N, PK_S, PK_E, PK_SOA, PK_EOA }; static DDS_Security_BasicProtectionKind bpk[] = { BPK_N, BPK_S, BPK_E }; @@ -787,7 +807,9 @@ static void test_readwrite_protection ( access_control_fini (2, (void * []) { gov_config, gov_topic_rule, rules_xml, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 11); } - +/* Test read/write access control by running test cases with different combinations + of allow and deny rules for publishing and subscribing on a topic, and check correct + working of the default policy. */ CU_Test(ddssec_access_control, readwrite_protection, .timeout=60) { for (int allow_pub = 0; allow_pub <= 1; allow_pub++) @@ -815,7 +837,8 @@ CU_Test(ddssec_access_control, readwrite_protection, .timeout=60) } } - +/* Test that all attributes and token retrieved from the access control plugin + are correctly returned. */ CU_Test(ddssec_access_control, check_returns) { char topic_name[100]; @@ -858,7 +881,8 @@ CU_Test(ddssec_access_control, check_returns) access_control_fini (2, (void * []) { gov_config, gov_topic_rule, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 10); } - +/* Check that communication for a topic that is allowed in the permissions config + keeps working in case the publisher also creates a writer for a non-allowed topic */ CU_Test(ddssec_access_control, denied_topic) { char topic_name[100], denied_topic_name[100]; diff --git a/src/security/core/tests/authentication.c b/src/security/core/tests/authentication.c index 79e9cb2..a09ad7d 100644 --- a/src/security/core/tests/authentication.c +++ b/src/security/core/tests/authentication.c @@ -183,7 +183,9 @@ CU_TheoryDataPoints(ddssec_authentication, id_ca_certs) = { }; #undef FM_CA #undef FM_INVK - +/* Test the security handshake result in test-cases using identity CA's that match and do not + match (i.e. a different CA that was not used for creating the identity) the identities used + in the participants security configuration. */ CU_Theory((const char * test_descr, const char * id2, const char *key2, const char *ca2, bool exp_fail_pp1, bool exp_fail_pp2, bool exp_fail_local, const char * fail_local_msg, @@ -218,6 +220,8 @@ CU_TheoryDataPoints(ddssec_authentication, trusted_ca_dir) = { CU_DataPoints(const char *, "", ".", "/nonexisting", NULL), CU_DataPoints(bool, false, false, true, false) }; +/* Test correct and incorrect values for the trusted CA directory in the + authentication plugin configuration */ CU_Theory((const char * ca_dir, bool exp_fail), ddssec_authentication, trusted_ca_dir) { print_test_msg ("Testing custom CA dir: %s\n", ca_dir); @@ -259,6 +263,9 @@ CU_TheoryDataPoints(ddssec_authentication, expired_cert) = { CU_DataPoints(uint32_t, 1, 0, 0, 0, 1, 0, 1, 10000 ), /* write/read data during x ms */ CU_DataPoints(bool, false, false, false, false, false, false, false, true ), /* expect read data failure */ }; +/* Test the security handshake result and check communication for scenarios using + valid identities, identities that are expired and identities that are not yet valid. + A test case using an identity that expires during the test is also included. */ CU_Theory( (const char * test_descr, int32_t ca_not_before, int32_t ca_not_after, int32_t id1_not_before, int32_t id1_not_after, bool id1_local_fail, @@ -300,7 +307,10 @@ CU_Theory( #undef H #undef M - +/* Test communication for a non-secure participant with a secure participant that + allows unauthenticated nodes in its governance configuration. Samples for a secured + topic should not be received by a reader in the non-secure participant; samples for + a non-secure topic should. */ CU_Test(ddssec_authentication, unauthenticated_pp) { char topic_name_secure[100]; diff --git a/src/security/core/tests/crypto.c b/src/security/core/tests/crypto.c index ca41f2f..68ae5fd 100644 --- a/src/security/core/tests/crypto.c +++ b/src/security/core/tests/crypto.c @@ -125,6 +125,10 @@ CU_TheoryDataPoints(ddssec_crypto, inject_plain_data) = { CU_DataPoints(DDS_Security_ProtectionKind, PK_N, PK_N, PK_E, PK_S, PK_N, PK_N), /* submessage protection */ CU_DataPoints(DDS_Security_ProtectionKind, PK_N, PK_N, PK_N, PK_N, PK_E, PK_S), /* rtps protection */ }; +/* This test validates that non-encrypted data will not be received by a reader that has protection + enabled for rtps/submsg/payload. The test uses a crypto plugin wrapper mode that force the plugin + to write plain data in the encoded output buffer to DDSI, ignoring the security attributes for the + reader and writer. */ CU_Theory((const char * test_descr, DDS_Security_BasicProtectionKind payload_pk, DDS_Security_ProtectionKind submsg_pk, DDS_Security_ProtectionKind rtps_pk), ddssec_crypto, inject_plain_data, .timeout=30) { diff --git a/src/security/core/tests/handshake.c b/src/security/core/tests/handshake.c index 0891d34..4988f69 100644 --- a/src/security/core/tests/handshake.c +++ b/src/security/core/tests/handshake.c @@ -105,6 +105,8 @@ static void handshake_fini(void) CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); } +/* Happy-day test for the security handshake, that tests succesfull handshake for + two participants using the same typical security settings. */ CU_Test(ddssec_handshake, happy_day) { struct Handshake *hs_list; @@ -129,6 +131,9 @@ CU_Test(ddssec_handshake, happy_day) handshake_fini (); } +/* This test checks that all tokens that are sent to a remote participant are received + correctly by that participant and the token-data stored in the remote participant + is equal to the data in the token that was sent. */ CU_Test(ddssec_handshake, check_tokens) { handshake_init ( diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index 52dd62d..3a3a6ec 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -387,6 +387,8 @@ static void test_payload_secret(DDS_Security_ProtectionKind rtps_pk, DDS_Securit ddsrt_free (sample.text); } +/* Test communication between 2 nodes for all combinations of RTPS, metadata (submsg) + and payload protection kinds using a single reader and writer */ CU_Test(ddssec_secure_communication, protection_kinds, .timeout = 120) { DDS_Security_ProtectionKind rtps_pk[] = { PK_N, PK_S, PK_E }; @@ -404,6 +406,8 @@ CU_Test(ddssec_secure_communication, protection_kinds, .timeout = 120) } } +/* Test communication between 2 nodes for all combinations of discovery and + liveliness protection kinds using a single reader and writer */ CU_Test(ddssec_secure_communication, discovery_liveliness_protection, .timeout = 60) { DDS_Security_ProtectionKind discovery_pk[] = { PK_N, PK_S, PK_E }; @@ -417,6 +421,8 @@ CU_Test(ddssec_secure_communication, discovery_liveliness_protection, .timeout = } } +/* Test that a specific character sequence from the plain data does not appear in + encrypted payload, submessage or rtps message when protection kind is ENCRYPT*/ CU_Test(ddssec_secure_communication, check_encrypted_secret, .timeout = 60) { DDS_Security_ProtectionKind rtps_pk[] = { PK_N, PK_E, PK_EOA }; @@ -434,6 +440,8 @@ CU_Test(ddssec_secure_communication, check_encrypted_secret, .timeout = 60) } } +/* Test communication with specific combinations payload and submsg protection + kinds for 1-3 domains, 1-3 participants per domain and 1-3 readers per participant */ CU_TheoryDataPoints(ddssec_secure_communication, multiple_readers) = { CU_DataPoints(size_t, 1, 1, 1, 3), /* number of domains */ CU_DataPoints(size_t, 1, 3, 1, 3), /* number of participants per domain */ @@ -452,6 +460,9 @@ CU_Theory((size_t n_dom, size_t n_pp, size_t n_rd), ddssec_secure_communication, } } +/* Test communication with specific combinations payload and submsg protection + kinds for 1-2 domains, 1-3 participants per domain, 1-3 readers per participant + and 1-3 writers per participant */ CU_TheoryDataPoints(ddssec_secure_communication, multiple_readers_writers) = { CU_DataPoints(size_t, 1, 1, 2), /* number of reader domains */ CU_DataPoints(size_t, 1, 3, 3), /* number of readers per domain */ From a151c5f1845f2934f675ebc5a099557f381049a8 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Thu, 14 May 2020 21:27:29 +0200 Subject: [PATCH 195/238] Processed review comments: added missing return topic_sec_attr in function is_topic_discovery_protected, moved returns-logging in access plugin to wrapper mode and removed specific test for this (as it will be tested in other access control tests now). Some cleanup in circular list usage in crypto and access control plugins Signed-off-by: Dennis Potman --- src/core/ddsi/src/ddsi_security_omg.c | 10 +- src/security/core/tests/access_control.c | 44 ------ .../tests/common/access_control_wrapper.c | 144 +++++++----------- .../tests/common/access_control_wrapper.h | 7 - .../core/tests/common/cryptography_wrapper.c | 26 ++-- .../core/tests/common/cryptography_wrapper.h | 6 +- 6 files changed, 72 insertions(+), 165 deletions(-) diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index d064105..79052b2 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -1401,12 +1401,18 @@ static bool is_topic_discovery_protected(DDS_Security_PermissionsHandle permissi { DDS_Security_TopicSecurityAttributes attributes = {0,0,0,0}; DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; + bool result = false; if (access_control->get_topic_sec_attributes(access_control, permission_handle, topic_name, &attributes, &exception)) - return attributes.is_discovery_protected; + { + result = attributes.is_discovery_protected; + access_control->return_topic_sec_attributes(access_control, &attributes, &exception); + } else + { DDS_Security_Exception_reset(&exception); - return false; + } + return result; } static void handle_not_allowed( diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index ed91c66..261fbdf 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -837,50 +837,6 @@ CU_Test(ddssec_access_control, readwrite_protection, .timeout=60) } } -/* Test that all attributes and token retrieved from the access control plugin - are correctly returned. */ -CU_Test(ddssec_access_control, check_returns) -{ - char topic_name[100]; - create_topic_name ("ddssec_access_control_", g_topic_nr++, topic_name, sizeof (topic_name)); - - char *ca, *id1, *id2, *id1_subj, *id2_subj; - ca = generate_ca ("ca1", TEST_IDENTITY_CA1_PRIVATE_KEY, 0, 3600); - id1 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id1", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id1_subj); - id2 = generate_identity (ca, TEST_IDENTITY_CA1_PRIVATE_KEY, "id2", TEST_IDENTITY1_PRIVATE_KEY, 0, 3600, &id2_subj); - - char * grants[] = { - get_permissions_default_grant ("id1", id1_subj, topic_name), - get_permissions_default_grant ("id2", id2_subj, topic_name) }; - char * perm_config = get_permissions_config (grants, 2, true); - - char * gov_topic_rule = get_governance_topic_rule (NULL, true, true, true, true, PK_E, BPK_E); - char * gov_config = get_governance_config (false, true, PK_E, PK_E, PK_E, gov_topic_rule, true); - const char * def_perm_ca = PF_F COMMON_ETC_PATH("default_permissions_ca.pem"); - - access_control_init ( - 2, - (const char *[]) { id1, id2 }, - (const char *[]) { TEST_IDENTITY1_PRIVATE_KEY, TEST_IDENTITY1_PRIVATE_KEY }, - (const char *[]) { ca, ca }, - (bool []) { false, false }, - (const char *[]) { "init_test_access_control_check_returns", "init_test_access_control_wrapped" }, - (const char *[]) { "finalize_test_access_control_check_returns", "finalize_test_access_control_wrapped" }, - (bool []) { true, true }, (const char *[]) { gov_config, gov_config }, - (bool []) { true, true }, (const char *[]) { perm_config, perm_config }, - (bool []) { true, true }, (const char *[]) { def_perm_ca, def_perm_ca }); - - dds_entity_t pub, sub, pub_tp, sub_tp, wr, rd; - rd_wr_init (g_participant[0], &pub, &pub_tp, &wr, g_participant[1], &sub, &sub_tp, &rd, topic_name); - sync_writer_to_readers (g_participant[0], wr, 1, DDS_SECS (1)); - sync_reader_to_writers (g_participant[1], rd, 1, DDS_SECS (1)); - - struct dds_security_access_control_impl * ac_context = get_access_control_context (g_participant[0]); - CU_ASSERT_FATAL (check_returns (ac_context)); - - access_control_fini (2, (void * []) { gov_config, gov_topic_rule, grants[0], grants[1], perm_config, ca, id1_subj, id2_subj, id1, id2 }, 10); -} - /* Check that communication for a topic that is allowed in the permissions config keeps working in case the publisher also creates a writer for a non-allowed topic */ CU_Test(ddssec_access_control, denied_topic) diff --git a/src/security/core/tests/common/access_control_wrapper.c b/src/security/core/tests/common/access_control_wrapper.c index 7a80087..ac9cbd9 100644 --- a/src/security/core/tests/common/access_control_wrapper.c +++ b/src/security/core/tests/common/access_control_wrapper.c @@ -11,6 +11,7 @@ */ #include #include +#include "CUnit/Test.h" #include "dds/dds.h" #include "dds/ddsrt/circlist.h" #include "dds/ddsrt/heap.h" @@ -29,7 +30,6 @@ enum ac_plugin_mode { PLUGIN_MODE_WRAPPED, PLUGIN_MODE_NOT_ALLOWED, PLUGIN_MODE_MISSING_FUNC, - PLUGIN_MODE_CHECK_RETURNS, }; enum ac_plugin_not_allowed { @@ -83,6 +83,7 @@ static void init_returns_log(struct dds_security_access_control_impl *impl) { ddsrt_mutex_init (&impl->returns_log_lock); ddsrt_circlist_init (&impl->returns_log); + impl->invalid_return = false; } static void fini_returns_log(struct dds_security_access_control_impl *impl) @@ -100,46 +101,55 @@ static void fini_returns_log(struct dds_security_access_control_impl *impl) static void register_return_obj (struct dds_security_access_control_impl * impl, void * obj) { - assert(impl->mode == PLUGIN_MODE_CHECK_RETURNS); + assert(impl->mode == PLUGIN_MODE_WRAPPED); ddsrt_mutex_lock (&impl->returns_log_lock); struct returns_log_data * attr_data = ddsrt_malloc (sizeof (*attr_data)); attr_data->obj = obj; ddsrt_circlist_append(&impl->returns_log, &attr_data->e); - printf("log obj %p\n", obj); ddsrt_mutex_unlock (&impl->returns_log_lock); } +static struct ddsrt_circlist_elem *find_return_obj_data (struct dds_security_access_control_impl * impl, void * obj) +{ + struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->returns_log), *elem = elem0; + if (elem != NULL) + { + do + { + struct returns_log_data *data = DDSRT_FROM_CIRCLIST (struct returns_log_data, e, elem); + if (data->obj == obj) + return elem; + elem = elem->next; + } while (elem != elem0); + } + return NULL; +} + static void unregister_return_obj (struct dds_security_access_control_impl * impl, void * obj) { - assert(impl->mode == PLUGIN_MODE_CHECK_RETURNS); + struct ddsrt_circlist_elem *elem; + assert(impl->mode == PLUGIN_MODE_WRAPPED); ddsrt_mutex_lock (&impl->returns_log_lock); - struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->returns_log), *elem = elem0; - while (elem != NULL) + if ((elem = find_return_obj_data (impl, obj)) != NULL) { - struct returns_log_data *data = DDSRT_FROM_CIRCLIST (struct returns_log_data, e, elem); - if (data->obj == obj) - { - ddsrt_circlist_remove (&impl->returns_log, elem); - ddsrt_mutex_unlock (&impl->returns_log_lock); - ddsrt_free (elem); - printf("return obj %p\n", obj); - return; - } - elem = elem->next; - if (elem == elem0) - break; + ddsrt_circlist_remove (&impl->returns_log, elem); + ddsrt_free (elem); + } + else + { + impl->invalid_return = true; + printf ("invalid return %p\n", obj); } - impl->invalid_return = true; ddsrt_mutex_unlock (&impl->returns_log_lock); } -bool check_returns (struct dds_security_access_control_impl * impl) +static bool all_returns_valid (struct dds_security_access_control_impl * impl) { - assert(impl->mode == PLUGIN_MODE_CHECK_RETURNS); + assert(impl->mode == PLUGIN_MODE_WRAPPED); ddsrt_mutex_lock (&impl->returns_log_lock); - bool result = impl->invalid_return || !ddsrt_circlist_isempty (&impl->returns_log); + bool valid = !impl->invalid_return && ddsrt_circlist_isempty (&impl->returns_log); ddsrt_mutex_unlock (&impl->returns_log_lock); - return result; + return valid; } static DDS_Security_PermissionsHandle validate_local_permissions( @@ -162,11 +172,8 @@ static DDS_Security_PermissionsHandle validate_local_permissions( } /* fall through */ case PLUGIN_MODE_WRAPPED: - case PLUGIN_MODE_CHECK_RETURNS: { DDS_Security_PermissionsHandle handle = impl->instance->validate_local_permissions(impl->instance, auth_plugin, identity, domain_id, participant_qos, ex); - if (impl->mode == PLUGIN_MODE_CHECK_RETURNS) - register_return_obj (impl, (void *) handle); return handle; } @@ -196,12 +203,9 @@ static DDS_Security_PermissionsHandle validate_remote_permissions( } /* fall through */ case PLUGIN_MODE_WRAPPED: - case PLUGIN_MODE_CHECK_RETURNS: { DDS_Security_PermissionsHandle handle = impl->instance->validate_remote_permissions(impl->instance, auth_plugin, local_identity_handle, remote_identity_handle, remote_permissions_token, remote_credential_token, ex); - if (impl->mode == PLUGIN_MODE_CHECK_RETURNS) - register_return_obj (impl, (void *) handle); return handle; } @@ -229,7 +233,6 @@ static DDS_Security_boolean check_create_participant( } /* fall through */ case PLUGIN_MODE_WRAPPED: - case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_create_participant(impl->instance, permissions_handle, domain_id, participant_qos, ex); default: @@ -262,7 +265,6 @@ static DDS_Security_boolean check_create_datawriter( } /* fall through */ case PLUGIN_MODE_WRAPPED: - case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_create_datawriter(impl->instance, permissions_handle, domain_id, topic_name, writer_qos, partition, data_tag, ex); default: @@ -292,7 +294,6 @@ static DDS_Security_boolean check_create_datareader( } /* fall through */ case PLUGIN_MODE_WRAPPED: - case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_create_datareader(impl->instance, permissions_handle, domain_id, topic_name, reader_qos, partition, data_tag, ex); default: @@ -320,7 +321,6 @@ static DDS_Security_boolean check_create_topic( } /* fall through */ case PLUGIN_MODE_WRAPPED: - case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_create_topic(impl->instance, permissions_handle, domain_id, topic_name, qos, ex); default: @@ -340,7 +340,6 @@ static DDS_Security_boolean check_local_datawriter_register_instance( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: - case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_local_datawriter_register_instance(impl->instance, permissions_handle, writer, key, ex); default: @@ -360,7 +359,6 @@ static DDS_Security_boolean check_local_datawriter_dispose_instance( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: - case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_local_datawriter_dispose_instance(impl->instance, permissions_handle, writer, key, ex); default: @@ -387,7 +385,6 @@ static DDS_Security_boolean check_remote_participant( } /* fall through */ case PLUGIN_MODE_WRAPPED: - case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_remote_participant(impl->instance, permissions_handle, domain_id, participant_data, ex); default: @@ -414,7 +411,6 @@ static DDS_Security_boolean check_remote_datawriter( } /* fall through */ case PLUGIN_MODE_WRAPPED: - case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_remote_datawriter(impl->instance, permissions_handle, domain_id, publication_data, ex); default: @@ -445,7 +441,6 @@ static DDS_Security_boolean check_remote_datareader( } /* fall through */ case PLUGIN_MODE_WRAPPED: - case PLUGIN_MODE_CHECK_RETURNS: { bool ret; if ((ret = impl->instance->check_remote_datareader(impl->instance, permissions_handle, domain_id, subscription_data, relay_only, ex))) @@ -485,7 +480,6 @@ static DDS_Security_boolean check_remote_topic( } /* fall through */ case PLUGIN_MODE_WRAPPED: - case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_remote_topic(impl->instance, permissions_handle, domain_id, topic_data, ex); default: @@ -506,7 +500,6 @@ static DDS_Security_boolean check_local_datawriter_match( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: - case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_local_datawriter_match(impl->instance, writer_permissions_handle, reader_permissions_handle, publication_data, subscription_data, ex); default: @@ -527,7 +520,6 @@ static DDS_Security_boolean check_local_datareader_match( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: - case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_local_datareader_match(impl->instance, reader_permissions_handle, writer_permissions_handle, subscription_data, publication_data, ex); default: @@ -549,7 +541,6 @@ static DDS_Security_boolean check_remote_datawriter_register_instance( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: - case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_remote_datawriter_register_instance(impl->instance, permissions_handle, reader, publication_handle, key, instance_handle, ex); default: @@ -570,7 +561,6 @@ static DDS_Security_boolean check_remote_datawriter_dispose_instance( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: - case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->check_remote_datawriter_dispose_instance(impl->instance, permissions_handle, reader, publication_handle, key, ex); default: @@ -587,10 +577,9 @@ static DDS_Security_boolean get_permissions_token( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { - case PLUGIN_MODE_CHECK_RETURNS: + case PLUGIN_MODE_WRAPPED: register_return_obj (impl, (void*) permissions_token); /* fall through */ - case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->get_permissions_token(impl->instance, permissions_token, handle, ex); @@ -610,10 +599,9 @@ static DDS_Security_boolean get_permissions_credential_token( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { - case PLUGIN_MODE_CHECK_RETURNS: + case PLUGIN_MODE_WRAPPED: register_return_obj (impl, (void*) permissions_credential_token); /* fall through */ - case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->get_permissions_credential_token(impl->instance, permissions_credential_token, handle, ex); @@ -632,7 +620,6 @@ static DDS_Security_boolean set_listener( { case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: - case PLUGIN_MODE_CHECK_RETURNS: return impl->instance->set_listener (impl->instance, listener, ex); default: @@ -648,10 +635,9 @@ static DDS_Security_boolean return_permissions_token( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { - case PLUGIN_MODE_CHECK_RETURNS: + case PLUGIN_MODE_WRAPPED: unregister_return_obj (impl, (void*) token); /* fall through */ - case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->return_permissions_token (impl->instance, token, ex); @@ -669,10 +655,9 @@ static DDS_Security_boolean return_permissions_credential_token( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { - case PLUGIN_MODE_CHECK_RETURNS: + case PLUGIN_MODE_WRAPPED: unregister_return_obj (impl, (void*) permissions_credential_token); /* fall through */ - case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->return_permissions_credential_token(impl->instance, permissions_credential_token, ex); @@ -690,10 +675,9 @@ static DDS_Security_boolean get_participant_sec_attributes( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { - case PLUGIN_MODE_CHECK_RETURNS: + case PLUGIN_MODE_WRAPPED: register_return_obj (impl, (void*) attributes); /* fall through */ - case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->get_participant_sec_attributes(impl->instance, permissions_handle, attributes, ex); @@ -712,10 +696,9 @@ static DDS_Security_boolean get_topic_sec_attributes( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { - case PLUGIN_MODE_CHECK_RETURNS: + case PLUGIN_MODE_WRAPPED: register_return_obj (impl, (void*) attributes); /* fall through */ - case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->get_topic_sec_attributes(impl->instance, permissions_handle, topic_name, attributes, ex); @@ -736,10 +719,9 @@ static DDS_Security_boolean get_datawriter_sec_attributes( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { - case PLUGIN_MODE_CHECK_RETURNS: + case PLUGIN_MODE_WRAPPED: register_return_obj (impl, (void*) attributes); /* fall through */ - case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->get_datawriter_sec_attributes(impl->instance, permissions_handle, topic_name, partition, data_tag, attributes, ex); @@ -760,10 +742,9 @@ static DDS_Security_boolean get_datareader_sec_attributes( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { - case PLUGIN_MODE_CHECK_RETURNS: + case PLUGIN_MODE_WRAPPED: register_return_obj (impl, (void*) attributes); /* fall through */ - case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->get_datareader_sec_attributes(impl->instance, permissions_handle, topic_name, partition, data_tag, attributes, ex); @@ -780,10 +761,9 @@ static DDS_Security_boolean return_participant_sec_attributes( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { - case PLUGIN_MODE_CHECK_RETURNS: + case PLUGIN_MODE_WRAPPED: unregister_return_obj (impl, (void*) attributes); /* fall through */ - case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->return_participant_sec_attributes(impl->instance, attributes, ex); @@ -800,10 +780,9 @@ static DDS_Security_boolean return_topic_sec_attributes( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { - case PLUGIN_MODE_CHECK_RETURNS: + case PLUGIN_MODE_WRAPPED: unregister_return_obj (impl, (void*) attributes); /* fall through */ - case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->return_topic_sec_attributes(impl->instance, attributes, ex); @@ -820,10 +799,9 @@ static DDS_Security_boolean return_datawriter_sec_attributes( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { - case PLUGIN_MODE_CHECK_RETURNS: + case PLUGIN_MODE_WRAPPED: unregister_return_obj (impl, (void*) attributes); /* fall through */ - case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->return_datawriter_sec_attributes(impl->instance, attributes, ex); @@ -840,10 +818,9 @@ static DDS_Security_boolean return_datareader_sec_attributes( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { - case PLUGIN_MODE_CHECK_RETURNS: + case PLUGIN_MODE_WRAPPED: unregister_return_obj (impl, (void*) attributes); /* fall through */ - case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->return_datareader_sec_attributes(impl->instance, attributes, ex); @@ -860,9 +837,6 @@ static DDS_Security_boolean return_permissions_handle( struct dds_security_access_control_impl *impl = (struct dds_security_access_control_impl *)instance; switch (impl->mode) { - case PLUGIN_MODE_CHECK_RETURNS: - unregister_return_obj (impl, (void*) permissions_handle); - /* fall through */ case PLUGIN_MODE_WRAPPED: case PLUGIN_MODE_NOT_ALLOWED: return impl->instance->return_permissions_handle(impl->instance, permissions_handle, ex); @@ -947,6 +921,7 @@ int init_test_access_control_wrapped(const char *argument, void **context, struc if (!impl) return DDS_SECURITY_FAILED; impl->mode = PLUGIN_MODE_WRAPPED; + init_returns_log (impl); *context = impl; return DDS_SECURITY_SUCCESS; } @@ -954,8 +929,12 @@ int init_test_access_control_wrapped(const char *argument, void **context, struc int finalize_test_access_control_wrapped(void *context) { struct dds_security_access_control_impl* impl = (struct dds_security_access_control_impl*) context; - assert(impl->mode == PLUGIN_MODE_WRAPPED); - return finalize_test_access_control_common(impl, true); + assert (impl->mode == PLUGIN_MODE_WRAPPED); + bool returns_valid = all_returns_valid (impl); + fini_returns_log (impl); + printf("returns result (impl %p): %s\n", impl, returns_valid ? "all valid" : "invalid"); + CU_ASSERT_FATAL (returns_valid); + return finalize_test_access_control_common (impl, true); } int init_test_access_control_missing_func(const char *argument, void **context, struct ddsi_domaingv *gv) @@ -1004,22 +983,3 @@ int finalize_test_access_control_not_allowed(void *context) assert(impl->mode == PLUGIN_MODE_NOT_ALLOWED); return finalize_test_access_control_common(impl, true); } - -int init_test_access_control_check_returns(const char *argument, void **context, struct ddsi_domaingv *gv) -{ - struct dds_security_access_control_impl *impl = init_test_access_control_common(argument, true, gv); - if (!impl) - return DDS_SECURITY_FAILED; - impl->mode = PLUGIN_MODE_CHECK_RETURNS; - init_returns_log (impl); - *context = impl; - return DDS_SECURITY_SUCCESS; -} - -int finalize_test_access_control_check_returns(void *context) -{ - struct dds_security_access_control_impl* impl = (struct dds_security_access_control_impl*) context; - assert(impl->mode == PLUGIN_MODE_CHECK_RETURNS); - fini_returns_log (impl); - return finalize_test_access_control_common(impl, true); -} diff --git a/src/security/core/tests/common/access_control_wrapper.h b/src/security/core/tests/common/access_control_wrapper.h index 8dc0ecd..a876311 100644 --- a/src/security/core/tests/common/access_control_wrapper.h +++ b/src/security/core/tests/common/access_control_wrapper.h @@ -22,8 +22,6 @@ struct dds_security_access_control_impl; -SECURITY_EXPORT bool check_returns (struct dds_security_access_control_impl * impl); - /* Init in all-ok mode: all functions return success without calling the actual plugin */ SECURITY_EXPORT int init_test_access_control_all_ok(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int finalize_test_access_control_all_ok(void *context); @@ -53,9 +51,4 @@ INIT_NOT_ALLOWED_DECL(remote_permissions_not_allowed) SECURITY_EXPORT int finalize_test_access_control_not_allowed(void *context); -/* Init in attribute get and return logging mode */ -SECURITY_EXPORT int init_test_access_control_check_returns(const char *argument, void **context, struct ddsi_domaingv *gv); -SECURITY_EXPORT int finalize_test_access_control_check_returns(void *context); - - #endif /* SECURITY_CORE_TEST_ACCESS_CONTROL_WRAPPER_H_ */ diff --git a/src/security/core/tests/common/cryptography_wrapper.c b/src/security/core/tests/common/cryptography_wrapper.c index ada7591..47d06c7 100644 --- a/src/security/core/tests/common/cryptography_wrapper.c +++ b/src/security/core/tests/common/cryptography_wrapper.c @@ -195,7 +195,7 @@ static void add_tokens (struct ddsrt_circlist *list, enum crypto_tokens_type typ token_data->local_handle = lch; token_data->remote_handle = rch; token_data->n_tokens = tokens->_length; - assert (tokens->_length <= CRYPTO_TOKEN_MAXLEN); + assert (tokens->_length <= CRYPTO_TOKEN_MAXCOUNT); for (uint32_t i = 0; i < tokens->_length; i++) { size_t len = tokens->_buffer[i].binary_properties._buffer[0].value._length; @@ -235,16 +235,14 @@ struct ddsrt_circlist * get_crypto_tokens (struct dds_security_cryptography_impl } struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->token_data_list), *elem = elem0; - while (elem != NULL) + do { struct crypto_token_data *elem_data = DDSRT_FROM_CIRCLIST (struct crypto_token_data, e, elem); struct crypto_token_data *token_data = ddsrt_malloc (sizeof (*token_data)); memcpy (token_data, elem_data, sizeof (*token_data)); ddsrt_circlist_append (tokens, &token_data->e); elem = elem->next; - if (elem == elem0) - break; - } + } while (elem != elem0); ddsrt_mutex_unlock (&impl->token_data_lock); return tokens; @@ -260,7 +258,7 @@ struct crypto_token_data * find_crypto_token (struct dds_security_cryptography_i return NULL; } struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->token_data_list), *elem = elem0; - while (elem != NULL) + do { struct crypto_token_data *elem_data = DDSRT_FROM_CIRCLIST (struct crypto_token_data, e, elem); if (elem_data->type == type) @@ -277,9 +275,7 @@ struct crypto_token_data * find_crypto_token (struct dds_security_cryptography_i } } elem = elem->next; - if (elem == elem0) - break; - } + } while (elem != elem0); ddsrt_mutex_unlock (&impl->token_data_lock); return NULL; } @@ -290,7 +286,7 @@ static void log_encode_decode (struct dds_security_cryptography_impl * impl, enu if (!ddsrt_circlist_isempty (&impl->encode_decode_log)) { struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->encode_decode_log), *elem = elem0; - while (elem != NULL) + do { struct crypto_encode_decode_data *data = DDSRT_FROM_CIRCLIST (struct crypto_encode_decode_data, e, elem); if (data->function == function && data->handle == handle) @@ -300,9 +296,7 @@ static void log_encode_decode (struct dds_security_cryptography_impl * impl, enu return; } elem = elem->next; - if (elem == elem0) - break; - } + } while (elem != elem0); } /* add new entry */ struct crypto_encode_decode_data *new_data = ddsrt_malloc (sizeof (*new_data)); @@ -319,7 +313,7 @@ struct crypto_encode_decode_data * get_encode_decode_log (struct dds_security_cr if (!ddsrt_circlist_isempty (&impl->encode_decode_log)) { struct ddsrt_circlist_elem *elem0 = ddsrt_circlist_oldest (&impl->encode_decode_log), *elem = elem0; - while (elem != NULL) + do { struct crypto_encode_decode_data *data = DDSRT_FROM_CIRCLIST (struct crypto_encode_decode_data, e, elem); if (data->function == function && data->handle == handle) @@ -330,9 +324,7 @@ struct crypto_encode_decode_data * get_encode_decode_log (struct dds_security_cr return result; } elem = elem->next; - if (elem == elem0) - break; - } + } while (elem != elem0); } ddsrt_mutex_unlock (&impl->encode_decode_log_lock); return NULL; diff --git a/src/security/core/tests/common/cryptography_wrapper.h b/src/security/core/tests/common/cryptography_wrapper.h index 98a6658..f466c55 100644 --- a/src/security/core/tests/common/cryptography_wrapper.h +++ b/src/security/core/tests/common/cryptography_wrapper.h @@ -18,7 +18,7 @@ #include "dds/security/dds_security_api_defs.h" #include "dds/security/cryptography_wrapper_export.h" -#define CRYPTO_TOKEN_MAXLEN 10 +#define CRYPTO_TOKEN_MAXCOUNT 10 #define CRYPTO_TOKEN_SIZE 256 struct dds_security_cryptography_impl; @@ -39,8 +39,8 @@ struct crypto_token_data { DDS_Security_ParticipantCryptoHandle local_handle; DDS_Security_ParticipantCryptoHandle remote_handle; uint32_t n_tokens; - unsigned char data[CRYPTO_TOKEN_MAXLEN][CRYPTO_TOKEN_SIZE]; - size_t data_len[CRYPTO_TOKEN_MAXLEN]; + unsigned char data[CRYPTO_TOKEN_MAXCOUNT][CRYPTO_TOKEN_SIZE]; + size_t data_len[CRYPTO_TOKEN_MAXCOUNT]; }; enum crypto_encode_decode_fn { From 2e6ea36fda40e62e02444c8dc53d5e222b49e66e Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Fri, 15 May 2020 14:10:11 +0200 Subject: [PATCH 196/238] Fix a race condition in delete_participant, that could occur on security permissions or identity expiry, which triggers a delete of the local participant Signed-off-by: Dennis Potman --- src/core/ddsi/src/ddsi_security_omg.c | 2 +- src/core/ddsi/src/q_entity.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 79052b2..9ef815a 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -842,7 +842,7 @@ static bool delete_pp_by_handle (DDS_Security_Handle handle, expired_pp_check_fn { if (q_omg_participant_is_secure (pp) && expired_pp_check_fn (pp, handle)) { - delete_participant (gv, &pp->e.guid); + (void) delete_participant (gv, &pp->e.guid); result = true; } } diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index b8858ca..4fb30cd 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -1308,14 +1308,19 @@ dds_return_t delete_participant (struct ddsi_domaingv *gv, const struct ddsi_gui { struct participant *pp; GVLOGDISC ("delete_participant("PGUIDFMT")\n", PGUID (*ppguid)); + ddsrt_mutex_lock (&gv->lock); if ((pp = entidx_lookup_participant_guid (gv->entity_index, ppguid)) == NULL) + { + ddsrt_mutex_unlock (&gv->lock); return DDS_RETCODE_BAD_PARAMETER; + } builtintopic_write (gv->builtin_topic_interface, &pp->e, ddsrt_time_wallclock(), false); remember_deleted_participant_guid (gv->deleted_participants, &pp->e.guid); #ifdef DDSI_INCLUDE_SECURITY disconnect_participant_secure (pp); #endif entidx_remove_participant_guid (gv->entity_index, pp); + ddsrt_mutex_unlock (&gv->lock); gcreq_participant (pp); return 0; } From 5f829684effc2e68c13a46fb1789cbc6397f8ce7 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 18 Apr 2020 17:32:56 +0200 Subject: [PATCH 197/238] Distinguish signed, float in type descriptor * Add a flag to indicate signed integral values and one to indicate floating-point values * Set these flags in the output of idlc * Use them when printing sample contents to the trace By encoding the information as flags in reserved bits the actual serialization and deserialization is unaffected. Signed-off-by: Erik Boasson --- .../ddsc/include/dds/ddsc/dds_public_impl.h | 7 +++ src/core/ddsi/src/ddsi_cdrstream.c | 62 ++++++++++++++----- .../cyclonedds/generator/BasicType.java | 12 ++-- 3 files changed, 58 insertions(+), 23 deletions(-) diff --git a/src/core/ddsc/include/dds/ddsc/dds_public_impl.h b/src/core/ddsc/include/dds/ddsc/dds_public_impl.h index 730020c..46bfcbe 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_public_impl.h +++ b/src/core/ddsc/include/dds/ddsc/dds_public_impl.h @@ -225,6 +225,13 @@ enum dds_stream_typecode_subtype { #define DDS_OP_FLAG_KEY 0x01 /* key field: applicable to {1,2,4,8}BY, STR, BST, ARR-of-{1,2,4,8}BY */ #define DDS_OP_FLAG_DEF 0x02 /* union has a default case (for DDS_OP_ADR | DDS_OP_TYPE_UNI) */ +/* For a union: (1) the discriminator may be a key field; (2) there may be a default value; + and (3) the discriminator can be an integral type (or enumerated - here treated as equivalent). + What it can't be is a floating-point type. So DEF and FP need never be set at the same time. + There are only a few flag bits, so saving one is not such a bad idea. */ +#define DDS_OP_FLAG_FP 0x02 /* floating-point: applicable to {4,8}BY and arrays, sequences of them */ +#define DDS_OP_FLAG_SGN 0x04 /* signed: applicable to {1,2,4,8}BY and arrays, sequences of them */ + /** * Description : Enable or disable write batching. Overrides default configuration * setting for write batching (Internal/WriteBatch). diff --git a/src/core/ddsi/src/ddsi_cdrstream.c b/src/core/ddsi/src/ddsi_cdrstream.c index 3565d45..6cdfb80 100644 --- a/src/core/ddsi/src/ddsi_cdrstream.c +++ b/src/core/ddsi/src/ddsi_cdrstream.c @@ -1995,14 +1995,42 @@ static size_t isprint_runlen (const unsigned char *s, size_t n) return m; } -static bool prtf_simple (char * __restrict *buf, size_t * __restrict bufsize, dds_istream_t * __restrict is, enum dds_stream_typecode type) +static bool prtf_simple (char * __restrict *buf, size_t * __restrict bufsize, dds_istream_t * __restrict is, enum dds_stream_typecode type, unsigned flags) { switch (type) { - case DDS_OP_VAL_1BY: return prtf (buf, bufsize, "%"PRIu8, dds_is_get1 (is)); - case DDS_OP_VAL_2BY: return prtf (buf, bufsize, "%"PRIu16, dds_is_get2 (is)); - case DDS_OP_VAL_4BY: return prtf (buf, bufsize, "%"PRIu32, dds_is_get4 (is)); - case DDS_OP_VAL_8BY: return prtf (buf, bufsize, "%"PRIu64, dds_is_get8 (is)); + case DDS_OP_VAL_1BY: { + const union { int8_t s; uint8_t u; } x = { .u = dds_is_get1 (is) }; + if (flags & DDS_OP_FLAG_SGN) + return prtf (buf, bufsize, "%"PRId8, x.s); + else + return prtf (buf, bufsize, "%"PRIu8, x.u); + } + case DDS_OP_VAL_2BY: { + const union { int16_t s; uint16_t u; } x = { .u = dds_is_get2 (is) }; + if (flags & DDS_OP_FLAG_SGN) + return prtf (buf, bufsize, "%"PRId16, x.s); + else + return prtf (buf, bufsize, "%"PRIu16, x.u); + } + case DDS_OP_VAL_4BY: { + const union { int32_t s; uint32_t u; float f; } x = { .u = dds_is_get4 (is) }; + if (flags & DDS_OP_FLAG_FP) + return prtf (buf, bufsize, "%g", x.f); + else if (flags & DDS_OP_FLAG_SGN) + return prtf (buf, bufsize, "%"PRId32, x.s); + else + return prtf (buf, bufsize, "%"PRIu32, x.u); + } + case DDS_OP_VAL_8BY: { + const union { int64_t s; uint64_t u; double f; } x = { .u = dds_is_get8 (is) }; + if (flags & DDS_OP_FLAG_FP) + return prtf (buf, bufsize, "%g", x.f); + else if (flags & DDS_OP_FLAG_SGN) + return prtf (buf, bufsize, "%"PRId64, x.s); + else + return prtf (buf, bufsize, "%"PRIu64, x.u); + } case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: return prtf_str (buf, bufsize, is); case DDS_OP_VAL_ARR: case DDS_OP_VAL_SEQ: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: abort (); @@ -2010,7 +2038,7 @@ static bool prtf_simple (char * __restrict *buf, size_t * __restrict bufsize, dd return false; } -static bool prtf_simple_array (char * __restrict *buf, size_t * __restrict bufsize, dds_istream_t * __restrict is, uint32_t num, enum dds_stream_typecode type) +static bool prtf_simple_array (char * __restrict *buf, size_t * __restrict bufsize, dds_istream_t * __restrict is, uint32_t num, enum dds_stream_typecode type, unsigned flags) { bool cont = prtf (buf, bufsize, "{"); switch (type) @@ -2033,7 +2061,7 @@ static bool prtf_simple_array (char * __restrict *buf, size_t * __restrict bufsi { if (i != 0) (void) prtf (buf, bufsize, ","); - cont = prtf_simple (buf, bufsize, is, type); + cont = prtf_simple (buf, bufsize, is, type, flags); i++; } } @@ -2045,7 +2073,7 @@ static bool prtf_simple_array (char * __restrict *buf, size_t * __restrict bufsi { if (i != 0) (void) prtf (buf, bufsize, ","); - cont = prtf_simple (buf, bufsize, is, type); + cont = prtf_simple (buf, bufsize, is, type, flags); } break; default: @@ -2070,10 +2098,10 @@ static const uint32_t *prtf_seq (char * __restrict *buf, size_t *bufsize, dds_is switch (subtype) { case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: - (void) prtf_simple_array (buf, bufsize, is, num, subtype); + (void) prtf_simple_array (buf, bufsize, is, num, subtype, DDS_OP_FLAGS (insn)); return ops + 2; case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: - (void) prtf_simple_array (buf, bufsize, is, num, subtype); + (void) prtf_simple_array (buf, bufsize, is, num, subtype, DDS_OP_FLAGS (insn)); return ops + (subtype == DDS_OP_VAL_STR ? 2 : 3); case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { const uint32_t jmp = DDS_OP_ADR_JMP (ops[3]); @@ -2098,10 +2126,10 @@ static const uint32_t *prtf_arr (char * __restrict *buf, size_t *bufsize, dds_is switch (subtype) { case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: - (void) prtf_simple_array (buf, bufsize, is, num, subtype); + (void) prtf_simple_array (buf, bufsize, is, num, subtype, DDS_OP_FLAGS (insn)); return ops + 3; case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: - (void) prtf_simple_array (buf, bufsize, is, num, subtype); + (void) prtf_simple_array (buf, bufsize, is, num, subtype, DDS_OP_FLAGS (insn)); return ops + (subtype == DDS_OP_VAL_STR ? 3 : 5); case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: { const uint32_t *jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]); @@ -2132,7 +2160,7 @@ static const uint32_t *prtf_uni (char * __restrict *buf, size_t *bufsize, dds_is { case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: - (void) prtf_simple (buf, bufsize, is, valtype); + (void) prtf_simple (buf, bufsize, is, valtype, DDS_OP_FLAGS (jeq_op[0])); break; case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: (void) dds_stream_print_sample1 (buf, bufsize, is, jeq_op + DDS_OP_ADR_JSR (jeq_op[0]), valtype == DDS_OP_VAL_STU); @@ -2161,11 +2189,11 @@ static bool dds_stream_print_sample1 (char * __restrict *buf, size_t * __restric { case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_STR: - cont = prtf_simple (buf, bufsize, is, DDS_OP_TYPE (insn)); + cont = prtf_simple (buf, bufsize, is, DDS_OP_TYPE (insn), DDS_OP_FLAGS (insn)); ops += 2; break; case DDS_OP_VAL_BST: - cont = prtf_simple (buf, bufsize, is, DDS_OP_TYPE (insn)); + cont = prtf_simple (buf, bufsize, is, DDS_OP_TYPE (insn), DDS_OP_FLAGS (insn)); ops += 3; break; case DDS_OP_VAL_SEQ: @@ -2217,10 +2245,10 @@ size_t dds_stream_print_key (dds_istream_t * __restrict is, const struct ddsi_se { case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY: case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: - cont = prtf_simple (&buf, &bufsize, is, DDS_OP_TYPE (*op)); + cont = prtf_simple (&buf, &bufsize, is, DDS_OP_TYPE (*op), DDS_OP_FLAGS (*op)); break; case DDS_OP_VAL_ARR: - cont = prtf_simple_array (&buf, &bufsize, is, op[2], DDS_OP_SUBTYPE (*op)); + cont = prtf_simple_array (&buf, &bufsize, is, op[2], DDS_OP_SUBTYPE (*op), DDS_OP_FLAGS (*op)); break; case DDS_OP_VAL_SEQ: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: abort (); diff --git a/src/idlc/src/org/eclipse/cyclonedds/generator/BasicType.java b/src/idlc/src/org/eclipse/cyclonedds/generator/BasicType.java index 6ddb67b..8964e7f 100644 --- a/src/idlc/src/org/eclipse/cyclonedds/generator/BasicType.java +++ b/src/idlc/src/org/eclipse/cyclonedds/generator/BasicType.java @@ -20,15 +20,15 @@ public class BasicType extends AbstractType { BOOLEAN ("bool", "DDS_OP_TYPE_BOO", "DDS_OP_SUBTYPE_BOO", Alignment.BOOL, "Boolean"), OCTET ("uint8_t", "DDS_OP_TYPE_1BY", "DDS_OP_SUBTYPE_1BY", Alignment.ONE, "Octet"), - CHAR ("char", "DDS_OP_TYPE_1BY", "DDS_OP_SUBTYPE_1BY", Alignment.ONE, "Char"), - SHORT ("int16_t", "DDS_OP_TYPE_2BY", "DDS_OP_SUBTYPE_2BY", Alignment.TWO, "Short"), + CHAR ("char", "DDS_OP_TYPE_1BY | DDS_OP_FLAG_SGN", "DDS_OP_SUBTYPE_1BY | DDS_OP_FLAG_SGN", Alignment.ONE, "Char"), + SHORT ("int16_t", "DDS_OP_TYPE_2BY | DDS_OP_FLAG_SGN", "DDS_OP_SUBTYPE_2BY | DDS_OP_FLAG_SGN", Alignment.TWO, "Short"), USHORT ("uint16_t", "DDS_OP_TYPE_2BY", "DDS_OP_SUBTYPE_2BY", Alignment.TWO, "UShort"), - LONG ("int32_t", "DDS_OP_TYPE_4BY", "DDS_OP_SUBTYPE_4BY", Alignment.FOUR, "Long"), + LONG ("int32_t", "DDS_OP_TYPE_4BY | DDS_OP_FLAG_SGN", "DDS_OP_SUBTYPE_4BY | DDS_OP_FLAG_SGN", Alignment.FOUR, "Long"), ULONG ("uint32_t", "DDS_OP_TYPE_4BY", "DDS_OP_SUBTYPE_4BY", Alignment.FOUR, "ULong"), - LONGLONG ("int64_t", "DDS_OP_TYPE_8BY", "DDS_OP_SUBTYPE_8BY", Alignment.EIGHT, "LongLong"), + LONGLONG ("int64_t", "DDS_OP_TYPE_8BY | DDS_OP_FLAG_SGN", "DDS_OP_SUBTYPE_8BY | DDS_OP_FLAG_SGN", Alignment.EIGHT, "LongLong"), ULONGLONG ("uint64_t", "DDS_OP_TYPE_8BY", "DDS_OP_SUBTYPE_8BY", Alignment.EIGHT, "ULongLong"), - FLOAT ("float", "DDS_OP_TYPE_4BY", "DDS_OP_SUBTYPE_4BY", Alignment.FOUR, "Float"), - DOUBLE ("double", "DDS_OP_TYPE_8BY", "DDS_OP_SUBTYPE_8BY", Alignment.EIGHT, "Double"), + FLOAT ("float", "DDS_OP_TYPE_4BY | DDS_OP_FLAG_FP", "DDS_OP_SUBTYPE_4BY | DDS_OP_FLAG_FP", Alignment.FOUR, "Float"), + DOUBLE ("double", "DDS_OP_TYPE_8BY | DDS_OP_FLAG_FP", "DDS_OP_SUBTYPE_8BY | DDS_OP_FLAG_FP", Alignment.EIGHT, "Double"), STRING ("char *", "DDS_OP_TYPE_STR", "DDS_OP_SUBTYPE_STR", Alignment.PTR, "String"); public final String cType; From 9aef05542f4d00a060b036e50a1a3e1118ddf7c7 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sun, 19 Apr 2020 17:36:01 +0200 Subject: [PATCH 198/238] Do not scan instances in dds_{read,take}_instance Scanning all instances was never good for anything: the RHC is organised as hash table on instance id (which is an alias for "instance handle") and it was always designed to do this with a fast lookup. Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/ddsc/dds_rhc.h | 17 +- src/core/ddsc/src/dds_read.c | 20 +- src/core/ddsc/src/dds_rhc_default.c | 708 ++++++++++------------- 3 files changed, 320 insertions(+), 425 deletions(-) diff --git a/src/core/ddsc/include/dds/ddsc/dds_rhc.h b/src/core/ddsc/include/dds/ddsc/dds_rhc.h index d0413e6..b5cba34 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_rhc.h +++ b/src/core/ddsc/include/dds/ddsc/dds_rhc.h @@ -27,9 +27,8 @@ struct dds_reader; struct ddsi_tkmap; typedef dds_return_t (*dds_rhc_associate_t) (struct dds_rhc *rhc, struct dds_reader *reader, const struct ddsi_sertopic *topic, struct ddsi_tkmap *tkmap); -typedef int (*dds_rhc_read_t) (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond); -typedef int (*dds_rhc_take_t) (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond); -typedef int (*dds_rhc_takecdr_t) (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle); +typedef int32_t (*dds_rhc_read_take_t) (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond); +typedef int32_t (*dds_rhc_read_take_cdr_t) (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle); typedef bool (*dds_rhc_add_readcondition_t) (struct dds_rhc *rhc, struct dds_readcond *cond); typedef void (*dds_rhc_remove_readcondition_t) (struct dds_rhc *rhc, struct dds_readcond *cond); @@ -40,9 +39,9 @@ struct dds_rhc_ops { /* A copy of DDSI rhc ops comes first so we can use either interface without additional indirections */ struct ddsi_rhc_ops rhc_ops; - dds_rhc_read_t read; - dds_rhc_take_t take; - dds_rhc_takecdr_t takecdr; + dds_rhc_read_take_t read; + dds_rhc_read_take_t take; + dds_rhc_read_take_cdr_t takecdr; dds_rhc_add_readcondition_t add_readcondition; dds_rhc_remove_readcondition_t remove_readcondition; dds_rhc_lock_samples_t lock_samples; @@ -76,13 +75,13 @@ DDS_EXPORT inline void dds_rhc_set_qos (struct dds_rhc *rhc, const struct dds_qo DDS_EXPORT inline void dds_rhc_free (struct dds_rhc *rhc) { rhc->common.ops->rhc_ops.free (&rhc->common.rhc); } -DDS_EXPORT inline int dds_rhc_read (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond) { +DDS_EXPORT inline int32_t dds_rhc_read (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond) { return (rhc->common.ops->read) (rhc, lock, values, info_seq, max_samples, mask, handle, cond); } -DDS_EXPORT inline int dds_rhc_take (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond) { +DDS_EXPORT inline int32_t dds_rhc_take (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond) { return rhc->common.ops->take (rhc, lock, values, info_seq, max_samples, mask, handle, cond); } -DDS_EXPORT inline int dds_rhc_takecdr (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) { +DDS_EXPORT inline int32_t dds_rhc_takecdr (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) { return rhc->common.ops->takecdr (rhc, lock, values, info_seq, max_samples, sample_states, view_states, instance_states, handle); } DDS_EXPORT inline bool dds_rhc_add_readcondition (struct dds_rhc *rhc, struct dds_readcond *cond) { diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index 701f50d..fd9ae5b 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -40,7 +40,7 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition, #define NC_FREE_BUF 2u #define NC_RESET_BUF 4u - if (buf == NULL || si == NULL || maxs == 0 || bufsz == 0 || bufsz < maxs) + if (buf == NULL || si == NULL || maxs == 0 || bufsz == 0 || bufsz < maxs || maxs > INT32_MAX) return DDS_RETCODE_BAD_PARAMETER; if ((ret = dds_entity_pin (reader_or_condition, &entity)) < 0) { @@ -61,14 +61,6 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition, thread_state_awake (ts1, &entity->m_domain->gv); - if (hand != DDS_HANDLE_NIL) - { - if (ddsi_tkmap_find_by_id (entity->m_domain->gv.m_tkmap, hand) == NULL) { - ret = DDS_RETCODE_PRECONDITION_NOT_MET; - goto fail_awake_pinned; - } - } - /* Allocate samples if not provided (assuming all or none provided) */ if (buf[0] == NULL) { @@ -142,8 +134,6 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition, #undef NC_FREE_BUF #undef NC_RESET_BUF -fail_awake_pinned: - thread_state_asleep (ts1); fail_pinned: dds_entity_unpin (entity); fail: @@ -157,12 +147,8 @@ static dds_return_t dds_readcdr_impl (bool take, dds_entity_t reader_or_conditio struct dds_reader *rd; struct dds_entity *entity; - assert (take); - assert (buf); - assert (si); - assert (hand == DDS_HANDLE_NIL); - assert (maxs > 0); - (void)take; + if (buf == NULL || si == NULL || maxs == 0 || maxs > INT32_MAX) + return DDS_RETCODE_BAD_PARAMETER; if ((ret = dds_entity_pin (reader_or_condition, &entity)) < 0) { return ret; diff --git a/src/core/ddsc/src/dds_rhc_default.c b/src/core/ddsc/src/dds_rhc_default.c index 50313ed..07692e7 100644 --- a/src/core/ddsc/src/dds_rhc_default.c +++ b/src/core/ddsc/src/dds_rhc_default.c @@ -337,7 +337,7 @@ struct dds_rhc_default { }; struct trigger_info_cmn { - unsigned qminst; + uint32_t qminst; bool has_read; bool has_not_read; }; @@ -368,9 +368,9 @@ static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, cons static void dds_rhc_default_unregister_wr (struct dds_rhc_default * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo); static void dds_rhc_default_relinquish_ownership (struct dds_rhc_default * __restrict rhc, const uint64_t wr_iid); static void dds_rhc_default_set_qos (struct dds_rhc_default *rhc, const struct dds_qos *qos); -static int dds_rhc_default_read (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond); -static int dds_rhc_default_take (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond); -static int dds_rhc_default_takecdr (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle); +static int32_t dds_rhc_default_read (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond); +static int32_t dds_rhc_default_take (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond); +static int32_t dds_rhc_default_takecdr (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle); static bool dds_rhc_default_add_readcondition (struct dds_rhc_default *rhc, dds_readcond *cond); static void dds_rhc_default_remove_readcondition (struct dds_rhc_default *rhc, dds_readcond *cond); static uint32_t dds_rhc_default_lock_samples (struct dds_rhc_default *rhc); @@ -390,13 +390,13 @@ static void dds_rhc_default_relinquish_ownership_wrap (struct ddsi_rhc * __restr static void dds_rhc_default_set_qos_wrap (struct ddsi_rhc *rhc, const struct dds_qos *qos) { dds_rhc_default_set_qos ((struct dds_rhc_default *) rhc, qos); } -static int dds_rhc_default_read_wrap (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) { +static int32_t dds_rhc_default_read_wrap (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) { return dds_rhc_default_read ((struct dds_rhc_default *) rhc, lock, values, info_seq, max_samples, mask, handle, cond); } -static int dds_rhc_default_take_wrap (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) { +static int32_t dds_rhc_default_take_wrap (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) { return dds_rhc_default_take ((struct dds_rhc_default *) rhc, lock, values, info_seq, max_samples, mask, handle, cond); } -static int dds_rhc_default_takecdr_wrap (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) { +static int32_t dds_rhc_default_takecdr_wrap (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) { return dds_rhc_default_takecdr ((struct dds_rhc_default *) rhc, lock, values, info_seq, max_samples, sample_states, view_states, instance_states, handle); } static bool dds_rhc_default_add_readcondition_wrap (struct dds_rhc *rhc, dds_readcond *cond) { @@ -432,12 +432,12 @@ static const struct dds_rhc_ops dds_rhc_default_ops = { .associate = dds_rhc_default_associate }; -static unsigned qmask_of_sample (const struct rhc_sample *s) +static uint32_t qmask_of_sample (const struct rhc_sample *s) { return s->isread ? DDS_READ_SAMPLE_STATE : DDS_NOT_READ_SAMPLE_STATE; } -static unsigned qmask_of_invsample (const struct rhc_instance *i) +static uint32_t qmask_of_invsample (const struct rhc_instance *i) { return i->inv_isread ? DDS_READ_SAMPLE_STATE : DDS_NOT_READ_SAMPLE_STATE; } @@ -467,17 +467,17 @@ static bool inst_has_unread (const struct rhc_instance *i) return inst_nread (i) < inst_nsamples (i); } -static void topicless_to_clean_invsample (const struct ddsi_sertopic *topic, const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim) +static bool topicless_to_clean_invsample (const struct ddsi_sertopic *topic, const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim) { /* ddsi_serdata_topicless_to_sample just deals with the key value, without paying any attention to attributes; but that makes life harder for the user: the attributes of an invalid sample would be garbage, but would nonetheless have to be freed in the end. Zero'ing it explicitly solves that problem. */ ddsi_sertopic_free_sample (topic, sample, DDS_FREE_CONTENTS); ddsi_sertopic_zero_sample (topic, sample); - ddsi_serdata_topicless_to_sample (topic, d, sample, bufptr, buflim); + return ddsi_serdata_topicless_to_sample (topic, d, sample, bufptr, buflim); } -static unsigned qmask_of_inst (const struct rhc_instance *inst); +static uint32_t qmask_of_inst (const struct rhc_instance *inst); static void free_sample (struct dds_rhc_default *rhc, struct rhc_instance *inst, struct rhc_sample *s); static void get_trigger_info_cmn (struct trigger_info_cmn *info, struct rhc_instance *inst); static void get_trigger_info_pre (struct trigger_info_pre *info, struct rhc_instance *inst); @@ -1462,7 +1462,7 @@ static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk) { const uint64_t wr_iid = wrinfo->iid; - const unsigned statusinfo = sample->statusinfo; + const uint32_t statusinfo = sample->statusinfo; const bool has_data = (sample->kind == SDK_DATA); const int is_dispose = (statusinfo & NN_STATUSINFO_DISPOSE) != 0; struct rhc_instance dummy_instance; @@ -1845,9 +1845,9 @@ static void dds_rhc_default_relinquish_ownership (struct dds_rhc_default * __res instance: ANY, ALIVE, NOT_ALIVE, NOT_ALIVE_NO_WRITERS, NOT_ALIVE_DISPOSED */ -static unsigned qmask_of_inst (const struct rhc_instance *inst) +static uint32_t qmask_of_inst (const struct rhc_instance *inst) { - unsigned qm = inst->isnew ? DDS_NEW_VIEW_STATE : DDS_NOT_NEW_VIEW_STATE; + uint32_t qm = inst->isnew ? DDS_NEW_VIEW_STATE : DDS_NOT_NEW_VIEW_STATE; if (inst->isdisposed) qm |= DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE; @@ -1905,9 +1905,9 @@ static uint32_t qmask_from_dcpsquery (uint32_t sample_states, uint32_t view_stat return qminv; } -static unsigned qmask_from_mask_n_cond (uint32_t mask, dds_readcond* cond) +static uint32_t qmask_from_mask_n_cond (uint32_t mask, dds_readcond* cond) { - unsigned qminv; + uint32_t qminv; if (mask == NO_STATE_MASK_SET) { if (cond) { /* No mask set, use the one from the condition. */ @@ -1962,12 +1962,11 @@ static void patch_generations (dds_sample_info_t *si, uint32_t last_of_inst) { if (last_of_inst > 0) { - const unsigned ref = + const uint32_t ref = si[last_of_inst].disposed_generation_count + si[last_of_inst].no_writers_generation_count; - uint32_t i; assert (si[last_of_inst].sample_rank == 0); assert (si[last_of_inst].generation_rank == 0); - for (i = 0; i < last_of_inst; i++) + for (uint32_t i = 0; i < last_of_inst; i++) { si[i].sample_rank = last_of_inst - i; si[i].generation_rank = ref - (si[i].disposed_generation_count + si[i].no_writers_generation_count); @@ -2014,418 +2013,329 @@ static bool take_sample_update_conditions (struct dds_rhc_default *rhc, struct t return false; } -static int dds_rhc_read_w_qminv (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, unsigned qminv, dds_instance_handle_t handle, dds_readcond *cond) -{ - uint32_t n = 0; +typedef bool (*read_take_to_sample_t) (const struct ddsi_serdata * __restrict d, void *__restrict *__restrict sample, void * __restrict * __restrict bufptr, void * __restrict buflim); +typedef bool (*read_take_to_invsample_t) (const struct ddsi_sertopic * __restrict topic, const struct ddsi_serdata * __restrict d, void *__restrict * __restrict sample, void * __restrict * __restrict bufptr, void * __restrict buflim); +static bool read_take_to_sample (const struct ddsi_serdata * __restrict d, void * __restrict * __restrict sample, void * __restrict * __restrict bufptr, void * __restrict buflim) +{ + return ddsi_serdata_to_sample (d, *sample, (void **) bufptr, buflim); +} + +static bool read_take_to_invsample (const struct ddsi_sertopic * __restrict topic, const struct ddsi_serdata * __restrict d, void * __restrict * __restrict sample, void * __restrict * __restrict bufptr, void * __restrict buflim) +{ + return topicless_to_clean_invsample (topic, d, *sample, (void **) bufptr, buflim); +} + +static bool read_take_to_sample_ref (const struct ddsi_serdata * __restrict d, void * __restrict * __restrict sample, void * __restrict * __restrict bufptr, void * __restrict buflim) +{ + (void) bufptr; (void) buflim; + *sample = ddsi_serdata_ref (d); + return true; +} + +static bool read_take_to_invsample_ref (const struct ddsi_sertopic * __restrict topic, const struct ddsi_serdata * __restrict d, void * __restrict * __restrict sample, void * __restrict * __restrict bufptr, void * __restrict buflim) +{ + (void) topic; (void) bufptr; (void) buflim; + *sample = ddsi_serdata_ref (d); + return true; +} + +static int32_t read_w_qminv_inst (struct dds_rhc_default * const __restrict rhc, struct rhc_instance * const __restrict inst, void * __restrict * __restrict values, dds_sample_info_t * __restrict info_seq, const int32_t max_samples, const uint32_t qminv, const dds_querycond_mask_t qcmask, read_take_to_sample_t to_sample, read_take_to_invsample_t to_invsample) +{ + assert (max_samples > 0); + if (inst_is_empty (inst) || (qmask_of_inst (inst) & qminv) != 0) + { + /* no samples present, or the instance/view state doesn't match */ + return 0; + } + + struct trigger_info_pre pre; + struct trigger_info_post post; + struct trigger_info_qcond trig_qc; + const uint32_t nread = inst_nread (inst); + int32_t n = 0; + get_trigger_info_pre (&pre, inst); + init_trigger_info_qcond (&trig_qc); + + /* any valid samples precede a possible invalid sample */ + if (inst->latest) + { + struct rhc_sample *sample = inst->latest->next, * const end1 = sample; + do { + if ((qmask_of_sample (sample) & qminv) == 0 && (qcmask == 0 || (sample->conds & qcmask))) + { + /* sample state matches too */ + set_sample_info (info_seq + n, inst, sample); + to_sample (sample->sample, values + n, 0, 0); + if (!sample->isread) + { + TRACE ("s"); + read_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, sample->conds, false); + sample->isread = true; + inst->nvread++; + rhc->n_vread++; + } + ++n; + } + sample = sample->next; + } while (n < max_samples && sample != end1); + } + + /* add an invalid sample if it exists, matches and there is room in the result */ + if (inst->inv_exists && n < max_samples && (qmask_of_invsample (inst) & qminv) == 0 && (qcmask == 0 || (inst->conds & qcmask))) + { + set_sample_info_invsample (info_seq + n, inst); + to_invsample (rhc->topic, inst->tk->m_sample, values + n, 0, 0); + if (!inst->inv_isread) + { + TRACE ("i"); + read_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, inst->conds, false); + inst->inv_isread = 1; + rhc->n_invread++; + } + ++n; + } + + /* set generation counts in sample info now that we can compute them; update instance state */ + bool inst_became_old = false; + if (n > 0) + { + patch_generations (info_seq, (uint32_t) n - 1); + if (inst->isnew) + { + inst_became_old = true; + inst->isnew = 0; + rhc->n_new--; + } + } + if (nread != inst_nread (inst) || inst_became_old) + { + size_t ntriggers = SIZE_MAX; + get_trigger_info_cmn (&post.c, inst); + assert (trig_qc.dec_conds_invsample == 0); + assert (trig_qc.dec_conds_sample == 0); + assert (trig_qc.inc_conds_invsample == 0); + assert (trig_qc.inc_conds_sample == 0); + update_conditions_locked (rhc, false, &pre, &post, &trig_qc, inst, NULL, &ntriggers); + } + return n; +} + +static int32_t take_w_qminv_inst (struct dds_rhc_default * const __restrict rhc, struct rhc_instance * const __restrict inst, void * __restrict * __restrict values, dds_sample_info_t * __restrict info_seq, const int32_t max_samples, const uint32_t qminv, const dds_querycond_mask_t qcmask, size_t * __restrict ntriggers, read_take_to_sample_t to_sample, read_take_to_invsample_t to_invsample) +{ + assert (max_samples > 0); + if (inst_is_empty (inst) || (qmask_of_inst (inst) & qminv) != 0) + { + /* no samples present, or the instance/view state doesn't match */ + return 0; + } + + struct trigger_info_pre pre; + struct trigger_info_post post; + struct trigger_info_qcond trig_qc; + int32_t n = 0; + get_trigger_info_pre (&pre, inst); + init_trigger_info_qcond (&trig_qc); + + if (inst->latest) + { + struct rhc_sample *psample = inst->latest; + struct rhc_sample *sample = psample->next; + uint32_t nvsamples = inst->nvsamples; + while (nvsamples--) + { + struct rhc_sample * const sample1 = sample->next; + if ((qmask_of_sample (sample) & qminv) != 0 || (qcmask != 0 && !(sample->conds & qcmask))) + { + /* sample mask doesn't match, or content predicate doesn't match */ + psample = sample; + } + else + { + take_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, sample->conds, sample->isread); + set_sample_info (info_seq + n, inst, sample); + to_sample (sample->sample, values + n, 0, 0); + rhc->n_vsamples--; + if (sample->isread) + { + inst->nvread--; + rhc->n_vread--; + } + if (--inst->nvsamples == 0) + inst->latest = NULL; + else + { + if (inst->latest == sample) + inst->latest = psample; + psample->next = sample1; + } + free_sample (rhc, inst, sample); + if (++n == max_samples) + break; + } + sample = sample1; + } + } + + if (inst->inv_exists && n < max_samples && (qmask_of_invsample (inst) & qminv) == 0 && (qcmask == 0 || (inst->conds & qcmask) != 0)) + { + struct trigger_info_qcond dummy_trig_qc; +#ifndef NDEBUG + init_trigger_info_qcond (&dummy_trig_qc); +#endif + take_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, inst->conds, inst->inv_isread); + set_sample_info_invsample (info_seq + n, inst); + to_invsample (rhc->topic, inst->tk->m_sample, values + n, 0, 0); + inst_clear_invsample (rhc, inst, &dummy_trig_qc); + ++n; + } + + if (n > 0) + { + patch_generations (info_seq, (uint32_t) n - 1); + if (inst->isnew) + { + inst->isnew = 0; + rhc->n_new--; + } + /* if nsamples = 0, it won't match anything, so no need to do anything here for drop_instance_noupdate_no_writers */ + get_trigger_info_cmn (&post.c, inst); + assert (trig_qc.dec_conds_invsample == 0); + assert (trig_qc.dec_conds_sample == 0); + assert (trig_qc.inc_conds_invsample == 0); + assert (trig_qc.inc_conds_sample == 0); + update_conditions_locked (rhc, false, &pre, &post, &trig_qc, inst, NULL, ntriggers); + } + + if (inst_is_empty (inst)) + { + remove_inst_from_nonempty_list (rhc, inst); + if (inst->isdisposed) + rhc->n_not_alive_disposed--; + if (inst->wrcount == 0) + { + TRACE ("take: iid %"PRIx64" #0,empty,drop\n", inst->iid); + if (!inst->isdisposed) + { + /* disposed has priority over no writers (why not just 2 bits?) */ + rhc->n_not_alive_no_writers--; + } + drop_instance_noupdate_no_writers (rhc, inst); + } + } + return n; +} + +static int32_t read_w_qminv (struct dds_rhc_default * __restrict rhc, bool lock, void * __restrict * __restrict values, dds_sample_info_t * __restrict info_seq, int32_t max_samples, uint32_t qminv, dds_instance_handle_t handle, dds_readcond * __restrict cond, read_take_to_sample_t to_sample, read_take_to_invsample_t to_invsample) +{ + int32_t n = 0; + assert (max_samples > 0); if (lock) { ddsrt_mutex_lock (&rhc->lock); } - TRACE ("read_w_qminv(%p,%p,%p,%"PRIu32",%x,%p) - inst %"PRIu32" nonempty %"PRIu32" disp %"PRIu32" nowr %"PRIu32" new %"PRIu32" samples %"PRIu32"+%"PRIu32" read %"PRIu32"+%"PRIu32"\n", - (void *) rhc, (void *) values, (void *) info_seq, max_samples, qminv, (void *) cond, + TRACE ("read_w_qminv(%p,%p,%p,%"PRId32",%x,%"PRIx64",%p) - inst %"PRIu32" nonempty %"PRIu32" disp %"PRIu32" nowr %"PRIu32" new %"PRIu32" samples %"PRIu32"+%"PRIu32" read %"PRIu32"+%"PRIu32"\n", + (void *) rhc, (void *) values, (void *) info_seq, max_samples, qminv, handle, (void *) cond, rhc->n_instances, rhc->n_nonempty_instances, rhc->n_not_alive_disposed, rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, rhc->n_invsamples, rhc->n_vread, rhc->n_invread); - if (!ddsrt_circlist_isempty (&rhc->nonempty_instances)) + const dds_querycond_mask_t qcmask = (cond && cond->m_query.m_filter) ? cond->m_query.m_qcmask : 0; + if (handle) + { + struct rhc_instance template, *inst; + template.iid = handle; + if ((inst = ddsrt_hh_lookup (rhc->instances, &template)) != NULL) + n = read_w_qminv_inst (rhc, inst, values, info_seq, max_samples, qminv, qcmask, to_sample, to_invsample); + else + n = DDS_RETCODE_PRECONDITION_NOT_MET; + } + else if (!ddsrt_circlist_isempty (&rhc->nonempty_instances)) { - const dds_querycond_mask_t qcmask = (cond && cond->m_query.m_filter) ? cond->m_query.m_qcmask : 0; struct rhc_instance * inst = oldest_nonempty_instance (rhc); struct rhc_instance * const end = inst; - do - { - if (handle == DDS_HANDLE_NIL || inst->iid == handle) - { - if (!inst_is_empty (inst) && (qmask_of_inst (inst) & qminv) == 0) - { - /* samples present & instance, view state matches */ - struct trigger_info_pre pre; - struct trigger_info_post post; - struct trigger_info_qcond trig_qc; - const unsigned nread = inst_nread (inst); - const uint32_t n_first = n; - get_trigger_info_pre (&pre, inst); - init_trigger_info_qcond (&trig_qc); - - if (inst->latest) - { - struct rhc_sample *sample = inst->latest->next, * const end1 = sample; - do - { - if ((qmask_of_sample (sample) & qminv) == 0 && (qcmask == 0 || (sample->conds & qcmask))) - { - /* sample state matches too */ - set_sample_info (info_seq + n, inst, sample); - ddsi_serdata_to_sample (sample->sample, values[n], 0, 0); - if (!sample->isread) - { - TRACE ("s"); - read_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, sample->conds, false); - sample->isread = true; - inst->nvread++; - rhc->n_vread++; - } - if (++n == max_samples) - { - break; - } - } - sample = sample->next; - } - while (sample != end1); - } - - if (inst->inv_exists && n < max_samples && (qmask_of_invsample (inst) & qminv) == 0 && (qcmask == 0 || (inst->conds & qcmask))) - { - set_sample_info_invsample (info_seq + n, inst); - topicless_to_clean_invsample (rhc->topic, inst->tk->m_sample, values[n], 0, 0); - if (!inst->inv_isread) - { - TRACE ("i"); - read_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, inst->conds, false); - inst->inv_isread = 1; - rhc->n_invread++; - } - ++n; - } - - bool inst_became_old = false; - if (n > n_first && inst->isnew) - { - inst_became_old = true; - inst->isnew = 0; - rhc->n_new--; - } - if (nread != inst_nread (inst) || inst_became_old) - { - size_t ntriggers = SIZE_MAX; - get_trigger_info_cmn (&post.c, inst); - assert (trig_qc.dec_conds_invsample == 0); - assert (trig_qc.dec_conds_sample == 0); - assert (trig_qc.inc_conds_invsample == 0); - assert (trig_qc.inc_conds_sample == 0); - update_conditions_locked (rhc, false, &pre, &post, &trig_qc, inst, NULL, &ntriggers); - } - - if (n > n_first) { - patch_generations (info_seq + n_first, n - n_first - 1); - } - } - if (inst->iid == handle) - { - break; - } - } + do { + n += read_w_qminv_inst(rhc, inst, values + n, info_seq + n, max_samples - n, qminv, qcmask, to_sample, to_invsample); inst = next_nonempty_instance (inst); - } - while (inst != end && n < max_samples); + } while (inst != end && n < max_samples); } TRACE ("read: returning %"PRIu32"\n", n); assert (rhc_check_counts_locked (rhc, true, false)); + + // FIXME: conditional "lock" plus unconditional "unlock" is inexcusably bad design + // It appears to have been introduced at some point so another language binding could lock + // the RHC using dds_rhc_default_lock_samples to find out the number of samples present, + // then allocate stuff and call read/take with lock=true. All that needs fixing. ddsrt_mutex_unlock (&rhc->lock); - assert (n <= INT_MAX); - return (int)n; + return n; } -static int dds_rhc_take_w_qminv (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, unsigned qminv, dds_instance_handle_t handle, dds_readcond *cond) +static int32_t take_w_qminv (struct dds_rhc_default * __restrict rhc, bool lock, void * __restrict * __restrict values, dds_sample_info_t * __restrict info_seq, int32_t max_samples, uint32_t qminv, dds_instance_handle_t handle, dds_readcond * __restrict cond, read_take_to_sample_t to_sample, read_take_to_invsample_t to_invsample) { - uint64_t iid; - uint32_t n = 0; + int32_t n = 0; size_t ntriggers = SIZE_MAX; - + assert (max_samples > 0); if (lock) { ddsrt_mutex_lock (&rhc->lock); } - TRACE ("take_w_qminv(%p,%p,%p,%"PRIu32",%x) - inst %"PRIu32" nonempty %"PRIu32" disp %"PRIu32" nowr %"PRIu32" new %"PRIu32" samples %"PRIu32"+%"PRIu32" read %"PRIu32"+%"PRIu32"\n", - (void*) rhc, (void*) values, (void*) info_seq, max_samples, qminv, + TRACE ("take_w_qminv(%p,%p,%p,%"PRId32",%x,%"PRIx64",%p) - inst %"PRIu32" nonempty %"PRIu32" disp %"PRIu32" nowr %"PRIu32" new %"PRIu32" samples %"PRIu32"+%"PRIu32" read %"PRIu32"+%"PRIu32"\n", + (void*) rhc, (void*) values, (void*) info_seq, max_samples, qminv, handle, (void *) cond, rhc->n_instances, rhc->n_nonempty_instances, rhc->n_not_alive_disposed, rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, rhc->n_invsamples, rhc->n_vread, rhc->n_invread); - if (!ddsrt_circlist_isempty (&rhc->nonempty_instances)) + const dds_querycond_mask_t qcmask = (cond && cond->m_query.m_filter) ? cond->m_query.m_qcmask : 0; + if (handle) + { + struct rhc_instance template, *inst; + template.iid = handle; + if ((inst = ddsrt_hh_lookup (rhc->instances, &template)) != NULL) + n = take_w_qminv_inst (rhc, inst, values, info_seq, max_samples, qminv, qcmask, &ntriggers, to_sample, to_invsample); + else + n = DDS_RETCODE_PRECONDITION_NOT_MET; + } + else if (!ddsrt_circlist_isempty (&rhc->nonempty_instances)) { - const dds_querycond_mask_t qcmask = (cond && cond->m_query.m_filter) ? cond->m_query.m_qcmask : 0; struct rhc_instance *inst = oldest_nonempty_instance (rhc); - unsigned n_insts = rhc->n_nonempty_instances; + uint32_t n_insts = rhc->n_nonempty_instances; while (n_insts-- > 0 && n < max_samples) { struct rhc_instance * const inst1 = next_nonempty_instance (inst); - iid = inst->iid; - if (handle == DDS_HANDLE_NIL || iid == handle) - { - if (!inst_is_empty (inst) && (qmask_of_inst (inst) & qminv) == 0) - { - struct trigger_info_pre pre; - struct trigger_info_post post; - struct trigger_info_qcond trig_qc; - unsigned nvsamples = inst->nvsamples; - const uint32_t n_first = n; - get_trigger_info_pre (&pre, inst); - init_trigger_info_qcond (&trig_qc); - - if (inst->latest) - { - struct rhc_sample *psample = inst->latest; - struct rhc_sample *sample = psample->next; - while (nvsamples--) - { - struct rhc_sample * const sample1 = sample->next; - - if ((qmask_of_sample (sample) & qminv) != 0 || (qcmask != 0 && !(sample->conds & qcmask))) - { - /* sample mask doesn't match, or content predicate doesn't match */ - psample = sample; - } - else - { - take_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, sample->conds, sample->isread); - - set_sample_info (info_seq + n, inst, sample); - ddsi_serdata_to_sample (sample->sample, values[n], 0, 0); - rhc->n_vsamples--; - if (sample->isread) - { - inst->nvread--; - rhc->n_vread--; - } - - if (--inst->nvsamples > 0) - { - if (inst->latest == sample) - inst->latest = psample; - psample->next = sample1; - } - else - { - inst->latest = NULL; - } - - free_sample (rhc, inst, sample); - - if (++n == max_samples) - { - break; - } - } - sample = sample1; - } - } - - if (inst->inv_exists && n < max_samples && (qmask_of_invsample (inst) & qminv) == 0 && (qcmask == 0 || (inst->conds & qcmask) != 0)) - { - struct trigger_info_qcond dummy_trig_qc; -#ifndef NDEBUG - init_trigger_info_qcond (&dummy_trig_qc); -#endif - take_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, inst->conds, inst->inv_isread); - set_sample_info_invsample (info_seq + n, inst); - topicless_to_clean_invsample (rhc->topic, inst->tk->m_sample, values[n], 0, 0); - inst_clear_invsample (rhc, inst, &dummy_trig_qc); - ++n; - } - - if (n > n_first && inst->isnew) - { - inst->isnew = 0; - rhc->n_new--; - } - - if (n > n_first) - { - /* if nsamples = 0, it won't match anything, so no need to do - anything here for drop_instance_noupdate_no_writers */ - get_trigger_info_cmn (&post.c, inst); - assert (trig_qc.dec_conds_invsample == 0); - assert (trig_qc.dec_conds_sample == 0); - assert (trig_qc.inc_conds_invsample == 0); - assert (trig_qc.inc_conds_sample == 0); - update_conditions_locked (rhc, false, &pre, &post, &trig_qc, inst, NULL, &ntriggers); - } - - if (inst_is_empty (inst)) - { - remove_inst_from_nonempty_list (rhc, inst); - - if (inst->isdisposed) - { - rhc->n_not_alive_disposed--; - } - if (inst->wrcount == 0) - { - TRACE ("take: iid %"PRIx64" #0,empty,drop\n", iid); - if (!inst->isdisposed) - { - /* disposed has priority over no writers (why not just 2 bits?) */ - rhc->n_not_alive_no_writers--; - } - drop_instance_noupdate_no_writers (rhc, inst); - } - } - - if (n > n_first) - patch_generations (info_seq + n_first, n - n_first - 1); - } - if (iid == handle) - { - break; - } - } + n += take_w_qminv_inst (rhc, inst, values + n, info_seq + n, max_samples - n, qminv, qcmask, &ntriggers, to_sample, to_invsample); inst = inst1; } } TRACE ("take: returning %"PRIu32"\n", n); assert (rhc_check_counts_locked (rhc, true, false)); + + // FIXME: conditional "lock" plus unconditional "unlock" is inexcusably bad design + // It appears to have been introduced at some point so another language binding could lock + // the RHC using dds_rhc_default_lock_samples to find out the number of samples present, + // then allocate stuff and call read/take with lock=true. All that needs fixing. ddsrt_mutex_unlock (&rhc->lock); - assert (n <= INT_MAX); - return (int)n; + return n; } -static int dds_rhc_takecdr_w_qminv (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, unsigned qminv, dds_instance_handle_t handle, dds_readcond *cond) +static int32_t dds_rhc_read_w_qminv (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t qminv, dds_instance_handle_t handle, dds_readcond *cond) { - uint64_t iid; - uint32_t n = 0; - (void)cond; + assert (max_samples <= INT32_MAX); + return read_w_qminv (rhc, lock, values, info_seq, (int32_t) max_samples, qminv, handle, cond, read_take_to_sample, read_take_to_invsample); +} - if (lock) - { - ddsrt_mutex_lock (&rhc->lock); - } +static int32_t dds_rhc_take_w_qminv (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t qminv, dds_instance_handle_t handle, dds_readcond *cond) +{ + assert (max_samples <= INT32_MAX); + return take_w_qminv (rhc, lock, values, info_seq, (int32_t) max_samples, qminv, handle, cond, read_take_to_sample, read_take_to_invsample); +} - TRACE ("take_w_qminv(%p,%p,%p,%"PRIu32",%x) - inst %"PRIu32" nonempty %"PRIu32" disp %"PRIu32" nowr %"PRIu32" new %"PRIu32" samples %"PRIu32"+%"PRIu32" read %"PRIu32"+%"PRIu32"\n", - (void*) rhc, (void*) values, (void*) info_seq, max_samples, qminv, - rhc->n_instances, rhc->n_nonempty_instances, rhc->n_not_alive_disposed, - rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, - rhc->n_invsamples, rhc->n_vread, rhc->n_invread); - - if (!ddsrt_circlist_isempty (&rhc->nonempty_instances)) - { - const dds_querycond_mask_t qcmask = (cond && cond->m_query.m_filter) ? cond->m_query.m_qcmask : 0; - struct rhc_instance *inst = oldest_nonempty_instance (rhc); - unsigned n_insts = rhc->n_nonempty_instances; - while (n_insts-- > 0 && n < max_samples) - { - struct rhc_instance * const inst1 = next_nonempty_instance (inst); - iid = inst->iid; - if (handle == DDS_HANDLE_NIL || iid == handle) - { - if (!inst_is_empty (inst) && (qmask_of_inst (inst) & qminv) == 0) - { - struct trigger_info_pre pre; - struct trigger_info_post post; - struct trigger_info_qcond trig_qc; - unsigned nvsamples = inst->nvsamples; - const uint32_t n_first = n; - get_trigger_info_pre (&pre, inst); - init_trigger_info_qcond (&trig_qc); - - if (inst->latest) - { - struct rhc_sample *psample = inst->latest; - struct rhc_sample *sample = psample->next; - while (nvsamples--) - { - struct rhc_sample * const sample1 = sample->next; - - if ((qmask_of_sample (sample) & qminv) != 0 || (qcmask && !(sample->conds & qcmask))) - { - psample = sample; - } - else - { - take_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, sample->conds, sample->isread); - set_sample_info (info_seq + n, inst, sample); - values[n] = ddsi_serdata_ref(sample->sample); - rhc->n_vsamples--; - if (sample->isread) - { - inst->nvread--; - rhc->n_vread--; - } - - if (--inst->nvsamples > 0) - psample->next = sample1; - else - inst->latest = NULL; - - free_sample (rhc, inst, sample); - - if (++n == max_samples) - { - break; - } - } - sample = sample1; - } - } - - if (inst->inv_exists && n < max_samples && (qmask_of_invsample (inst) & qminv) == 0 && (qcmask == 0 || (inst->conds & qcmask) != 0)) - { - struct trigger_info_qcond dummy_trig_qc; -#ifndef NDEBUG - init_trigger_info_qcond (&dummy_trig_qc); -#endif - take_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, inst->conds, inst->inv_isread); - set_sample_info_invsample (info_seq + n, inst); - values[n] = ddsi_serdata_ref(inst->tk->m_sample); - inst_clear_invsample (rhc, inst, &dummy_trig_qc); - ++n; - } - - if (n > n_first && inst->isnew) - { - inst->isnew = 0; - rhc->n_new--; - } - - if (n > n_first) - { - /* if nsamples = 0, it won't match anything, so no need to do - anything here for drop_instance_noupdate_no_writers */ - size_t ntriggers = SIZE_MAX; - get_trigger_info_cmn (&post.c, inst); - update_conditions_locked (rhc, false, &pre, &post, &trig_qc, inst, NULL, &ntriggers); - } - - if (inst_is_empty (inst)) - { - remove_inst_from_nonempty_list (rhc, inst); - - if (inst->isdisposed) - { - rhc->n_not_alive_disposed--; - } - if (inst->wrcount == 0) - { - TRACE ("take: iid %"PRIx64" #0,empty,drop\n", iid); - if (!inst->isdisposed) - { - /* disposed has priority over no writers (why not just 2 bits?) */ - rhc->n_not_alive_no_writers--; - } - drop_instance_noupdate_no_writers (rhc, inst); - } - } - - if (n > n_first) - patch_generations (info_seq + n_first, n - n_first - 1); - } - if (iid == handle) - { - break; - } - } - inst = inst1; - } - } - TRACE ("take: returning %"PRIu32"\n", n); - assert (rhc_check_counts_locked (rhc, true, false)); - ddsrt_mutex_unlock (&rhc->lock); - assert (n <= INT_MAX); - return (int)n; +static int32_t dds_rhc_takecdr_w_qminv (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t qminv, dds_instance_handle_t handle, dds_readcond *cond) +{ + DDSRT_STATIC_ASSERT (sizeof (void *) == sizeof (struct ddsi_serdata *)); + assert (max_samples <= INT32_MAX); + return take_w_qminv (rhc, lock, (void **) values, info_seq, (int32_t) max_samples, qminv, handle, cond, read_take_to_sample_ref, read_take_to_invsample_ref); } /************************* @@ -2805,21 +2715,21 @@ static bool update_conditions_locked (struct dds_rhc_default *rhc, bool called_f ****** READ/TAKE ****** *************************/ -static int dds_rhc_default_read (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) +static int32_t dds_rhc_default_read (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) { - unsigned qminv = qmask_from_mask_n_cond (mask, cond); - return dds_rhc_read_w_qminv (rhc, lock, values, info_seq, max_samples, qminv, handle, cond); + uint32_t qminv = qmask_from_mask_n_cond (mask, cond); + return dds_rhc_read_w_qminv (rhc, lock, values, info_seq, max_samples, qminv, handle, cond); } -static int dds_rhc_default_take (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) +static int32_t dds_rhc_default_take (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) { - unsigned qminv = qmask_from_mask_n_cond(mask, cond); - return dds_rhc_take_w_qminv (rhc, lock, values, info_seq, max_samples, qminv, handle, cond); + uint32_t qminv = qmask_from_mask_n_cond(mask, cond); + return dds_rhc_take_w_qminv (rhc, lock, values, info_seq, max_samples, qminv, handle, cond); } -static int dds_rhc_default_takecdr (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) +static int32_t dds_rhc_default_takecdr (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) { - unsigned qminv = qmask_from_dcpsquery (sample_states, view_states, instance_states); + uint32_t qminv = qmask_from_dcpsquery (sample_states, view_states, instance_states); return dds_rhc_takecdr_w_qminv (rhc, lock, values, info_seq, max_samples, qminv, handle, NULL); } @@ -2835,11 +2745,11 @@ static int rhc_check_counts_locked (struct dds_rhc_default *rhc, bool check_cond return 1; const uint32_t ncheck = rhc->nconds < CHECK_MAX_CONDS ? rhc->nconds : CHECK_MAX_CONDS; - unsigned n_instances = 0, n_nonempty_instances = 0; - unsigned n_not_alive_disposed = 0, n_not_alive_no_writers = 0, n_new = 0; - unsigned n_vsamples = 0, n_vread = 0; - unsigned n_invsamples = 0, n_invread = 0; - unsigned cond_match_count[CHECK_MAX_CONDS]; + uint32_t n_instances = 0, n_nonempty_instances = 0; + uint32_t n_not_alive_disposed = 0, n_not_alive_no_writers = 0, n_new = 0; + uint32_t n_vsamples = 0, n_vread = 0; + uint32_t n_invsamples = 0, n_invread = 0; + uint32_t cond_match_count[CHECK_MAX_CONDS]; dds_querycond_mask_t enabled_qcmask = 0; struct rhc_instance *inst; struct ddsrt_hh_iter iter; @@ -2860,7 +2770,7 @@ static int rhc_check_counts_locked (struct dds_rhc_default *rhc, bool check_cond for (inst = ddsrt_hh_iter_first (rhc->instances, &iter); inst; inst = ddsrt_hh_iter_next (&iter)) { - unsigned n_vsamples_in_instance = 0, n_read_vsamples_in_instance = 0; + uint32_t n_vsamples_in_instance = 0, n_read_vsamples_in_instance = 0; bool a_sample_free = true; n_instances++; From 0006e09566c8050be22b258335d48c4cc4e59b7c Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sun, 19 Apr 2020 17:38:25 +0200 Subject: [PATCH 199/238] Add a dds_readcdr analogous to dds_takecdr Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/dds.h | 47 ++++++++++++++++++++++++ src/core/ddsc/include/dds/ddsc/dds_rhc.h | 4 ++ src/core/ddsc/src/dds_read.c | 18 ++++++++- src/core/ddsc/src/dds_rhc.c | 1 + src/core/ddsc/src/dds_rhc_default.c | 18 +++++++++ 5 files changed, 87 insertions(+), 1 deletion(-) diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index e62be5e..8383b06 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -2756,6 +2756,53 @@ dds_take_mask_wl( uint32_t maxs, uint32_t mask); +#define DDS_HAS_READCDR 1 +/** + * @brief Access the collection of serialized data values (of same type) and + * sample info from the data reader, readcondition or querycondition. + * + * This call accesses the serialized data from the data reader, readcondition or + * querycondition and makes it available to the application. The serialized data + * is made available through \ref ddsi_serdata structures. Returned samples are + * marked as READ. + * + * Return value provides information about the number of samples read, which will + * be <= maxs. Based on the count, the buffer will contain serialized data to be + * read only when valid_data bit in sample info structure is set. + * The buffer required for data values, could be allocated explicitly or can + * use the memory from data reader to prevent copy. In the latter case, buffer and + * sample_info should be returned back, once it is no longer using the data. + * + * @param[in] reader_or_condition Reader, readcondition or querycondition entity. + * @param[out] buf An array of pointers to \ref ddsi_serdata structures that contain + * the serialized data. The pointers can be NULL. + * @param[in] maxs Maximum number of samples to read. + * @param[out] si Pointer to an array of \ref dds_sample_info_t returned for each data value. + * @param[in] mask Filter the data based on dds_sample_state_t|dds_view_state_t|dds_instance_state_t. + * + * @returns A dds_return_t with the number of samples read or an error code. + * + * @retval >=0 + * Number of samples read. + * @retval DDS_RETCODE_ERROR + * An internal error has occurred. + * @retval DDS_RETCODE_BAD_PARAMETER + * One of the given arguments is not valid. + * @retval DDS_RETCODE_ILLEGAL_OPERATION + * The operation is invoked on an inappropriate object. + * @retval DDS_RETCODE_ALREADY_DELETED + * The entity has already been deleted. + * @retval DDS_RETCODE_PRECONDITION_NOT_MET + * The precondition for this operation is not met. + */ +DDS_EXPORT dds_return_t +dds_readcdr( + dds_entity_t reader_or_condition, + struct ddsi_serdata **buf, + uint32_t maxs, + dds_sample_info_t *si, + uint32_t mask); + /** * @brief Access the collection of serialized data values (of same type) and * sample info from the data reader, readcondition or querycondition. diff --git a/src/core/ddsc/include/dds/ddsc/dds_rhc.h b/src/core/ddsc/include/dds/ddsc/dds_rhc.h index b5cba34..e3bf4d6 100644 --- a/src/core/ddsc/include/dds/ddsc/dds_rhc.h +++ b/src/core/ddsc/include/dds/ddsc/dds_rhc.h @@ -41,6 +41,7 @@ struct dds_rhc_ops { struct ddsi_rhc_ops rhc_ops; dds_rhc_read_take_t read; dds_rhc_read_take_t take; + dds_rhc_read_take_cdr_t readcdr; dds_rhc_read_take_cdr_t takecdr; dds_rhc_add_readcondition_t add_readcondition; dds_rhc_remove_readcondition_t remove_readcondition; @@ -81,6 +82,9 @@ DDS_EXPORT inline int32_t dds_rhc_read (struct dds_rhc *rhc, bool lock, void **v DDS_EXPORT inline int32_t dds_rhc_take (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond) { return rhc->common.ops->take (rhc, lock, values, info_seq, max_samples, mask, handle, cond); } +DDS_EXPORT inline int32_t dds_rhc_readcdr (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) { + return rhc->common.ops->readcdr (rhc, lock, values, info_seq, max_samples, sample_states, view_states, instance_states, handle); +} DDS_EXPORT inline int32_t dds_rhc_takecdr (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) { return rhc->common.ops->takecdr (rhc, lock, values, info_seq, max_samples, sample_states, view_states, instance_states, handle); } diff --git a/src/core/ddsc/src/dds_read.c b/src/core/ddsc/src/dds_read.c index fd9ae5b..a5c932d 100644 --- a/src/core/ddsc/src/dds_read.c +++ b/src/core/ddsc/src/dds_read.c @@ -171,7 +171,11 @@ static dds_return_t dds_readcdr_impl (bool take, dds_entity_t reader_or_conditio assert (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER); dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS); - ret = dds_rhc_takecdr (rd->m_rhc, lock, buf, si, maxs, mask & DDS_ANY_SAMPLE_STATE, mask & DDS_ANY_VIEW_STATE, mask & DDS_ANY_INSTANCE_STATE, hand); + if (take) + ret = dds_rhc_takecdr (rd->m_rhc, lock, buf, si, maxs, mask & DDS_ANY_SAMPLE_STATE, mask & DDS_ANY_VIEW_STATE, mask & DDS_ANY_INSTANCE_STATE, hand); + else + ret = dds_rhc_readcdr (rd->m_rhc, lock, buf, si, maxs, mask & DDS_ANY_SAMPLE_STATE, mask & DDS_ANY_VIEW_STATE, mask & DDS_ANY_INSTANCE_STATE, hand); + dds_entity_unpin (entity); thread_state_asleep (ts1); return ret; @@ -225,6 +229,18 @@ dds_return_t dds_read_mask_wl (dds_entity_t rd_or_cnd, void **buf, dds_sample_in return dds_read_impl (false, rd_or_cnd, buf, maxs, maxs, si, mask, DDS_HANDLE_NIL, lock, false); } +dds_return_t dds_readcdr (dds_entity_t rd_or_cnd, struct ddsi_serdata **buf, uint32_t maxs, dds_sample_info_t *si, uint32_t mask) +{ + bool lock = true; + if (maxs == DDS_READ_WITHOUT_LOCK) + { + lock = false; + /* FIXME: Fix the interface. */ + maxs = 100; + } + return dds_readcdr_impl (false, rd_or_cnd, buf, maxs, si, mask, DDS_HANDLE_NIL, lock); +} + dds_return_t dds_read_instance (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs, dds_instance_handle_t handle) { bool lock = true; diff --git a/src/core/ddsc/src/dds_rhc.c b/src/core/ddsc/src/dds_rhc.c index f159422..7db2ff0 100644 --- a/src/core/ddsc/src/dds_rhc.c +++ b/src/core/ddsc/src/dds_rhc.c @@ -22,6 +22,7 @@ extern inline void dds_rhc_set_qos (struct dds_rhc *rhc, const struct dds_qos *q extern inline void dds_rhc_free (struct dds_rhc *rhc); extern inline int dds_rhc_read (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond); extern inline int dds_rhc_take (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond); +extern inline int dds_rhc_readcdr (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle); extern inline int dds_rhc_takecdr (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle); extern inline bool dds_rhc_add_readcondition (struct dds_rhc *rhc, struct dds_readcond *cond); extern inline void dds_rhc_remove_readcondition (struct dds_rhc *rhc, struct dds_readcond *cond); diff --git a/src/core/ddsc/src/dds_rhc_default.c b/src/core/ddsc/src/dds_rhc_default.c index 07692e7..d5754f3 100644 --- a/src/core/ddsc/src/dds_rhc_default.c +++ b/src/core/ddsc/src/dds_rhc_default.c @@ -370,6 +370,7 @@ static void dds_rhc_default_relinquish_ownership (struct dds_rhc_default * __res static void dds_rhc_default_set_qos (struct dds_rhc_default *rhc, const struct dds_qos *qos); static int32_t dds_rhc_default_read (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond); static int32_t dds_rhc_default_take (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond); +static int32_t dds_rhc_default_readcdr (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle); static int32_t dds_rhc_default_takecdr (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle); static bool dds_rhc_default_add_readcondition (struct dds_rhc_default *rhc, dds_readcond *cond); static void dds_rhc_default_remove_readcondition (struct dds_rhc_default *rhc, dds_readcond *cond); @@ -396,6 +397,9 @@ static int32_t dds_rhc_default_read_wrap (struct dds_rhc *rhc, bool lock, void * static int32_t dds_rhc_default_take_wrap (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) { return dds_rhc_default_take ((struct dds_rhc_default *) rhc, lock, values, info_seq, max_samples, mask, handle, cond); } +static int32_t dds_rhc_default_readcdr_wrap (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) { + return dds_rhc_default_readcdr ((struct dds_rhc_default *) rhc, lock, values, info_seq, max_samples, sample_states, view_states, instance_states, handle); +} static int32_t dds_rhc_default_takecdr_wrap (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) { return dds_rhc_default_takecdr ((struct dds_rhc_default *) rhc, lock, values, info_seq, max_samples, sample_states, view_states, instance_states, handle); } @@ -425,6 +429,7 @@ static const struct dds_rhc_ops dds_rhc_default_ops = { }, .read = dds_rhc_default_read_wrap, .take = dds_rhc_default_take_wrap, + .readcdr = dds_rhc_default_readcdr_wrap, .takecdr = dds_rhc_default_takecdr_wrap, .add_readcondition = dds_rhc_default_add_readcondition_wrap, .remove_readcondition = dds_rhc_default_remove_readcondition_wrap, @@ -2331,6 +2336,13 @@ static int32_t dds_rhc_take_w_qminv (struct dds_rhc_default *rhc, bool lock, voi return take_w_qminv (rhc, lock, values, info_seq, (int32_t) max_samples, qminv, handle, cond, read_take_to_sample, read_take_to_invsample); } +static int32_t dds_rhc_readcdr_w_qminv (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t qminv, dds_instance_handle_t handle, dds_readcond *cond) +{ + DDSRT_STATIC_ASSERT (sizeof (void *) == sizeof (struct ddsi_serdata *)); + assert (max_samples <= INT32_MAX); + return read_w_qminv (rhc, lock, (void **) values, info_seq, (int32_t) max_samples, qminv, handle, cond, read_take_to_sample_ref, read_take_to_invsample_ref); +} + static int32_t dds_rhc_takecdr_w_qminv (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t qminv, dds_instance_handle_t handle, dds_readcond *cond) { DDSRT_STATIC_ASSERT (sizeof (void *) == sizeof (struct ddsi_serdata *)); @@ -2727,6 +2739,12 @@ static int32_t dds_rhc_default_take (struct dds_rhc_default *rhc, bool lock, voi return dds_rhc_take_w_qminv (rhc, lock, values, info_seq, max_samples, qminv, handle, cond); } +static int32_t dds_rhc_default_readcdr (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) +{ + uint32_t qminv = qmask_from_dcpsquery (sample_states, view_states, instance_states); + return dds_rhc_readcdr_w_qminv (rhc, lock, values, info_seq, max_samples, qminv, handle, NULL); +} + static int32_t dds_rhc_default_takecdr (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) { uint32_t qminv = qmask_from_dcpsquery (sample_states, view_states, instance_states); From 8b934a7dddb9a10b2d95228286b366edab8357d7 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 20 Apr 2020 11:10:54 +0200 Subject: [PATCH 200/238] Remove a layer of wrapper functions in default RHC Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_rhc_default.c | 135 +++++++++++----------------- 1 file changed, 50 insertions(+), 85 deletions(-) diff --git a/src/core/ddsc/src/dds_rhc_default.c b/src/core/ddsc/src/dds_rhc_default.c index d5754f3..a4c774c 100644 --- a/src/core/ddsc/src/dds_rhc_default.c +++ b/src/core/ddsc/src/dds_rhc_default.c @@ -363,79 +363,7 @@ struct trigger_info_post { struct trigger_info_cmn c; }; -static void dds_rhc_default_free (struct dds_rhc_default *rhc); -static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk); -static void dds_rhc_default_unregister_wr (struct dds_rhc_default * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo); -static void dds_rhc_default_relinquish_ownership (struct dds_rhc_default * __restrict rhc, const uint64_t wr_iid); -static void dds_rhc_default_set_qos (struct dds_rhc_default *rhc, const struct dds_qos *qos); -static int32_t dds_rhc_default_read (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond); -static int32_t dds_rhc_default_take (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond); -static int32_t dds_rhc_default_readcdr (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle); -static int32_t dds_rhc_default_takecdr (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle); -static bool dds_rhc_default_add_readcondition (struct dds_rhc_default *rhc, dds_readcond *cond); -static void dds_rhc_default_remove_readcondition (struct dds_rhc_default *rhc, dds_readcond *cond); -static uint32_t dds_rhc_default_lock_samples (struct dds_rhc_default *rhc); - -static void dds_rhc_default_free_wrap (struct ddsi_rhc *rhc) { - dds_rhc_default_free ((struct dds_rhc_default *) rhc); -} -static bool dds_rhc_default_store_wrap (struct ddsi_rhc * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk) { - return dds_rhc_default_store ((struct dds_rhc_default *) rhc, wrinfo, sample, tk); -} -static void dds_rhc_default_unregister_wr_wrap (struct ddsi_rhc * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo) { - dds_rhc_default_unregister_wr ((struct dds_rhc_default *) rhc, wrinfo); -} -static void dds_rhc_default_relinquish_ownership_wrap (struct ddsi_rhc * __restrict rhc, const uint64_t wr_iid) { - dds_rhc_default_relinquish_ownership ((struct dds_rhc_default *) rhc, wr_iid); -} -static void dds_rhc_default_set_qos_wrap (struct ddsi_rhc *rhc, const struct dds_qos *qos) { - dds_rhc_default_set_qos ((struct dds_rhc_default *) rhc, qos); -} -static int32_t dds_rhc_default_read_wrap (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) { - return dds_rhc_default_read ((struct dds_rhc_default *) rhc, lock, values, info_seq, max_samples, mask, handle, cond); -} -static int32_t dds_rhc_default_take_wrap (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) { - return dds_rhc_default_take ((struct dds_rhc_default *) rhc, lock, values, info_seq, max_samples, mask, handle, cond); -} -static int32_t dds_rhc_default_readcdr_wrap (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) { - return dds_rhc_default_readcdr ((struct dds_rhc_default *) rhc, lock, values, info_seq, max_samples, sample_states, view_states, instance_states, handle); -} -static int32_t dds_rhc_default_takecdr_wrap (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) { - return dds_rhc_default_takecdr ((struct dds_rhc_default *) rhc, lock, values, info_seq, max_samples, sample_states, view_states, instance_states, handle); -} -static bool dds_rhc_default_add_readcondition_wrap (struct dds_rhc *rhc, dds_readcond *cond) { - return dds_rhc_default_add_readcondition ((struct dds_rhc_default *) rhc, cond); -} -static void dds_rhc_default_remove_readcondition_wrap (struct dds_rhc *rhc, dds_readcond *cond) { - dds_rhc_default_remove_readcondition ((struct dds_rhc_default *) rhc, cond); -} -static uint32_t dds_rhc_default_lock_samples_wrap (struct dds_rhc *rhc) { - return dds_rhc_default_lock_samples ((struct dds_rhc_default *) rhc); -} -static dds_return_t dds_rhc_default_associate (struct dds_rhc *rhc, dds_reader *reader, const struct ddsi_sertopic *topic, struct ddsi_tkmap *tkmap) -{ - /* ignored out of laziness */ - (void) rhc; (void) reader; (void) topic; (void) tkmap; - return DDS_RETCODE_OK; -} - -static const struct dds_rhc_ops dds_rhc_default_ops = { - .rhc_ops = { - .store = dds_rhc_default_store_wrap, - .unregister_wr = dds_rhc_default_unregister_wr_wrap, - .relinquish_ownership = dds_rhc_default_relinquish_ownership_wrap, - .set_qos = dds_rhc_default_set_qos_wrap, - .free = dds_rhc_default_free_wrap - }, - .read = dds_rhc_default_read_wrap, - .take = dds_rhc_default_take_wrap, - .readcdr = dds_rhc_default_readcdr_wrap, - .takecdr = dds_rhc_default_takecdr_wrap, - .add_readcondition = dds_rhc_default_add_readcondition_wrap, - .remove_readcondition = dds_rhc_default_remove_readcondition_wrap, - .lock_samples = dds_rhc_default_lock_samples_wrap, - .associate = dds_rhc_default_associate -}; +static const struct dds_rhc_ops dds_rhc_default_ops; static uint32_t qmask_of_sample (const struct rhc_sample *s) { @@ -675,8 +603,16 @@ struct dds_rhc *dds_rhc_default_new (dds_reader *reader, const struct ddsi_serto return dds_rhc_default_new_xchecks (reader, &reader->m_entity.m_domain->gv, topic, (reader->m_entity.m_domain->gv.config.enabled_xchecks & DDS_XCHECK_RHC) != 0); } -static void dds_rhc_default_set_qos (struct dds_rhc_default * rhc, const dds_qos_t * qos) +static dds_return_t dds_rhc_default_associate (struct dds_rhc *rhc, dds_reader *reader, const struct ddsi_sertopic *topic, struct ddsi_tkmap *tkmap) { + /* ignored out of laziness */ + (void) rhc; (void) reader; (void) topic; (void) tkmap; + return DDS_RETCODE_OK; +} + +static void dds_rhc_default_set_qos (struct ddsi_rhc *rhc_common, const dds_qos_t * qos) +{ + struct dds_rhc_default * const rhc = (struct dds_rhc_default *) rhc_common; /* Set read related QoS */ rhc->max_samples = qos->resource_limits.max_samples; @@ -822,8 +758,9 @@ static void free_instance_rhc_free (struct rhc_instance *inst, struct dds_rhc_de free_empty_instance(inst, rhc); } -static uint32_t dds_rhc_default_lock_samples (struct dds_rhc_default *rhc) +static uint32_t dds_rhc_default_lock_samples (struct dds_rhc *rhc_common) { + struct dds_rhc_default * const rhc = (struct dds_rhc_default *) rhc_common; uint32_t no; ddsrt_mutex_lock (&rhc->lock); no = rhc->n_vsamples + rhc->n_invsamples; @@ -839,8 +776,9 @@ static void free_instance_rhc_free_wrap (void *vnode, void *varg) free_instance_rhc_free (vnode, varg); } -static void dds_rhc_default_free (struct dds_rhc_default *rhc) +static void dds_rhc_default_free (struct ddsi_rhc *rhc_common) { + struct dds_rhc_default *rhc = (struct dds_rhc_default *) rhc_common; #ifdef DDSI_INCLUDE_LIFESPAN dds_rhc_default_sample_expired_cb (rhc, DDSRT_MTIME_NEVER); lifespan_fini (&rhc->lifespan); @@ -1464,8 +1402,9 @@ static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst delivered (true unless a reliable sample rejected). */ -static bool dds_rhc_default_store (struct dds_rhc_default * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk) +static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, const struct ddsi_writer_info * __restrict wrinfo, struct ddsi_serdata * __restrict sample, struct ddsi_tkmap_instance * __restrict tk) { + struct dds_rhc_default * const __restrict rhc = (struct dds_rhc_default * __restrict) rhc_common; const uint64_t wr_iid = wrinfo->iid; const uint32_t statusinfo = sample->statusinfo; const bool has_data = (sample->kind == SDK_DATA); @@ -1740,7 +1679,7 @@ error_or_nochange: return delivered; } -static void dds_rhc_default_unregister_wr (struct dds_rhc_default * __restrict rhc, const struct ddsi_writer_info * __restrict wrinfo) +static void dds_rhc_default_unregister_wr (struct ddsi_rhc * __restrict rhc_common, const struct ddsi_writer_info * __restrict wrinfo) { /* Only to be called when writer with ID WR_IID has died. @@ -1757,6 +1696,7 @@ static void dds_rhc_default_unregister_wr (struct dds_rhc_default * __restrict r need to get two IIDs: the one visible to the application in the built-in topics and in get_instance_handle, and one used internally for tracking registrations and unregistrations. */ + struct dds_rhc_default * __restrict const rhc = (struct dds_rhc_default * __restrict) rhc_common; bool notify_data_available = false; struct rhc_instance *inst; struct ddsrt_hh_iter iter; @@ -1825,8 +1765,9 @@ static void dds_rhc_default_unregister_wr (struct dds_rhc_default * __restrict r } } -static void dds_rhc_default_relinquish_ownership (struct dds_rhc_default * __restrict rhc, const uint64_t wr_iid) +static void dds_rhc_default_relinquish_ownership (struct ddsi_rhc * __restrict rhc_common, const uint64_t wr_iid) { + struct dds_rhc_default * __restrict const rhc = (struct dds_rhc_default * __restrict) rhc_common; struct rhc_instance *inst; struct ddsrt_hh_iter iter; ddsrt_mutex_lock (&rhc->lock); @@ -2393,12 +2334,13 @@ static bool cond_is_sample_state_dependent (const struct dds_readcond *cond) } } -static bool dds_rhc_default_add_readcondition (struct dds_rhc_default *rhc, dds_readcond *cond) +static bool dds_rhc_default_add_readcondition (struct dds_rhc *rhc_common, dds_readcond *cond) { /* On the assumption that a readcondition will be attached to a waitset for nearly all of its life, we keep track of all readconditions on a reader in one set, without distinguishing between those attached to a waitset or not. */ + struct dds_rhc_default * const rhc = (struct dds_rhc_default *) rhc_common; struct ddsrt_hh_iter it; assert ((dds_entity_kind (&cond->m_entity) == DDS_KIND_COND_READ && cond->m_query.m_filter == 0) || @@ -2498,8 +2440,9 @@ static bool dds_rhc_default_add_readcondition (struct dds_rhc_default *rhc, dds_ return true; } -static void dds_rhc_default_remove_readcondition (struct dds_rhc_default *rhc, dds_readcond *cond) +static void dds_rhc_default_remove_readcondition (struct dds_rhc *rhc_common, dds_readcond *cond) { + struct dds_rhc_default * const rhc = (struct dds_rhc_default *) rhc_common; dds_readcond **ptr; ddsrt_mutex_lock (&rhc->lock); ptr = &rhc->conds; @@ -2727,26 +2670,30 @@ static bool update_conditions_locked (struct dds_rhc_default *rhc, bool called_f ****** READ/TAKE ****** *************************/ -static int32_t dds_rhc_default_read (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) +static int32_t dds_rhc_default_read (struct dds_rhc *rhc_common, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) { + struct dds_rhc_default * const rhc = (struct dds_rhc_default *) rhc_common; uint32_t qminv = qmask_from_mask_n_cond (mask, cond); return dds_rhc_read_w_qminv (rhc, lock, values, info_seq, max_samples, qminv, handle, cond); } -static int32_t dds_rhc_default_take (struct dds_rhc_default *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) +static int32_t dds_rhc_default_take (struct dds_rhc *rhc_common, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, dds_readcond *cond) { + struct dds_rhc_default * const rhc = (struct dds_rhc_default *) rhc_common; uint32_t qminv = qmask_from_mask_n_cond(mask, cond); return dds_rhc_take_w_qminv (rhc, lock, values, info_seq, max_samples, qminv, handle, cond); } -static int32_t dds_rhc_default_readcdr (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) +static int32_t dds_rhc_default_readcdr (struct dds_rhc *rhc_common, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) { + struct dds_rhc_default * const rhc = (struct dds_rhc_default *) rhc_common; uint32_t qminv = qmask_from_dcpsquery (sample_states, view_states, instance_states); return dds_rhc_readcdr_w_qminv (rhc, lock, values, info_seq, max_samples, qminv, handle, NULL); } -static int32_t dds_rhc_default_takecdr (struct dds_rhc_default *rhc, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) +static int32_t dds_rhc_default_takecdr (struct dds_rhc *rhc_common, bool lock, struct ddsi_serdata ** values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) { + struct dds_rhc_default * const rhc = (struct dds_rhc_default *) rhc_common; uint32_t qminv = qmask_from_dcpsquery (sample_states, view_states, instance_states); return dds_rhc_takecdr_w_qminv (rhc, lock, values, info_seq, max_samples, qminv, handle, NULL); } @@ -2924,3 +2871,21 @@ static int rhc_check_counts_locked (struct dds_rhc_default *rhc, bool check_cond } #undef CHECK_MAX_CONDS #endif + +static const struct dds_rhc_ops dds_rhc_default_ops = { + .rhc_ops = { + .store = dds_rhc_default_store, + .unregister_wr = dds_rhc_default_unregister_wr, + .relinquish_ownership = dds_rhc_default_relinquish_ownership, + .set_qos = dds_rhc_default_set_qos, + .free = dds_rhc_default_free + }, + .read = dds_rhc_default_read, + .take = dds_rhc_default_take, + .readcdr = dds_rhc_default_readcdr, + .takecdr = dds_rhc_default_takecdr, + .add_readcondition = dds_rhc_default_add_readcondition, + .remove_readcondition = dds_rhc_default_remove_readcondition, + .lock_samples = dds_rhc_default_lock_samples, + .associate = dds_rhc_default_associate +}; From ff591ae68469e36031ed5d43c5491fc269e0ac3d Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sun, 26 Apr 2020 10:13:15 +0200 Subject: [PATCH 201/238] Null instance pointer after dropping instance Do not pass a dangling pointer to update_conditions_locked after dropping an instance. The dangling pointer did not actually get dereferenced because of the state changes caused by dropping the samples, but that is cutting a bit fine. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_rhc_default.c | 101 +++++++++++++++------------- 1 file changed, 53 insertions(+), 48 deletions(-) diff --git a/src/core/ddsc/src/dds_rhc_default.c b/src/core/ddsc/src/dds_rhc_default.c index a4c774c..e1a17b1 100644 --- a/src/core/ddsc/src/dds_rhc_default.c +++ b/src/core/ddsc/src/dds_rhc_default.c @@ -415,8 +415,9 @@ static void free_sample (struct dds_rhc_default *rhc, struct rhc_instance *inst, static void get_trigger_info_cmn (struct trigger_info_cmn *info, struct rhc_instance *inst); static void get_trigger_info_pre (struct trigger_info_pre *info, struct rhc_instance *inst); static void init_trigger_info_qcond (struct trigger_info_qcond *qc); -static void drop_instance_noupdate_no_writers (struct dds_rhc_default *rhc, struct rhc_instance *inst); +static void drop_instance_noupdate_no_writers (struct dds_rhc_default * __restrict rhc, struct rhc_instance * __restrict * __restrict instptr); static bool update_conditions_locked (struct dds_rhc_default *rhc, bool called_from_insert, const struct trigger_info_pre *pre, const struct trigger_info_post *post, const struct trigger_info_qcond *trig_qc, const struct rhc_instance *inst, struct dds_entity *triggers[], size_t *ntriggers); +static void account_for_nonempty_to_empty_transition (struct dds_rhc_default * __restrict rhc, struct rhc_instance * __restrict * __restrict instptr, const char *__restrict traceprefix); #ifndef NDEBUG static int rhc_check_counts_locked (struct dds_rhc_default *rhc, bool check_conds, bool check_qcmask); #endif @@ -512,18 +513,7 @@ static void drop_expired_samples (struct dds_rhc_default *rhc, struct rhc_sample get_trigger_info_cmn (&post.c, inst); update_conditions_locked (rhc, false, &pre, &post, &trig_qc, inst, NULL, &ntriggers); if (inst_is_empty (inst)) - { - remove_inst_from_nonempty_list (rhc, inst); - if (inst->isdisposed) - rhc->n_not_alive_disposed--; - if (inst->wrcount == 0) - { - TRACE ("; iid %"PRIx64" #0,empty,drop", inst->iid); - if (!inst->isdisposed) - rhc->n_not_alive_no_writers--; - drop_instance_noupdate_no_writers (rhc, inst); - } - } + account_for_nonempty_to_empty_transition(rhc, &inst, "; "); TRACE (")\n"); } @@ -1023,8 +1013,9 @@ static void update_inst (struct rhc_instance *inst, const struct ddsi_writer_inf inst->strength = wrinfo->ownership_strength; } -static void drop_instance_noupdate_no_writers (struct dds_rhc_default *rhc, struct rhc_instance *inst) +static void drop_instance_noupdate_no_writers (struct dds_rhc_default *__restrict rhc, struct rhc_instance * __restrict * __restrict instptr) { + struct rhc_instance *inst = *instptr; int ret; assert (inst_is_empty (inst)); @@ -1037,6 +1028,7 @@ static void drop_instance_noupdate_no_writers (struct dds_rhc_default *rhc, stru (void) ret; free_empty_instance (inst, rhc); + *instptr = NULL; } static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance *inst, uint64_t wr_iid, bool iid_update) @@ -1163,6 +1155,25 @@ static void account_for_empty_to_nonempty_transition (struct dds_rhc_default *rh rhc->n_not_alive_no_writers++; } +static void account_for_nonempty_to_empty_transition (struct dds_rhc_default *__restrict rhc, struct rhc_instance * __restrict * __restrict instptr, const char * __restrict traceprefix) +{ + struct rhc_instance *inst = *instptr; + assert (inst_is_empty (inst)); + remove_inst_from_nonempty_list (rhc, inst); + if (inst->isdisposed) + rhc->n_not_alive_disposed--; + if (inst->wrcount == 0) + { + TRACE ("%siid %"PRIx64" #0,empty,drop\n", traceprefix, inst->iid); + if (!inst->isdisposed) + { + /* disposed has priority over no writers (why not just 2 bits?) */ + rhc->n_not_alive_no_writers--; + } + drop_instance_noupdate_no_writers (rhc, instptr); + } +} + static int rhc_unregister_isreg_w_sideeffects (struct dds_rhc_default *rhc, const struct rhc_instance *inst, uint64_t wr_iid) { /* Returns 1 if last registration just disappeared */ @@ -1207,8 +1218,9 @@ static int rhc_unregister_isreg_w_sideeffects (struct dds_rhc_default *rhc, cons } } -static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_instance *inst, const struct ddsi_writer_info * __restrict wrinfo, ddsrt_wctime_t tstamp, struct trigger_info_qcond *trig_qc, bool *nda) +static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_instance **instptr, const struct ddsi_writer_info * __restrict wrinfo, ddsrt_wctime_t tstamp, struct trigger_info_qcond *trig_qc, bool *nda) { + struct rhc_instance * const inst = *instptr; assert (inst->wrcount > 0); if (--inst->wrcount > 0) @@ -1253,7 +1265,7 @@ static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_in { /* No content left, no registrations left, so drop */ TRACE (",#0,empty,disposed,drop"); - drop_instance_noupdate_no_writers (rhc, inst); + drop_instance_noupdate_no_writers (rhc, instptr); return 1; } else @@ -1270,8 +1282,9 @@ static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_in } } -static bool dds_rhc_unregister (struct dds_rhc_default *rhc, struct rhc_instance *inst, const struct ddsi_writer_info * __restrict wrinfo, ddsrt_wctime_t tstamp, struct trigger_info_post *post, struct trigger_info_qcond *trig_qc) +static bool dds_rhc_unregister (struct dds_rhc_default *rhc, struct rhc_instance **instptr, const struct ddsi_writer_info * __restrict wrinfo, ddsrt_wctime_t tstamp, struct trigger_info_post *post, struct trigger_info_qcond *trig_qc) { + struct rhc_instance * const inst = *instptr; bool notify_data_available = false; /* 'post' always gets set; instance may have been freed upon return. */ @@ -1281,7 +1294,7 @@ static bool dds_rhc_unregister (struct dds_rhc_default *rhc, struct rhc_instance /* other registrations remain */ get_trigger_info_cmn (&post->c, inst); } - else if (rhc_unregister_updateinst (rhc, inst, wrinfo, tstamp, trig_qc, ¬ify_data_available)) + else if (rhc_unregister_updateinst (rhc, instptr, wrinfo, tstamp, trig_qc, ¬ify_data_available)) { /* instance dropped */ init_trigger_info_cmn_nonmatch (&post->c); @@ -1477,7 +1490,7 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons } if (statusinfo & NN_STATUSINFO_UNREGISTER) { - if (dds_rhc_unregister (rhc, inst, wrinfo, sample->timestamp, &post, &trig_qc)) + if (dds_rhc_unregister (rhc, &inst, wrinfo, sample->timestamp, &post, &trig_qc)) notify_data_available = true; } else @@ -1633,7 +1646,7 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons mean an application reading "x" after the write and reading it again after the unregister will see a change in the no_writers_generation field? */ - dds_rhc_unregister (rhc, inst, wrinfo, sample->timestamp, &post, &trig_qc); + dds_rhc_unregister (rhc, &inst, wrinfo, sample->timestamp, &post, &trig_qc); } else { @@ -1744,7 +1757,7 @@ static void dds_rhc_default_unregister_wr (struct ddsi_rhc * __restrict rhc_comm } } - (void) dds_rhc_unregister (rhc, inst, wrinfo, inst->tstamp, &post, &trig_qc); + (void) dds_rhc_unregister (rhc, &inst, wrinfo, inst->tstamp, &post, &trig_qc); TRACE ("\n"); @@ -2067,8 +2080,9 @@ static int32_t read_w_qminv_inst (struct dds_rhc_default * const __restrict rhc, return n; } -static int32_t take_w_qminv_inst (struct dds_rhc_default * const __restrict rhc, struct rhc_instance * const __restrict inst, void * __restrict * __restrict values, dds_sample_info_t * __restrict info_seq, const int32_t max_samples, const uint32_t qminv, const dds_querycond_mask_t qcmask, size_t * __restrict ntriggers, read_take_to_sample_t to_sample, read_take_to_invsample_t to_invsample) +static int32_t take_w_qminv_inst (struct dds_rhc_default * const __restrict rhc, struct rhc_instance * __restrict * __restrict instptr, void * __restrict * __restrict values, dds_sample_info_t * __restrict info_seq, const int32_t max_samples, const uint32_t qminv, const dds_querycond_mask_t qcmask, size_t * __restrict ntriggers, read_take_to_sample_t to_sample, read_take_to_invsample_t to_invsample) { + struct rhc_instance *inst = *instptr; assert (max_samples > 0); if (inst_is_empty (inst) || (qmask_of_inst (inst) & qminv) != 0) { @@ -2154,21 +2168,7 @@ static int32_t take_w_qminv_inst (struct dds_rhc_default * const __restrict rhc, } if (inst_is_empty (inst)) - { - remove_inst_from_nonempty_list (rhc, inst); - if (inst->isdisposed) - rhc->n_not_alive_disposed--; - if (inst->wrcount == 0) - { - TRACE ("take: iid %"PRIx64" #0,empty,drop\n", inst->iid); - if (!inst->isdisposed) - { - /* disposed has priority over no writers (why not just 2 bits?) */ - rhc->n_not_alive_no_writers--; - } - drop_instance_noupdate_no_writers (rhc, inst); - } - } + account_for_nonempty_to_empty_transition (rhc, instptr, "take: "); return n; } @@ -2239,7 +2239,7 @@ static int32_t take_w_qminv (struct dds_rhc_default * __restrict rhc, bool lock, struct rhc_instance template, *inst; template.iid = handle; if ((inst = ddsrt_hh_lookup (rhc->instances, &template)) != NULL) - n = take_w_qminv_inst (rhc, inst, values, info_seq, max_samples, qminv, qcmask, &ntriggers, to_sample, to_invsample); + n = take_w_qminv_inst (rhc, &inst, values, info_seq, max_samples, qminv, qcmask, &ntriggers, to_sample, to_invsample); else n = DDS_RETCODE_PRECONDITION_NOT_MET; } @@ -2250,7 +2250,7 @@ static int32_t take_w_qminv (struct dds_rhc_default * __restrict rhc, bool lock, while (n_insts-- > 0 && n < max_samples) { struct rhc_instance * const inst1 = next_nonempty_instance (inst); - n += take_w_qminv_inst (rhc, inst, values + n, info_seq + n, max_samples - n, qminv, qcmask, &ntriggers, to_sample, to_invsample); + n += take_w_qminv_inst (rhc, &inst, values + n, info_seq + n, max_samples - n, qminv, qcmask, &ntriggers, to_sample, to_invsample); inst = inst1; } } @@ -2475,7 +2475,9 @@ static bool update_conditions_locked (struct dds_rhc_default *rhc, bool called_f TRACE ("update_conditions_locked(%p %p) - inst %"PRIu32" nonempty %"PRIu32" disp %"PRIu32" nowr %"PRIu32" new %"PRIu32" samples %"PRIu32" read %"PRIu32"\n", (void *) rhc, (void *) inst, rhc->n_instances, rhc->n_nonempty_instances, rhc->n_not_alive_disposed, rhc->n_not_alive_no_writers, rhc->n_new, rhc->n_vsamples, rhc->n_vread); - TRACE (" read -[%d,%d]+[%d,%d] qcmask -[%"PRIx32",%"PRIx32"]+[%"PRIx32",%"PRIx32"]\n", + TRACE (" pre (%"PRIx32",%d,%d) post (%"PRIx32",%d,%d) read -[%d,%d]+[%d,%d] qcmask -[%"PRIx32",%"PRIx32"]+[%"PRIx32",%"PRIx32"]\n", + pre->c.qminst, pre->c.has_read, pre->c.has_not_read, + post->c.qminst, post->c.has_read, post->c.has_not_read, trig_qc->dec_invsample_read, trig_qc->dec_sample_read, trig_qc->inc_invsample_read, trig_qc->inc_sample_read, trig_qc->dec_conds_invsample, trig_qc->dec_conds_sample, trig_qc->inc_conds_invsample, trig_qc->inc_conds_sample); @@ -2611,15 +2613,18 @@ static bool update_conditions_locked (struct dds_rhc_default *rhc, bool called_f or there was a match and now there is not: so also scan all samples for matches. The only difference is in whether the number of matches should be added or subtracted. */ int32_t mcurrent = 0; - if (inst->inv_exists) - mcurrent += (qmask_of_invsample (inst) & iter->m_qminv) == 0 && (inst->conds & qcmask) != 0; - if (inst->latest) + if (inst) { - struct rhc_sample *sample = inst->latest->next, * const end = sample; - do { - mcurrent += (qmask_of_sample (sample) & iter->m_qminv) == 0 && (sample->conds & qcmask) != 0; - sample = sample->next; - } while (sample != end); + if (inst->inv_exists) + mcurrent += (qmask_of_invsample (inst) & iter->m_qminv) == 0 && (inst->conds & qcmask) != 0; + if (inst->latest) + { + struct rhc_sample *sample = inst->latest->next, * const end = sample; + do { + mcurrent += (qmask_of_sample (sample) & iter->m_qminv) == 0 && (sample->conds & qcmask) != 0; + sample = sample->next; + } while (sample != end); + } } if (mdelta == 0 && mcurrent == 0) TRACE ("no change @ %"PRIu32" (2)", ddsrt_atomic_ld32 (&iter->m_entity.m_status.m_trigger)); From c29a81b339de245dd3fd13152c00e70bbadb9c8e Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 29 Apr 2020 17:47:13 +0200 Subject: [PATCH 202/238] Track deadline registration, consolidate updates Deadline registration, renewal and deregistration was somewhat spread through the code and relied on the "isdisposed" flag as a proxy for whether it was registered or not. This consolidates the deadline handling code in a final step of updating the instance and uses a separate flag to track whether the instance is currently registered in the deadline administration or not. This also makes it possible to trivially change the rules for when deadline notifications are required, and so allows for, e.g., adding a mode in which instances in the "no writers" state do not trigger any deadline missed notifications, or just once (both of which seem useful modes). Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_rhc_default.c | 129 +++++++++++++--------------- 1 file changed, 59 insertions(+), 70 deletions(-) diff --git a/src/core/ddsc/src/dds_rhc_default.c b/src/core/ddsc/src/dds_rhc_default.c index e1a17b1..2ee62f2 100644 --- a/src/core/ddsc/src/dds_rhc_default.c +++ b/src/core/ddsc/src/dds_rhc_default.c @@ -270,6 +270,7 @@ struct rhc_instance { unsigned wr_iid_islive : 1; /* whether wr_iid is of a live writer */ unsigned inv_exists : 1; /* whether or not state change occurred since last sample (i.e., must return invalid sample) */ unsigned inv_isread : 1; /* whether or not that state change has been read before */ + unsigned deadline_reg : 1; /* whether or not registered for a deadline (== isdisposed, except store() defers updates) */ uint32_t disposed_gen; /* bloody generation counters - worst invention of mankind */ uint32_t no_writers_gen; /* __/ */ int32_t strength; /* "current" ownership strength */ @@ -713,7 +714,7 @@ static void free_empty_instance (struct rhc_instance *inst, struct dds_rhc_defau assert (inst_is_empty (inst)); ddsi_tkmap_instance_unref (rhc->tkmap, inst->tk); #ifdef DDSI_INCLUDE_DEADLINE_MISSED - if (!inst->isdisposed) + if (inst->deadline_reg) deadline_unregister_instance_locked (&rhc->deadline, &inst->deadline); #endif ddsrt_free (inst); @@ -918,11 +919,6 @@ static bool add_sample (struct dds_rhc_default *rhc, struct rhc_instance *inst, s->lifespan.t_expire = wrinfo->lifespan_exp; lifespan_register_sample_locked (&rhc->lifespan, &s->lifespan); #endif -#ifdef DDSI_INCLUDE_DEADLINE_MISSED - /* Only renew the deadline missed counter in case the sample is actually stored in the rhc */ - if (!inst->isdisposed) - deadline_renew_instance_locked (&rhc->deadline, &inst->deadline); -#endif s->conds = 0; if (rhc->nqconds != 0) @@ -1264,8 +1260,7 @@ static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_in else if (inst->isdisposed) { /* No content left, no registrations left, so drop */ - TRACE (",#0,empty,disposed,drop"); - drop_instance_noupdate_no_writers (rhc, instptr); + TRACE (",#0,empty,nowriters,disposed"); return 1; } else @@ -1318,6 +1313,7 @@ static struct rhc_instance *alloc_new_instance (struct dds_rhc_default *rhc, con inst->tk = tk; inst->wrcount = (serdata->statusinfo & NN_STATUSINFO_UNREGISTER) ? 0 : 1; inst->isdisposed = (serdata->statusinfo & NN_STATUSINFO_DISPOSE) != 0; + inst->deadline_reg = 0; inst->isnew = 1; inst->a_sample_free = 1; inst->conds = 0; @@ -1337,12 +1333,6 @@ static struct rhc_instance *alloc_new_instance (struct dds_rhc_default *rhc, con inst->conds |= c->m_query.m_qcmask; } } - -#ifdef DDSI_INCLUDE_DEADLINE_MISSED - if (!inst->isdisposed) - deadline_register_instance_locked (&rhc->deadline, &inst->deadline, ddsrt_time_monotonic ()); -#endif - return inst; } @@ -1410,6 +1400,44 @@ static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst return RHC_STORED; } +static void postprocess_instance_update (struct dds_rhc_default * __restrict rhc, struct rhc_instance * __restrict * __restrict instptr, const struct trigger_info_pre *pre, const struct trigger_info_post *post, struct trigger_info_qcond *trig_qc, dds_entity *triggers[], size_t *ntriggers) +{ + { + struct rhc_instance *inst = *instptr; + +#ifdef DDSI_INCLUDE_DEADLINE_MISSED + if (inst->isdisposed) + { + if (inst->deadline_reg) + { + inst->deadline_reg = 0; + deadline_unregister_instance_locked (&rhc->deadline, &inst->deadline); + } + } + else + { + if (inst->deadline_reg) + deadline_renew_instance_locked (&rhc->deadline, &inst->deadline); + else + { + deadline_register_instance_locked (&rhc->deadline, &inst->deadline, ddsrt_time_monotonic ()); + inst->deadline_reg = 1; + } + } +#endif + + if (inst_is_empty (inst) && inst->wrcount == 0) + { + drop_instance_noupdate_no_writers (rhc, instptr); + } + } + + if (trigger_info_differs (rhc, pre, post, trig_qc)) + update_conditions_locked (rhc, true, pre, post, trig_qc, *instptr, triggers, ntriggers); + + assert (rhc_check_counts_locked (rhc, true, true)); +} + /* dds_rhc_store: DDSI up call into read cache to store new sample. Returns whether sample delivered (true unless a reliable sample rejected). @@ -1429,22 +1457,25 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons struct trigger_info_qcond trig_qc; rhc_store_result_t stored; status_cb_data_t cb_data; /* Callback data for reader status callback */ - bool delivered = true; - bool notify_data_available = false; + bool notify_data_available; + dds_entity *triggers[MAX_FAST_TRIGGERS]; + size_t ntriggers; - TRACE ("rhc_store(%"PRIx64",%"PRIx64" si %x has_data %d:", tk->m_iid, wr_iid, statusinfo, has_data); + TRACE ("rhc_store %"PRIx64",%"PRIx64" si %x has_data %d:", tk->m_iid, wr_iid, statusinfo, has_data); if (!has_data && statusinfo == 0) { /* Write with nothing but a key -- I guess that would be a register, which we do implicitly. (Currently DDSI2 won't allow it through anyway.) */ - TRACE (" ignore explicit register)\n"); - return delivered; + TRACE (" ignore explicit register\n"); + return true; } + notify_data_available = false; dummy_instance.iid = tk->m_iid; stored = RHC_FILTERED; cb_data.raw_status_id = -1; + ntriggers = 0; init_trigger_info_qcond (&trig_qc); @@ -1459,7 +1490,7 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons */ if (!has_data && !is_dispose) { - TRACE (" disp/unreg on unknown instance"); + TRACE (" unreg on unknown instance\n"); goto error_or_nochange; } else @@ -1481,7 +1512,7 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons will raise a SAMPLE_REJECTED, and indicate that the system should kill itself.) Not letting instances go to ALIVE or NEW based on a rejected sample - (no one knows, it seemed) */ - TRACE (" instance rejects sample"); + TRACE (" instance rejects sample\n"); get_trigger_info_pre (&pre, inst); if (has_data || is_dispose) @@ -1553,19 +1584,11 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons TRACE (" disposed->notdisposed"); inst->isdisposed = 0; inst->disposed_gen++; -#ifdef DDSI_INCLUDE_DEADLINE_MISSED - if (!is_dispose) - deadline_register_instance_locked (&rhc->deadline, &inst->deadline, ddsrt_time_monotonic ()); -#endif } if (is_dispose) { inst->isdisposed = 1; inst_became_disposed = !old_isdisposed; -#ifdef DDSI_INCLUDE_DEADLINE_MISSED - if (inst_became_disposed) - deadline_unregister_instance_locked (&rhc->deadline, &inst->deadline); -#endif TRACE (" dispose(%d)", inst_became_disposed); } @@ -1587,17 +1610,11 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons if (!inst->isdisposed) { inst->isdisposed = 1; -#ifdef DDSI_INCLUDE_DEADLINE_MISSED - deadline_unregister_instance_locked (&rhc->deadline, &inst->deadline); -#endif } } else if (inst->isdisposed) { inst->isdisposed = 0; -#ifdef DDSI_INCLUDE_DEADLINE_MISSED - deadline_register_instance_locked (&rhc->deadline, &inst->deadline, ddsrt_time_monotonic ()); -#endif } goto error_or_nochange; } @@ -1654,15 +1671,9 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons } } - TRACE (")\n"); - - dds_entity *triggers[MAX_FAST_TRIGGERS]; - size_t ntriggers = 0; - if (trigger_info_differs (rhc, &pre, &post, &trig_qc)) - update_conditions_locked (rhc, true, &pre, &post, &trig_qc, inst, triggers, &ntriggers); - - assert (rhc_check_counts_locked (rhc, true, true)); + postprocess_instance_update (rhc, &inst, &pre, &post, &trig_qc, triggers, &ntriggers); +error_or_nochange: ddsrt_mutex_unlock (&rhc->lock); if (rhc->reader) @@ -1671,25 +1682,10 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons dds_reader_data_available_cb (rhc->reader); for (size_t i = 0; i < ntriggers; i++) dds_entity_status_signal (triggers[i], 0); + if (cb_data.raw_status_id >= 0) + dds_reader_status_cb (&rhc->reader->m_entity, &cb_data); } - - return delivered; - -error_or_nochange: - - if (rhc->reliable && (stored == RHC_REJECTED)) - { - delivered = false; - } - - ddsrt_mutex_unlock (&rhc->lock); - TRACE (")\n"); - - /* Make any reader status callback */ - - if (cb_data.raw_status_id >= 0 && rhc->reader) - dds_reader_status_cb (&rhc->reader->m_entity, &cb_data); - return delivered; + return !(rhc->reliable && stored == RHC_REJECTED); } static void dds_rhc_default_unregister_wr (struct ddsi_rhc * __restrict rhc_common, const struct ddsi_writer_info * __restrict wrinfo) @@ -1736,9 +1732,6 @@ static void dds_rhc_default_unregister_wr (struct ddsi_rhc * __restrict rhc_comm if (auto_dispose && !inst->isdisposed) { inst->isdisposed = 1; -#ifdef DDSI_INCLUDE_DEADLINE_MISSED - deadline_unregister_instance_locked (&rhc->deadline, &inst->deadline); -#endif /* Set invalid sample for disposing it (unregister may also set it for unregistering) */ if (inst->latest) @@ -1758,13 +1751,9 @@ static void dds_rhc_default_unregister_wr (struct ddsi_rhc * __restrict rhc_comm } (void) dds_rhc_unregister (rhc, &inst, wrinfo, inst->tstamp, &post, &trig_qc); - - TRACE ("\n"); - notify_data_available = true; - if (trigger_info_differs (rhc, &pre, &post, &trig_qc)) - update_conditions_locked (rhc, true, &pre, &post, &trig_qc, inst, NULL, &ntriggers); - assert (rhc_check_counts_locked (rhc, true, false)); + postprocess_instance_update (rhc, &inst, &pre, &post, &trig_qc, NULL, &ntriggers); + TRACE ("\n"); } } TRACE (")\n"); From 7f8f1d1a125a060168d4d563ba7db95d4043781f Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 29 Apr 2020 17:59:22 +0200 Subject: [PATCH 203/238] Auto-dispose when the instance goes to NO_WRITERS This changes the behaviour of auto-dispose writers: instead of always disposing when the writer disposes the data, it now only disposes the data when the instance would otherwise go to the "no writers" state. This only affects the behaviour when there are multiple writers for the same instance. In case the writers use a different value for the auto-dispose setting, it now tracks whether an instance has ever been touched by an writer with auto-dispose enabled, and treats auto-disposes the instance when the last writer leaves if this is the case. This way, if an instance is registered by one auto-dispose and one non-auto-dispose writer, the order of unregistering does not matter. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_rhc_default.c | 67 ++++++++++++++++------- src/core/ddsc/tests/listener.c | 6 +- src/core/xtests/rhc_torture/rhc_torture.c | 44 +++++++++++---- 3 files changed, 84 insertions(+), 33 deletions(-) diff --git a/src/core/ddsc/src/dds_rhc_default.c b/src/core/ddsc/src/dds_rhc_default.c index 2ee62f2..09989e0 100644 --- a/src/core/ddsc/src/dds_rhc_default.c +++ b/src/core/ddsc/src/dds_rhc_default.c @@ -267,6 +267,7 @@ struct rhc_instance { unsigned isnew : 1; /* NEW or NOT_NEW view state */ unsigned a_sample_free : 1; /* whether or not a_sample is in use */ unsigned isdisposed : 1; /* DISPOSED or NOT_DISPOSED (if not disposed, wrcount determines ALIVE/NOT_ALIVE_NO_WRITERS) */ + unsigned autodispose : 1; /* wrcount > 0 => at least one registered writer has had auto-dispose set on some update */ unsigned wr_iid_islive : 1; /* whether wr_iid is of a live writer */ unsigned inv_exists : 1; /* whether or not state change occurred since last sample (i.e., must return invalid sample) */ unsigned inv_isread : 1; /* whether or not that state change has been read before */ @@ -696,7 +697,12 @@ static void inst_clear_invsample_if_exists (struct dds_rhc_default *rhc, struct static void inst_set_invsample (struct dds_rhc_default *rhc, struct rhc_instance *inst, struct trigger_info_qcond *trig_qc, bool *nda) { - if (!inst->inv_exists || inst->inv_isread) + if (inst->inv_exists && !inst->inv_isread) + { + /* FIXME: should this indeed trigger a "notify data available" event?*/ + *nda = true; + } + else { /* Obviously optimisable, but that is perhaps not worth the bother */ inst_clear_invsample_if_exists (rhc, inst, trig_qc); @@ -1027,7 +1033,7 @@ static void drop_instance_noupdate_no_writers (struct dds_rhc_default *__restric *instptr = NULL; } -static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance *inst, uint64_t wr_iid, bool iid_update) +static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance *inst, uint64_t wr_iid, bool autodispose, bool iid_update) { const uint64_t inst_wr_iid = inst->wr_iid_islive ? inst->wr_iid : 0; @@ -1064,6 +1070,7 @@ static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance * } inst->wrcount++; inst->no_writers_gen++; + inst->autodispose = autodispose; TRACE ("new1"); if (!inst_is_empty (inst) && !inst->isdisposed) @@ -1089,6 +1096,8 @@ static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance * if (lwregs_add (&rhc->registrations, inst->iid, wr_iid)) { inst->wrcount++; + if (autodispose) + inst->autodispose = 1; TRACE ("new2iidnull"); } else @@ -1125,6 +1134,8 @@ static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance * registers a previously unknown writer or not */ TRACE ("new3"); inst->wrcount++; + if (autodispose) + inst->autodispose = 1; } else { @@ -1218,6 +1229,8 @@ static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_in { struct rhc_instance * const inst = *instptr; assert (inst->wrcount > 0); + if (wrinfo->auto_dispose) + inst->autodispose = 1; if (--inst->wrcount > 0) { @@ -1239,20 +1252,27 @@ static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_in if (!inst_is_empty (inst)) { /* Instance still has content - do not drop until application - takes the last sample. Set the invalid sample if the latest - sample has been read already, so that the application can - read the change to not-alive. (If the latest sample is still - unread, we don't bother, even though it means the application - won't see the timestamp for the unregister event. It shouldn't - care.) */ - if (inst->latest == NULL || inst->latest->isread) - { - inst_set_invsample (rhc, inst, trig_qc, nda); - update_inst (inst, wrinfo, false, tstamp); - } + takes the last sample. Set the invalid sample if the latest + sample has been read already, so that the application can + read the change to not-alive. (If the latest sample is still + unread, we don't bother, even though it means the application + won't see the timestamp for the unregister event. It shouldn't + care.) */ if (!inst->isdisposed) { - rhc->n_not_alive_no_writers++; + if (inst->latest == NULL || inst->latest->isread) + { + inst_set_invsample (rhc, inst, trig_qc, nda); + update_inst (inst, wrinfo, false, tstamp); + } + if (!inst->autodispose) + rhc->n_not_alive_no_writers++; + else + { + TRACE (",autodispose"); + inst->isdisposed = 1; + rhc->n_not_alive_disposed++; + } } inst->wr_iid_islive = 0; return 0; @@ -1270,6 +1290,11 @@ static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_in assert (inst_is_empty (inst)); inst_set_invsample (rhc, inst, trig_qc, nda); update_inst (inst, wrinfo, false, tstamp); + if (inst->autodispose) + { + TRACE (",autodispose"); + inst->isdisposed = 1; + } account_for_empty_to_nonempty_transition (rhc, inst); inst->wr_iid_islive = 0; return 0; @@ -1313,6 +1338,7 @@ static struct rhc_instance *alloc_new_instance (struct dds_rhc_default *rhc, con inst->tk = tk; inst->wrcount = (serdata->statusinfo & NN_STATUSINFO_UNREGISTER) ? 0 : 1; inst->isdisposed = (serdata->statusinfo & NN_STATUSINFO_DISPOSE) != 0; + inst->autodispose = wrinfo->auto_dispose; inst->deadline_reg = 0; inst->isnew = 1; inst->a_sample_free = 1; @@ -1517,7 +1543,7 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons get_trigger_info_pre (&pre, inst); if (has_data || is_dispose) { - dds_rhc_register (rhc, inst, wr_iid, false); + dds_rhc_register (rhc, inst, wr_iid, wrinfo->auto_dispose, false); } if (statusinfo & NN_STATUSINFO_UNREGISTER) { @@ -1563,7 +1589,7 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons (i.e., out-of-memory), abort the operation and hope that the caller can still notify the application. */ - dds_rhc_register (rhc, inst, wr_iid, true); + dds_rhc_register (rhc, inst, wr_iid, wrinfo->auto_dispose, true); /* Sample arriving for a NOT_ALIVE instance => view state NEW */ if (has_data && not_alive) @@ -1710,16 +1736,16 @@ static void dds_rhc_default_unregister_wr (struct ddsi_rhc * __restrict rhc_comm struct rhc_instance *inst; struct ddsrt_hh_iter iter; const uint64_t wr_iid = wrinfo->iid; - const int auto_dispose = wrinfo->auto_dispose; - + const bool auto_dispose = wrinfo->auto_dispose; size_t ntriggers = SIZE_MAX; ddsrt_mutex_lock (&rhc->lock); - TRACE ("rhc_unregister_wr_iid(%"PRIx64",%d:\n", wr_iid, auto_dispose); + TRACE ("rhc_unregister_wr_iid %"PRIx64",%d:\n", wr_iid, wrinfo->auto_dispose); for (inst = ddsrt_hh_iter_first (rhc->instances, &iter); inst; inst = ddsrt_hh_iter_next (&iter)) { if ((inst->wr_iid_islive && inst->wr_iid == wr_iid) || lwregs_contains (&rhc->registrations, inst->iid, wr_iid)) { + assert (inst->wrcount > 0); struct trigger_info_pre pre; struct trigger_info_post post; struct trigger_info_qcond trig_qc; @@ -1731,10 +1757,11 @@ static void dds_rhc_default_unregister_wr (struct ddsi_rhc * __restrict rhc_comm assert (inst->wrcount > 0); if (auto_dispose && !inst->isdisposed) { + notify_data_available = true; inst->isdisposed = 1; /* Set invalid sample for disposing it (unregister may also set it for unregistering) */ - if (inst->latest) + if (inst->latest && !inst->latest->isread) { assert (!inst->inv_exists); rhc->n_not_alive_disposed++; diff --git a/src/core/ddsc/tests/listener.c b/src/core/ddsc/tests/listener.c index 1ad9f71..0ab0108 100644 --- a/src/core/ddsc/tests/listener.c +++ b/src/core/ddsc/tests/listener.c @@ -997,9 +997,9 @@ CU_Test(ddsc_listener, data_available_delete_writer_disposed, .init=init_trigger ret = dds_delete (g_writer); CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); g_writer = 0; - triggered = waitfor_cb(DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); + ddsrt_mutex_lock(&g_mutex); + CU_ASSERT_EQUAL_FATAL(cb_called & DDS_DATA_AVAILABLE_STATUS_ID, 0); + ddsrt_mutex_unlock(&g_mutex); /* The listener should have swallowed the status. */ ret = dds_read_status(g_subscriber, &status, DDS_DATA_ON_READERS_STATUS); diff --git a/src/core/xtests/rhc_torture/rhc_torture.c b/src/core/xtests/rhc_torture/rhc_torture.c index fe9dc53..132fbc6 100644 --- a/src/core/xtests/rhc_torture/rhc_torture.c +++ b/src/core/xtests/rhc_torture/rhc_torture.c @@ -935,6 +935,7 @@ int main (int argc, char **argv) printf ("************* 0 *************\n"); struct dds_rhc *rhc = mkrhc (gv, NULL, DDS_HISTORY_KEEP_LAST, 1, DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP); struct proxy_writer *wr0 = mkwr (gv, 1); + struct proxy_writer *wr1 = mkwr (gv, 1); uint64_t iid0, iid1, iid_t; iid0 = store (tkmap, rhc, wr0, mksample (0, 0), print, false); iid1 = store (tkmap, rhc, wr0, mksample (1, NN_STATUSINFO_DISPOSE), print, false); @@ -944,17 +945,38 @@ int main (int argc, char **argv) { 0, 0, 0, 0, 0, 0, 0, 0 } }; rdall (rhc, c0, print, states_seen); - iid_t = store (tkmap, rhc, wr0, mkkeysample (0, NN_STATUSINFO_UNREGISTER), print, false); + /* write instance 0 with 2nd writer to have 2 live writers */ + iid_t = store (tkmap, rhc, wr1, mksample (0, 0), print, false); assert (iid_t == iid0); - (void)iid0; - (void)iid_t; const struct check c1[] = { - { "ROU", iid0, wr0->e.iid, 0,0, 1, 0,1 }, - { "NOU", iid0, 0, 0,0, 0, 0,0 }, + { "NOA", iid0, wr1->e.iid, 0,0, 1, 0,3 }, { "ROD", iid1, wr0->e.iid, 0,0, 1, 1,2 }, { 0, 0, 0, 0, 0, 0, 0, 0 } }; rdall (rhc, c1, print, states_seen); + /* unregister instance 0 with wr0 - autodispose, but 2nd writer keeps it alive, no visible change */ + iid_t = store (tkmap, rhc, wr0, mkkeysample (0, NN_STATUSINFO_UNREGISTER), print, false); + assert (iid_t == iid0); + const struct check c2[] = { + { "ROA", iid0, wr1->e.iid, 0,0, 1, 0,3 }, + { "ROD", iid1, wr0->e.iid, 0,0, 1, 1,2 }, + { 0, 0, 0, 0, 0, 0, 0, 0 } + }; + rdall (rhc, c2, print, states_seen); + /* unregistering instance 0 again should be a no-op because wr0 no longer has it registered */ + iid_t = store (tkmap, rhc, wr0, mkkeysample (0, NN_STATUSINFO_UNREGISTER), print, false); + assert (iid_t == iid0); + rdall (rhc, c2, print, states_seen); + /* unregistering instance 0 with wr1 - autodispose, no live writers -> dispose */ + iid_t = store (tkmap, rhc, wr1, mkkeysample (0, NN_STATUSINFO_UNREGISTER), print, false); + assert (iid_t == iid0); + const struct check c3[] = { + { "ROD", iid0, wr1->e.iid, 0,0, 1, 0,3 }, + { "NOD", iid0, 0, 0,0, 0, 0,0 }, + { "ROD", iid1, wr0->e.iid, 0,0, 1, 1,2 }, + { 0, 0, 0, 0, 0, 0, 0, 0 } + }; + rdall (rhc, c3, print, states_seen); thread_state_awake_domain_ok (lookup_thread_state ()); struct ddsi_writer_info wr0_info; wr0_info.auto_dispose = wr0->c.xqos->writer_data_lifecycle.autodispose_unregistered_instances; @@ -966,16 +988,18 @@ int main (int argc, char **argv) #endif dds_rhc_unregister_wr (rhc, &wr0_info); thread_state_asleep (lookup_thread_state ()); - const struct check c2[] = { - { "ROU", iid0, wr0->e.iid, 0,0, 1, 0,1 }, - { "ROU", iid0, 0, 0,0, 0, 0,0 }, + const struct check c4[] = { + { "ROD", iid0, wr1->e.iid, 0,0, 1, 0,3 }, + { "ROD", iid0, 0, 0,0, 0, 0,0 }, { "ROD", iid1, wr0->e.iid, 0,0, 1, 1,2 }, - { "NOD", iid1, 0, 0,0, 0, 1,0 }, + // { "NOD", iid1, 0, 0,0, 0, 1,0 }, doesn't exist because it is already disposed { 0, 0, 0, 0, 0, 0, 0, 0 } }; - tkall (rhc, c2, print, states_seen); + tkall (rhc, c4, print, states_seen); frhc (rhc); fwr (wr0); + fwr (wr1); + (void)iid_t; } if (1 >= first) From 347b6edf047cb8ba08da6ef21c7a06623d19e82e Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 29 Apr 2020 19:49:59 +0200 Subject: [PATCH 204/238] Default to doing expensive checks in rhc_torture The entire point of this test program is to exercise the RHC while checking its internal state. The likelihood of (at least some) forgetting to enable the "expensive" checks has been proven to be significant. Signed-off-by: Erik Boasson --- src/core/xtests/rhc_torture/rhc_torture.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/core/xtests/rhc_torture/rhc_torture.c b/src/core/xtests/rhc_torture/rhc_torture.c index 132fbc6..b08fa4f 100644 --- a/src/core/xtests/rhc_torture/rhc_torture.c +++ b/src/core/xtests/rhc_torture/rhc_torture.c @@ -894,6 +894,7 @@ int main (int argc, char **argv) uint32_t states_seen[2 * 2 * 3][2] = {{ 0 }}; unsigned seed = 0; bool print = false; + int xchecks = 1; int first = 0, count = 10000; ddsrt_mutex_init (&wait_gc_cycle_lock); @@ -909,10 +910,21 @@ int main (int argc, char **argv) count = atoi (argv[3]); if (argc > 4) print = (atoi (argv[4]) != 0); + if (argc > 5) + xchecks = atoi (argv[4]); - printf ("prng seed %u first %d count %d print %d\n", seed, first, count, print); + printf ("prng seed %u first %d count %d print %d xchecks %d\n", seed, first, count, print, xchecks); ddsrt_prng_init_simple (&prng, seed); + if (xchecks != 0) + { + struct ddsi_domaingv *gv = get_gv (pp); + if (xchecks > 0) + gv->config.enabled_xchecks = ~0u; + else + gv->config.enabled_xchecks = 0u; + } + memset (rres_mseq, 0, sizeof (rres_mseq)); for (size_t i = 0; i < sizeof (rres_iseq) / sizeof(rres_iseq[0]); i++) rres_ptrs[i] = &rres_mseq[i]; From 0be287b67bca5e778cd42ef4a7d92a202d3c6619 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 29 Apr 2020 19:50:52 +0200 Subject: [PATCH 205/238] No auto-dispose in deadline test Use of an auto-dispose writer meant the NO_WRITERS case did not actually get tested. The behaviour of the implementation was to generate deadline missed notifications for such instances, but the test expected otherwise. There is a disagreement between different DDS implementations on the desirability of generating deadline missed notifications for NOT_ALIVE instances. Deadline notifications on DISPOSED instances seems silly, as it means end-of-life. Deadline notifications on a NO_WRITERS instance are certainly valuable for applications that don't pay attention to the number of writers (otherwise one has to monitor both liveliness changed and deadline missed notifications to be be sure to get some notification). Different usage patterns definitely affect what is desirable and I doubt one-size-fits-all is the right approach. This commit changes the test and retains the behaviour, and if it errs, it at least errs on the side of caution. Signed-off-by: Erik Boasson --- src/core/ddsc/tests/deadline.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/core/ddsc/tests/deadline.c b/src/core/ddsc/tests/deadline.c index e10bd74..c97debb 100644 --- a/src/core/ddsc/tests/deadline.c +++ b/src/core/ddsc/tests/deadline.c @@ -125,6 +125,7 @@ static void deadline_init(void) dds_qset_history(g_qos, DDS_HISTORY_KEEP_ALL, DDS_LENGTH_UNLIMITED); dds_qset_durability(g_qos, DDS_DURABILITY_TRANSIENT_LOCAL); dds_qset_reliability(g_qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY); + dds_qset_writer_data_lifecycle(g_qos, false); } static void deadline_fini(void) @@ -422,7 +423,10 @@ CU_Theory((int32_t n_inst, uint8_t unreg_nth, uint8_t dispose_nth), ddsc_deadlin n_dispose++; } } - n_alive = n_inst - n_dispose - n_unreg; + /* FIXME: should unregistered instances cause deadline expirations? I do think so + and that is what it actually implemented + if they shouldn't: n_alive = n_inst - n_dispose - n_unreg */ + n_alive = n_inst - n_dispose; /* Sleep deadline_dur + 50% and check missed deadline count */ sleepfor(3 * deadline_dur / 2); From 6800887a7433796e1731c86a94d15731b90145d7 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 29 Apr 2020 20:00:51 +0200 Subject: [PATCH 206/238] Always add invalid sample if empty or latest read Disposing an instance would only add an invalid sample if the instance is empty, but it should also do so when the latest sample is read. Otherwise reading all NOT_READ samples gives nothing or nonsensical output. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_rhc_default.c | 2 +- src/core/ddsc/tests/reader_iterator.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/ddsc/src/dds_rhc_default.c b/src/core/ddsc/src/dds_rhc_default.c index 09989e0..0a373e7 100644 --- a/src/core/ddsc/src/dds_rhc_default.c +++ b/src/core/ddsc/src/dds_rhc_default.c @@ -1648,7 +1648,7 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons } /* If instance became disposed, add an invalid sample if there are no samples left */ - if (inst_became_disposed && inst->latest == NULL) + if (inst_became_disposed && (inst->latest == NULL || inst->latest->isread)) inst_set_invsample (rhc, inst, &trig_qc, ¬ify_data_available); update_inst (inst, wrinfo, true, sample->timestamp); diff --git a/src/core/ddsc/tests/reader_iterator.c b/src/core/ddsc/tests/reader_iterator.c index df1e4c1..945564c 100644 --- a/src/core/ddsc/tests/reader_iterator.c +++ b/src/core/ddsc/tests/reader_iterator.c @@ -55,7 +55,7 @@ #define MAX_SAMPLES 21 #define RDR_NOT_READ_CNT 11 -#define RDR_INV_READ_CNT 1 +#define RDR_INV_READ_CNT 2 int rdr_expected_long_2[RDR_NOT_READ_CNT] = { 0, 1, 2, 6, 7, 9, 11, 13, 14, 16, 19 }; /* Because we only read one sample at a time, only the first sample of an instance From ebdb3fc5cf38c3bee423155d064842f4859d1e8d Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 29 Apr 2020 20:08:48 +0200 Subject: [PATCH 207/238] Refactor storing and unregistering writers in RHC Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_rhc_default.c | 245 +++++++++++----------------- 1 file changed, 94 insertions(+), 151 deletions(-) diff --git a/src/core/ddsc/src/dds_rhc_default.c b/src/core/ddsc/src/dds_rhc_default.c index 0a373e7..9195cd9 100644 --- a/src/core/ddsc/src/dds_rhc_default.c +++ b/src/core/ddsc/src/dds_rhc_default.c @@ -695,7 +695,7 @@ static void inst_clear_invsample_if_exists (struct dds_rhc_default *rhc, struct inst_clear_invsample (rhc, inst, trig_qc); } -static void inst_set_invsample (struct dds_rhc_default *rhc, struct rhc_instance *inst, struct trigger_info_qcond *trig_qc, bool *nda) +static void inst_set_invsample (struct dds_rhc_default *rhc, struct rhc_instance *inst, struct trigger_info_qcond *trig_qc, bool * __restrict nda) { if (inst->inv_exists && !inst->inv_isread) { @@ -842,7 +842,7 @@ static bool trigger_info_differs (const struct dds_rhc_default *rhc, const struc trig_qc->dec_sample_read != trig_qc->inc_sample_read); } -static bool add_sample (struct dds_rhc_default *rhc, struct rhc_instance *inst, const struct ddsi_writer_info *wrinfo, const struct ddsi_serdata *sample, status_cb_data_t *cb_data, struct trigger_info_qcond *trig_qc) +static bool add_sample (struct dds_rhc_default *rhc, struct rhc_instance *inst, const struct ddsi_writer_info *wrinfo, const struct ddsi_serdata *sample, status_cb_data_t *cb_data, struct trigger_info_qcond *trig_qc, bool * __restrict nda) { struct rhc_sample *s; @@ -936,6 +936,7 @@ static bool add_sample (struct dds_rhc_default *rhc, struct rhc_instance *inst, trig_qc->inc_conds_sample = s->conds; inst->latest = s; + *nda = true; return true; } @@ -1033,7 +1034,7 @@ static void drop_instance_noupdate_no_writers (struct dds_rhc_default *__restric *instptr = NULL; } -static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance *inst, uint64_t wr_iid, bool autodispose, bool iid_update) +static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance *inst, uint64_t wr_iid, bool autodispose, bool iid_update, bool * __restrict nda) { const uint64_t inst_wr_iid = inst->wr_iid_islive ? inst->wr_iid : 0; @@ -1054,10 +1055,8 @@ static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance * else. */ TRACE ("cached"); assert (inst->wrcount > 0); - return; } - - if (inst->wrcount == 0) + else if (inst->wrcount == 0) { /* Currently no writers at all */ assert (!inst->wr_iid_islive); @@ -1075,6 +1074,7 @@ static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance * if (!inst_is_empty (inst) && !inst->isdisposed) rhc->n_not_alive_no_writers--; + *nda = true; } else if (inst_wr_iid == 0 && inst->wrcount == 1) { @@ -1136,6 +1136,7 @@ static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance * inst->wrcount++; if (autodispose) inst->autodispose = 1; + *nda = true; } else { @@ -1181,7 +1182,7 @@ static void account_for_nonempty_to_empty_transition (struct dds_rhc_default *__ } } -static int rhc_unregister_isreg_w_sideeffects (struct dds_rhc_default *rhc, const struct rhc_instance *inst, uint64_t wr_iid) +static int rhc_unregister_delete_registration (struct dds_rhc_default *rhc, const struct rhc_instance *inst, uint64_t wr_iid) { /* Returns 1 if last registration just disappeared */ if (inst->wrcount == 0) @@ -1225,9 +1226,8 @@ static int rhc_unregister_isreg_w_sideeffects (struct dds_rhc_default *rhc, cons } } -static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_instance **instptr, const struct ddsi_writer_info * __restrict wrinfo, ddsrt_wctime_t tstamp, struct trigger_info_qcond *trig_qc, bool *nda) +static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_instance *inst, const struct ddsi_writer_info * __restrict wrinfo, ddsrt_wctime_t tstamp, struct trigger_info_qcond *trig_qc, bool * __restrict nda) { - struct rhc_instance * const inst = *instptr; assert (inst->wrcount > 0); if (wrinfo->auto_dispose) inst->autodispose = 1; @@ -1273,6 +1273,7 @@ static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_in inst->isdisposed = 1; rhc->n_not_alive_disposed++; } + *nda = true; } inst->wr_iid_islive = 0; return 0; @@ -1297,34 +1298,27 @@ static int rhc_unregister_updateinst (struct dds_rhc_default *rhc, struct rhc_in } account_for_empty_to_nonempty_transition (rhc, inst); inst->wr_iid_islive = 0; + *nda = true; return 0; } } } -static bool dds_rhc_unregister (struct dds_rhc_default *rhc, struct rhc_instance **instptr, const struct ddsi_writer_info * __restrict wrinfo, ddsrt_wctime_t tstamp, struct trigger_info_post *post, struct trigger_info_qcond *trig_qc) +static void dds_rhc_unregister (struct dds_rhc_default *rhc, struct rhc_instance *inst, const struct ddsi_writer_info * __restrict wrinfo, ddsrt_wctime_t tstamp, struct trigger_info_post *post, struct trigger_info_qcond *trig_qc, bool * __restrict nda) { - struct rhc_instance * const inst = *instptr; - bool notify_data_available = false; - - /* 'post' always gets set; instance may have been freed upon return. */ + /* 'post' always gets set */ TRACE (" unregister:"); - if (!rhc_unregister_isreg_w_sideeffects (rhc, inst, wrinfo->iid)) - { + if (!rhc_unregister_delete_registration (rhc, inst, wrinfo->iid)) { /* other registrations remain */ get_trigger_info_cmn (&post->c, inst); - } - else if (rhc_unregister_updateinst (rhc, instptr, wrinfo, tstamp, trig_qc, ¬ify_data_available)) - { + } else if (rhc_unregister_updateinst (rhc, inst, wrinfo, tstamp, trig_qc, nda)) { /* instance dropped */ init_trigger_info_cmn_nonmatch (&post->c); - } - else - { + } else { /* no writers remain, but instance not empty */ get_trigger_info_cmn (&post->c, inst); } - return notify_data_available; + TRACE (" nda=%d\n", *nda); } static struct rhc_instance *alloc_new_instance (struct dds_rhc_default *rhc, const struct ddsi_writer_info *wrinfo, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk) @@ -1336,7 +1330,7 @@ static struct rhc_instance *alloc_new_instance (struct dds_rhc_default *rhc, con memset (inst, 0, sizeof (*inst)); inst->iid = tk->m_iid; inst->tk = tk; - inst->wrcount = (serdata->statusinfo & NN_STATUSINFO_UNREGISTER) ? 0 : 1; + inst->wrcount = 1; inst->isdisposed = (serdata->statusinfo & NN_STATUSINFO_DISPOSE) != 0; inst->autodispose = wrinfo->auto_dispose; inst->deadline_reg = 0; @@ -1362,7 +1356,7 @@ static struct rhc_instance *alloc_new_instance (struct dds_rhc_default *rhc, con return inst; } -static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst, struct dds_rhc_default *rhc, const struct ddsi_writer_info *wrinfo, struct ddsi_serdata *sample, struct ddsi_tkmap_instance *tk, const bool has_data, status_cb_data_t *cb_data, struct trigger_info_post *post, struct trigger_info_qcond *trig_qc) +static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst, struct dds_rhc_default *rhc, const struct ddsi_writer_info *wrinfo, struct ddsi_serdata *sample, struct ddsi_tkmap_instance *tk, const bool has_data, status_cb_data_t *cb_data, struct trigger_info_qcond *trig_qc, bool * __restrict nda) { struct rhc_instance *inst; int ret; @@ -1400,7 +1394,7 @@ static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst inst = alloc_new_instance (rhc, wrinfo, sample, tk); if (has_data) { - if (!add_sample (rhc, inst, wrinfo, sample, cb_data, trig_qc)) + if (!add_sample (rhc, inst, wrinfo, sample, cb_data, trig_qc, nda)) { free_empty_instance (inst, rhc); return RHC_REJECTED; @@ -1408,10 +1402,8 @@ static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst } else { - if (inst->isdisposed) { - bool nda_dummy = false; - inst_set_invsample (rhc, inst, trig_qc, &nda_dummy); - } + if (inst->isdisposed) + inst_set_invsample (rhc, inst, trig_qc, nda); } account_for_empty_to_nonempty_transition (rhc, inst); @@ -1420,7 +1412,6 @@ static rhc_store_result_t rhc_store_new_instance (struct rhc_instance **out_inst (void) ret; rhc->n_instances++; rhc->n_new++; - get_trigger_info_cmn (&post->c, inst); *out_inst = inst; return RHC_STORED; @@ -1464,6 +1455,43 @@ static void postprocess_instance_update (struct dds_rhc_default * __restrict rhc assert (rhc_check_counts_locked (rhc, true, true)); } +static void update_viewstate_and_disposedness (struct dds_rhc_default * __restrict rhc, struct rhc_instance * __restrict inst, bool has_data, bool not_alive, bool is_dispose, bool * __restrict nda) +{ + /* Sample arriving for a NOT_ALIVE instance => view state NEW */ + if (has_data && not_alive) + { + TRACE (" notalive->alive"); + inst->isnew = 1; + *nda = true; + } + + /* Desired effect on instance state and disposed_gen: + op DISPOSED NOT_DISPOSED + W ND;gen++ ND + D D D + WD D;gen++ D + Simplest way is to toggle istate when it is currently DISPOSED + and the operation is WD. */ + if (has_data && inst->isdisposed) + { + TRACE (" disposed->notdisposed"); + inst->disposed_gen++; + if (!is_dispose) + inst->isdisposed = 0; + *nda = true; + } + if (is_dispose) + { + bool wasdisposed = inst->isdisposed; + if (!inst->isdisposed) + { + inst->isdisposed = 1; + *nda = true; + } + TRACE (" dispose(%d)", !wasdisposed); + } +} + /* dds_rhc_store: DDSI up call into read cache to store new sample. Returns whether sample delivered (true unless a reliable sample rejected). @@ -1521,14 +1549,12 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons } else { - TRACE (" new instance"); - stored = rhc_store_new_instance (&inst, rhc, wrinfo, sample, tk, has_data, &cb_data, &post, &trig_qc); + TRACE (" new instance\n"); + stored = rhc_store_new_instance (&inst, rhc, wrinfo, sample, tk, has_data, &cb_data, &trig_qc, ¬ify_data_available); if (stored != RHC_STORED) - { goto error_or_nochange; - } + init_trigger_info_cmn_nonmatch (&pre.c); - notify_data_available = true; } } else if (!inst_accepts_sample (rhc, inst, wrinfo, sample, has_data)) @@ -1542,25 +1568,13 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons get_trigger_info_pre (&pre, inst); if (has_data || is_dispose) - { - dds_rhc_register (rhc, inst, wr_iid, wrinfo->auto_dispose, false); - } - if (statusinfo & NN_STATUSINFO_UNREGISTER) - { - if (dds_rhc_unregister (rhc, &inst, wrinfo, sample->timestamp, &post, &trig_qc)) - notify_data_available = true; - } - else - { - get_trigger_info_cmn (&post.c, inst); - } - /* notify sample lost */ + dds_rhc_register (rhc, inst, wr_iid, wrinfo->auto_dispose, false, ¬ify_data_available); + /* notify sample lost */ cb_data.raw_status_id = (int) DDS_SAMPLE_LOST_STATUS_ID; cb_data.extra = 0; cb_data.handle = 0; cb_data.add = true; - goto error_or_nochange; } else { @@ -1579,7 +1593,6 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons const bool old_isdisposed = inst->isdisposed; const bool old_isnew = inst->isnew; const bool was_empty = inst_is_empty (inst); - int inst_became_disposed = 0; /* Not just an unregister, so a write and/or a dispose (possibly combined with an unregister). Write & dispose create a @@ -1589,66 +1602,29 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons (i.e., out-of-memory), abort the operation and hope that the caller can still notify the application. */ - dds_rhc_register (rhc, inst, wr_iid, wrinfo->auto_dispose, true); + dds_rhc_register (rhc, inst, wr_iid, wrinfo->auto_dispose, true, ¬ify_data_available); + update_viewstate_and_disposedness (rhc, inst, has_data, not_alive, is_dispose, ¬ify_data_available); - /* Sample arriving for a NOT_ALIVE instance => view state NEW */ - if (has_data && not_alive) - { - TRACE (" notalive->alive"); - inst->isnew = 1; - } - - /* Desired effect on instance state and disposed_gen: - op DISPOSED NOT_DISPOSED - W ND;gen++ ND - D D D - WD D;gen++ D - Simplest way is to toggle istate when it is currently DISPOSED - and the operation is WD. */ - if (has_data && inst->isdisposed) - { - TRACE (" disposed->notdisposed"); - inst->isdisposed = 0; - inst->disposed_gen++; - } - if (is_dispose) - { - inst->isdisposed = 1; - inst_became_disposed = !old_isdisposed; - TRACE (" dispose(%d)", inst_became_disposed); - } - - /* Only need to add a sample to the history if the input actually - is a sample. */ + /* Only need to add a sample to the history if the input actually is a sample. */ if (has_data) { TRACE (" add_sample"); - if (!add_sample (rhc, inst, wrinfo, sample, &cb_data, &trig_qc)) + if (!add_sample (rhc, inst, wrinfo, sample, &cb_data, &trig_qc, ¬ify_data_available)) { - TRACE ("(reject)"); + TRACE ("(reject)\n"); stored = RHC_REJECTED; /* FIXME: fix the bad rejection handling, probably put back in a proper rollback, until then a band-aid like this will have to do: */ inst->isnew = old_isnew; if (old_isdisposed) - { inst->disposed_gen--; - if (!inst->isdisposed) - { - inst->isdisposed = 1; - } - } - else if (inst->isdisposed) - { - inst->isdisposed = 0; - } + inst->isdisposed = old_isdisposed; goto error_or_nochange; } - notify_data_available = true; } /* If instance became disposed, add an invalid sample if there are no samples left */ - if (inst_became_disposed && (inst->latest == NULL || inst->latest->isread)) + if ((bool) inst->isdisposed > old_isdisposed && (inst->latest == NULL || inst->latest->isread)) inst_set_invsample (rhc, inst, &trig_qc, ¬ify_data_available); update_inst (inst, wrinfo, true, sample->timestamp); @@ -1658,7 +1634,7 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons guaranteed that we end up with a non-empty instance: for example, if the instance was disposed & empty, nothing changes. */ - if (inst->latest || inst_became_disposed) + if (inst->latest || (bool) inst->isdisposed > old_isdisposed) { if (was_empty) account_for_empty_to_nonempty_transition (rhc, inst); @@ -1672,29 +1648,30 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons } } + TRACE(" nda=%d\n", notify_data_available); assert (rhc_check_counts_locked (rhc, false, false)); + } - if (statusinfo & NN_STATUSINFO_UNREGISTER) - { - /* Either a pure unregister, or the instance rejected the sample - because of time stamps, content filter, or something else. If - the writer unregisters the instance, I think we should ignore - the acceptance filters and process it anyway. + if (statusinfo & NN_STATUSINFO_UNREGISTER) + { + /* Either a pure unregister, or the instance rejected the sample + because of time stamps, content filter, or something else. If + the writer unregisters the instance, I think we should ignore + the acceptance filters and process it anyway. - It is a bit unclear what + It is a bit unclear what - write_w_timestamp(x,1) ; unregister_w_timestamp(x,0) + write_w_timestamp(x,1) ; unregister_w_timestamp(x,0) - actually means if BY_SOURCE ordering is selected: does that - mean an application reading "x" after the write and reading it - again after the unregister will see a change in the - no_writers_generation field? */ - dds_rhc_unregister (rhc, &inst, wrinfo, sample->timestamp, &post, &trig_qc); - } - else - { - get_trigger_info_cmn (&post.c, inst); - } + actually means if BY_SOURCE ordering is selected: does that + mean an application reading "x" after the write and reading it + again after the unregister will see a change in the + no_writers_generation field? */ + dds_rhc_unregister (rhc, inst, wrinfo, sample->timestamp, &post, &trig_qc, ¬ify_data_available); + } + else + { + get_trigger_info_cmn (&post.c, inst); } postprocess_instance_update (rhc, &inst, &pre, &post, &trig_qc, triggers, &ntriggers); @@ -1736,7 +1713,6 @@ static void dds_rhc_default_unregister_wr (struct ddsi_rhc * __restrict rhc_comm struct rhc_instance *inst; struct ddsrt_hh_iter iter; const uint64_t wr_iid = wrinfo->iid; - const bool auto_dispose = wrinfo->auto_dispose; size_t ntriggers = SIZE_MAX; ddsrt_mutex_lock (&rhc->lock); @@ -1751,47 +1727,16 @@ static void dds_rhc_default_unregister_wr (struct ddsi_rhc * __restrict rhc_comm struct trigger_info_qcond trig_qc; get_trigger_info_pre (&pre, inst); init_trigger_info_qcond (&trig_qc); - TRACE (" %"PRIx64":", inst->iid); - - assert (inst->wrcount > 0); - if (auto_dispose && !inst->isdisposed) - { - notify_data_available = true; - inst->isdisposed = 1; - - /* Set invalid sample for disposing it (unregister may also set it for unregistering) */ - if (inst->latest && !inst->latest->isread) - { - assert (!inst->inv_exists); - rhc->n_not_alive_disposed++; - } - else - { - const bool was_empty = inst_is_empty (inst); - inst_set_invsample (rhc, inst, &trig_qc, ¬ify_data_available); - if (was_empty) - account_for_empty_to_nonempty_transition (rhc, inst); - else - rhc->n_not_alive_disposed++; - } - } - - (void) dds_rhc_unregister (rhc, &inst, wrinfo, inst->tstamp, &post, &trig_qc); - notify_data_available = true; + dds_rhc_unregister (rhc, inst, wrinfo, inst->tstamp, &post, &trig_qc, ¬ify_data_available); postprocess_instance_update (rhc, &inst, &pre, &post, &trig_qc, NULL, &ntriggers); TRACE ("\n"); } } - TRACE (")\n"); - ddsrt_mutex_unlock (&rhc->lock); - if (rhc->reader) - { - if (notify_data_available) - dds_reader_data_available_cb (rhc->reader); - } + if (rhc->reader && notify_data_available) + dds_reader_data_available_cb (rhc->reader); } static void dds_rhc_default_relinquish_ownership (struct ddsi_rhc * __restrict rhc_common, const uint64_t wr_iid) @@ -2044,7 +1989,6 @@ static int32_t read_w_qminv_inst (struct dds_rhc_default * const __restrict rhc, to_sample (sample->sample, values + n, 0, 0); if (!sample->isread) { - TRACE ("s"); read_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, sample->conds, false); sample->isread = true; inst->nvread++; @@ -2063,7 +2007,6 @@ static int32_t read_w_qminv_inst (struct dds_rhc_default * const __restrict rhc, to_invsample (rhc->topic, inst->tk->m_sample, values + n, 0, 0); if (!inst->inv_isread) { - TRACE ("i"); read_sample_update_conditions (rhc, &pre, &post, &trig_qc, inst, inst->conds, false); inst->inv_isread = 1; rhc->n_invread++; From 6ee69374ec67d58af3fdab2d744774ec35140a55 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 30 Apr 2020 09:20:04 +0200 Subject: [PATCH 208/238] Standard byte order when creating built-in samples The standard defines GUIDs as an array of 16 uint8_t and so they are presented on the network and in built-in topic samples. Internally they are arrays of 4 uint32_t, requiring byte-order conversion. A keyhash is also an array of 16 uint8_t, and used almost exclusively on the network. The exception is the generation of built-in topic samples, which relies on the "from_keyhash" function. One would expect the keyhash here to contain the GUID in the external representation, and this commit adds the byte-order conversions to conform to the expectation. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_builtin.c | 18 +++++++++++------- src/core/ddsc/src/dds_serdata_builtintopic.c | 10 ++++++---- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/core/ddsc/src/dds_builtin.c b/src/core/ddsc/src/dds_builtin.c index eee50f1..d224810 100644 --- a/src/core/ddsc/src/dds_builtin.c +++ b/src/core/ddsc/src/dds_builtin.c @@ -15,6 +15,7 @@ #include "dds/ddsi/q_entity.h" #include "dds/ddsi/q_thread.h" #include "dds/ddsi/q_config.h" +#include "dds/ddsi/q_bswap.h" #include "dds/ddsi/ddsi_domaingv.h" #include "dds/ddsi/ddsi_plist.h" #include "dds__init.h" @@ -181,10 +182,13 @@ static struct ddsi_tkmap_instance *dds__builtin_get_tkmap_entry (const struct dd struct dds_domain *domain = vdomain; struct ddsi_tkmap_instance *tk; struct ddsi_serdata *sd; - struct ddsi_keyhash kh; - memcpy (&kh, guid, sizeof (kh)); - /* any random builtin topic will do (provided it has a GUID for a key), because what matters is the "class" of the topic, not the actual topic; also, this is called early in the initialisation of the entity with this GUID, which simply causes serdata_from_keyhash to create a key-only serdata because the key lookup fails. */ - sd = ddsi_serdata_from_keyhash (domain->builtin_participant_topic, &kh); + union { ddsi_guid_t guid; struct ddsi_keyhash keyhash; } x; + x.guid = nn_hton_guid (*guid); + /* any random builtin topic will do (provided it has a GUID for a key), because what matters is the "class" + of the topic, not the actual topic; also, this is called early in the initialisation of the entity with + this GUID, which simply causes serdata_from_keyhash to create a key-only serdata because the key lookup + fails. */ + sd = ddsi_serdata_from_keyhash (domain->builtin_participant_topic, &x.keyhash); tk = ddsi_tkmap_find (domain->gv.m_tkmap, sd, true); ddsi_serdata_unref (sd); return tk; @@ -196,7 +200,7 @@ struct ddsi_serdata *dds__builtin_make_sample (const struct entity_common *e, dd struct dds_domain *dom = e->gv->builtin_topic_interface->arg; struct ddsi_sertopic *topic = NULL; struct ddsi_serdata *serdata; - struct ddsi_keyhash keyhash; + union { ddsi_guid_t guid; struct ddsi_keyhash keyhash; } x; switch (e->kind) { case EK_PARTICIPANT: @@ -213,8 +217,8 @@ struct ddsi_serdata *dds__builtin_make_sample (const struct entity_common *e, dd break; } assert (topic != NULL); - memcpy (&keyhash, &e->guid, sizeof (keyhash)); - serdata = ddsi_serdata_from_keyhash (topic, &keyhash); + x.guid = nn_hton_guid (e->guid); + serdata = ddsi_serdata_from_keyhash (topic, &x.keyhash); serdata->timestamp = timestamp; serdata->statusinfo = alive ? 0 : NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER; return serdata; diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index 614a566..9991e8b 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -130,10 +130,12 @@ static struct ddsi_serdata *ddsi_serdata_builtin_from_keyhash (const struct ddsi { /* FIXME: not quite elegant to manage the creation of a serdata for a built-in topic via this function, but I also find it quite unelegant to let from_sample read straight from the underlying internal entity, and to_sample convert to the external format ... I could claim the internal entity is the "serialised form", but that forces wrapping it in a fragchain in one way or another, which, though possible, is also a bit lacking in elegance. */ const struct ddsi_sertopic_builtintopic *tp = (const struct ddsi_sertopic_builtintopic *)tpcmn; - /* keyhash must in host format (which the GUIDs always are internally) */ - struct entity_common *entity = entidx_lookup_guid_untyped (tp->c.gv->entity_index, (const ddsi_guid_t *) keyhash->value); - struct ddsi_serdata_builtintopic *d = serdata_builtin_new(tp, entity ? SDK_DATA : SDK_KEY); - memcpy (&d->key, keyhash->value, sizeof (d->key)); + union { ddsi_guid_t guid; ddsi_keyhash_t keyhash; } x; + x.keyhash = *keyhash; + x.guid = nn_ntoh_guid (x.guid); + struct entity_common *entity = entidx_lookup_guid_untyped (tp->c.gv->entity_index, &x.guid); + struct ddsi_serdata_builtintopic *d = serdata_builtin_new (tp, entity ? SDK_DATA : SDK_KEY); + d->key = x.guid; if (entity) { ddsrt_mutex_lock (&entity->qos_lock); From 23678edad535b0bb76a0e52127bd13a93248aeff Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 30 Apr 2020 09:30:14 +0200 Subject: [PATCH 209/238] Implement "from_sample" for built-in topics One cannot create writers for built-in topics, therefore one generally does not create samples for them. However, one can lookup an instance handle from a sample with just a key value in it, and so the function is needed. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_serdata_builtintopic.c | 37 +++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/core/ddsc/src/dds_serdata_builtintopic.c b/src/core/ddsc/src/dds_serdata_builtintopic.c index 9991e8b..cc07285 100644 --- a/src/core/ddsc/src/dds_serdata_builtintopic.c +++ b/src/core/ddsc/src/dds_serdata_builtintopic.c @@ -171,6 +171,41 @@ static struct ddsi_serdata *ddsi_serdata_builtin_from_keyhash (const struct ddsi return fix_serdata_builtin(d, tp->c.serdata_basehash); } +static struct ddsi_serdata *ddsi_serdata_builtin_from_sample (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, const void *sample) +{ + const struct ddsi_sertopic_builtintopic *tp = (const struct ddsi_sertopic_builtintopic *)tpcmn; + union { + dds_guid_t extguid; + ddsi_keyhash_t keyhash; + } x; + + /* no-one should be trying to convert user-provided data into a built-in topic sample, but converting + a key is something that can be necessary, e.g., dds_lookup_instance depends on it */ + if (kind != SDK_KEY) + return NULL; + + /* memset x (even though it is entirely superfluous) so we can leave out a default case from the + switch (ensuring at least some compilers will warn when more types are added) without getting + warnings from any compiler */ + memset (&x, 0, sizeof (x)); + switch (tp->type) + { + case DSBT_PARTICIPANT: { + const dds_builtintopic_participant_t *s = sample; + x.extguid = s->key; + break; + } + case DSBT_READER: + case DSBT_WRITER: { + const dds_builtintopic_endpoint_t *s = sample; + x.extguid = s->key; + break; + } + } + + return ddsi_serdata_from_keyhash (tpcmn, &x.keyhash); +} + static struct ddsi_serdata *serdata_builtin_to_topicless (const struct ddsi_serdata *serdata_common) { /* All built-in ones are currently topicless */ @@ -291,7 +326,7 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_builtintopic = { .from_ser = 0, .from_ser_iov = 0, .from_keyhash = ddsi_serdata_builtin_from_keyhash, - .from_sample = 0, + .from_sample = ddsi_serdata_builtin_from_sample, .to_ser = serdata_builtin_to_ser, .to_sample = serdata_builtin_to_sample, .to_ser_ref = serdata_builtin_to_ser_ref, From 06a0ba26c935421297cc5f77841011e6ef0f7e2b Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 29 Apr 2020 20:10:14 +0200 Subject: [PATCH 210/238] Rework listener tests A few failures to signal DATA_AVAILABLE (as well as some where it was signalled unnecessarily) were discovered while refactoring the RHC despite the tests all passing. Clearly the tests were inadequate. The enormous amount of boilerplate in the tests prompted a small rewrite to a programmable listener invocation tester that one simply feeds a noise-like one-liner in a string. This trades the boilerplate for somewhat inscrutable code. Signed-off-by: Erik Boasson --- src/core/ddsc/tests/listener.c | 2321 ++++++++++++++++---------------- 1 file changed, 1158 insertions(+), 1163 deletions(-) diff --git a/src/core/ddsc/tests/listener.c b/src/core/ddsc/tests/listener.c index 0ab0108..6738cf7 100644 --- a/src/core/ddsc/tests/listener.c +++ b/src/core/ddsc/tests/listener.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * Copyright(c) 2006 to 2020 ADLINK Technology Limited and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at @@ -9,1254 +9,1249 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ +#include + #include "dds/dds.h" - -#include "dds/ddsrt/cdtors.h" #include "dds/ddsrt/misc.h" -#include "dds/ddsrt/process.h" #include "dds/ddsrt/sync.h" -#include "dds/ddsrt/threads.h" - +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/environ.h" #include "test_common.h" -/**************************************************************************** - * TODO: Add DDS_INCONSISTENT_TOPIC_STATUS test - * TODO: Add DDS_OFFERED/REQUESTED_DEADLINE_MISSED_STATUS test - * TODO: Add DDS_LIVELINESS_LOST_STATUS test - * TODO: Check DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS intermittent fail (total_count != 1) - ****************************************************************************/ +static ddsrt_mutex_t g_mutex; +static ddsrt_cond_t g_cond; +static uint32_t cb_called; +static dds_entity_t cb_topic, cb_writer, cb_reader, cb_subscriber; + +#define DEFINE_STATUS_CALLBACK(name, NAME, kind) \ + static dds_##name##_status_t cb_##name##_status; \ + static void name##_cb (dds_entity_t kind, const dds_##name##_status_t status, void *arg) \ + { \ + (void) arg; \ + ddsrt_mutex_lock (&g_mutex); \ + cb_##kind = kind; \ + cb_##name##_status = status; \ + cb_called |= DDS_##NAME##_STATUS; \ + ddsrt_cond_broadcast (&g_cond); \ + ddsrt_mutex_unlock (&g_mutex); \ + } + +DEFINE_STATUS_CALLBACK (inconsistent_topic, INCONSISTENT_TOPIC, topic) +DEFINE_STATUS_CALLBACK (liveliness_changed, LIVELINESS_CHANGED, reader) +DEFINE_STATUS_CALLBACK (liveliness_lost, LIVELINESS_LOST, writer) +DEFINE_STATUS_CALLBACK (offered_deadline_missed, OFFERED_DEADLINE_MISSED, writer) +DEFINE_STATUS_CALLBACK (offered_incompatible_qos, OFFERED_INCOMPATIBLE_QOS, writer) +DEFINE_STATUS_CALLBACK (publication_matched, PUBLICATION_MATCHED, writer) +DEFINE_STATUS_CALLBACK (requested_deadline_missed, REQUESTED_DEADLINE_MISSED, reader) +DEFINE_STATUS_CALLBACK (requested_incompatible_qos, REQUESTED_INCOMPATIBLE_QOS, reader) +DEFINE_STATUS_CALLBACK (sample_lost, SAMPLE_LOST, reader) +DEFINE_STATUS_CALLBACK (sample_rejected, SAMPLE_REJECTED, reader) +DEFINE_STATUS_CALLBACK (subscription_matched, SUBSCRIPTION_MATCHED, reader) + +static void data_on_readers_cb (dds_entity_t subscriber, void *arg) +{ + (void) arg; + ddsrt_mutex_lock (&g_mutex); + cb_subscriber = subscriber; + cb_called |= DDS_DATA_ON_READERS_STATUS; + ddsrt_cond_broadcast (&g_cond); + ddsrt_mutex_unlock (&g_mutex); +} + +static void data_available_cb (dds_entity_t reader, void *arg) +{ + (void)arg; + ddsrt_mutex_lock (&g_mutex); + cb_reader = reader; + cb_called |= DDS_DATA_AVAILABLE_STATUS; + ddsrt_cond_broadcast (&g_cond); + ddsrt_mutex_unlock (&g_mutex); +} + +static void dummy_data_on_readers_cb (dds_entity_t subscriber, void *arg) +{ + (void)subscriber; + (void)arg; +} + +static void dummy_data_available_cb (dds_entity_t reader, void *arg) +{ + (void)reader; + (void)arg; +} + +static void dummy_subscription_matched_cb (dds_entity_t reader, const dds_subscription_matched_status_t status, void *arg) +{ + (void)reader; + (void)status; + (void)arg; +} + +static void dummy_liveliness_changed_cb (dds_entity_t reader, const dds_liveliness_changed_status_t status, void *arg) +{ + (void)reader; + (void)status; + (void)arg; +} + +static void dummy_cb (void) +{ + // Used as a listener function in checking merging of listeners, + // and for that purpose, casting it to whatever function type is + // required is ok. It is not supposed to ever be called. + abort (); +} + +#undef DEFINE_STATUS_CALLBACK + +/************************************************** + **** **** + **** create/delete/get/set/copy/merge/reset **** + **** **** + **************************************************/ + +static void set_all_const (dds_listener_t *l, void (*c) (void)) +{ + dds_lset_data_available (l, (dds_on_data_available_fn) c); + dds_lset_data_on_readers (l, (dds_on_data_on_readers_fn) c); + dds_lset_inconsistent_topic (l, (dds_on_inconsistent_topic_fn) c); + dds_lset_liveliness_changed (l, (dds_on_liveliness_changed_fn) c); + dds_lset_liveliness_lost (l, (dds_on_liveliness_lost_fn) c); + dds_lset_offered_deadline_missed (l, (dds_on_offered_deadline_missed_fn) c); + dds_lset_offered_incompatible_qos (l, (dds_on_offered_incompatible_qos_fn) c); + dds_lset_publication_matched (l, (dds_on_publication_matched_fn) c); + dds_lset_requested_deadline_missed (l, (dds_on_requested_deadline_missed_fn) c); + dds_lset_requested_incompatible_qos (l, (dds_on_requested_incompatible_qos_fn) c); + dds_lset_sample_lost (l, (dds_on_sample_lost_fn) c); + dds_lset_sample_rejected (l, (dds_on_sample_rejected_fn) c); + dds_lset_subscription_matched (l, (dds_on_subscription_matched_fn) c); +} + +static void set_all (dds_listener_t *l) +{ + dds_lset_data_available (l, data_available_cb); + dds_lset_data_on_readers (l, data_on_readers_cb); + dds_lset_inconsistent_topic (l, inconsistent_topic_cb); + dds_lset_liveliness_changed (l, liveliness_changed_cb); + dds_lset_liveliness_lost (l, liveliness_lost_cb); + dds_lset_offered_deadline_missed (l, offered_deadline_missed_cb); + dds_lset_offered_incompatible_qos (l, offered_incompatible_qos_cb); + dds_lset_publication_matched (l, publication_matched_cb); + dds_lset_requested_deadline_missed (l, requested_deadline_missed_cb); + dds_lset_requested_incompatible_qos (l, requested_incompatible_qos_cb); + dds_lset_sample_lost (l, sample_lost_cb); + dds_lset_sample_rejected (l, sample_rejected_cb); + dds_lset_subscription_matched (l, subscription_matched_cb); +} -/**************************************************************************** - * Convenience test macros. - ****************************************************************************/ #define ASSERT_CALLBACK_EQUAL(fntype, listener, expected) \ - do { \ - dds_on_##fntype##_fn cb; \ - dds_lget_##fntype(listener, &cb); \ - CU_ASSERT_EQUAL(cb, expected); \ - } while (0) + do { \ + dds_on_##fntype##_fn cb; \ + dds_lget_##fntype(listener, &cb); \ + CU_ASSERT_EQUAL(cb, expected); \ + } while (0) -#define STR(fntype) #fntype##_cb - -#define TEST_GET_SET(listener, fntype, cb) \ - do { \ - dds_on_##fntype##_fn dummy = NULL; \ - /* Initially expect DDS_LUNSET on a newly created listener */ \ - ASSERT_CALLBACK_EQUAL(fntype, listener, DDS_LUNSET); \ - /* Using listener or callback NULL, shouldn't crash and be noop */ \ - dds_lset_##fntype(NULL, NULL); \ - dds_lget_##fntype(NULL, NULL); \ - dds_lget_##fntype(listener, NULL); \ - dds_lget_##fntype(NULL, &dummy); \ - CU_ASSERT_EQUAL_FATAL(dummy, NULL); \ - /* Set to NULL, get to confirm it succeeds */ \ - dds_lset_##fntype(listener, NULL); \ - ASSERT_CALLBACK_EQUAL(fntype, listener, NULL); \ - /* Set to a proper cb method, get to confirm it succeeds */ \ - dds_lset_##fntype(listener, cb); \ - ASSERT_CALLBACK_EQUAL(fntype, listener, cb); \ - } while (0) - - - -/**************************************************************************** - * Test globals. - ****************************************************************************/ -static dds_entity_t g_participant = 0; -static dds_entity_t g_subscriber = 0; -static dds_entity_t g_publisher = 0; -static dds_entity_t g_topic = 0; -static dds_entity_t g_writer = 0; -static dds_entity_t g_reader = 0; - -static dds_listener_t *g_listener = NULL; -static dds_qos_t *g_qos = NULL; -static ddsrt_mutex_t g_mutex; -static ddsrt_cond_t g_cond; - - - -/**************************************************************************** - * Callback stuff. - ****************************************************************************/ -static uint32_t cb_called = 0; -static dds_entity_t cb_topic = 0; -static dds_entity_t cb_writer = 0; -static dds_entity_t cb_reader = 0; -static dds_entity_t cb_subscriber = 0; - -static dds_inconsistent_topic_status_t cb_inconsistent_topic_status; -static dds_liveliness_lost_status_t cb_liveliness_lost_status; -static dds_offered_deadline_missed_status_t cb_offered_deadline_missed_status; -static dds_offered_incompatible_qos_status_t cb_offered_incompatible_qos_status; -static dds_sample_lost_status_t cb_sample_lost_status; -static dds_sample_rejected_status_t cb_sample_rejected_status; -static dds_liveliness_changed_status_t cb_liveliness_changed_status; -static dds_requested_deadline_missed_status_t cb_requested_deadline_missed_status; -static dds_requested_incompatible_qos_status_t cb_requested_incompatible_qos_status; -static dds_publication_matched_status_t cb_publication_matched_status; -static dds_subscription_matched_status_t cb_subscription_matched_status; - - -static void -inconsistent_topic_cb( - dds_entity_t topic, - const dds_inconsistent_topic_status_t status, void* arg) +static void check_all_const (const dds_listener_t *l, void (*c) (void)) { - (void)arg; - ddsrt_mutex_lock(&g_mutex); - cb_topic = topic; - cb_inconsistent_topic_status = status; - cb_called |= DDS_INCONSISTENT_TOPIC_STATUS; - ddsrt_cond_broadcast(&g_cond); - ddsrt_mutex_unlock(&g_mutex); + ASSERT_CALLBACK_EQUAL (data_available, l, (dds_on_data_available_fn) c); + ASSERT_CALLBACK_EQUAL (data_on_readers, l, (dds_on_data_on_readers_fn) c); + ASSERT_CALLBACK_EQUAL (inconsistent_topic, l, (dds_on_inconsistent_topic_fn) c); + ASSERT_CALLBACK_EQUAL (liveliness_changed, l, (dds_on_liveliness_changed_fn) c); + ASSERT_CALLBACK_EQUAL (liveliness_lost, l, (dds_on_liveliness_lost_fn) c); + ASSERT_CALLBACK_EQUAL (offered_deadline_missed, l, (dds_on_offered_deadline_missed_fn) c); + ASSERT_CALLBACK_EQUAL (offered_incompatible_qos, l, (dds_on_offered_incompatible_qos_fn) c); + ASSERT_CALLBACK_EQUAL (publication_matched, l, (dds_on_publication_matched_fn) c); + ASSERT_CALLBACK_EQUAL (requested_deadline_missed, l, (dds_on_requested_deadline_missed_fn) c); + ASSERT_CALLBACK_EQUAL (requested_incompatible_qos, l, (dds_on_requested_incompatible_qos_fn) c); + ASSERT_CALLBACK_EQUAL (sample_lost, l, (dds_on_sample_lost_fn) c); + ASSERT_CALLBACK_EQUAL (sample_rejected, l, (dds_on_sample_rejected_fn) c); + ASSERT_CALLBACK_EQUAL (subscription_matched, l, (dds_on_subscription_matched_fn) c); } -static void -liveliness_lost_cb( - dds_entity_t writer, - const dds_liveliness_lost_status_t status, - void* arg) +static void check_all (const dds_listener_t *l) { - (void)arg; - ddsrt_mutex_lock(&g_mutex); - cb_writer = writer; - cb_liveliness_lost_status = status; - cb_called |= DDS_LIVELINESS_LOST_STATUS; - ddsrt_cond_broadcast(&g_cond); - ddsrt_mutex_unlock(&g_mutex); + ASSERT_CALLBACK_EQUAL (data_available, l, data_available_cb); + ASSERT_CALLBACK_EQUAL (data_on_readers, l, data_on_readers_cb); + ASSERT_CALLBACK_EQUAL (inconsistent_topic, l, inconsistent_topic_cb); + ASSERT_CALLBACK_EQUAL (liveliness_changed, l, liveliness_changed_cb); + ASSERT_CALLBACK_EQUAL (liveliness_lost, l, liveliness_lost_cb); + ASSERT_CALLBACK_EQUAL (offered_deadline_missed, l, offered_deadline_missed_cb); + ASSERT_CALLBACK_EQUAL (offered_incompatible_qos, l, offered_incompatible_qos_cb); + ASSERT_CALLBACK_EQUAL (publication_matched, l, publication_matched_cb); + ASSERT_CALLBACK_EQUAL (requested_deadline_missed, l, requested_deadline_missed_cb); + ASSERT_CALLBACK_EQUAL (requested_incompatible_qos, l, requested_incompatible_qos_cb); + ASSERT_CALLBACK_EQUAL (sample_lost, l, sample_lost_cb); + ASSERT_CALLBACK_EQUAL (sample_rejected, l, sample_rejected_cb); + ASSERT_CALLBACK_EQUAL (subscription_matched, l, subscription_matched_cb); } -static void -offered_deadline_missed_cb( - dds_entity_t writer, - const dds_offered_deadline_missed_status_t status, - void* arg) +CU_Test (ddsc_listener, create_and_delete) { - (void)arg; - ddsrt_mutex_lock(&g_mutex); - cb_writer = writer; - cb_offered_deadline_missed_status = status; - cb_called |= DDS_OFFERED_DEADLINE_MISSED_STATUS; - ddsrt_cond_broadcast(&g_cond); - ddsrt_mutex_unlock(&g_mutex); + dds_listener_t *listener = dds_create_listener (NULL); + CU_ASSERT_PTR_NOT_NULL_FATAL (listener); + check_all_const (listener, 0); + dds_delete_listener (listener); + + // check delete_listeners handles a null pointer gracefully + dds_delete_listener (NULL); } -static void -offered_incompatible_qos_cb( - dds_entity_t writer, - const dds_offered_incompatible_qos_status_t status, - void* arg) +CU_Test (ddsc_listener, reset) { - (void)arg; - ddsrt_mutex_lock(&g_mutex); - cb_writer = writer; - cb_offered_incompatible_qos_status = status; - cb_called |= DDS_OFFERED_INCOMPATIBLE_QOS_STATUS; - ddsrt_cond_broadcast(&g_cond); - ddsrt_mutex_unlock(&g_mutex); + dds_listener_t *listener = dds_create_listener (NULL); + CU_ASSERT_PTR_NOT_NULL_FATAL (listener); + + set_all (listener); + + // all callbacks should revert to default after reset + dds_reset_listener (listener); + check_all_const (listener, 0); + dds_delete_listener (listener); + + // check reset_listeners handles a null pointer gracefully + dds_reset_listener (NULL); } -static void -data_on_readers_cb( - dds_entity_t subscriber, - void* arg) +CU_Test (ddsc_listener, copy) { - (void)arg; - ddsrt_mutex_lock(&g_mutex); - cb_subscriber = subscriber; - cb_called |= DDS_DATA_ON_READERS_STATUS; - ddsrt_cond_broadcast(&g_cond); - ddsrt_mutex_unlock(&g_mutex); + dds_listener_t *listener1 = dds_create_listener (NULL); + CU_ASSERT_PTR_NOT_NULL_FATAL (listener1); + set_all (listener1); + + dds_listener_t *listener2 = dds_create_listener (NULL); + CU_ASSERT_PTR_NOT_NULL_FATAL (listener2); + dds_copy_listener (listener2, listener1); + check_all (listener2); + + // Calling copy with NULL should not crash and be noops + dds_copy_listener (listener2, NULL); + dds_copy_listener (NULL, listener1); + dds_copy_listener (NULL, NULL); + + dds_delete_listener (listener1); + dds_delete_listener (listener2); } -static void -sample_lost_cb( - dds_entity_t reader, - const dds_sample_lost_status_t status, - void* arg) +CU_Test (ddsc_listener, merge) { - (void)arg; - ddsrt_mutex_lock(&g_mutex); - cb_reader = reader; - cb_sample_lost_status = status; - cb_called |= DDS_SAMPLE_LOST_STATUS; - ddsrt_cond_broadcast(&g_cond); - ddsrt_mutex_unlock(&g_mutex); -} + dds_listener_t *listener1 = dds_create_listener (NULL); + CU_ASSERT_PTR_NOT_NULL_FATAL (listener1); + set_all (listener1); -static void -data_available_cb( - dds_entity_t reader, - void* arg) -{ - (void)arg; - ddsrt_mutex_lock(&g_mutex); - cb_reader = reader; - cb_called |= DDS_DATA_AVAILABLE_STATUS; - ddsrt_cond_broadcast(&g_cond); - ddsrt_mutex_unlock(&g_mutex); -} + // Merging listener1 into empty listener2 be like a copy + dds_listener_t *listener2 = dds_create_listener (NULL); + CU_ASSERT_PTR_NOT_NULL_FATAL (listener2); + dds_merge_listener (listener2, listener1); + check_all (listener2); -static void -sample_rejected_cb( - dds_entity_t reader, - const dds_sample_rejected_status_t status, - void* arg) -{ - (void)arg; - ddsrt_mutex_lock(&g_mutex); - cb_reader = reader; - cb_sample_rejected_status = status; - cb_called |= DDS_SAMPLE_REJECTED_STATUS; - ddsrt_cond_broadcast(&g_cond); - ddsrt_mutex_unlock(&g_mutex); -} + // Merging listener into a full listener2 should not overwrite anything + set_all_const (listener2, dummy_cb); + dds_merge_listener (listener2, listener1); + check_all_const (listener2, dummy_cb); -static void -liveliness_changed_cb( - dds_entity_t reader, - const dds_liveliness_changed_status_t status, - void* arg) -{ - (void)arg; - ddsrt_mutex_lock(&g_mutex); - cb_reader = reader; - cb_liveliness_changed_status = status; - cb_called |= DDS_LIVELINESS_CHANGED_STATUS; - ddsrt_cond_broadcast(&g_cond); - ddsrt_mutex_unlock(&g_mutex); -} + // Using NULLs shouldn't crash and be noops + dds_merge_listener (listener2, NULL); + dds_merge_listener (NULL, listener1); + dds_merge_listener (NULL, NULL); -static void -requested_deadline_missed_cb( - dds_entity_t reader, - const dds_requested_deadline_missed_status_t status, - void* arg) -{ - (void)arg; - ddsrt_mutex_lock(&g_mutex); - cb_reader = reader; - cb_requested_deadline_missed_status = status; - cb_called |= DDS_REQUESTED_DEADLINE_MISSED_STATUS; - ddsrt_cond_broadcast(&g_cond); - ddsrt_mutex_unlock(&g_mutex); -} - -static void -requested_incompatible_qos_cb( - dds_entity_t reader, - const dds_requested_incompatible_qos_status_t status, - void* arg) -{ - (void)arg; - ddsrt_mutex_lock(&g_mutex); - cb_reader = reader; - cb_requested_incompatible_qos_status = status; - cb_called |= DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS; - ddsrt_cond_broadcast(&g_cond); - ddsrt_mutex_unlock(&g_mutex); -} - -static void -publication_matched_cb( - dds_entity_t writer, - const dds_publication_matched_status_t status, - void* arg) -{ - (void)arg; - ddsrt_mutex_lock(&g_mutex); - cb_writer = writer; - cb_publication_matched_status = status; - cb_called |= DDS_PUBLICATION_MATCHED_STATUS; - ddsrt_cond_broadcast(&g_cond); - ddsrt_mutex_unlock(&g_mutex); -} - -static void -subscription_matched_cb( - dds_entity_t reader, - const dds_subscription_matched_status_t status, - void* arg) -{ - (void)arg; - ddsrt_mutex_lock(&g_mutex); - cb_reader = reader; - cb_subscription_matched_status = status; - cb_called |= DDS_SUBSCRIPTION_MATCHED_STATUS; - ddsrt_cond_broadcast(&g_cond); - ddsrt_mutex_unlock(&g_mutex); -} - -static void -callback_dummy(void) -{ -} - -static uint32_t -waitfor_cb(uint32_t expected) -{ - dds_time_t timeout = 5 * DDS_NSECS_IN_SEC; - bool signalled = true; - ddsrt_mutex_lock(&g_mutex); - while (((cb_called & expected) != expected) && (signalled)) { - signalled = ddsrt_cond_waitfor(&g_cond, &g_mutex, timeout); - } - ddsrt_mutex_unlock(&g_mutex); - return cb_called; -} - - - -/**************************************************************************** - * Test initializations and teardowns. - ****************************************************************************/ - -static void -init_triggering_base(void) -{ - char name[100]; - - ddsrt_init(); - - ddsrt_mutex_init(&g_mutex); - ddsrt_cond_init(&g_cond); - - g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - CU_ASSERT_FATAL(g_participant > 0); - - g_subscriber = dds_create_subscriber(g_participant, NULL, NULL); - CU_ASSERT_FATAL(g_subscriber > 0); - - g_publisher = dds_create_publisher(g_participant, NULL, NULL); - CU_ASSERT_FATAL(g_publisher > 0); - - g_topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, create_unique_topic_name("ddsc_listener_test", name, 100), NULL, NULL); - CU_ASSERT_FATAL(g_topic > 0); - - g_listener = dds_create_listener(NULL); - CU_ASSERT_PTR_NOT_NULL_FATAL(g_listener); - - g_qos = dds_create_qos(); - CU_ASSERT_PTR_NOT_NULL_FATAL(g_qos); - dds_qset_reliability(g_qos, DDS_RELIABILITY_RELIABLE, DDS_SECS(1)); - dds_qset_history(g_qos, DDS_HISTORY_KEEP_ALL, 0); - - cb_called = 0; -} - -static void -init_triggering_test(void) -{ - uint32_t triggered; - - /* Initialize base. */ - init_triggering_base(); - - /* Set QoS Policies that'll help us test various status callbacks. */ - dds_qset_destination_order(g_qos, DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP); - dds_qset_reliability(g_qos, DDS_RELIABILITY_BEST_EFFORT, DDS_MSECS(100)); - dds_qset_resource_limits(g_qos, 1, 1, 1); - - /* Use these to be sure reader and writer know each other. */ - dds_lset_publication_matched(g_listener, publication_matched_cb); - dds_lset_subscription_matched(g_listener, subscription_matched_cb); - dds_lset_liveliness_changed(g_listener, liveliness_changed_cb); - - /* Create reader and writer with proper listeners. */ - g_writer = dds_create_writer(g_publisher, g_topic, g_qos, g_listener); - CU_ASSERT(g_writer > 0); - g_reader = dds_create_reader(g_subscriber, g_topic, g_qos, g_listener); - CU_ASSERT(g_reader > 0); - - /* Sync. */ - triggered = waitfor_cb(DDS_PUBLICATION_MATCHED_STATUS | DDS_SUBSCRIPTION_MATCHED_STATUS | DDS_LIVELINESS_CHANGED_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_LIVELINESS_CHANGED_STATUS, DDS_LIVELINESS_CHANGED_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_PUBLICATION_MATCHED_STATUS, DDS_PUBLICATION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_SUBSCRIPTION_MATCHED_STATUS, DDS_SUBSCRIPTION_MATCHED_STATUS); -} - -static void -fini_triggering_base(void) -{ - dds_delete_qos(g_qos); - dds_delete_listener(g_listener); - dds_delete(g_participant); - ddsrt_cond_destroy(&g_cond); - ddsrt_mutex_destroy(&g_mutex); - ddsrt_fini(); -} - -static void -fini_triggering_test(void) -{ - dds_delete(g_reader); - if (g_writer) - dds_delete(g_writer); - fini_triggering_base(); -} - - -/**************************************************************************** - * API tests - ****************************************************************************/ -CU_Test(ddsc_listener, create_and_delete) -{ - /* Verify create doesn't return null */ - dds_listener_t *listener; - listener = dds_create_listener(NULL); - CU_ASSERT_PTR_NOT_NULL_FATAL(listener); - - /* Check default cb's are set */ - ASSERT_CALLBACK_EQUAL(inconsistent_topic, listener, DDS_LUNSET); - ASSERT_CALLBACK_EQUAL(liveliness_lost, listener, DDS_LUNSET); - ASSERT_CALLBACK_EQUAL(offered_deadline_missed, listener, DDS_LUNSET); - ASSERT_CALLBACK_EQUAL(offered_incompatible_qos, listener, DDS_LUNSET); - ASSERT_CALLBACK_EQUAL(data_on_readers, listener, DDS_LUNSET); - ASSERT_CALLBACK_EQUAL(sample_lost, listener, DDS_LUNSET); - ASSERT_CALLBACK_EQUAL(sample_rejected, listener, DDS_LUNSET); - ASSERT_CALLBACK_EQUAL(liveliness_changed, listener, DDS_LUNSET); - ASSERT_CALLBACK_EQUAL(requested_deadline_missed, listener, DDS_LUNSET); - ASSERT_CALLBACK_EQUAL(requested_incompatible_qos, listener, DDS_LUNSET); - ASSERT_CALLBACK_EQUAL(publication_matched, listener, DDS_LUNSET); - ASSERT_CALLBACK_EQUAL(subscription_matched, listener, DDS_LUNSET); - ASSERT_CALLBACK_EQUAL(data_available, listener, DDS_LUNSET); - - dds_delete_listener(listener); - DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ - dds_delete_listener(NULL); - DDSRT_WARNING_MSVC_ON(6387); -} - -CU_Test(ddsc_listener, reset) -{ - dds_listener_t *listener; - listener = dds_create_listener(NULL); - CU_ASSERT_PTR_NOT_NULL_FATAL(listener); - - /* Set a listener cb to a non-default value */ - dds_lset_data_available(listener, NULL); - ASSERT_CALLBACK_EQUAL(data_available, listener, NULL); - - /* Listener cb should revert to default after reset */ - dds_reset_listener(listener); - ASSERT_CALLBACK_EQUAL(data_available, listener, DDS_LUNSET); - - /* Resetting a NULL listener should not crash */ - dds_reset_listener(NULL); - - dds_delete_listener(listener); -} - -CU_Test(ddsc_listener, copy) -{ - dds_listener_t *listener1 = NULL, *listener2 = NULL; - listener1 = dds_create_listener(NULL); - listener2 = dds_create_listener(NULL); - CU_ASSERT_PTR_NOT_NULL_FATAL(listener1); - CU_ASSERT_PTR_NOT_NULL_FATAL(listener2); - - /* Set some listener1 callbacks to non-default values */ - dds_lset_data_available(listener1, NULL); - dds_lset_sample_lost(listener1, sample_lost_cb); - ASSERT_CALLBACK_EQUAL(data_available, listener1, NULL); - ASSERT_CALLBACK_EQUAL(sample_lost, listener1, sample_lost_cb); - ASSERT_CALLBACK_EQUAL(data_available, listener2, DDS_LUNSET); - ASSERT_CALLBACK_EQUAL(sample_lost, listener2, DDS_LUNSET); - - /* Cb's should be copied to listener2 */ - dds_copy_listener(listener2, listener1); - ASSERT_CALLBACK_EQUAL(data_available, listener1, NULL); - ASSERT_CALLBACK_EQUAL(data_available, listener2, NULL); - ASSERT_CALLBACK_EQUAL(sample_lost, listener1, sample_lost_cb); - ASSERT_CALLBACK_EQUAL(sample_lost, listener2, sample_lost_cb); - - /* Calling copy with NULL should not crash and be noops. */ - DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ - dds_copy_listener(listener2, NULL); - dds_copy_listener(NULL, listener1); - dds_copy_listener(NULL, NULL); - DDSRT_WARNING_MSVC_ON(6387); - - dds_delete_listener(listener1); - dds_delete_listener(listener2); -} - -CU_Test(ddsc_listener, merge) -{ - dds_listener_t *listener1 = NULL, *listener2 = NULL; - listener1 = dds_create_listener(NULL); - listener2 = dds_create_listener(NULL); - CU_ASSERT_PTR_NOT_NULL_FATAL(listener1); - CU_ASSERT_PTR_NOT_NULL_FATAL(listener2); - - /* Set all listener1 callbacks to non-default values */ - dds_lset_inconsistent_topic (listener1, inconsistent_topic_cb); - dds_lset_liveliness_lost (listener1, liveliness_lost_cb); - dds_lset_offered_deadline_missed (listener1, offered_deadline_missed_cb); - dds_lset_offered_incompatible_qos (listener1, offered_incompatible_qos_cb); - dds_lset_data_on_readers (listener1, data_on_readers_cb); - dds_lset_sample_lost (listener1, sample_lost_cb); - dds_lset_data_available (listener1, data_available_cb); - dds_lset_sample_rejected (listener1, sample_rejected_cb); - dds_lset_liveliness_changed (listener1, liveliness_changed_cb); - dds_lset_requested_deadline_missed (listener1, requested_deadline_missed_cb); - dds_lset_requested_incompatible_qos (listener1, requested_incompatible_qos_cb); - dds_lset_publication_matched (listener1, publication_matched_cb); - dds_lset_subscription_matched (listener1, subscription_matched_cb); - - /* Merging listener1 into empty listener2 should act a bit like a copy. */ - dds_merge_listener(listener2, listener1); - ASSERT_CALLBACK_EQUAL(inconsistent_topic, listener2, inconsistent_topic_cb); - ASSERT_CALLBACK_EQUAL(liveliness_lost, listener2, liveliness_lost_cb); - ASSERT_CALLBACK_EQUAL(offered_deadline_missed, listener2, offered_deadline_missed_cb); - ASSERT_CALLBACK_EQUAL(offered_incompatible_qos, listener2, offered_incompatible_qos_cb); - ASSERT_CALLBACK_EQUAL(data_on_readers, listener2, data_on_readers_cb); - ASSERT_CALLBACK_EQUAL(sample_lost, listener2, sample_lost_cb); - ASSERT_CALLBACK_EQUAL(data_available, listener2, data_available_cb); - ASSERT_CALLBACK_EQUAL(sample_rejected, listener2, sample_rejected_cb); - ASSERT_CALLBACK_EQUAL(liveliness_changed, listener2, liveliness_changed_cb); - ASSERT_CALLBACK_EQUAL(requested_deadline_missed, listener2, requested_deadline_missed_cb); - ASSERT_CALLBACK_EQUAL(requested_incompatible_qos, listener2, requested_incompatible_qos_cb); - ASSERT_CALLBACK_EQUAL(publication_matched, listener2, publication_matched_cb); - ASSERT_CALLBACK_EQUAL(subscription_matched, listener2, subscription_matched_cb); - - /* Merging listener into a full listener2 should act as a noop. */ - dds_lset_inconsistent_topic (listener2, (dds_on_inconsistent_topic_fn)callback_dummy); - dds_lset_liveliness_lost (listener2, (dds_on_liveliness_lost_fn)callback_dummy); - dds_lset_offered_deadline_missed (listener2, (dds_on_offered_deadline_missed_fn)callback_dummy); - dds_lset_offered_incompatible_qos (listener2, (dds_on_offered_incompatible_qos_fn)callback_dummy); - dds_lset_data_on_readers (listener2, (dds_on_data_on_readers_fn)callback_dummy); - dds_lset_sample_lost (listener2, (dds_on_sample_lost_fn)callback_dummy); - dds_lset_data_available (listener2, (dds_on_data_available_fn)callback_dummy); - dds_lset_sample_rejected (listener2, (dds_on_sample_rejected_fn)callback_dummy); - dds_lset_liveliness_changed (listener2, (dds_on_liveliness_changed_fn)callback_dummy); - dds_lset_requested_deadline_missed (listener2, (dds_on_requested_deadline_missed_fn)callback_dummy); - dds_lset_requested_incompatible_qos (listener2, (dds_on_requested_incompatible_qos_fn)callback_dummy); - dds_lset_publication_matched (listener2, (dds_on_publication_matched_fn)callback_dummy); - dds_lset_subscription_matched (listener2, (dds_on_subscription_matched_fn)callback_dummy); - dds_merge_listener(listener2, listener1); - ASSERT_CALLBACK_EQUAL(inconsistent_topic, listener2, (dds_on_inconsistent_topic_fn)callback_dummy); - ASSERT_CALLBACK_EQUAL(liveliness_lost, listener2, (dds_on_liveliness_lost_fn)callback_dummy); - ASSERT_CALLBACK_EQUAL(offered_deadline_missed, listener2, (dds_on_offered_deadline_missed_fn)callback_dummy); - ASSERT_CALLBACK_EQUAL(offered_incompatible_qos, listener2, (dds_on_offered_incompatible_qos_fn)callback_dummy); - ASSERT_CALLBACK_EQUAL(data_on_readers, listener2, (dds_on_data_on_readers_fn)callback_dummy); - ASSERT_CALLBACK_EQUAL(sample_lost, listener2, (dds_on_sample_lost_fn)callback_dummy); - ASSERT_CALLBACK_EQUAL(data_available, listener2, (dds_on_data_available_fn)callback_dummy); - ASSERT_CALLBACK_EQUAL(sample_rejected, listener2, (dds_on_sample_rejected_fn)callback_dummy); - ASSERT_CALLBACK_EQUAL(liveliness_changed, listener2, (dds_on_liveliness_changed_fn)callback_dummy); - ASSERT_CALLBACK_EQUAL(requested_deadline_missed, listener2, (dds_on_requested_deadline_missed_fn)callback_dummy); - ASSERT_CALLBACK_EQUAL(requested_incompatible_qos, listener2, (dds_on_requested_incompatible_qos_fn)callback_dummy); - ASSERT_CALLBACK_EQUAL(publication_matched, listener2, (dds_on_publication_matched_fn)callback_dummy); - ASSERT_CALLBACK_EQUAL(subscription_matched, listener2, (dds_on_subscription_matched_fn)callback_dummy); - - /* Using NULLs shouldn't crash and be noops. */ - dds_merge_listener(listener2, NULL); - dds_merge_listener(NULL, listener1); - dds_merge_listener(NULL, NULL); - - dds_delete_listener(listener1); - dds_delete_listener(listener2); + dds_delete_listener (listener1); + dds_delete_listener (listener2); } CU_Test(ddsc_listener, getters_setters) { - /* test all individual cb get/set methods */ - dds_listener_t *listener = dds_create_listener(NULL); - CU_ASSERT_PTR_NOT_NULL_FATAL(listener); + // test all individual cb get/set methods + dds_listener_t *listener = dds_create_listener (NULL); + CU_ASSERT_PTR_NOT_NULL_FATAL (listener); - DDSRT_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */ \ - TEST_GET_SET(listener, inconsistent_topic, inconsistent_topic_cb); - TEST_GET_SET(listener, liveliness_lost, liveliness_lost_cb); - TEST_GET_SET(listener, offered_deadline_missed, offered_deadline_missed_cb); - TEST_GET_SET(listener, offered_incompatible_qos, offered_incompatible_qos_cb); - TEST_GET_SET(listener, data_on_readers, data_on_readers_cb); - TEST_GET_SET(listener, sample_lost, sample_lost_cb); - TEST_GET_SET(listener, sample_rejected, sample_rejected_cb); - TEST_GET_SET(listener, liveliness_changed, liveliness_changed_cb); - TEST_GET_SET(listener, requested_deadline_missed, requested_deadline_missed_cb); - TEST_GET_SET(listener, requested_incompatible_qos, requested_incompatible_qos_cb); - TEST_GET_SET(listener, publication_matched, publication_matched_cb); - TEST_GET_SET(listener, subscription_matched, subscription_matched_cb); - TEST_GET_SET(listener, data_available, data_available_cb); - DDSRT_WARNING_MSVC_ON(6387); +#define TEST_GET_SET(listener, fntype, cb) \ + do { \ + dds_on_##fntype##_fn dummy = NULL; \ + /* Initially expect DDS_LUNSET on a newly created listener */ \ + ASSERT_CALLBACK_EQUAL (fntype, listener, 0); \ + /* Using listener or callback NULL, shouldn't crash and be noop */ \ + dds_lset_##fntype (NULL, NULL); \ + dds_lget_##fntype (NULL, NULL); \ + dds_lget_##fntype (listener, NULL); \ + dds_lget_##fntype (NULL, &dummy); \ + CU_ASSERT_EQUAL_FATAL (dummy, NULL); \ + /* Set to NULL, get to confirm it succeeds */ \ + dds_lset_##fntype (listener, NULL); \ + ASSERT_CALLBACK_EQUAL (fntype, listener, NULL); \ + /* Set to a proper cb method, get to confirm it succeeds */ \ + dds_lset_##fntype (listener, cb); \ + ASSERT_CALLBACK_EQUAL (fntype, listener, cb); \ + } while (0) + TEST_GET_SET (listener, data_available, data_available_cb); + TEST_GET_SET (listener, data_on_readers, data_on_readers_cb); + TEST_GET_SET (listener, inconsistent_topic, inconsistent_topic_cb); + TEST_GET_SET (listener, liveliness_changed, liveliness_changed_cb); + TEST_GET_SET (listener, liveliness_lost, liveliness_lost_cb); + TEST_GET_SET (listener, offered_deadline_missed, offered_deadline_missed_cb); + TEST_GET_SET (listener, offered_incompatible_qos, offered_incompatible_qos_cb); + TEST_GET_SET (listener, publication_matched, publication_matched_cb); + TEST_GET_SET (listener, requested_deadline_missed, requested_deadline_missed_cb); + TEST_GET_SET (listener, requested_incompatible_qos, requested_incompatible_qos_cb); + TEST_GET_SET (listener, sample_lost, sample_lost_cb); + TEST_GET_SET (listener, sample_rejected, sample_rejected_cb); + TEST_GET_SET (listener, subscription_matched, subscription_matched_cb); +#undef TEST_GET_SET - dds_delete_listener(listener); + dds_delete_listener (listener); } +#undef ASSERT_CALLBACK_EQUAL +/************************************************** + **** **** + **** programmable listener checker **** + **** **** + **************************************************/ -/**************************************************************************** - * Triggering tests - ****************************************************************************/ -CU_Test(ddsc_listener, propagation, .init=init_triggering_base, .fini=fini_triggering_base) +// These had better match the corresponding type definitions! +// n uint32_t ...count +// c int32_t ...count_change +// I instance handle of a data instance +// P uint32_t QoS policy ID +// E instance handle of an entity +// R sample_rejected_status_kind +static const struct { + size_t size; // size of status struct + const char *desc; // description of status struct + uint32_t mask; // status mask, bit in "cb_called" + const dds_entity_t *cb_entity; // which cb_... entity to look at + const void *cb_status; // cb_..._status to look at +} lldesc[] = { + { 0, NULL, DDS_DATA_AVAILABLE_STATUS, &cb_reader, NULL }, // data available + { 0, NULL, DDS_DATA_ON_READERS_STATUS, &cb_subscriber, NULL }, // data on readers + { sizeof (dds_inconsistent_topic_status_t), "nc", DDS_INCONSISTENT_TOPIC_STATUS, &cb_topic, &cb_inconsistent_topic_status }, + { sizeof (dds_liveliness_changed_status_t), "nnccE", DDS_LIVELINESS_CHANGED_STATUS, &cb_reader, &cb_liveliness_changed_status }, + { sizeof (dds_liveliness_lost_status_t), "nc", DDS_LIVELINESS_LOST_STATUS, &cb_writer, &cb_liveliness_lost_status }, + { sizeof (dds_offered_deadline_missed_status_t), "ncI", DDS_OFFERED_DEADLINE_MISSED_STATUS, &cb_writer, &cb_offered_deadline_missed_status }, + { sizeof (dds_offered_incompatible_qos_status_t), "ncP", DDS_OFFERED_INCOMPATIBLE_QOS_STATUS, &cb_writer, &cb_offered_incompatible_qos_status }, + { sizeof (dds_publication_matched_status_t), "ncncE", DDS_PUBLICATION_MATCHED_STATUS, &cb_writer, &cb_publication_matched_status }, + { sizeof (dds_requested_deadline_missed_status_t), "ncI", DDS_REQUESTED_DEADLINE_MISSED_STATUS, &cb_reader, &cb_requested_deadline_missed_status }, + { sizeof (dds_requested_incompatible_qos_status_t), "ncP", DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS, &cb_reader, &cb_requested_incompatible_qos_status }, + { sizeof (dds_sample_lost_status_t), "nc", DDS_SAMPLE_LOST_STATUS, &cb_reader, &cb_sample_lost_status }, + { sizeof (dds_sample_rejected_status_t), "ncRI", DDS_SAMPLE_REJECTED_STATUS, &cb_reader, &cb_sample_rejected_status }, + { sizeof (dds_subscription_matched_status_t), "ncncE", DDS_SUBSCRIPTION_MATCHED_STATUS, &cb_reader, &cb_subscription_matched_status } +}; + +static const void *advance (const void *status, size_t *off, char code) { - dds_listener_t *listener_par = NULL; - dds_listener_t *listener_pub = NULL; - dds_listener_t *listener_sub = NULL; - uint32_t triggered; +#define alignof(type_) offsetof (struct { char c; type_ d; }, d) + size_t align = 1, size = 1; + switch (code) + { + case 'n': case 'c': case 'P': + align = alignof (uint32_t); size = sizeof (uint32_t); + break; + case 'E': case 'I': + align = alignof (dds_instance_handle_t); size = sizeof (dds_instance_handle_t); + break; + case 'R': + align = alignof (dds_sample_rejected_status_kind); size = sizeof (dds_sample_rejected_status_kind); + break; + default: + abort (); + } +#undef alignof + *off = (*off + align - 1) & ~(align - 1); + const void *p = (const char *) status + *off; + *off += size; + return p; +} + +static void get_status (int ll, dds_entity_t ent, void *status) +{ + dds_return_t ret; + switch (ll) + { + case 2: ret = dds_get_inconsistent_topic_status (ent, status); break; + case 3: ret = dds_get_liveliness_changed_status (ent, status); break; + case 4: ret = dds_get_liveliness_lost_status (ent, status); break; + case 5: ret = dds_get_offered_deadline_missed_status (ent, status); break; + case 6: ret = dds_get_offered_incompatible_qos_status (ent, status); break; + case 7: ret = dds_get_publication_matched_status (ent, status); break; + case 8: ret = dds_get_requested_deadline_missed_status (ent, status); break; + case 9: ret = dds_get_requested_incompatible_qos_status (ent, status); break; + case 10: ret = dds_get_sample_lost_status (ent, status); break; + case 11: ret = dds_get_sample_rejected_status (ent, status); break; + case 12: ret = dds_get_subscription_matched_status (ent, status); break; + default: abort (); + } + CU_ASSERT_FATAL (ret == 0); +} + +static void assert_status_change_fields_are_0 (int ll, dds_entity_t ent) +{ + if (lldesc[ll].desc) + { + const char *d = lldesc[ll].desc; + void *status = malloc (lldesc[ll].size); + get_status (ll, ent, status); + size_t off = 0; + while (*d) + { + const uint32_t *p = advance (status, &off, *d); + if (*d == 'c') + CU_ASSERT_FATAL (*p == 0); + d++; + } + assert (off <= lldesc[ll].size); + free (status); + } +} + +static int getentity (const char *tok, bool *isbang, bool *ishash) +{ + static const char *known = "PRWrstwxy"; + const char *p; + if (isbang) + *isbang = false; + if (ishash) + *ishash = false; + if ((p = strchr (known, *tok)) == NULL) + return -1; + int ent = (int) (p - known); + if (*++tok == 0) + return ent; + if (*tok == '\'') + { + ent += (int) strlen (known); + tok++; + } + while (*tok == '!' || *tok == '#') + { + if (strchr (known + 3, *p) == NULL) + return -1; // only readers, writers + if (*tok == '!' && isbang) + *isbang = true; + else if (*tok == '#' && ishash) + *ishash = true; + tok++; + } + return (*tok == 0) ? ent : -1; +} + +static int getlistener (const char *tok, bool *isbang) +{ + // note: sort order is on full name (so sample rejected precedes subscription matched) + static const char *ls[] = { + "da", "dor", "it", "lc", "ll", "odm", "oiq", "pm", "rdm", "riq", "sl", "sr", "sm" + }; + if (isbang) + *isbang = false; + for (size_t i = 0; i < sizeof (ls) / sizeof (*ls); i++) + { + size_t n = strlen (ls[i]); + if (strncmp (tok, ls[i], n) == 0 && (tok[n] == 0 || tok[n+1] == ',')) + { + if (isbang) + *isbang = (tok[n] == '!'); + return (int) i; + } + } + return -1; +} + +struct ents { + dds_entity_t es[2 * 9]; + dds_entity_t tps[2]; + dds_entity_t doms[2]; + dds_instance_handle_t esi[2 * 9]; + // built-in topic readers for cross-referencing instance handles + dds_entity_t pubrd[2]; + dds_entity_t subrd[2]; +}; + +static void make_participant (struct ents *es, const char *topicname, int ent, const dds_qos_t *qos, dds_listener_t *list) +{ + const dds_domainid_t domid = (ent < 9) ? 0 : 1; + char *conf = ddsrt_expand_envvars ("${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}0", domid); + printf ("create domain %"PRIu32, domid); + fflush (stdout); + es->doms[domid] = dds_create_domain (domid, conf); + CU_ASSERT_FATAL (es->doms[domid] > 0); + ddsrt_free (conf); + printf (" create participant P%s", (ent < 9) ? "" : "'"); + fflush (stdout); + es->es[ent] = dds_create_participant (domid, NULL, list); + CU_ASSERT_FATAL (es->es[ent] > 0); + es->tps[domid] = dds_create_topic (es->es[ent], &Space_Type1_desc, topicname, qos, NULL); + CU_ASSERT_FATAL (es->tps[domid] > 0); + + // Create the built-in topic readers with a dummy listener to avoid any event (data available comes to mind) + // from propagating to the normal data available listener, in case it has been set on the participant. + // + // - dummy_cb aborts when it is invoked, but all reader-related listeners that can possibly trigger are set + // separately (incompatible qos, deadline missed, sample lost and sample rejected are all impossible by + // construction) + // - regarding data_on_readers: Cyclone handles listeners installed on an ancestor by *inheriting* them, + // rather than by walking up ancestor chain. Setting data_on_readers on the reader therefore overrides the + // listener set on the subscriber. It is a nice feature! + dds_listener_t *dummylist = dds_create_listener (NULL); + set_all_const (dummylist, dummy_cb); + dds_lset_data_available (dummylist, dummy_data_available_cb); + dds_lset_data_on_readers (dummylist, dummy_data_on_readers_cb); + dds_lset_subscription_matched (dummylist, dummy_subscription_matched_cb); + dds_lset_liveliness_changed (dummylist, dummy_liveliness_changed_cb); + es->pubrd[domid] = dds_create_reader (es->es[ent], DDS_BUILTIN_TOPIC_DCPSPUBLICATION, NULL, dummylist); + CU_ASSERT_FATAL (es->pubrd[domid] > 0); + es->subrd[domid] = dds_create_reader (es->es[ent], DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, dummylist); + CU_ASSERT_FATAL (es->subrd[domid] > 0); + dds_delete_listener (dummylist); + printf ("pubrd %"PRId32" subrd %"PRId32" sub %"PRId32"\n", es->pubrd[domid], es->subrd[domid], dds_get_parent (es->pubrd[domid])); +} + +static void make_entity1 (struct ents *es, const char *topicname, int ent, bool isbang, bool ishash, const dds_qos_t *qos, dds_qos_t *rwqos, dds_listener_t *list) +{ + dds_return_t ret; + switch (ent) + { + case 0: case 9: + make_participant (es, topicname, ent, qos, list); + break; + case 1: case 10: + if (es->es[ent-1] == 0) + { + printf ("["); + make_entity1 (es, topicname, ent-1, false, false, qos, rwqos, NULL); + printf ("] "); + } + printf ("create subscriber R%s", (ent < 9) ? "" : "'"); + fflush (stdout); + es->es[ent] = dds_create_subscriber (es->es[ent-1], NULL, list); + break; + case 2: case 11: + if (es->es[ent-2] == 0) + { + printf ("["); + make_entity1 (es, topicname, ent-2, false, false, qos, rwqos, NULL); + printf ("] "); + } + printf ("create publisher W%s", (ent < 9) ? "" : "'"); + fflush (stdout); + es->es[ent] = dds_create_publisher (es->es[ent-2], NULL, list); + break; + case 3: case 4: case 5: case 12: case 13: case 14: + if (es->es[ent < 9 ? 1 : 10] == 0) + { + printf ("["); + make_entity1 (es, topicname, ent < 9 ? 1 : 10, false, false, qos, rwqos, NULL); + printf ("] "); + } + printf ("create %s reader %c%s", isbang ? "best-effort" : "reliable", 'r' + (ent < 9 ? ent-3 : ent-12), (ent < 9) ? "" : "'"); + fflush (stdout); + dds_reset_qos (rwqos); + if (isbang) + dds_qset_reliability (rwqos, DDS_RELIABILITY_BEST_EFFORT, DDS_MSECS (100)); + if (ishash) + dds_qset_resource_limits (rwqos, 1, DDS_LENGTH_UNLIMITED, DDS_LENGTH_UNLIMITED); + es->es[ent] = dds_create_reader (es->es[ent < 9 ? 1 : 10], es->tps[ent < 9 ? 0 : 1], rwqos, list); + break; + case 6: case 7: case 8: case 15: case 16: case 17: + if (es->es[ent < 9 ? 2 : 11] == 0) + { + printf ("["); + make_entity1 (es, topicname, ent < 9 ? 2 : 11, false, false, qos, rwqos, NULL); + printf ("] "); + } + printf ("create %s writer %c%s", isbang ? "best-effort" : "reliable", 'w' + (ent < 9 ? ent-6 : ent-15), (ent < 9) ? "" : "'"); + fflush (stdout); + dds_reset_qos (rwqos); + if (isbang) + dds_qset_reliability (rwqos, DDS_RELIABILITY_BEST_EFFORT, DDS_MSECS (100)); + if (ishash) + dds_qset_resource_limits (rwqos, 1, DDS_LENGTH_UNLIMITED, DDS_LENGTH_UNLIMITED); + es->es[ent] = dds_create_writer (es->es[ent < 9 ? 2 : 11], es->tps[ent < 9 ? 0 : 1], rwqos, list); + break; + default: + abort (); + } + printf (" = %"PRId32, es->es[ent]); + fflush (stdout); + CU_ASSERT_FATAL (es->es[ent] > 0); + ret = dds_get_instance_handle (es->es[ent], &es->esi[ent]); + //printf (" %"PRIx64, es->esi[ent]); + //fflush (stdout); + CU_ASSERT_FATAL (ret == 0); +} + +static void make_entity (struct ents *es, const char *topicname, int ent, bool isbang, bool ishash, const dds_qos_t *qos, dds_qos_t *rwqos, dds_listener_t *list) +{ + make_entity1 (es, topicname, ent, isbang, ishash, qos, rwqos, list); + printf ("\n"); +} + +static char *strsep_noempty (char **cursor, const char *sep) +{ + char *tok; + while ((tok = ddsrt_strsep (cursor, sep)) != NULL && *tok == 0) { } + return tok; +} + +static dds_instance_handle_t lookup_insthandle (const struct ents *es, int ent, int ent1) +{ + // if both are in the same domain, it's easy + if (ent / 9 == ent1 / 9) + return es->esi[ent1]; + else + { + // if they aren't ... find GUID from instance handle in the one domain, + // then find instance handle for GUID in the other + dds_entity_t rd1 = 0, rd2 = 0; + switch (ent1) + { + case 3: case 4: case 5: rd1 = es->subrd[0]; rd2 = es->subrd[1]; break; + case 12: case 13: case 14: rd1 = es->subrd[1]; rd2 = es->subrd[0]; break; + case 6: case 7: case 8: rd1 = es->pubrd[0]; rd2 = es->pubrd[1]; break; + case 15: case 16: case 17: rd1 = es->pubrd[1]; rd2 = es->pubrd[0]; break; + default: abort (); + } + dds_return_t ret; - RoundTripModule_DataType sample; - memset (&sample, 0, sizeof (sample)); - - /* Let participant be interested in data. */ - listener_par = dds_create_listener(NULL); - CU_ASSERT_PTR_NOT_NULL_FATAL(listener_par); - dds_lset_data_on_readers(listener_par, data_on_readers_cb); - ret = dds_set_listener(g_participant, listener_par); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - dds_delete_listener(listener_par); - - /* Let publisher be interested in publication matched. */ - listener_pub = dds_create_listener(NULL); - CU_ASSERT_PTR_NOT_NULL_FATAL(listener_pub); - dds_lset_publication_matched(listener_pub, publication_matched_cb); - ret = dds_set_listener(g_publisher, listener_pub); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - dds_delete_listener(listener_pub); - - /* Let subscriber be interested in subscription matched. */ - listener_sub = dds_create_listener(NULL); - CU_ASSERT_PTR_NOT_NULL_FATAL(listener_pub); - dds_lset_subscription_matched(listener_sub, subscription_matched_cb); - ret = dds_set_listener(g_subscriber, listener_sub); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - dds_delete_listener(listener_sub); - - /* Create reader and writer without listeners. */ - g_reader = dds_create_reader(g_subscriber, g_topic, g_qos, NULL); - CU_ASSERT_FATAL(g_reader > 0); - g_writer = dds_create_writer(g_publisher, g_topic, g_qos, NULL); - CU_ASSERT_FATAL(g_writer > 0); - - /* Publication and Subscription should be matched. */ - triggered = waitfor_cb(DDS_PUBLICATION_MATCHED_STATUS | DDS_SUBSCRIPTION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_SUBSCRIPTION_MATCHED_STATUS, DDS_SUBSCRIPTION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_PUBLICATION_MATCHED_STATUS, DDS_PUBLICATION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_writer, g_writer); - CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); - - /* Write sample. */ - ret = dds_write(g_writer, &sample); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - - /* Data on readers should be triggered with the right status. */ - triggered = waitfor_cb(DDS_DATA_ON_READERS_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_ON_READERS_STATUS, DDS_DATA_ON_READERS_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_subscriber, g_subscriber); - CU_ASSERT_NOT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); - - dds_delete(g_writer); - dds_delete(g_reader); + dds_builtintopic_endpoint_t keysample; + //printf ("(in %"PRId32" %"PRIx64" -> ", rd1, es->esi[ent1]); + //fflush (stdout); + ret = dds_instance_get_key (rd1, es->esi[ent1], &keysample); + CU_ASSERT_FATAL (ret == 0); + // In principle, only key fields are set in sample returned by get_key; + // in the case of a built-in topic that is extended to the participant + // key. The qos and topic/type names should not be set, and there is no + // (therefore) memory allocated for the sample. + CU_ASSERT_FATAL (keysample.qos == NULL); + CU_ASSERT_FATAL (keysample.topic_name == NULL); + CU_ASSERT_FATAL (keysample.type_name == NULL); + //for (size_t j = 0; j < sizeof (keysample.key.v); j++) + // printf ("%s%02x", (j > 0 && j % 4 == 0) ? ":" : "", keysample.key.v[j]); + const dds_instance_handle_t ih = dds_lookup_instance (rd2, &keysample); + CU_ASSERT_FATAL (ih != 0); + //printf (" -> %"PRIx64")", ih); + //fflush (stdout); + return ih; + } } - -CU_Test(ddsc_listener, matched, .init=init_triggering_base, .fini=fini_triggering_base) +static void checkstatus (int ll, const struct ents *es, int ent, const char *args, const void *status) { - uint32_t triggered; - - /* We will basically do the same as the 'normal' init_triggering_test() and - * fini_triggering_test() calls. It's just that we do it in a different - * order and use the participant iso subscriber and publisher. */ - - /* We are interested in matched notifications. */ - dds_lset_publication_matched(g_listener, publication_matched_cb); - dds_lset_subscription_matched(g_listener, subscription_matched_cb); - - /* Create reader and writer with proper listeners. - * The creation order is deliberately different from publication_matched and subscription_matched. */ - g_reader = dds_create_reader(g_participant, g_topic, g_qos, g_listener); - CU_ASSERT_FATAL(g_reader > 0); - g_writer = dds_create_writer(g_participant, g_topic, g_qos, g_listener); - CU_ASSERT_FATAL(g_writer > 0); - - /* Both matched should be triggered on the right entities. */ - triggered = waitfor_cb(DDS_PUBLICATION_MATCHED_STATUS | DDS_SUBSCRIPTION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_SUBSCRIPTION_MATCHED_STATUS, DDS_SUBSCRIPTION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_PUBLICATION_MATCHED_STATUS, DDS_PUBLICATION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_writer, g_writer); - CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); - - dds_delete(g_writer); - dds_delete(g_reader); + DDSRT_WARNING_MSVC_OFF(4996); // use of sscanf triggers a warning + if (*args == 0) + return; + if (*args++ != '(') + abort (); + assert (lldesc[ll].desc != NULL); + const char *d = lldesc[ll].desc; + const char *sep = "("; + size_t off = 0; + while (*d) + { + const void *p = advance (status, &off, *d); + char str[32]; + unsigned u; + int i, pos = -1; + switch (*d) + { + case 'n': + if (sscanf (args, "%u%n", &u, &pos) != 1 || (args[pos] != ',' && args[pos] != ')')) + abort (); + printf ("%s%"PRIu32" %u", sep, *(uint32_t *)p, u); fflush (stdout); + CU_ASSERT_FATAL (*(uint32_t *)p == u); + break; + case 'c': + if (sscanf (args, "%d%n", &i, &pos) != 1 || (args[pos] != ',' && args[pos] != ')')) + abort (); + printf ("%s%"PRId32" %d", sep, *(int32_t *)p, i); fflush (stdout); + CU_ASSERT_FATAL (*(int32_t *)p == i); + break; + case 'P': // policy id: currently fixed at reliability + pos = -1; // not actually consuming an argument + printf ("%s%"PRIu32" %d", sep, *(uint32_t *)p, (int) DDS_RELIABILITY_QOS_POLICY_ID); fflush (stdout); + CU_ASSERT_FATAL (*(uint32_t *)p == (uint32_t) DDS_RELIABILITY_QOS_POLICY_ID); + break; + case 'R': + if (sscanf (args, "%31[^,)]%n", str, &pos) != 1 || (args[pos] != ',' && args[pos] != ')')) + abort (); + if (strcmp (str, "i") == 0) + i = (int) DDS_REJECTED_BY_INSTANCES_LIMIT; + else if (strcmp (str, "s") == 0) + i = (int) DDS_REJECTED_BY_SAMPLES_LIMIT; + else if (strcmp (str, "spi") == 0) + i = (int) DDS_REJECTED_BY_SAMPLES_PER_INSTANCE_LIMIT; + else + abort (); + printf ("%s%d %d", sep, (int) *(dds_sample_rejected_status_kind *)p, i); fflush (stdout); + CU_ASSERT_FATAL (*(dds_sample_rejected_status_kind *)p == (dds_sample_rejected_status_kind) i); + break; + case 'I': // instance handle is too complicated + pos = -1; // not actually consuming an argument + break; + case 'E': { + int ent1 = -1; + dds_instance_handle_t esi1 = 0; + if (sscanf (args, "%31[^,)]%n", str, &pos) != 1 || (args[pos] != ',' && args[pos] != ')')) + abort (); + if (strcmp (str, "*") != 0 && (ent1 = getentity (str, NULL, NULL)) < 0) + abort (); + if (ent1 != -1) + esi1 = lookup_insthandle (es, ent, ent1); + printf ("%s%"PRIx64" %"PRIx64, sep, *(dds_instance_handle_t *)p, esi1); fflush (stdout); + CU_ASSERT_FATAL (ent1 == -1 || *(dds_instance_handle_t *)p == esi1); + break; + } + default: abort (); + } + args += pos + 1; + sep = ", "; + d++; + } + printf (")"); + assert (*args == 0); + assert (off <= lldesc[ll].size); + DDSRT_WARNING_MSVC_ON(4996); } -CU_Test(ddsc_listener, publication_matched, .init=init_triggering_test, .fini=fini_triggering_test) +/** @brief run a "test" consisting of a sequence of simplish operations + * + * This operation takes a test description, really a program in a bizarre syntax, and executes it. Any failures, + * be it because of error codes coming out of the Cyclone calls or expected values being wrong cause it to fail + * the test via CU_ASSERT_FATAL. While it is doing this, it outputs the test steps to stdout including some + * actual values. An invalid program is mostly reported by calling abort(). It is geared towards checking for + * listener invocations and the effects on statuses. + * + * Entities in play: + * + * - participants: P P' + * - subscribers: R R' + * - publishers: W W' + * - readers: r s t r' s' t' + * - writers: w x y w' x' y' + * + * The unprimed ones exist in domain 0, the primed ones in domain 1 (but configured such that it talks to + * domain 0), so that network-related listener invocations can be checked as well. + * + * The first mention of an entity creates it as well as its ancestors. Implicitly created ancestors always have + * standard QoS and have no listeners. There is one topic that is created implicitly when the participant is + * created. + * + * Standard QoS is: default + reliable (100ms), by-source-timestamp, keep-all. + * The QoS of a reader/writer can be altered at the first mention of it by suffixing its name with "!" and/or "#" + * (the apostrophe is part of the name, so w#! or r'! are valid). Those suffixes are ignored if the entity + * already exists. + * + * A program consists of a sequence of operations separated by whitespace, ';' or '/' (there is no meaning to the + * separators, they exist to allow visual grouping): + * + * PROGRAM ::= (OP (\s+|[/;])*)* + * + * OP ::= (LISTENER)* ENTITY-NAME + * if entity ENTITY-NAME does not exist: + * creates the entity with the given listeners installed + * else + * changes the entity's listeners to the specified ones + * (see above for the valid ENTITY-NAMEs) + * | -ENTITY-NAME + * deletes the specified entity + * | WRITE-LIKE[fail][@DT] KEY + * writes/disposes/unregisters key KEY (an integer), if "fail" is appended, the + * expectation is that it fails with a timeout, if @DT is appended, the timestamp is the + * start time of the test +
    s rather than the current time; DT is a floating-point + * number + * | READ-LIKE[(A,B))] + * reads/takes at most 10 samples, counting the number of valid and invalid samples seen + * and checking it against A and B if given + * | ?LISTENER[(ARGS)] + * waits until the specified listener has been invoked on using a flag set + * by the listener function, resets the flag and verifies that neither the entity status + * bit nor the "change" fields in the various statuses were set + * ARGS is used to check the status argument most recently passed to the listener: + * it (A,B) verifies count and change match A and B, policy matches RELIABILITY + * lc (A,B,C,D,E) verifies that alive and not-alive counts match A and B, that + * alive and not-alive changes match C and D and that the last handle matches + * E if an entity name (ignored if E = "*") + * ll (A,B) verifies count and change match A and B + * odm (A,B) verifies count and change match A and B, last handle is ignored + * oiq (A,B) verifies that total count and change match A and B and that the + * mismatching QoS is reliability (the only one that can for now) + * pm (A,B,C,D,E) verifies that total count and change match A and B, that + * current count and change match C and D and that the last handle matches E + * if an entity name (ignored if E = "*") + * rdm see odm + * riq see oiq + * sl (A,B) verifies that total count and change match A and B + * sr (A,B,C) verifies total count and change match A and B, and that the reason + * matches C (one of "s" for samples, "i" for instances, "spi" for samples + * per instance) + * sm see pm + * | ?!LISTENER + * (not listener) tests that LISTENER has not been invoked since last reset + * | sleep D + * delay program execution for D s (D is a floating-point number) + * WRITE-LIKE ::= wr write + * | wrdisp write-dispose + * | disp dispose + * | unreg unregister + * READ-LIKE ::= read dds_read (so any state) + * | take dds_take (so any state) + * LISTENER ::= da data available (acts on a reader) + * | dor data on readers (acts on a subcsriber) + * | it incompatible topic (acts on a topic) + * | lc liveliness changed (acts on a reader) + * | ll liveliness lost (acts on a writer) + * | odm offered deadline missed (acts on a writer) + * | oiq offered incompatible QoS (acts on a writer) + * | pm publication matched (acts on a writer) + * | rdm requested deadline missed (acts on a reader) + * | riq requested incompatible QoS (acts on a reader) + * | sl sample lost (acts on a reader) + * | sr sample rejected (acts on a reader) + * | sm subscription matched (acts on a reader) + * + * All entities share the listeners with their global state. Only the latest invocation is visible. + * + * @param[in] ops Program to execute. + */ +static void dotest (const char *ops) { - dds_publication_matched_status_t publication_matched; - dds_instance_handle_t reader_hdl; - dds_return_t ret; - uint32_t triggered; - uint32_t status; + DDSRT_WARNING_MSVC_OFF(4996); // use of sscanf triggers a warning + static const char *sep = " /;\n\t\r\v"; + char *opscopy = ddsrt_strdup (ops), *cursor = opscopy, *tok; + struct ents es; + dds_return_t ret; + Space_Type1 sample; + char topicname[100]; + dds_qos_t *qos = dds_create_qos (), *rwqos = dds_create_qos (); + dds_listener_t *list = dds_create_listener (NULL); + const dds_time_t tref = dds_time (); + CU_ASSERT_FATAL (qos != NULL); + CU_ASSERT_FATAL (rwqos != NULL); + CU_ASSERT_FATAL (list != NULL); + dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_MSECS (100)); + dds_qset_destination_order (qos, DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP); + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0); + memset (&es, 0, sizeof (es)); + memset (&sample, 0, sizeof (sample)); - /* Get reader handle that should be part of the status. */ - ret = dds_get_instance_handle(g_reader, &reader_hdl); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + ddsrt_mutex_init (&g_mutex); + ddsrt_cond_init (&g_cond); + ddsrt_mutex_lock (&g_mutex); + cb_called = 0; + ddsrt_mutex_unlock (&g_mutex); - /* Publication matched should be triggered with the right status. */ - triggered = waitfor_cb(DDS_PUBLICATION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_PUBLICATION_MATCHED_STATUS, DDS_PUBLICATION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_writer, g_writer); - CU_ASSERT_EQUAL_FATAL(cb_publication_matched_status.current_count, 1); - CU_ASSERT_EQUAL_FATAL(cb_publication_matched_status.current_count_change, 1); - CU_ASSERT_EQUAL_FATAL(cb_publication_matched_status.total_count, 1); - CU_ASSERT_EQUAL_FATAL(cb_publication_matched_status.total_count_change, 1); - CU_ASSERT_EQUAL_FATAL(cb_publication_matched_status.last_subscription_handle, reader_hdl); + create_unique_topic_name ("ddsc_listener_test", topicname, 100); + printf ("dotest: %s\n", ops); + printf ("topic: %s\n", topicname); + while ((tok = strsep_noempty (&cursor, sep)) != NULL) + { + int ent, ll; + bool isbang, ishash; + if ((ent = getentity (tok, &isbang, &ishash)) >= 0) + { + make_entity (&es, topicname, ent, isbang, ishash, qos, rwqos, NULL); + } + else if (*tok == '-' && (ent = getentity (tok + 1, NULL, NULL)) >= 0) + { + // delete deliberately leaves the instance handle in place for checking + // the publication/subscription handle in subscription matched/publication + // matched for a lost match + printf ("delete %"PRId32"\n", es.es[ent]); + ret = dds_delete (es.es[ent]); + CU_ASSERT_FATAL (ret == 0); + es.es[ent] = 0; + } + else if ((ll = getlistener (tok, &isbang)) >= 0) + { + printf ("set listener:"); + dds_reset_listener (list); + do { + printf (" %s", tok); + switch (ll) + { + case 0: dds_lset_data_available (list, isbang ? 0 : data_available_cb); break; + case 1: dds_lset_data_on_readers (list, isbang ? 0 : data_on_readers_cb); break; + case 2: dds_lset_inconsistent_topic (list, isbang ? 0: inconsistent_topic_cb); break; + case 3: dds_lset_liveliness_changed (list, isbang ? 0 : liveliness_changed_cb); break; + case 4: dds_lset_liveliness_lost (list, isbang ? 0 : liveliness_lost_cb); break; + case 5: dds_lset_offered_deadline_missed (list, isbang ? 0 : offered_deadline_missed_cb); break; + case 6: dds_lset_offered_incompatible_qos (list, isbang ? 0 : offered_incompatible_qos_cb); break; + case 7: dds_lset_publication_matched (list, isbang ? 0 : publication_matched_cb); break; + case 8: dds_lset_requested_deadline_missed (list, isbang ? 0 : requested_deadline_missed_cb); break; + case 9: dds_lset_requested_incompatible_qos (list, isbang ? 0 : requested_incompatible_qos_cb); break; + case 10: dds_lset_sample_lost (list, isbang ? 0 : sample_lost_cb); break; + case 11: dds_lset_sample_rejected (list, isbang ? 0 : sample_rejected_cb); break; + case 12: dds_lset_subscription_matched (list, isbang ? 0 : subscription_matched_cb); break; + default: abort (); + } + } while ((tok = strsep_noempty (&cursor, sep)) != NULL && (ll = getlistener (tok, &isbang)) >= 0); + if (tok == NULL || (ent = getentity (tok, &isbang, &ishash)) < 0) + abort (); + if (es.es[ent] == 0) + { + printf (" for "); + make_entity (&es, topicname, ent, isbang, ishash, qos, rwqos, list); + } + else + { + dds_listener_t *tmplist = dds_create_listener (NULL); + CU_ASSERT_FATAL (tmplist != NULL); + ret = dds_get_listener (es.es[ent], tmplist); + CU_ASSERT_FATAL (ret == 0); + dds_merge_listener (list, tmplist); + dds_delete_listener (tmplist); + printf (" on entity %"PRId32"\n", es.es[ent]); + ret = dds_set_listener (es.es[ent], list); + CU_ASSERT_FATAL (ret == 0); + } + } + else if (strncmp (tok, "wr", 2) == 0 || strncmp (tok, "disp", 4) == 0 || strncmp (tok, "unreg", 5) == 0) + { + dds_return_t (*fn) (dds_entity_t wr, const void *sample, dds_time_t ts) = 0; + double dt = 0.0; + dds_time_t ts = dds_time (); + char *cmd = tok; + bool expectfail = false; + int off, pos, key; + if ((tok = strsep_noempty (&cursor, sep)) == NULL) + abort (); + if (sscanf (tok, "%d%n", &key, &pos) != 1 || tok[pos] != 0) + abort (); + if ((tok = strsep_noempty (&cursor, sep)) == NULL || (ent = getentity (tok, &isbang, &ishash)) < 0) + abort (); + if (es.es[ent] == 0) + make_entity (&es, topicname, ent, isbang, ishash, qos, rwqos, NULL); + switch (cmd[0]) + { + case 'w': + if (strncmp (cmd + 2, "disp", 4) == 0) { + off = 6; fn = dds_writedispose_ts; + } else { + off = 2; fn = dds_write_ts; + } + break; + case 'd': off = 4; fn = dds_dispose_ts; break; + case 'u': off = 5; fn = dds_unregister_instance_ts; break; + default: abort (); + } + if (strncmp (cmd + off, "fail", 4) == 0) + { + expectfail = true; + off += 4; + } + if (cmd[off] == '@') + { + if (sscanf (cmd + off, "@%lf%n", &dt, &pos) != 1 || cmd[off + pos] != 0) + abort (); + ts = tref + (dds_time_t) (dt * 1e9); + } + sample.long_1 = key; + printf ("entity %"PRId32": %*.*s@%"PRId64".%09"PRId64" %d\n", es.es[ent], off, off, cmd, ts / DDS_NSECS_IN_SEC, ts % DDS_NSECS_IN_SEC, key); + ret = fn (es.es[ent], &sample, ts); + if (expectfail) { + CU_ASSERT_FATAL (ret == DDS_RETCODE_TIMEOUT); + } else { + CU_ASSERT_FATAL (ret == 0); + } + } + else if (strncmp (tok, "take", 4) == 0 || strncmp(tok, "read", 4) == 0) + { + char *args = (tok[4] ? tok + 4 : NULL); + int exp_nvalid = -1, exp_ninvalid = -1, pos; + dds_return_t (*fn) (dds_entity_t, void **buf, dds_sample_info_t *, size_t, uint32_t); + fn = (strncmp (tok, "take", 4) == 0) ? dds_take : dds_read; + assert (args == NULL || *args == '('); + if (args && (sscanf (args, "(%d,%d)%n", &exp_nvalid, &exp_ninvalid, &pos) != 2 || args[pos] != 0)) + abort (); + if ((tok = strsep_noempty (&cursor, sep)) == NULL || (ent = getentity (tok, &isbang, &ishash)) < 0) + abort (); + if (es.es[ent] == 0) + make_entity (&es, topicname, ent, isbang, ishash, qos, rwqos, NULL); + printf ("entity %"PRId32": %s", es.es[ent], (fn == dds_take) ? "take" : "read"); + fflush (stdout); + void *raw[10] = { NULL }; + dds_sample_info_t si[10]; + const uint32_t maxs = (uint32_t) (sizeof (raw) / sizeof (raw[0])); + int count[2] = { 0, 0 }; + ret = fn (es.es[ent], raw, si, maxs, maxs); + CU_ASSERT_FATAL (ret >= 0); + for (int32_t i = 0; i < ret; i++) + count[si[i].valid_data]++; + ret = dds_return_loan (es.es[ent], raw, ret); + CU_ASSERT_FATAL (ret == 0); + printf (" valid %d %d invalid %d %d\n", count[1], exp_nvalid, count[0], exp_ninvalid); + if (exp_nvalid >= 0) + CU_ASSERT_FATAL (count[1] == exp_nvalid); + if (exp_ninvalid >= 0) + CU_ASSERT_FATAL (count[0] == exp_ninvalid); + } + else if (tok[0] == '?') + { + const bool expectclear = (tok[1] == '!'); + const char *llname = tok + (expectclear ? 2 : 1); + char *checkargs; + if ((checkargs = strchr (llname, '(')) != NULL) + *checkargs = 0; // clear so getlistener groks the input + if ((ll = getlistener (llname, NULL)) < 0) + abort (); + if (expectclear) + { + printf ("listener %s: check not called", llname); + fflush (stdout); + ddsrt_mutex_lock (&g_mutex); + printf (" cb_called %"PRIx32" %s\n", cb_called, (cb_called & lldesc[ll].mask) == 0 ? "ok" : "fail"); + CU_ASSERT_FATAL ((cb_called & lldesc[ll].mask) == 0); + ddsrt_mutex_unlock (&g_mutex); + } + else + { + bool signalled = true; + uint32_t status; + if ((tok = strsep_noempty (&cursor, sep)) == NULL || (ent = getentity (tok, &isbang, &ishash)) < 0) + abort (); + if (es.es[ent] == 0) + make_entity (&es, topicname, ent, isbang, ishash, qos, rwqos, NULL); + if ((size_t) ll >= sizeof (lldesc) / sizeof (*lldesc)) + abort (); + printf ("listener %s: check called for entity %"PRId32, llname, es.es[ent]); + fflush (stdout); + ddsrt_mutex_lock (&g_mutex); + while ((cb_called & lldesc[ll].mask) == 0 && signalled) + signalled = ddsrt_cond_waitfor (&g_cond, &g_mutex, DDS_SECS (5)); + printf (" cb_called %"PRIx32" (%s)", cb_called, (cb_called & lldesc[ll].mask) != 0 ? "ok" : "fail"); + fflush (stdout); + CU_ASSERT_FATAL ((cb_called & lldesc[ll].mask) != 0); + printf (" cb_entity %"PRId32" %"PRId32" (%s)", *lldesc[ll].cb_entity, es.es[ent], (*lldesc[ll].cb_entity == es.es[ent]) ? "ok" : "fail"); + fflush (stdout); + CU_ASSERT_FATAL (*lldesc[ll].cb_entity == es.es[ent]); + if (!(es.doms[0] && es.doms[1])) + { + // FIXME: two domains: listener invocation happens on another thread and we can observe non-0 "change" fields + // they get updated, listener gets invoked, then they get reset -- pretty sure it is allowed by the spec, but + // not quite elegant + assert_status_change_fields_are_0 (ll, es.es[ent]); + } + if (checkargs && lldesc[ll].cb_status) + { + *checkargs = '('; // restore ( so checkargs function gets a more sensible input + checkstatus (ll, &es, ent, checkargs, lldesc[ll].cb_status); + } + printf ("\n"); + cb_called &= ~lldesc[ll].mask; + ddsrt_mutex_unlock (&g_mutex); + ret = dds_get_status_changes (es.es[ent], &status); + CU_ASSERT_FATAL (ret == 0); + CU_ASSERT_FATAL ((status & lldesc[ll].mask) == 0); + } + } + else if (strcmp (tok, "sleep") == 0) + { + if ((tok = strsep_noempty (&cursor, sep)) == NULL) + abort (); + double d; int pos; + if (sscanf (tok, "%lf%n", &d, &pos) != 1 || tok[pos] != 0) + abort (); + printf ("sleep %fs\n", d); + dds_sleepfor ((dds_duration_t) (d * 1e9)); + } + else + { + printf ("tok '%s': unrecognized\n", tok); + abort (); + } + } - /* The listener should have swallowed the status. */ - ret = dds_read_status(g_writer, &status, DDS_PUBLICATION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); - - /* The listener should have reset the count_change. */ - ret = dds_get_publication_matched_status(g_writer, &publication_matched); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(publication_matched.current_count, 1); - CU_ASSERT_EQUAL_FATAL(publication_matched.current_count_change, 0); - CU_ASSERT_EQUAL_FATAL(publication_matched.total_count, 1); - CU_ASSERT_EQUAL_FATAL(publication_matched.total_count_change, 0); - CU_ASSERT_EQUAL_FATAL(publication_matched.last_subscription_handle, reader_hdl); - - /* Reset the trigger flags. */ - ddsrt_mutex_lock(&g_mutex); - cb_called = 0; - ddsrt_mutex_unlock(&g_mutex); - - /* Un-match the publication by deleting the reader. */ - dds_delete(g_reader); - - /* Publication matched should be triggered with the right status. */ - triggered = waitfor_cb(DDS_PUBLICATION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_PUBLICATION_MATCHED_STATUS, DDS_PUBLICATION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_writer, g_writer); - CU_ASSERT_EQUAL_FATAL(cb_publication_matched_status.current_count, 0); - CU_ASSERT_EQUAL_FATAL(cb_publication_matched_status.current_count_change, -1); - CU_ASSERT_EQUAL_FATAL(cb_publication_matched_status.total_count, 1); - CU_ASSERT_EQUAL_FATAL(cb_publication_matched_status.total_count_change, 0); - CU_ASSERT_EQUAL_FATAL(cb_publication_matched_status.last_subscription_handle, reader_hdl); - - /* The listener should have reset the count_change. */ - ret = dds_get_publication_matched_status(g_writer, &publication_matched); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(publication_matched.current_count, 0); - CU_ASSERT_EQUAL_FATAL(publication_matched.current_count_change, 0); - CU_ASSERT_EQUAL_FATAL(publication_matched.total_count, 1); - CU_ASSERT_EQUAL_FATAL(publication_matched.total_count_change, 0); - CU_ASSERT_EQUAL_FATAL(publication_matched.last_subscription_handle, reader_hdl); + dds_delete_listener (list); + dds_delete_qos (rwqos); + dds_delete_qos (qos); + // prevent any listeners from being invoked so we can safely delete the + // mutex and the condition variable -- must do this going down the + // hierarchy, or listeners may remain set through inheritance + for (size_t i = 0; i < sizeof (es.es) / sizeof (es.es[0]); i++) + { + if (es.es[i]) + { + ret = dds_set_listener (es.es[i], NULL); + CU_ASSERT_FATAL (ret == 0); + } + } + ddsrt_mutex_destroy (&g_mutex); + ddsrt_cond_destroy (&g_cond); + for (size_t i = 0; i < sizeof (es.doms) / sizeof (es.doms[0]); i++) + { + if (es.doms[i]) + { + ret = dds_delete (es.doms[i]); + CU_ASSERT_FATAL (ret == 0); + } + } + ddsrt_free (opscopy); + DDSRT_WARNING_MSVC_ON(4996); } -CU_Test(ddsc_listener, subscription_matched, .init=init_triggering_test, .fini=fini_triggering_test) +/************************************************** + **** **** + **** listener invocation checks **** + **** **** + **************************************************/ + +CU_Test (ddsc_listener, propagation) { - dds_subscription_matched_status_t subscription_matched; - dds_instance_handle_t writer_hdl; - dds_return_t ret; - uint32_t triggered; - uint32_t status; - - /* Get writer handle that should be part of the status. */ - ret = dds_get_instance_handle(g_writer, &writer_hdl); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - - /* Subscription matched should be triggered with the right status. */ - triggered = waitfor_cb(DDS_SUBSCRIPTION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_SUBSCRIPTION_MATCHED_STATUS, DDS_SUBSCRIPTION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); - CU_ASSERT_EQUAL_FATAL(cb_subscription_matched_status.current_count, 1); - CU_ASSERT_EQUAL_FATAL(cb_subscription_matched_status.current_count_change, 1); - CU_ASSERT_EQUAL_FATAL(cb_subscription_matched_status.total_count, 1); - CU_ASSERT_EQUAL_FATAL(cb_subscription_matched_status.total_count_change, 1); - CU_ASSERT_EQUAL_FATAL(cb_subscription_matched_status.last_publication_handle, writer_hdl); - - /* The listener should have swallowed the status. */ - ret = dds_read_status(g_reader, &status, DDS_SUBSCRIPTION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); - - /* The listener should have reset the count_change. */ - ret = dds_get_subscription_matched_status(g_reader, &subscription_matched); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(subscription_matched.current_count, 1); - CU_ASSERT_EQUAL_FATAL(subscription_matched.current_count_change, 0); - CU_ASSERT_EQUAL_FATAL(subscription_matched.total_count, 1); - CU_ASSERT_EQUAL_FATAL(subscription_matched.total_count_change, 0); - CU_ASSERT_EQUAL_FATAL(subscription_matched.last_publication_handle, writer_hdl); - - /* Reset the trigger flags. */ - ddsrt_mutex_lock(&g_mutex); - cb_called = 0; - ddsrt_mutex_unlock(&g_mutex); - - /* Un-match the subscription by deleting the writer. */ - dds_delete(g_writer); - - /* Subscription matched should be triggered with the right status. */ - triggered = waitfor_cb(DDS_SUBSCRIPTION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_SUBSCRIPTION_MATCHED_STATUS, DDS_SUBSCRIPTION_MATCHED_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); - CU_ASSERT_EQUAL_FATAL(cb_subscription_matched_status.current_count, 0); - CU_ASSERT_EQUAL_FATAL(cb_subscription_matched_status.current_count_change, -1); - CU_ASSERT_EQUAL_FATAL(cb_subscription_matched_status.total_count, 1); - CU_ASSERT_EQUAL_FATAL(cb_subscription_matched_status.total_count_change, 0); - CU_ASSERT_EQUAL_FATAL(cb_subscription_matched_status.last_publication_handle, writer_hdl); - - /* The listener should have reset the count_change. */ - ret = dds_get_subscription_matched_status(g_reader, &subscription_matched); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(subscription_matched.current_count, 0); - CU_ASSERT_EQUAL_FATAL(subscription_matched.current_count_change, 0); - CU_ASSERT_EQUAL_FATAL(subscription_matched.total_count, 1); - CU_ASSERT_EQUAL_FATAL(subscription_matched.total_count_change, 0); - CU_ASSERT_EQUAL_FATAL(subscription_matched.last_publication_handle, writer_hdl); + // data-on-readers set on a participant at creation time must not trigger for + // the readers for DCPSPublication and DCPSSubscription: those events must be + // invisible for the test logic to work reliably. Installing a dummy listener + // for it on the reader should prevent that from happening + dotest ("da dor lc sm P ; ?!dor ?!da ?!sm ?!lc"); + // writing data should trigger data-available unless data-on-readers is set + dotest ("da lc sm P ; r ; wr 0 w ; ?da r ?sm r ?lc r"); + dotest ("da dor lc sm P ; r ; wr 0 w ; ?!da ; ?dor R ?sm r ?lc r"); + // setting listeners after entity creation should work, too + dotest ("P W R ; dor P pm W sm R ; r w ; ?sm r ?pm w ; wr 0 w ; ?dor R ; ?!da"); } -CU_Test(ddsc_listener, incompatible_qos, .init=init_triggering_base, .fini=fini_triggering_base) +CU_Test (ddsc_listener, matched) { - dds_offered_incompatible_qos_status_t offered_incompatible_qos; - dds_requested_incompatible_qos_status_t requested_incompatible_qos; - dds_return_t ret; - uint32_t triggered; - uint32_t status; - - /* We are interested in incompatible qos notifications. */ - dds_lset_offered_incompatible_qos(g_listener, offered_incompatible_qos_cb); - dds_lset_requested_incompatible_qos(g_listener, requested_incompatible_qos_cb); - - /* Create reader and writer with proper listeners. - * But create reader with persistent durability to get incompatible qos. */ - g_writer = dds_create_writer(g_participant, g_topic, g_qos, g_listener); - CU_ASSERT_FATAL(g_writer > 0); - dds_qset_durability (g_qos, DDS_DURABILITY_PERSISTENT); - g_reader = dds_create_reader(g_participant, g_topic, g_qos, g_listener); - CU_ASSERT_FATAL(g_reader > 0); - - /* Incompatible QoS should be triggered with the right status. */ - triggered = waitfor_cb(DDS_OFFERED_INCOMPATIBLE_QOS_STATUS | DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_OFFERED_INCOMPATIBLE_QOS_STATUS, DDS_OFFERED_INCOMPATIBLE_QOS_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS, DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); - CU_ASSERT_EQUAL_FATAL(cb_writer, g_writer); - CU_ASSERT_EQUAL_FATAL(cb_offered_incompatible_qos_status.total_count, 1); - CU_ASSERT_EQUAL_FATAL(cb_offered_incompatible_qos_status.total_count_change, 1); - CU_ASSERT_EQUAL_FATAL(cb_offered_incompatible_qos_status.last_policy_id, DDS_DURABILITY_QOS_POLICY_ID); - CU_ASSERT_EQUAL_FATAL(cb_requested_incompatible_qos_status.total_count, 1); - CU_ASSERT_EQUAL_FATAL(cb_requested_incompatible_qos_status.total_count_change, 1); - CU_ASSERT_EQUAL_FATAL(cb_requested_incompatible_qos_status.last_policy_id, DDS_DURABILITY_QOS_POLICY_ID); - - /* The listener should have swallowed the status. */ - ret = dds_read_status(g_writer, &status, DDS_OFFERED_INCOMPATIBLE_QOS_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); - ret = dds_read_status(g_reader, &status, DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); - - /* The listener should have reset the count_change. */ - ret = dds_get_offered_incompatible_qos_status(g_writer, &offered_incompatible_qos); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - ret = dds_get_requested_incompatible_qos_status(g_reader, &requested_incompatible_qos); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(offered_incompatible_qos.total_count, 1); - CU_ASSERT_EQUAL_FATAL(offered_incompatible_qos.total_count_change, 0); - CU_ASSERT_EQUAL_FATAL(offered_incompatible_qos.last_policy_id, DDS_DURABILITY_QOS_POLICY_ID); - CU_ASSERT_EQUAL_FATAL(requested_incompatible_qos.total_count, 1); - CU_ASSERT_EQUAL_FATAL(requested_incompatible_qos.total_count_change, 0); - CU_ASSERT_EQUAL_FATAL(requested_incompatible_qos.last_policy_id, DDS_DURABILITY_QOS_POLICY_ID); - - dds_delete(g_writer); - dds_delete(g_reader); + // publication & subscription matched must both trigger; note: reader/writer matching inside + // a process is synchronous, no need to check everywhere + dotest ("sm r pm w ?pm w ?sm r"); + // across the network it should work just as well (matching happens on different threads for + // remote & local entity creation, so it is meaningfully different test) + dotest ("sm r pm w' ?pm w' ?sm r"); } -CU_Test(ddsc_listener, data_available, .init=init_triggering_test, .fini=fini_triggering_test) +CU_Test (ddsc_listener, publication_matched) { - dds_return_t ret; - uint32_t triggered; - uint32_t status; - RoundTripModule_DataType sample; - memset (&sample, 0, sizeof (sample)); + // regardless of order of creation, the writer should see one reader come & then go + dotest ("sm r pm w ; ?pm(1,1,1,1,r) w ?sm r ; -r ; ?pm(1,0,0,-1,r) w"); + dotest ("pm w sm r ; ?pm(1,1,1,1,r) w ?sm r ; -r ; ?pm(1,0,0,-1,r) w"); - /* We are interested in data available notifications. */ - dds_lset_data_available(g_listener, data_available_cb); - ret = dds_set_listener(g_reader, g_listener); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + // regardless of order of creation, the writer should see one reader come & then go, also + // when a second reader introduced + dotest ("sm r pm w ; ?pm(1,1,1,1,r) w ?sm r ; t ?pm(2,1,2,1,t) w ; -r ; ?pm(2,0,1,-1,r) w"); + dotest ("pm w sm r ; ?pm(1,1,1,1,r) w ?sm r ; t ?pm(2,1,2,1,t) w ; -t ; ?pm(2,0,1,-1,t) w"); - /* Write sample. */ - ret = dds_write(g_writer, &sample); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + // same with 2 domains + dotest ("sm r pm w' ; ?pm(1,1,1,1,r) w' ?sm r ; -r ; ?pm(1,0,0,-1,r) w'"); + dotest ("pm w sm r' ; ?pm(1,1,1,1,r') w ?sm r' ; -r' ; ?pm(1,0,0,-1,r') w"); - /* Data available should be triggered with the right status. */ - triggered = waitfor_cb(DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); - - /* The listener should have swallowed the status. */ - ret = dds_read_status(g_subscriber, &status, DDS_DATA_ON_READERS_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); - ret = dds_read_status(g_reader, &status, DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); - - /* Deleting the writer causes unregisters (or dispose+unregister), and those - should trigger DATA_AVAILABLE as well */ - ddsrt_mutex_lock(&g_mutex); - cb_called = 0; - cb_reader = 0; - ddsrt_mutex_unlock(&g_mutex); - ret = dds_delete (g_writer); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - g_writer = 0; - triggered = waitfor_cb(DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); - - /* The listener should have swallowed the status. */ - ret = dds_read_status(g_subscriber, &status, DDS_DATA_ON_READERS_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); - ret = dds_read_status(g_reader, &status, DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); + dotest ("sm r pm w' ; ?pm(1,1,1,1,r) w' ?sm r ; t ?pm(2,1,2,1,t) w' ; -r ; ?pm(2,0,1,-1,r) w'"); + dotest ("pm w sm r' ; ?pm(1,1,1,1,r') w ?sm r' ; t ?pm(2,1,2,1,t) w ; -t ; ?pm(2,0,1,-1,t) w"); + dotest ("sm r pm w' ; ?pm(1,1,1,1,r) w' ?sm r ; t' ?pm(2,1,2,1,t') w' ; -r ; ?pm(2,0,1,-1,r) w'"); + dotest ("pm w sm r' ; ?pm(1,1,1,1,r') w ?sm r' ; t' ?pm(2,1,2,1,t') w ; -t' ; ?pm(2,0,1,-1,t') w"); } -CU_Test(ddsc_listener, data_available_delete_writer, .init=init_triggering_test, .fini=fini_triggering_test) +CU_Test (ddsc_listener, subscription_matched) { - dds_return_t ret; - uint32_t triggered; - uint32_t status; - RoundTripModule_DataType sample; - memset (&sample, 0, sizeof (sample)); + // regardless of order of creation, the reader should see one writer come & then go + dotest ("sm r pm w ; ?pm w ?sm(1,1,1,1,w) r ; -w ; ?sm(1,0,0,-1,w) r"); + dotest ("pm w sm r ; ?pm w ?sm(1,1,1,1,w) r ; -w ; ?sm(1,0,0,-1,w) r"); - /* We are interested in data available notifications. */ - dds_lset_data_available(g_listener, data_available_cb); - ret = dds_set_listener(g_reader, g_listener); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + // regardless of order of creation, the reader should see one writer come & then go, also + // when a second writer is introduced + dotest ("sm r pm w ; ?pm w ?sm(1,1,1,1,w) r ; x ?sm(2,1,2,1,x) r ; -w ; ?sm(2,0,1,-1,w) r"); + dotest ("pm w sm r ; ?pm w ?sm(1,1,1,1,w) r ; x ?sm(2,1,2,1,x) r ; -x ; ?sm(2,0,1,-1,x) r"); - /* Write sample, wait for the listener to swallow the status. */ - ret = dds_write(g_writer, &sample); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - triggered = waitfor_cb(DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); + // same with 2 domains + dotest ("sm r pm w' ; ?pm w' ?sm(1,1,1,1,w') r ; -w' ; ?sm(1,0,0,-1,w') r"); + dotest ("pm w sm r' ; ?pm w ?sm(1,1,1,1,w) r' ; -w ; ?sm(1,0,0,-1,w) r'"); - /* Deleting the writer must trigger DATA_AVAILABLE as well */ - ddsrt_mutex_lock(&g_mutex); - cb_called = 0; - cb_reader = 0; - ddsrt_mutex_unlock(&g_mutex); - ret = dds_delete (g_writer); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - g_writer = 0; - triggered = waitfor_cb(DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); - - /* The listener should have swallowed the status. */ - ret = dds_read_status(g_subscriber, &status, DDS_DATA_ON_READERS_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); - ret = dds_read_status(g_reader, &status, DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); + dotest ("sm r pm w' ; ?pm w' ?sm(1,1,1,1,w') r ; x ?sm(2,1,2,1,x) r ; -w' ; ?sm(2,0,1,-1,w') r"); + dotest ("pm w sm r' ; ?pm w ?sm(1,1,1,1,w) r' ; x ?sm(2,1,2,1,x) r' ; -x ; ?sm(2,0,1,-1,x) r'"); + dotest ("sm r pm w' ; ?pm w' ?sm(1,1,1,1,w') r ; x' ?sm(2,1,2,1,x') r ; -w' ; ?sm(2,0,1,-1,w') r"); + dotest ("pm w sm r' ; ?pm w ?sm(1,1,1,1,w) r' ; x' ?sm(2,1,2,1,x') r' ; -x' ; ?sm(2,0,1,-1,x') r'"); } -CU_Test(ddsc_listener, data_available_delete_writer_disposed, .init=init_triggering_test, .fini=fini_triggering_test) +CU_Test (ddsc_listener, incompatible_qos) { - dds_return_t ret; - uint32_t triggered; - uint32_t status; - RoundTripModule_DataType sample; - memset (&sample, 0, sizeof (sample)); - - /* We are interested in data available notifications. */ - dds_lset_data_available(g_listener, data_available_cb); - ret = dds_set_listener(g_reader, g_listener); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - - /* Write & dispose sample and take it so that the instance is empty & disposed. Then deleting - the writer should silently drop the instance. */ - ret = dds_write(g_writer, &sample); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - ret = dds_dispose(g_writer, &sample); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - triggered = waitfor_cb(DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); - - /* Take all data so that the instance becomes empty & disposed */ - do { - void *sampleptr = &sample; - dds_sample_info_t info; - ret = dds_take (g_reader, &sampleptr, &info, 1, 1); - } while (ret > 0); - - /* Deleting the writer should not trigger DATA_AVAILABLE with all instances empty & disposed */ - ddsrt_mutex_lock(&g_mutex); - cb_called = 0; - cb_reader = 0; - ddsrt_mutex_unlock(&g_mutex); - ret = dds_delete (g_writer); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - g_writer = 0; - ddsrt_mutex_lock(&g_mutex); - CU_ASSERT_EQUAL_FATAL(cb_called & DDS_DATA_AVAILABLE_STATUS_ID, 0); - ddsrt_mutex_unlock(&g_mutex); - - /* The listener should have swallowed the status. */ - ret = dds_read_status(g_subscriber, &status, DDS_DATA_ON_READERS_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); - ret = dds_read_status(g_reader, &status, DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); + // best-effort writer & reliable reader: both must trigger incompatible QoS event + dotest ("oiq w! riq r ; ?oiq(1,1) w ?riq(1,1) r"); + dotest ("riq r oiq w! ; ?oiq(1,1) w ?riq(1,1) r"); } -CU_Test(ddsc_listener, data_on_readers, .init=init_triggering_test, .fini=fini_triggering_test) +CU_Test (ddsc_listener, data_available) { - dds_return_t ret; - uint32_t triggered; - uint32_t status; - RoundTripModule_DataType sample; - memset (&sample, 0, sizeof (sample)); - - /* We are interested in data available notifications. */ - dds_lset_data_on_readers(g_listener, data_on_readers_cb); - ret = dds_set_listener(g_subscriber, g_listener); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - - /* Setting data available notifications should not 'sabotage' the on_readers call. */ - dds_lset_data_available(g_listener, data_available_cb); - ret = dds_set_listener(g_reader, g_listener); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - - /* Write sample. */ - ret = dds_write(g_writer, &sample); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - - /* Data on readers should be triggered with the right status. */ - triggered = waitfor_cb(DDS_DATA_ON_READERS_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_DATA_ON_READERS_STATUS, DDS_DATA_ON_READERS_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_subscriber, g_subscriber); - CU_ASSERT_NOT_EQUAL_FATAL(triggered & DDS_DATA_AVAILABLE_STATUS, DDS_DATA_AVAILABLE_STATUS); - - /* The listener should have swallowed the status. */ - ret = dds_read_status(g_subscriber, &status, DDS_DATA_ON_READERS_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); - ret = dds_read_status(g_reader, &status, DDS_DATA_AVAILABLE_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); + // data available on reader + dotest ("da sm r pm w ?pm w ?sm r wr 0 w ?da r ?!dor"); + // data available set on subscriber + dotest ("da R sm r pm w ?pm w ?sm r wr 0 w ?da r ?!dor"); + // data available set on participant + dotest ("da P sm r pm w ?pm w ?sm r wr 0 w ?da r ?!dor"); } - -CU_Test(ddsc_listener, sample_lost, .init=init_triggering_test, .fini=fini_triggering_test) +CU_Test (ddsc_listener, data_available_delete_writer) { - dds_sample_lost_status_t sample_lost; - dds_return_t ret; - uint32_t triggered; - dds_time_t the_past; - uint32_t status; - RoundTripModule_DataType sample; - memset (&sample, 0, sizeof (sample)); - - /* Get a time that should be historic on all platforms.*/ - the_past = dds_time() - 1000000; - - /* We are interested in sample lost notifications. */ - dds_lset_sample_lost(g_listener, sample_lost_cb); - ret = dds_set_listener(g_reader, g_listener); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - - /* Write first sample with current timestamp. */ - ret = dds_write_ts(g_writer, &sample, dds_time()); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - - /* Write second sample with older timestamp. */ - ret = dds_write_ts(g_writer, &sample, the_past); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - - /* Sample lost should be triggered with the right status. */ - triggered = waitfor_cb(DDS_SAMPLE_LOST_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_SAMPLE_LOST_STATUS, DDS_SAMPLE_LOST_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); - CU_ASSERT_EQUAL_FATAL(cb_sample_lost_status.total_count, 1); - CU_ASSERT_EQUAL_FATAL(cb_sample_lost_status.total_count_change, 1); - - /* The listener should have swallowed the status. */ - ret = dds_read_status(g_reader, &status, DDS_SAMPLE_LOST_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); - - /* The listener should have reset the count_change. */ - ret = dds_get_sample_lost_status(g_reader, &sample_lost); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(sample_lost.total_count, 1); - CU_ASSERT_EQUAL_FATAL(sample_lost.total_count_change, 0); + // unmatching a writer that didn't read anything has no visible effect on RHC + // subscription-matched event is generated synchronously, so "?sm r" doesn't + // really add anything (it'd be different if there are two domain instances) + dotest ("da sm r w ; -w ?sm r ?!da ; take(0,0) r"); + // after writing: auto-dispose should always trigger data available, an invalid + // sample needs to show up if there isn't an unread sample to use instead + dotest ("da r w ; wr 0 w ?da r ; -w ?da r ; take(1,0) r"); + dotest ("da r w ; wr 0 w ?da r ; read(1,0) r ; -w ?da r ; take(1,1) r"); + dotest ("da r w ; wr 0 w ?da r ; take(1,0) r ; -w ?da r ; take(0,1) r"); + // same with two writers (no point in doing this also with two domains) + dotest ("da r w x ; -w ?!da -x ?!da ; take(0,0) r"); + dotest ("da r w x ; wr 0 w ?da r ; -x ?!da ; -w ?da r ; take(1,0) r"); + dotest ("da r w x ; wr 0 w ?da r ; -w ?da r ; take(1,0) r ; -x ?!da ; take(0,0) r"); + dotest ("da r w x ; wr 0 w wr 0 x ?da r ; -w ?!da ; take(2,0) r ; -x ?da r ; take(0,1) r"); + dotest ("da r w x ; wr 0 w wr 0 x ?da r ; read(2,0) r ; -w ?!da -x ?da r ; take(2,1) r"); + dotest ("da r w x ; wr 0 w wr 0 x ?da r ; read(2,0) r ; -x ?!da -w ?da r ; take(2,1) r"); + dotest ("da r w x ; wr 0 w read(1,0) r ; wr 0 x ?da r ; -w ?!da -x ?da r ; take(2,0) r"); + dotest ("da r w x ; wr 0 w read(1,0) r ; wr 0 x ?da r ; -x ?!da -w ?da r ; take(2,0) r"); + dotest ("da r w x ; wr 0 w read(1,0) r ; wr 0 x ?da r ; read(2,0) r ; -w ?!da -x ?da r ; take(2,1) r"); + dotest ("da r w x ; wr 0 w read(1,0) r ; wr 0 x ?da r ; read(2,0) r ; -x ?!da -w ?da r ; take(2,1) r"); + dotest ("da r w x ; wr 0 w wr 0 x ?da r ; take(2,0) r ; -w ?!da -x ?da r ; take(0,1) r"); + dotest ("da r w x ; wr 0 w wr 0 x ?da r ; take(2,0) r ; -x ?!da -w ?da r ; take(0,1) r"); } -CU_Test(ddsc_listener, sample_rejected, .init=init_triggering_test, .fini=fini_triggering_test) +CU_Test (ddsc_listener, data_available_delete_writer_disposed) { - dds_sample_rejected_status_t sample_rejected; - dds_return_t ret; - uint32_t triggered; - uint32_t status; - RoundTripModule_DataType sample; - memset (&sample, 0, sizeof (sample)); + // same as data_available_delete_writer, but now with the instance disposed first + dotest ("da r w ; wr 0 w disp 0 w ?da r ; -w ?!da"); + dotest ("da r w ; wr 0 w disp 0 w ?da r ; read(1,0) r ; -w ?!da"); + dotest ("da r w ; wr 0 w disp 0 w ?da r ; take(1,0) r ; -w ?!da"); - /* We are interested in sample rejected notifications. */ - dds_lset_sample_rejected(g_listener, sample_rejected_cb); - ret = dds_set_listener(g_reader, g_listener); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); + dotest ("da r w x ; wr 0 w ?da r ; read(1,0) r ; disp 0 w ?da r ; read(1,1) r ; -w ?!da -x ?!da"); + dotest ("da r w x ; wr 0 w ?da r ; take(1,0) r ; disp 0 w ?da r ; take(0,1) r ; -w ?!da -x ?!da"); + dotest ("da r w x ; wr 0 w ?da r ; read(1,0) r ; disp 0 w ?da r ; read(1,1) r ; -x ?!da -w ?!da"); + dotest ("da r w x ; wr 0 w ?da r ; take(1,0) r ; disp 0 w ?da r ; take(0,1) r ; -x ?!da -w ?!da"); - /* Write more than resource limits set by the reader. */ - ret = dds_write(g_writer, &sample); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - ret = dds_write(g_writer, &sample); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - ret = dds_write(g_writer, &sample); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - - /* Sample lost should be triggered with the right status. */ - triggered = waitfor_cb(DDS_SAMPLE_REJECTED_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_SAMPLE_REJECTED_STATUS, DDS_SAMPLE_REJECTED_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); - CU_ASSERT_EQUAL_FATAL(cb_sample_rejected_status.total_count, 2); - CU_ASSERT_EQUAL_FATAL(cb_sample_rejected_status.total_count_change, 1); - CU_ASSERT_EQUAL_FATAL(cb_sample_rejected_status.last_reason, DDS_REJECTED_BY_SAMPLES_LIMIT); - - /* The listener should have swallowed the status. */ - ret = dds_read_status(g_reader, &status, DDS_SAMPLE_REJECTED_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); - - /* The listener should have reset the count_change. */ - ret = dds_get_sample_rejected_status(g_reader, &sample_rejected); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(sample_rejected.total_count, 2); - CU_ASSERT_EQUAL_FATAL(sample_rejected.total_count_change, 0); - CU_ASSERT_EQUAL_FATAL(cb_sample_rejected_status.last_reason, DDS_REJECTED_BY_SAMPLES_LIMIT); + dotest ("da r w x ; wr 0 w ?da r ; read(1,0) r ; disp 0 x ?da r ; read(1,1) r ; -w ?!da -x ?!da"); + dotest ("da r w x ; wr 0 w ?da r ; take(1,0) r ; disp 0 x ?da r ; take(0,1) r ; -w ?!da -x ?!da"); + dotest ("da r w x ; wr 0 w ?da r ; read(1,0) r ; disp 0 x ?da r ; read(1,1) r ; -x ?!da -w ?!da"); + dotest ("da r w x ; wr 0 w ?da r ; take(1,0) r ; disp 0 x ?da r ; take(0,1) r ; -x ?!da -w ?!da"); } -CU_Test(ddsc_listener, liveliness_changed, .init=init_triggering_test, .fini=fini_triggering_base) +CU_Test (ddsc_listener, data_on_readers) { - dds_liveliness_changed_status_t liveliness_changed; - dds_instance_handle_t writer_hdl; - dds_return_t ret; - uint32_t triggered; - uint32_t status; - - /* The init_triggering_test_byliveliness set our interest in liveliness. */ - - /* Get writer handle that should be part of the status. */ - ret = dds_get_instance_handle(g_writer, &writer_hdl); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - - /* Liveliness changed should be triggered with the right status. */ - triggered = waitfor_cb(DDS_LIVELINESS_CHANGED_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_LIVELINESS_CHANGED_STATUS, DDS_LIVELINESS_CHANGED_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); - CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.alive_count, 1); - CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.alive_count_change, 1); - CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.not_alive_count, 0); - CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.not_alive_count_change, 0); - CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.last_publication_handle, writer_hdl); - - /* The listener should have swallowed the status. */ - ret = dds_read_status(g_reader, &status, DDS_LIVELINESS_CHANGED_STATUS); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(status, 0); - - /* The listener should have reset the count_change. */ - ret = dds_get_liveliness_changed_status(g_reader, &liveliness_changed); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count, 1); - CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count_change, 0); - CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count, 0); - CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count_change, 0); - CU_ASSERT_EQUAL_FATAL(liveliness_changed.last_publication_handle, writer_hdl); - - /* Reset the trigger flags. */ - ddsrt_mutex_lock(&g_mutex); - cb_called = 0; - ddsrt_mutex_unlock(&g_mutex); - - /* Change liveliness again by deleting the writer. */ - dds_delete(g_writer); - - /* Liveliness changed should be triggered with the right status. */ - triggered = waitfor_cb(DDS_LIVELINESS_CHANGED_STATUS); - CU_ASSERT_EQUAL_FATAL(triggered & DDS_LIVELINESS_CHANGED_STATUS, DDS_LIVELINESS_CHANGED_STATUS); - CU_ASSERT_EQUAL_FATAL(cb_reader, g_reader); - CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.alive_count, 0); - CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.alive_count_change, -1); - CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.not_alive_count, 0); - CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.not_alive_count_change, 0); - CU_ASSERT_EQUAL_FATAL(cb_liveliness_changed_status.last_publication_handle, writer_hdl); - - /* The listener should have reset the count_change. */ - ret = dds_get_liveliness_changed_status(g_reader, &liveliness_changed); - CU_ASSERT_EQUAL_FATAL(ret, DDS_RETCODE_OK); - CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count, 0); - CU_ASSERT_EQUAL_FATAL(liveliness_changed.alive_count_change, 0); - CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count, 0); - CU_ASSERT_EQUAL_FATAL(liveliness_changed.not_alive_count_change, 0); - CU_ASSERT_EQUAL_FATAL(liveliness_changed.last_publication_handle, writer_hdl); + // data on readers wins from data available + dotest ("dor R da r ; wr 0 w ; ?dor R ?!da"); + dotest ("dor P da r ; wr 0 w ; ?dor R ?!da"); } -#if 0 -/* This is basically the same as the Lite test, but inconsistent topic is not triggered. - * That is actually what I would expect, because the code doesn't seem to be the way - * to go to test for inconsistent topic. */ -Test(ddsc_listener, inconsistent_topic, .init=init_triggering_base, .fini=fini_triggering_base) +CU_Test (ddsc_listener, sample_lost) { - dds_entity_t wr_topic; - dds_entity_t rd_topic; - dds_entity_t writer; - dds_entity_t reader; - uint32_t triggered; - - os_osInit(); - - ddsrt_mutex_init(&g_mutex); - ddsrt_cond_init(&g_cond); - - g_qos = dds_create_qos(); - cr_assert_not_null(g_qos, "Failed to create prerequisite g_qos"); - - g_listener = dds_create_listener(NULL); - cr_assert_not_null(g_listener, "Failed to create prerequisite g_listener"); - - g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL); - cr_assert_gt(g_participant, 0, "Failed to create prerequisite g_participant"); - - /* We are interested in inconsistent topics. */ - dds_lset_inconsistent_topic(g_listener, inconsistent_topic_cb); - - wr_topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, "WRITER_TOPIC", NULL, g_listener); - cr_assert_gt(g_topic, 0, "Failed to create prerequisite wr_topic"); - - rd_topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, "READER_TOPIC", NULL, g_listener); - cr_assert_gt(g_topic, 0, "Failed to create prerequisite rd_topic"); - - /* Create reader and writer. */ - writer = dds_create_writer(g_participant, g_topic, NULL, NULL); - cr_assert_gt(writer, 0, "Failed to create prerequisite writer"); - dds_qset_reliability (g_qos, DDS_RELIABILITY_RELIABLE, DDS_SECS (1)); - dds_qset_history (g_qos, DDS_HISTORY_KEEP_ALL, 0); - reader = dds_create_reader(g_subscriber, g_topic, g_qos, NULL); - cr_assert_gt(reader, 0, "Failed to create prerequisite reader"); - - /* Inconsistent topic should be triggered with the right status. */ - triggered = waitfor_cb(DDS_INCONSISTENT_TOPIC_STATUS); - cr_assert_eq(triggered & DDS_INCONSISTENT_TOPIC_STATUS, DDS_INCONSISTENT_TOPIC_STATUS, "DDS_INCONSISTENT_TOPIC_STATUS not triggered"); - - dds_delete(reader); - dds_delete(writer); - dds_delete(rd_topic); - dds_delete(wr_topic); - dds_delete(g_participant); - - dds_delete_listener(g_listener); - dds_delete_qos(g_qos); + // FIXME: figure out what really constitutes a "lost sample" + dotest ("sl r ; wr@0 0 w ?!sl ; wr@-1 0 w ?sl(1,1) r"); } -#endif +CU_Test (ddsc_listener, sample_rejected) +{ + // FIXME: rejection counts with retries? + // reliable: expect timeout on the write when max samples has been reached + // invalid samples don't count towards resource limits, so dispose should + // not be blocked + dotest ("sr r# ; wr 0 w wrfail 0 w wrfail 0 w ; ?sr r"); + dotest ("sr r# ; wr 0 w wrfail 0 w ; read(1,0) r ; disp 0 w ; read(1,1) r ; ?sr r"); + + // best-effort: writes should succeed despite not delivering the data adding + // the data in the RHC, also check number of samples rejected + dotest ("sr r#! ; wr 0 w! wr 0 w wr 0 w ; ?sr(2,1,s) r"); + dotest ("sr r#! ; wr 0 w! wr 0 w ; read(1,0) r ; disp 0 w ; read(1,1) r ; ?sr(1,1,s) r"); +} + +CU_Test (ddsc_listener, liveliness_changed) +{ + // liveliness changed should trigger along with matching + dotest ("pm w lc sm r ; ?pm w ?sm r ; ?lc(1,0,1,0,w) r ; -w ; ?lc(0,0,-1,0,w) r"); + dotest ("pm w lc sm r' ; ?pm w ?sm r' ; ?lc(1,0,1,0,w) r' ; -w ; ?lc(0,0,-1,0,w) r'"); +} From bf25c6ec807c1b33b23e5369d3715cce8b2fc7f0 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 6 May 2020 21:31:58 +0200 Subject: [PATCH 211/238] Properly pair entity_pin/mutex_lock Coverity has difficulty observering that dds_entity_pin / ddsrt_mutex_lock / dds_entity_unlock is correct. It is perhaps a bit confusing, so change it. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_topic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c index a07b4e3..0f48cbd 100644 --- a/src/core/ddsc/src/dds_topic.c +++ b/src/core/ddsc/src/dds_topic.c @@ -359,7 +359,8 @@ dds_entity_t dds_create_topic_impl (dds_entity_t participant, struct ddsi_sertop hdl = create_topic_pp_locked (pp, ktp, (sertopic_registered->ops == &ddsi_sertopic_ops_builtintopic), sertopic_registered, listener, sedp_plist); ddsi_sertopic_unref (*sertopic); *sertopic = sertopic_registered; - dds_participant_unlock (pp); + ddsrt_mutex_unlock (&pp->m_entity.m_mutex); + dds_entity_unpin (&pp->m_entity); GVTRACE ("dds_create_topic_generic: new topic %"PRId32"\n", hdl); return hdl; From 02ed74e6bdcfee32512c454e780663768903ba88 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 6 May 2020 21:34:21 +0200 Subject: [PATCH 212/238] Fix conversion of user_data to security plugin The security plugins currently use the standardized representations of octet sequences, unlike the DDSI stack's internal representation. A shallow copy is therefore not simply a memcpy. Signed-off-by: Erik Boasson --- src/core/ddsi/src/ddsi_security_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ddsi/src/ddsi_security_util.c b/src/core/ddsi/src/ddsi_security_util.c index 11f39b5..65959bc 100644 --- a/src/core/ddsi/src/ddsi_security_util.c +++ b/src/core/ddsi/src/ddsi_security_util.c @@ -517,7 +517,7 @@ q_omg_shallow_copy_ParticipantBuiltinTopicDataSecure( /* Copy the DDS_Security_OctetSeq content (length, pointer, etc), not the buffer content. */ if (plist->qos.present & QP_USER_DATA) - memcpy(&(dst->user_data.value), &(plist->qos.user_data.value), sizeof(DDS_Security_OctetSeq)); + g_omg_shallow_copy_octSeq(&dst->user_data.value, &plist->qos.user_data); /* Tokens are actually DataHolders. */ if (plist->present & PP_IDENTITY_TOKEN) q_omg_shallow_copyin_DataHolder(&(dst->identity_token), &(plist->identity_token)); From 58e02d0b12c2c53aa075048712445f1b764cab43 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 6 May 2020 21:35:55 +0200 Subject: [PATCH 213/238] Fix leak when inserting p2p message in WHC fails Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_transmit.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/ddsi/src/q_transmit.c b/src/core/ddsi/src/q_transmit.c index 2b27d54..4a52fdb 100644 --- a/src/core/ddsi/src/q_transmit.c +++ b/src/core/ddsi/src/q_transmit.c @@ -1212,6 +1212,10 @@ int write_sample_p2p_wrlock_held(struct writer *wr, seqno_t seq, struct ddsi_pli if (wr->heartbeat_xevent) writer_hbcontrol_note_asyncwrite(wr, tnow); } + else if (gap) + { + nn_xmsg_free (gap); + } prd_is_deleting: return r; From a0d7b71e52e981a0146e577cfd40f10b466dd5df Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 6 May 2020 21:37:23 +0200 Subject: [PATCH 214/238] Atomic update next heartbeat time for p2p writers Sending a heartbeat to all matched readers for the P2P builtin participant volatile secure writer unlocks the writer before pushing each individual message out, and so determining the time of the next heartbeat event before writing and updating it afterwards means the state may have changed. While this is appears benign, it is better to do the update atomically. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_xevent.c | 40 ++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/core/ddsi/src/q_xevent.c b/src/core/ddsi/src/q_xevent.c index b535bbd..443a9fc 100644 --- a/src/core/ddsi/src/q_xevent.c +++ b/src/core/ddsi/src/q_xevent.c @@ -620,6 +620,31 @@ static void handle_xevk_entityid (struct nn_xpack *xp, struct xevent_nt *ev) } #ifdef DDSI_INCLUDE_SECURITY +static int send_heartbeat_to_all_readers_check_and_sched (struct xevent *ev, struct writer *wr, const struct whc_state *whcst, ddsrt_mtime_t tnow, ddsrt_mtime_t *t_next) +{ + int send; + if (!writer_must_have_hb_scheduled (wr, whcst)) + { + wr->hbcontrol.tsched = DDSRT_MTIME_NEVER; + send = -1; + } + else if (!writer_hbcontrol_must_send (wr, whcst, tnow)) + { + wr->hbcontrol.tsched = ddsrt_mtime_add_duration (tnow, writer_hbcontrol_intv (wr, whcst, tnow)); + send = -1; + } + else + { + const int hbansreq = writer_hbcontrol_ack_required (wr, whcst, tnow); + wr->hbcontrol.tsched = ddsrt_mtime_add_duration (tnow, writer_hbcontrol_intv (wr, whcst, tnow)); + send = hbansreq; + } + + resched_xevent_if_earlier (ev, wr->hbcontrol.tsched); + *t_next = wr->hbcontrol.tsched; + return send; +} + static void send_heartbeat_to_all_readers (struct nn_xpack *xp, struct xevent *ev, struct writer *wr, ddsrt_mtime_t tnow) { struct whc_state whcst; @@ -629,17 +654,11 @@ static void send_heartbeat_to_all_readers (struct nn_xpack *xp, struct xevent *e ddsrt_mutex_lock (&wr->e.lock); whc_get_state(wr->whc, &whcst); - - if (!writer_must_have_hb_scheduled (wr, &whcst)) - t_next = DDSRT_MTIME_NEVER; - else if (!writer_hbcontrol_must_send (wr, &whcst, tnow)) - t_next = ddsrt_mtime_add_duration (tnow, writer_hbcontrol_intv (wr, &whcst, tnow)); - else + const int hbansreq = send_heartbeat_to_all_readers_check_and_sched (ev, wr, &whcst, tnow, &t_next); + if (hbansreq >= 0) { struct wr_prd_match *m; struct ddsi_guid last_guid = { .prefix = {.u = {0,0,0}}, .entityid = {0} }; - const int hbansreq = writer_hbcontrol_ack_required (wr, &whcst, tnow); - t_next = ddsrt_mtime_add_duration (tnow, writer_hbcontrol_intv (wr, &whcst, tnow)); while ((m = ddsrt_avl_lookup_succ (&wr_readers_treedef, &wr->readers, &last_guid)) != NULL) { @@ -669,16 +688,11 @@ static void send_heartbeat_to_all_readers (struct nn_xpack *xp, struct xevent *e count++; } } - } } - resched_xevent_if_earlier (ev, t_next); - wr->hbcontrol.tsched = t_next; - if (count == 0) { - (void)resched_xevent_if_earlier (ev, t_next); ETRACE (wr, "heartbeat(wr "PGUIDFMT") suppressed, resched in %g s (min-ack %"PRId64"%s, avail-seq %"PRId64", xmit %"PRId64")\n", PGUID (wr->e.guid), (t_next.v == DDS_NEVER) ? INFINITY : (double)(t_next.v - tnow.v) / 1e9, From fa6dbe6c3d845813b4d6ac99e62f7245531b10db Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 6 May 2020 21:41:48 +0200 Subject: [PATCH 215/238] Memory leak reading access control configuration Signed-off-by: Erik Boasson --- .../access_control/src/access_control.c | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/security/builtin_plugins/access_control/src/access_control.c b/src/security/builtin_plugins/access_control/src/access_control.c index df27ea7..e9d91e0 100644 --- a/src/security/builtin_plugins/access_control/src/access_control.c +++ b/src/security/builtin_plugins/access_control/src/access_control.c @@ -2063,23 +2063,27 @@ read_document( char **doc, DDS_Security_SecurityException *ex) { - bool result = true; char *data = NULL; - switch (DDS_Security_get_conf_item_type(doc_uri, &data)) { - case DDS_SECURITY_CONFIG_ITEM_PREFIX_DATA: - *doc = data; - break; - case DDS_SECURITY_CONFIG_ITEM_PREFIX_FILE: - result = read_document_from_file(data, doc, ex); - ddsrt_free(data); - break; - default: - DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_URI_TYPE_NOT_SUPPORTED_CODE, 0, DDS_SECURITY_ERR_URI_TYPE_NOT_SUPPORTED_MESSAGE, doc_uri); - return false; + case DDS_SECURITY_CONFIG_ITEM_PREFIX_DATA: + *doc = data; + return true; + + case DDS_SECURITY_CONFIG_ITEM_PREFIX_FILE: { + const bool result = read_document_from_file(data, doc, ex); + ddsrt_free(data); + return result; + } + + case DDS_SECURITY_CONFIG_ITEM_PREFIX_PKCS11: + case DDS_SECURITY_CONFIG_ITEM_PREFIX_UNKNOWN: + DDS_Security_Exception_set(ex, DDS_ACCESS_CONTROL_PLUGIN_CONTEXT, DDS_SECURITY_ERR_URI_TYPE_NOT_SUPPORTED_CODE, 0, DDS_SECURITY_ERR_URI_TYPE_NOT_SUPPORTED_MESSAGE, doc_uri); + ddsrt_free(data); + return false; } - return result; + assert (0); + return false; } static bool From 59a2b9d273112a6d2a39d6b19cbc31158f8fa8e1 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 6 May 2020 21:44:12 +0200 Subject: [PATCH 216/238] Fix double free if local identity validation fails on certificate expiry Signed-off-by: Erik Boasson --- .../authentication/src/authentication.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index 316c910..f17ae41 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -762,6 +762,12 @@ DDS_Security_ValidationResult_t validate_local_identity(dds_security_authenticat if (verify_certificate(identityCert, identityCA, ex) != DDS_SECURITY_VALIDATION_OK) goto err_verification_failed; + if ((certExpiry = get_certificate_expiry(identityCert)) == DDS_TIME_INVALID) + { + DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Expiry date of the certificate is invalid"); + goto err_verification_failed; + } + if (get_adjusted_participant_guid(identityCert, candidate_participant_guid, adjusted_participant_guid, ex) != DDS_SECURITY_VALIDATION_OK) goto err_adj_guid_failed; @@ -774,12 +780,7 @@ DDS_Security_ValidationResult_t validate_local_identity(dds_security_authenticat identity = local_identity_info_new(domain_id, identityCert, identityCA, privateKey, candidate_participant_guid, adjusted_participant_guid); *local_identity_handle = IDENTITY_HANDLE(identity); - if ((certExpiry = get_certificate_expiry(identityCert)) == DDS_TIME_INVALID) - { - DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "Expiry date of the certificate is invalid"); - goto err_verification_failed; - } - else if (certExpiry != DDS_NEVER) + if (certExpiry != DDS_NEVER) add_validity_end_trigger(implementation, *local_identity_handle, certExpiry); ddsrt_mutex_lock(&implementation->lock); From fa7999c5d8075284b0d6a3aba7c315f7cf1fa636 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 6 May 2020 21:45:56 +0200 Subject: [PATCH 217/238] Vet lengths of property lists in crypto deserialization The memory allocation in deserializing property lists within the crypto code should not trust the deserialized length and try to allocate that much memory but should first verify that the length is consistent with the number of bytes remaining in the input. (Noted by Coverity as use of tainted data.) Signed-off-by: Erik Boasson --- .../core/src/dds_security_serialize.c | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/security/core/src/dds_security_serialize.c b/src/security/core/src/dds_security_serialize.c index 0e92790..7e182df 100644 --- a/src/security/core/src/dds_security_serialize.c +++ b/src/security/core/src/dds_security_serialize.c @@ -627,14 +627,20 @@ DDS_Security_Deserialize_PropertySeq( DDS_Security_Deserializer dser, DDS_Security_PropertySeq *seq) { + /* A well-formed CDR string is length + content including terminating 0, length is + 4 bytes and 4-byte aligned, so the minimum length for a non-empty property + sequence is 4+1+(3 pad)+4+1 = 13 bytes. Just use 8 because it is way faster + and just as good for checking that the length value isn't completely ridiculous. */ + const uint32_t minpropsize = (uint32_t) (2 * sizeof (uint32_t)); int r = 1; uint32_t i; if (!DDS_Security_Deserialize_uint32_t(dser, &seq->_length)) { return 0; - } - - if (seq->_length > 0) { + } else if (seq->_length > dser->remain / minpropsize) { + seq->_length = 0; + return 0; + } else if (seq->_length > 0) { seq->_buffer = DDS_Security_PropertySeq_allocbuf(seq->_length); for (i = 0; i < seq->_length && r; i++) { r = DDS_Security_Deserialize_Property(dser, &seq->_buffer[i]); @@ -649,14 +655,19 @@ DDS_Security_Deserialize_BinaryPropertySeq( DDS_Security_Deserializer dser, DDS_Security_BinaryPropertySeq *seq) { + /* A well-formed CDR string + a well-formed octet sequence: 4+1+(3 pad)+4 = 12 bytes. + Just use 8 because it is way faster and just as good for checking that the length + value isn't completely ridiculous. */ + const uint32_t minpropsize = (uint32_t) (2 * sizeof (uint32_t)); int r = 1; uint32_t i; if (!DDS_Security_Deserialize_uint32_t(dser, &seq->_length)) { return 0; - } - - if (seq->_length > 0) { + } else if (seq->_length > dser->remain / minpropsize) { + seq->_length = 0; + return 0; + } else if (seq->_length > 0) { seq->_buffer = DDS_Security_BinaryPropertySeq_allocbuf(seq->_length); for (i = 0; i < seq->_length && r; i++) { r = DDS_Security_Deserialize_BinaryProperty(dser, &seq->_buffer[i]); From 4447fb87ee2acb283bf8b7eaa5b60ab2f38f210f Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 7 May 2020 09:33:25 +0200 Subject: [PATCH 218/238] No reason to prevent rediscovery for 10s by default Signed-off-by: Erik Boasson --- docs/manual/options.md | 2 +- etc/cyclonedds.rnc | 2 +- etc/cyclonedds.xsd | 2 +- src/core/ddsi/src/q_config.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/manual/options.md b/docs/manual/options.md index 8341f3d..f8a7aa5 100644 --- a/docs/manual/options.md +++ b/docs/manual/options.md @@ -1349,7 +1349,7 @@ is therefore recommended to set it to at least several seconds. Valid values are finite durations with an explicit unit or the keyword 'inf' for infinity. Recognised units: ns, us, ms, s, min, hr, day. -The default value is: "10s". +The default value is: "0s". #### //CycloneDDS/Domain/Internal/RediscoveryBlacklistDuration[@enforce] diff --git a/etc/cyclonedds.rnc b/etc/cyclonedds.rnc index e6ce80d..0898f32 100644 --- a/etc/cyclonedds.rnc +++ b/etc/cyclonedds.rnc @@ -1113,7 +1113,7 @@ is therefore recommended to set it to at least several seconds.

    Valid values are finite durations with an explicit unit or the keyword 'inf' for infinity. Recognised units: ns, us, ms, s, min, hr, -day.

    The default value is: "10s".

    """ ] ] +day.

    The default value is: "0s".

    """ ] ] element RediscoveryBlacklistDuration { [ a:documentation [ xml:lang="en" """

    This attribute controls whether the configured time during which diff --git a/etc/cyclonedds.xsd b/etc/cyclonedds.xsd index cca1c3c..8214bf1 100644 --- a/etc/cyclonedds.xsd +++ b/etc/cyclonedds.xsd @@ -1475,7 +1475,7 @@ is therefore recommended to set it to at least several seconds.</p> <p>Valid values are finite durations with an explicit unit or the keyword 'inf' for infinity. Recognised units: ns, us, ms, s, min, hr, -day.</p><p>The default value is: &quot;10s&quot;.</p> +day.</p><p>The default value is: &quot;0s&quot;.</p> diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 6808f31..6bfb3de 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -728,7 +728,7 @@ static const struct cfgelem internal_cfgelems[] = { BLURB("

    Do not use.

    ") }, { LEAF("SendAsync"), 1, "false", ABSOFF(xpack_send_async), 0, uf_boolean, 0, pf_boolean, BLURB("

    This element controls whether the actual sending of packets occurs on the same thread that prepares them, or is done asynchronously by another thread.

    ") }, - { LEAF_W_ATTRS("RediscoveryBlacklistDuration", rediscovery_blacklist_duration_attrs), 1, "10s", ABSOFF(prune_deleted_ppant.delay), 0, uf_duration_inf, 0, pf_duration, + { LEAF_W_ATTRS("RediscoveryBlacklistDuration", rediscovery_blacklist_duration_attrs), 1, "0s", ABSOFF(prune_deleted_ppant.delay), 0, uf_duration_inf, 0, pf_duration, BLURB("

    This element controls for how long a remote participant that was previously deleted will remain on a blacklist to prevent rediscovery, giving the software on a node time to perform any cleanup actions it needs to do. To some extent this delay is required internally by DDSI2E, but in the default configuration with the 'enforce' attribute set to false, DDSI2E will reallow rediscovery as soon as it has cleared its internal administration. Setting it to too small a value may result in the entry being pruned from the blacklist before DDSI2E is ready, it is therefore recommended to set it to at least several seconds.

    ") }, { LEAF_W_ATTRS("MultipleReceiveThreads", multiple_recv_threads_attrs), 1, "default", ABSOFF(multiple_recv_threads), 0, uf_boolean_default, 0, pf_boolean_default, BLURB("

    This element controls whether all traffic is handled by a single receive thread (false) or whether multiple receive threads may be used to improve latency (true). By default it is disabled on Windows because it appears that one cannot count on being able to send packets to oneself, which is necessary to stop the thread during shutdown. Currently multiple receive threads are only used for connectionless transport (e.g., UDP) and ManySocketsMode not set to single (the default).

    ") }, From db4f96dc02eeaeabbdfe3399e697644c59dc666c Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 11 May 2020 16:00:45 +0200 Subject: [PATCH 219/238] Add DDS_STATUS_ID_MAX for ranging over status ids Signed-off-by: Erik Boasson --- src/core/ddsc/include/dds/dds.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/ddsc/include/dds/dds.h b/src/core/ddsc/include/dds/dds.h index 8383b06..2a63fbb 100644 --- a/src/core/ddsc/include/dds/dds.h +++ b/src/core/ddsc/include/dds/dds.h @@ -90,6 +90,7 @@ typedef enum dds_status_id { DDS_PUBLICATION_MATCHED_STATUS_ID, DDS_SUBSCRIPTION_MATCHED_STATUS_ID } dds_status_id_t; +#define DDS_STATUS_ID_MAX (DDS_SUBSCRIPTION_MATCHED_STATUS_ID) /** Another topic exists with the same name but with different characteristics. */ #define DDS_INCONSISTENT_TOPIC_STATUS (1u << DDS_INCONSISTENT_TOPIC_STATUS_ID) From 7897dff9ce39110edc23dd14b0c9943529c50e64 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 11 May 2020 16:01:48 +0200 Subject: [PATCH 220/238] Merging listeners: only when source is set This leaves the argument pointer in the destination unchanged, rather than resetting it to an irrelevant value. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_listener.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/ddsc/src/dds_listener.c b/src/core/ddsc/src/dds_listener.c index eee9ef6..ae71ec9 100644 --- a/src/core/ddsc/src/dds_listener.c +++ b/src/core/ddsc/src/dds_listener.c @@ -90,8 +90,7 @@ void dds_listener_copy(dds_listener_t * __restrict dst, const dds_listener_t * _ static bool dds_combine_listener_merge (uint32_t inherited, void (*dst)(void), void (*src)(void)) { (void)inherited; - (void)src; - return dst == 0; + return dst == 0 && src != 0; } static bool dds_combine_listener_override_inherited (uint32_t inherited, void (*dst)(void), void (*src)(void)) From d5d44cc8be3538f72c18d532ff803df19de19f94 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 7 May 2020 09:36:20 +0200 Subject: [PATCH 221/238] Refactor oneliner listener tests The code for executing one-liner tests might be more generally useful. Signed-off-by: Erik Boasson --- src/core/ddsc/tests/CMakeLists.txt | 4 +- src/core/ddsc/tests/listener.c | 969 ++--------- src/core/ddsc/tests/test_oneliner.c | 1780 +++++++++++++++++++++ src/core/ddsc/tests/test_oneliner.h | 326 ++++ src/core/ddsi/include/dds/ddsi/q_entity.h | 2 +- 5 files changed, 2200 insertions(+), 881 deletions(-) create mode 100644 src/core/ddsc/tests/test_oneliner.c create mode 100644 src/core/ddsc/tests/test_oneliner.h diff --git a/src/core/ddsc/tests/CMakeLists.txt b/src/core/ddsc/tests/CMakeLists.txt index 0942ce3..bde5eae 100644 --- a/src/core/ddsc/tests/CMakeLists.txt +++ b/src/core/ddsc/tests/CMakeLists.txt @@ -59,7 +59,9 @@ set(ddsc_test_sources "write_various_types.c" "writer.c" "test_common.c" - "test_common.h") + "test_common.h" + "test_oneliner.c" + "test_oneliner.h") if(ENABLE_LIFESPAN) list(APPEND ddsc_test_sources "lifespan.c") diff --git a/src/core/ddsc/tests/listener.c b/src/core/ddsc/tests/listener.c index 6738cf7..2bd4112 100644 --- a/src/core/ddsc/tests/listener.c +++ b/src/core/ddsc/tests/listener.c @@ -18,23 +18,14 @@ #include "dds/ddsrt/string.h" #include "dds/ddsrt/environ.h" #include "test_common.h" - -static ddsrt_mutex_t g_mutex; -static ddsrt_cond_t g_cond; -static uint32_t cb_called; -static dds_entity_t cb_topic, cb_writer, cb_reader, cb_subscriber; +#include "test_oneliner.h" #define DEFINE_STATUS_CALLBACK(name, NAME, kind) \ - static dds_##name##_status_t cb_##name##_status; \ static void name##_cb (dds_entity_t kind, const dds_##name##_status_t status, void *arg) \ { \ (void) arg; \ - ddsrt_mutex_lock (&g_mutex); \ - cb_##kind = kind; \ - cb_##name##_status = status; \ - cb_called |= DDS_##NAME##_STATUS; \ - ddsrt_cond_broadcast (&g_cond); \ - ddsrt_mutex_unlock (&g_mutex); \ + (void) kind; \ + (void) status; \ } DEFINE_STATUS_CALLBACK (inconsistent_topic, INCONSISTENT_TOPIC, topic) @@ -51,48 +42,14 @@ DEFINE_STATUS_CALLBACK (subscription_matched, SUBSCRIPTION_MATCHED, reader) static void data_on_readers_cb (dds_entity_t subscriber, void *arg) { + (void) subscriber; (void) arg; - ddsrt_mutex_lock (&g_mutex); - cb_subscriber = subscriber; - cb_called |= DDS_DATA_ON_READERS_STATUS; - ddsrt_cond_broadcast (&g_cond); - ddsrt_mutex_unlock (&g_mutex); } static void data_available_cb (dds_entity_t reader, void *arg) { - (void)arg; - ddsrt_mutex_lock (&g_mutex); - cb_reader = reader; - cb_called |= DDS_DATA_AVAILABLE_STATUS; - ddsrt_cond_broadcast (&g_cond); - ddsrt_mutex_unlock (&g_mutex); -} - -static void dummy_data_on_readers_cb (dds_entity_t subscriber, void *arg) -{ - (void)subscriber; - (void)arg; -} - -static void dummy_data_available_cb (dds_entity_t reader, void *arg) -{ - (void)reader; - (void)arg; -} - -static void dummy_subscription_matched_cb (dds_entity_t reader, const dds_subscription_matched_status_t status, void *arg) -{ - (void)reader; - (void)status; - (void)arg; -} - -static void dummy_liveliness_changed_cb (dds_entity_t reader, const dds_liveliness_changed_status_t status, void *arg) -{ - (void)reader; - (void)status; - (void)arg; + (void) reader; + (void) arg; } static void dummy_cb (void) @@ -303,796 +260,7 @@ CU_Test(ddsc_listener, getters_setters) #undef ASSERT_CALLBACK_EQUAL -/************************************************** - **** **** - **** programmable listener checker **** - **** **** - **************************************************/ - -// These had better match the corresponding type definitions! -// n uint32_t ...count -// c int32_t ...count_change -// I instance handle of a data instance -// P uint32_t QoS policy ID -// E instance handle of an entity -// R sample_rejected_status_kind -static const struct { - size_t size; // size of status struct - const char *desc; // description of status struct - uint32_t mask; // status mask, bit in "cb_called" - const dds_entity_t *cb_entity; // which cb_... entity to look at - const void *cb_status; // cb_..._status to look at -} lldesc[] = { - { 0, NULL, DDS_DATA_AVAILABLE_STATUS, &cb_reader, NULL }, // data available - { 0, NULL, DDS_DATA_ON_READERS_STATUS, &cb_subscriber, NULL }, // data on readers - { sizeof (dds_inconsistent_topic_status_t), "nc", DDS_INCONSISTENT_TOPIC_STATUS, &cb_topic, &cb_inconsistent_topic_status }, - { sizeof (dds_liveliness_changed_status_t), "nnccE", DDS_LIVELINESS_CHANGED_STATUS, &cb_reader, &cb_liveliness_changed_status }, - { sizeof (dds_liveliness_lost_status_t), "nc", DDS_LIVELINESS_LOST_STATUS, &cb_writer, &cb_liveliness_lost_status }, - { sizeof (dds_offered_deadline_missed_status_t), "ncI", DDS_OFFERED_DEADLINE_MISSED_STATUS, &cb_writer, &cb_offered_deadline_missed_status }, - { sizeof (dds_offered_incompatible_qos_status_t), "ncP", DDS_OFFERED_INCOMPATIBLE_QOS_STATUS, &cb_writer, &cb_offered_incompatible_qos_status }, - { sizeof (dds_publication_matched_status_t), "ncncE", DDS_PUBLICATION_MATCHED_STATUS, &cb_writer, &cb_publication_matched_status }, - { sizeof (dds_requested_deadline_missed_status_t), "ncI", DDS_REQUESTED_DEADLINE_MISSED_STATUS, &cb_reader, &cb_requested_deadline_missed_status }, - { sizeof (dds_requested_incompatible_qos_status_t), "ncP", DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS, &cb_reader, &cb_requested_incompatible_qos_status }, - { sizeof (dds_sample_lost_status_t), "nc", DDS_SAMPLE_LOST_STATUS, &cb_reader, &cb_sample_lost_status }, - { sizeof (dds_sample_rejected_status_t), "ncRI", DDS_SAMPLE_REJECTED_STATUS, &cb_reader, &cb_sample_rejected_status }, - { sizeof (dds_subscription_matched_status_t), "ncncE", DDS_SUBSCRIPTION_MATCHED_STATUS, &cb_reader, &cb_subscription_matched_status } -}; - -static const void *advance (const void *status, size_t *off, char code) -{ -#define alignof(type_) offsetof (struct { char c; type_ d; }, d) - size_t align = 1, size = 1; - switch (code) - { - case 'n': case 'c': case 'P': - align = alignof (uint32_t); size = sizeof (uint32_t); - break; - case 'E': case 'I': - align = alignof (dds_instance_handle_t); size = sizeof (dds_instance_handle_t); - break; - case 'R': - align = alignof (dds_sample_rejected_status_kind); size = sizeof (dds_sample_rejected_status_kind); - break; - default: - abort (); - } -#undef alignof - *off = (*off + align - 1) & ~(align - 1); - const void *p = (const char *) status + *off; - *off += size; - return p; -} - -static void get_status (int ll, dds_entity_t ent, void *status) -{ - dds_return_t ret; - switch (ll) - { - case 2: ret = dds_get_inconsistent_topic_status (ent, status); break; - case 3: ret = dds_get_liveliness_changed_status (ent, status); break; - case 4: ret = dds_get_liveliness_lost_status (ent, status); break; - case 5: ret = dds_get_offered_deadline_missed_status (ent, status); break; - case 6: ret = dds_get_offered_incompatible_qos_status (ent, status); break; - case 7: ret = dds_get_publication_matched_status (ent, status); break; - case 8: ret = dds_get_requested_deadline_missed_status (ent, status); break; - case 9: ret = dds_get_requested_incompatible_qos_status (ent, status); break; - case 10: ret = dds_get_sample_lost_status (ent, status); break; - case 11: ret = dds_get_sample_rejected_status (ent, status); break; - case 12: ret = dds_get_subscription_matched_status (ent, status); break; - default: abort (); - } - CU_ASSERT_FATAL (ret == 0); -} - -static void assert_status_change_fields_are_0 (int ll, dds_entity_t ent) -{ - if (lldesc[ll].desc) - { - const char *d = lldesc[ll].desc; - void *status = malloc (lldesc[ll].size); - get_status (ll, ent, status); - size_t off = 0; - while (*d) - { - const uint32_t *p = advance (status, &off, *d); - if (*d == 'c') - CU_ASSERT_FATAL (*p == 0); - d++; - } - assert (off <= lldesc[ll].size); - free (status); - } -} - -static int getentity (const char *tok, bool *isbang, bool *ishash) -{ - static const char *known = "PRWrstwxy"; - const char *p; - if (isbang) - *isbang = false; - if (ishash) - *ishash = false; - if ((p = strchr (known, *tok)) == NULL) - return -1; - int ent = (int) (p - known); - if (*++tok == 0) - return ent; - if (*tok == '\'') - { - ent += (int) strlen (known); - tok++; - } - while (*tok == '!' || *tok == '#') - { - if (strchr (known + 3, *p) == NULL) - return -1; // only readers, writers - if (*tok == '!' && isbang) - *isbang = true; - else if (*tok == '#' && ishash) - *ishash = true; - tok++; - } - return (*tok == 0) ? ent : -1; -} - -static int getlistener (const char *tok, bool *isbang) -{ - // note: sort order is on full name (so sample rejected precedes subscription matched) - static const char *ls[] = { - "da", "dor", "it", "lc", "ll", "odm", "oiq", "pm", "rdm", "riq", "sl", "sr", "sm" - }; - if (isbang) - *isbang = false; - for (size_t i = 0; i < sizeof (ls) / sizeof (*ls); i++) - { - size_t n = strlen (ls[i]); - if (strncmp (tok, ls[i], n) == 0 && (tok[n] == 0 || tok[n+1] == ',')) - { - if (isbang) - *isbang = (tok[n] == '!'); - return (int) i; - } - } - return -1; -} - -struct ents { - dds_entity_t es[2 * 9]; - dds_entity_t tps[2]; - dds_entity_t doms[2]; - dds_instance_handle_t esi[2 * 9]; - // built-in topic readers for cross-referencing instance handles - dds_entity_t pubrd[2]; - dds_entity_t subrd[2]; -}; - -static void make_participant (struct ents *es, const char *topicname, int ent, const dds_qos_t *qos, dds_listener_t *list) -{ - const dds_domainid_t domid = (ent < 9) ? 0 : 1; - char *conf = ddsrt_expand_envvars ("${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}0", domid); - printf ("create domain %"PRIu32, domid); - fflush (stdout); - es->doms[domid] = dds_create_domain (domid, conf); - CU_ASSERT_FATAL (es->doms[domid] > 0); - ddsrt_free (conf); - printf (" create participant P%s", (ent < 9) ? "" : "'"); - fflush (stdout); - es->es[ent] = dds_create_participant (domid, NULL, list); - CU_ASSERT_FATAL (es->es[ent] > 0); - es->tps[domid] = dds_create_topic (es->es[ent], &Space_Type1_desc, topicname, qos, NULL); - CU_ASSERT_FATAL (es->tps[domid] > 0); - - // Create the built-in topic readers with a dummy listener to avoid any event (data available comes to mind) - // from propagating to the normal data available listener, in case it has been set on the participant. - // - // - dummy_cb aborts when it is invoked, but all reader-related listeners that can possibly trigger are set - // separately (incompatible qos, deadline missed, sample lost and sample rejected are all impossible by - // construction) - // - regarding data_on_readers: Cyclone handles listeners installed on an ancestor by *inheriting* them, - // rather than by walking up ancestor chain. Setting data_on_readers on the reader therefore overrides the - // listener set on the subscriber. It is a nice feature! - dds_listener_t *dummylist = dds_create_listener (NULL); - set_all_const (dummylist, dummy_cb); - dds_lset_data_available (dummylist, dummy_data_available_cb); - dds_lset_data_on_readers (dummylist, dummy_data_on_readers_cb); - dds_lset_subscription_matched (dummylist, dummy_subscription_matched_cb); - dds_lset_liveliness_changed (dummylist, dummy_liveliness_changed_cb); - es->pubrd[domid] = dds_create_reader (es->es[ent], DDS_BUILTIN_TOPIC_DCPSPUBLICATION, NULL, dummylist); - CU_ASSERT_FATAL (es->pubrd[domid] > 0); - es->subrd[domid] = dds_create_reader (es->es[ent], DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, dummylist); - CU_ASSERT_FATAL (es->subrd[domid] > 0); - dds_delete_listener (dummylist); - printf ("pubrd %"PRId32" subrd %"PRId32" sub %"PRId32"\n", es->pubrd[domid], es->subrd[domid], dds_get_parent (es->pubrd[domid])); -} - -static void make_entity1 (struct ents *es, const char *topicname, int ent, bool isbang, bool ishash, const dds_qos_t *qos, dds_qos_t *rwqos, dds_listener_t *list) -{ - dds_return_t ret; - switch (ent) - { - case 0: case 9: - make_participant (es, topicname, ent, qos, list); - break; - case 1: case 10: - if (es->es[ent-1] == 0) - { - printf ("["); - make_entity1 (es, topicname, ent-1, false, false, qos, rwqos, NULL); - printf ("] "); - } - printf ("create subscriber R%s", (ent < 9) ? "" : "'"); - fflush (stdout); - es->es[ent] = dds_create_subscriber (es->es[ent-1], NULL, list); - break; - case 2: case 11: - if (es->es[ent-2] == 0) - { - printf ("["); - make_entity1 (es, topicname, ent-2, false, false, qos, rwqos, NULL); - printf ("] "); - } - printf ("create publisher W%s", (ent < 9) ? "" : "'"); - fflush (stdout); - es->es[ent] = dds_create_publisher (es->es[ent-2], NULL, list); - break; - case 3: case 4: case 5: case 12: case 13: case 14: - if (es->es[ent < 9 ? 1 : 10] == 0) - { - printf ("["); - make_entity1 (es, topicname, ent < 9 ? 1 : 10, false, false, qos, rwqos, NULL); - printf ("] "); - } - printf ("create %s reader %c%s", isbang ? "best-effort" : "reliable", 'r' + (ent < 9 ? ent-3 : ent-12), (ent < 9) ? "" : "'"); - fflush (stdout); - dds_reset_qos (rwqos); - if (isbang) - dds_qset_reliability (rwqos, DDS_RELIABILITY_BEST_EFFORT, DDS_MSECS (100)); - if (ishash) - dds_qset_resource_limits (rwqos, 1, DDS_LENGTH_UNLIMITED, DDS_LENGTH_UNLIMITED); - es->es[ent] = dds_create_reader (es->es[ent < 9 ? 1 : 10], es->tps[ent < 9 ? 0 : 1], rwqos, list); - break; - case 6: case 7: case 8: case 15: case 16: case 17: - if (es->es[ent < 9 ? 2 : 11] == 0) - { - printf ("["); - make_entity1 (es, topicname, ent < 9 ? 2 : 11, false, false, qos, rwqos, NULL); - printf ("] "); - } - printf ("create %s writer %c%s", isbang ? "best-effort" : "reliable", 'w' + (ent < 9 ? ent-6 : ent-15), (ent < 9) ? "" : "'"); - fflush (stdout); - dds_reset_qos (rwqos); - if (isbang) - dds_qset_reliability (rwqos, DDS_RELIABILITY_BEST_EFFORT, DDS_MSECS (100)); - if (ishash) - dds_qset_resource_limits (rwqos, 1, DDS_LENGTH_UNLIMITED, DDS_LENGTH_UNLIMITED); - es->es[ent] = dds_create_writer (es->es[ent < 9 ? 2 : 11], es->tps[ent < 9 ? 0 : 1], rwqos, list); - break; - default: - abort (); - } - printf (" = %"PRId32, es->es[ent]); - fflush (stdout); - CU_ASSERT_FATAL (es->es[ent] > 0); - ret = dds_get_instance_handle (es->es[ent], &es->esi[ent]); - //printf (" %"PRIx64, es->esi[ent]); - //fflush (stdout); - CU_ASSERT_FATAL (ret == 0); -} - -static void make_entity (struct ents *es, const char *topicname, int ent, bool isbang, bool ishash, const dds_qos_t *qos, dds_qos_t *rwqos, dds_listener_t *list) -{ - make_entity1 (es, topicname, ent, isbang, ishash, qos, rwqos, list); - printf ("\n"); -} - -static char *strsep_noempty (char **cursor, const char *sep) -{ - char *tok; - while ((tok = ddsrt_strsep (cursor, sep)) != NULL && *tok == 0) { } - return tok; -} - -static dds_instance_handle_t lookup_insthandle (const struct ents *es, int ent, int ent1) -{ - // if both are in the same domain, it's easy - if (ent / 9 == ent1 / 9) - return es->esi[ent1]; - else - { - // if they aren't ... find GUID from instance handle in the one domain, - // then find instance handle for GUID in the other - dds_entity_t rd1 = 0, rd2 = 0; - switch (ent1) - { - case 3: case 4: case 5: rd1 = es->subrd[0]; rd2 = es->subrd[1]; break; - case 12: case 13: case 14: rd1 = es->subrd[1]; rd2 = es->subrd[0]; break; - case 6: case 7: case 8: rd1 = es->pubrd[0]; rd2 = es->pubrd[1]; break; - case 15: case 16: case 17: rd1 = es->pubrd[1]; rd2 = es->pubrd[0]; break; - default: abort (); - } - - dds_return_t ret; - dds_builtintopic_endpoint_t keysample; - //printf ("(in %"PRId32" %"PRIx64" -> ", rd1, es->esi[ent1]); - //fflush (stdout); - ret = dds_instance_get_key (rd1, es->esi[ent1], &keysample); - CU_ASSERT_FATAL (ret == 0); - // In principle, only key fields are set in sample returned by get_key; - // in the case of a built-in topic that is extended to the participant - // key. The qos and topic/type names should not be set, and there is no - // (therefore) memory allocated for the sample. - CU_ASSERT_FATAL (keysample.qos == NULL); - CU_ASSERT_FATAL (keysample.topic_name == NULL); - CU_ASSERT_FATAL (keysample.type_name == NULL); - //for (size_t j = 0; j < sizeof (keysample.key.v); j++) - // printf ("%s%02x", (j > 0 && j % 4 == 0) ? ":" : "", keysample.key.v[j]); - const dds_instance_handle_t ih = dds_lookup_instance (rd2, &keysample); - CU_ASSERT_FATAL (ih != 0); - //printf (" -> %"PRIx64")", ih); - //fflush (stdout); - return ih; - } -} - -static void checkstatus (int ll, const struct ents *es, int ent, const char *args, const void *status) -{ - DDSRT_WARNING_MSVC_OFF(4996); // use of sscanf triggers a warning - if (*args == 0) - return; - if (*args++ != '(') - abort (); - assert (lldesc[ll].desc != NULL); - const char *d = lldesc[ll].desc; - const char *sep = "("; - size_t off = 0; - while (*d) - { - const void *p = advance (status, &off, *d); - char str[32]; - unsigned u; - int i, pos = -1; - switch (*d) - { - case 'n': - if (sscanf (args, "%u%n", &u, &pos) != 1 || (args[pos] != ',' && args[pos] != ')')) - abort (); - printf ("%s%"PRIu32" %u", sep, *(uint32_t *)p, u); fflush (stdout); - CU_ASSERT_FATAL (*(uint32_t *)p == u); - break; - case 'c': - if (sscanf (args, "%d%n", &i, &pos) != 1 || (args[pos] != ',' && args[pos] != ')')) - abort (); - printf ("%s%"PRId32" %d", sep, *(int32_t *)p, i); fflush (stdout); - CU_ASSERT_FATAL (*(int32_t *)p == i); - break; - case 'P': // policy id: currently fixed at reliability - pos = -1; // not actually consuming an argument - printf ("%s%"PRIu32" %d", sep, *(uint32_t *)p, (int) DDS_RELIABILITY_QOS_POLICY_ID); fflush (stdout); - CU_ASSERT_FATAL (*(uint32_t *)p == (uint32_t) DDS_RELIABILITY_QOS_POLICY_ID); - break; - case 'R': - if (sscanf (args, "%31[^,)]%n", str, &pos) != 1 || (args[pos] != ',' && args[pos] != ')')) - abort (); - if (strcmp (str, "i") == 0) - i = (int) DDS_REJECTED_BY_INSTANCES_LIMIT; - else if (strcmp (str, "s") == 0) - i = (int) DDS_REJECTED_BY_SAMPLES_LIMIT; - else if (strcmp (str, "spi") == 0) - i = (int) DDS_REJECTED_BY_SAMPLES_PER_INSTANCE_LIMIT; - else - abort (); - printf ("%s%d %d", sep, (int) *(dds_sample_rejected_status_kind *)p, i); fflush (stdout); - CU_ASSERT_FATAL (*(dds_sample_rejected_status_kind *)p == (dds_sample_rejected_status_kind) i); - break; - case 'I': // instance handle is too complicated - pos = -1; // not actually consuming an argument - break; - case 'E': { - int ent1 = -1; - dds_instance_handle_t esi1 = 0; - if (sscanf (args, "%31[^,)]%n", str, &pos) != 1 || (args[pos] != ',' && args[pos] != ')')) - abort (); - if (strcmp (str, "*") != 0 && (ent1 = getentity (str, NULL, NULL)) < 0) - abort (); - if (ent1 != -1) - esi1 = lookup_insthandle (es, ent, ent1); - printf ("%s%"PRIx64" %"PRIx64, sep, *(dds_instance_handle_t *)p, esi1); fflush (stdout); - CU_ASSERT_FATAL (ent1 == -1 || *(dds_instance_handle_t *)p == esi1); - break; - } - default: abort (); - } - args += pos + 1; - sep = ", "; - d++; - } - printf (")"); - assert (*args == 0); - assert (off <= lldesc[ll].size); - DDSRT_WARNING_MSVC_ON(4996); -} - -/** @brief run a "test" consisting of a sequence of simplish operations - * - * This operation takes a test description, really a program in a bizarre syntax, and executes it. Any failures, - * be it because of error codes coming out of the Cyclone calls or expected values being wrong cause it to fail - * the test via CU_ASSERT_FATAL. While it is doing this, it outputs the test steps to stdout including some - * actual values. An invalid program is mostly reported by calling abort(). It is geared towards checking for - * listener invocations and the effects on statuses. - * - * Entities in play: - * - * - participants: P P' - * - subscribers: R R' - * - publishers: W W' - * - readers: r s t r' s' t' - * - writers: w x y w' x' y' - * - * The unprimed ones exist in domain 0, the primed ones in domain 1 (but configured such that it talks to - * domain 0), so that network-related listener invocations can be checked as well. - * - * The first mention of an entity creates it as well as its ancestors. Implicitly created ancestors always have - * standard QoS and have no listeners. There is one topic that is created implicitly when the participant is - * created. - * - * Standard QoS is: default + reliable (100ms), by-source-timestamp, keep-all. - * The QoS of a reader/writer can be altered at the first mention of it by suffixing its name with "!" and/or "#" - * (the apostrophe is part of the name, so w#! or r'! are valid). Those suffixes are ignored if the entity - * already exists. - * - * A program consists of a sequence of operations separated by whitespace, ';' or '/' (there is no meaning to the - * separators, they exist to allow visual grouping): - * - * PROGRAM ::= (OP (\s+|[/;])*)* - * - * OP ::= (LISTENER)* ENTITY-NAME - * if entity ENTITY-NAME does not exist: - * creates the entity with the given listeners installed - * else - * changes the entity's listeners to the specified ones - * (see above for the valid ENTITY-NAMEs) - * | -ENTITY-NAME - * deletes the specified entity - * | WRITE-LIKE[fail][@DT] KEY - * writes/disposes/unregisters key KEY (an integer), if "fail" is appended, the - * expectation is that it fails with a timeout, if @DT is appended, the timestamp is the - * start time of the test +
    s rather than the current time; DT is a floating-point - * number - * | READ-LIKE[(A,B))] - * reads/takes at most 10 samples, counting the number of valid and invalid samples seen - * and checking it against A and B if given - * | ?LISTENER[(ARGS)] - * waits until the specified listener has been invoked on using a flag set - * by the listener function, resets the flag and verifies that neither the entity status - * bit nor the "change" fields in the various statuses were set - * ARGS is used to check the status argument most recently passed to the listener: - * it (A,B) verifies count and change match A and B, policy matches RELIABILITY - * lc (A,B,C,D,E) verifies that alive and not-alive counts match A and B, that - * alive and not-alive changes match C and D and that the last handle matches - * E if an entity name (ignored if E = "*") - * ll (A,B) verifies count and change match A and B - * odm (A,B) verifies count and change match A and B, last handle is ignored - * oiq (A,B) verifies that total count and change match A and B and that the - * mismatching QoS is reliability (the only one that can for now) - * pm (A,B,C,D,E) verifies that total count and change match A and B, that - * current count and change match C and D and that the last handle matches E - * if an entity name (ignored if E = "*") - * rdm see odm - * riq see oiq - * sl (A,B) verifies that total count and change match A and B - * sr (A,B,C) verifies total count and change match A and B, and that the reason - * matches C (one of "s" for samples, "i" for instances, "spi" for samples - * per instance) - * sm see pm - * | ?!LISTENER - * (not listener) tests that LISTENER has not been invoked since last reset - * | sleep D - * delay program execution for D s (D is a floating-point number) - * WRITE-LIKE ::= wr write - * | wrdisp write-dispose - * | disp dispose - * | unreg unregister - * READ-LIKE ::= read dds_read (so any state) - * | take dds_take (so any state) - * LISTENER ::= da data available (acts on a reader) - * | dor data on readers (acts on a subcsriber) - * | it incompatible topic (acts on a topic) - * | lc liveliness changed (acts on a reader) - * | ll liveliness lost (acts on a writer) - * | odm offered deadline missed (acts on a writer) - * | oiq offered incompatible QoS (acts on a writer) - * | pm publication matched (acts on a writer) - * | rdm requested deadline missed (acts on a reader) - * | riq requested incompatible QoS (acts on a reader) - * | sl sample lost (acts on a reader) - * | sr sample rejected (acts on a reader) - * | sm subscription matched (acts on a reader) - * - * All entities share the listeners with their global state. Only the latest invocation is visible. - * - * @param[in] ops Program to execute. - */ -static void dotest (const char *ops) -{ - DDSRT_WARNING_MSVC_OFF(4996); // use of sscanf triggers a warning - static const char *sep = " /;\n\t\r\v"; - char *opscopy = ddsrt_strdup (ops), *cursor = opscopy, *tok; - struct ents es; - dds_return_t ret; - Space_Type1 sample; - char topicname[100]; - dds_qos_t *qos = dds_create_qos (), *rwqos = dds_create_qos (); - dds_listener_t *list = dds_create_listener (NULL); - const dds_time_t tref = dds_time (); - CU_ASSERT_FATAL (qos != NULL); - CU_ASSERT_FATAL (rwqos != NULL); - CU_ASSERT_FATAL (list != NULL); - dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_MSECS (100)); - dds_qset_destination_order (qos, DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP); - dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0); - memset (&es, 0, sizeof (es)); - memset (&sample, 0, sizeof (sample)); - - ddsrt_mutex_init (&g_mutex); - ddsrt_cond_init (&g_cond); - ddsrt_mutex_lock (&g_mutex); - cb_called = 0; - ddsrt_mutex_unlock (&g_mutex); - - create_unique_topic_name ("ddsc_listener_test", topicname, 100); - printf ("dotest: %s\n", ops); - printf ("topic: %s\n", topicname); - while ((tok = strsep_noempty (&cursor, sep)) != NULL) - { - int ent, ll; - bool isbang, ishash; - if ((ent = getentity (tok, &isbang, &ishash)) >= 0) - { - make_entity (&es, topicname, ent, isbang, ishash, qos, rwqos, NULL); - } - else if (*tok == '-' && (ent = getentity (tok + 1, NULL, NULL)) >= 0) - { - // delete deliberately leaves the instance handle in place for checking - // the publication/subscription handle in subscription matched/publication - // matched for a lost match - printf ("delete %"PRId32"\n", es.es[ent]); - ret = dds_delete (es.es[ent]); - CU_ASSERT_FATAL (ret == 0); - es.es[ent] = 0; - } - else if ((ll = getlistener (tok, &isbang)) >= 0) - { - printf ("set listener:"); - dds_reset_listener (list); - do { - printf (" %s", tok); - switch (ll) - { - case 0: dds_lset_data_available (list, isbang ? 0 : data_available_cb); break; - case 1: dds_lset_data_on_readers (list, isbang ? 0 : data_on_readers_cb); break; - case 2: dds_lset_inconsistent_topic (list, isbang ? 0: inconsistent_topic_cb); break; - case 3: dds_lset_liveliness_changed (list, isbang ? 0 : liveliness_changed_cb); break; - case 4: dds_lset_liveliness_lost (list, isbang ? 0 : liveliness_lost_cb); break; - case 5: dds_lset_offered_deadline_missed (list, isbang ? 0 : offered_deadline_missed_cb); break; - case 6: dds_lset_offered_incompatible_qos (list, isbang ? 0 : offered_incompatible_qos_cb); break; - case 7: dds_lset_publication_matched (list, isbang ? 0 : publication_matched_cb); break; - case 8: dds_lset_requested_deadline_missed (list, isbang ? 0 : requested_deadline_missed_cb); break; - case 9: dds_lset_requested_incompatible_qos (list, isbang ? 0 : requested_incompatible_qos_cb); break; - case 10: dds_lset_sample_lost (list, isbang ? 0 : sample_lost_cb); break; - case 11: dds_lset_sample_rejected (list, isbang ? 0 : sample_rejected_cb); break; - case 12: dds_lset_subscription_matched (list, isbang ? 0 : subscription_matched_cb); break; - default: abort (); - } - } while ((tok = strsep_noempty (&cursor, sep)) != NULL && (ll = getlistener (tok, &isbang)) >= 0); - if (tok == NULL || (ent = getentity (tok, &isbang, &ishash)) < 0) - abort (); - if (es.es[ent] == 0) - { - printf (" for "); - make_entity (&es, topicname, ent, isbang, ishash, qos, rwqos, list); - } - else - { - dds_listener_t *tmplist = dds_create_listener (NULL); - CU_ASSERT_FATAL (tmplist != NULL); - ret = dds_get_listener (es.es[ent], tmplist); - CU_ASSERT_FATAL (ret == 0); - dds_merge_listener (list, tmplist); - dds_delete_listener (tmplist); - printf (" on entity %"PRId32"\n", es.es[ent]); - ret = dds_set_listener (es.es[ent], list); - CU_ASSERT_FATAL (ret == 0); - } - } - else if (strncmp (tok, "wr", 2) == 0 || strncmp (tok, "disp", 4) == 0 || strncmp (tok, "unreg", 5) == 0) - { - dds_return_t (*fn) (dds_entity_t wr, const void *sample, dds_time_t ts) = 0; - double dt = 0.0; - dds_time_t ts = dds_time (); - char *cmd = tok; - bool expectfail = false; - int off, pos, key; - if ((tok = strsep_noempty (&cursor, sep)) == NULL) - abort (); - if (sscanf (tok, "%d%n", &key, &pos) != 1 || tok[pos] != 0) - abort (); - if ((tok = strsep_noempty (&cursor, sep)) == NULL || (ent = getentity (tok, &isbang, &ishash)) < 0) - abort (); - if (es.es[ent] == 0) - make_entity (&es, topicname, ent, isbang, ishash, qos, rwqos, NULL); - switch (cmd[0]) - { - case 'w': - if (strncmp (cmd + 2, "disp", 4) == 0) { - off = 6; fn = dds_writedispose_ts; - } else { - off = 2; fn = dds_write_ts; - } - break; - case 'd': off = 4; fn = dds_dispose_ts; break; - case 'u': off = 5; fn = dds_unregister_instance_ts; break; - default: abort (); - } - if (strncmp (cmd + off, "fail", 4) == 0) - { - expectfail = true; - off += 4; - } - if (cmd[off] == '@') - { - if (sscanf (cmd + off, "@%lf%n", &dt, &pos) != 1 || cmd[off + pos] != 0) - abort (); - ts = tref + (dds_time_t) (dt * 1e9); - } - sample.long_1 = key; - printf ("entity %"PRId32": %*.*s@%"PRId64".%09"PRId64" %d\n", es.es[ent], off, off, cmd, ts / DDS_NSECS_IN_SEC, ts % DDS_NSECS_IN_SEC, key); - ret = fn (es.es[ent], &sample, ts); - if (expectfail) { - CU_ASSERT_FATAL (ret == DDS_RETCODE_TIMEOUT); - } else { - CU_ASSERT_FATAL (ret == 0); - } - } - else if (strncmp (tok, "take", 4) == 0 || strncmp(tok, "read", 4) == 0) - { - char *args = (tok[4] ? tok + 4 : NULL); - int exp_nvalid = -1, exp_ninvalid = -1, pos; - dds_return_t (*fn) (dds_entity_t, void **buf, dds_sample_info_t *, size_t, uint32_t); - fn = (strncmp (tok, "take", 4) == 0) ? dds_take : dds_read; - assert (args == NULL || *args == '('); - if (args && (sscanf (args, "(%d,%d)%n", &exp_nvalid, &exp_ninvalid, &pos) != 2 || args[pos] != 0)) - abort (); - if ((tok = strsep_noempty (&cursor, sep)) == NULL || (ent = getentity (tok, &isbang, &ishash)) < 0) - abort (); - if (es.es[ent] == 0) - make_entity (&es, topicname, ent, isbang, ishash, qos, rwqos, NULL); - printf ("entity %"PRId32": %s", es.es[ent], (fn == dds_take) ? "take" : "read"); - fflush (stdout); - void *raw[10] = { NULL }; - dds_sample_info_t si[10]; - const uint32_t maxs = (uint32_t) (sizeof (raw) / sizeof (raw[0])); - int count[2] = { 0, 0 }; - ret = fn (es.es[ent], raw, si, maxs, maxs); - CU_ASSERT_FATAL (ret >= 0); - for (int32_t i = 0; i < ret; i++) - count[si[i].valid_data]++; - ret = dds_return_loan (es.es[ent], raw, ret); - CU_ASSERT_FATAL (ret == 0); - printf (" valid %d %d invalid %d %d\n", count[1], exp_nvalid, count[0], exp_ninvalid); - if (exp_nvalid >= 0) - CU_ASSERT_FATAL (count[1] == exp_nvalid); - if (exp_ninvalid >= 0) - CU_ASSERT_FATAL (count[0] == exp_ninvalid); - } - else if (tok[0] == '?') - { - const bool expectclear = (tok[1] == '!'); - const char *llname = tok + (expectclear ? 2 : 1); - char *checkargs; - if ((checkargs = strchr (llname, '(')) != NULL) - *checkargs = 0; // clear so getlistener groks the input - if ((ll = getlistener (llname, NULL)) < 0) - abort (); - if (expectclear) - { - printf ("listener %s: check not called", llname); - fflush (stdout); - ddsrt_mutex_lock (&g_mutex); - printf (" cb_called %"PRIx32" %s\n", cb_called, (cb_called & lldesc[ll].mask) == 0 ? "ok" : "fail"); - CU_ASSERT_FATAL ((cb_called & lldesc[ll].mask) == 0); - ddsrt_mutex_unlock (&g_mutex); - } - else - { - bool signalled = true; - uint32_t status; - if ((tok = strsep_noempty (&cursor, sep)) == NULL || (ent = getentity (tok, &isbang, &ishash)) < 0) - abort (); - if (es.es[ent] == 0) - make_entity (&es, topicname, ent, isbang, ishash, qos, rwqos, NULL); - if ((size_t) ll >= sizeof (lldesc) / sizeof (*lldesc)) - abort (); - printf ("listener %s: check called for entity %"PRId32, llname, es.es[ent]); - fflush (stdout); - ddsrt_mutex_lock (&g_mutex); - while ((cb_called & lldesc[ll].mask) == 0 && signalled) - signalled = ddsrt_cond_waitfor (&g_cond, &g_mutex, DDS_SECS (5)); - printf (" cb_called %"PRIx32" (%s)", cb_called, (cb_called & lldesc[ll].mask) != 0 ? "ok" : "fail"); - fflush (stdout); - CU_ASSERT_FATAL ((cb_called & lldesc[ll].mask) != 0); - printf (" cb_entity %"PRId32" %"PRId32" (%s)", *lldesc[ll].cb_entity, es.es[ent], (*lldesc[ll].cb_entity == es.es[ent]) ? "ok" : "fail"); - fflush (stdout); - CU_ASSERT_FATAL (*lldesc[ll].cb_entity == es.es[ent]); - if (!(es.doms[0] && es.doms[1])) - { - // FIXME: two domains: listener invocation happens on another thread and we can observe non-0 "change" fields - // they get updated, listener gets invoked, then they get reset -- pretty sure it is allowed by the spec, but - // not quite elegant - assert_status_change_fields_are_0 (ll, es.es[ent]); - } - if (checkargs && lldesc[ll].cb_status) - { - *checkargs = '('; // restore ( so checkargs function gets a more sensible input - checkstatus (ll, &es, ent, checkargs, lldesc[ll].cb_status); - } - printf ("\n"); - cb_called &= ~lldesc[ll].mask; - ddsrt_mutex_unlock (&g_mutex); - ret = dds_get_status_changes (es.es[ent], &status); - CU_ASSERT_FATAL (ret == 0); - CU_ASSERT_FATAL ((status & lldesc[ll].mask) == 0); - } - } - else if (strcmp (tok, "sleep") == 0) - { - if ((tok = strsep_noempty (&cursor, sep)) == NULL) - abort (); - double d; int pos; - if (sscanf (tok, "%lf%n", &d, &pos) != 1 || tok[pos] != 0) - abort (); - printf ("sleep %fs\n", d); - dds_sleepfor ((dds_duration_t) (d * 1e9)); - } - else - { - printf ("tok '%s': unrecognized\n", tok); - abort (); - } - } - - dds_delete_listener (list); - dds_delete_qos (rwqos); - dds_delete_qos (qos); - // prevent any listeners from being invoked so we can safely delete the - // mutex and the condition variable -- must do this going down the - // hierarchy, or listeners may remain set through inheritance - for (size_t i = 0; i < sizeof (es.es) / sizeof (es.es[0]); i++) - { - if (es.es[i]) - { - ret = dds_set_listener (es.es[i], NULL); - CU_ASSERT_FATAL (ret == 0); - } - } - ddsrt_mutex_destroy (&g_mutex); - ddsrt_cond_destroy (&g_cond); - for (size_t i = 0; i < sizeof (es.doms) / sizeof (es.doms[0]); i++) - { - if (es.doms[i]) - { - ret = dds_delete (es.doms[i]); - CU_ASSERT_FATAL (ret == 0); - } - } - ddsrt_free (opscopy); - DDSRT_WARNING_MSVC_ON(4996); -} - -/************************************************** - **** **** - **** listener invocation checks **** - **** **** - **************************************************/ +#define dotest(ops) CU_ASSERT_FATAL (test_oneliner (ops) > 0) CU_Test (ddsc_listener, propagation) { @@ -1102,10 +270,10 @@ CU_Test (ddsc_listener, propagation) // for it on the reader should prevent that from happening dotest ("da dor lc sm P ; ?!dor ?!da ?!sm ?!lc"); // writing data should trigger data-available unless data-on-readers is set - dotest ("da lc sm P ; r ; wr 0 w ; ?da r ?sm r ?lc r"); - dotest ("da dor lc sm P ; r ; wr 0 w ; ?!da ; ?dor R ?sm r ?lc r"); + dotest ("da lc sm P ; r ; wr w 0 ; ?da r ?sm r ?lc r"); + dotest ("da dor lc sm P ; r ; wr w 0 ; ?!da ; ?dor R ?sm r ?lc r"); // setting listeners after entity creation should work, too - dotest ("P W R ; dor P pm W sm R ; r w ; ?sm r ?pm w ; wr 0 w ; ?dor R ; ?!da"); + dotest ("P W R ; dor P pm W sm R ; r w ; ?sm r ?pm w ; wr w 0 ; ?dor R ; ?!da"); } CU_Test (ddsc_listener, matched) @@ -1116,6 +284,47 @@ CU_Test (ddsc_listener, matched) // across the network it should work just as well (matching happens on different threads for // remote & local entity creation, so it is meaningfully different test) dotest ("sm r pm w' ?pm w' ?sm r"); + + // Disconnect + reconnect; "deaf P" means the disconnect is asymmetrical: P no longer observes P' + // but P' still observes P. If r did not ACK the data before losing connectivity, w' will hold + // the data and it will be re-delivered after reconnecting, depending on QoS settings (the "..." + // allows for extra samples) and whether the instance was taken or not + // + // the uncertainty also means we don't really know how many "data available" events there will be + // and the "sleep 0.3" simply gives it a bit more time after the first event + dotest ("sm da r pm w' ; ?sm r ?pm w' ;" + " wr w' 1 ; ?da r take{(1,0,0)} r sleep 1;" + " deaf P ; ?sm(1,0,0,-1,w') r ?da r take{d1} r ; wr w' 2 ;" + " hearing P ; ?sm(2,1,1,1,w') r ?da r sleep 0.3 take{(2,0,0),...} r ; ?!pm"); + // same without taking the "dispose" after disconnect + // sample 1 will be delivered anew + dotest ("sm da r pm w' ; ?sm r ?pm w' ; wr w' 1 ; ?da r take{(1,0,0)} r ;" + " deaf P ; ?sm(1,0,0,-1,w') r ?da r ; wr w' 2 ;" + " hearing P ; ?sm(2,1,1,1,w') r ?da r sleep 0.3 take{d1,(2,0,0)} r ; ?!pm"); + + // if a volatile writer loses the reader temporarily, the data won't show up + dotest ("sm da r pm w' ; ?sm r ?pm w' ; wr w' 1 ; ?da r read{(1,0,0)} r ;" + " deaf P' ; ?!sm ?!da ?pm(1,0,0,-1,r) w' ; wr w' 2 ;" + " hearing P' ; ?!sm ?pm(2,1,1,1,r) w' ?!da ; wr w' 3 ;" + " ?da r sleep 0.3 read{s(1,0,0),f(3,0,0)} r"); + // if a transient-local writer loses the reader temporarily, what data + // has been published during the disconnect must still show up; delete + // writer, &c. checks nothing else showed up afterward + // - first: durability service history depth 1: 2nd write of 2 pushes + // the 1st write of it out of the history and only 2 samples arrive + // - second: d.s. keep-all: both writes are kept and 3 samples arrive + dotest ("sm da r(d=tl) pm w'(d=tl,h=1,ds=0/1) ; ?sm r ?pm w' ;" + " wr w' 1 ; ?da r read{(1,0,0)} r ;" + " deaf P' ; ?pm(1,0,0,-1,r) w' ; wr w' 2 wr w' 2 ;" + " hearing P' ; ?pm(2,1,1,1,r) w' ; wr w' 3 ;" + " ?da(2) r read{s(1,0,0),f(2,0,0),f(3,0,0)} r ;" + " -w' ?sm r ?da r read(3,3) r"); + dotest ("sm da r(d=tl) pm w'(d=tl,h=1,ds=0/all) ; ?sm r ?pm w' ;" + " wr w' 1 ; ?da r read{(1,0,0)} r ;" + " deaf P' ; ?pm(1,0,0,-1,r) w' ; wr w' 2 wr w' 2 ;" + " hearing P' ; ?pm(2,1,1,1,r) w' ; wr w' 3 ;" + " ?da(3) r read{s(1,0,0),f(2,0,0),f(2,0,0),f(3,0,0)} r ;" + " -w' ?sm r ?da r read(4,3) r"); } CU_Test (ddsc_listener, publication_matched) @@ -1163,18 +372,20 @@ CU_Test (ddsc_listener, subscription_matched) CU_Test (ddsc_listener, incompatible_qos) { // best-effort writer & reliable reader: both must trigger incompatible QoS event - dotest ("oiq w! riq r ; ?oiq(1,1) w ?riq(1,1) r"); - dotest ("riq r oiq w! ; ?oiq(1,1) w ?riq(1,1) r"); + dotest ("oiq w(r=be) riq r ; ?oiq(1,1,r) w ?riq(1,1,r) r"); + dotest ("riq r oiq w(r=be) ; ?oiq(1,1,r) w ?riq(1,1,r) r"); + dotest ("oiq w(o=x) riq r ; ?oiq(1,1,o) w ?riq(1,1,o) r"); + dotest ("riq r oiq w(o=x) ; ?oiq(1,1,o) w ?riq(1,1,o) r"); } CU_Test (ddsc_listener, data_available) { // data available on reader - dotest ("da sm r pm w ?pm w ?sm r wr 0 w ?da r ?!dor"); + dotest ("da sm r pm w ?pm w ?sm r wr w 0 ?da r ?!dor"); // data available set on subscriber - dotest ("da R sm r pm w ?pm w ?sm r wr 0 w ?da r ?!dor"); + dotest ("da R sm r pm w ?pm w ?sm r wr w 0 ?da r ?!dor"); // data available set on participant - dotest ("da P sm r pm w ?pm w ?sm r wr 0 w ?da r ?!dor"); + dotest ("da P sm r pm w ?pm w ?sm r wr w 0 ?da r ?!dor"); } CU_Test (ddsc_listener, data_available_delete_writer) @@ -1185,53 +396,53 @@ CU_Test (ddsc_listener, data_available_delete_writer) dotest ("da sm r w ; -w ?sm r ?!da ; take(0,0) r"); // after writing: auto-dispose should always trigger data available, an invalid // sample needs to show up if there isn't an unread sample to use instead - dotest ("da r w ; wr 0 w ?da r ; -w ?da r ; take(1,0) r"); - dotest ("da r w ; wr 0 w ?da r ; read(1,0) r ; -w ?da r ; take(1,1) r"); - dotest ("da r w ; wr 0 w ?da r ; take(1,0) r ; -w ?da r ; take(0,1) r"); + dotest ("da r w ; wr w 0 ?da r ; -w ?da r ; take(1,0) r"); + dotest ("da r w ; wr w 0 ?da r ; read(1,0) r ; -w ?da r ; take(1,1) r"); + dotest ("da r w ; wr w 0 ?da r ; take(1,0) r ; -w ?da r ; take(0,1) r"); // same with two writers (no point in doing this also with two domains) dotest ("da r w x ; -w ?!da -x ?!da ; take(0,0) r"); - dotest ("da r w x ; wr 0 w ?da r ; -x ?!da ; -w ?da r ; take(1,0) r"); - dotest ("da r w x ; wr 0 w ?da r ; -w ?da r ; take(1,0) r ; -x ?!da ; take(0,0) r"); - dotest ("da r w x ; wr 0 w wr 0 x ?da r ; -w ?!da ; take(2,0) r ; -x ?da r ; take(0,1) r"); - dotest ("da r w x ; wr 0 w wr 0 x ?da r ; read(2,0) r ; -w ?!da -x ?da r ; take(2,1) r"); - dotest ("da r w x ; wr 0 w wr 0 x ?da r ; read(2,0) r ; -x ?!da -w ?da r ; take(2,1) r"); - dotest ("da r w x ; wr 0 w read(1,0) r ; wr 0 x ?da r ; -w ?!da -x ?da r ; take(2,0) r"); - dotest ("da r w x ; wr 0 w read(1,0) r ; wr 0 x ?da r ; -x ?!da -w ?da r ; take(2,0) r"); - dotest ("da r w x ; wr 0 w read(1,0) r ; wr 0 x ?da r ; read(2,0) r ; -w ?!da -x ?da r ; take(2,1) r"); - dotest ("da r w x ; wr 0 w read(1,0) r ; wr 0 x ?da r ; read(2,0) r ; -x ?!da -w ?da r ; take(2,1) r"); - dotest ("da r w x ; wr 0 w wr 0 x ?da r ; take(2,0) r ; -w ?!da -x ?da r ; take(0,1) r"); - dotest ("da r w x ; wr 0 w wr 0 x ?da r ; take(2,0) r ; -x ?!da -w ?da r ; take(0,1) r"); + dotest ("da r w x ; wr w 0 ?da r ; -x ?!da ; -w ?da r ; take(1,0) r"); + dotest ("da r w x ; wr w 0 ?da r ; -w ?da r ; take(1,0) r ; -x ?!da ; take(0,0) r"); + dotest ("da r w x ; wr w 0 wr x 0 ?da r ; -w ?!da ; take(2,0) r ; -x ?da r ; take(0,1) r"); + dotest ("da r w x ; wr w 0 wr x 0 ?da r ; read(2,0) r ; -w ?!da -x ?da r ; take(2,1) r"); + dotest ("da r w x ; wr w 0 wr x 0 ?da r ; read(2,0) r ; -x ?!da -w ?da r ; take(2,1) r"); + dotest ("da r w x ; wr w 0 read(1,0) r ; wr x 0 ?da r ; -w ?!da -x ?da r ; take(2,0) r"); + dotest ("da r w x ; wr w 0 read(1,0) r ; wr x 0 ?da r ; -x ?!da -w ?da r ; take(2,0) r"); + dotest ("da r w x ; wr w 0 read(1,0) r ; wr x 0 ?da r ; read(2,0) r ; -w ?!da -x ?da r ; take(2,1) r"); + dotest ("da r w x ; wr w 0 read(1,0) r ; wr x 0 ?da r ; read(2,0) r ; -x ?!da -w ?da r ; take(2,1) r"); + dotest ("da r w x ; wr w 0 wr x 0 ?da r ; take(2,0) r ; -w ?!da -x ?da r ; take(0,1) r"); + dotest ("da r w x ; wr w 0 wr x 0 ?da r ; take(2,0) r ; -x ?!da -w ?da r ; take(0,1) r"); } CU_Test (ddsc_listener, data_available_delete_writer_disposed) { // same as data_available_delete_writer, but now with the instance disposed first - dotest ("da r w ; wr 0 w disp 0 w ?da r ; -w ?!da"); - dotest ("da r w ; wr 0 w disp 0 w ?da r ; read(1,0) r ; -w ?!da"); - dotest ("da r w ; wr 0 w disp 0 w ?da r ; take(1,0) r ; -w ?!da"); + dotest ("da r w ; wr w 0 disp w 0 ?da r ; -w ?!da"); + dotest ("da r w ; wr w 0 disp w 0 ?da r ; read(1,0) r ; -w ?!da"); + dotest ("da r w ; wr w 0 disp w 0 ?da r ; take(1,0) r ; -w ?!da"); - dotest ("da r w x ; wr 0 w ?da r ; read(1,0) r ; disp 0 w ?da r ; read(1,1) r ; -w ?!da -x ?!da"); - dotest ("da r w x ; wr 0 w ?da r ; take(1,0) r ; disp 0 w ?da r ; take(0,1) r ; -w ?!da -x ?!da"); - dotest ("da r w x ; wr 0 w ?da r ; read(1,0) r ; disp 0 w ?da r ; read(1,1) r ; -x ?!da -w ?!da"); - dotest ("da r w x ; wr 0 w ?da r ; take(1,0) r ; disp 0 w ?da r ; take(0,1) r ; -x ?!da -w ?!da"); + dotest ("da r w x ; wr w 0 ?da r ; read(1,0) r ; disp w 0 ?da r ; read(1,1) r ; -w ?!da -x ?!da"); + dotest ("da r w x ; wr w 0 ?da r ; take(1,0) r ; disp w 0 ?da r ; take(0,1) r ; -w ?!da -x ?!da"); + dotest ("da r w x ; wr w 0 ?da r ; read(1,0) r ; disp w 0 ?da r ; read(1,1) r ; -x ?!da -w ?!da"); + dotest ("da r w x ; wr w 0 ?da r ; take(1,0) r ; disp w 0 ?da r ; take(0,1) r ; -x ?!da -w ?!da"); - dotest ("da r w x ; wr 0 w ?da r ; read(1,0) r ; disp 0 x ?da r ; read(1,1) r ; -w ?!da -x ?!da"); - dotest ("da r w x ; wr 0 w ?da r ; take(1,0) r ; disp 0 x ?da r ; take(0,1) r ; -w ?!da -x ?!da"); - dotest ("da r w x ; wr 0 w ?da r ; read(1,0) r ; disp 0 x ?da r ; read(1,1) r ; -x ?!da -w ?!da"); - dotest ("da r w x ; wr 0 w ?da r ; take(1,0) r ; disp 0 x ?da r ; take(0,1) r ; -x ?!da -w ?!da"); + dotest ("da r w x ; wr w 0 ?da r ; read(1,0) r ; disp x 0 ?da r ; read(1,1) r ; -w ?!da -x ?!da"); + dotest ("da r w x ; wr w 0 ?da r ; take(1,0) r ; disp x 0 ?da r ; take(0,1) r ; -w ?!da -x ?!da"); + dotest ("da r w x ; wr w 0 ?da r ; read(1,0) r ; disp x 0 ?da r ; read(1,1) r ; -x ?!da -w ?!da"); + dotest ("da r w x ; wr w 0 ?da r ; take(1,0) r ; disp x 0 ?da r ; take(0,1) r ; -x ?!da -w ?!da"); } CU_Test (ddsc_listener, data_on_readers) { // data on readers wins from data available - dotest ("dor R da r ; wr 0 w ; ?dor R ?!da"); - dotest ("dor P da r ; wr 0 w ; ?dor R ?!da"); + dotest ("dor R da r ; wr w 0 ; ?dor R ?!da"); + dotest ("dor P da r ; wr w 0 ; ?dor R ?!da"); } CU_Test (ddsc_listener, sample_lost) { // FIXME: figure out what really constitutes a "lost sample" - dotest ("sl r ; wr@0 0 w ?!sl ; wr@-1 0 w ?sl(1,1) r"); + dotest ("sl r ; wr w 0@0 ?!sl ; wr w 0@-1 ?sl(1,1) r"); } CU_Test (ddsc_listener, sample_rejected) @@ -1240,13 +451,13 @@ CU_Test (ddsc_listener, sample_rejected) // reliable: expect timeout on the write when max samples has been reached // invalid samples don't count towards resource limits, so dispose should // not be blocked - dotest ("sr r# ; wr 0 w wrfail 0 w wrfail 0 w ; ?sr r"); - dotest ("sr r# ; wr 0 w wrfail 0 w ; read(1,0) r ; disp 0 w ; read(1,1) r ; ?sr r"); + dotest ("sr r(rl=1) ; wr w 0 wrfail w 0 wrfail w 0 ; ?sr r"); + dotest ("sr r(rl=1) ; wr w 0 wrfail w 0 ; read(1,0) r ; disp w 0 ; read(1,1) r ; ?sr r"); // best-effort: writes should succeed despite not delivering the data adding // the data in the RHC, also check number of samples rejected - dotest ("sr r#! ; wr 0 w! wr 0 w wr 0 w ; ?sr(2,1,s) r"); - dotest ("sr r#! ; wr 0 w! wr 0 w ; read(1,0) r ; disp 0 w ; read(1,1) r ; ?sr(1,1,s) r"); + dotest ("sr r(rl=1,r=be) ; wr w(r=be) 0 wr w 0 wr w 0 ; ?sr(2,1,s) r"); + dotest ("sr r(rl=1,r=be) ; wr w(r=be) 0 wr w 0 ; read(1,0) r ; disp w 0 ; read(1,1) r ; ?sr(1,1,s) r"); } CU_Test (ddsc_listener, liveliness_changed) diff --git a/src/core/ddsc/tests/test_oneliner.c b/src/core/ddsc/tests/test_oneliner.c new file mode 100644 index 0000000..255400a --- /dev/null +++ b/src/core/ddsc/tests/test_oneliner.c @@ -0,0 +1,1780 @@ +/* + * Copyright(c) 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include +#include + +#include "dds/dds.h" +#include "dds/ddsrt/misc.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/strtod.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/environ.h" + +#include "dds__types.h" +#include "dds__entity.h" +#include "dds/ddsi/q_lease.h" +#include "dds/ddsi/q_xevent.h" +#include "dds/ddsi/ddsi_entity_index.h" + +#include "test_common.h" +#include "test_oneliner.h" + +#define MAXDOMS (sizeof (((struct oneliner_ctx){.result=0}).doms) / sizeof (((struct oneliner_ctx){.result=0}).doms[0])) + +static const char knownentities[] = "PRWrstwxy"; +typedef struct { char n[MAXDOMS + 1]; } entname_t; + +#define DEFINE_STATUS_CALLBACK(name, NAME, kind) \ + static void name##_cb (dds_entity_t kind, const dds_##name##_status_t status, void *arg) \ + { \ + struct oneliner_cb *cb = arg; \ + ddsrt_mutex_lock (&cb->ctx->g_mutex); \ + cb->cb_##kind = kind; \ + cb->cb_##name##_status = status; \ + cb->cb_called[DDS_##NAME##_STATUS_ID]++; \ + ddsrt_cond_broadcast (&cb->ctx->g_cond); \ + ddsrt_mutex_unlock (&cb->ctx->g_mutex); \ + } + +DEFINE_STATUS_CALLBACK (inconsistent_topic, INCONSISTENT_TOPIC, topic) +DEFINE_STATUS_CALLBACK (liveliness_changed, LIVELINESS_CHANGED, reader) +DEFINE_STATUS_CALLBACK (liveliness_lost, LIVELINESS_LOST, writer) +DEFINE_STATUS_CALLBACK (offered_deadline_missed, OFFERED_DEADLINE_MISSED, writer) +DEFINE_STATUS_CALLBACK (offered_incompatible_qos, OFFERED_INCOMPATIBLE_QOS, writer) +DEFINE_STATUS_CALLBACK (publication_matched, PUBLICATION_MATCHED, writer) +DEFINE_STATUS_CALLBACK (requested_deadline_missed, REQUESTED_DEADLINE_MISSED, reader) +DEFINE_STATUS_CALLBACK (requested_incompatible_qos, REQUESTED_INCOMPATIBLE_QOS, reader) +DEFINE_STATUS_CALLBACK (sample_lost, SAMPLE_LOST, reader) +DEFINE_STATUS_CALLBACK (sample_rejected, SAMPLE_REJECTED, reader) +DEFINE_STATUS_CALLBACK (subscription_matched, SUBSCRIPTION_MATCHED, reader) + +static void data_on_readers_cb (dds_entity_t subscriber, void *arg) +{ + struct oneliner_cb *cb = arg; + ddsrt_mutex_lock (&cb->ctx->g_mutex); + cb->cb_subscriber = subscriber; + cb->cb_called[DDS_DATA_ON_READERS_STATUS_ID]++; + ddsrt_cond_broadcast (&cb->ctx->g_cond); + ddsrt_mutex_unlock (&cb->ctx->g_mutex); +} + +static void data_available_cb (dds_entity_t reader, void *arg) +{ + struct oneliner_cb *cb = arg; + ddsrt_mutex_lock (&cb->ctx->g_mutex); + cb->cb_reader = reader; + cb->cb_called[DDS_DATA_AVAILABLE_STATUS_ID]++; + ddsrt_cond_broadcast (&cb->ctx->g_cond); + ddsrt_mutex_unlock (&cb->ctx->g_mutex); +} + +static void dummy_data_on_readers_cb (dds_entity_t subscriber, void *arg) +{ + (void)subscriber; + (void)arg; +} + +static void dummy_data_available_cb (dds_entity_t reader, void *arg) +{ + (void)reader; + (void)arg; +} + +static void dummy_subscription_matched_cb (dds_entity_t reader, const dds_subscription_matched_status_t status, void *arg) +{ + (void)reader; + (void)status; + (void)arg; +} + +static void dummy_liveliness_changed_cb (dds_entity_t reader, const dds_liveliness_changed_status_t status, void *arg) +{ + (void)reader; + (void)status; + (void)arg; +} + +static void dummy_cb (void) +{ + // Used as a listener function in checking merging of listeners, + // and for that purpose, casting it to whatever function type is + // required is ok. It is not supposed to ever be called. + abort (); +} + +#undef DEFINE_STATUS_CALLBACK + +// These had better match the corresponding type definitions! +// n uint32_t ...count +// c int32_t ...count_change +// I instance handle of a data instance +// P uint32_t QoS policy ID +// E instance handle of an entity +// R sample_rejected_status_kind +static const struct { + const char *name; + size_t size; // size of status struct + const char *desc; // description of status struct + dds_status_id_t id; // status id, entry in "cb_called" + size_t cb_entity_off; // which cb_... entity to look at + size_t cb_status_off; // cb_..._status to look at +} lldesc[] = { +#define S0(abbrev, NAME, entity) \ + { abbrev, 0, NULL, DDS_##NAME##_STATUS_ID, offsetof (struct oneliner_cb, cb_##entity), 0 } +#define S(abbrev, name, NAME, desc, entity) \ + { abbrev, sizeof (dds_##name##_status_t), desc, DDS_##NAME##_STATUS_ID, offsetof (struct oneliner_cb, cb_##entity), offsetof (struct oneliner_cb, cb_##name##_status) } + S0 ("da", DATA_AVAILABLE, reader), + S0 ("dor", DATA_ON_READERS, subscriber), + S ("it", inconsistent_topic, INCONSISTENT_TOPIC, "nc", topic), + S ("lc", liveliness_changed, LIVELINESS_CHANGED, "nnccE", reader), + S ("ll", liveliness_lost, LIVELINESS_LOST, "nc", writer), + S ("odm", offered_deadline_missed, OFFERED_DEADLINE_MISSED, "ncI", writer), + S ("oiq", offered_incompatible_qos, OFFERED_INCOMPATIBLE_QOS, "ncP", writer), + S ("pm", publication_matched, PUBLICATION_MATCHED, "ncncE", writer), + S ("rdm", requested_deadline_missed, REQUESTED_DEADLINE_MISSED, "ncI", reader), + S ("riq", requested_incompatible_qos, REQUESTED_INCOMPATIBLE_QOS, "ncP", reader), + S ("sl", sample_lost, SAMPLE_LOST, "nc", reader), + S ("sr", sample_rejected, SAMPLE_REJECTED, "ncRI", reader), + S ("sm", subscription_matched, SUBSCRIPTION_MATCHED, "ncncE", reader) +#undef S +#undef S0 +}; + + +static const void *advance (const void *status, size_t *off, char code) +{ +#define alignof(type_) offsetof (struct { char c; type_ d; }, d) + size_t align = 1, size = 1; + switch (code) + { + case 'n': case 'c': case 'P': + align = alignof (uint32_t); size = sizeof (uint32_t); + break; + case 'E': case 'I': + align = alignof (dds_instance_handle_t); size = sizeof (dds_instance_handle_t); + break; + case 'R': + align = alignof (dds_sample_rejected_status_kind); size = sizeof (dds_sample_rejected_status_kind); + break; + default: + abort (); + } +#undef alignof + *off = (*off + align - 1) & ~(align - 1); + const void *p = (const char *) status + *off; + *off += size; + return p; +} + +static dds_return_t get_status (int ll, dds_entity_t ent, void *status) +{ + dds_return_t ret; + switch (ll) + { + case 2: ret = dds_get_inconsistent_topic_status (ent, status); break; + case 3: ret = dds_get_liveliness_changed_status (ent, status); break; + case 4: ret = dds_get_liveliness_lost_status (ent, status); break; + case 5: ret = dds_get_offered_deadline_missed_status (ent, status); break; + case 6: ret = dds_get_offered_incompatible_qos_status (ent, status); break; + case 7: ret = dds_get_publication_matched_status (ent, status); break; + case 8: ret = dds_get_requested_deadline_missed_status (ent, status); break; + case 9: ret = dds_get_requested_incompatible_qos_status (ent, status); break; + case 10: ret = dds_get_sample_lost_status (ent, status); break; + case 11: ret = dds_get_sample_rejected_status (ent, status); break; + case 12: ret = dds_get_subscription_matched_status (ent, status); break; + default: return -1; + } + return (ret == 0); +} + +static dds_return_t check_status_change_fields_are_0 (int ll, dds_entity_t ent) +{ + if (lldesc[ll].desc) + { + const char *d = lldesc[ll].desc; + void *status = malloc (lldesc[ll].size); + dds_return_t ret; + if ((ret = get_status (ll, ent, status)) <= 0) + { + free (status); + return ret; + } + size_t off = 0; + while (*d) + { + const uint32_t *p = advance (status, &off, *d); + if (*d == 'c' && *p != 0) + { + free (status); + return 0; + } + d++; + } + assert (off <= lldesc[ll].size); + free (status); + } + return 1; +} + +#define TOK_END -1 +#define TOK_NAME -2 +#define TOK_INT -3 +#define TOK_DURATION -4 +#define TOK_TIMESTAMP -5 +#define TOK_ELLIPSIS -6 +#define TOK_INVALID -7 + +static int setresult (struct oneliner_ctx *ctx, int result, const char *msg, ...) ddsrt_attribute_format((printf, 3, 4)); +static void error (struct oneliner_ctx *ctx, const char *msg, ...) ddsrt_attribute_format((printf, 2, 3)); +static void error_dds (struct oneliner_ctx *ctx, dds_return_t ret, const char *msg, ...) ddsrt_attribute_format((printf, 3, 4)); +static void testfail (struct oneliner_ctx *ctx, const char *msg, ...) ddsrt_attribute_format((printf, 2, 3)); + +static void vsetresult (struct oneliner_ctx *ctx, int result, const char *msg, va_list ap) +{ + assert (result <= 0); + ctx->result = result; + vsnprintf (ctx->msg, sizeof (ctx->msg), msg, ap); +} + +static int setresult (struct oneliner_ctx *ctx, int result, const char *msg, ...) +{ + va_list ap; + va_start (ap, msg); + vsetresult (ctx, result, msg, ap); + va_end (ap); + return result; +} + +static void error (struct oneliner_ctx *ctx, const char *msg, ...) +{ + va_list ap; + va_start (ap, msg); + vsetresult (ctx, -1, msg, ap); + va_end (ap); + longjmp (ctx->jb, 1); +} + +static void error_dds (struct oneliner_ctx *ctx, dds_return_t ret, const char *msg, ...) +{ + va_list ap; + va_start (ap, msg); + vsetresult (ctx, -1, msg, ap); + va_end (ap); + size_t n = strlen (ctx->msg); + if (n < sizeof (ctx->msg)) + snprintf (ctx->msg + n, sizeof (ctx->msg) - n, " (%s)", dds_strretcode (ret)); + longjmp (ctx->jb, 1); +} + +static void testfail (struct oneliner_ctx *ctx, const char *msg, ...) +{ + va_list ap; + va_start (ap, msg); + vsetresult (ctx, 0, msg, ap); + va_end (ap); + longjmp (ctx->jb, 1); +} + +static void advancetok (struct oneliner_lex *l) +{ + while (isspace ((unsigned char) *l->inp)) + l->inp++; +} + +static int issymchar0 (char c) +{ + return isalpha ((unsigned char) c) || c == '_'; +} + +static int issymchar (char c) +{ + return isalnum ((unsigned char) c) || c == '_' || c == '\''; +} + +static bool lookingatnum (const struct oneliner_lex *l) +{ + return (isdigit ((unsigned char) l->inp[(l->inp[0] == '-')])); +} + +static int nexttok_dur (struct oneliner_lex *l, union oneliner_tokval *v, bool expecting_duration) +{ + advancetok (l); + if (l->inp[0] == 0) + { + l->tok = TOK_END; + } + else if (strncmp (l->inp, "...", 3) == 0) + { + l->inp += 3; + l->tok = TOK_ELLIPSIS; + } + else if (!expecting_duration && lookingatnum (l)) + { + char *endp; + // strtol: [0-9]+ ; endp = l->inp if no digits present + l->v.i = (int) strtol (l->inp, &endp, 10); + l->inp = endp; + if (v) *v = l->v; + l->tok = TOK_INT; + } + else if (l->inp[0] == '@' || (expecting_duration && lookingatnum (l))) + { + const int ists = (l->inp[0] == '@'); + char *endp; + if (!ists && strncmp (l->inp + ists, "inf", 3) == 0 && !issymchar (l->inp[ists + 3])) + { + l->inp += ists + 3; + l->v.d = DDS_INFINITY; + } + else + { + double d; + if (ddsrt_strtod (l->inp + ists, &endp, &d) != DDS_RETCODE_OK) + return false; + if (!ists && d < 0) + return false; + if (d >= (double) (INT64_MAX / DDS_NSECS_IN_SEC)) + l->v.d = DDS_INFINITY; + else if (d >= 0) + l->v.d = (int64_t) (d * 1e9 + 0.5); + else + l->v.d = -(int64_t) (-d * 1e9 + 0.5); + if (ists) + l->v.d += l->tref; + l->inp = endp; + } + if (v) *v = l->v; + l->tok = ists ? TOK_TIMESTAMP : TOK_DURATION; + } + else if (issymchar0 (l->inp[0])) + { + int p = 0; + while (issymchar (l->inp[p])) + { + if (p == (int) sizeof (l->v.n)) + return TOK_INVALID; + l->v.n[p] = l->inp[p]; + p++; + } + l->v.n[p] = 0; + l->inp += p; + if (v) *v = l->v; + l->tok = TOK_NAME; + } + else + { + l->tok = *l->inp++; + } + return l->tok; +} + +static int nexttok (struct oneliner_lex *l, union oneliner_tokval *v) +{ + return nexttok_dur (l, v, false); +} + +static int peektok (const struct oneliner_lex *l, union oneliner_tokval *v) +{ + struct oneliner_lex l1 = *l; + return nexttok (&l1, v); +} + +static bool nexttok_if (struct oneliner_lex *l, int tok) +{ + if (peektok (l, NULL) != tok) + return false; + nexttok (l, NULL); + return true; +} + +static bool nexttok_int (struct oneliner_lex *l, int *dst) +{ + if (peektok (l, NULL) != TOK_INT) + return false; + (void) nexttok (l, NULL); + *dst = l->v.i; + return true; +} + +struct kvarg { + const char *k; + size_t klen; + int v; + bool (*arg) (struct oneliner_lex *l, void *dst); // *inp unchanged when false + void (*def) (void *dst); +}; + +static void def_kvarg_int0 (void *dst) { *(int *)dst = 0; } +static void def_kvarg_int1 (void *dst) { *(int *)dst = 1; } +static void def_kvarg_dur_inf (void *dst) { *(dds_duration_t *)dst = DDS_INFINITY; } +static void def_kvarg_dur_100ms (void *dst) { *(dds_duration_t *)dst = DDS_MSECS (100); } + +static bool read_kvarg_int (struct oneliner_lex *l, void *dst) +{ + return nexttok_int (l, dst); +} + +static bool read_kvarg_posint (struct oneliner_lex *l, void *dst) +{ + return nexttok_int (l, dst) && l->v.i > 0; +} + +static bool read_kvarg_dur (struct oneliner_lex *l, void *dst) +{ + dds_duration_t *x = dst; + struct oneliner_lex l1 = *l; + if (nexttok_dur (&l1, NULL, true) != TOK_DURATION) + return false; + *x = l1.v.d; + *l = l1; + return true; +} + +static bool read_kvarg_3len (struct oneliner_lex *l, void *dst) +{ + struct oneliner_lex l1 = *l; + int *x = dst, i = 0; + x[0] = x[1] = x[2] = DDS_LENGTH_UNLIMITED; + do { + if (!nexttok_int (&l1, &x[i]) || (x[i] <= 0 && x[i] != DDS_LENGTH_UNLIMITED)) + return false; + } while (++i < 3 && nexttok_if (&l1, '/')); + *l = l1; + return true; +} + +static bool read_kvarg (const struct kvarg *ks, size_t sizeof_ks, struct oneliner_lex *l, int *v, void *arg) +{ + // l points at name, *inp is , or ) terminated; *l unchanged when false + const struct kvarg *kend = ks + sizeof_ks / sizeof (*ks); + struct oneliner_lex l1 = *l; + advancetok (&l1); + for (const struct kvarg *k = ks; k < kend; k++) + { + assert (strlen (k->k) == k->klen); + *v = k->v; + if (k->klen == 0) + { + assert (k->arg != 0 && k->def == 0); + struct oneliner_lex l2 = l1; + if (k->arg (&l2, arg) && (peektok (&l2, NULL) == ',' || peektok (&l2, NULL) == ')')) + { + *l = l2; + return true; + } + } + else if (strncmp (l1.inp, k->k, k->klen) != 0) + { + continue; + } + else + { + /* skip symbol */ + struct oneliner_lex l2 = l1; + l2.inp += k->klen; + if (peektok (&l2, NULL) == ',' || peektok (&l2, NULL) == ')') + { + if (k->arg == 0 || k->def != 0) + { + if (k->def) k->def (arg); + *l = l2; + return true; + } + } + else if (k->arg != 0 && nexttok (&l2, NULL) == ':') + { + if (k->arg (&l2, arg) && (peektok (&l2, NULL) == ',' || peektok (&l2, NULL) == ')')) + { + *l = l2; + return true; + } + } + } + } + return false; +} + +static bool qos_durability (struct oneliner_lex *l, dds_qos_t *q) +{ + static const struct kvarg ks[] = { + { "v", 1, (int) DDS_DURABILITY_VOLATILE }, + { "tl", 2, (int) DDS_DURABILITY_TRANSIENT_LOCAL }, + { "t", 1, (int) DDS_DURABILITY_TRANSIENT }, + { "p", 1, (int) DDS_DURABILITY_PERSISTENT } + }; + int v; + if (!read_kvarg (ks, sizeof ks, l, &v, NULL)) + return false; + dds_qset_durability (q, (dds_durability_kind_t) v); + return true; +} + +static const struct kvarg ks_history[] = { + { "all", 3, (int) DDS_HISTORY_KEEP_ALL, .def = def_kvarg_int1 }, + { "", 0, (int) DDS_HISTORY_KEEP_LAST, .arg = read_kvarg_posint } +}; + +static bool qos_history (struct oneliner_lex *l, dds_qos_t *q) +{ + int v, x = 1; + if (!read_kvarg (ks_history, sizeof ks_history, l, &v, &x)) + return false; + dds_qset_history (q, (dds_history_kind_t) v, x); + return true; +} + +static bool qos_destination_order (struct oneliner_lex *l, dds_qos_t *q) +{ + static const struct kvarg ks[] = { + { "r", 1, (int) DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP }, + { "s", 1, (int) DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP } + }; + int v; + if (!read_kvarg (ks, sizeof ks, l, &v, NULL)) + return false; + dds_qset_destination_order (q, (dds_destination_order_kind_t) v); + return true; +} + +static bool qos_ownership (struct oneliner_lex *l, dds_qos_t *q) +{ + static const struct kvarg ks[] = { + { "s", 1, (int) DDS_OWNERSHIP_SHARED, .def = def_kvarg_int0 }, + { "x", 1, (int) DDS_OWNERSHIP_EXCLUSIVE, .arg = read_kvarg_int, .def = def_kvarg_int0 } + }; + int v, x; + if (!read_kvarg (ks, sizeof ks, l, &v, &x)) + return false; + dds_qset_ownership (q, (dds_ownership_kind_t) v); + dds_qset_ownership_strength (q, x); + return true; +} + +static bool qos_transport_priority (struct oneliner_lex *l, dds_qos_t *q) +{ + static const struct kvarg k = { "", 0, 0, .arg = read_kvarg_int }; + int v, x; + if (!read_kvarg (&k, sizeof k, l, &v, &x)) + return false; + dds_qset_transport_priority (q, x); + return true; +} + +static bool qos_reliability (struct oneliner_lex *l, dds_qos_t *q) +{ + static const struct kvarg ks[] = { + { "be", 2, (int) DDS_RELIABILITY_BEST_EFFORT, .def = def_kvarg_dur_100ms }, + { "r", 1, (int) DDS_RELIABILITY_RELIABLE, .def = def_kvarg_dur_100ms, .arg = read_kvarg_dur } + }; + int v; + dds_duration_t x; + if (!read_kvarg (ks, sizeof ks, l, &v, &x)) + return false; + dds_qset_reliability (q, (dds_reliability_kind_t) v, x); + return true; +} + +static bool qos_liveliness (struct oneliner_lex *l, dds_qos_t *q) +{ + static const struct kvarg ks[] = { + { "a", 1, (int) DDS_LIVELINESS_AUTOMATIC, .def = def_kvarg_dur_inf, .arg = read_kvarg_dur }, + { "p", 1, (int) DDS_LIVELINESS_MANUAL_BY_PARTICIPANT, .arg = read_kvarg_dur }, + { "w", 1, (int) DDS_LIVELINESS_MANUAL_BY_TOPIC, .arg = read_kvarg_dur } + }; + int v; + dds_duration_t x; + if (!read_kvarg (ks, sizeof ks, l, &v, &x)) + return false; + dds_qset_liveliness (q, (dds_liveliness_kind_t) v, x); + return true; +} + +static bool qos_simple_duration (struct oneliner_lex *l, dds_qos_t *q, void (*set) (dds_qos_t * __restrict q, dds_duration_t dur)) +{ + static const struct kvarg k = { "", 0, 0, .arg = read_kvarg_dur }; + int v; + dds_duration_t x; + if (!read_kvarg (&k, sizeof k, l, &v, &x)) + return false; + set (q, x); + return true; +} + +static bool qos_latency_budget (struct oneliner_lex *l, dds_qos_t *q) +{ + return qos_simple_duration (l, q, dds_qset_latency_budget); +} + +static bool qos_deadline (struct oneliner_lex *l, dds_qos_t *q) +{ + return qos_simple_duration (l, q, dds_qset_deadline); +} + +static bool qos_lifespan (struct oneliner_lex *l, dds_qos_t *q) +{ + return qos_simple_duration (l, q, dds_qset_lifespan); +} + +static bool qos_resource_limits (struct oneliner_lex *l, dds_qos_t *q) +{ + int rl[3]; + if (!read_kvarg_3len (l, rl)) + return false; + dds_qset_resource_limits (q, rl[0], rl[1], rl[2]); + return true; +} + +static bool qos_durability_service (struct oneliner_lex *l, dds_qos_t *q) +{ + struct oneliner_lex l1 = *l; + dds_duration_t scd; + int hk = DDS_HISTORY_KEEP_LAST, hd = 1, rl[3]; + if (!read_kvarg_dur (&l1, &scd)) + return false; + if (peektok (&l1, NULL) == '/') + { + (void) nexttok (&l1, NULL); + if (!read_kvarg (ks_history, sizeof ks_history, &l1, &hk, &hd)) + return false; + } + if (peektok (&l1, NULL) != '/') + rl[0] = rl[1] = rl[2] = DDS_LENGTH_UNLIMITED; + else + { + (void) nexttok (&l1, NULL); + if (!read_kvarg_3len (&l1, rl)) + return false; + } + dds_qset_durability_service (q, scd, (dds_history_kind_t) hk, hd, rl[0], rl[1], rl[2]); + *l = l1; + return true; +} + +static bool qos_presentation (struct oneliner_lex *l, dds_qos_t *q) +{ + static const struct kvarg ks[] = { + { "i", 1, (int) DDS_PRESENTATION_INSTANCE, .def = def_kvarg_int0 }, + { "t", 1, (int) DDS_PRESENTATION_TOPIC, .def = def_kvarg_int1 }, + { "g", 1, (int) DDS_PRESENTATION_GROUP, .def = def_kvarg_int1 } + }; + int v, x; + if (!read_kvarg (ks, sizeof ks, l, &v, &x)) + return false; + dds_qset_presentation (q, (dds_presentation_access_scope_kind_t) v, x, 0); + return true; +} + +static bool qos_autodispose_unregistered_instances (struct oneliner_lex *l, dds_qos_t *q) +{ + static const struct kvarg ks[] = { + { "y", 1, 1 }, + { "n", 1, 0 } + }; + int v; + if (!read_kvarg (ks, sizeof ks, l, &v, NULL)) + return false; + dds_qset_writer_data_lifecycle (q, !!v); + return true; +} + +static const struct { + char *abbrev; + size_t n; + bool (*fn) (struct oneliner_lex *l, dds_qos_t *q); + dds_qos_policy_id_t id; +} qostab[] = { + { "ll", 2, qos_liveliness, DDS_LIVELINESS_QOS_POLICY_ID }, + { "d", 1, qos_durability, DDS_DURABILITY_QOS_POLICY_ID }, + { "dl", 2, qos_deadline, DDS_DEADLINE_QOS_POLICY_ID }, + { "h", 1, qos_history, DDS_HISTORY_QOS_POLICY_ID }, + { "lb", 2, qos_latency_budget, DDS_LATENCYBUDGET_QOS_POLICY_ID }, + { "ls", 2, qos_lifespan, DDS_LIFESPAN_QOS_POLICY_ID }, + { "do", 2, qos_destination_order, DDS_DESTINATIONORDER_QOS_POLICY_ID }, + { "o", 1, qos_ownership, DDS_OWNERSHIP_QOS_POLICY_ID }, + { "tp", 2, qos_transport_priority, DDS_OWNERSHIPSTRENGTH_QOS_POLICY_ID }, + { "p", 1, qos_presentation, DDS_PRESENTATION_QOS_POLICY_ID }, + { "r", 1, qos_reliability, DDS_RELIABILITY_QOS_POLICY_ID }, + { "rl", 2, qos_resource_limits, DDS_RESOURCELIMITS_QOS_POLICY_ID }, + { "ds", 2, qos_durability_service, DDS_DURABILITYSERVICE_QOS_POLICY_ID }, + { "ad", 2, qos_autodispose_unregistered_instances, DDS_WRITERDATALIFECYCLE_QOS_POLICY_ID } +}; + +static bool setqos (struct oneliner_lex *l, dds_qos_t *q) +{ + struct oneliner_lex l1 = *l; + dds_reset_qos (q); + // no whitespace between name & QoS + if (*l1.inp != '(') + return true; + nexttok (&l1, NULL); // eat '(' + do { + size_t i; + union oneliner_tokval name; + if (nexttok (&l1, &name) != TOK_NAME || nexttok (&l1, NULL) != '=') + return false; + for (i = 0; i < sizeof (qostab) / sizeof (qostab[0]); i++) + { + assert (strlen (qostab[i].abbrev) == qostab[i].n); + if (strcmp (name.n, qostab[i].abbrev) == 0) + break; + } + if (i == sizeof (qostab) / sizeof (qostab[0])) + return false; + if (!qostab[i].fn (&l1, q)) + return false; + } while (nexttok_if (&l1, ',')); + if (nexttok (&l1, NULL) != ')') + return false; + *l = l1; + return true; +} + +static int parse_entity1 (struct oneliner_lex *l, dds_qos_t *qos) +{ + struct oneliner_lex l1 = *l; + if (nexttok (&l1, NULL) != TOK_NAME) + return -1; + const char *p; + if ((p = strchr (knownentities, l1.v.n[0])) == NULL) + return -1; + int ent = (int) (p - knownentities); + int i; + for (i = 1; l1.v.n[i] == '\''; i++) + ent += (int) sizeof (knownentities) - 1; + if (l1.v.n[i] != 0) + return -1; + if (ent / 9 >= (int) MAXDOMS) + return -1; + if (!setqos (&l1, qos)) + return -1; + *l = l1; + return ent; +} + +static int parse_entity (struct oneliner_ctx *ctx) +{ + return parse_entity1 (&ctx->l, ctx->rwqos); +} + +static int parse_listener1 (struct oneliner_lex *l) +{ + struct oneliner_lex l1 = *l; + size_t i; + if (nexttok (&l1, NULL) != TOK_NAME) + return -1; + for (i = 0; i < sizeof (lldesc) / sizeof (lldesc[0]); i++) + if (strcmp (l1.v.n, lldesc[i].name) == 0) + break; + if (i == sizeof (lldesc) / sizeof (lldesc[0])) + return -1; + *l = l1; + return (int) i; +} + +static int parse_listener (struct oneliner_ctx *ctx) +{ + return parse_listener1 (&ctx->l); +} + +static const char *getentname (entname_t *name, int ent) +{ + DDSRT_STATIC_ASSERT (sizeof (knownentities) == 10); + DDSRT_STATIC_ASSERT (MAXDOMS == 3); + name->n[0] = knownentities[ent % 9]; + const int dom = ent / 9; + int i; + for (i = 1; i <= dom; i++) + name->n[i] = '\''; + name->n[i] = 0; + return name->n; +} + +static void make_participant (struct oneliner_ctx *ctx, int ent, dds_listener_t *list) +{ + const dds_domainid_t domid = (dds_domainid_t) (ent / 9); + char *conf = ddsrt_expand_envvars ("${CYCLONEDDS_URI}${CYCLONEDDS_URI:+,}0", domid); + entname_t name; + printf ("create domain %"PRIu32, domid); + fflush (stdout); + if ((ctx->doms[domid] = dds_create_domain (domid, conf)) <= 0) + error_dds (ctx, ctx->doms[domid], "make_participant: create domain %"PRIu32" failed", domid); + ddsrt_free (conf); + printf (" create participant %s", getentname (&name, ent)); + fflush (stdout); + if ((ctx->es[ent] = dds_create_participant (domid, NULL, list)) <= 0) + error_dds (ctx, ctx->es[ent], "make_participant: create participant failed in domain %"PRIu32, domid); + if ((ctx->tps[domid] = dds_create_topic (ctx->es[ent], &Space_Type1_desc, ctx->topicname, ctx->qos, NULL)) <= 0) + error_dds (ctx, ctx->tps[domid], "make_participant: create topic failed in domain %"PRIu32, domid); + + // Create the built-in topic readers with a dummy listener to avoid any event (data available comes to mind) + // from propagating to the normal data available listener, in case it has been set on the participant. + // + // - dummy_cb aborts when it is invoked, but all reader-related listeners that can possibly trigger are set + // separately (incompatible qos, deadline missed, sample lost and sample rejected are all impossible by + // construction) + // - regarding data_on_readers: Cyclone handles listeners installed on an ancestor by *inheriting* them, + // rather than by walking up ancestor chain. Setting data_on_readers on the reader therefore overrides the + // listener set on the subscriber. It is a nice feature! + dds_listener_t *dummylist = dds_create_listener (ctx); + dds_lset_data_available (dummylist, dummy_data_available_cb); + dds_lset_data_on_readers (dummylist, dummy_data_on_readers_cb); + dds_lset_inconsistent_topic (dummylist, (dds_on_inconsistent_topic_fn) dummy_cb); + dds_lset_liveliness_changed (dummylist, dummy_liveliness_changed_cb); + dds_lset_liveliness_lost (dummylist, (dds_on_liveliness_lost_fn) dummy_cb); + dds_lset_offered_deadline_missed (dummylist, (dds_on_offered_deadline_missed_fn) dummy_cb); + dds_lset_offered_incompatible_qos (dummylist, (dds_on_offered_incompatible_qos_fn) dummy_cb); + dds_lset_publication_matched (dummylist, (dds_on_publication_matched_fn) dummy_cb); + dds_lset_requested_deadline_missed (dummylist, (dds_on_requested_deadline_missed_fn) dummy_cb); + dds_lset_requested_incompatible_qos (dummylist, (dds_on_requested_incompatible_qos_fn) dummy_cb); + dds_lset_sample_lost (dummylist, (dds_on_sample_lost_fn) dummy_cb); + dds_lset_sample_rejected (dummylist, (dds_on_sample_rejected_fn) dummy_cb); + dds_lset_subscription_matched (dummylist, dummy_subscription_matched_cb); + if ((ctx->pubrd[domid] = dds_create_reader (ctx->es[ent], DDS_BUILTIN_TOPIC_DCPSPUBLICATION, NULL, dummylist)) <= 0) + error_dds (ctx, ctx->pubrd[domid], "make_participant: create DCPSPublication reader in domain %"PRIu32, domid); + if ((ctx->subrd[domid] = dds_create_reader (ctx->es[ent], DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, dummylist)) <= 0) + error_dds (ctx, ctx->subrd[domid], "make_participant: create DCPSSubscription reader in domain %"PRIu32, domid); + dds_delete_listener (dummylist); + //printf ("pubrd %"PRId32" subrd %"PRId32" sub %"PRId32"\n", es->pubrd[domid], es->subrd[domid], dds_get_parent (es->pubrd[domid])); +} + +static void make_entity1 (struct oneliner_ctx *ctx, int ent, dds_listener_t *list) +{ + entname_t wrname; + dds_return_t ret; + int domid = ent / 9; + int ent1 = ent % 9; + switch (ent1) + { + case 0: + make_participant (ctx, ent, list); + break; + case 1: + if (ctx->es[ent-1] == 0) + { + printf ("["); + make_entity1 (ctx, ent-1, NULL); + printf ("] "); + } + printf ("create subscriber %s", getentname (&wrname, ent)); + fflush (stdout); + ctx->es[ent] = dds_create_subscriber (ctx->es[ent-1], NULL, list); + break; + case 2: + if (ctx->es[ent-2] == 0) + { + printf ("["); + make_entity1 (ctx, ent-2, NULL); + printf ("] "); + } + printf ("create publisher %s", getentname (&wrname, ent)); + fflush (stdout); + ctx->es[ent] = dds_create_publisher (ctx->es[ent-2], NULL, list); + break; + case 3: case 4: case 5: + if (ctx->es[9*domid+1] == 0) + { + printf ("["); + make_entity1 (ctx, 9*domid+1, NULL); + printf ("] "); + } + printf ("create reader %s", getentname (&wrname, ent)); + fflush (stdout); + ctx->es[ent] = dds_create_reader (ctx->es[9*domid+1], ctx->tps[domid], ctx->rwqos, list); + break; + case 6: case 7: case 8: + if (ctx->es[9*domid+2] == 0) + { + printf ("["); + make_entity1 (ctx, 9*domid+2, NULL); + printf ("] "); + } + printf ("create writer %s", getentname (&wrname, ent)); + fflush (stdout); + ctx->es[ent] = dds_create_writer (ctx->es[9*domid+2], ctx->tps[domid], ctx->rwqos, list); + break; + default: + abort (); + } + printf (" = %"PRId32, ctx->es[ent]); + fflush (stdout); + if (ctx->es[ent] <= 0) + error_dds (ctx, ctx->es[ent], "create entity %d failed", ent); + if ((ret = dds_get_instance_handle (ctx->es[ent], &ctx->esi[ent])) != 0) + error_dds (ctx, ret, "get instance handle for entity %"PRId32" failed", ctx->es[ent]); + //printf (" %"PRIx64, es->esi[ent]); + //fflush (stdout); +} + +static void make_entity (struct oneliner_ctx *ctx, int ent, dds_listener_t *list) +{ + make_entity1 (ctx, ent, list); + printf ("\n"); +} + +static void setlistener (struct oneliner_ctx *ctx, struct oneliner_lex *l, int ll, int ent) +{ + printf ("set listener:"); + dds_return_t ret; + int dom = ent / 9; + dds_listener_t *list = ctx->cb[dom].list; + dds_reset_listener (list); + do { + printf (" %s", lldesc[ll].name); + switch (ll) + { + case 0: dds_lset_data_available (list, data_available_cb); break; + case 1: dds_lset_data_on_readers (list, data_on_readers_cb); break; + case 2: dds_lset_inconsistent_topic (list, inconsistent_topic_cb); break; + case 3: dds_lset_liveliness_changed (list, liveliness_changed_cb); break; + case 4: dds_lset_liveliness_lost (list, liveliness_lost_cb); break; + case 5: dds_lset_offered_deadline_missed (list, offered_deadline_missed_cb); break; + case 6: dds_lset_offered_incompatible_qos (list, offered_incompatible_qos_cb); break; + case 7: dds_lset_publication_matched (list, publication_matched_cb); break; + case 8: dds_lset_requested_deadline_missed (list, requested_deadline_missed_cb); break; + case 9: dds_lset_requested_incompatible_qos (list, requested_incompatible_qos_cb); break; + case 10: dds_lset_sample_lost (list, sample_lost_cb); break; + case 11: dds_lset_sample_rejected (list, sample_rejected_cb); break; + case 12: dds_lset_subscription_matched (list, subscription_matched_cb); break; + default: abort (); + } + } while (l && (ll = parse_listener1 (l)) >= 0); + if (ctx->es[ent] == 0) + { + printf (" for "); + make_entity (ctx, ent, list); + } + else + { + dds_listener_t *tmplist = dds_create_listener (&ctx->cb[dom]); + if ((ret = dds_get_listener (ctx->es[ent], tmplist)) != 0) + { + dds_delete_listener (tmplist); + error_dds (ctx, ret, "set listener: dds_get_listener failed on %"PRId32, ctx->es[ent]); + } + dds_merge_listener (list, tmplist); + dds_delete_listener (tmplist); + printf (" on entity %"PRId32"\n", ctx->es[ent]); + if ((ret = dds_set_listener (ctx->es[ent], list)) != 0) + error_dds (ctx, ret, "set listener: dds_set_listener failed on %"PRId32, ctx->es[ent]); + } +} + +static dds_instance_handle_t lookup_insthandle (const struct oneliner_ctx *ctx, int ent, int ent1) +{ + // if both are in the same domain, it's easy + if (ent / 9 == ent1 / 9) + return ctx->esi[ent1]; + else + { + // if they aren't ... find GUID from instance handle in the one domain, + // then find instance handle for GUID in the other + dds_entity_t rd1 = 0, rd2 = 0; + switch (ent1 % 9) + { + case 3: case 4: case 5: rd1 = ctx->subrd[ent1/9]; rd2 = ctx->subrd[ent/9]; break; + case 6: case 7: case 8: rd1 = ctx->pubrd[ent1/9]; rd2 = ctx->pubrd[ent/9]; break; + default: return 0; + } + + dds_builtintopic_endpoint_t keysample; + //printf ("(in %"PRId32" %"PRIx64" -> ", rd1, es->esi[ent1]); + //fflush (stdout); + if (dds_instance_get_key (rd1, ctx->esi[ent1], &keysample) != 0) + return 0; + // In principle, only key fields are set in sample returned by get_key; + // in the case of a built-in topic that is extended to the participant + // key. The qos and topic/type names should not be set, and there is no + // (therefore) memory allocated for the sample. + assert (keysample.qos == NULL); + assert (keysample.topic_name == NULL); + assert (keysample.type_name == NULL); + //for (size_t j = 0; j < sizeof (keysample.key.v); j++) + // printf ("%s%02x", (j > 0 && j % 4 == 0) ? ":" : "", keysample.key.v[j]); + const dds_instance_handle_t ih = dds_lookup_instance (rd2, &keysample); + //printf (" -> %"PRIx64")", ih); + //fflush (stdout); + return ih; + } +} + +static void print_timestamp (struct oneliner_ctx *ctx, dds_time_t ts) +{ + dds_time_t dt = ts - ctx->l.tref; + if ((dt % DDS_NSECS_IN_SEC) == 0) + printf ("@%"PRId64, dt / DDS_NSECS_IN_SEC); + else + { + unsigned frac = (unsigned) (dt % DDS_NSECS_IN_SEC); + int digs = 9; + while ((frac % 10) == 0) + { + digs--; + frac /= 10; + } + printf ("@%"PRId64".%0*u", dt / DDS_NSECS_IN_SEC, digs, frac); + } +} + +static bool parse_sample_value (struct oneliner_ctx *ctx, Space_Type1 *s, bool *valid_data, int def) +{ + s->long_1 = s->long_2 = s->long_3 = def; + if (nexttok (&ctx->l, NULL) == TOK_INT) // key value (invalid sample) + { + if (ctx->l.v.i < 0) + return false; + s->long_1 = ctx->l.v.i; + *valid_data = false; + return true; + } + else if (ctx->l.tok == '(') + { + if (nexttok (&ctx->l, NULL) != TOK_INT || ctx->l.v.i < 0) + return false; + s->long_1 = ctx->l.v.i; + if (nexttok (&ctx->l, NULL) != ',' || nexttok (&ctx->l, NULL) != TOK_INT || ctx->l.v.i < 0) + return false; + s->long_2 = ctx->l.v.i; + if (nexttok (&ctx->l, NULL) != ',' || nexttok (&ctx->l, NULL) != TOK_INT || ctx->l.v.i < 0) + return false; + s->long_3 = ctx->l.v.i; + *valid_data = true; + return nexttok (&ctx->l, NULL) == ')'; + } + else + { + return false; + } +} + +struct doreadlike_sample { + uint32_t state; + bool valid_data; + dds_time_t ts; + int wrent; + dds_instance_handle_t wrih; + Space_Type1 data; +}; + +static bool wrname_from_pubhandle (const struct oneliner_ctx *ctx, int ent, dds_instance_handle_t pubhandle, entname_t *wrname) +{ + dds_builtintopic_endpoint_t inf, inf1; + if (dds_instance_get_key (ctx->pubrd[ent/9], pubhandle, &inf) != 0) + return false; + for (int j = 0; j < (int) (sizeof (ctx->doms) / sizeof (ctx->doms[0])); j++) + { + for (int k = 6; k < 9; k++) + { + if (ctx->esi[9*j+k] != 0) + { + if (dds_instance_get_key (ctx->pubrd[j], ctx->esi[9*j+k], &inf1) != 0) + return false; + if (memcmp (&inf.key, &inf1.key, sizeof (inf.key)) == 0) + { + getentname (wrname, 9*j+k); + return true; + } + } + } + } + return false; +} + +static bool doreadlike_parse_sample (struct oneliner_ctx *ctx, struct doreadlike_sample *s) +{ + static const char *statechars = "fsaudno"; + static const uint32_t statemap[] = { + DDS_NOT_READ_SAMPLE_STATE, DDS_READ_SAMPLE_STATE, + DDS_ALIVE_INSTANCE_STATE, DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE, DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE, + DDS_NEW_VIEW_STATE, DDS_NOT_NEW_VIEW_STATE + }; + // syntax: [state]k[pubhandle][@ts] or [state](k,l,m)[pubhandle][@ts] + // the first is an invalid sample, the second a valid one, the third says anything goes + // state is a combination of: sample state (F,S fresh/stale), instance state (A,U,D), view state (N,O) + // unspecified: don't care + s->state = 0; + s->ts = -1; + s->wrent = -1; + s->wrih = 0; + struct oneliner_lex l1 = ctx->l; + if (nexttok_if (&ctx->l, TOK_NAME)) + { + char *inp1 = ctx->l.v.n; + char *p; + while (*inp1 && (p = strchr (statechars, *inp1)) != NULL) + { + s->state |= statemap[(int) (p - statechars)]; + inp1++; + } + if (*inp1 == 0) + ; + else if (!isdigit (*inp1)) + return false; + else // rewind input to digit + ctx->l.inp = l1.inp + (inp1 - ctx->l.v.n); + } + // missing states: allow everything + if ((s->state & (statemap[0] | statemap[1])) == 0) + s->state |= statemap[0] | statemap[1]; + if ((s->state & (statemap[2] | statemap[3] | statemap[4])) == 0) + s->state |= statemap[2] | statemap[3] | statemap[4]; + if ((s->state & (statemap[5] | statemap[6])) == 0) + s->state |= statemap[5] | statemap[6]; + if (!parse_sample_value (ctx, &s->data, &s->valid_data, -1)) + return false; + s->wrent = parse_entity1 (&ctx->l, NULL); + if (nexttok_if (&ctx->l, TOK_TIMESTAMP)) + s->ts = ctx->l.v.d; + return true; +} + +static bool doreadlike_ismatch (const dds_sample_info_t *si, const Space_Type1 *s, const struct doreadlike_sample *exp) +{ + return (si->valid_data == exp->valid_data && + (si->sample_state & exp->state) != 0 && + (si->instance_state & exp->state) != 0 && + (si->view_state & exp->state) != 0 && + (exp->data.long_1 < 0 || s->long_1 == exp->data.long_1) && + (!exp->valid_data || exp->data.long_2 < 0 || s->long_2 == exp->data.long_2) && + (!exp->valid_data || exp->data.long_3 < 0 || s->long_3 == exp->data.long_3) && + (exp->ts < 0 || si->source_timestamp == exp->ts) && + (exp->wrent < 0 || si->publication_handle == exp->wrih)); +} + +static bool doreadlike_matchstep (const dds_sample_info_t *si, const Space_Type1 *s, const struct doreadlike_sample *exp, int nexp, bool ellipsis, unsigned *tomatch, int *cursor, dds_instance_handle_t *lastih, int *matchidx) +{ + if (si->instance_handle != *lastih) + { + *lastih = si->instance_handle; + *cursor = -1; + for (int m = 0; m < nexp; m++) + { + if ((*tomatch & (1u << m)) && s->long_1 == exp[m].data.long_1) + { + *cursor = m; + break; + } + } + } + if (*cursor < 0 || *cursor >= nexp) + { + *matchidx = ellipsis ? nexp : -1; + return ellipsis; + } + else if (doreadlike_ismatch (si, s, &exp[*cursor])) + { + *matchidx = *cursor; + *tomatch &= ~(1u << *cursor); + (*cursor)++; + return true; + } + else if (ellipsis) + { + *matchidx = nexp; + return true; + } + else + { + *matchidx = -1; + return false; + } +} + +static void doreadlike (struct oneliner_ctx *ctx, const char *name, dds_return_t (*fn) (dds_entity_t, void **buf, dds_sample_info_t *, size_t, uint32_t)) +{ +#define MAXN 10 + struct doreadlike_sample exp[MAXN]; + int nexp = 0; + bool ellipsis = false; + int exp_nvalid = -1, exp_ninvalid = -1; + int ent; + switch (peektok (&ctx->l, NULL)) + { + default: // no expectations + ellipsis = true; + break; + case '(': // (# valid, # invalid) + nexttok (&ctx->l, NULL); + if (!(nexttok_int (&ctx->l, &exp_nvalid) && nexttok_if (&ctx->l, ',') && nexttok_int (&ctx->l, &exp_ninvalid) && nexttok_if (&ctx->l, ')'))) + error (ctx, "%s: expecting (NINVALID, NVALID)", name); + ellipsis = true; + break; + case '{': + nexttok (&ctx->l, NULL); + if (!nexttok_if (&ctx->l, '}')) + { + do { + if (nexttok_if (&ctx->l, TOK_ELLIPSIS)) { + ellipsis = true; break; + } else if (nexp == MAXN) { + error (ctx, "%s: too many samples specified", name); + } else if (!doreadlike_parse_sample (ctx, &exp[nexp++])) { + error (ctx, "%s: expecting sample", name); + } + } while (nexttok_if (&ctx->l, ',')); + if (!nexttok_if (&ctx->l, '}')) + error (ctx, "%s: expecting '}'", name); + } + break; + } + if ((ent = parse_entity1 (&ctx->l, NULL)) < 0) + error (ctx, "%s: entity required", name); + + for (int i = 0; i < nexp; i++) + { + if (exp[i].wrent >= 0 && (exp[i].wrih = lookup_insthandle (ctx, ent, exp[i].wrent)) == 0) + error (ctx, "%s: instance lookup failed", name); + } + + printf ("entity %"PRId32": %s: ", ctx->es[ent], (fn == dds_take) ? "take" : "read"); + fflush (stdout); + Space_Type1 data[MAXN]; + void *raw[MAXN]; + for (int i = 0; i < MAXN; i++) + raw[i] = &data[i]; + int matchidx[MAXN]; + dds_sample_info_t si[MAXN]; + DDSRT_STATIC_ASSERT (MAXN < CHAR_BIT * sizeof (unsigned)); + const uint32_t maxs = (uint32_t) (sizeof (raw) / sizeof (raw[0])); + const int32_t n = fn (ctx->es[ent], raw, si, maxs, maxs); + if (n < 0) + error_dds (ctx, n, "%s: failed on %"PRId32, name, ctx->es[ent]); + unsigned tomatch = (1u << nexp) - 1; // used to track result entries matched by spec + dds_instance_handle_t lastih = 0; + int cursor = -1; + int count[2] = { 0, 0 }; + bool matchok = true; + printf ("{"); + for (int i = 0; i < n; i++) + { + const Space_Type1 *s = raw[i]; + entname_t wrname; + count[si[i].valid_data]++; + printf ("%s%c%c%c", + (i > 0) ? "," : "", + (si[i].sample_state == DDS_NOT_READ_SAMPLE_STATE) ? 'f' : 's', + (si[i].instance_state == DDS_ALIVE_INSTANCE_STATE) ? 'a' : (si[i].instance_state == DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE) ? 'u' : 'd', + (si[i].view_state == DDS_NEW_VIEW_STATE) ? 'n' : 'o'); + if (si[i].valid_data) + printf ("(%"PRId32",%"PRId32",%"PRId32")", s->long_1, s->long_2, s->long_3); + else + printf ("%"PRId32, s->long_1); + if (!wrname_from_pubhandle (ctx, ent, si[i].publication_handle, &wrname)) + error (ctx, "%s: unknown publication handle received", name); + printf ("%s", wrname.n); + print_timestamp (ctx, si[i].source_timestamp); + if (!doreadlike_matchstep (&si[i], s, exp, nexp, ellipsis, &tomatch, &cursor, &lastih, &matchidx[i])) + matchok = false; + } + printf ("}:"); + for (int i = 0; i < n; i++) + printf (" %d", matchidx[i]); + if (tomatch != 0) + { + printf (" (samples missing)"); + matchok = false; + } + printf (" valid %d %d invalid %d %d", count[1], exp_nvalid, count[0], exp_ninvalid); + if (exp_nvalid >= 0 && (count[1] != exp_nvalid)) + matchok = false; + if (exp_ninvalid >= 0 && (count[0] != exp_ninvalid)) + matchok = false; + printf ("\n"); + fflush (stdout); + if (!matchok) + testfail (ctx, "%s: mismatch between actual and expected set\n", name); +#undef MAXN +} + +static void dotake (struct oneliner_ctx *ctx) { doreadlike (ctx, "take", dds_take); } +static void doread (struct oneliner_ctx *ctx) { doreadlike (ctx, "read", dds_read); } + +static void dowritelike (struct oneliner_ctx *ctx, const char *name, bool fail, dds_return_t (*fn) (dds_entity_t wr, const void *sample, dds_time_t ts)) +{ + dds_return_t ret; + dds_time_t ts = dds_time (); + bool valid_data; + int ent; + Space_Type1 sample; + if ((ent = parse_entity (ctx)) < 0) + error (ctx, "%s: expecting entity", name); + if (ctx->es[ent] == 0) + make_entity (ctx, ent, NULL); + if (!parse_sample_value (ctx, &sample, &valid_data, 0)) + error (ctx, "%s: expecting sample value", name); + if (nexttok_if (&ctx->l, TOK_TIMESTAMP)) + ts = ctx->l.v.d; + printf ("entity %"PRId32": %s (%"PRId32",%"PRId32",%"PRId32")", ctx->es[ent], name, sample.long_1, sample.long_2, sample.long_3); + print_timestamp (ctx, ts); + printf ("\n"); + ret = fn (ctx->es[ent], &sample, ts); + if (!fail) + { + if (ret != 0) + error_dds (ctx, ret, "%s: failed", name); + } + else + { + if (ret == 0) + testfail (ctx, "%s: succeeded unexpectedly", name); + else if (ret != DDS_RETCODE_TIMEOUT) + error_dds (ctx, ret, "%s: failed", name); + } +} + +static void dowr (struct oneliner_ctx *ctx) { dowritelike (ctx, "wr", false, dds_write_ts); } +static void dowrfail (struct oneliner_ctx *ctx) { dowritelike (ctx, "wrfail", true, dds_write_ts); } +static void dowrdisp (struct oneliner_ctx *ctx) { dowritelike (ctx, "wrdisp", false, dds_writedispose_ts); } +static void dowrdispfail (struct oneliner_ctx *ctx) { dowritelike (ctx, "wrdispfail", true, dds_writedispose_ts); } +static void dodisp (struct oneliner_ctx *ctx) { dowritelike (ctx, "disp", false, dds_dispose_ts); } +static void dodispfail (struct oneliner_ctx *ctx) { dowritelike (ctx, "dispfail", true, dds_dispose_ts); } +static void dounreg (struct oneliner_ctx *ctx) { dowritelike (ctx, "unreg", false, dds_unregister_instance_ts); } +static void dounregfail (struct oneliner_ctx *ctx) { dowritelike (ctx, "unregfail", true, dds_unregister_instance_ts); } + +static int checkstatus (struct oneliner_ctx *ctx, int ll, int ent, struct oneliner_lex *argl, const void *status) +{ + assert (lldesc[ll].desc != NULL); + const char *d = lldesc[ll].desc; + int field = 0; + const char *sep = "("; + size_t off = 0; + if (nexttok (argl, NULL) != '(') + abort (); + while (*d) + { + const void *p = advance (status, &off, *d); + int i; + switch (*d) + { + case 'n': + if (!nexttok_int (argl, &i) || i < 0) + return setresult (ctx, -1, "checkstatus: field %d expecting non-negative integer", field); + printf ("%s%"PRIu32" %d", sep, *(uint32_t *)p, i); fflush (stdout); + if (*(uint32_t *)p != (uint32_t)i) + return setresult (ctx, 0, "checkstatus: field %d has actual %"PRIu32" expected %d", field, *(uint32_t *)p, i); + break; + case 'c': + if (!nexttok_int (argl, &i)) + return setresult (ctx, -1, "checkstatus: field %d expecting integer", field); + printf ("%s%"PRId32" %d", sep, *(int32_t *)p, i); fflush (stdout); + if (*(int32_t *)p != i) + return setresult (ctx, 0, "checkstatus: field %d has actual %"PRId32" expected %d", field, *(int32_t *)p, i); + break; + case 'P': + if (nexttok (argl, NULL) != TOK_NAME) + return setresult (ctx, -1, "checkstatus: field %d expecting policy name", field); + size_t polidx; + for (polidx = 0; polidx < sizeof (qostab) / sizeof (qostab[0]); polidx++) + if (strcmp (argl->v.n, qostab[polidx].abbrev) == 0) + break; + if (polidx == sizeof (qostab) / sizeof (qostab[0])) + return setresult (ctx, -1, "checkstatus: field %d expecting policy name", field); + printf ("%s%"PRIu32" %"PRIu32, sep, *(uint32_t *)p, (uint32_t) qostab[polidx].id); fflush (stdout); + if (*(uint32_t *)p != (uint32_t) qostab[polidx].id) + return setresult (ctx, 0, "checkstatus: field %d has actual %"PRIu32" expected %d", field, *(uint32_t *)p, (int) qostab[polidx].id); + break; + case 'R': + if (nexttok (argl, NULL) != TOK_NAME) + return setresult (ctx, -1, "checkstatus: field %d expecting reason", field); + if (strcmp (argl->v.n, "i") == 0) i = (int) DDS_REJECTED_BY_INSTANCES_LIMIT; + else if (strcmp (argl->v.n, "s") == 0) i = (int) DDS_REJECTED_BY_SAMPLES_LIMIT; + else if (strcmp (argl->v.n, "spi") == 0) i = (int) DDS_REJECTED_BY_SAMPLES_PER_INSTANCE_LIMIT; + else return setresult (ctx, -1, "checkstatus: field %d expecting reason", field); + printf ("%s%d %d", sep, (int) *(dds_sample_rejected_status_kind *)p, i); fflush (stdout); + if (*(dds_sample_rejected_status_kind *)p != (dds_sample_rejected_status_kind) i) + return setresult (ctx, 0, "checkstatus: field %d has actual %d expected %d", field, (int) (*(dds_sample_rejected_status_kind *)p), i); + break; + case 'I': // instance handle is too complicated + break; + case 'E': { + int ent1 = -1; + dds_instance_handle_t esi1 = 0; + if (nexttok_if (argl, '*')) + ent1 = -1; + else if ((ent1 = parse_entity1 (argl, NULL)) < 0) + return setresult (ctx, -1, "checkstatus: field %d expecting * or entity name", field); + else if ((esi1 = lookup_insthandle (ctx, ent, ent1)) == 0) + return setresult (ctx, -1, "checkstatus: field %d instance handle lookup failed", field); + printf ("%s%"PRIx64" %"PRIx64, sep, *(dds_instance_handle_t *)p, esi1); fflush (stdout); + if (ent1 >= 0 && *(dds_instance_handle_t *)p != esi1) + return setresult (ctx, 0, "checkstatus: field %d has actual %"PRIx64" expected %"PRIx64, field, *(dds_instance_handle_t *)p, esi1); + break; + } + default: + return DDS_RETCODE_BAD_PARAMETER; + } + sep = ", "; + if (*d != 'I') + field++; + ++d; + if (*d && *d != 'I' && !nexttok_if (argl, ',')) + return setresult (ctx, -1, "checkstatus: field %d expecting ','", field); + } + printf (")"); + if (!nexttok_if (argl, ')')) + return setresult (ctx, -1, "checkstatus: field %d expecting ')'", field); + assert (off <= lldesc[ll].size); + return 1; +} + +static void checklistener (struct oneliner_ctx *ctx, int ll, int ent, struct oneliner_lex *argl) +{ + bool signalled = true; + uint32_t min_cnt = 1, max_cnt = UINT32_MAX; + uint32_t status; + const int dom = ent / 9; + dds_return_t ret; + printf ("listener %s: check called for entity %"PRId32, lldesc[ll].name, ctx->es[ent]); + fflush (stdout); + if (argl && lldesc[ll].cb_status_off == 0) + { + // those that don't have a status can check the number of invocations + int cnt = -1; + if (!(nexttok_if (argl, '(') && nexttok_int (argl, &cnt) && nexttok_if (argl, ')'))) + error (ctx, "listener %s: expecting (COUNT)", lldesc[ll].name); + if (cnt < 0) + error (ctx, "listener %s: invocation count must be at least 0", lldesc[ll].name); + min_cnt = max_cnt = (uint32_t) cnt; + } + ddsrt_mutex_lock (&ctx->g_mutex); + bool cnt_ok = (ctx->cb[dom].cb_called[lldesc[ll].id] >= min_cnt && ctx->cb[dom].cb_called[lldesc[ll].id] <= max_cnt); + while (ctx->cb[dom].cb_called[lldesc[ll].id] < min_cnt && signalled) + { + signalled = ddsrt_cond_waitfor (&ctx->g_cond, &ctx->g_mutex, DDS_SECS (5)); + cnt_ok = (ctx->cb[dom].cb_called[lldesc[ll].id] >= min_cnt && ctx->cb[dom].cb_called[lldesc[ll].id] <= max_cnt); + } + printf (" cb_called %"PRIu32" (%s)", ctx->cb[dom].cb_called[lldesc[ll].id], cnt_ok ? "ok" : "fail"); + fflush (stdout); + if (!cnt_ok) + { + ddsrt_mutex_unlock (&ctx->g_mutex); + testfail (ctx, "listener %s: not invoked [%"PRIu32",%"PRIu32"] times", lldesc[ll].name, min_cnt, max_cnt); + } + dds_entity_t * const cb_entity = (dds_entity_t *) ((char *) &ctx->cb[dom] + lldesc[ll].cb_entity_off); + printf (" cb_entity %"PRId32" %"PRId32" (%s)", *cb_entity, ctx->es[ent], (*cb_entity == ctx->es[ent]) ? "ok" : "fail"); + fflush (stdout); + if (*cb_entity != ctx->es[ent]) + { + ddsrt_mutex_unlock (&ctx->g_mutex); + testfail (ctx, "listener %s: invoked on %"PRId32" instead of %"PRId32, lldesc[ll].name, *cb_entity, ctx->es[ent]); + } + if (!(ctx->doms[0] && ctx->doms[1])) + { + // FIXME: two domains: listener invocation happens on another thread and we can observe non-0 "change" fields + // they get updated, listener gets invoked, then they get reset -- pretty sure it is allowed by the spec, but + // not quite elegant + if ((ret = check_status_change_fields_are_0 (ll, ctx->es[ent])) <= 0) + { + ddsrt_mutex_unlock (&ctx->g_mutex); + if (ret == 0) + testfail (ctx, "listener %s: status contains non-zero change fields", lldesc[ll].name); + else if (ret < 0) + error_dds (ctx, ret, "listener %s: get entity status failed", lldesc[ll].name); + } + } + if (argl && lldesc[ll].cb_status_off != 0) + { + void *cb_status = (char *) &ctx->cb[dom] + lldesc[ll].cb_status_off; + if (checkstatus (ctx, ll, ent, argl, cb_status) <= 0) + { + ddsrt_mutex_unlock (&ctx->g_mutex); + longjmp (ctx->jb, 1); + } + } + printf ("\n"); + ctx->cb[dom].cb_called[lldesc[ll].id] = 0; + ddsrt_mutex_unlock (&ctx->g_mutex); + if ((ret = dds_get_status_changes (ctx->es[ent], &status)) != 0) + error_dds (ctx, ret, "listener %s: dds_get_status_change on %"PRId32, lldesc[ll].name, ctx->es[ent]); + if ((status & (1u << lldesc[ll].id)) != 0) + testfail (ctx, "listener %s: status mask not cleared", lldesc[ll].name); +} + +static void dochecklistener (struct oneliner_ctx *ctx) +{ + const bool expectclear = nexttok_if (&ctx->l, '!'); + const int ll = parse_listener (ctx); + if (ll < 0) + error (ctx, "check listener: requires listener name"); + else if (expectclear) + { + printf ("listener %s: check not called", lldesc[ll].name); + fflush (stdout); + ddsrt_mutex_lock (&ctx->g_mutex); + bool ret = true; + for (int i = 0; i < (int) (sizeof (ctx->doms) / sizeof (ctx->doms[0])); i++) + { + printf (" cb_called %"PRIu32" %s\n", ctx->cb[i].cb_called[lldesc[ll].id], ctx->cb[i].cb_called[lldesc[ll].id] == 0 ? "ok" : "fail"); + if (ctx->cb[i].cb_called[lldesc[ll].id] != 0) + ret = false; + } + ddsrt_mutex_unlock (&ctx->g_mutex); + if (!ret) + testfail (ctx, "callback %s invoked unexpectedly", lldesc[ll].name); + } + else + { + struct oneliner_lex l1 = ctx->l; + // no whitespace between name and args + const bool have_args = (*ctx->l.inp == '('); + if (have_args) + { + // skip args: we need the entity before we can interpret them + int tok; + while ((tok = nexttok (&ctx->l, NULL)) != EOF && tok != ')') + ; + } + const int ent = parse_entity (ctx); + if (ent < 0) + error (ctx, "check listener: requires an entity"); + if (ctx->es[ent] == 0) + setlistener (ctx, NULL, ll, ent); + checklistener (ctx, ll, ent, have_args ? &l1 : NULL); + } +} + +static void dodelete (struct oneliner_ctx *ctx) +{ + dds_return_t ret; + int ent; + if ((ent = parse_entity (ctx)) < 0) + error (ctx, "delete: requires entity"); + if ((ret = dds_delete (ctx->es[ent])) != 0) + error_dds (ctx, ret, "delete: failed on %"PRId32, ctx->es[ent]); + ctx->es[ent] = 0; +} + +static void dodeaf (struct oneliner_ctx *ctx) +{ + dds_return_t ret; + entname_t name; + int ent; + if ((ent = parse_entity (ctx)) < 0 || (ent % 9) != 0) + error (ctx, "deaf: requires participant"); + printf ("deaf: %s\n", getentname (&name, ent)); + if ((ret = dds_domain_set_deafmute (ctx->es[ent], true, false, DDS_INFINITY)) != 0) + error_dds (ctx, ret, "deaf: dds_domain_set_deafmute failed on %"PRId32, ctx->es[ent]); + // speed up the process by forcing lease expiry + dds_entity *x, *xprime; + if ((ret = dds_entity_pin (ctx->es[ent], &x)) < 0) + error_dds (ctx, ret, "deaf: pin participant failed %"PRId32, ctx->es[ent]); + for (int i = 0; i < (int) (sizeof (ctx->doms) / sizeof (ctx->doms[0])); i++) + { + if (i == ent / 9 || ctx->es[9*i] == 0) + continue; + if ((ret = dds_entity_pin (ctx->es[9*i], &xprime)) < 0) + { + dds_entity_unpin (x); + error_dds (ctx, ret, "deaf: pin counterpart participant failed %"PRId32, ctx->es[9*i]); + } + thread_state_awake (lookup_thread_state (), &x->m_domain->gv); + delete_proxy_participant_by_guid (&x->m_domain->gv, &xprime->m_guid, ddsrt_time_wallclock (), true); + thread_state_asleep (lookup_thread_state ()); + dds_entity_unpin (xprime); + } + dds_entity_unpin (x); +} + +static void dohearing (struct oneliner_ctx *ctx) +{ + dds_return_t ret; + entname_t name; + int ent; + if ((ent = parse_entity (ctx)) < 0 || (ent % 9) != 0) + error (ctx, "hearing: requires participant"); + printf ("hearing: %s\n", getentname (&name, ent)); + if ((ret = dds_domain_set_deafmute (ctx->es[ent], false, false, DDS_INFINITY)) != 0) + error_dds (ctx, ret, "hearing: dds_domain_set_deafmute failed %"PRId32, ctx->es[ent]); + // speed up the process by forcing SPDP publication on the remote + for (int i = 0; i < (int) (sizeof (ctx->doms) / sizeof (ctx->doms[0])); i++) + { + if (i == ent / 9 || ctx->es[9*i] == 0) + continue; + dds_entity *xprime; + struct participant *pp; + if ((ret = dds_entity_pin (ctx->es[9*i], &xprime)) < 0) + error_dds (ctx, ret, "hearing: pin counterpart participant failed %"PRId32, ctx->es[9*i]); + thread_state_awake (lookup_thread_state (), &xprime->m_domain->gv); + if ((pp = entidx_lookup_participant_guid (xprime->m_domain->gv.entity_index, &xprime->m_guid)) != NULL) + resched_xevent_if_earlier (pp->spdp_xevent, ddsrt_mtime_add_duration (ddsrt_time_monotonic (), DDS_MSECS (100))); + thread_state_asleep (lookup_thread_state ()); + dds_entity_unpin (xprime); + } +} + +static void dosleep (struct oneliner_ctx *ctx) +{ + if (nexttok_dur (&ctx->l, NULL, true) != TOK_DURATION) + error (ctx, "sleep: invalid duration"); + dds_sleepfor (ctx->l.v.d); +} + +static void dispatchcmd (struct oneliner_ctx *ctx) +{ + static const struct { + const char *name; + void (*fn) (struct oneliner_ctx *ct); + } cs[] = { + { "-", dodelete }, + { "?", dochecklistener }, + { "wr", dowr }, + { "wrdisp", dowrdisp }, + { "disp", dodisp }, + { "unreg", dounreg }, + { "wrfail", dowrfail }, + { "wrdispfail", dowrdispfail }, + { "dispfail", dodispfail }, + { "unregfail", dounregfail }, + { "take", dotake }, + { "read", doread }, + { "deaf", dodeaf }, + { "hearing", dohearing }, + { "sleep", dosleep } + }; + size_t i; + if (ctx->l.tok > 0) + { + // convert single-character token to string + ctx->l.v.n[0] = (char) ctx->l.tok; + ctx->l.v.n[1] = 0; + } + for (i = 0; i < sizeof (cs) / sizeof (cs[0]); i++) + if (strcmp (ctx->l.v.n, cs[i].name) == 0) + break; + if (i == sizeof (cs) / sizeof (cs[0])) + error (ctx, "%s: unknown command", ctx->l.v.n); + cs[i].fn (ctx); +} + +static void dosetlistener (struct oneliner_ctx *ctx, int ll) +{ + int ent; + struct oneliner_lex l1 = ctx->l; + // scan past listener names to get at the entity, which we need + // to get the right listener object (and hence argument) + while (parse_listener1 (&ctx->l) >= 0) + ; + if ((ent = parse_entity (ctx)) < 0) + error (ctx, "set listener: entity required"); + setlistener (ctx, &l1, ll, ent); +} + +static void test_oneliner_step1 (struct oneliner_ctx *ctx) +{ + while (peektok (&ctx->l, NULL) != TOK_END) + { + int ent, ll; + if (nexttok_if (&ctx->l, ';')) + ; // skip ;s + else if ((ent = parse_entity (ctx)) >= 0) + make_entity (ctx, ent, NULL); + else if ((ll = parse_listener (ctx)) >= 0) + dosetlistener (ctx, ll); + else if (nexttok (&ctx->l, NULL) == TOK_NAME || ctx->l.tok > 0) + dispatchcmd (ctx); + else + error (ctx, "unexpected token %d", ctx->l.tok); + } +} + +void test_oneliner_init (struct oneliner_ctx *ctx) +{ + dds_qos_t *qos = dds_create_qos (); + dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_MSECS (100)); + dds_qset_destination_order (qos, DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP); + dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, 0); + + *ctx = (struct oneliner_ctx) { + .l = { .tref = dds_time () }, + .qos = qos, + .rwqos = dds_create_qos (), + .result = 1, + .cb = { + [0] = { .ctx = ctx, .list = dds_create_listener (&ctx->cb[0]) }, + [1] = { .ctx = ctx, .list = dds_create_listener (&ctx->cb[1]) }, + [2] = { .ctx = ctx, .list = dds_create_listener (&ctx->cb[2]) } + } + }; + + ddsrt_mutex_init (&ctx->g_mutex); + ddsrt_cond_init (&ctx->g_cond); + + create_unique_topic_name ("ddsc_listener_test", ctx->topicname, sizeof (ctx->topicname)); +} + +int test_oneliner_step (struct oneliner_ctx *ctx, const char *ops) +{ + if (ctx->result > 0 && setjmp (ctx->jb) == 0) + { + ctx->l.inp = ops; + test_oneliner_step1 (ctx); + } + return ctx->result; +} + +const char *test_oneliner_message (const struct oneliner_ctx *ctx) +{ + return ctx->msg; +} + +int test_oneliner_fini (struct oneliner_ctx *ctx) +{ + for (size_t i = 0; i < sizeof (ctx->cb) / sizeof (ctx->cb[0]); i++) + dds_delete_listener (ctx->cb[i].list); + dds_delete_qos (ctx->rwqos); + dds_delete_qos ((dds_qos_t *) ctx->qos); + // prevent any listeners from being invoked so we can safely delete the + // mutex and the condition variable -- must do this going down the + // hierarchy, or listeners may remain set through inheritance + dds_return_t ret; + for (size_t i = 0; i < sizeof (ctx->es) / sizeof (ctx->es[0]); i++) + if (ctx->es[i] && (ret = dds_set_listener (ctx->es[i], NULL)) != 0) + setresult (ctx, ret, "terminate: reset listener failed on %"PRId32, ctx->es[i]); + if (ctx->result == 0) + { + printf ("\n"); + for (int i = 0; i < (int) (sizeof (ctx->doms) / sizeof (ctx->doms[0])); i++) + { + for (int j = 3; j <= 5; j++) + { + if (ctx->es[9*i + j]) + { + const char *inp_orig = ctx->l.inp; + entname_t n; + ctx->l.inp = getentname (&n, 9*i + j); + doreadlike (ctx, "read", dds_read); + ctx->l.inp = inp_orig; + } + } + } + } + ddsrt_mutex_destroy (&ctx->g_mutex); + ddsrt_cond_destroy (&ctx->g_cond); + for (size_t i = 0; i < sizeof (ctx->doms) / sizeof (ctx->doms[0]); i++) + if (ctx->doms[i] && (ret = dds_delete (ctx->doms[i])) != 0) + setresult (ctx, ret, "terminate: delete domain on %"PRId32, ctx->doms[i]); + return ctx->result; +} + +int test_oneliner (const char *ops) +{ + struct oneliner_ctx ctx; + printf ("dotest: %s\n", ops); + test_oneliner_init (&ctx); + test_oneliner_step (&ctx, ops); + if (test_oneliner_fini (&ctx) <= 0) + fprintf (stderr, "FAIL: %s\n", test_oneliner_message (&ctx)); + return ctx.result; +} diff --git a/src/core/ddsc/tests/test_oneliner.h b/src/core/ddsc/tests/test_oneliner.h new file mode 100644 index 0000000..1a8b75e --- /dev/null +++ b/src/core/ddsc/tests/test_oneliner.h @@ -0,0 +1,326 @@ +/* + * Copyright(c) 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef _TEST_ONELINER_H_ +#define _TEST_ONELINER_H_ + +#include +#include + +#include "dds/dds.h" +#include "dds/ddsrt/sync.h" + +/** @brief run a "test" consisting of a sequence of simplish operations + * + * This operation takes a test description, really a program in a bizarre syntax, and + * executes it. Any failures, be it because of error codes coming out of the Cyclone + * calls or expected values being wrong cause it to fail the test via CU_ASSERT_FATAL. + * While it is doing this, it outputs the test steps to stdout including some actual + * values. An invalid program is mostly reported by calling abort(). It is geared towards + * checking for listener invocations and the effects on statuses. + * + * Entities in play: + * + * - participants: P P' P'' + * - subscribers: R R' R'' + * - publishers: W W' W'' + * - readers: r s t r' s' t' r'' s'' t'' + * - writers: w x y w' x' y' w'' x'' y'' + * + * The unprimed ones exist in domain 0, the primed ones in domain 1 (but configured such + * that it talks to domain 0), and the double-primed ones in domain 2 (again configured such + * that it talks to domain 0) so that network-related listener invocations can be checked + * as well. + * + * The first mention of an entity creates it as well as its ancestors. Implicitly created + * ancestors always have standard QoS and have no listeners. There is one topic that is + * created implicitly when the participant is created. + * + * Standard QoS is: default + reliable (100ms), by-source-timestamp, keep-all. The QoS of + * a reader/writer can be overridden at the first mention of it (i.e., when it is created) + * by appending a list of QoS overrides between parentheses. + * + * A program consists of a sequence of operations separated by whitespace, ';' or '/' + * (there is no meaning to the separators, they exist to allow visual grouping): + * + * PROGRAM ::= (OP (\s+|;)*)* + * + * OP ::= (LISTENER)* ENTITY-NAME[(QOS[,QOS[,QOS...]])] + * + * If entity ENTITY-NAME does not exist: + * creates the entity with the given listeners installed + * QOS can be used to override the standard QoS + * else + * changes the entity's listeners to the specified ones + * (see above for the valid ENTITY-NAMEs) + * + * | -ENTITY-NAME + * + * Deletes the specified entity + * + * | WRITE-LIKE[fail] ENTITY-NAME K[@DT] + * | WRITE-LIKE[fail] ENTITY-NAME (K,X,Y)[@DT] + * + * Writes/disposes/unregisters (K,0,0) (first form) or (K,X,Y). If + * "fail" is appended, the expectation is that it fails with a + * timeout, if @DT is appended, the timestamp is the start time of + * the test +
    s rather than the current time; DT is a + * floating-point number + * + * | READ-LIKE ENTITY-NAME + * | READ-LIKE(A,B) ENTITY-NAME + * | READ-LIKE{[S1[,S2[,S3...]][,...]} ENTITY-NAME + * + * Reads/takes at most 10 samples. The second form counts the + * number of valid and invalid samples seen and checks them against + * A and B. + * + * In the third form, the exact result set is given by the sample + * Si, which is a comma-separated list of samples: + * + * [STATE]K[ENTITY-NAME][@DT] + * [STATE](K,X,Y)[ENTITY-NAME][@DT] + * + * The first form is an invalid sample with only the (integer) key + * value K, the second form also specifies the two (integer) + * attribute fields. + * + * STATE specifies allowed sample (f - not-read (fresh), s - read + * (stale)), instance (a - alive, u - no-writers (unregistered) d - + * disposed) and view states (n - new, o - old). If no sample state + * is specified, all sample states are allowed, &c. + * + * ENTITY-NAME is the name of the publishing writer expected in the + * publication_handle. Not specifying a writer means any writer is + * ok. DT is the timestamp in the same manner as the write-like + * operations. Not specifying a timestamp means any timestamp is + * ok. + * + * If the expected set ends up with "..." there may be other samples + * in the result as well. + * + * | ?LISTENER[(ARGS)] ENTITY-NAME + * + * Waits until the specified listener has been invoked on using a flag set by the listener function, resets the flag + * and verifies that neither the entity status bit nor the "change" + * fields in the various statuses were set. + * + * ARGS is used to check the status argument most recently passed to + * the listener: + * + * da(A) verifies that it has been invoked A times + * dor(A) see da + * it(A,B) verifies count and change match A and B, policy + * matches RELIABILITY + * lc(A,B,C,D,E) verifies that alive and not-alive counts match A + * and B, that alive and not-alive changes match C and D + * and that the last handle matches E if an entity name + * (ignored if E = "*") + * ll (A,B) verifies count and change match A and B + * odm (A,B) verifies count and change match A and B, last handle + * is ignored + * oiq (A,B,C) verifies that total count and change match A and B + * and that the mismatching QoS is C (using the same + * abbreviations as used for defining QoS on entity + * creation) + * pm (A,B,C,D,E) verifies that total count and change match A and + * B, that current count and change match C and D and + * that the last handle matches E if an entity name + * (ignored if E = "*") + * rdm see odm + * riq see oiq + * sl (A,B) verifies that total count and change match A and B + * sr (A,B,C) verifies total count and change match A and B, and + * that the reason matches C (one of "s" for samples, + * "i" for instances, "spi" for samples per instance) + * sm see pm + * + * | ?!LISTENER + * + * (Not listener) tests that LISTENER has not been invoked since + * last reset + * + * | sleep D + * + * Delay program execution for D s (D is a floating-point number) + * + * | deaf ENTITY-NAME + * | hearing ENTITY-NAME + * + * Makes the domain wherein the specified entity exists deaf, + * respectively restoring hearing. The entity must be either P or + * P' and both must exist. Plays some tricks to speed up lease + * expiry and reconnection (like forcibly deleting a proxy + * participant or triggering the publication of SPDP packets). + * + * WRITE-LIKE ::= wr write + * | wrdisp write-dispose + * | disp dispose + * | unreg unregister + * + * READ-LIKE ::= read dds_read (so any state) + * | take dds_take (so any state) + * + * LISTENER ::= da data available (acts on a reader) + * | dor data on readers (acts on a subcsriber) + * | it incompatible topic (acts on a topic) + * | lc liveliness changed (acts on a reader) + * | ll liveliness lost (acts on a writer) + * | odm offered deadline missed (acts on a writer) + * | oiq offered incompatible QoS (acts on a writer) + * | pm publication matched (acts on a writer) + * | rdm requested deadline missed (acts on a reader) + * | riq requested incompatible QoS (acts on a reader) + * | sl sample lost (acts on a reader) + * | sr sample rejected (acts on a reader) + * | sm subscription matched (acts on a reader) + * + * QOS ::= ad={y|n} auto-dispose unregistered instances + * | d={v|tl|t|p} durability + * | dl={inf|DT} deadline (infinite or DT seconds) + * | ds=DT/H/RL durability service: cleanup delay, history, + * resource limits + * | do={r|s} by-reception or by-source destination order + * | h={N|all} history keep-last-N or keep-all + * | lb={inf|DT} latency budget + * | ll={a[:DT]|p:DT|w:DT} liveliness (automatic, manual by + * participant, manual by topic) + * | ls={inf|DT} lifespan + * | o={s|x[:N]} ownership shared or exclusive (strength N) + * | p={i|t|g} presentation: instance, coherent-topic or + * coherent-group + * | r={be|r[:DT]} best-effort or reliable (with max blocking time) + * | rl=N[/N[/N]] resource limits (sample, instances, samples per + * instance; "inf" is allowed, ommitted ones are + * unlimited) + * | tp=N transport-priority + * | ud=... user data (with escape sequences and hex/octal + * input allowed) + * + * All entities share the listeners with their global state. Only the latest invocation is visible. + * + * @param[in] ops Program to execute. + * + * @return > 0 success, 0 failure, < 0 invalid input + */ +int test_oneliner (const char *ops); + +union oneliner_tokval { + int i; + int64_t d; + char n[32]; +}; + +struct oneliner_lex { + const char *inp; + dds_time_t tref; + int tok; + union oneliner_tokval v; +}; + +struct oneliner_ctx; + +struct oneliner_cb { + struct oneliner_ctx *ctx; + dds_listener_t *list; + uint32_t cb_called[DDS_STATUS_ID_MAX + 1]; + dds_entity_t cb_topic, cb_writer, cb_reader, cb_subscriber; + dds_inconsistent_topic_status_t cb_inconsistent_topic_status; + dds_liveliness_changed_status_t cb_liveliness_changed_status; + dds_liveliness_lost_status_t cb_liveliness_lost_status; + dds_offered_deadline_missed_status_t cb_offered_deadline_missed_status; + dds_offered_incompatible_qos_status_t cb_offered_incompatible_qos_status; + dds_publication_matched_status_t cb_publication_matched_status; + dds_requested_deadline_missed_status_t cb_requested_deadline_missed_status; + dds_requested_incompatible_qos_status_t cb_requested_incompatible_qos_status; + dds_sample_lost_status_t cb_sample_lost_status; + dds_sample_rejected_status_t cb_sample_rejected_status; + dds_subscription_matched_status_t cb_subscription_matched_status; +}; + +struct oneliner_ctx { + struct oneliner_lex l; + + dds_entity_t es[3 * 9]; + dds_entity_t tps[3]; + dds_entity_t doms[3]; + dds_instance_handle_t esi[3 * 9]; + // built-in topic readers for cross-referencing instance handles + dds_entity_t pubrd[3]; + dds_entity_t subrd[3]; + // topic name used for data + char topicname[100]; + + const dds_qos_t *qos; + dds_qos_t *rwqos; + + int result; + char msg[256]; + + jmp_buf jb; + + ddsrt_mutex_t g_mutex; + ddsrt_cond_t g_cond; + struct oneliner_cb cb[3]; +}; + +/** @brief Initialize a "oneliner test" context + * + * @param[out] ctx context to initialize + */ +void test_oneliner_init (struct oneliner_ctx *ctx); + +/** @brief Run a sequence of operations in an initialized context + * + * If the context indicates a preceding step has failed, this is a + * no-op and the previous result is propagated to the return value. + * + * @param[in,out] ctx context to operate in + * @param[in] ops sequence of operations to execute (@ref test_oneliner) + * + * @return integer indicating success or failure + * + * @retval 1 success + * @retval 0 test failure + * @retval <0 syntax error unexpected error + */ +int test_oneliner_step (struct oneliner_ctx *ctx, const char *ops); + +/** @brief Get a pointer to the error message from a "oneliner test" + * + * If a preceding step has failed, this returns a pointer to a message + * containing some information about the failure. If no error + * occurred, the message is meaningless. + * + * + * @param[in] ctx context to retrieve message from + * + * @return pointer to null-terminated string aliasing a string in ctx + */ +const char *test_oneliner_message (const struct oneliner_ctx *ctx); + +/** @brief Deinitialize a "oneliner test" context + * + * This releases all resources used by the context. + * + * @param[in,out] ctx context to operate in + * + * @return integer indicating success or failure in any of the + * preceding steps. If no steps were taken, the result is success. + * + * @retval 1 success + * @retval 0 test failure + * @retval <0 syntax error unexpected error + */ +int test_oneliner_fini (struct oneliner_ctx *ctx); + +#endif diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 9d2765e..14f59f8 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -696,7 +696,7 @@ int writer_set_notalive (struct writer *wr, bool notify); #define CF_PROXYPP_NO_SPDP (1 << 2) void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct ddsi_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, ddsrt_wctime_t timestamp, seqno_t seq); -int delete_proxy_participant_by_guid (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, ddsrt_wctime_t timestamp, int isimplicit); +DDS_EXPORT int delete_proxy_participant_by_guid (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, ddsrt_wctime_t timestamp, int isimplicit); int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, seqno_t seq, const struct ddsi_plist *datap, ddsrt_wctime_t timestamp); int update_proxy_participant_plist (struct proxy_participant *proxypp, seqno_t seq, const struct ddsi_plist *datap, ddsrt_wctime_t timestamp); From bb95de69c362c7b51fe2d643bc960a9e0472adeb Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Thu, 7 May 2020 14:43:20 +0200 Subject: [PATCH 222/238] Instance to ALIVE also for rejected samples In particular, this means instances published by a transient-local writer will go back to ALIVE following a disconnect and reconnect. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_rhc_default.c | 33 +++++++++++++++++++++-------- src/core/ddsc/tests/listener.c | 12 ++++++++--- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/core/ddsc/src/dds_rhc_default.c b/src/core/ddsc/src/dds_rhc_default.c index 9195cd9..4a56d32 100644 --- a/src/core/ddsc/src/dds_rhc_default.c +++ b/src/core/ddsc/src/dds_rhc_default.c @@ -1034,7 +1034,7 @@ static void drop_instance_noupdate_no_writers (struct dds_rhc_default *__restric *instptr = NULL; } -static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance *inst, uint64_t wr_iid, bool autodispose, bool iid_update, bool * __restrict nda) +static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance *inst, uint64_t wr_iid, bool autodispose, bool sample_accepted, bool * __restrict nda) { const uint64_t inst_wr_iid = inst->wr_iid_islive ? inst->wr_iid : 0; @@ -1061,12 +1061,16 @@ static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance * /* Currently no writers at all */ assert (!inst->wr_iid_islive); - /* to avoid wr_iid update when register is called for sample rejected */ - if (iid_update) - { - inst->wr_iid = wr_iid; + /* When registering a writer based on a rejected sample and causing + the instance to transition from not-alive to alive, we do want + to generate an invalid sample with the id of the newly registered + (or re-registered) writer, but we don't want inst_accepts_sample + to be affected (it was "too old" in the ordering). wr_iid_islive + determines whether wr_iid is meaningful, so setting wr_iid while + leaving wr_iid_islive false gets us the desired behaviour. */ + inst->wr_iid = wr_iid; + if (sample_accepted) inst->wr_iid_islive = 1; - } inst->wrcount++; inst->no_writers_gen++; inst->autodispose = autodispose; @@ -1108,7 +1112,7 @@ static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance * TRACE ("restore"); } /* to avoid wr_iid update when register is called for sample rejected */ - if (iid_update) + if (sample_accepted) { inst->wr_iid = wr_iid; inst->wr_iid_islive = 1; @@ -1136,7 +1140,6 @@ static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance * inst->wrcount++; if (autodispose) inst->autodispose = 1; - *nda = true; } else { @@ -1145,7 +1148,7 @@ static void dds_rhc_register (struct dds_rhc_default *rhc, struct rhc_instance * assert (inst->wrcount >= 2); /* the most recent writer gets the fast path */ /* to avoid wr_iid update when register is called for sample rejected */ - if (iid_update) + if (sample_accepted) { inst->wr_iid = wr_iid; inst->wr_iid_islive = 1; @@ -1568,7 +1571,19 @@ static bool dds_rhc_default_store (struct ddsi_rhc * __restrict rhc_common, cons get_trigger_info_pre (&pre, inst); if (has_data || is_dispose) + { dds_rhc_register (rhc, inst, wr_iid, wrinfo->auto_dispose, false, ¬ify_data_available); + if (notify_data_available) + { + if (inst->latest == NULL || inst->latest->isread) + { + const bool was_empty = inst_is_empty (inst); + inst_set_invsample (rhc, inst, &trig_qc, ¬ify_data_available); + if (was_empty) + account_for_empty_to_nonempty_transition (rhc, inst); + } + } + } /* notify sample lost */ cb_data.raw_status_id = (int) DDS_SAMPLE_LOST_STATUS_ID; diff --git a/src/core/ddsc/tests/listener.c b/src/core/ddsc/tests/listener.c index 2bd4112..378f0b3 100644 --- a/src/core/ddsc/tests/listener.c +++ b/src/core/ddsc/tests/listener.c @@ -380,12 +380,18 @@ CU_Test (ddsc_listener, incompatible_qos) CU_Test (ddsc_listener, data_available) { - // data available on reader + // data available on reader (+ absence of data-on-readers) dotest ("da sm r pm w ?pm w ?sm r wr w 0 ?da r ?!dor"); - // data available set on subscriber + // data available set on subscriber (+ absence of data-on-readers) dotest ("da R sm r pm w ?pm w ?sm r wr w 0 ?da r ?!dor"); - // data available set on participant + // data available set on participant (+ absence of data-on-readers) dotest ("da P sm r pm w ?pm w ?sm r wr w 0 ?da r ?!dor"); + + // non-auto-dispose, transient-local: disconnect => no_writers, reconnect => alive (using invalid samples) + // the invalid sample has the source time stamp of the latest update -- one wonders whether that is wise? + dotest ("da r(d=tl) ?pm w'(d=tl,ad=n) ; wr w' (1,2,3)@1.1 ?da r read{fan(1,2,3)w'} r ;" + " deaf P ; ?da r read{suo(1,2,3)w'@1.1,fuo1w'@1.1} r ;" + " hearing P ; ?da r read{sao(1,2,3)w'@1.1,fao1w'@1.1} r"); } CU_Test (ddsc_listener, data_available_delete_writer) From b9660e46c9a2f2944be6b653907e3c1dfe7d8a63 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 11 May 2020 14:08:12 +0200 Subject: [PATCH 223/238] Remove dead stores triggering clang warnings Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds_matched.c | 6 ++---- src/core/ddsc/src/dds_write.c | 3 +-- src/core/ddsi/src/ddsi_mcgroup.c | 2 +- src/core/ddsi/src/ddsi_security_omg.c | 6 ++---- src/core/ddsi/src/ddsi_udp.c | 6 +++--- src/core/ddsi/src/q_config.c | 3 +-- src/ddsrt/src/sync/posix/sync.c | 8 ++------ 7 files changed, 12 insertions(+), 22 deletions(-) diff --git a/src/core/ddsc/src/dds_matched.c b/src/core/ddsc/src/dds_matched.c index d2cc6a9..f10ab4c 100644 --- a/src/core/ddsc/src/dds_matched.c +++ b/src/core/ddsc/src/dds_matched.c @@ -144,8 +144,7 @@ static dds_builtintopic_endpoint_t *make_builtintopic_endpoint (const ddsi_guid_ dds_builtintopic_endpoint_t *dds_get_matched_subscription_data (dds_entity_t writer, dds_instance_handle_t ih) { dds_writer *wr; - dds_return_t rc; - if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK) + if (dds_writer_lock (writer, &wr)) return NULL; else { @@ -187,8 +186,7 @@ dds_builtintopic_endpoint_t *dds_get_matched_subscription_data (dds_entity_t wri dds_builtintopic_endpoint_t *dds_get_matched_publication_data (dds_entity_t reader, dds_instance_handle_t ih) { dds_reader *rd; - dds_return_t rc; - if ((rc = dds_reader_lock (reader, &rd)) != DDS_RETCODE_OK) + if (dds_reader_lock (reader, &rd)) return NULL; else { diff --git a/src/core/ddsc/src/dds_write.c b/src/core/ddsc/src/dds_write.c index a2b978b..cc0b1e8 100644 --- a/src/core/ddsc/src/dds_write.c +++ b/src/core/ddsc/src/dds_write.c @@ -267,8 +267,7 @@ void dds_write_flush (dds_entity_t writer) { struct thread_state1 * const ts1 = lookup_thread_state (); dds_writer *wr; - dds_return_t rc; - if ((rc = dds_writer_lock (writer, &wr)) == DDS_RETCODE_OK) + if (dds_writer_lock (writer, &wr) == DDS_RETCODE_OK) { thread_state_awake (ts1, &wr->m_entity.m_domain->gv); nn_xpack_send (wr->m_xp, true); diff --git a/src/core/ddsi/src/ddsi_mcgroup.c b/src/core/ddsi/src/ddsi_mcgroup.c index cd49444..b01b33e 100644 --- a/src/core/ddsi/src/ddsi_mcgroup.c +++ b/src/core/ddsi/src/ddsi_mcgroup.c @@ -203,7 +203,7 @@ static int joinleave_mcgroups (const struct ddsi_domaingv *gv, ddsi_tran_conn_t { if (gv->recvips_mode == RECVIPS_MODE_ALL || interface_in_recvips_p (gv->recvips, &gv->interfaces[i])) { - if ((rc = joinleave_mcgroup (conn, join, srcloc, mcloc, &gv->interfaces[i])) < 0) + if (joinleave_mcgroup (conn, join, srcloc, mcloc, &gv->interfaces[i]) < 0) fails++; else oks++; diff --git a/src/core/ddsi/src/ddsi_security_omg.c b/src/core/ddsi/src/ddsi_security_omg.c index 9ef815a..92c9529 100644 --- a/src/core/ddsi/src/ddsi_security_omg.c +++ b/src/core/ddsi/src/ddsi_security_omg.c @@ -2250,7 +2250,6 @@ static bool q_omg_security_register_remote_writer_match(struct proxy_writer *pwr struct dds_security_context *sc = q_omg_security_get_secure_context(pp); DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; struct proxypp_pp_match *proxypp_match; - struct rd_pwr_match *match; bool send_tokens = false; bool allowed = false; @@ -2258,7 +2257,7 @@ static bool q_omg_security_register_remote_writer_match(struct proxy_writer *pwr return false; ddsrt_mutex_lock(&rd->e.lock); - if ((match = ddsrt_avl_lookup (&rd_writers_treedef, &rd->writers, &pwr->e.guid)) != NULL) + if (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) { @@ -2584,7 +2583,6 @@ static bool q_omg_security_register_remote_reader_match(struct proxy_reader *prd struct dds_security_context *sc = q_omg_security_get_secure_context(pp); DDS_Security_SecurityException exception = DDS_SECURITY_EXCEPTION_INIT; struct proxypp_pp_match *proxypp_match; - struct wr_prd_match *match; bool send_tokens = false; bool allowed = false; @@ -2592,7 +2590,7 @@ static bool q_omg_security_register_remote_reader_match(struct proxy_reader *prd return false; ddsrt_mutex_lock(&wr->e.lock); - if ((match = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, &prd->e.guid)) != NULL) + if (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) { diff --git a/src/core/ddsi/src/ddsi_udp.c b/src/core/ddsi/src/ddsi_udp.c index 65d10fd..d67929d 100644 --- a/src/core/ddsi/src/ddsi_udp.c +++ b/src/core/ddsi/src/ddsi_udp.c @@ -477,11 +477,11 @@ static dds_return_t ddsi_udp_create_conn (ddsi_tran_conn_t *conn_out, ddsi_tran_ } } - if ((rc = set_rcvbuf (gv, sock, &gv->config.socket_min_rcvbuf_size)) != DDS_RETCODE_OK) + if (set_rcvbuf (gv, sock, &gv->config.socket_min_rcvbuf_size) != DDS_RETCODE_OK) goto fail_w_socket; - if ((rc = set_sndbuf (gv, sock, gv->config.socket_min_sndbuf_size)) != DDS_RETCODE_OK) + if (set_sndbuf (gv, sock, gv->config.socket_min_sndbuf_size) != DDS_RETCODE_OK) goto fail_w_socket; - if (gv->config.dontRoute && (rc = set_dont_route (gv, sock, ipv6)) != DDS_RETCODE_OK) + if (gv->config.dontRoute && set_dont_route (gv, sock, ipv6) != DDS_RETCODE_OK) goto fail_w_socket; if ((rc = ddsrt_bind (sock, &socketname.a, ddsrt_sockaddr_get_size (&socketname.a))) != DDS_RETCODE_OK) diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index 6bfb3de..e54c7e6 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -2246,14 +2246,13 @@ static int set_defaults (struct cfgst *cfgst, void *parent, int isattr, struct c int ok = 1; for (const struct cfgelem *ce = cfgelem; ce && ce->name; ce++) { - struct cfgst_node *n; struct cfgst_nodekey key; key.e = ce; key.p = parent; cfgst_push (cfgst, isattr, ce, parent); if (ce->multiplicity <= 1) { - if ((n = ddsrt_avl_lookup (&cfgst_found_treedef, &cfgst->found, &key)) == NULL) + if (ddsrt_avl_lookup (&cfgst_found_treedef, &cfgst->found, &key) == NULL) { if (ce->update) { diff --git a/src/ddsrt/src/sync/posix/sync.c b/src/ddsrt/src/sync/posix/sync.c index a7f92e8..7dcd203 100644 --- a/src/ddsrt/src/sync/posix/sync.c +++ b/src/ddsrt/src/sync/posix/sync.c @@ -159,22 +159,18 @@ ddsrt_cond_broadcast (ddsrt_cond_t *cond) void ddsrt_rwlock_init (ddsrt_rwlock_t *rwlock) { - int err = 0; - assert(rwlock != NULL); /* process-shared attribute is set to PTHREAD_PROCESS_PRIVATE by default */ - if ((err = pthread_rwlock_init(&rwlock->rwlock, NULL)) != 0) + if (pthread_rwlock_init(&rwlock->rwlock, NULL) != 0) abort(); } void ddsrt_rwlock_destroy (ddsrt_rwlock_t *rwlock) { - int err; - assert(rwlock != NULL); - if ((err = pthread_rwlock_destroy (&rwlock->rwlock)) != 0) + if (pthread_rwlock_destroy (&rwlock->rwlock) != 0) abort(); } From 0b6ea7946924ea0b66174aa9cdb9de0ad17e65ad Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 11 May 2020 14:08:30 +0200 Subject: [PATCH 224/238] Assertions to help clang static analyzer Signed-off-by: Erik Boasson --- src/core/ddsc/tests/loan.c | 4 ++++ src/core/ddsi/src/ddsi_serdata_pserop.c | 1 + 2 files changed, 5 insertions(+) diff --git a/src/core/ddsc/tests/loan.c b/src/core/ddsc/tests/loan.c index 5e12d84..2b822c7 100644 --- a/src/core/ddsc/tests/loan.c +++ b/src/core/ddsc/tests/loan.c @@ -110,6 +110,7 @@ CU_Test (ddsc_loan, success, .init = create_entities, .fini = delete_entities) CU_ASSERT_FATAL (result == DDS_RETCODE_OK); /* return resets buf[0] (so that it picks up the loan the next time) and zeros the data */ CU_ASSERT_FATAL (ptrs[0] == NULL); + assert (ptr0copy != NULL); /* clang static analyzer */ CU_ASSERT_FATAL (memcmp (ptr0copy, zeros, sizeof (s)) == 0); /* read 3, return: should work fine, causes realloc */ @@ -121,6 +122,7 @@ CU_Test (ddsc_loan, success, .init = create_entities, .fini = delete_entities) result = dds_return_loan (reader, ptrs, n); CU_ASSERT_FATAL (result == DDS_RETCODE_OK); CU_ASSERT_FATAL (ptrs[0] == NULL); + assert (ptr0copy != NULL); /* clang static analyzer */ CU_ASSERT_FATAL (memcmp (ptr0copy, zeros, 3 * sizeof (s)) == 0); /* read 1 using loan, expecting to get the same address (no realloc needed), defer return. @@ -145,6 +147,7 @@ CU_Test (ddsc_loan, success, .init = create_entities, .fini = delete_entities) { const struct RoundTripModule_DataType *a = ptrs[0]; const struct RoundTripModule_DataType *b = ptrs2[0]; + assert (a != NULL && b != NULL); /* clang static analyzer */ CU_ASSERT_FATAL (a->payload._length == b->payload._length); CU_ASSERT_FATAL (a->payload._buffer != b->payload._buffer); CU_ASSERT_FATAL (a->payload._buffer[0] == b->payload._buffer[0]); @@ -164,6 +167,7 @@ CU_Test (ddsc_loan, success, .init = create_entities, .fini = delete_entities) //This should be a use-after-free //CU_ASSERT_FATAL (memcmp (ptr0copy, zeros, sizeof (s)) == 0); + (void) ptr0copy; } CU_Test (ddsc_loan, take_cleanup, .init = create_entities, .fini = delete_entities) diff --git a/src/core/ddsi/src/ddsi_serdata_pserop.c b/src/core/ddsi/src/ddsi_serdata_pserop.c index a3df6d2..1796497 100644 --- a/src/core/ddsi/src/ddsi_serdata_pserop.c +++ b/src/core/ddsi/src/ddsi_serdata_pserop.c @@ -213,6 +213,7 @@ static struct ddsi_serdata *serdata_pserop_from_sample (const struct ddsi_sertop const size_t size4 = (size + 3) & ~(size_t)3; struct ddsi_serdata_pserop *d = serdata_pserop_new (tp, kind, size4, &header); assert (tp->ops_key == NULL || (size >= 16 && tp->memsize >= 16)); + assert (d->data != NULL); // clang static analyzer memcpy (d->data, data, size); memset (d->data + size, 0, size4 - size); d->pos = (uint32_t) size; From 659e7dc446909115b9f1aa2a4fe4ff0a7f37165b Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 11 May 2020 14:13:06 +0200 Subject: [PATCH 225/238] Fix documentation comment Signed-off-by: Erik Boasson --- .../ddsi/include/dds/ddsi/ddsi_security_omg.h | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) 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 460a4ad..6eeb9eb 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h @@ -485,22 +485,15 @@ bool q_omg_security_is_remote_rtps_protected(const struct proxy_participant *pro void set_proxy_participant_security_info(struct proxy_participant *proxypp, const ddsi_plist_t *plist); /** - * @brief Check if the participant and the proxy participant - * have compatible security info settings. + * @brief Determine if the messages, related to the given remote + * entity, are RTPS protected or not. * - * Associated with a secure participant is the ParticipantSecurityInfo parameter. - * This parameter contains the setting of the security attributes and the associated - * plugin security attributes of the secure participant. - * This function will check if the received ParticipantSecurityInfo parameter is - * compatible with the local ParticipantSecurityInfo parameter. - * - * @param[in] pp The participant. - * @param[in] proxypp The proxy participant. + * @param[in] pp The participant. + * @param[in] entityid ID of the entity to check. * * @returns bool - * @retval true The participant and the proxy participant have compatible - * security info settings. - * @retval false Otherwise. + * @retval true The entity messages are RTPS protected. + * @retval false The entity messages are not RTPS protected. */ bool q_omg_security_is_local_rtps_protected(const struct participant *pp, ddsi_entityid_t entityid); From 8fea8d56731887d1f7a2b9755d038602e8a5f3d8 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 11 May 2020 14:20:36 +0200 Subject: [PATCH 226/238] Use C99 flex array member instead of length-1 array Signed-off-by: Erik Boasson --- .../builtin_plugins/cryptographic/src/crypto_transform.c | 6 +++--- .../src/encode_datareader_submessage_utests.c | 2 +- .../src/encode_datawriter_submessage_utests.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_transform.c b/src/security/builtin_plugins/cryptographic/src/crypto_transform.c index a2f6893..1fd32b9 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_transform.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_transform.c @@ -59,7 +59,7 @@ struct crypto_header struct crypto_contents { uint32_t _length; - unsigned char _data[1]; + unsigned char _data[]; }; struct crypto_contents_ref @@ -71,7 +71,7 @@ struct crypto_contents_ref struct receiver_specific_mac_seq { uint32_t _length; - struct receiver_specific_mac _buffer[1]; + struct receiver_specific_mac _buffer[]; }; struct crypto_footer @@ -83,7 +83,7 @@ struct crypto_footer struct encrypted_data { uint32_t length; - unsigned char data[1]; + unsigned char data[]; }; /* diff --git a/src/security/builtin_plugins/tests/encode_datareader_submessage/src/encode_datareader_submessage_utests.c b/src/security/builtin_plugins/tests/encode_datareader_submessage/src/encode_datareader_submessage_utests.c index 30bacaa..2962aca 100644 --- a/src/security/builtin_plugins/tests/encode_datareader_submessage/src/encode_datareader_submessage_utests.c +++ b/src/security/builtin_plugins/tests/encode_datareader_submessage/src/encode_datareader_submessage_utests.c @@ -77,7 +77,7 @@ struct receiver_specific_mac struct encrypted_data { uint32_t length; - unsigned char data[1]; + unsigned char data[]; }; struct seq_number diff --git a/src/security/builtin_plugins/tests/encode_datawriter_submessage/src/encode_datawriter_submessage_utests.c b/src/security/builtin_plugins/tests/encode_datawriter_submessage/src/encode_datawriter_submessage_utests.c index a186641..30a4ce4 100644 --- a/src/security/builtin_plugins/tests/encode_datawriter_submessage/src/encode_datawriter_submessage_utests.c +++ b/src/security/builtin_plugins/tests/encode_datawriter_submessage/src/encode_datawriter_submessage_utests.c @@ -83,7 +83,7 @@ struct receiver_specific_mac struct encrypted_data { uint32_t length; - unsigned char data[1]; + unsigned char data[]; }; static void reset_exception(DDS_Security_SecurityException *ex) From fe81a6bda50cd84cb6537524c8f07884f122fafd Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 12 May 2020 09:07:08 +0200 Subject: [PATCH 227/238] Make wait_for_acks implementation capable of waiting for one reader The dds_wait_for_acks function follows the DCPS specification and allows waiting for all matching readers to have acknowledged all data written prior to that point. This commit leaves the API unchanged but extends the implementation to make it possible to wait until a specific reader has acknowledged everything, as this is a useful device in testing with deliberate one-way disconnections using dds_domain_set_deafmute. Signed-off-by: Erik Boasson --- src/core/ddsc/src/dds__writer.h | 2 +- src/core/ddsc/src/dds_publisher.c | 2 +- src/core/ddsc/src/dds_writer.c | 4 ++-- src/core/ddsi/include/dds/ddsi/q_entity.h | 2 +- src/core/ddsi/src/q_entity.c | 24 ++++++++++++++++++----- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/core/ddsc/src/dds__writer.h b/src/core/ddsc/src/dds__writer.h index 69ff7e1..111e93d 100644 --- a/src/core/ddsc/src/dds__writer.h +++ b/src/core/ddsc/src/dds__writer.h @@ -23,7 +23,7 @@ DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_writer, DDS_KIND_WRITER) struct status_cb_data; void dds_writer_status_cb (void *entity, const struct status_cb_data * data); -dds_return_t dds__writer_wait_for_acks (struct dds_writer *wr, dds_time_t abstimeout); +DDS_EXPORT dds_return_t dds__writer_wait_for_acks (struct dds_writer *wr, ddsi_guid_t *rdguid, dds_time_t abstimeout); #if defined (__cplusplus) } diff --git a/src/core/ddsc/src/dds_publisher.c b/src/core/ddsc/src/dds_publisher.c index 00ea520..ca17999 100644 --- a/src/core/ddsc/src/dds_publisher.c +++ b/src/core/ddsc/src/dds_publisher.c @@ -114,7 +114,7 @@ dds_return_t dds_wait_for_acks (dds_entity_t publisher_or_writer, dds_duration_t return DDS_RETCODE_UNSUPPORTED; case DDS_KIND_WRITER: - ret = dds__writer_wait_for_acks ((struct dds_writer *) p_or_w_ent, abstimeout); + ret = dds__writer_wait_for_acks ((struct dds_writer *) p_or_w_ent, NULL, abstimeout); dds_entity_unpin (p_or_w_ent); return ret; diff --git a/src/core/ddsc/src/dds_writer.c b/src/core/ddsc/src/dds_writer.c index bebebcc..cad0492 100644 --- a/src/core/ddsc/src/dds_writer.c +++ b/src/core/ddsc/src/dds_writer.c @@ -410,14 +410,14 @@ dds_entity_t dds_get_publisher (dds_entity_t writer) } } -dds_return_t dds__writer_wait_for_acks (struct dds_writer *wr, dds_time_t abstimeout) +dds_return_t dds__writer_wait_for_acks (struct dds_writer *wr, ddsi_guid_t *rdguid, dds_time_t abstimeout) { /* during lifetime of the writer m_wr is constant, it is only during deletion that it gets erased at some point */ if (wr->m_wr == NULL) return DDS_RETCODE_OK; else - return writer_wait_for_acks (wr->m_wr, abstimeout); + return writer_wait_for_acks (wr->m_wr, rdguid, abstimeout); } DDS_GET_STATUS(writer, publication_matched, PUBLICATION_MATCHED, total_count_change, current_count_change) diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 14f59f8..289ab84 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -655,7 +655,7 @@ seqno_t writer_max_drop_seq (const struct writer *wr); int writer_must_have_hb_scheduled (const struct writer *wr, const struct whc_state *whcst); void writer_set_retransmitting (struct writer *wr); void writer_clear_retransmitting (struct writer *wr); -dds_return_t writer_wait_for_acks (struct writer *wr, dds_time_t abstimeout); +dds_return_t writer_wait_for_acks (struct writer *wr, const ddsi_guid_t *rdguid, dds_time_t abstimeout); dds_return_t unblock_throttled_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *guid); dds_return_t delete_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *guid); diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 4fb30cd..9a8b5ef 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -3969,16 +3969,30 @@ dds_return_t unblock_throttled_writer (struct ddsi_domaingv *gv, const struct dd return 0; } -dds_return_t writer_wait_for_acks (struct writer *wr, dds_time_t abstimeout) +dds_return_t writer_wait_for_acks (struct writer *wr, const ddsi_guid_t *rdguid, dds_time_t abstimeout) { dds_return_t rc; seqno_t ref_seq; ddsrt_mutex_lock (&wr->e.lock); ref_seq = wr->seq; - while (wr->state == WRST_OPERATIONAL && ref_seq > writer_max_drop_seq (wr)) - if (!ddsrt_cond_waituntil (&wr->throttle_cond, &wr->e.lock, abstimeout)) - break; - rc = (ref_seq <= writer_max_drop_seq (wr)) ? DDS_RETCODE_OK : DDS_RETCODE_TIMEOUT; + if (rdguid == NULL) + { + while (wr->state == WRST_OPERATIONAL && ref_seq > writer_max_drop_seq (wr)) + if (!ddsrt_cond_waituntil (&wr->throttle_cond, &wr->e.lock, abstimeout)) + break; + rc = (ref_seq <= writer_max_drop_seq (wr)) ? DDS_RETCODE_OK : DDS_RETCODE_TIMEOUT; + } + else + { + struct wr_prd_match *m = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, rdguid); + while (wr->state == WRST_OPERATIONAL && m && ref_seq > m->seq) + { + if (!ddsrt_cond_waituntil (&wr->throttle_cond, &wr->e.lock, abstimeout)) + break; + m = ddsrt_avl_lookup (&wr_readers_treedef, &wr->readers, rdguid); + } + rc = (m == NULL || ref_seq <= m->seq) ? DDS_RETCODE_OK : DDS_RETCODE_TIMEOUT; + } ddsrt_mutex_unlock (&wr->e.lock); return rc; } From 1b448dee9bf9c133e9c47a56db175faf69ddc26f Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Tue, 12 May 2020 09:22:56 +0200 Subject: [PATCH 228/238] Add wait-for-acknowledgement to oneliner tests Signed-off-by: Erik Boasson --- src/core/ddsc/tests/listener.c | 29 ++++- src/core/ddsc/tests/test_oneliner.c | 136 +++++++++++++++++------ src/core/ddsi/include/dds/ddsi/q_bswap.h | 4 +- 3 files changed, 124 insertions(+), 45 deletions(-) diff --git a/src/core/ddsc/tests/listener.c b/src/core/ddsc/tests/listener.c index 378f0b3..1bc7005 100644 --- a/src/core/ddsc/tests/listener.c +++ b/src/core/ddsc/tests/listener.c @@ -286,16 +286,33 @@ CU_Test (ddsc_listener, matched) dotest ("sm r pm w' ?pm w' ?sm r"); // Disconnect + reconnect; "deaf P" means the disconnect is asymmetrical: P no longer observes P' - // but P' still observes P. If r did not ACK the data before losing connectivity, w' will hold + // but P' still observes P. If r did not ack the data before losing connectivity, w' will hold // the data and it will be re-delivered after reconnecting, depending on QoS settings (the "..." // allows for extra samples) and whether the instance was taken or not // - // the uncertainty also means we don't really know how many "data available" events there will be - // and the "sleep 0.3" simply gives it a bit more time after the first event + // If r did ack the data, w will drop it and it can't be delivered. If there is another r'' that + // did not ack, r will still not get the data because the writer determines that it was ack'd + // already and it won't retransmit. + // FIXME: this differs from what the spec says should happen, maybe it should be changed? + // (It is a fall-out from changes to make sure a volatile reader doesn't get historical data, but + // it could be handled differently.) + // + // Waiting for an acknowledgement therefore makes sense (and in the other runs, a 0.3s sleep + // kind-a solves the problem of not known exactly how many events there will be: it means at + // least one event has been observed, and behaviour of Cyclone in a simple case like this means + // the full retransmit request will be replied to with a single packet, and that therefore the + // likelihood of the retransmitted data arriving within a window of 0.3s is very high. (Where + // 0.3s is an attempt to pick a duration on the long side of what's needed and short enough not + // to delay things much.) + dotest ("sm da r pm w' ?sm r ?pm w' ;" // matched reader/writer pair + " wr w' 1 ; ?da r take{(1,0,0)} r ?ack w' ;" // wait-for-acks => writer drops data + " deaf P ; ?sm(1,0,0,-1,w') r ?da r take{d1} r ; wr w' 2 ;" // write lost on "wire" + " hearing P ; ?sm(2,1,1,1,w') r ?da r sleep 0.3 take{(2,0,0)} r ; ?!pm"); dotest ("sm da r pm w' ; ?sm r ?pm w' ;" - " wr w' 1 ; ?da r take{(1,0,0)} r sleep 1;" - " deaf P ; ?sm(1,0,0,-1,w') r ?da r take{d1} r ; wr w' 2 ;" - " hearing P ; ?sm(2,1,1,1,w') r ?da r sleep 0.3 take{(2,0,0),...} r ; ?!pm"); + " r'' ?pm w' deaf P'' ;" // with second reader: reader is deaf so won't ACK + " wr w' 1 ; ?da r take{(1,0,0)} r ?ack(r) w' ;" // wait for ack from r' (not r'') + " deaf P ; ?sm(1,0,0,-1,w') r ?da r take{d1} r ; wr w' 2 ;" // write lost on "wire" + " hearing P ; ?sm(2,1,1,1,w') r ?da r sleep 0.3 take{(2,0,0)} r ; ?!pm"); // same without taking the "dispose" after disconnect // sample 1 will be delivered anew dotest ("sm da r pm w' ; ?sm r ?pm w' ; wr w' 1 ; ?da r take{(1,0,0)} r ;" diff --git a/src/core/ddsc/tests/test_oneliner.c b/src/core/ddsc/tests/test_oneliner.c index 255400a..2b635bd 100644 --- a/src/core/ddsc/tests/test_oneliner.c +++ b/src/core/ddsc/tests/test_oneliner.c @@ -25,6 +25,8 @@ #include "dds__types.h" #include "dds__entity.h" +#include "dds__writer.h" +#include "dds/ddsi/q_bswap.h" #include "dds/ddsi/q_lease.h" #include "dds/ddsi/q_xevent.h" #include "dds/ddsi/ddsi_entity_index.h" @@ -1502,46 +1504,106 @@ static void checklistener (struct oneliner_ctx *ctx, int ll, int ent, struct one testfail (ctx, "listener %s: status mask not cleared", lldesc[ll].name); } -static void dochecklistener (struct oneliner_ctx *ctx) +static void dowaitforack (struct oneliner_ctx *ctx) { - const bool expectclear = nexttok_if (&ctx->l, '!'); - const int ll = parse_listener (ctx); - if (ll < 0) - error (ctx, "check listener: requires listener name"); - else if (expectclear) + dds_return_t ret; + int ent, ent1 = -1; + union { dds_guid_t x; ddsi_guid_t i; } rdguid; + if (*ctx->l.inp == '(') // reader present { - printf ("listener %s: check not called", lldesc[ll].name); - fflush (stdout); - ddsrt_mutex_lock (&ctx->g_mutex); - bool ret = true; - for (int i = 0; i < (int) (sizeof (ctx->doms) / sizeof (ctx->doms[0])); i++) - { - printf (" cb_called %"PRIu32" %s\n", ctx->cb[i].cb_called[lldesc[ll].id], ctx->cb[i].cb_called[lldesc[ll].id] == 0 ? "ok" : "fail"); - if (ctx->cb[i].cb_called[lldesc[ll].id] != 0) - ret = false; - } - ddsrt_mutex_unlock (&ctx->g_mutex); - if (!ret) - testfail (ctx, "callback %s invoked unexpectedly", lldesc[ll].name); + nexttok (&ctx->l, NULL); + if ((ent1 = parse_entity (ctx)) < 0) + error (ctx, "wait for ack: expecting entity"); + if ((ent1 % 9) < 3 || (ent1 % 9) > 5 || ctx->es[ent1] == 0) + error (ctx, "wait for ack: expecting existing reader as argument"); + if ((ret = dds_get_guid (ctx->es[ent1], &rdguid.x)) != 0) + error_dds (ctx, ret, "wait for ack: failed to get GUID for reader %"PRId32, ctx->es[ent1]); + rdguid.i = nn_ntoh_guid (rdguid.i); + if (!nexttok_if (&ctx->l, ')')) + error (ctx, "wait for ack: expecting ')'"); + } + if ((ent = parse_entity (ctx)) < 0) + error (ctx, "wait for ack: expecting writer"); + if (ent1 >= 0 && ent / 9 == ent1 / 9) + error (ctx, "wait for ack: reader and writer must be in different domains"); + if (ctx->es[ent] == 0) + make_entity (ctx, ent, NULL); + printf ("wait for ack %"PRId32" reader %"PRId32"\n", ctx->es[ent], ent1 < 0 ? 0 : ctx->es[ent1]); + + // without a reader argument a simple dds_wait_for_acks (ctx->es[ent], DDS_SECS (5)) suffices + struct dds_entity *x; + if ((ret = dds_entity_pin (ctx->es[ent], &x)) < 0) + error_dds (ctx, ret, "wait for ack: pin entity failed %"PRId32, ctx->es[ent]); + if (dds_entity_kind (x) != DDS_KIND_WRITER) + error_dds (ctx, ret, "wait for ack: %"PRId32" is not a writer", ctx->es[ent]); + else + ret = dds__writer_wait_for_acks ((struct dds_writer *) x, (ent1 < 0) ? NULL : &rdguid.i, dds_time () + DDS_SECS (5)); + dds_entity_unpin (x); + if (ret != 0) + { + if (ret == DDS_RETCODE_TIMEOUT) + testfail (ctx, "wait for acks timed out on entity %"PRId32, ctx->es[ent]); + else + error_dds (ctx, ret, "wait for acks failed on entity %"PRId32, ctx->es[ent]); + } +} + +static void dowaitfornolistener (struct oneliner_ctx *ctx, int ll) +{ + printf ("listener %s: check not called", lldesc[ll].name); + fflush (stdout); + ddsrt_mutex_lock (&ctx->g_mutex); + bool ret = true; + for (int i = 0; i < (int) (sizeof (ctx->doms) / sizeof (ctx->doms[0])); i++) + { + printf (" %"PRIu32, ctx->cb[i].cb_called[lldesc[ll].id]); + if (ctx->cb[i].cb_called[lldesc[ll].id] != 0) + ret = false; + } + printf (" (%s)\n", ret ? "ok" : "fail"); + ddsrt_mutex_unlock (&ctx->g_mutex); + if (!ret) + testfail (ctx, "callback %s invoked unexpectedly", lldesc[ll].name); +} + +static void dowaitforlistener (struct oneliner_ctx *ctx, int ll) +{ + struct oneliner_lex l1 = ctx->l; + // no whitespace between name and args + const bool have_args = (*ctx->l.inp == '('); + if (have_args) + { + // skip args: we need the entity before we can interpret them + int tok; + while ((tok = nexttok (&ctx->l, NULL)) != EOF && tok != ')') + ; + } + const int ent = parse_entity (ctx); + if (ent < 0) + error (ctx, "check listener: requires an entity"); + if (ctx->es[ent] == 0) + setlistener (ctx, NULL, ll, ent); + checklistener (ctx, ll, ent, have_args ? &l1 : NULL); +} + +static void dowait (struct oneliner_ctx *ctx) +{ + union oneliner_tokval tokval; + if (peektok (&ctx->l, &tokval) == TOK_NAME && strcmp (tokval.n, "ack") == 0) + { + nexttok (&ctx->l, NULL); + dowaitforack (ctx); } else { - struct oneliner_lex l1 = ctx->l; - // no whitespace between name and args - const bool have_args = (*ctx->l.inp == '('); - if (have_args) - { - // skip args: we need the entity before we can interpret them - int tok; - while ((tok = nexttok (&ctx->l, NULL)) != EOF && tok != ')') - ; - } - const int ent = parse_entity (ctx); - if (ent < 0) - error (ctx, "check listener: requires an entity"); - if (ctx->es[ent] == 0) - setlistener (ctx, NULL, ll, ent); - checklistener (ctx, ll, ent, have_args ? &l1 : NULL); + const bool expectclear = nexttok_if (&ctx->l, '!'); + const int ll = parse_listener (ctx); + if (ll < 0) + error (ctx, "check listener: requires listener name"); + if (expectclear) + dowaitfornolistener (ctx, ll); + else + dowaitforlistener (ctx, ll); } } @@ -1628,7 +1690,7 @@ static void dispatchcmd (struct oneliner_ctx *ctx) void (*fn) (struct oneliner_ctx *ct); } cs[] = { { "-", dodelete }, - { "?", dochecklistener }, + { "?", dowait }, { "wr", dowr }, { "wrdisp", dowrdisp }, { "disp", dodisp }, @@ -1744,7 +1806,7 @@ int test_oneliner_fini (struct oneliner_ctx *ctx) setresult (ctx, ret, "terminate: reset listener failed on %"PRId32, ctx->es[i]); if (ctx->result == 0) { - printf ("\n"); + printf ("\n-- dumping content of readers after failure --\n"); for (int i = 0; i < (int) (sizeof (ctx->doms) / sizeof (ctx->doms[0])); i++) { for (int j = 3; j <= 5; j++) diff --git a/src/core/ddsi/include/dds/ddsi/q_bswap.h b/src/core/ddsi/include/dds/ddsi/q_bswap.h index 93a3706..2a2dded 100644 --- a/src/core/ddsi/include/dds/ddsi/q_bswap.h +++ b/src/core/ddsi/include/dds/ddsi/q_bswap.h @@ -33,8 +33,8 @@ ddsi_guid_prefix_t nn_hton_guid_prefix (ddsi_guid_prefix_t p); ddsi_guid_prefix_t nn_ntoh_guid_prefix (ddsi_guid_prefix_t p); ddsi_entityid_t nn_hton_entityid (ddsi_entityid_t e); ddsi_entityid_t nn_ntoh_entityid (ddsi_entityid_t e); -ddsi_guid_t nn_hton_guid (ddsi_guid_t g); -ddsi_guid_t nn_ntoh_guid (ddsi_guid_t g); +DDS_EXPORT ddsi_guid_t nn_hton_guid (ddsi_guid_t g); +DDS_EXPORT ddsi_guid_t nn_ntoh_guid (ddsi_guid_t g); void bswap_sequence_number_set_hdr (nn_sequence_number_set_header_t *snset); void bswap_sequence_number_set_bitmap (nn_sequence_number_set_header_t *snset, uint32_t *bits); From 2ef17d02008155a11392fedf65cd7c6d46594ae4 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Fri, 15 May 2020 15:00:12 +0200 Subject: [PATCH 229/238] Ignore backward jumps in computing serializer size When defining a new topic, typically the serializer instructions that are usually in constant memory and generated by the IDL compiler are copied into memory managed by the Cyclone implementation. For this it needs to compute the size of the serializer, which the IDL compiler doesn't provide. It does this by effectively dry-running the program. (Note that it doesn't validate the program.) All but the JSR operations move the program counter forward, but the JSR operation can cause it to go backward instead and allows implementing recursive types (the IDL compiler doesn't support them, but one might decide to work around that limitation). When dry-running the program, following a backwards jump can cause a non-terminating loop. The jump could potentially be to an unexplored address and so ignoring all backwards jumps potentially means it skips part of the program. As this is not a validator and the program can always be arranged so that a following a backwards jump is not relevant to computing the size correctly, this is reasonable approximation. Signed-off-by: Erik Boasson --- src/core/ddsi/src/ddsi_cdrstream.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/ddsi/src/ddsi_cdrstream.c b/src/core/ddsi/src/ddsi_cdrstream.c index 6cdfb80..9556766 100644 --- a/src/core/ddsi/src/ddsi_cdrstream.c +++ b/src/core/ddsi/src/ddsi_cdrstream.c @@ -364,7 +364,8 @@ static void dds_stream_countops1 (const uint32_t * __restrict ops, const uint32_ break; } case DDS_OP_JSR: { - dds_stream_countops1 (ops + DDS_OP_JUMP (insn), ops_end); + if (DDS_OP_JUMP (insn) > 0) + dds_stream_countops1 (ops + DDS_OP_JUMP (insn), ops_end); ops++; break; } From be7f7af7416668492bf1cebc2db8f82266737ba7 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 16 May 2020 08:38:58 +0200 Subject: [PATCH 230/238] Tweak timeout handling of authentication tests * Compute the time at which the handshake must have completed from the initial timeout specification, rather than using it as a timeout for the individual steps of the handshake * If the handshake fails because an expected message is not present, print this, including whether the timeout occured because the message queue was empty or because the expected message could not be found in a non-empty queue. * Replace the 0.5s per-step timeout to a single 2s timeout. Signed-off-by: Erik Boasson --- src/security/core/tests/access_control.c | 6 +- .../tests/common/authentication_wrapper.c | 4 +- .../tests/common/authentication_wrapper.h | 2 +- .../core/tests/common/plugin_wrapper_msg_q.c | 27 ++-- .../core/tests/common/plugin_wrapper_msg_q.h | 8 +- src/security/core/tests/common/test_utils.c | 130 +++++++++++++----- 6 files changed, 122 insertions(+), 55 deletions(-) diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index 261fbdf..f22dbe5 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -700,7 +700,7 @@ static void test_encoding_mismatch( struct Handshake *hs_list; int nhs; - validate_handshake (DDS_DOMAINID, false, NULL, &hs_list, &nhs, DDS_MSECS(500)); + validate_handshake (DDS_DOMAINID, false, NULL, &hs_list, &nhs, DDS_SECS(2)); CU_ASSERT_EQUAL_FATAL (exp_hs_fail, nhs < 1); handshake_list_fini (hs_list, nhs); @@ -799,7 +799,7 @@ static void test_readwrite_protection ( if (!exp_pub_pp_fail && !exp_sub_pp_fail) { dds_entity_t pub, sub, pub_tp, sub_tp, wr, rd; - validate_handshake_nofail (DDS_DOMAINID, DDS_MSECS(500)); + validate_handshake_nofail (DDS_DOMAINID, DDS_SECS(2)); rd_wr_init_fail (g_participant[0], &pub, &pub_tp, &wr, g_participant[1], &sub, &sub_tp, &rd, topic_name, exp_pub_tp_fail, exp_wr_fail, exp_sub_tp_fail, exp_rd_fail); if (!exp_pub_tp_fail && !exp_wr_fail && !exp_sub_tp_fail && !exp_rd_fail) sync_writer_to_readers (g_participant[0], wr, exp_sync_fail ? 0 : 1, DDS_SECS(1)); @@ -893,4 +893,4 @@ CU_Test(ddssec_access_control, denied_topic) dds_delete_qos (qos); access_control_fini (2, (void * []) { gov_config, gov_topic_rule, sub_rules_xml, grants_pub[0], grants_sub[0], perm_config_pub, perm_config_sub, ca, id1_subj, id2_subj, id1, id2 }, 12); -} \ No newline at end of file +} diff --git a/src/security/core/tests/common/authentication_wrapper.c b/src/security/core/tests/common/authentication_wrapper.c index 86290df..693ac11 100644 --- a/src/security/core/tests/common/authentication_wrapper.c +++ b/src/security/core/tests/common/authentication_wrapper.c @@ -446,11 +446,11 @@ static struct dds_security_authentication_impl * get_impl_for_domain(dds_domaini return NULL; } -struct message * test_authentication_plugin_take_msg(dds_domainid_t domain_id, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, dds_duration_t timeout) +enum take_message_result test_authentication_plugin_take_msg(dds_domainid_t domain_id, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, dds_time_t abstimeout, struct message **msg) { struct dds_security_authentication_impl *impl = get_impl_for_domain(domain_id); assert(impl); - return take_message(&impl->msg_queue, kind, lidHandle, ridHandle, hsHandle, timeout); + return take_message(&impl->msg_queue, kind, lidHandle, ridHandle, hsHandle, abstimeout, msg); } void test_authentication_plugin_release_msg(struct message *msg) diff --git a/src/security/core/tests/common/authentication_wrapper.h b/src/security/core/tests/common/authentication_wrapper.h index f58121d..939db10 100644 --- a/src/security/core/tests/common/authentication_wrapper.h +++ b/src/security/core/tests/common/authentication_wrapper.h @@ -33,7 +33,7 @@ SECURITY_EXPORT int finalize_test_authentication_missing_func(void *context); SECURITY_EXPORT int init_test_authentication_init_error(const char *argument, void **context, struct ddsi_domaingv *gv); SECURITY_EXPORT int finalize_test_authentication_init_error(void *context); -SECURITY_EXPORT struct message * test_authentication_plugin_take_msg(dds_domainid_t domain_id, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, dds_duration_t timeout); +SECURITY_EXPORT enum take_message_result test_authentication_plugin_take_msg(dds_domainid_t domain_id, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, dds_time_t abstimeout, struct message **msg); SECURITY_EXPORT void test_authentication_plugin_release_msg(struct message *msg); #endif /* SECURITY_CORE_TEST_AUTHENTICATION_WRAPPER_H_ */ diff --git a/src/security/core/tests/common/plugin_wrapper_msg_q.c b/src/security/core/tests/common/plugin_wrapper_msg_q.c index 3ecad82..0b03ded 100644 --- a/src/security/core/tests/common/plugin_wrapper_msg_q.c +++ b/src/security/core/tests/common/plugin_wrapper_msg_q.c @@ -95,25 +95,26 @@ int message_matched(struct message *msg, message_kind_t kind, DDS_Security_Ident (!hsHandle || msg->hsHandle == hsHandle); } -struct message * take_message(struct message_queue *queue, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, dds_duration_t timeout) +enum take_message_result take_message(struct message_queue *queue, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, dds_time_t abstimeout, struct message **msg) { - struct message *msg = NULL, *cur, *prev; - int r = 1; + struct message *cur, *prev; + enum take_message_result ret = TAKE_MESSAGE_OK; + *msg = NULL; ddsrt_mutex_lock(&queue->lock); do { cur = queue->head; prev = NULL; - while (cur && !msg) + while (cur && *msg == NULL) { if (message_matched(cur, kind, lidHandle, ridHandle, hsHandle)) { - msg = cur; + *msg = cur; if (prev) - prev->next = msg->next; + prev->next = cur->next; else - queue->head = msg->next; - if (queue->tail == msg) + queue->head = cur->next; + if (queue->tail == cur) queue->tail = prev; } else @@ -122,13 +123,13 @@ struct message * take_message(struct message_queue *queue, message_kind_t kind, cur = cur->next; } } - if (!msg) + if (*msg == NULL) { - if (!ddsrt_cond_waitfor(&queue->cond, &queue->lock, timeout)) - r = 0; + if (!ddsrt_cond_waituntil(&queue->cond, &queue->lock, abstimeout)) + ret = queue->head ? TAKE_MESSAGE_TIMEOUT_NONEMPTY : TAKE_MESSAGE_TIMEOUT_EMPTY; } - } while (r && !msg); + } while (ret == TAKE_MESSAGE_OK && *msg == NULL); ddsrt_mutex_unlock(&queue->lock); - return msg; + return ret; } diff --git a/src/security/core/tests/common/plugin_wrapper_msg_q.h b/src/security/core/tests/common/plugin_wrapper_msg_q.h index 32ec557..c70e5f2 100644 --- a/src/security/core/tests/common/plugin_wrapper_msg_q.h +++ b/src/security/core/tests/common/plugin_wrapper_msg_q.h @@ -46,6 +46,12 @@ struct message_queue { struct message *tail; }; +enum take_message_result { + TAKE_MESSAGE_OK, /* message found */ + TAKE_MESSAGE_TIMEOUT_EMPTY, /* no message found, queue is empty */ + TAKE_MESSAGE_TIMEOUT_NONEMPTY /* no message found, queue is not empty */ +}; + struct dds_security_authentication_impl; void insert_message(struct message_queue *queue, struct message *msg); @@ -56,7 +62,7 @@ void delete_message(struct message *msg); void init_message_queue(struct message_queue *queue); void deinit_message_queue(struct message_queue *queue); int message_matched(struct message *msg, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle); -struct message * take_message(struct message_queue *queue, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, dds_duration_t timeout); +enum take_message_result take_message(struct message_queue *queue, message_kind_t kind, DDS_Security_IdentityHandle lidHandle, DDS_Security_IdentityHandle ridHandle, DDS_Security_IdentityHandle hsHandle, dds_time_t abstimeout, struct message **msg); #endif /* SECURITY_CORE_PLUGIN_WRAPPER_MSG_Q_H_ */ diff --git a/src/security/core/tests/common/test_utils.c b/src/security/core/tests/common/test_utils.c index e7e7ed4..cab9bef 100644 --- a/src/security/core/tests/common/test_utils.c +++ b/src/security/core/tests/common/test_utils.c @@ -149,58 +149,92 @@ static int find_handshake (DDS_Security_HandshakeHandle handle) return -1; } -static void handle_process_message (dds_domainid_t domain_id, DDS_Security_IdentityHandle handshake, dds_duration_t timeout) +static void handle_process_message (dds_domainid_t domain_id, DDS_Security_IdentityHandle handshake, dds_time_t abstimeout) { struct message *msg; - if ((msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_PROCESS_HANDSHAKE, 0, 0, handshake, timeout))) + switch (test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_PROCESS_HANDSHAKE, 0, 0, handshake, abstimeout, &msg)) { - int idx; - if ((idx = find_handshake (msg->hsHandle)) >= 0) - { - print_test_msg ("set handshake %"PRId64" final result to '%s' (errmsg: %s)\n", msg->hsHandle, get_validation_result_str (msg->result), msg->err_msg); - handshakeList[idx].finalResult = msg->result; - handshakeList[idx].err_msg = ddsrt_strdup (msg->err_msg); + case TAKE_MESSAGE_OK: { + int idx; + if ((idx = find_handshake (msg->hsHandle)) >= 0) + { + print_test_msg ("set handshake %"PRId64" final result to '%s' (errmsg: %s)\n", msg->hsHandle, get_validation_result_str (msg->result), msg->err_msg); + handshakeList[idx].finalResult = msg->result; + handshakeList[idx].err_msg = ddsrt_strdup (msg->err_msg); + } + test_authentication_plugin_release_msg (msg); + break; + } + case TAKE_MESSAGE_TIMEOUT_EMPTY: { + print_test_msg ("handle_process_message: timed out on empty queue\n"); + break; + } + case TAKE_MESSAGE_TIMEOUT_NONEMPTY: { + print_test_msg ("handle_process_message: timed out on non-empty queue\n"); + break; } - test_authentication_plugin_release_msg (msg); } } -static void handle_begin_handshake_request (dds_domainid_t domain_id, struct Handshake *hs, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid, dds_duration_t timeout) +static void handle_begin_handshake_request (dds_domainid_t domain_id, struct Handshake *hs, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid, dds_time_t abstimeout) { struct message *msg; print_test_msg ("handle begin handshake request %"PRId64"<->%"PRId64"\n", lid, rid); - if ((msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REQUEST, lid, rid, 0, timeout))) + switch (test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REQUEST, lid, rid, 0, abstimeout, &msg)) { - hs->handle = msg->hsHandle; - hs->handshakeResult = msg->result; - if (msg->result != DDS_SECURITY_VALIDATION_FAILED) - handle_process_message (domain_id, msg->hsHandle, timeout); - else - hs->err_msg = ddsrt_strdup (msg->err_msg); - test_authentication_plugin_release_msg (msg); + case TAKE_MESSAGE_OK: { + hs->handle = msg->hsHandle; + hs->handshakeResult = msg->result; + if (msg->result != DDS_SECURITY_VALIDATION_FAILED) + handle_process_message (domain_id, msg->hsHandle, abstimeout); + else + hs->err_msg = ddsrt_strdup (msg->err_msg); + test_authentication_plugin_release_msg (msg); + break; + } + case TAKE_MESSAGE_TIMEOUT_EMPTY: { + print_test_msg ("handle_begin_handshake_request: timed out on empty queue\n"); + break; + } + case TAKE_MESSAGE_TIMEOUT_NONEMPTY: { + print_test_msg ("handle_begin_handshake_request: timed out on non-empty queue\n"); + break; + } } } -static void handle_begin_handshake_reply (dds_domainid_t domain_id, struct Handshake *hs, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid, dds_duration_t timeout) +static void handle_begin_handshake_reply (dds_domainid_t domain_id, struct Handshake *hs, DDS_Security_IdentityHandle lid, DDS_Security_IdentityHandle rid, dds_time_t abstimeout) { struct message *msg; print_test_msg ("handle begin handshake reply %"PRId64"<->%"PRId64"\n", lid, rid); - if ((msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REPLY, lid, rid, 0, timeout))) + switch (test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_BEGIN_HANDSHAKE_REPLY, lid, rid, 0, abstimeout, &msg)) { - hs->handle = msg->hsHandle; - hs->handshakeResult = msg->result; - if (msg->result != DDS_SECURITY_VALIDATION_FAILED) - handle_process_message (domain_id, msg->hsHandle, timeout); - else - hs->err_msg = ddsrt_strdup (msg->err_msg); - test_authentication_plugin_release_msg (msg); + case TAKE_MESSAGE_OK: { + hs->handle = msg->hsHandle; + hs->handshakeResult = msg->result; + if (msg->result != DDS_SECURITY_VALIDATION_FAILED) + handle_process_message (domain_id, msg->hsHandle, abstimeout); + else + hs->err_msg = ddsrt_strdup (msg->err_msg); + test_authentication_plugin_release_msg (msg); + break; + } + case TAKE_MESSAGE_TIMEOUT_EMPTY: { + print_test_msg ("handle_begin_handshake_reply: timed out on empty queue\n"); + break; + } + case TAKE_MESSAGE_TIMEOUT_NONEMPTY: { + print_test_msg ("handle_begin_handshake_reply: timed out on non-empty queue\n"); + break; + } } } -static void handle_validate_remote_identity (dds_domainid_t domain_id, DDS_Security_IdentityHandle lid, int count, dds_duration_t timeout) +static void handle_validate_remote_identity (dds_domainid_t domain_id, DDS_Security_IdentityHandle lid, int count, dds_time_t abstimeout) { + enum take_message_result res = TAKE_MESSAGE_OK; struct message *msg; - while (count-- > 0 && (msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_VALIDATE_REMOTE_IDENTITY, lid, 0, 0, timeout))) + while (count-- > 0 && (res = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_VALIDATE_REMOTE_IDENTITY, lid, 0, 0, abstimeout, &msg)) == TAKE_MESSAGE_OK) { struct Handshake *hs; add_remote_identity (msg->ridHandle, &msg->rguid); @@ -208,12 +242,12 @@ static void handle_validate_remote_identity (dds_domainid_t domain_id, DDS_Secur if (msg->result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_REQUEST) { hs->node_type = HSN_REQUESTER; - handle_begin_handshake_request (domain_id, hs, lid, msg->ridHandle, timeout); + handle_begin_handshake_request (domain_id, hs, lid, msg->ridHandle, abstimeout); } else if (msg->result == DDS_SECURITY_VALIDATION_PENDING_HANDSHAKE_MESSAGE) { hs->node_type = HSN_REPLIER; - handle_begin_handshake_reply (domain_id, hs, lid, msg->ridHandle, timeout); + handle_begin_handshake_reply (domain_id, hs, lid, msg->ridHandle, abstimeout); } else { @@ -221,11 +255,34 @@ static void handle_validate_remote_identity (dds_domainid_t domain_id, DDS_Secur } test_authentication_plugin_release_msg (msg); } + + switch (res) + { + case TAKE_MESSAGE_OK: + break; + case TAKE_MESSAGE_TIMEOUT_EMPTY: + print_test_msg ("handle_validate_remote_identity: timed out on empty queue\n"); + break; + case TAKE_MESSAGE_TIMEOUT_NONEMPTY: + print_test_msg ("handle_validate_remote_identity: timed out on non-empty queue\n"); + break; + } } -static void handle_validate_local_identity (dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg, dds_duration_t timeout) +static void handle_validate_local_identity (dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg, dds_time_t abstimeout) { - struct message *msg = test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_VALIDATE_LOCAL_IDENTITY, 0, 0, 0, timeout); + struct message *msg; + switch (test_authentication_plugin_take_msg (domain_id, MESSAGE_KIND_VALIDATE_LOCAL_IDENTITY, 0, 0, 0, abstimeout, &msg)) + { + case TAKE_MESSAGE_OK: + break; + case TAKE_MESSAGE_TIMEOUT_EMPTY: + print_test_msg ("handle_validate_local_identity: timed out on empty queue\n"); + break; + case TAKE_MESSAGE_TIMEOUT_NONEMPTY: + print_test_msg ("handle_validate_local_identity: timed out on non-empty queue\n"); + break; + } CU_ASSERT_FATAL (msg != NULL); CU_ASSERT_FATAL ((msg->result == DDS_SECURITY_VALIDATION_OK) != exp_localid_fail); if (exp_localid_fail && exp_localid_msg) @@ -234,12 +291,15 @@ static void handle_validate_local_identity (dds_domainid_t domain_id, bool exp_l CU_ASSERT_FATAL (msg->err_msg && strstr (msg->err_msg, exp_localid_msg) != NULL); } else + { add_local_identity (msg->lidHandle, &msg->lguid); + } test_authentication_plugin_release_msg (msg); } void validate_handshake (dds_domainid_t domain_id, bool exp_localid_fail, const char * exp_localid_msg, struct Handshake *hs_list[], int *nhs, dds_duration_t timeout) { + dds_time_t abstimeout = dds_time() + timeout; clear_stores (); if (nhs) @@ -247,10 +307,10 @@ void validate_handshake (dds_domainid_t domain_id, bool exp_localid_fail, const if (hs_list) *hs_list = NULL; - handle_validate_local_identity (domain_id, exp_localid_fail, exp_localid_msg, timeout); + handle_validate_local_identity (domain_id, exp_localid_fail, exp_localid_msg, abstimeout); if (!exp_localid_fail) { - handle_validate_remote_identity (domain_id, localIdentityList[0].handle, 1, timeout); + handle_validate_remote_identity (domain_id, localIdentityList[0].handle, 1, abstimeout); for (int n = 0; n < numHandshake; n++) { struct Handshake *hs = &handshakeList[n]; From a292e800acf11d67a13fc7fe26bc747769b2ea60 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 16 May 2020 11:12:45 +0200 Subject: [PATCH 231/238] Do not respond to an ignored SPDP message Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_entity.h | 2 +- src/core/ddsi/src/q_ddsi_discovery.c | 67 ++++++++++------------- src/core/ddsi/src/q_entity.c | 5 +- 3 files changed, 32 insertions(+), 42 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 289ab84..8a4f22f 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -695,7 +695,7 @@ int writer_set_notalive (struct writer *wr, bool notify); /* Set when this proxy participant is not to be announced on the built-in topics yet */ #define CF_PROXYPP_NO_SPDP (1 << 2) -void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct ddsi_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, ddsrt_wctime_t timestamp, seqno_t seq); +bool new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct ddsi_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, ddsrt_wctime_t timestamp, seqno_t seq); DDS_EXPORT int delete_proxy_participant_by_guid (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, ddsrt_wctime_t timestamp, int isimplicit); int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, seqno_t seq, const struct ddsi_plist *datap, ddsrt_wctime_t timestamp); diff --git a/src/core/ddsi/src/q_ddsi_discovery.c b/src/core/ddsi/src/q_ddsi_discovery.c index 1bc06c4..1f031d2 100644 --- a/src/core/ddsi/src/q_ddsi_discovery.c +++ b/src/core/ddsi/src/q_ddsi_discovery.c @@ -764,28 +764,17 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, dds maybe_add_pp_as_meta_to_as_disc (gv, as_meta); - new_proxy_participant - ( - gv, - &datap->participant_guid, - builtin_endpoint_set, - &privileged_pp_guid, - as_default, - as_meta, - datap, - lease_duration, - rst->vendor, - custom_flags, - timestamp, - seq - ); - - /* Force transmission of SPDP messages - we're not very careful - in avoiding the processing of SPDP packets addressed to others - so filter here */ + if (!new_proxy_participant (gv, &datap->participant_guid, builtin_endpoint_set, &privileged_pp_guid, as_default, as_meta, datap, lease_duration, rst->vendor, custom_flags, timestamp, seq)) { - int have_dst = - (rst->dst_guid_prefix.u[0] != 0 || rst->dst_guid_prefix.u[1] != 0 || rst->dst_guid_prefix.u[2] != 0); + /* If no proxy participant was created, don't respond */ + return 0; + } + else + { + /* Force transmission of SPDP messages - we're not very careful + in avoiding the processing of SPDP packets addressed to others + so filter here */ + int have_dst = (rst->dst_guid_prefix.u[0] != 0 || rst->dst_guid_prefix.u[1] != 0 || rst->dst_guid_prefix.u[2] != 0); if (!have_dst) { GVLOGDISC ("broadcasted SPDP packet -> answering"); @@ -795,27 +784,27 @@ static int handle_SPDP_alive (const struct receiver_state *rst, seqno_t seq, dds { GVLOGDISC ("directed SPDP packet -> not responding\n"); } - } - if (custom_flags & CF_PARTICIPANT_IS_DDSI2) - { - /* If we just discovered DDSI2, make sure any existing - participants served by it are made dependent on it */ - make_participants_dependent_on_ddsi2 (gv, &datap->participant_guid, timestamp); - } - else if (privileged_pp_guid.prefix.u[0] || privileged_pp_guid.prefix.u[1] || privileged_pp_guid.prefix.u[2]) - { - /* If we just created a participant dependent on DDSI2, make sure - DDSI2 still exists. There is a risk of racing the lease expiry - of DDSI2. */ - if (entidx_lookup_proxy_participant_guid (gv->entity_index, &privileged_pp_guid) == NULL) + if (custom_flags & CF_PARTICIPANT_IS_DDSI2) { - GVLOGDISC ("make_participants_dependent_on_ddsi2: ddsi2 "PGUIDFMT" is no more, delete "PGUIDFMT"\n", - PGUID (privileged_pp_guid), PGUID (datap->participant_guid)); - delete_proxy_participant_by_guid (gv, &datap->participant_guid, timestamp, 1); + /* If we just discovered DDSI2, make sure any existing + participants served by it are made dependent on it */ + make_participants_dependent_on_ddsi2 (gv, &datap->participant_guid, timestamp); } + else if (privileged_pp_guid.prefix.u[0] || privileged_pp_guid.prefix.u[1] || privileged_pp_guid.prefix.u[2]) + { + /* If we just created a participant dependent on DDSI2, make sure + DDSI2 still exists. There is a risk of racing the lease expiry + of DDSI2. */ + if (entidx_lookup_proxy_participant_guid (gv->entity_index, &privileged_pp_guid) == NULL) + { + GVLOGDISC ("make_participants_dependent_on_ddsi2: ddsi2 "PGUIDFMT" is no more, delete "PGUIDFMT"\n", + PGUID (privileged_pp_guid), PGUID (datap->participant_guid)); + delete_proxy_participant_by_guid (gv, &datap->participant_guid, timestamp, 1); + } + } + return 1; } - return 1; } static void handle_SPDP (const struct receiver_state *rst, ddsi_entityid_t pwr_entityid, seqno_t seq, const struct ddsi_serdata *serdata) @@ -1102,7 +1091,7 @@ static struct proxy_participant *implicitly_create_proxypp (struct ddsi_domaingv doing anything about (1). That means we fall back to the legacy mode of locally generating GIDs but leaving the system id unchanged if the remote is OSPL. */ actual_vendorid = (datap->present & PP_VENDORID) ? datap->vendorid : vendorid; - new_proxy_participant(gv, ppguid, 0, &privguid, new_addrset(), new_addrset(), &pp_plist, DDS_INFINITY, actual_vendorid, CF_IMPLICITLY_CREATED_PROXYPP, timestamp, seq); + (void) new_proxy_participant(gv, ppguid, 0, &privguid, new_addrset(), new_addrset(), &pp_plist, DDS_INFINITY, actual_vendorid, CF_IMPLICITLY_CREATED_PROXYPP, timestamp, seq); } else if (ppguid->prefix.u[0] == src_guid_prefix->u[0] && vendor_is_eclipse_or_opensplice (vendorid)) { diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 9a8b5ef..5ea7def 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -4872,7 +4872,7 @@ static void free_proxy_participant(struct proxy_participant *proxypp) ddsrt_free (proxypp); } -void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const ddsi_plist_t *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, ddsrt_wctime_t timestamp, seqno_t seq) +bool new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *ppguid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const ddsi_plist_t *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, ddsrt_wctime_t timestamp, seqno_t seq) { /* No locking => iff all participants use unique guids, and sedp runs on a single thread, it can't go wrong. FIXME, maybe? The @@ -4978,7 +4978,7 @@ void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *pp { GVWARNING ("Remote secure participant "PGUIDFMT" not allowed\n", PGUID (*ppguid)); free_proxy_participant (proxypp); - return; + return false; } } #endif @@ -5004,6 +5004,7 @@ void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *pp proxy_participant_create_handshakes (gv, proxypp); } #endif + return true; } int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, seqno_t seq, const struct ddsi_plist *datap, ddsrt_wctime_t timestamp) From 2aa70548cc05a851f8f205861e9f6c04b76c5587 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 16 May 2020 11:13:58 +0200 Subject: [PATCH 232/238] Tweak timeouts in secure communication tests * Increase the matching timeout to 5s (there are some hints the failures on Travis are timing related) * Replace the relative timeout in the waitset by a timestamp so that it gives up after the specified timeout regardless of the number of events that occur Signed-off-by: Erik Boasson --- src/security/core/tests/common/test_utils.c | 6 ++++-- src/security/core/tests/secure_communication.c | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/security/core/tests/common/test_utils.c b/src/security/core/tests/common/test_utils.c index cab9bef..39c0489 100644 --- a/src/security/core/tests/common/test_utils.c +++ b/src/security/core/tests/common/test_utils.c @@ -390,6 +390,7 @@ void handshake_list_fini (struct Handshake *hs_list, int nhs) void sync_writer_to_readers (dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_count, dds_duration_t timeout) { + dds_time_t abstimeout = dds_time() + timeout; dds_attach_t triggered; dds_entity_t ws = dds_create_waitset (pp_wr); CU_ASSERT_FATAL (ws > 0); @@ -399,7 +400,7 @@ void sync_writer_to_readers (dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_c CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); while (true) { - ret = dds_waitset_wait (ws, &triggered, 1, timeout); + ret = dds_waitset_wait_until (ws, &triggered, 1, abstimeout); CU_ASSERT_EQUAL_FATAL (exp_count > 0, ret >= 1); if (exp_count > 0) CU_ASSERT_EQUAL_FATAL (wr, (dds_entity_t)(intptr_t) triggered); @@ -414,6 +415,7 @@ void sync_writer_to_readers (dds_entity_t pp_wr, dds_entity_t wr, uint32_t exp_c void sync_reader_to_writers (dds_entity_t pp_rd, dds_entity_t rd, uint32_t exp_count, dds_duration_t timeout) { + dds_time_t abstimeout = dds_time() + timeout; dds_attach_t triggered; dds_entity_t ws = dds_create_waitset (pp_rd); CU_ASSERT_FATAL (ws > 0); @@ -423,7 +425,7 @@ void sync_reader_to_writers (dds_entity_t pp_rd, dds_entity_t rd, uint32_t exp_c CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); while (true) { - ret = dds_waitset_wait (ws, &triggered, 1, timeout); + ret = dds_waitset_wait_until (ws, &triggered, 1, abstimeout); CU_ASSERT_EQUAL_FATAL (exp_count > 0, ret >= 1); if (exp_count > 0) CU_ASSERT_EQUAL_FATAL (rd, (dds_entity_t)(intptr_t) triggered); diff --git a/src/security/core/tests/secure_communication.c b/src/security/core/tests/secure_communication.c index 3a3a6ec..2d1720d 100644 --- a/src/security/core/tests/secure_communication.c +++ b/src/security/core/tests/secure_communication.c @@ -254,7 +254,7 @@ static void test_write_read(struct domain_sec_config *domain_config, for (size_t w = 0; w < n_writers; w++) { size_t wr_index = pp_index * n_writers + w; - sync_writer_to_readers (g_pub_participants[pp_index], writers[wr_index], (uint32_t)(n_sub_domains * n_sub_participants * n_readers), DDS_SECS(2)); + sync_writer_to_readers (g_pub_participants[pp_index], writers[wr_index], (uint32_t)(n_sub_domains * n_sub_participants * n_readers), DDS_SECS(5)); sample.id = (int32_t) wr_index; printf("writer %"PRId32" writing sample %d\n", writers[wr_index], sample.id); ret = dds_write (writers[wr_index], &sample); From 296b49cf2077bf262ca9d97f5117e6669e081f6b Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Sat, 16 May 2020 21:54:11 +0200 Subject: [PATCH 233/238] Fix use-after-free via (proxy)pp min lease pointer This changes the handling of the removal of the lease of a manual liveliness (proxy) writer from the (proxy) participant, such that the invariant maintained for the "min lease" objects in the (proxy) participant changes from: a clone of some lease with the minimum duration, to: a clone of the lease that is returned by the ddsrt_fibheap_min operation on the lease heap. This fixes a use-after-free of the entity pointed to by the cloned lease object in a scenario where the shortest lease duration is used by multiple writers and the removal of a lease from the heap shuffles the remaining entries around. For example (before this change): 1. initial situation: three writers w1, w2 and w3 with equal lease durations: - pp.heap = w1.lease : w2.lease w3.lease - pp.minl = clone of w1.lease 2. delete w2: - assuming deleting w2.lease from the heap moves w3.lease to the front (only guarantee is that there are no smaller keys in the heap than that of the entry returned by minimum operation) - min(pp.heap) = w1.lease != w2.lease thus: pp.minl unchanged, pp.minl.entity = w1 - pp.heap = w3.lease : w1.lease 3. delete w1: - min(pp.heap) = w3.lease != w1.lease, thus: pp.minl unchanged, pp.minl.entity = w1 - pp.heap = w3 - free w1 - now pp.minl.entity has a dangling pointer, touched on deleting the (proxy) particpant or on lease expiry. With this chamge, pp.minl is updated in step 2 to be a clone of w3.lease because the lease returned by min(pp.heap) changes. This ensures that in step 3 there is no dangling pointer and no use-after-free. Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/q_entity.h | 6 ++-- src/core/ddsi/src/q_entity.c | 36 +++++++++++++---------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/q_entity.h b/src/core/ddsi/include/dds/ddsi/q_entity.h index 8a4f22f..ce1c7c3 100644 --- a/src/core/ddsi/include/dds/ddsi/q_entity.h +++ b/src/core/ddsi/include/dds/ddsi/q_entity.h @@ -231,7 +231,7 @@ struct participant int32_t builtin_refc; /* number of built-in endpoints in this participant [refc_lock] */ int builtins_deleted; /* whether deletion of built-in endpoints has been initiated [refc_lock] */ ddsrt_fibheap_t ldur_auto_wr; /* Heap that contains lease duration for writers with automatic liveliness in this participant */ - ddsrt_atomic_voidp_t minl_man; /* lease object for shortest manual-by-participant liveliness writer's lease */ + ddsrt_atomic_voidp_t minl_man; /* clone of min(leaseheap_man) */ ddsrt_fibheap_t leaseheap_man; /* keeps leases for this participant's writers (with liveliness manual-by-participant) */ #ifdef DDSI_INCLUDE_SECURITY struct participant_sec_attributes *sec_attr; @@ -369,9 +369,9 @@ struct proxy_participant unsigned bes; /* built-in endpoint set */ ddsi_guid_t privileged_pp_guid; /* if this PP depends on another PP for its SEDP writing */ struct ddsi_plist *plist; /* settings/QoS for this participant */ - ddsrt_atomic_voidp_t minl_auto; /* lease object for shortest automatic liveliness pwr's lease (includes this proxypp's lease) */ + ddsrt_atomic_voidp_t minl_auto; /* clone of min(leaseheap_auto) */ ddsrt_fibheap_t leaseheap_auto; /* keeps leases for this proxypp and leases for pwrs (with liveliness automatic) */ - ddsrt_atomic_voidp_t minl_man; /* lease object for shortest manual-by-participant liveliness pwr's lease */ + ddsrt_atomic_voidp_t minl_man; /* clone of min(leaseheap_man) */ ddsrt_fibheap_t leaseheap_man; /* keeps leases for this proxypp and leases for pwrs (with liveliness manual-by-participant) */ struct lease *lease; /* lease for this proxypp */ struct addrset *as_default; /* default address set to use for user data traffic */ diff --git a/src/core/ddsi/src/q_entity.c b/src/core/ddsi/src/q_entity.c index 5ea7def..2c3ca90 100644 --- a/src/core/ddsi/src/q_entity.c +++ b/src/core/ddsi/src/q_entity.c @@ -750,7 +750,7 @@ static void participant_add_wr_lease_locked (struct participant * pp, const stru minl_prev = ddsrt_fibheap_min (&lease_fhdef_pp, &pp->leaseheap_man); ddsrt_fibheap_insert (&lease_fhdef_pp, &pp->leaseheap_man, wr->lease); minl_new = ddsrt_fibheap_min (&lease_fhdef_pp, &pp->leaseheap_man); - /* if inserted lease is new shortest lease */ + /* ensure pp->minl_man is equivalent to min(leaseheap_man) */ if (minl_prev != minl_new) { ddsrt_etime_t texp = ddsrt_etime_add_duration (ddsrt_time_elapsed (), minl_new->tdur); @@ -770,21 +770,23 @@ static void participant_add_wr_lease_locked (struct participant * pp, const stru static void participant_remove_wr_lease_locked (struct participant * pp, struct writer * wr) { - struct lease *minl; + struct lease *minl_prev; + struct lease *minl_new; assert (wr->lease != NULL); assert (wr->xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT); - minl = ddsrt_fibheap_min (&lease_fhdef_pp, &pp->leaseheap_man); + minl_prev = ddsrt_fibheap_min (&lease_fhdef_pp, &pp->leaseheap_man); ddsrt_fibheap_delete (&lease_fhdef_pp, &pp->leaseheap_man, wr->lease); - /* if writer with min lease is removed: update participant lease to use new minimal duration */ - if (wr->lease == minl) + minl_new = ddsrt_fibheap_min (&lease_fhdef_pp, &pp->leaseheap_man); + /* ensure pp->minl_man is equivalent to min(leaseheap_man) */ + if (minl_prev != minl_new) { - if ((minl = ddsrt_fibheap_min (&lease_fhdef_pp, &pp->leaseheap_man)) != NULL) + if (minl_new != NULL) { - dds_duration_t trem = minl->tdur - wr->lease->tdur; + dds_duration_t trem = minl_new->tdur - minl_prev->tdur; assert (trem >= 0); ddsrt_etime_t texp = ddsrt_etime_add_duration (ddsrt_time_elapsed(), trem); - struct lease *lnew = lease_new (texp, minl->tdur, minl->entity); + struct lease *lnew = lease_new (texp, minl_new->tdur, minl_new->entity); participant_replace_minl (pp, lnew); lease_register (lnew); } @@ -4692,7 +4694,7 @@ static void proxy_participant_add_pwr_lease_locked (struct proxy_participant * p minl_prev = ddsrt_fibheap_min (&lease_fhdef_pp, lh); ddsrt_fibheap_insert (&lease_fhdef_pp, lh, pwr->lease); minl_new = ddsrt_fibheap_min (&lease_fhdef_pp, lh); - /* if inserted lease is new shortest lease */ + /* ensure proxypp->minl_man/minl_auto is equivalent to min(leaseheap_man/auto) */ if (proxypp->owns_lease && minl_prev != minl_new) { ddsrt_etime_t texp = ddsrt_etime_add_duration (ddsrt_time_elapsed (), minl_new->tdur); @@ -4713,24 +4715,26 @@ static void proxy_participant_add_pwr_lease_locked (struct proxy_participant * p static void proxy_participant_remove_pwr_lease_locked (struct proxy_participant * proxypp, struct proxy_writer * pwr) { - struct lease *minl; + struct lease *minl_prev; + struct lease *minl_new; bool manbypp; ddsrt_fibheap_t *lh; assert (pwr->lease != NULL); manbypp = (pwr->c.xqos->liveliness.kind == DDS_LIVELINESS_MANUAL_BY_PARTICIPANT); lh = manbypp ? &proxypp->leaseheap_man : &proxypp->leaseheap_auto; - minl = ddsrt_fibheap_min (&lease_fhdef_pp, lh); + minl_prev = ddsrt_fibheap_min (&lease_fhdef_pp, lh); ddsrt_fibheap_delete (&lease_fhdef_pp, lh, pwr->lease); - /* if pwr with min lease is removed: update proxypp lease to use new minimal duration */ - if (proxypp->owns_lease && pwr->lease == minl) + minl_new = ddsrt_fibheap_min (&lease_fhdef_pp, lh); + /* ensure proxypp->minl_man/minl_auto is equivalent to min(leaseheap_man/auto) */ + if (proxypp->owns_lease && minl_prev != minl_new) { - if ((minl = ddsrt_fibheap_min (&lease_fhdef_pp, lh)) != NULL) + if (minl_new != NULL) { - dds_duration_t trem = minl->tdur - pwr->lease->tdur; + dds_duration_t trem = minl_new->tdur - minl_prev->tdur; assert (trem >= 0); ddsrt_etime_t texp = ddsrt_etime_add_duration (ddsrt_time_elapsed(), trem); - struct lease *lnew = lease_new (texp, minl->tdur, minl->entity); + struct lease *lnew = lease_new (texp, minl_new->tdur, minl_new->entity); proxy_participant_replace_minl (proxypp, manbypp, lnew); lease_register (lnew); } From d4013f9c82f531cdcd6e9eaf3867595dc2ffa822 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 18 May 2020 14:03:30 +0200 Subject: [PATCH 234/238] Handling of syntax errors in network partitions The various network partition-related structs were left mostly uninitialized by the various init functions (e.g., if_partition_mapping) and these were moreover interpreted on parse errors. This initializes them to null pointers and skips all configuration post-processing in case of an error. Signed-off-by: Erik Boasson --- src/core/ddsi/src/q_config.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c index e54c7e6..1f5ffa1 100644 --- a/src/core/ddsi/src/q_config.c +++ b/src/core/ddsi/src/q_config.c @@ -1388,20 +1388,30 @@ static int if_network_partition (struct cfgst *cfgst, void *parent, struct cfgel if (new == NULL) return -1; new->address_string = NULL; + new->as = NULL; + new->name = NULL; + new->partitionId = 0; + new->connected = 0; return 0; } static int if_ignored_partition (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { + struct config_ignoredpartition_listelem *new = if_common (cfgst, parent, cfgelem, sizeof(*new)); if (if_common (cfgst, parent, cfgelem, sizeof (struct config_ignoredpartition_listelem)) == NULL) return -1; + new->DCPSPartitionTopic = NULL; return 0; } static int if_partition_mapping (struct cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) { - if (if_common (cfgst, parent, cfgelem, sizeof (struct config_partitionmapping_listelem)) == NULL) + struct config_partitionmapping_listelem *new = if_common (cfgst, parent, cfgelem, sizeof(*new)); + if (new == NULL) return -1; + new->DCPSPartitionTopic = NULL; + new->networkPartition = NULL; + new->partition = NULL; return 0; } #endif /* DDSI_INCLUDE_NETWORK_PARTITIONS */ @@ -2937,6 +2947,7 @@ struct cfgst *config_init (const char *config, struct config *cfg, uint32_t domi /* Compatibility settings of IPv6, TCP -- a bit too complicated for the poor framework */ + if (ok) { int ok1 = 1; switch (cfgst->cfg->transport_selector) @@ -2946,7 +2957,7 @@ struct cfgst *config_init (const char *config, struct config *cfg, uint32_t domi cfgst->cfg->transport_selector = (cfgst->cfg->compat_use_ipv6 == BOOLDEF_TRUE) ? TRANS_TCP6 : TRANS_TCP; else cfgst->cfg->transport_selector = (cfgst->cfg->compat_use_ipv6 == BOOLDEF_TRUE) ? TRANS_UDP6 : TRANS_UDP; - break; + break; case TRANS_TCP: ok1 = !(cfgst->cfg->compat_tcp_enable == BOOLDEF_FALSE || cfgst->cfg->compat_use_ipv6 == BOOLDEF_TRUE); break; @@ -2973,14 +2984,18 @@ struct cfgst *config_init (const char *config, struct config *cfg, uint32_t domi #ifdef DDSI_INCLUDE_NETWORK_CHANNELS /* Default channel gets set outside set_defaults -- a bit too complicated for the poor framework */ - if (set_default_channel (cfgst->cfg) < 0) - ok = 0; - if (cfgst->cfg->channels && sort_channels_check_nodups (cfgst->cfg) < 0) - ok = 0; + if (ok) + { + if (set_default_channel (cfgst->cfg) < 0) + ok = 0; + if (cfgst->cfg->channels && sort_channels_check_nodups (cfgst->cfg) < 0) + ok = 0; + } #endif #ifdef DDSI_INCLUDE_NETWORK_PARTITIONS /* Assign network partition ids */ + if (ok) { struct config_networkpartition_listelem *p = cfgst->cfg->networkPartitions; cfgst->cfg->nof_networkPartitions = 0; @@ -2994,6 +3009,7 @@ struct cfgst *config_init (const char *config, struct config *cfg, uint32_t domi /* Create links from the partitionmappings to the network partitions and signal errors if partitions do not exist */ + if (ok) { struct config_partitionmapping_listelem * m = cfgst->cfg->partitionMappings; while (m) From cc8308819d75958bf84dc2cf43e8c667afbbf2a5 Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Tue, 19 May 2020 17:13:34 +0200 Subject: [PATCH 235/238] Refactor access control test permissions_expiry_multiple to reduce timing issues in test runs on travis Signed-off-by: Dennis Potman --- src/security/core/tests/access_control.c | 133 +++++++++++------------ 1 file changed, 61 insertions(+), 72 deletions(-) diff --git a/src/security/core/tests/access_control.c b/src/security/core/tests/access_control.c index f22dbe5..6fbdb52 100644 --- a/src/security/core/tests/access_control.c +++ b/src/security/core/tests/access_control.c @@ -257,13 +257,12 @@ CU_Theory( } -#define N_RD 1 // N_RD > 1 not yet implemented #define N_WR 3 -#define N_NODES (N_RD + N_WR) -#define PERM_EXP_BASE 3 +#define N_NODES (1 + N_WR) +#define PERM_EXP_BASE 2 +#define PERM_EXP_INCR 2 /* Tests permissions configuration expiry using multiple writers, to validate - that a reader still received data from writers that still have valid - permissions config */ + that a reader keeps receiving data from writers that have valid permissions config */ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) { char topic_name[100]; @@ -290,10 +289,10 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) gov[i] = PF_F COMMON_ETC_PATH ("default_governance.p7s"); perm_ca[i] = PF_F COMMON_ETC_PATH ("default_permissions_ca.pem"); incl_el[i] = true; - dds_duration_t v = DDS_SECS(i < N_RD ? 3600 : PERM_EXP_BASE + 2 * i); /* readers should not expire */ + dds_duration_t v = DDS_SECS(i == 0 ? 3600 : PERM_EXP_BASE + PERM_EXP_INCR * i); /* reader should not expire */ dds_time_t t_exp = ddsrt_time_add_duration (t_perm, v); - if (i >= N_RD) - print_test_msg ("w[%d] grant expires at %d.%06d\n", i - N_RD, (int32_t) (t_exp / DDS_NSECS_IN_SEC), (int32_t) (t_exp % DDS_NSECS_IN_SEC) / 1000); + if (i >= 1) + print_test_msg ("w[%d] grant expires at %d.%06d\n", i - 1, (int32_t) (t_exp / DDS_NSECS_IN_SEC), (int32_t) (t_exp % DDS_NSECS_IN_SEC) / 1000); grants[i] = get_permissions_grant (id_name, id_subj[i], t_perm, t_exp, rules_xml, NULL); ddsrt_free (id_name); } @@ -307,104 +306,94 @@ CU_Test(ddssec_access_control, permissions_expiry_multiple, .timeout=20) id, pk, ca_list, exp_fail, NULL, NULL, incl_el, gov, incl_el, perm_conf, incl_el, perm_ca); - dds_qos_t * qos = get_default_test_qos (); - dds_entity_t rd[N_RD]; - for (int i = 0; i < N_RD; i++) - { - dds_entity_t sub = dds_create_subscriber (g_participant[i], NULL, NULL); - CU_ASSERT_FATAL (sub > 0); - dds_entity_t sub_tp = dds_create_topic (g_participant[i], &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL); - CU_ASSERT_FATAL (sub_tp > 0); - rd[i] = dds_create_reader (sub, sub_tp, qos, NULL); - CU_ASSERT_FATAL (rd[i] > 0); - dds_set_status_mask (rd[i], DDS_SUBSCRIPTION_MATCHED_STATUS); - } + // create 1 reader + dds_qos_t * rdqos = get_default_test_qos (); + dds_entity_t sub = dds_create_subscriber (g_participant[0], NULL, NULL); + CU_ASSERT_FATAL (sub > 0); + dds_entity_t sub_tp = dds_create_topic (g_participant[0], &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL); + CU_ASSERT_FATAL (sub_tp > 0); + dds_entity_t rd = dds_create_reader (sub, sub_tp, rdqos, NULL); + CU_ASSERT_FATAL (rd > 0); + dds_set_status_mask (rd, DDS_SUBSCRIPTION_MATCHED_STATUS); + dds_delete_qos (rdqos); + // create N_WR writers + dds_qos_t * wrqos = get_default_test_qos (); dds_entity_t wr[N_WR]; for (int i = 0; i < N_WR; i++) { - dds_entity_t pub = dds_create_publisher (g_participant[i + N_RD], NULL, NULL); + dds_entity_t pub = dds_create_publisher (g_participant[i + 1], NULL, NULL); CU_ASSERT_FATAL (pub > 0); - dds_entity_t pub_tp = dds_create_topic (g_participant[i + N_RD], &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL); + dds_entity_t pub_tp = dds_create_topic (g_participant[i + 1], &SecurityCoreTests_Type1_desc, topic_name, NULL, NULL); CU_ASSERT_FATAL (pub_tp > 0); - wr[i] = dds_create_writer (pub, pub_tp, qos, NULL); + wr[i] = dds_create_writer (pub, pub_tp, wrqos, NULL); CU_ASSERT_FATAL (wr[i] > 0); dds_set_status_mask (wr[i], DDS_PUBLICATION_MATCHED_STATUS); - sync_writer_to_readers (g_participant[i + N_RD], wr[i], N_RD, DDS_SECS(2)); - } - dds_delete_qos (qos); - for (int i = 0; i < N_RD; i++) - { - sync_reader_to_writers (g_participant[i], rd[i], N_WR, DDS_SECS (2)); - dds_set_status_mask (rd[i], DDS_DATA_AVAILABLE_STATUS); + sync_writer_to_readers (g_participant[i + 1], wr[i], 1, DDS_SECS(2)); } + dds_delete_qos (wrqos); + sync_reader_to_writers (g_participant[0], rd, N_WR, DDS_SECS (2)); + + // write data SecurityCoreTests_Type1 sample = { 1, 1 }; - SecurityCoreTests_Type1 rd_sample; - void * samples[] = { &rd_sample }; - dds_sample_info_t info[1]; dds_return_t ret; + dds_entity_t ws = dds_create_waitset (g_participant[0]); + dds_entity_t gcond = dds_create_guardcondition (g_participant[0]); + dds_set_guardcondition (gcond, false); + dds_waitset_attach (ws, gcond, 0); + dds_set_status_mask (rd, DDS_DATA_AVAILABLE_STATUS); for (int run = 0; run < N_WR; run++) { - // sleep until 1s after next writer pp permission expires - dds_duration_t delay = DDS_SECS (PERM_EXP_BASE + 2 * run + 1) - (dds_time () - t_perm); - if (delay > 0) - dds_sleepfor (delay); - + // wait until 1s after next writer pp permission expires + dds_waitset_wait_until (ws, NULL, 0, t_perm + DDS_SECS (PERM_EXP_BASE + PERM_EXP_INCR * run + 1)); print_test_msg ("run %d\n", run); - - for (int w = run; w < N_WR; w++) + for (int w = 0; w < N_WR; w++) { sample.id = w; ret = dds_write (wr[w], &sample); - CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); print_test_msg ("write %d\n", w); + CU_ASSERT_EQUAL_FATAL (ret, DDS_RETCODE_OK); } - - // Expect reader to receive data from writers with non-expired permissions - int n_samples = 0, n_invalid = 0, n_wait = 0; - while (n_samples + n_invalid < N_WR && n_wait < 5) - { - ret = dds_take (rd[0], samples, info, 1, 1); - CU_ASSERT_FATAL (ret >= 0); - if (ret == 0) - { - reader_wait_for_data (g_participant[0], rd[0], DDS_MSECS (200)); - print_test_msg ("wait for data\n"); - n_wait++; - } - else if (info[0].instance_state == DDS_IST_ALIVE) - { - print_test_msg ("recv sample %d\n", rd_sample.id); - n_samples++; - } - else - { - print_test_msg ("recv inv sample\n"); - n_invalid++; - } - } - CU_ASSERT_EQUAL (n_samples, N_WR - run); - CU_ASSERT (n_invalid <= run); } - access_control_fini (N_NODES, NULL, 0); + // wait until last pp's permissions are expired + dds_waitset_wait_until (ws, NULL, 0, t_perm + DDS_SECS (PERM_EXP_BASE + PERM_EXP_INCR * N_WR + 1)); + // check received data + SecurityCoreTests_Type1 * data = ddsrt_calloc (N_WR, sizeof (*data)); + dds_sample_info_t rd_info[N_WR]; + static void * rd_samples[N_WR]; + for (int i = 0; i < N_WR; i++) + rd_samples[i] = &data[i]; + + for (int w = 0; w < N_WR; w++) + { + sample.id = w; + dds_instance_handle_t ih = dds_lookup_instance(rd, &sample); + CU_ASSERT_NOT_EQUAL_FATAL(ih, DDS_HANDLE_NIL); + ret = dds_take_instance (rd, rd_samples, rd_info, N_WR, N_WR, ih); + print_test_msg ("samples from writer %d: %d\n", w, ret); + CU_ASSERT_EQUAL_FATAL (ret, w + 1); + print_test_msg ("writer %d instance state: %d\n", w, rd_info[w].instance_state); + CU_ASSERT_EQUAL_FATAL (rd_info[w].instance_state, DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE); + print_test_msg ("writer %d valid data: %d\n", w, rd_info[w].valid_data); + CU_ASSERT_EQUAL_FATAL (rd_info[w].valid_data, true); + } + + access_control_fini (N_NODES, (void * []) { ca, rules_xml, perm_config_str, data }, 4); for (int i = 0; i < N_NODES; i++) { ddsrt_free (grants[i]); ddsrt_free (id_subj[i]); ddsrt_free ((char *)id[i]); } - ddsrt_free (ca); - ddsrt_free (rules_xml); - ddsrt_free (perm_config_str); } -#undef N_RD #undef N_WR #undef N_NODES #undef PERM_EXP_BASE +#undef PERM_EXP_INCR #define na false CU_TheoryDataPoints(ddssec_access_control, hooks) = { From 6a9ebf88eba8b73091a38d200129f45c6836f78e Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 25 May 2020 09:10:10 +0200 Subject: [PATCH 236/238] OpenSSL 1.0.2 compatibility This addresses a number of issues with building Cyclone DDS including DDS Security while using OpenSSL 1.0.2. Compatibility with 1.0.2 is a courtesy towards those who are unable to move to 1.1.x or later because of other libraries. * On Windows, one must include Winsock2.h prior to including the OpenSSL header files, or it'll pull in incompatible definitions from Winsock.h and that breaks some of the files. * OpenSSL 1.0.2 requires initializing the library (or more particular, loading all the required algorithms) but this is no longer needed in OpenSSL 1.1.x. It ends up being needed in a few places and having tons of essentially dead initialization code lying around is unpleasant. Hence this has been consolidated in a single function and protected with ddsrt_once(). * One ought to undo the above initialization on 1.0.2g and older, but it is impossible to know whether that can safely be done from a library. This is also the reason OpenSSL deprecated all the initialization and cleanup interfaces. So if one insists on trying it with such an old version, let there be some leaks. * Thread state cleanup is sort-of required prior 1.1.0, but that suffers from the same problems; we'd have to do per-thread cleanup code for OpenSSL for any thread that could call into it (which is pretty much any thread). So once again, people should just use 1.1.0 or newer. * There are some interfaces added in 1.1.0 that we use, but a few small workarounds those can be made to work on 1.0.2 as well. These also were replicated in a number of places and consolidated by this commit. Signed-off-by: Erik Boasson --- src/ddsrt/include/dds/ddsrt/xmlparser.h | 1 + src/security/CMakeLists.txt | 1 + .../access_control/CMakeLists.txt | 2 + .../access_control/src/access_control.c | 23 +--- .../src/access_control_objects.h | 2 +- .../src/access_control_parser.c | 6 +- .../access_control/src/access_control_utils.c | 7 +- .../access_control/src/access_control_utils.h | 4 +- .../authentication/CMakeLists.txt | 2 + .../authentication/src/auth_utils.c | 41 ++---- .../authentication/src/auth_utils.h | 7 + .../authentication/src/authentication.c | 47 +------ .../cryptographic/CMakeLists.txt | 2 + .../cryptographic/src/crypto_cipher.c | 4 +- .../cryptographic/src/crypto_key_factory.c | 7 +- .../cryptographic/src/crypto_transform.c | 25 +--- .../cryptographic/src/crypto_utils.c | 6 +- .../builtin_plugins/tests/CMakeLists.txt | 15 +-- .../tests/common/src/crypto_helper.c | 5 +- .../tests/common/src/handshake_helper.c | 30 ++--- .../tests/common/src/handshake_helper.h | 10 +- ...te_local_datareader_crypto_tokens_utests.c | 6 +- ...te_local_datawriter_crypto_tokens_utests.c | 6 +- ...e_local_participant_crypto_tokens_utests.c | 6 +- .../src/decode_datareader_submessage_utests.c | 7 +- .../src/decode_datawriter_submessage_utests.c | 5 +- .../src/decode_rtps_message_utests.c | 5 +- .../src/decode_serialized_payload_utests.c | 6 +- .../src/encode_datareader_submessage_utests.c | 5 +- .../src/encode_datawriter_submessage_utests.c | 5 +- .../src/encode_rtps_message_utests.c | 5 +- .../src/encode_serialized_payload_utests.c | 5 +- ...thenticated_peer_credential_token_utests.c | 28 ++-- .../get_permissions_credential_token_utests.c | 5 +- .../src/get_permissions_token_utests.c | 5 +- .../src/get_xxx_sec_attributes_utests.c | 5 +- .../src/listeners_access_control_utests.c | 23 +--- .../src/listeners_authentication_utests.c | 50 ++----- .../src/preprocess_secure_submsg_utests.c | 6 +- .../src/process_handshake_utests.c | 37 ++--- .../src/register_local_datareader_utests.c | 6 +- .../src/register_local_datawriter_utests.c | 6 +- .../src/register_local_participant_utests.c | 6 +- ...egister_matched_remote_datareader_utests.c | 6 +- ...egister_matched_remote_datawriter_utests.c | 6 +- ...gister_matched_remote_participant_utests.c | 6 +- ...t_remote_datareader_crypto_tokens_utests.c | 6 +- ...t_remote_datawriter_crypto_tokens_utests.c | 6 +- ..._remote_participant_crypto_tokens_utests.c | 6 +- .../validate_begin_handshake_reply_utests.c | 36 ++--- .../validate_begin_handshake_request_utests.c | 4 + .../src/validate_local_identity_utests.c | 3 +- .../src/validate_local_permissions_utests.c | 5 +- .../src/validate_remote_permissions_utests.c | 5 +- .../dds/security/core/dds_security_utils.h | 12 +- src/security/core/src/dds_security_utils.c | 47 +------ src/security/core/tests/CMakeLists.txt | 7 + src/security/core/tests/common/cert_utils.c | 7 +- .../tests/common/security_config_test_utils.c | 9 +- src/security/openssl/CMakeLists.txt | 21 +++ .../include/dds/security/openssl_support.h | 80 +++++++++++ src/security/openssl/src/openssl_support.c | 127 ++++++++++++++++++ 62 files changed, 380 insertions(+), 504 deletions(-) create mode 100644 src/security/openssl/CMakeLists.txt create mode 100644 src/security/openssl/include/dds/security/openssl_support.h create mode 100644 src/security/openssl/src/openssl_support.c diff --git a/src/ddsrt/include/dds/ddsrt/xmlparser.h b/src/ddsrt/include/dds/ddsrt/xmlparser.h index 93bd92d..732bb2a 100644 --- a/src/ddsrt/include/dds/ddsrt/xmlparser.h +++ b/src/ddsrt/include/dds/ddsrt/xmlparser.h @@ -12,6 +12,7 @@ #ifndef DDSRT_XMLPARSER_H #define DDSRT_XMLPARSER_H +#include #include #include "dds/export.h" diff --git a/src/security/CMakeLists.txt b/src/security/CMakeLists.txt index fd9af5d..1c8ec01 100644 --- a/src/security/CMakeLists.txt +++ b/src/security/CMakeLists.txt @@ -16,6 +16,7 @@ if(ENABLE_SECURITY) add_subdirectory(core) if(ENABLE_SSL) + add_subdirectory(openssl) add_subdirectory(builtin_plugins) endif() endif() diff --git a/src/security/builtin_plugins/access_control/CMakeLists.txt b/src/security/builtin_plugins/access_control/CMakeLists.txt index e7bf471..d21815c 100644 --- a/src/security/builtin_plugins/access_control/CMakeLists.txt +++ b/src/security/builtin_plugins/access_control/CMakeLists.txt @@ -26,6 +26,7 @@ generate_export_header( EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/dds/security/export.h" ) +target_link_libraries(dds_security_ac PRIVATE security_openssl) target_link_libraries(dds_security_ac PUBLIC ddsc) target_link_libraries(dds_security_ac PUBLIC OpenSSL::SSL) if(CMAKE_GENERATOR MATCHES "Visual Studio") @@ -36,6 +37,7 @@ target_include_directories(dds_security_ac PUBLIC "$>" "$>" + "$>" "$>" "$" ) diff --git a/src/security/builtin_plugins/access_control/src/access_control.c b/src/security/builtin_plugins/access_control/src/access_control.c index e9d91e0..1a45c4e 100644 --- a/src/security/builtin_plugins/access_control/src/access_control.c +++ b/src/security/builtin_plugins/access_control/src/access_control.c @@ -13,8 +13,7 @@ #include #include -#include -#include + #include "dds/ddsrt/heap.h" #include "dds/ddsrt/misc.h" #include "dds/ddsrt/string.h" @@ -24,19 +23,12 @@ #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/dds_security_timed_cb.h" +#include "dds/security/openssl_support.h" #include "access_control.h" #include "access_control_utils.h" #include "access_control_objects.h" #include "access_control_parser.h" -#if OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10100000L -#define REMOVE_THREAD_STATE() ERR_remove_thread_state(NULL); -#elif OPENSSL_VERSION_NUMBER < 0x10000000L -#define REMOVE_THREAD_STATE() ERR_remove_state(0); -#else -#define REMOVE_THREAD_STATE() -#endif - static const char *ACCESS_CONTROL_PROTOCOL_CLASS = "DDS:Access"; static const unsigned ACCESS_CONTROL_PROTOCOL_VERSION_MAJOR = 1; static const unsigned ACCESS_CONTROL_PROTOCOL_VERSION_MINOR = 0; @@ -1522,12 +1514,7 @@ int init_access_control(const char *argument, void **context, struct ddsi_domain #endif access_control->remote_permissions = access_control_table_new(); - OpenSSL_add_all_algorithms(); - OpenSSL_add_all_ciphers(); - OpenSSL_add_all_digests(); - ERR_load_BIO_strings(); - ERR_load_crypto_strings(); - + dds_openssl_init (); *context = access_control; return 0; } @@ -2473,9 +2460,5 @@ int finalize_access_control(void *context) ddsrt_mutex_destroy(&access_control->lock); ddsrt_free(access_control); } - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - REMOVE_THREAD_STATE(); - ERR_free_strings(); return 0; } diff --git a/src/security/builtin_plugins/access_control/src/access_control_objects.h b/src/security/builtin_plugins/access_control/src/access_control_objects.h index b1f033b..867bab9 100644 --- a/src/security/builtin_plugins/access_control/src/access_control_objects.h +++ b/src/security/builtin_plugins/access_control/src/access_control_objects.h @@ -12,10 +12,10 @@ #ifndef ACCESS_CONTROL_OBJECTS_H #define ACCESS_CONTROL_OBJECTS_H -#include #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/types.h" #include "dds/security/dds_security_api.h" +#include "dds/security/openssl_support.h" #define ACCESS_CONTROL_OBJECT(o) ((AccessControlObject *)(o)) #define ACCESS_CONTROL_OBJECT_HANDLE(o) ((o) ? ACCESS_CONTROL_OBJECT(o)->handle : DDS_SECURITY_HANDLE_NIL) diff --git a/src/security/builtin_plugins/access_control/src/access_control_parser.c b/src/security/builtin_plugins/access_control/src/access_control_parser.c index efd72ef..2d7d3af 100644 --- a/src/security/builtin_plugins/access_control/src/access_control_parser.c +++ b/src/security/builtin_plugins/access_control/src/access_control_parser.c @@ -11,11 +11,7 @@ */ #include #include -#include -#include -#include -#include -#include + #include "dds/ddsrt/heap.h" #include "dds/ddsrt/misc.h" #include "dds/ddsrt/string.h" diff --git a/src/security/builtin_plugins/access_control/src/access_control_utils.c b/src/security/builtin_plugins/access_control/src/access_control_utils.c index ca80d77..c30dbf2 100644 --- a/src/security/builtin_plugins/access_control/src/access_control_utils.c +++ b/src/security/builtin_plugins/access_control/src/access_control_utils.c @@ -14,11 +14,7 @@ #include #include #include -#include -#include -#include -#include -#include + #include "dds/ddsrt/heap.h" #include "dds/ddsrt/misc.h" #include "dds/ddsrt/string.h" @@ -26,6 +22,7 @@ #include "dds/ddsrt/types.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_utils.h" +#include "dds/security/openssl_support.h" #include "access_control_utils.h" #define SEQ_ERR -1 diff --git a/src/security/builtin_plugins/access_control/src/access_control_utils.h b/src/security/builtin_plugins/access_control/src/access_control_utils.h index 008ab21..d786416 100644 --- a/src/security/builtin_plugins/access_control/src/access_control_utils.h +++ b/src/security/builtin_plugins/access_control/src/access_control_utils.h @@ -12,10 +12,10 @@ #ifndef ACCESS_CONTROL_UTILS_H #define ACCESS_CONTROL_UTILS_H -#include #include "dds/ddsrt/types.h" -#include "dds/security/dds_security_api.h" #include "dds/security/export.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/openssl_support.h" #define DDS_ACCESS_CONTROL_PLUGIN_CONTEXT "Access Control" diff --git a/src/security/builtin_plugins/authentication/CMakeLists.txt b/src/security/builtin_plugins/authentication/CMakeLists.txt index c6716e7..880b832 100644 --- a/src/security/builtin_plugins/authentication/CMakeLists.txt +++ b/src/security/builtin_plugins/authentication/CMakeLists.txt @@ -31,6 +31,7 @@ generate_export_header( EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/dds/security/export.h" ) +target_link_libraries(dds_security_auth PRIVATE security_openssl) target_link_libraries(dds_security_auth PUBLIC ddsc) target_link_libraries(dds_security_auth PUBLIC OpenSSL::SSL) if(CMAKE_GENERATOR MATCHES "Visual Studio") @@ -41,6 +42,7 @@ target_include_directories(dds_security_auth PUBLIC "$>" "$>" + "$>" "$>" "$" "$" diff --git a/src/security/builtin_plugins/authentication/src/auth_utils.c b/src/security/builtin_plugins/authentication/src/auth_utils.c index e79a951..1eea973 100644 --- a/src/security/builtin_plugins/authentication/src/auth_utils.c +++ b/src/security/builtin_plugins/authentication/src/auth_utils.c @@ -12,24 +12,7 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if OPENSSL_VERSION_NUMBER >= 0x1000200fL -#define AUTH_INCLUDE_EC -#include -#if OPENSSL_VERSION_NUMBER >= 0x10100000L -#define AUTH_INCLUDE_DH_ACCESSORS -#endif -#else -#error "OpenSSL version is not supported" -#endif + #include "dds/ddsrt/time.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/filesystem.h" @@ -40,17 +23,9 @@ #include "dds/ddsrt/io.h" #include "dds/security/dds_security_api_defs.h" #include "dds/security/core/dds_security_utils.h" +#include "dds/security/openssl_support.h" #include "auth_utils.h" -/* There is a problem when compiling on windows w.r.t. X509_NAME. - * The windows api already defines the type X509_NAME which - * conficts with some openssl versions. The workaround is to - * undef the openssl X509_NAME - */ -#ifdef _WIN32 -#undef X509_NAME -#endif - #define MAX_TRUSTED_CA 100 char *get_openssl_error_message(void) @@ -151,8 +126,10 @@ static DDS_Security_ValidationResult_t check_key_type_and_size(EVP_PKEY *key, in } if (isPrivate) { - RSA *rsaKey = EVP_PKEY_get0_RSA(key); - if (rsaKey && RSA_check_key(rsaKey) != 1) + RSA *rsaKey = EVP_PKEY_get1_RSA(key); + const bool fail = (rsaKey && RSA_check_key(rsaKey) != 1); + RSA_free(rsaKey); + if (fail) { DDS_Security_Exception_set_with_openssl_error(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "RSA key not correct : "); return DDS_SECURITY_VALIDATION_FAILED; @@ -166,8 +143,10 @@ static DDS_Security_ValidationResult_t check_key_type_and_size(EVP_PKEY *key, in DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "EC %s has unsupported key size (%d)", sub, EVP_PKEY_bits(key)); return DDS_SECURITY_VALIDATION_FAILED; } - EC_KEY *ecKey = EVP_PKEY_get0_EC_KEY(key); - if (ecKey && EC_KEY_check_key(ecKey) != 1) + EC_KEY *ecKey = EVP_PKEY_get1_EC_KEY(key); + const bool fail = (ecKey && EC_KEY_check_key(ecKey) != 1); + EC_KEY_free(ecKey); + if (fail) { DDS_Security_Exception_set(ex, DDS_AUTH_PLUGIN_CONTEXT, DDS_SECURITY_ERR_UNDEFINED_CODE, DDS_SECURITY_VALIDATION_FAILED, "EC key not correct : "); return DDS_SECURITY_VALIDATION_FAILED; diff --git a/src/security/builtin_plugins/authentication/src/auth_utils.h b/src/security/builtin_plugins/authentication/src/auth_utils.h index 52ca1f7..31eb5d9 100644 --- a/src/security/builtin_plugins/authentication/src/auth_utils.h +++ b/src/security/builtin_plugins/authentication/src/auth_utils.h @@ -13,6 +13,13 @@ #ifndef AUTH_UTILS_H #define AUTH_UTILS_H +#ifdef _WIN32 +/* supposedly WinSock2 must be included before openssl 1.0.2 headers otherwise winsock will be used */ +#include +#endif +#include +#include + #include "dds/security/dds_security_api.h" #include "dds/ddsrt/time.h" diff --git a/src/security/builtin_plugins/authentication/src/authentication.c b/src/security/builtin_plugins/authentication/src/authentication.c index f17ae41..20f2c2c 100644 --- a/src/security/builtin_plugins/authentication/src/authentication.c +++ b/src/security/builtin_plugins/authentication/src/authentication.c @@ -13,28 +13,6 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#if OPENSLL_VERSION_NUMBER >= 0x10002000L -#define AUTH_INCLUDE_EC -#include -#endif -#include - -/* There is a problem when compiling on windows w.r.t. X509_NAME. - * The windows api already defines the type X509_NAME which - * conficts with some openssl versions. The workaround is to - * undef the openssl X509_NAME - */ -#ifdef _WIN32 -#undef X509_NAME -#endif #include "dds/ddsrt/heap.h" #include "dds/ddsrt/atomics.h" @@ -43,13 +21,13 @@ #include "dds/ddsrt/hopscotch.h" #include "dds/ddsi/ddsi_domaingv.h" #include "dds/security/dds_security_api.h" +#include "dds/security/dds_security_api_types.h" #include "dds/security/core/dds_security_timed_cb.h" #include "dds/security/core/dds_security_utils.h" -#include "dds/security/dds_security_api.h" -#include "dds/security/dds_security_api_types.h" #include "dds/security/core/shared_secret.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/dds_security_serialize.h" +#include "dds/security/openssl_support.h" #include "auth_utils.h" #include "authentication.h" @@ -57,14 +35,6 @@ #define EVP_PKEY_id(k) ((k)->type) #endif -#if OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10100000L -#define REMOVE_THREAD_STATE() ERR_remove_thread_state(NULL); -#elif OPENSSL_VERSION_NUMBER < 0x10000000L -#define REMOVE_THREAD_STATE() ERR_remove_state(0); -#else -#define REMOVE_THREAD_STATE() -#endif - #define HANDSHAKE_SIGNATURE_CONTENT_SIZE 6 #define ADJUSTED_GUID_PREFIX_FLAG 0x80 @@ -2276,12 +2246,7 @@ int32_t init_authentication(const char *argument, void **context, struct ddsi_do else authentication->include_optional = true; - OpenSSL_add_all_algorithms(); - OpenSSL_add_all_ciphers(); - OpenSSL_add_all_digests(); - ERR_load_BIO_strings(); - ERR_load_crypto_strings(); - + dds_openssl_init (); *context = authentication; return 0; } @@ -2308,11 +2273,5 @@ int32_t finalize_authentication(void *instance) ddsrt_mutex_destroy(&authentication->lock); ddsrt_free((dds_security_authentication_impl *)instance); } - - RAND_cleanup(); - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - REMOVE_THREAD_STATE(); - ERR_free_strings(); return 0; } diff --git a/src/security/builtin_plugins/cryptographic/CMakeLists.txt b/src/security/builtin_plugins/cryptographic/CMakeLists.txt index 180e7f3..7fac1df 100644 --- a/src/security/builtin_plugins/cryptographic/CMakeLists.txt +++ b/src/security/builtin_plugins/cryptographic/CMakeLists.txt @@ -29,6 +29,7 @@ generate_export_header( EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/dds/security/export.h" ) +target_link_libraries(dds_security_crypto PRIVATE security_openssl) target_link_libraries(dds_security_crypto PUBLIC ddsc) target_link_libraries(dds_security_crypto PUBLIC OpenSSL::SSL) if(CMAKE_GENERATOR MATCHES "Visual Studio") @@ -40,6 +41,7 @@ target_include_directories(dds_security_crypto PUBLIC "$>" "$>" + "$>" "$>" "$" "$" diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_cipher.c b/src/security/builtin_plugins/cryptographic/src/crypto_cipher.c index 80d79f3..a870699 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_cipher.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_cipher.c @@ -10,10 +10,10 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include -#include -#include + #include "dds/ddsrt/heap.h" #include "dds/ddsrt/types.h" +#include "dds/security/openssl_support.h" #include "crypto_defs.h" #include "crypto_utils.h" #include "crypto_cipher.h" diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c index 1ce7e49..7a04865 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_key_factory.c @@ -11,11 +11,7 @@ */ #include #include -#include -#include -#include -#include -#include + #include "dds/ddsrt/atomics.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/sync.h" @@ -25,6 +21,7 @@ #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "crypto_defs.h" #include "crypto_utils.h" #include "crypto_cipher.h" diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_transform.c b/src/security/builtin_plugins/cryptographic/src/crypto_transform.c index 1fd32b9..58b1da3 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_transform.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_transform.c @@ -12,14 +12,14 @@ #include #include #include -#include -#include + #include "dds/ddsrt/bswap.h" #include "dds/ddsrt/endian.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/types.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_utils.h" +#include "dds/security/openssl_support.h" #include "cryptography.h" #include "crypto_cipher.h" #include "crypto_defs.h" @@ -34,14 +34,6 @@ #define INFO_SRC_HDR_SIZE 8 #define RTPS_HEADER_SIZE 20 -#if OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10100000L -#define REMOVE_THREAD_STATE() ERR_remove_thread_state(NULL); -#elif OPENSSL_VERSION_NUMBER < 0x10000000L -#define REMOVE_THREAD_STATE() ERR_remove_state(0); -#else -#define REMOVE_THREAD_STATE() -#endif - struct submsg_header { unsigned char id; @@ -2444,23 +2436,12 @@ dds_security_crypto_transform__alloc( instance->base.decode_datareader_submessage = &decode_datareader_submessage; instance->base.decode_serialized_payload = &decode_serialized_payload; - OpenSSL_add_all_algorithms(); - OpenSSL_add_all_ciphers(); - OpenSSL_add_all_digests(); - ERR_load_BIO_strings(); - ERR_load_crypto_strings(); - + dds_openssl_init (); return (dds_security_crypto_transform *)instance; } void dds_security_crypto_transform__dealloc( dds_security_crypto_transform *instance) { - RAND_cleanup(); - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - REMOVE_THREAD_STATE(); - ERR_free_strings(); - ddsrt_free((dds_security_crypto_transform_impl *)instance); } diff --git a/src/security/builtin_plugins/cryptographic/src/crypto_utils.c b/src/security/builtin_plugins/cryptographic/src/crypto_utils.c index 12ca32e..075a8ef 100644 --- a/src/security/builtin_plugins/cryptographic/src/crypto_utils.c +++ b/src/security/builtin_plugins/cryptographic/src/crypto_utils.c @@ -11,16 +11,14 @@ */ #include #include -#include -#include -#include -#include + #include "dds/ddsrt/bswap.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/types.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_utils.h" +#include "dds/security/openssl_support.h" #include "crypto_defs.h" #include "crypto_utils.h" diff --git a/src/security/builtin_plugins/tests/CMakeLists.txt b/src/security/builtin_plugins/tests/CMakeLists.txt index 60a9704..6f26a68 100644 --- a/src/security/builtin_plugins/tests/CMakeLists.txt +++ b/src/security/builtin_plugins/tests/CMakeLists.txt @@ -63,30 +63,23 @@ add_cunit_executable(cunit_security_plugins ${security_auth_test_sources} ${secu target_include_directories( cunit_security_plugins PRIVATE + "$" + "$" "$" "$>" "$>" + "$>" "$>" "$" "$" ) target_link_libraries(cunit_security_plugins PRIVATE ddsc security_api dds_security_ac dds_security_crypto) +target_link_libraries(cunit_security_plugins PRIVATE security_openssl) target_link_libraries(cunit_security_plugins PRIVATE OpenSSL::SSL) if(CMAKE_GENERATOR MATCHES "Visual Studio") set_target_properties(cunit_security_plugins PROPERTIES LINK_FLAGS "/ignore:4099") endif() -target_include_directories( - cunit_security_plugins PRIVATE - "$" - "$" - "$>" - "$>" - "$>" - "$" - "$" -) - set(CUnit_builtin_plugins_tests_dir "${CMAKE_CURRENT_LIST_DIR}") set(CUnit_build_dir "${CMAKE_CURRENT_BINARY_DIR}") configure_file("config_env.h.in" "config_env.h") diff --git a/src/security/builtin_plugins/tests/common/src/crypto_helper.c b/src/security/builtin_plugins/tests/common/src/crypto_helper.c index 8497f80..824918b 100644 --- a/src/security/builtin_plugins/tests/common/src/crypto_helper.c +++ b/src/security/builtin_plugins/tests/common/src/crypto_helper.c @@ -10,10 +10,6 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include -#include -#include -#include -#include #include "dds/ddsrt/bswap.h" #include "dds/ddsrt/endian.h" @@ -25,6 +21,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "crypto_helper.h" diff --git a/src/security/builtin_plugins/tests/common/src/handshake_helper.c b/src/security/builtin_plugins/tests/common/src/handshake_helper.c index 2ff63bd..ae755f8 100644 --- a/src/security/builtin_plugins/tests/common/src/handshake_helper.c +++ b/src/security/builtin_plugins/tests/common/src/handshake_helper.c @@ -9,31 +9,21 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#include "handshake_helper.h" -#include "dds/security/core/dds_security_serialize.h" -#include "dds/ddsrt/string.h" -#include "dds/ddsrt/heap.h" #include #include +#include + +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/heap.h" #include "dds/ddsrt/environ.h" -#include "CUnit/CUnit.h" -#include "CUnit/Test.h" -#include "assert.h" #include "dds/ddsrt/misc.h" #include "dds/security/core/shared_secret.h" - -#if OPENSSL_VERSION_NUMBER >= 0x1000200fL -#define AUTH_INCLUDE_EC -#include -#include - -#if OPENSSL_VERSION_NUMBER >= 0x10100000L -#define AUTH_INCLUDE_DH_ACCESSORS -#endif -#else -#error "version not found" -#endif - +#include "dds/security/openssl_support.h" +#include "dds/security/core/dds_security_serialize.h" +#include "dds/security/core/dds_security_utils.h" +#include "CUnit/CUnit.h" +#include "CUnit/Test.h" +#include "handshake_helper.h" const BIGNUM * dh_get_public_key( diff --git a/src/security/builtin_plugins/tests/common/src/handshake_helper.h b/src/security/builtin_plugins/tests/common/src/handshake_helper.h index ac3ec24..b0e3df2 100644 --- a/src/security/builtin_plugins/tests/common/src/handshake_helper.h +++ b/src/security/builtin_plugins/tests/common/src/handshake_helper.h @@ -15,15 +15,7 @@ #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_serialize.h" - -#include -#include -#include -#include -#include -#include -#include -#include +#include "dds/security/openssl_support.h" const BIGNUM * dh_get_public_key( diff --git a/src/security/builtin_plugins/tests/create_local_datareader_crypto_tokens/src/create_local_datareader_crypto_tokens_utests.c b/src/security/builtin_plugins/tests/create_local_datareader_crypto_tokens/src/create_local_datareader_crypto_tokens_utests.c index be6a188..014b3e2 100644 --- a/src/security/builtin_plugins/tests/create_local_datareader_crypto_tokens/src/create_local_datareader_crypto_tokens_utests.c +++ b/src/security/builtin_plugins/tests/create_local_datareader_crypto_tokens/src/create_local_datareader_crypto_tokens_utests.c @@ -9,11 +9,6 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#include -#include -#include -#include - #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/types.h" @@ -22,6 +17,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/create_local_datawriter_crypto_tokens/src/create_local_datawriter_crypto_tokens_utests.c b/src/security/builtin_plugins/tests/create_local_datawriter_crypto_tokens/src/create_local_datawriter_crypto_tokens_utests.c index 0913528..e29ab77 100644 --- a/src/security/builtin_plugins/tests/create_local_datawriter_crypto_tokens/src/create_local_datawriter_crypto_tokens_utests.c +++ b/src/security/builtin_plugins/tests/create_local_datawriter_crypto_tokens/src/create_local_datawriter_crypto_tokens_utests.c @@ -9,11 +9,6 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#include -#include -#include -#include - #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/types.h" @@ -22,6 +17,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/create_local_participant_crypto_tokens/src/create_local_participant_crypto_tokens_utests.c b/src/security/builtin_plugins/tests/create_local_participant_crypto_tokens/src/create_local_participant_crypto_tokens_utests.c index d568d58..f06138f 100644 --- a/src/security/builtin_plugins/tests/create_local_participant_crypto_tokens/src/create_local_participant_crypto_tokens_utests.c +++ b/src/security/builtin_plugins/tests/create_local_participant_crypto_tokens/src/create_local_participant_crypto_tokens_utests.c @@ -9,11 +9,6 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#include -#include -#include -#include - #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/types.h" @@ -22,6 +17,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/decode_datareader_submessage/src/decode_datareader_submessage_utests.c b/src/security/builtin_plugins/tests/decode_datareader_submessage/src/decode_datareader_submessage_utests.c index 6af6f07..d3e1972 100644 --- a/src/security/builtin_plugins/tests/decode_datareader_submessage/src/decode_datareader_submessage_utests.c +++ b/src/security/builtin_plugins/tests/decode_datareader_submessage/src/decode_datareader_submessage_utests.c @@ -9,12 +9,6 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#include -#include -#include -#include -#include - #include "dds/ddsrt/bswap.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" @@ -24,6 +18,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/decode_datawriter_submessage/src/decode_datawriter_submessage_utests.c b/src/security/builtin_plugins/tests/decode_datawriter_submessage/src/decode_datawriter_submessage_utests.c index 4c297fc..15e1139 100644 --- a/src/security/builtin_plugins/tests/decode_datawriter_submessage/src/decode_datawriter_submessage_utests.c +++ b/src/security/builtin_plugins/tests/decode_datawriter_submessage/src/decode_datawriter_submessage_utests.c @@ -10,10 +10,6 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include -#include -#include -#include -#include #include "dds/ddsrt/bswap.h" #include "dds/ddsrt/heap.h" @@ -25,6 +21,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/decode_rtps_message/src/decode_rtps_message_utests.c b/src/security/builtin_plugins/tests/decode_rtps_message/src/decode_rtps_message_utests.c index 0923af3..778701b 100644 --- a/src/security/builtin_plugins/tests/decode_rtps_message/src/decode_rtps_message_utests.c +++ b/src/security/builtin_plugins/tests/decode_rtps_message/src/decode_rtps_message_utests.c @@ -10,10 +10,6 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include -#include -#include -#include -#include #include "dds/ddsrt/bswap.h" #include "dds/ddsrt/endian.h" @@ -25,6 +21,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/decode_serialized_payload/src/decode_serialized_payload_utests.c b/src/security/builtin_plugins/tests/decode_serialized_payload/src/decode_serialized_payload_utests.c index 05fcf46..85a3c2d 100644 --- a/src/security/builtin_plugins/tests/decode_serialized_payload/src/decode_serialized_payload_utests.c +++ b/src/security/builtin_plugins/tests/decode_serialized_payload/src/decode_serialized_payload_utests.c @@ -11,11 +11,6 @@ */ #include -#include -#include -#include -#include - #include "dds/ddsrt/bswap.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" @@ -25,6 +20,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/encode_datareader_submessage/src/encode_datareader_submessage_utests.c b/src/security/builtin_plugins/tests/encode_datareader_submessage/src/encode_datareader_submessage_utests.c index 2962aca..2924299 100644 --- a/src/security/builtin_plugins/tests/encode_datareader_submessage/src/encode_datareader_submessage_utests.c +++ b/src/security/builtin_plugins/tests/encode_datareader_submessage/src/encode_datareader_submessage_utests.c @@ -10,10 +10,6 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include -#include -#include -#include -#include #include "dds/ddsrt/bswap.h" #include "dds/ddsrt/endian.h" @@ -25,6 +21,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/encode_datawriter_submessage/src/encode_datawriter_submessage_utests.c b/src/security/builtin_plugins/tests/encode_datawriter_submessage/src/encode_datawriter_submessage_utests.c index 30a4ce4..389c27c 100644 --- a/src/security/builtin_plugins/tests/encode_datawriter_submessage/src/encode_datawriter_submessage_utests.c +++ b/src/security/builtin_plugins/tests/encode_datawriter_submessage/src/encode_datawriter_submessage_utests.c @@ -10,10 +10,6 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include -#include -#include -#include -#include #include "dds/ddsrt/bswap.h" #include "dds/ddsrt/endian.h" @@ -25,6 +21,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c b/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c index ea77f41..c6d6244 100644 --- a/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c +++ b/src/security/builtin_plugins/tests/encode_rtps_message/src/encode_rtps_message_utests.c @@ -10,10 +10,6 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include -#include -#include -#include -#include #include "dds/ddsrt/bswap.h" #include "dds/ddsrt/heap.h" @@ -24,6 +20,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/encode_serialized_payload/src/encode_serialized_payload_utests.c b/src/security/builtin_plugins/tests/encode_serialized_payload/src/encode_serialized_payload_utests.c index e4cd8ea..302972b 100644 --- a/src/security/builtin_plugins/tests/encode_serialized_payload/src/encode_serialized_payload_utests.c +++ b/src/security/builtin_plugins/tests/encode_serialized_payload/src/encode_serialized_payload_utests.c @@ -10,10 +10,6 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include -#include -#include -#include -#include #include "dds/ddsrt/bswap.h" #include "dds/ddsrt/heap.h" @@ -24,6 +20,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/get_authenticated_peer_credential_token/src/get_authenticated_peer_credential_token_utests.c b/src/security/builtin_plugins/tests/get_authenticated_peer_credential_token/src/get_authenticated_peer_credential_token_utests.c index 6ae66d7..28f88e2 100644 --- a/src/security/builtin_plugins/tests/get_authenticated_peer_credential_token/src/get_authenticated_peer_credential_token_utests.c +++ b/src/security/builtin_plugins/tests/get_authenticated_peer_credential_token/src/get_authenticated_peer_credential_token_utests.c @@ -10,32 +10,23 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -/* CUnit includes. */ - -#include "CUnit/CUnit.h" -#include "CUnit/Test.h" -#include "assert.h" -/* Test helper includes. */ -#include "common/src/loader.h" -#include "common/src/handshake_helper.h" - -#include "dds/security/dds_security_api.h" -#include -#include -#include -#include +#include +#include +#include #include "dds/ddsrt/string.h" #include "dds/ddsrt/heap.h" -#include -#include #include "dds/ddsrt/environ.h" - #include "dds/ddsrt/bswap.h" #include "dds/ddsrt/misc.h" -#include "dds/security/core/dds_security_serialize.h" #include "dds/security/dds_security_api.h" +#include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" +#include "dds/security/openssl_support.h" +#include "CUnit/CUnit.h" +#include "CUnit/Test.h" +#include "common/src/loader.h" +#include "common/src/handshake_helper.h" #define HANDSHAKE_SIGNATURE_SIZE 6 @@ -884,6 +875,7 @@ release_remote_identities(void) CU_Init(ddssec_builtin_get_authenticated_peer_credential) { int result = 0; + dds_openssl_init (); /* Only need the authentication plugin. */ g_plugins = load_plugins(NULL /* Access Control */, diff --git a/src/security/builtin_plugins/tests/get_permissions_credential_token/src/get_permissions_credential_token_utests.c b/src/security/builtin_plugins/tests/get_permissions_credential_token/src/get_permissions_credential_token_utests.c index bed337f..0a7c2b8 100644 --- a/src/security/builtin_plugins/tests/get_permissions_credential_token/src/get_permissions_credential_token_utests.c +++ b/src/security/builtin_plugins/tests/get_permissions_credential_token/src/get_permissions_credential_token_utests.c @@ -11,10 +11,6 @@ */ #include #include -#include -#include -#include -#include #include "dds/ddsrt/environ.h" #include "dds/ddsrt/heap.h" @@ -23,6 +19,7 @@ #include "dds/ddsrt/types.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_utils.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/get_permissions_token/src/get_permissions_token_utests.c b/src/security/builtin_plugins/tests/get_permissions_token/src/get_permissions_token_utests.c index ca4f708..5d39735 100644 --- a/src/security/builtin_plugins/tests/get_permissions_token/src/get_permissions_token_utests.c +++ b/src/security/builtin_plugins/tests/get_permissions_token/src/get_permissions_token_utests.c @@ -10,10 +10,6 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include -#include -#include -#include -#include #include "dds/ddsrt/environ.h" #include "dds/ddsrt/heap.h" @@ -22,6 +18,7 @@ #include "dds/ddsrt/types.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_utils.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/src/get_xxx_sec_attributes_utests.c b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/src/get_xxx_sec_attributes_utests.c index 04df354..2b0c47e 100644 --- a/src/security/builtin_plugins/tests/get_xxx_sec_attributes/src/get_xxx_sec_attributes_utests.c +++ b/src/security/builtin_plugins/tests/get_xxx_sec_attributes/src/get_xxx_sec_attributes_utests.c @@ -10,10 +10,6 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include -#include -#include -#include -#include #include "dds/ddsrt/environ.h" #include "dds/ddsrt/heap.h" @@ -22,6 +18,7 @@ #include "dds/ddsrt/types.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_utils.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/listeners_access_control/src/listeners_access_control_utests.c b/src/security/builtin_plugins/tests/listeners_access_control/src/listeners_access_control_utests.c index bd7eab6..5cc898a 100644 --- a/src/security/builtin_plugins/tests/listeners_access_control/src/listeners_access_control_utests.c +++ b/src/security/builtin_plugins/tests/listeners_access_control/src/listeners_access_control_utests.c @@ -10,12 +10,6 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include -#include -#include -#include -#include -#include -#include #include "dds/ddsrt/environ.h" #include "dds/ddsrt/heap.h" @@ -25,19 +19,12 @@ #include "dds/ddsrt/types.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_utils.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" #include "config_env.h" -#if OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10100000L -#define REMOVE_THREAD_STATE() ERR_remove_thread_state(NULL); -#elif OPENSSL_VERSION_NUMBER < 0x10000000L -#define REMOVE_THREAD_STATE() ERR_remove_state(0); -#else -#define REMOVE_THREAD_STATE() -#endif - static const char *ACCESS_PERMISSIONS_TOKEN_ID = "DDS:Access:Permissions:1.0"; static const char *AUTH_PROTOCOL_CLASS_ID = "DDS:Auth:PKI-DH:1.0"; @@ -549,8 +536,7 @@ CU_Init(ddssec_builtin_listeners_access_control) } else { set_path_to_etc_dir(); set_path_build_dir(); - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); + dds_openssl_init (); } return res; @@ -560,11 +546,6 @@ CU_Clean(ddssec_builtin_listeners_access_control) { unload_plugins(plugins); ddsrt_free(g_path_to_etc_dir); - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - REMOVE_THREAD_STATE(); - ERR_free_strings(); - return 0; } diff --git a/src/security/builtin_plugins/tests/listeners_authentication/src/listeners_authentication_utests.c b/src/security/builtin_plugins/tests/listeners_authentication/src/listeners_authentication_utests.c index 7575837..fb27369 100644 --- a/src/security/builtin_plugins/tests/listeners_authentication/src/listeners_authentication_utests.c +++ b/src/security/builtin_plugins/tests/listeners_authentication/src/listeners_authentication_utests.c @@ -2,49 +2,23 @@ * @brief Unit tests for qos APIs * */ -/* CUnit includes. */ -#include "CUnit/CUnit.h" -#include "CUnit/Test.h" - #include -/* Test helper includes. */ -#include "common/src/loader.h" - -#include "config_env.h" - #include "dds/ddsrt/time.h" -#include "dds/security/dds_security_api.h" -#include "dds/security/dds_security_api_authentication.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/misc.h" #include "dds/ddsrt/endian.h" #include "dds/ddsrt/io.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/dds_security_api_authentication.h" #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#if OPENSSL_VERSION_NUMBER >= 0x1000200fL -#define AUTH_INCLUDE_EC -#include -#if OPENSSL_VERSION_NUMBER >= 0x10100000L -#define AUTH_INCLUDE_DH_ACCESSORS -#endif -#else -#error "version not found" -#endif - +#include "dds/security/openssl_support.h" +#include "CUnit/CUnit.h" +#include "CUnit/Test.h" +#include "common/src/loader.h" +#include "config_env.h" static const char * ACCESS_PERMISSIONS_TOKEN_ID = "DDS:Access:Permissions:1.0"; static const char * AUTH_PROTOCOL_CLASS_ID = "DDS:Auth:PKI-DH:1.0"; @@ -1119,6 +1093,7 @@ get_dh_public_key_ecdh( CU_Init(ddssec_builtin_listeners_auth) { int res = 0; + dds_openssl_init (); plugins = load_plugins(&access_control /* Access Control */, &auth /* Authentication */, @@ -1146,11 +1121,7 @@ CU_Init(ddssec_builtin_listeners_auth) res = -1; } - /* Openssl init */ - OpenSSL_add_all_algorithms(); - ERR_load_BIO_strings(); - ERR_load_crypto_strings(); - + dds_openssl_init (); return res; } @@ -1168,9 +1139,6 @@ CU_Clean(ddssec_builtin_listeners_auth) unload_plugins(plugins); ddsrt_free(path_to_etc_dir); - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - ERR_free_strings(); return 0; } diff --git a/src/security/builtin_plugins/tests/preprocess_secure_submsg/src/preprocess_secure_submsg_utests.c b/src/security/builtin_plugins/tests/preprocess_secure_submsg/src/preprocess_secure_submsg_utests.c index 62a6973..d8c5201 100644 --- a/src/security/builtin_plugins/tests/preprocess_secure_submsg/src/preprocess_secure_submsg_utests.c +++ b/src/security/builtin_plugins/tests/preprocess_secure_submsg/src/preprocess_secure_submsg_utests.c @@ -9,11 +9,6 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#include -#include -#include -#include - #include "dds/ddsrt/bswap.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" @@ -23,6 +18,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/process_handshake/src/process_handshake_utests.c b/src/security/builtin_plugins/tests/process_handshake/src/process_handshake_utests.c index dabd5a8..d342cfb 100644 --- a/src/security/builtin_plugins/tests/process_handshake/src/process_handshake_utests.c +++ b/src/security/builtin_plugins/tests/process_handshake/src/process_handshake_utests.c @@ -1,36 +1,20 @@ +#include +#include +#include - -/* CUnit includes. */ -#include "common/src/handshake_helper.h" - -/* Test helper includes. */ -#include "common/src/loader.h" - -/* Private header include */ -#include "dds/security/dds_security_api.h" -#include "dds/security/core/dds_security_serialize.h" -#include "dds/security/core/dds_security_utils.h" -#include "dds/security/dds_security_api.h" #include "dds/ddsrt/bswap.h" #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" -#include -#include #include "dds/ddsrt/environ.h" +#include "dds/security/dds_security_api.h" +#include "dds/security/core/dds_security_serialize.h" +#include "dds/security/core/dds_security_utils.h" +#include "dds/security/openssl_support.h" +#include "common/src/handshake_helper.h" +#include "common/src/loader.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" -#include "assert.h" - -#include -#include -#include -#include -#include - - -#include "dds/security/core/dds_security_serialize.h" -#include "dds/security/dds_security_api.h" -#include "dds/security/core/dds_security_utils.h" +#include "config_env.h" #define HANDSHAKE_SIGNATURE_SIZE 6 @@ -1003,6 +987,7 @@ release_remote_identities(void) CU_Init(ddssec_builtin_process_handshake) { int result = 0; + dds_openssl_init (); /* Only need the authentication plugin. */ plugins = load_plugins(NULL /* Access Control */, diff --git a/src/security/builtin_plugins/tests/register_local_datareader/src/register_local_datareader_utests.c b/src/security/builtin_plugins/tests/register_local_datareader/src/register_local_datareader_utests.c index 503ef14..9001047 100644 --- a/src/security/builtin_plugins/tests/register_local_datareader/src/register_local_datareader_utests.c +++ b/src/security/builtin_plugins/tests/register_local_datareader/src/register_local_datareader_utests.c @@ -11,11 +11,6 @@ */ #include -#include -#include -#include -#include - #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/types.h" @@ -24,6 +19,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/register_local_datawriter/src/register_local_datawriter_utests.c b/src/security/builtin_plugins/tests/register_local_datawriter/src/register_local_datawriter_utests.c index 4830f68..80486e5 100644 --- a/src/security/builtin_plugins/tests/register_local_datawriter/src/register_local_datawriter_utests.c +++ b/src/security/builtin_plugins/tests/register_local_datawriter/src/register_local_datawriter_utests.c @@ -11,11 +11,6 @@ */ #include -#include -#include -#include -#include - #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/types.h" @@ -24,6 +19,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/register_local_participant/src/register_local_participant_utests.c b/src/security/builtin_plugins/tests/register_local_participant/src/register_local_participant_utests.c index 1602d9a..c3f39fc 100644 --- a/src/security/builtin_plugins/tests/register_local_participant/src/register_local_participant_utests.c +++ b/src/security/builtin_plugins/tests/register_local_participant/src/register_local_participant_utests.c @@ -11,11 +11,6 @@ */ #include -#include -#include -#include -#include - #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/types.h" @@ -24,6 +19,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/register_matched_remote_datareader/src/register_matched_remote_datareader_utests.c b/src/security/builtin_plugins/tests/register_matched_remote_datareader/src/register_matched_remote_datareader_utests.c index 2f0eadb..1ed3591 100644 --- a/src/security/builtin_plugins/tests/register_matched_remote_datareader/src/register_matched_remote_datareader_utests.c +++ b/src/security/builtin_plugins/tests/register_matched_remote_datareader/src/register_matched_remote_datareader_utests.c @@ -11,11 +11,6 @@ */ #include -#include -#include -#include -#include - #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/types.h" @@ -24,6 +19,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/register_matched_remote_datawriter/src/register_matched_remote_datawriter_utests.c b/src/security/builtin_plugins/tests/register_matched_remote_datawriter/src/register_matched_remote_datawriter_utests.c index c9dc669..6e4ac1a 100644 --- a/src/security/builtin_plugins/tests/register_matched_remote_datawriter/src/register_matched_remote_datawriter_utests.c +++ b/src/security/builtin_plugins/tests/register_matched_remote_datawriter/src/register_matched_remote_datawriter_utests.c @@ -11,11 +11,6 @@ */ #include -#include -#include -#include -#include - #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/types.h" @@ -24,6 +19,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/register_matched_remote_participant/src/register_matched_remote_participant_utests.c b/src/security/builtin_plugins/tests/register_matched_remote_participant/src/register_matched_remote_participant_utests.c index 2402697..43b4c53 100644 --- a/src/security/builtin_plugins/tests/register_matched_remote_participant/src/register_matched_remote_participant_utests.c +++ b/src/security/builtin_plugins/tests/register_matched_remote_participant/src/register_matched_remote_participant_utests.c @@ -9,11 +9,6 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#include -#include -#include -#include - #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/types.h" @@ -22,6 +17,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/set_remote_datareader_crypto_tokens/src/set_remote_datareader_crypto_tokens_utests.c b/src/security/builtin_plugins/tests/set_remote_datareader_crypto_tokens/src/set_remote_datareader_crypto_tokens_utests.c index 68e3448..5cdb615 100644 --- a/src/security/builtin_plugins/tests/set_remote_datareader_crypto_tokens/src/set_remote_datareader_crypto_tokens_utests.c +++ b/src/security/builtin_plugins/tests/set_remote_datareader_crypto_tokens/src/set_remote_datareader_crypto_tokens_utests.c @@ -9,11 +9,6 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#include -#include -#include -#include - #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/types.h" @@ -22,6 +17,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/set_remote_datawriter_crypto_tokens/src/set_remote_datawriter_crypto_tokens_utests.c b/src/security/builtin_plugins/tests/set_remote_datawriter_crypto_tokens/src/set_remote_datawriter_crypto_tokens_utests.c index a223604..5816149 100644 --- a/src/security/builtin_plugins/tests/set_remote_datawriter_crypto_tokens/src/set_remote_datawriter_crypto_tokens_utests.c +++ b/src/security/builtin_plugins/tests/set_remote_datawriter_crypto_tokens/src/set_remote_datawriter_crypto_tokens_utests.c @@ -9,11 +9,6 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#include -#include -#include -#include - #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/types.h" @@ -22,6 +17,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/set_remote_participant_crypto_tokens/src/set_remote_participant_crypto_tokens_utests.c b/src/security/builtin_plugins/tests/set_remote_participant_crypto_tokens/src/set_remote_participant_crypto_tokens_utests.c index 433b8fc..ddaf325 100644 --- a/src/security/builtin_plugins/tests/set_remote_participant_crypto_tokens/src/set_remote_participant_crypto_tokens_utests.c +++ b/src/security/builtin_plugins/tests/set_remote_participant_crypto_tokens/src/set_remote_participant_crypto_tokens_utests.c @@ -9,11 +9,6 @@ * * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ -#include -#include -#include -#include - #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/types.h" @@ -22,6 +17,7 @@ #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/core/shared_secret.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/validate_begin_handshake_reply/src/validate_begin_handshake_reply_utests.c b/src/security/builtin_plugins/tests/validate_begin_handshake_reply/src/validate_begin_handshake_reply_utests.c index e8f5259..bd2021b 100644 --- a/src/security/builtin_plugins/tests/validate_begin_handshake_reply/src/validate_begin_handshake_reply_utests.c +++ b/src/security/builtin_plugins/tests/validate_begin_handshake_reply/src/validate_begin_handshake_reply_utests.c @@ -1,35 +1,19 @@ +#include +#include +#include - - - -/* CUnit includes. */ - - -/* Test helper includes. */ -#include "common/src/loader.h" -#include "config_env.h" - -/* Private header include */ -#include -#include -#include -#include -#include -#include - -#include "dds/security/dds_security_api.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/bswap.h" +#include "dds/ddsrt/environ.h" #include "dds/security/core/dds_security_serialize.h" #include "dds/security/core/dds_security_utils.h" #include "dds/security/dds_security_api.h" -#include "dds/ddsrt/heap.h" -#include "dds/ddsrt/string.h" -#include -#include -#include "dds/ddsrt/bswap.h" -#include "dds/ddsrt/environ.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" -#include "assert.h" +#include "common/src/loader.h" +#include "config_env.h" static const char * AUTH_PROTOCOL_CLASS_ID = "DDS:Auth:PKI-DH:1.0"; static const char * PERM_ACCESS_CLASS_ID = "DDS:Access:Permissions:1.0"; diff --git a/src/security/builtin_plugins/tests/validate_begin_handshake_request/src/validate_begin_handshake_request_utests.c b/src/security/builtin_plugins/tests/validate_begin_handshake_request/src/validate_begin_handshake_request_utests.c index 5137565..0c1b198 100644 --- a/src/security/builtin_plugins/tests/validate_begin_handshake_request/src/validate_begin_handshake_request_utests.c +++ b/src/security/builtin_plugins/tests/validate_begin_handshake_request/src/validate_begin_handshake_request_utests.c @@ -22,6 +22,10 @@ /* Private header include */ +#ifdef _WIN32 +/* supposedly WinSock2 must be included before openssl 1.0.2 headers otherwise winsock will be used */ +#include +#endif #include static const char * AUTH_PROTOCOL_CLASS_ID = "DDS:Auth:PKI-DH:1.0"; diff --git a/src/security/builtin_plugins/tests/validate_local_identity/src/validate_local_identity_utests.c b/src/security/builtin_plugins/tests/validate_local_identity/src/validate_local_identity_utests.c index 721e854..2d27668 100644 --- a/src/security/builtin_plugins/tests/validate_local_identity/src/validate_local_identity_utests.c +++ b/src/security/builtin_plugins/tests/validate_local_identity/src/validate_local_identity_utests.c @@ -16,7 +16,8 @@ #include "dds/security/dds_security_api.h" -#include +#include "dds/security/openssl_support.h" + #include #include #include diff --git a/src/security/builtin_plugins/tests/validate_local_permissions/src/validate_local_permissions_utests.c b/src/security/builtin_plugins/tests/validate_local_permissions/src/validate_local_permissions_utests.c index f0a4cb5..2db3d15 100644 --- a/src/security/builtin_plugins/tests/validate_local_permissions/src/validate_local_permissions_utests.c +++ b/src/security/builtin_plugins/tests/validate_local_permissions/src/validate_local_permissions_utests.c @@ -10,10 +10,6 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include -#include -#include -#include -#include #include "dds/ddsrt/environ.h" #include "dds/ddsrt/heap.h" @@ -22,6 +18,7 @@ #include "dds/ddsrt/types.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_utils.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/builtin_plugins/tests/validate_remote_permissions/src/validate_remote_permissions_utests.c b/src/security/builtin_plugins/tests/validate_remote_permissions/src/validate_remote_permissions_utests.c index 84c413f..700a38a 100644 --- a/src/security/builtin_plugins/tests/validate_remote_permissions/src/validate_remote_permissions_utests.c +++ b/src/security/builtin_plugins/tests/validate_remote_permissions/src/validate_remote_permissions_utests.c @@ -10,10 +10,6 @@ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause */ #include -#include -#include -#include -#include #include "dds/ddsrt/environ.h" #include "dds/ddsrt/heap.h" @@ -22,6 +18,7 @@ #include "dds/ddsrt/types.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_utils.h" +#include "dds/security/openssl_support.h" #include "CUnit/CUnit.h" #include "CUnit/Test.h" #include "common/src/loader.h" diff --git a/src/security/core/include/dds/security/core/dds_security_utils.h b/src/security/core/include/dds/security/core/dds_security_utils.h index 21ac8fc..e56a5f9 100644 --- a/src/security/core/include/dds/security/core/dds_security_utils.h +++ b/src/security/core/include/dds/security/core/dds_security_utils.h @@ -17,6 +17,7 @@ #include #include #include + #include "dds/export.h" #include "dds/ddsrt/strtol.h" #include "dds/ddsrt/time.h" @@ -280,17 +281,6 @@ DDS_Security_Exception_set( const char *fmt, ...); - -#ifdef DDSI_INCLUDE_SSL -DDS_EXPORT void -DDS_Security_Exception_set_with_openssl_error( - DDS_Security_SecurityException *ex, - const char *context, - int code, - int minor_code, - const char *fmt); -#endif - DDS_EXPORT void DDS_Security_Exception_reset( DDS_Security_SecurityException *ex); diff --git a/src/security/core/src/dds_security_utils.c b/src/security/core/src/dds_security_utils.c index 0d3742a..5bf7843 100644 --- a/src/security/core/src/dds_security_utils.c +++ b/src/security/core/src/dds_security_utils.c @@ -13,19 +13,14 @@ #include #include #include +#include #include + +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/misc.h" #include "dds/security/dds_security_api.h" #include "dds/security/core/dds_security_utils.h" #include "dds/ddsrt/heap.h" -#include "stdlib.h" -#include "stdarg.h" -#include "dds/ddsrt/string.h" -#include "dds/ddsrt/misc.h" - -#ifdef DDSI_INCLUDE_SSL -#include -#include -#endif DDS_Security_BinaryProperty_t * DDS_Security_BinaryProperty_alloc (void) @@ -805,40 +800,6 @@ void DDS_Security_Exception_set (DDS_Security_SecurityException *ex, const char va_end(args1); } -#ifdef DDSI_INCLUDE_SSL -DDS_EXPORT void -DDS_Security_Exception_set_with_openssl_error( - DDS_Security_SecurityException *ex, - const char *context, - int code, - int minor_code, - const char *error_area) -{ - BIO *bio; - assert(context); - assert(error_area); - assert(ex); - DDSRT_UNUSED_ARG(context); - - if ((bio = BIO_new(BIO_s_mem()))) { - ERR_print_errors(bio); - char *buf = NULL; - size_t len = (size_t)BIO_get_mem_data(bio, &buf); - size_t exception_msg_len = len + strlen(error_area) + 1; - char *str = ddsrt_malloc(exception_msg_len); - ddsrt_strlcpy(str, error_area, exception_msg_len); - memcpy(str + strlen(error_area), buf, len); - str[exception_msg_len - 1] = '\0'; - ex->message = str; - ex->code = code; - ex->minor_code = minor_code; - BIO_free(bio); - } else { - DDS_Security_Exception_set(ex, context, code, minor_code, "BIO_new failed"); - } -} -#endif - void DDS_Security_Exception_reset( DDS_Security_SecurityException *ex) diff --git a/src/security/core/tests/CMakeLists.txt b/src/security/core/tests/CMakeLists.txt index 19fc14a..a1aaa93 100644 --- a/src/security/core/tests/CMakeLists.txt +++ b/src/security/core/tests/CMakeLists.txt @@ -102,6 +102,12 @@ target_include_directories( "$" "$" ) +if(ENABLE_SSL) + target_include_directories( + cunit_security_core PRIVATE + "$>" + ) +endif() set(common_etc_dir "${CMAKE_CURRENT_SOURCE_DIR}/common/etc") set(plugin_wrapper_lib_dir "${CMAKE_CURRENT_BINARY_DIR}") @@ -111,5 +117,6 @@ target_link_libraries(cunit_security_core PRIVATE ddsc security_api SecurityCore if(ENABLE_SSL) target_link_libraries(cunit_security_core PRIVATE dds_security_auth dds_security_ac dds_security_crypto dds_security_access_control_wrapper dds_security_authentication_wrapper dds_security_cryptography_wrapper) target_link_libraries(cunit_security_core PRIVATE OpenSSL::SSL) + target_link_libraries(cunit_security_core PRIVATE security_openssl) endif() target_include_directories(cunit_security_core PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") diff --git a/src/security/core/tests/common/cert_utils.c b/src/security/core/tests/common/cert_utils.c index f2e7386..fbaf7a9 100644 --- a/src/security/core/tests/common/cert_utils.c +++ b/src/security/core/tests/common/cert_utils.c @@ -12,15 +12,10 @@ #include #include -#include -#include -#include -#include -#include -#include #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" +#include "dds/security/openssl_support.h" #include "CUnit/Test.h" #include "cert_utils.h" diff --git a/src/security/core/tests/common/security_config_test_utils.c b/src/security/core/tests/common/security_config_test_utils.c index ea8158b..bde2eee 100644 --- a/src/security/core/tests/common/security_config_test_utils.c +++ b/src/security/core/tests/common/security_config_test_utils.c @@ -12,12 +12,6 @@ #include #include -#include -#include -#include -#include -#include -#include #include "CUnit/Test.h" #include "dds/dds.h" @@ -26,6 +20,7 @@ #include "dds/ddsrt/heap.h" #include "dds/ddsrt/string.h" #include "dds/ddsrt/io.h" +#include "dds/security/openssl_support.h" #include "common/config_env.h" #include "common/test_utils.h" #include "security_config_test_utils.h" @@ -160,6 +155,8 @@ static char * get_xml_datetime(dds_time_t t, char * buf, size_t len) static char * smime_sign(char * ca_cert_path, char * ca_priv_key_path, const char * data) { + dds_openssl_init (); + // Read CA certificate BIO *ca_cert_bio = BIO_new (BIO_s_file ()); if (BIO_read_filename (ca_cert_bio, ca_cert_path) <= 0) diff --git a/src/security/openssl/CMakeLists.txt b/src/security/openssl/CMakeLists.txt new file mode 100644 index 0000000..ebcbfc9 --- /dev/null +++ b/src/security/openssl/CMakeLists.txt @@ -0,0 +1,21 @@ +# +# Copyright(c) 2020 ADLINK Technology Limited and others +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +# v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# + +add_library(security_openssl INTERFACE) + +target_sources(security_openssl INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/src/openssl_support.c") + +target_include_directories( + security_openssl INTERFACE + "$" +) diff --git a/src/security/openssl/include/dds/security/openssl_support.h b/src/security/openssl/include/dds/security/openssl_support.h new file mode 100644 index 0000000..a6cf7d8 --- /dev/null +++ b/src/security/openssl/include/dds/security/openssl_support.h @@ -0,0 +1,80 @@ +/* + * Copyright(c) 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ + +#ifndef DDS_OPENSSL_SUPPORT_H +#define DDS_OPENSSL_SUPPORT_H + +#include "dds/security/dds_security_api_types.h" + +/* There's OpenSSL 1.1.x and there's OpenSSL 1.0.2 and the difference is like + night and day: 1.1.0 deprecated all the initialization and cleanup routines + and so any library can link with OpenSSL and use it safely without breaking + the application code or some other library in the same process. + + OpenSSL 1.0.2h deprecated the cleanup functions such as EVP_cleanup because + calling the initialisation functions multiple times was survivable, but an + premature invocation of the cleanup functions deadly. It still has the per- + thread error state that one ought to clean up, but that firstly requires + keeping track of which threads make OpenSSL calls, and secondly we do + perform OpenSSL calls on the applications main-thread and so cleaning up + might interfere with the application code. + + Compatibility with 1.0.2 exists merely as a courtesy to those who insist on + using it with that problematic piece of code. We only initialise it, and we + don't clean up thread state. If Cyclone DDS is the only part of the process + that uses OpenSSL, it should be ok (just some some minor leaks at the end), + if the application code or another library also uses it, it'll probably be + fine too. */ + +#ifdef _WIN32 +/* WinSock2 must be included before openssl 1.0.2 headers otherwise winsock will be used */ +#include +#endif + +#include +#include +#include +#include +#include + +#if OPENSSL_VERSION_NUMBER >= 0x1000200fL +#define AUTH_INCLUDE_EC +#include +#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#define AUTH_INCLUDE_DH_ACCESSORS +#endif +#else +#error "OpenSSL version is not supported" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void dds_openssl_init (void); + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +/* 1.1.0 has it as a supported API. 1.0.2 has it in practice and since that has been + obsolete for ages, chances are that we can safely use it */ +struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result); +#endif + +void DDS_Security_Exception_set_with_openssl_error (DDS_Security_SecurityException *ex, const char *context, int code, int minor_code, const char *error_area); + +#endif diff --git a/src/security/openssl/src/openssl_support.c b/src/security/openssl/src/openssl_support.c new file mode 100644 index 0000000..a212439 --- /dev/null +++ b/src/security/openssl/src/openssl_support.c @@ -0,0 +1,127 @@ +/* + * Copyright(c) 2020 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/sync.h" +#include "dds/ddsrt/misc.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/threads.h" +#include "dds/ddsrt/atomics.h" +#include "dds/security/core/dds_security_utils.h" +#include "dds/security/openssl_support.h" + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +static unsigned long ssl_id (void) +{ + return (unsigned long) ddsrt_gettid (); +} + +typedef struct CRYPTO_dynlock_value { + ddsrt_mutex_t m_mutex; +} CRYPTO_dynlock_value; + +CRYPTO_dynlock_value *dds_openssl102_ssl_locks = NULL; + +static void ssl_dynlock_lock (int mode, CRYPTO_dynlock_value *lock, const char *file, int line) +{ + (void) file; + (void) line; + if (mode & CRYPTO_LOCK) + ddsrt_mutex_lock (&lock->m_mutex); + else + ddsrt_mutex_unlock (&lock->m_mutex); +} + +static void ssl_lock (int mode, int n, const char *file, int line) +{ + ssl_dynlock_lock (mode, &dds_openssl102_ssl_locks[n], file, line); +} + +static CRYPTO_dynlock_value *ssl_dynlock_create (const char *file, int line) +{ + (void) file; + (void) line; + CRYPTO_dynlock_value *val = ddsrt_malloc (sizeof (*val)); + ddsrt_mutex_init (&val->m_mutex); + return val; +} + +static void ssl_dynlock_destroy (CRYPTO_dynlock_value *lock, const char *file, int line) +{ + (void) file; + (void) line; + ddsrt_mutex_destroy (&lock->m_mutex); + ddsrt_free (lock); +} + +void dds_openssl_init (void) +{ + // This is terribly fragile and broken-by-design, but with OpenSSL sometimes + // linked dynamically and sometimes linked statically, with Windows and Unix + // in the mix, this appears to be the compromise that makes it work reliably + // enough ... + if (CRYPTO_get_id_callback () == 0) + { + CRYPTO_set_id_callback (ssl_id); + CRYPTO_set_locking_callback (ssl_lock); + CRYPTO_set_dynlock_create_callback (ssl_dynlock_create); + CRYPTO_set_dynlock_lock_callback (ssl_dynlock_lock); + CRYPTO_set_dynlock_destroy_callback (ssl_dynlock_destroy); + + if (dds_openssl102_ssl_locks == NULL) + { + const int locks = CRYPTO_num_locks (); + assert (locks >= 0); + dds_openssl102_ssl_locks = ddsrt_malloc (sizeof (CRYPTO_dynlock_value) * (size_t) locks); + for (int i = 0; i < locks; i++) + ddsrt_mutex_init (&dds_openssl102_ssl_locks[i].m_mutex); + } + + OpenSSL_add_all_algorithms (); + OpenSSL_add_all_ciphers (); + OpenSSL_add_all_digests (); + ERR_load_BIO_strings (); + ERR_load_crypto_strings (); + } +} +#else +void dds_openssl_init (void) +{ + // nothing needed for OpenSSL 1.1.0 and later +} +#endif + +void DDS_Security_Exception_set_with_openssl_error (DDS_Security_SecurityException *ex, const char *context, int code, int minor_code, const char *error_area) +{ + BIO *bio; + assert (context); + assert (error_area); + assert (ex); + DDSRT_UNUSED_ARG (context); + + if ((bio = BIO_new (BIO_s_mem ()))) { + ERR_print_errors (bio); + char *buf = NULL; + size_t len = (size_t) BIO_get_mem_data (bio, &buf); + size_t exception_msg_len = len + strlen (error_area) + 1; + char *str = ddsrt_malloc (exception_msg_len); + ddsrt_strlcpy (str, error_area, exception_msg_len); + memcpy (str + strlen (error_area), buf, len); + str[exception_msg_len - 1] = '\0'; + ex->message = str; + ex->code = code; + ex->minor_code = minor_code; + BIO_free (bio); + } else { + DDS_Security_Exception_set (ex, context, code, minor_code, "BIO_new failed"); + } +} From 7c7814e878ec5a4534d3ad210cfc65acda9cfa82 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Mon, 25 May 2020 10:46:24 +0200 Subject: [PATCH 237/238] Include OpenSSL 1.0.2 in CI Signed-off-by: Erik Boasson --- .travis.yml | 6 ++++-- conanfile102.txt | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 conanfile102.txt diff --git a/.travis.yml b/.travis.yml index b0032c7..65b4303 100644 --- a/.travis.yml +++ b/.travis.yml @@ -147,6 +147,8 @@ jobs: if: type = cron - <<: *linux_gcc8 env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ] + - <<: *linux_gcc8 + env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles", CONANFILE=conanfile102.txt ] - <<: *linux_gcc8 env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ] - <<: *linux_gcc8 @@ -167,7 +169,7 @@ jobs: - <<: *osx_xcode env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ] - <<: *windows_vs2017 - env: [ ARCH=x86, ASAN=none, BUILD_TYPE=Debug, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Visual Studio 15 2017" ] + env: [ ARCH=x86, ASAN=none, BUILD_TYPE=Debug, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Visual Studio 15 2017", CONANFILE=conanfile102.txt ] - <<: *windows_vs2017 env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Visual Studio 15 2017 Win64" ] - <<: *windows_vs2017 @@ -197,7 +199,7 @@ script: - INSTALLPREFIX="$(pwd)/install" - mkdir build - cd build - - conan install -b missing -s arch=${ARCH} -s build_type=${BUILD_TYPE} .. + - conan install -b missing -s arch=${ARCH} -s build_type=${BUILD_TYPE} ../${CONANFILE:-conanfile.txt} - which trang && BUILD_SCHEMA=1 || BUILD_SCHEMA=0 - cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${INSTALLPREFIX} diff --git a/conanfile102.txt b/conanfile102.txt new file mode 100644 index 0000000..64560b9 --- /dev/null +++ b/conanfile102.txt @@ -0,0 +1,6 @@ +[requires] +cunit/2.1-3@bincrafters/stable +OpenSSL/1.0.2@conan/stable + +[generators] +cmake From 62608242518b6e3cb0194a9c19f9ef41c55e823f Mon Sep 17 00:00:00 2001 From: Dennis Potman Date: Fri, 29 May 2020 13:31:16 +0200 Subject: [PATCH 238/238] Fix uninitialized use of relay_only Fix using the variable relay_only uninitialized in the function connect_proxy_writer_with_reader when security is disabled in the build configuration. Signed-off-by: Dennis Potman --- src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h | 1 + 1 file changed, 1 insertion(+) 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 6eeb9eb..bcf81ec 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h @@ -1290,6 +1290,7 @@ inline bool q_omg_reader_is_submessage_protected(UNUSED_ARG(const struct reader inline bool q_omg_security_check_remote_reader_permissions(UNUSED_ARG(const struct proxy_reader *prd), UNUSED_ARG(uint32_t domain_id), UNUSED_ARG(struct participant *pp), UNUSED_ARG(bool *relay_only)) { + *relay_only = false; return true; }