#include <stdlib.h>
#include <assert.h>
#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/ddsrt/string.h"
#include "dds/ddsi/ddsi_domaingv.h"
#include "dds/ddsi/ddsi_xqos.h"
#include "ddsi__misc.h"
#include "dds/security/dds_security_api.h"
#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:+,}"
"<Domain id=\"any\">"
" <Discovery>"
" <ExternalDomainId>0</ExternalDomainId>"
" <Tag>\\${CYCLONEDDS_PID}</Tag>"
" </Discovery>"
" <Security>"
" <Authentication>"
" <Library initFunction=\"${AUTH_INIT}\" finalizeFunction=\"${AUTH_FINI}\" path=\"" WRAPPERLIB_PATH("dds_security_authentication_wrapper") "\"/>"
" <IdentityCertificate>data:,"TEST_IDENTITY1_CERTIFICATE"</IdentityCertificate>"
" <PrivateKey>data:,"TEST_IDENTITY1_PRIVATE_KEY"</PrivateKey>"
" <IdentityCA>data:,"TEST_IDENTITY_CA1_CERTIFICATE"</IdentityCA>"
" </Authentication>"
" <AccessControl>"
" <Library finalizeFunction=\"finalize_access_control\" initFunction=\"init_access_control\"/>"
" <Governance>file:" COMMON_ETC_PATH("default_governance.p7s") "</Governance>"
" <PermissionsCA>file:" COMMON_ETC_PATH("default_permissions_ca.pem") "</PermissionsCA>"
" <Permissions>file:" COMMON_ETC_PATH("default_permissions.p7s") "</Permissions>"
" </AccessControl>"
" <Cryptographic>"
" <Library initFunction=\"${CRYPTO_INIT}\" finalizeFunction=\"${CRYPTO_FINI}\" path=\"" WRAPPERLIB_PATH("dds_security_cryptography_wrapper") "\"/>"
" </Cryptographic>"
" </Security>"
"</Domain>";
#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 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)
{
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 }
};
char *conf = ddsrt_expand_vars_sh (config, &expand_lookup_vars_env, config_vars);
int32_t unmatched = expand_lookup_unmatched (config_vars);
CU_ASSERT_EQ_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_GT_FATAL (g_participant1, 0);
g_participant2 = dds_create_participant (DDS_DOMAINID2, NULL, NULL);
CU_ASSERT_GT_FATAL (g_participant2, 0);
}
static void handshake_fini(void)
{
dds_return_t ret = dds_delete (g_domain1);
CU_ASSERT_EQ_FATAL (ret, DDS_RETCODE_OK);
ret = dds_delete (g_domain2);
CU_ASSERT_EQ_FATAL (ret, DDS_RETCODE_OK);
}
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 (DDS_DOMAINID1, false, NULL, &hs_list, &nhs, DDS_SECS(2));
CU_ASSERT_EQ_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_EQ_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 ();
}
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, 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));
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);
struct dds_security_cryptography_impl * crypto_context_pub = get_cryptography_context (g_participant1);
CU_ASSERT_NEQ_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_cryptography_context (g_participant2);
CU_ASSERT_NEQ_FATAL (crypto_context_sub, NULL);
struct ddsrt_circlist *sub_tokens = get_crypto_tokens (crypto_context_sub);
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_NEQ_FATAL (st, NULL);
}
ddsrt_circlist_remove (pub_tokens, list_elem);
ddsrt_free (token_data);
}
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 ();
}