diff options
author | Nick Mathewson <nickm@torproject.org> | 2018-09-07 15:03:32 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2018-09-07 15:03:32 -0400 |
commit | 9ca1af9a8757ee73cf4018263cb3ae2340ebaa9f (patch) | |
tree | c747d03a54dde4ad4defa2c4c129545aa31064b1 /src/test | |
parent | 13d0855a893a46a0f6dc06dc7d983ea321f7206a (diff) | |
parent | 3695ef6343fa1c05cd15a3ddf35c3fe6991ff2ad (diff) | |
download | tor-9ca1af9a8757ee73cf4018263cb3ae2340ebaa9f.tar.gz tor-9ca1af9a8757ee73cf4018263cb3ae2340ebaa9f.zip |
Merge remote-tracking branch 'dgoulet/ticket20700_035_03'
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/fuzz/fuzz_hsdescv3.c | 4 | ||||
-rw-r--r-- | src/test/hs_test_helpers.c | 43 | ||||
-rw-r--r-- | src/test/test_hs_cache.c | 20 | ||||
-rw-r--r-- | src/test/test_hs_client.c | 178 | ||||
-rw-r--r-- | src/test/test_hs_common.c | 6 | ||||
-rw-r--r-- | src/test/test_hs_descriptor.c | 262 | ||||
-rw-r--r-- | src/test/test_hs_service.c | 459 | ||||
-rw-r--r-- | src/test/testing_common.c | 4 |
8 files changed, 861 insertions, 115 deletions
diff --git a/src/test/fuzz/fuzz_hsdescv3.c b/src/test/fuzz/fuzz_hsdescv3.c index 4ec8db0a87..b332973b39 100644 --- a/src/test/fuzz/fuzz_hsdescv3.c +++ b/src/test/fuzz/fuzz_hsdescv3.c @@ -38,11 +38,13 @@ static size_t mock_decrypt_desc_layer(const hs_descriptor_t *desc, const uint8_t *encrypted_blob, size_t encrypted_blob_size, + const uint8_t *descriptor_cookie, int is_superencrypted_layer, char **decrypted_out) { (void)is_superencrypted_layer; (void)desc; + (void)descriptor_cookie; const size_t overhead = HS_DESC_ENCRYPTED_SALT_LEN + DIGEST256_LEN; if (encrypted_blob_size < overhead) return 0; @@ -84,7 +86,7 @@ fuzz_main(const uint8_t *data, size_t sz) char *fuzzing_data = tor_memdup_nulterm(data, sz); memset(subcredential, 'A', sizeof(subcredential)); - hs_desc_decode_descriptor(fuzzing_data, subcredential, &desc); + hs_desc_decode_descriptor(fuzzing_data, subcredential, NULL, &desc); if (desc) { log_debug(LD_GENERAL, "Decoding okay"); hs_descriptor_free(desc); diff --git a/src/test/hs_test_helpers.c b/src/test/hs_test_helpers.c index afe3eafa2f..4e13ba43a7 100644 --- a/src/test/hs_test_helpers.c +++ b/src/test/hs_test_helpers.c @@ -98,8 +98,11 @@ static hs_descriptor_t * hs_helper_build_hs_desc_impl(unsigned int no_ip, const ed25519_keypair_t *signing_kp) { + int ret; + int i; time_t now = approx_time(); ed25519_keypair_t blinded_kp; + curve25519_keypair_t auth_ephemeral_kp; hs_descriptor_t *descp = NULL, *desc = tor_malloc_zero(sizeof(*desc)); desc->plaintext_data.version = HS_DESC_SUPPORTED_FORMAT_VERSION_MAX; @@ -126,6 +129,20 @@ hs_helper_build_hs_desc_impl(unsigned int no_ip, hs_get_subcredential(&signing_kp->pubkey, &blinded_kp.pubkey, desc->subcredential); + /* Setup superencrypted data section. */ + ret = curve25519_keypair_generate(&auth_ephemeral_kp, 0); + tt_int_op(ret, ==, 0); + memcpy(&desc->superencrypted_data.auth_ephemeral_pubkey, + &auth_ephemeral_kp.pubkey, + sizeof(curve25519_public_key_t)); + + desc->superencrypted_data.clients = smartlist_new(); + for (i = 0; i < HS_DESC_AUTH_CLIENT_MULTIPLE; i++) { + hs_desc_authorized_client_t *desc_client = + hs_desc_build_fake_authorized_client(); + smartlist_add(desc->superencrypted_data.clients, desc_client); + } + /* Setup encrypted data section. */ desc->encrypted_data.create2_ntor = 1; desc->encrypted_data.intro_auth_types = smartlist_new(); @@ -207,6 +224,32 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1, * encrypted blob. As contrast to the decoding process where we populate a * descriptor object. */ + /* Superencrypted data section. */ + tt_mem_op(desc1->superencrypted_data.auth_ephemeral_pubkey.public_key, OP_EQ, + desc2->superencrypted_data.auth_ephemeral_pubkey.public_key, + CURVE25519_PUBKEY_LEN); + + /* Auth clients. */ + { + tt_assert(desc1->superencrypted_data.clients); + tt_assert(desc2->superencrypted_data.clients); + tt_int_op(smartlist_len(desc1->superencrypted_data.clients), ==, + smartlist_len(desc2->superencrypted_data.clients)); + for (int i=0; + i < smartlist_len(desc1->superencrypted_data.clients); + i++) { + hs_desc_authorized_client_t + *client1 = smartlist_get(desc1->superencrypted_data.clients, i), + *client2 = smartlist_get(desc2->superencrypted_data.clients, i); + tor_memeq(client1->client_id, client2->client_id, + sizeof(client1->client_id)); + tor_memeq(client1->iv, client2->iv, + sizeof(client1->iv)); + tor_memeq(client1->encrypted_cookie, client2->encrypted_cookie, + sizeof(client1->encrypted_cookie)); + } + } + /* Encrypted data section. */ tt_uint_op(desc1->encrypted_data.create2_ntor, ==, desc2->encrypted_data.create2_ntor); diff --git a/src/test/test_hs_cache.c b/src/test/test_hs_cache.c index c1a69af829..728bb4a2f5 100644 --- a/src/test/test_hs_cache.c +++ b/src/test/test_hs_cache.c @@ -64,7 +64,7 @@ test_directory(void *arg) tt_int_op(ret, OP_EQ, 0); desc1 = hs_helper_build_hs_desc_with_ip(&signing_kp1); tt_assert(desc1); - ret = hs_desc_encode_descriptor(desc1, &signing_kp1, &desc1_str); + ret = hs_desc_encode_descriptor(desc1, &signing_kp1, NULL, &desc1_str); tt_int_op(ret, OP_EQ, 0); /* Very first basic test, should be able to be stored, survive a @@ -102,7 +102,7 @@ test_directory(void *arg) desc_zero_lifetime->plaintext_data.lifetime_sec = 0; char *desc_zero_lifetime_str; ret = hs_desc_encode_descriptor(desc_zero_lifetime, &signing_kp_zero, - &desc_zero_lifetime_str); + NULL, &desc_zero_lifetime_str); tt_int_op(ret, OP_EQ, 0); ret = hs_cache_store_as_dir(desc1_str); @@ -153,7 +153,7 @@ test_directory(void *arg) tt_int_op(ret, OP_EQ, 1); /* Bump revision counter. */ desc1->plaintext_data.revision_counter++; - ret = hs_desc_encode_descriptor(desc1, &signing_kp1, &new_desc_str); + ret = hs_desc_encode_descriptor(desc1, &signing_kp1, NULL, &new_desc_str); tt_int_op(ret, OP_EQ, 0); ret = hs_cache_store_as_dir(new_desc_str); tt_int_op(ret, OP_EQ, 0); @@ -187,7 +187,7 @@ test_clean_as_dir(void *arg) tt_int_op(ret, OP_EQ, 0); desc1 = hs_helper_build_hs_desc_with_ip(&signing_kp1); tt_assert(desc1); - ret = hs_desc_encode_descriptor(desc1, &signing_kp1, &desc1_str); + ret = hs_desc_encode_descriptor(desc1, &signing_kp1, NULL, &desc1_str); tt_int_op(ret, OP_EQ, 0); ret = hs_cache_store_as_dir(desc1_str); tt_int_op(ret, OP_EQ, 0); @@ -301,7 +301,7 @@ test_upload_and_download_hs_desc(void *arg) published_desc = hs_helper_build_hs_desc_with_ip(&signing_kp); tt_assert(published_desc); retval = hs_desc_encode_descriptor(published_desc, &signing_kp, - &published_desc_str); + NULL, &published_desc_str); tt_int_op(retval, OP_EQ, 0); } @@ -365,7 +365,7 @@ test_hsdir_revision_counter_check(void *arg) published_desc = hs_helper_build_hs_desc_with_ip(&signing_kp); tt_assert(published_desc); retval = hs_desc_encode_descriptor(published_desc, &signing_kp, - &published_desc_str); + NULL, &published_desc_str); tt_int_op(retval, OP_EQ, 0); } @@ -390,7 +390,7 @@ test_hsdir_revision_counter_check(void *arg) received_desc_str = helper_fetch_desc_from_hsdir(blinded_key); retval = hs_desc_decode_descriptor(received_desc_str, - subcredential, &received_desc); + subcredential, NULL, &received_desc); tt_int_op(retval, OP_EQ, 0); tt_assert(received_desc); @@ -407,7 +407,7 @@ test_hsdir_revision_counter_check(void *arg) published_desc->plaintext_data.revision_counter = 1313; tor_free(published_desc_str); retval = hs_desc_encode_descriptor(published_desc, &signing_kp, - &published_desc_str); + NULL, &published_desc_str); tt_int_op(retval, OP_EQ, 0); retval = handle_post_hs_descriptor("/tor/hs/3/publish",published_desc_str); @@ -423,7 +423,7 @@ test_hsdir_revision_counter_check(void *arg) received_desc_str = helper_fetch_desc_from_hsdir(blinded_key); retval = hs_desc_decode_descriptor(received_desc_str, - subcredential, &received_desc); + subcredential, NULL, &received_desc); tt_int_op(retval, OP_EQ, 0); tt_assert(received_desc); @@ -482,7 +482,7 @@ test_client_cache(void *arg) published_desc = hs_helper_build_hs_desc_with_ip(&signing_kp); tt_assert(published_desc); retval = hs_desc_encode_descriptor(published_desc, &signing_kp, - &published_desc_str); + NULL, &published_desc_str); tt_int_op(retval, OP_EQ, 0); memcpy(wanted_subcredential, published_desc->subcredential, DIGEST256_LEN); tt_assert(!tor_mem_is_zero((char*)wanted_subcredential, DIGEST256_LEN)); diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c index 7fcc1db195..c91e82ed4a 100644 --- a/src/test/test_hs_client.c +++ b/src/test/test_hs_client.c @@ -6,6 +6,7 @@ * \brief Test prop224 HS client functionality. */ +#define CONFIG_PRIVATE #define CRYPTO_PRIVATE #define MAIN_PRIVATE #define HS_CLIENT_PRIVATE @@ -32,6 +33,7 @@ #include "feature/hs/hs_circuit.h" #include "feature/hs/hs_circuitmap.h" #include "feature/hs/hs_client.h" +#include "feature/hs/hs_config.h" #include "feature/hs/hs_ident.h" #include "feature/hs/hs_cache.h" #include "core/or/circuitlist.h" @@ -73,6 +75,20 @@ mock_networkstatus_get_live_consensus(time_t now) return &mock_ns; } +static int +helper_config_client(const char *conf, int validate_only) +{ + int ret = 0; + or_options_t *options = NULL; + tt_assert(conf); + options = helper_parse_options(conf); + tt_assert(options); + ret = hs_config_client_auth_all(options, validate_only); + done: + or_options_free(options); + return ret; +} + /* Test helper function: Setup a circuit and a stream with the same hidden * service destination, and put them in <b>circ_out</b> and * <b>conn_out</b>. Make the stream wait for circuits to be established to the @@ -366,7 +382,7 @@ test_client_pick_intro(void *arg) { char *encoded = NULL; desc = hs_helper_build_hs_desc_with_ip(&service_kp); - ret = hs_desc_encode_descriptor(desc, &service_kp, &encoded); + ret = hs_desc_encode_descriptor(desc, &service_kp, NULL, &encoded); tt_int_op(ret, OP_EQ, 0); tt_assert(encoded); @@ -601,6 +617,160 @@ test_descriptor_fetch(void *arg) hs_free_all(); } +static void +test_auth_key_filename_is_valid(void *arg) +{ + (void) arg; + + /* Valid file name. */ + tt_assert(auth_key_filename_is_valid("a.auth_private")); + /* Valid file name with special character. */ + tt_assert(auth_key_filename_is_valid("a-.auth_private")); + /* Invalid extension. */ + tt_assert(!auth_key_filename_is_valid("a.ath_private")); + /* Nothing before the extension. */ + tt_assert(!auth_key_filename_is_valid(".auth_private")); + + done: + ; +} + +static void +test_parse_auth_file_content(void *arg) +{ + hs_client_service_authorization_t *auth = NULL; + + (void) arg; + + /* Valid authorized client. */ + auth = parse_auth_file_content( + "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad:descriptor:" + "x25519:zdsyvn2jq534ugyiuzgjy4267jbtzcjbsgedhshzx5mforyxtryq"); + tt_assert(auth); + + /* Wrong number of fields. */ + tt_assert(!parse_auth_file_content("a:b")); + /* Wrong auth type. */ + tt_assert(!parse_auth_file_content( + "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad:x:" + "x25519:zdsyvn2jq534ugyiuzgjy4267jbtzcjbsgedhshzx5mforyxtryq")); + /* Wrong key type. */ + tt_assert(!parse_auth_file_content( + "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad:descriptor:" + "x:zdsyvn2jq534ugyiuzgjy4267jbtzcjbsgedhshzx5mforyxtryq")); + /* Some malformed string. */ + tt_assert(!parse_auth_file_content("xx:descriptor:x25519:aa==")); + /* Bigger key than it should be */ + tt_assert(!parse_auth_file_content("xx:descriptor:x25519:" + "vjqea4jbhwwc4hto7ekyvqfbeodghbaq6nxi45hz4wr3qvhqv3yqa")); + done: + tor_free(auth); +} + +static char * +mock_read_file_to_str(const char *filename, int flags, struct stat *stat_out) +{ + char *ret = NULL; + + (void) flags; + (void) stat_out; + + if (!strcmp(filename, get_fname("auth_keys" PATH_SEPARATOR + "client1.auth_private"))) { + ret = tor_strdup( + "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad:descriptor:" + "x25519:zdsyvn2jq534ugyiuzgjy4267jbtzcjbsgedhshzx5mforyxtryq"); + goto done; + } + + if (!strcmp(filename, get_fname("auth_keys" PATH_SEPARATOR "dummy.xxx"))) { + ret = tor_strdup( + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:descriptor:" + "x25519:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); + goto done; + } + + if (!strcmp(filename, get_fname("auth_keys" PATH_SEPARATOR + "client2.auth_private"))) { + ret = tor_strdup( + "25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid:descriptor:" + "x25519:fdreqzjqso7d2ac7qscrxfl5qfpamdvgy5d6cxejcgzc3hvhurmq"); + goto done; + } + + done: + return ret; +} + +static int +mock_check_private_dir(const char *dirname, cpd_check_t check, + const char *effective_user) +{ + (void) dirname; + (void) check; + (void) effective_user; + + return 0; +} + +static smartlist_t * +mock_tor_listdir(const char *dirname) +{ + smartlist_t *file_list = smartlist_new(); + + (void) dirname; + + smartlist_add(file_list, tor_strdup("client1.auth_private")); + smartlist_add(file_list, tor_strdup("dummy.xxx")); + smartlist_add(file_list, tor_strdup("client2.auth_private")); + + return file_list; +} + +static void +test_config_client_authorization(void *arg) +{ + int ret; + char *conf = NULL; + ed25519_public_key_t pk1, pk2; + digest256map_t *global_map = NULL; + char *key_dir = tor_strdup(get_fname("auth_keys")); + + (void) arg; + + MOCK(read_file_to_str, mock_read_file_to_str); + MOCK(tor_listdir, mock_tor_listdir); + MOCK(check_private_dir, mock_check_private_dir); + +#define conf_fmt \ + "ClientOnionAuthDir %s\n" + + tor_asprintf(&conf, conf_fmt, key_dir); + ret = helper_config_client(conf, 0); + tor_free(conf); + tt_int_op(ret, OP_EQ, 0); + +#undef conf_fmt + + global_map = get_hs_client_auths_map(); + tt_int_op(digest256map_size(global_map), OP_EQ, 2); + + hs_parse_address("4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad", + &pk1, NULL, NULL); + hs_parse_address("25njqamcweflpvkl73j4szahhihoc4xt3ktcgjnpaingr5yhkenl5sid", + &pk2, NULL, NULL); + + tt_assert(digest256map_get(global_map, pk1.pubkey)); + tt_assert(digest256map_get(global_map, pk2.pubkey)); + + done: + tor_free(key_dir); + hs_free_all(); + UNMOCK(read_file_to_str); + UNMOCK(tor_listdir); + UNMOCK(check_private_dir); +} + struct testcase_t hs_client_tests[] = { { "e2e_rend_circuit_setup_legacy", test_e2e_rend_circuit_setup_legacy, TT_FORK, NULL, NULL }, @@ -610,5 +780,11 @@ struct testcase_t hs_client_tests[] = { TT_FORK, NULL, NULL }, { "descriptor_fetch", test_descriptor_fetch, TT_FORK, NULL, NULL }, + { "auth_key_filename_is_valid", test_auth_key_filename_is_valid, TT_FORK, + NULL, NULL }, + { "parse_auth_file_content", test_parse_auth_file_content, TT_FORK, + NULL, NULL }, + { "config_client_authorization", test_config_client_authorization, + TT_FORK, NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_hs_common.c b/src/test/test_hs_common.c index c1001ee5c4..c60d6e2640 100644 --- a/src/test/test_hs_common.c +++ b/src/test/test_hs_common.c @@ -428,11 +428,13 @@ mock_directory_initiate_request(directory_request_t *req) static int mock_hs_desc_encode_descriptor(const hs_descriptor_t *desc, - const ed25519_keypair_t *signing_kp, - char **encoded_out) + const ed25519_keypair_t *signing_kp, + const uint8_t *descriptor_cookie, + char **encoded_out) { (void)desc; (void)signing_kp; + (void)descriptor_cookie; tor_asprintf(encoded_out, "lulu"); return 0; diff --git a/src/test/test_hs_descriptor.c b/src/test/test_hs_descriptor.c index 9a7e66eaea..4889281cb1 100644 --- a/src/test/test_hs_descriptor.c +++ b/src/test/test_hs_descriptor.c @@ -30,6 +30,13 @@ DISABLE_GCC_WARNING(overlength-strings) #include "test_hs_descriptor.inc" ENABLE_GCC_WARNING(overlength-strings) +/* Mock function to fill all bytes with 1 */ +static void +mock_crypto_strongest_rand(uint8_t *out, size_t out_len) +{ + memset(out, 1, out_len); +} + /* Test certificate encoding put in a descriptor. */ static void test_cert_encoding(void *arg) @@ -284,7 +291,6 @@ static void test_encode_descriptor(void *arg) { int ret; - char *encoded = NULL; ed25519_keypair_t signing_kp; hs_descriptor_t *desc = NULL; @@ -293,19 +299,38 @@ test_encode_descriptor(void *arg) ret = ed25519_keypair_generate(&signing_kp, 0); tt_int_op(ret, OP_EQ, 0); desc = hs_helper_build_hs_desc_with_ip(&signing_kp); - ret = hs_desc_encode_descriptor(desc, &signing_kp, &encoded); - tt_int_op(ret, OP_EQ, 0); - tt_assert(encoded); + { + char *encoded = NULL; + ret = hs_desc_encode_descriptor(desc, &signing_kp, NULL, &encoded); + tt_int_op(ret, OP_EQ, 0); + tt_assert(encoded); + + tor_free(encoded); + } + + { + char *encoded = NULL; + uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN]; + + crypto_strongest_rand(descriptor_cookie, sizeof(descriptor_cookie)); + + ret = hs_desc_encode_descriptor(desc, &signing_kp, + descriptor_cookie, &encoded); + tt_int_op(ret, OP_EQ, 0); + tt_assert(encoded); + + tor_free(encoded); + } done: hs_descriptor_free(desc); - tor_free(encoded); } static void test_decode_descriptor(void *arg) { int ret; + int i; char *encoded = NULL; ed25519_keypair_t signing_kp; hs_descriptor_t *desc = NULL; @@ -323,14 +348,15 @@ test_decode_descriptor(void *arg) subcredential); /* Give some bad stuff to the decoding function. */ - ret = hs_desc_decode_descriptor("hladfjlkjadf", subcredential, &decoded); + ret = hs_desc_decode_descriptor("hladfjlkjadf", subcredential, + NULL, &decoded); tt_int_op(ret, OP_EQ, -1); - ret = hs_desc_encode_descriptor(desc, &signing_kp, &encoded); + ret = hs_desc_encode_descriptor(desc, &signing_kp, NULL, &encoded); tt_int_op(ret, OP_EQ, 0); tt_assert(encoded); - ret = hs_desc_decode_descriptor(encoded, subcredential, &decoded); + ret = hs_desc_decode_descriptor(encoded, subcredential, NULL, &decoded); tt_int_op(ret, OP_EQ, 0); tt_assert(decoded); @@ -346,13 +372,84 @@ test_decode_descriptor(void *arg) desc_no_ip = hs_helper_build_hs_desc_no_ip(&signing_kp_no_ip); tt_assert(desc_no_ip); tor_free(encoded); - ret = hs_desc_encode_descriptor(desc_no_ip, &signing_kp_no_ip, &encoded); + ret = hs_desc_encode_descriptor(desc_no_ip, &signing_kp_no_ip, + NULL, &encoded); + tt_int_op(ret, OP_EQ, 0); + tt_assert(encoded); + hs_descriptor_free(decoded); + ret = hs_desc_decode_descriptor(encoded, subcredential, NULL, &decoded); + tt_int_op(ret, OP_EQ, 0); + tt_assert(decoded); + } + + /* Decode a descriptor with auth clients. */ + { + uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN]; + curve25519_keypair_t auth_ephemeral_kp; + curve25519_keypair_t client_kp, invalid_client_kp; + smartlist_t *clients; + hs_desc_authorized_client_t *client, *fake_client; + client = tor_malloc_zero(sizeof(hs_desc_authorized_client_t)); + + /* Prepare all the keys needed to build the auth client. */ + curve25519_keypair_generate(&auth_ephemeral_kp, 0); + curve25519_keypair_generate(&client_kp, 0); + curve25519_keypair_generate(&invalid_client_kp, 0); + crypto_strongest_rand(descriptor_cookie, HS_DESC_DESCRIPTOR_COOKIE_LEN); + + memcpy(&desc->superencrypted_data.auth_ephemeral_pubkey, + &auth_ephemeral_kp.pubkey, CURVE25519_PUBKEY_LEN); + + hs_helper_get_subcred_from_identity_keypair(&signing_kp, + subcredential); + + /* Build and add the auth client to the descriptor. */ + clients = desc->superencrypted_data.clients; + if (!clients) { + clients = smartlist_new(); + } + hs_desc_build_authorized_client(subcredential, + &client_kp.pubkey, + &auth_ephemeral_kp.seckey, + descriptor_cookie, client); + smartlist_add(clients, client); + + /* We need to add fake auth clients here. */ + for (i=0; i < 15; ++i) { + fake_client = hs_desc_build_fake_authorized_client(); + smartlist_add(clients, fake_client); + } + desc->superencrypted_data.clients = clients; + + /* Test the encoding/decoding in the following lines. */ + tor_free(encoded); + ret = hs_desc_encode_descriptor(desc, &signing_kp, + descriptor_cookie, &encoded); tt_int_op(ret, OP_EQ, 0); tt_assert(encoded); + + /* If we do not have the client secret key, the decoding must fail. */ hs_descriptor_free(decoded); - ret = hs_desc_decode_descriptor(encoded, subcredential, &decoded); + ret = hs_desc_decode_descriptor(encoded, subcredential, + NULL, &decoded); + tt_int_op(ret, OP_LT, 0); + tt_assert(!decoded); + + /* If we have an invalid client secret key, the decoding must fail. */ + hs_descriptor_free(decoded); + ret = hs_desc_decode_descriptor(encoded, subcredential, + &invalid_client_kp.seckey, &decoded); + tt_int_op(ret, OP_LT, 0); + tt_assert(!decoded); + + /* If we have the client secret key, the decoding must succeed and the + * decoded descriptor must be correct. */ + ret = hs_desc_decode_descriptor(encoded, subcredential, + &client_kp.seckey, &decoded); tt_int_op(ret, OP_EQ, 0); tt_assert(decoded); + + hs_helper_desc_equal(desc, decoded); } done: @@ -588,7 +685,7 @@ test_decode_bad_signature(void *arg) teardown_capture_of_logs(); done: - desc_plaintext_data_free_contents(&desc_plaintext); + hs_desc_plaintext_data_free_contents(&desc_plaintext); } static void @@ -764,101 +861,69 @@ test_desc_signature(void *arg) tor_free(data); } -/* bad desc auth type */ -static const char bad_superencrypted_text1[] = "desc-auth-type scoobysnack\n" - "desc-auth-ephemeral-key A/O8DVtnUheb3r1JqoB8uJB7wxXL1XJX3eny4yB+eFA=\n" - "auth-client oiNrQB8WwKo S5D02W7vKgiWIMygrBl8RQ FB//SfOBmLEx1kViEWWL1g\n" - "encrypted\n" - "-----BEGIN MESSAGE-----\n" - "YmVpbmcgb24gbW91bnRhaW5zLCB0aGlua2luZyBhYm91dCBjb21wdXRlcnMsIGlzIG5vdC" - "BiYWQgYXQgYWxs\n" - "-----END MESSAGE-----\n"; - -/* bad ephemeral key */ -static const char bad_superencrypted_text2[] = "desc-auth-type x25519\n" - "desc-auth-ephemeral-key differentalphabet\n" - "auth-client oiNrQB8WwKo S5D02W7vKgiWIMygrBl8RQ FB//SfOBmLEx1kViEWWL1g\n" - "encrypted\n" - "-----BEGIN MESSAGE-----\n" - "YmVpbmcgb24gbW91bnRhaW5zLCB0aGlua2luZyBhYm91dCBjb21wdXRlcnMsIGlzIG5vdC" - "BiYWQgYXQgYWxs\n" - "-----END MESSAGE-----\n"; - -/* bad encrypted msg */ -static const char bad_superencrypted_text3[] = "desc-auth-type x25519\n" - "desc-auth-ephemeral-key A/O8DVtnUheb3r1JqoB8uJB7wxXL1XJX3eny4yB+eFA=\n" - "auth-client oiNrQB8WwKo S5D02W7vKgiWIMygrBl8RQ FB//SfOBmLEx1kViEWWL1g\n" - "encrypted\n" - "-----BEGIN MESSAGE-----\n" - "SO SMALL NOT GOOD\n" - "-----END MESSAGE-----\n"; - -static const char correct_superencrypted_text[] = "desc-auth-type x25519\n" - "desc-auth-ephemeral-key A/O8DVtnUheb3r1JqoB8uJB7wxXL1XJX3eny4yB+eFA=\n" - "auth-client oiNrQB8WwKo S5D02W7vKgiWIMygrBl8RQ FB//SfOBmLEx1kViEWWL1g\n" - "auth-client Od09Qu636Qo /PKLzqewAdS/+0+vZC+MvQ dpw4NFo13zDnuPz45rxrOg\n" - "auth-client JRr840iGYN0 8s8cxYqF7Lx23+NducC4Qg zAafl4wPLURkuEjJreZq1g\n" - "encrypted\n" - "-----BEGIN MESSAGE-----\n" - "YmVpbmcgb24gbW91bnRhaW5zLCB0aGlua2luZyBhYm91dCBjb21wdXRlcnMsIGlzIG5vdC" - "BiYWQgYXQgYWxs\n" - "-----END MESSAGE-----\n"; - -static const char correct_encrypted_plaintext[] = "being on mountains, " - "thinking about computers, is not bad at all"; - static void -test_parse_hs_desc_superencrypted(void *arg) +test_build_authorized_client(void *arg) { + int ret; + hs_desc_authorized_client_t *desc_client = NULL; + uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN]; + curve25519_secret_key_t auth_ephemeral_sk; + curve25519_secret_key_t client_auth_sk; + curve25519_public_key_t client_auth_pk; + const char ephemeral_sk_b16[] = + "d023b674d993a5c8446bd2ca97e9961149b3c0e88c7dc14e8777744dd3468d6a"; + const char descriptor_cookie_b16[] = + "07d087f1d8c68393721f6e70316d3b29"; + const char client_pubkey_b16[] = + "8c1298fa6050e372f8598f6deca32e27b0ad457741422c2629ebb132cf7fae37"; + uint8_t subcredential[DIGEST256_LEN]; + char *mem_op_hex_tmp=NULL; + (void) arg; - size_t retval; - uint8_t *encrypted_out = NULL; - { - setup_full_capture_of_logs(LOG_WARN); - retval = decode_superencrypted(bad_superencrypted_text1, - strlen(bad_superencrypted_text1), - &encrypted_out); - tt_u64_op(retval, OP_EQ, 0); - tt_ptr_op(encrypted_out, OP_EQ, NULL); - expect_log_msg_containing("Unrecognized desc auth type"); - teardown_capture_of_logs(); - } + ret = curve25519_secret_key_generate(&auth_ephemeral_sk, 0); + tt_int_op(ret, OP_EQ, 0); - { - setup_full_capture_of_logs(LOG_WARN); - retval = decode_superencrypted(bad_superencrypted_text2, - strlen(bad_superencrypted_text2), - &encrypted_out); - tt_u64_op(retval, OP_EQ, 0); - tt_ptr_op(encrypted_out, OP_EQ, NULL); - expect_log_msg_containing("Bogus desc auth key in HS desc"); - teardown_capture_of_logs(); - } + ret = curve25519_secret_key_generate(&client_auth_sk, 0); + tt_int_op(ret, OP_EQ, 0); + curve25519_public_key_generate(&client_auth_pk, &client_auth_sk); - { - setup_full_capture_of_logs(LOG_WARN); - retval = decode_superencrypted(bad_superencrypted_text3, - strlen(bad_superencrypted_text3), - &encrypted_out); - tt_u64_op(retval, OP_EQ, 0); - tt_ptr_op(encrypted_out, OP_EQ, NULL); - expect_log_msg_containing("Length of descriptor\'s encrypted data " - "is too small."); - teardown_capture_of_logs(); - } + memset(subcredential, 42, sizeof(subcredential)); - /* Now finally the good one */ - retval = decode_superencrypted(correct_superencrypted_text, - strlen(correct_superencrypted_text), - &encrypted_out); + desc_client = tor_malloc_zero(sizeof(hs_desc_authorized_client_t)); - tt_u64_op(retval, OP_EQ, strlen(correct_encrypted_plaintext)); - tt_mem_op(encrypted_out, OP_EQ, correct_encrypted_plaintext, - strlen(correct_encrypted_plaintext)); + base16_decode((char *) &auth_ephemeral_sk, + sizeof(auth_ephemeral_sk), + ephemeral_sk_b16, + strlen(ephemeral_sk_b16)); + + base16_decode((char *) descriptor_cookie, + sizeof(descriptor_cookie), + descriptor_cookie_b16, + strlen(descriptor_cookie_b16)); + + base16_decode((char *) &client_auth_pk, + sizeof(client_auth_pk), + client_pubkey_b16, + strlen(client_pubkey_b16)); + + MOCK(crypto_strongest_rand, mock_crypto_strongest_rand); + + hs_desc_build_authorized_client(subcredential, + &client_auth_pk, &auth_ephemeral_sk, + descriptor_cookie, desc_client); + + test_memeq_hex((char *) desc_client->client_id, + "EC19B7FF4D2DDA13"); + test_memeq_hex((char *) desc_client->iv, + "01010101010101010101010101010101"); + test_memeq_hex((char *) desc_client->encrypted_cookie, + "B21222BE13F385F355BD07B2381F9F29"); done: - tor_free(encrypted_out); + tor_free(desc_client); + tor_free(mem_op_hex_tmp); + UNMOCK(crypto_strongest_rand); } struct testcase_t hs_descriptor[] = { @@ -891,9 +956,8 @@ struct testcase_t hs_descriptor[] = { NULL, NULL }, { "desc_signature", test_desc_signature, TT_FORK, NULL, NULL }, - - { "parse_hs_desc_superencrypted", test_parse_hs_desc_superencrypted, - TT_FORK, NULL, NULL }, + { "build_authorized_client", test_build_authorized_client, TT_FORK, + NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c index f8a465629a..6a061eaea4 100644 --- a/src/test/test_hs_service.c +++ b/src/test/test_hs_service.c @@ -34,6 +34,7 @@ #include "core/or/circuitlist.h" #include "core/or/circuituse.h" #include "lib/crypt_ops/crypto_rand.h" +#include "lib/fs/dir.h" #include "feature/dirauth/dirvote.h" #include "feature/nodelist/networkstatus.h" #include "feature/nodelist/nodelist.h" @@ -65,6 +66,13 @@ /* Trunnel */ #include "trunnel/hs/cell_establish_intro.h" +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + static networkstatus_t mock_ns; static networkstatus_t * @@ -220,6 +228,40 @@ helper_create_origin_circuit(int purpose, int flags) return circ; } +/* Helper: Return a newly allocated authorized client object with + * and a newly generated public key. */ +static hs_service_authorized_client_t * +helper_create_authorized_client(void) +{ + int ret; + hs_service_authorized_client_t *client; + curve25519_secret_key_t seckey; + client = tor_malloc_zero(sizeof(hs_service_authorized_client_t)); + + ret = curve25519_secret_key_generate(&seckey, 0); + tt_int_op(ret, OP_EQ, 0); + curve25519_public_key_generate(&client->client_pk, &seckey); + + done: + return client; +} + +/* Helper: Return a newly allocated authorized client object with the + * same client name and the same public key as the given client. */ +static hs_service_authorized_client_t * +helper_clone_authorized_client(const hs_service_authorized_client_t *client) +{ + hs_service_authorized_client_t *client_out; + + tor_assert(client); + + client_out = tor_malloc_zero(sizeof(hs_service_authorized_client_t)); + memcpy(client_out->client_pk.public_key, + client->client_pk.public_key, CURVE25519_PUBKEY_LEN); + + return client_out; +} + /* Helper: Return a newly allocated service object with the identity keypair * sets and the current descriptor. Then register it to the global map. * Caller should us hs_free_all() to free this service or remove it from the @@ -244,6 +286,26 @@ helper_create_service(void) return service; } +/* Helper: Return a newly allocated service object with clients. */ +static hs_service_t * +helper_create_service_with_clients(int num_clients) +{ + int i; + hs_service_t *service = helper_create_service(); + tt_assert(service); + service->config.is_client_auth_enabled = 1; + service->config.clients = smartlist_new(); + + for (i = 0; i < num_clients; i++) { + hs_service_authorized_client_t *client; + client = helper_create_authorized_client(); + smartlist_add(service->config.clients, client); + } + + done: + return service; +} + /* Helper: Return a newly allocated service intro point with two link * specifiers, one IPv4 and one legacy ID set to As. */ static hs_service_intro_point_t * @@ -303,6 +365,8 @@ test_load_keys(void *arg) /* It's in staging? */ tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1); +#undef conf_fmt + /* Load the keys for these. After that, the v3 service should be registered * in the global map. */ hs_service_load_all_keys(); @@ -322,6 +386,9 @@ test_load_keys(void *arg) tt_int_op(hs_address_is_valid(addr), OP_EQ, 1); tt_str_op(addr, OP_EQ, s->onion_address); + /* Check that the is_client_auth_enabled is not set. */ + tt_assert(!s->config.is_client_auth_enabled); + done: tor_free(hsdir_v2); tor_free(hsdir_v3); @@ -329,6 +396,184 @@ test_load_keys(void *arg) } static void +test_client_filename_is_valid(void *arg) +{ + (void) arg; + + /* Valid file name. */ + tt_assert(client_filename_is_valid("a.auth")); + /* Valid file name with special character. */ + tt_assert(client_filename_is_valid("a-.auth")); + /* Invalid extension. */ + tt_assert(!client_filename_is_valid("a.ath")); + /* Nothing before the extension. */ + tt_assert(!client_filename_is_valid(".auth")); + + done: + ; +} + +static void +test_parse_authorized_client(void *arg) +{ + hs_service_authorized_client_t *client = NULL; + + (void) arg; + + /* Valid authorized client. */ + client = parse_authorized_client( + "descriptor:x25519:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"); + tt_assert(client); + + /* Wrong number of fields. */ + tt_assert(!parse_authorized_client("a:b:c:d:e")); + /* Wrong auth type. */ + tt_assert(!parse_authorized_client( + "x:x25519:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja")); + /* Wrong key type. */ + tt_assert(!parse_authorized_client( + "descriptor:x:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja")); + /* Some malformed string. */ + tt_assert(!parse_authorized_client("descriptor:x25519:aa==")); + tt_assert(!parse_authorized_client("descriptor:")); + tt_assert(!parse_authorized_client("descriptor:x25519")); + tt_assert(!parse_authorized_client("descriptor:x25519:")); + tt_assert(!parse_authorized_client("")); + + done: + service_authorized_client_free(client); +} + +static char * +mock_read_file_to_str(const char *filename, int flags, struct stat *stat_out) +{ + char *ret = NULL; + + (void) flags; + (void) stat_out; + + if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR + "authorized_clients" PATH_SEPARATOR + "client1.auth"))) { + ret = tor_strdup("descriptor:x25519:" + "dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"); + goto done; + } + + if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR + "authorized_clients" PATH_SEPARATOR + "dummy.xxx"))) { + ret = tor_strdup("descriptor:x25519:" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); + goto done; + } + + if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR + "authorized_clients" PATH_SEPARATOR + "client2.auth"))) { + ret = tor_strdup("descriptor:x25519:" + "okoi2gml3wd6x7jganlk5d66xxyjgg24sxw4y7javx4giqr66zta"); + goto done; + } + + done: + return ret; +} + +static smartlist_t * +mock_tor_listdir(const char *dirname) +{ + smartlist_t *file_list = smartlist_new(); + + (void) dirname; + + smartlist_add(file_list, tor_strdup("client1.auth")); + smartlist_add(file_list, tor_strdup("dummy.xxx")); + smartlist_add(file_list, tor_strdup("client2.auth")); + + return file_list; +} + +static void +test_load_keys_with_client_auth(void *arg) +{ + int ret; + char *conf = NULL; + smartlist_t *pubkey_b32_list = smartlist_new(); + char *hsdir_v3 = tor_strdup(get_fname("hs3")); + hs_service_t *service; + + (void) arg; + + hs_init(); + smartlist_add(pubkey_b32_list, tor_strdup( + "dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja")); + smartlist_add(pubkey_b32_list, tor_strdup( + "okoi2gml3wd6x7jganlk5d66xxyjgg24sxw4y7javx4giqr66zta")); + +#define conf_fmt \ + "HiddenServiceDir %s\n" \ + "HiddenServiceVersion %d\n" \ + "HiddenServicePort 65534\n" + + tor_asprintf(&conf, conf_fmt, hsdir_v3, HS_VERSION_THREE); + ret = helper_config_service(conf); + tor_free(conf); + tt_int_op(ret, OP_EQ, 0); + /* It's in staging? */ + tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1); + +#undef conf_fmt + + MOCK(read_file_to_str, mock_read_file_to_str); + MOCK(tor_listdir, mock_tor_listdir); + + /* Load the keys for these. After that, the v3 service should be registered + * in the global map. */ + hs_service_load_all_keys(); + tt_int_op(get_hs_service_map_size(), OP_EQ, 1); + + service = get_first_service(); + tt_assert(service->config.clients); + tt_int_op(smartlist_len(service->config.clients), OP_EQ, + smartlist_len(pubkey_b32_list)); + + /* Test that the is_client_auth_enabled flag is set. */ + tt_assert(service->config.is_client_auth_enabled); + + /* Test that the keys in clients are correct. */ + SMARTLIST_FOREACH_BEGIN(pubkey_b32_list, char *, pubkey_b32) { + + curve25519_public_key_t pubkey; + /* This flag will be set if the key is found in clients. */ + int is_found = 0; + base32_decode((char *) pubkey.public_key, sizeof(pubkey.public_key), + pubkey_b32, strlen(pubkey_b32)); + + SMARTLIST_FOREACH_BEGIN(service->config.clients, + hs_service_authorized_client_t *, client) { + if (tor_memeq(&pubkey, &client->client_pk, sizeof(pubkey))) { + is_found = 1; + break; + } + } SMARTLIST_FOREACH_END(client); + + tt_assert(is_found); + + } SMARTLIST_FOREACH_END(pubkey_b32); + + done: + if (pubkey_b32_list) { + SMARTLIST_FOREACH(pubkey_b32_list, char *, s, tor_free(s)); + } + smartlist_free(pubkey_b32_list); + tor_free(hsdir_v3); + hs_free_all(); + UNMOCK(read_file_to_str); + UNMOCK(tor_listdir); +} + +static void test_access_service(void *arg) { int ret; @@ -1371,6 +1616,90 @@ test_build_update_descriptors(void *arg) nodelist_free_all(); } +/** Test building descriptors. We use this separate function instead of + * using test_build_update_descriptors because that function is too complex + * and also too interactive. */ +static void +test_build_descriptors(void *arg) +{ + int ret; + time_t now = time(NULL); + + (void) arg; + + hs_init(); + + MOCK(get_or_state, + get_or_state_replacement); + MOCK(networkstatus_get_live_consensus, + mock_networkstatus_get_live_consensus); + + dummy_state = tor_malloc_zero(sizeof(or_state_t)); + + ret = parse_rfc1123_time("Sat, 26 Oct 1985 03:00:00 UTC", + &mock_ns.valid_after); + tt_int_op(ret, OP_EQ, 0); + ret = parse_rfc1123_time("Sat, 26 Oct 1985 04:00:00 UTC", + &mock_ns.fresh_until); + tt_int_op(ret, OP_EQ, 0); + voting_schedule_recalculate_timing(get_options(), mock_ns.valid_after); + + /* Generate a valid number of fake auth clients when a client authorization + * is disabled. */ + { + hs_service_t *service = helper_create_service(); + service_descriptor_free(service->desc_current); + service->desc_current = NULL; + + build_all_descriptors(now); + hs_desc_superencrypted_data_t *superencrypted; + superencrypted = &service->desc_current->desc->superencrypted_data; + tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 16); + } + + /* Generate a valid number of fake auth clients when the number of + * clients is zero. */ + { + hs_service_t *service = helper_create_service_with_clients(0); + service_descriptor_free(service->desc_current); + service->desc_current = NULL; + + build_all_descriptors(now); + hs_desc_superencrypted_data_t *superencrypted; + superencrypted = &service->desc_current->desc->superencrypted_data; + tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 16); + } + + /* Generate a valid number of fake auth clients when the number of + * clients is not a multiple of 16. */ + { + hs_service_t *service = helper_create_service_with_clients(20); + service_descriptor_free(service->desc_current); + service->desc_current = NULL; + + build_all_descriptors(now); + hs_desc_superencrypted_data_t *superencrypted; + superencrypted = &service->desc_current->desc->superencrypted_data; + tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 32); + } + + /* Do not generate any fake desc client when the number of clients is + * a multiple of 16 but not zero. */ + { + hs_service_t *service = helper_create_service_with_clients(32); + service_descriptor_free(service->desc_current); + service->desc_current = NULL; + + build_all_descriptors(now); + hs_desc_superencrypted_data_t *superencrypted; + superencrypted = &service->desc_current->desc->superencrypted_data; + tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 32); + } + + done: + hs_free_all(); +} + static void test_upload_descriptors(void *arg) { @@ -1556,11 +1885,137 @@ test_rendezvous1_parsing(void *arg) UNMOCK(relay_send_command_from_edge_); } +static void +test_authorized_client_config_equal(void *arg) +{ + int ret; + hs_service_config_t *config1, *config2; + + (void) arg; + + config1 = tor_malloc_zero(sizeof(*config1)); + config2 = tor_malloc_zero(sizeof(*config2)); + + /* Both configs are empty. */ + { + config1->clients = smartlist_new(); + config2->clients = smartlist_new(); + + ret = service_authorized_client_config_equal(config1, config2); + tt_int_op(ret, OP_EQ, 1); + + service_clear_config(config1); + service_clear_config(config2); + } + + /* Both configs have exactly the same client config. */ + { + config1->clients = smartlist_new(); + config2->clients = smartlist_new(); + + hs_service_authorized_client_t *client1, *client2; + client1 = helper_create_authorized_client(); + client2 = helper_create_authorized_client(); + + smartlist_add(config1->clients, client1); + smartlist_add(config1->clients, client2); + + /* We should swap the order of clients here to test that the order + * does not matter. */ + smartlist_add(config2->clients, helper_clone_authorized_client(client2)); + smartlist_add(config2->clients, helper_clone_authorized_client(client1)); + + ret = service_authorized_client_config_equal(config1, config2); + tt_int_op(ret, OP_EQ, 1); + + service_clear_config(config1); + service_clear_config(config2); + } + + /* The numbers of clients in both configs are not equal. */ + { + config1->clients = smartlist_new(); + config2->clients = smartlist_new(); + + hs_service_authorized_client_t *client1, *client2; + client1 = helper_create_authorized_client(); + client2 = helper_create_authorized_client(); + + smartlist_add(config1->clients, client1); + smartlist_add(config1->clients, client2); + + smartlist_add(config2->clients, helper_clone_authorized_client(client1)); + + ret = service_authorized_client_config_equal(config1, config2); + tt_int_op(ret, OP_EQ, 0); + + service_clear_config(config1); + service_clear_config(config2); + } + + /* The first config has two distinct clients while the second config + * has two clients but they are duplicate. */ + { + config1->clients = smartlist_new(); + config2->clients = smartlist_new(); + + hs_service_authorized_client_t *client1, *client2; + client1 = helper_create_authorized_client(); + client2 = helper_create_authorized_client(); + + smartlist_add(config1->clients, client1); + smartlist_add(config1->clients, client2); + + smartlist_add(config2->clients, helper_clone_authorized_client(client1)); + smartlist_add(config2->clients, helper_clone_authorized_client(client1)); + + ret = service_authorized_client_config_equal(config1, config2); + tt_int_op(ret, OP_EQ, 0); + + service_clear_config(config1); + service_clear_config(config2); + } + + /* Both configs have totally distinct clients. */ + { + config1->clients = smartlist_new(); + config2->clients = smartlist_new(); + + hs_service_authorized_client_t *client1, *client2, *client3, *client4; + client1 = helper_create_authorized_client(); + client2 = helper_create_authorized_client(); + client3 = helper_create_authorized_client(); + client4 = helper_create_authorized_client(); + + smartlist_add(config1->clients, client1); + smartlist_add(config1->clients, client2); + + smartlist_add(config2->clients, client3); + smartlist_add(config2->clients, client4); + + ret = service_authorized_client_config_equal(config1, config2); + tt_int_op(ret, OP_EQ, 0); + + service_clear_config(config1); + service_clear_config(config2); + } + + done: + tor_free(config1); + tor_free(config2); +} + struct testcase_t hs_service_tests[] = { { "e2e_rend_circuit_setup", test_e2e_rend_circuit_setup, TT_FORK, NULL, NULL }, { "load_keys", test_load_keys, TT_FORK, NULL, NULL }, + { "client_filename_is_valid", test_client_filename_is_valid, TT_FORK, + NULL, NULL }, + { "parse_authorized_client", test_parse_authorized_client, TT_FORK, + NULL, NULL }, + { "load_keys_with_client_auth", test_load_keys_with_client_auth, TT_FORK, + NULL, NULL }, { "access_service", test_access_service, TT_FORK, NULL, NULL }, { "service_intro_point", test_service_intro_point, TT_FORK, @@ -1583,10 +2038,14 @@ struct testcase_t hs_service_tests[] = { NULL, NULL }, { "build_update_descriptors", test_build_update_descriptors, TT_FORK, NULL, NULL }, + { "build_descriptors", test_build_descriptors, TT_FORK, + NULL, NULL }, { "upload_descriptors", test_upload_descriptors, TT_FORK, NULL, NULL }, { "rendezvous1_parsing", test_rendezvous1_parsing, TT_FORK, NULL, NULL }, + { "authorized_client_config_equal", test_authorized_client_config_equal, + TT_FORK, NULL, NULL }, END_OF_TESTCASES }; diff --git a/src/test/testing_common.c b/src/test/testing_common.c index 42b5190ca0..5d4c2f15af 100644 --- a/src/test/testing_common.c +++ b/src/test/testing_common.c @@ -113,8 +113,8 @@ get_fname_suffix(const char *name, const char *suffix) setup_directory(); if (!name) return temp_dir; - tor_snprintf(buf,sizeof(buf),"%s/%s%s%s",temp_dir,name,suffix ? "_" : "", - suffix ? suffix : ""); + tor_snprintf(buf,sizeof(buf),"%s%s%s%s%s", temp_dir, PATH_SEPARATOR, name, + suffix ? "_" : "", suffix ? suffix : ""); return buf; } |