LCOV - code coverage report
Current view: top level - test - test_hs_ob.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 123 126 97.6 %
Date: 2021-11-24 03:28:48 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /* Copyright (c) 2020-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * \file test_hs_ob.c
       6             :  * \brief Test hidden service onion balance functionality.
       7             :  */
       8             : 
       9             : #define CONFIG_PRIVATE
      10             : #define HS_SERVICE_PRIVATE
      11             : #define HS_OB_PRIVATE
      12             : 
      13             : #include "test/test.h"
      14             : #include "test/test_helpers.h"
      15             : #include "test/log_test_helpers.h"
      16             : 
      17             : #include "app/config/config.h"
      18             : #include "feature/hs/hs_config.h"
      19             : #include "feature/hs/hs_ob.h"
      20             : #include "feature/hs/hs_service.h"
      21             : #include "feature/nodelist/networkstatus.h"
      22             : #include "feature/nodelist/networkstatus_st.h"
      23             : 
      24             : static ed25519_keypair_t onion_addr_kp_1;
      25             : static char onion_addr_1[HS_SERVICE_ADDR_LEN_BASE32 + 1];
      26             : 
      27             : static ed25519_keypair_t onion_addr_kp_2;
      28             : static char onion_addr_2[HS_SERVICE_ADDR_LEN_BASE32 + 1];
      29             : 
      30             : static bool config_is_good = true;
      31             : 
      32             : static int
      33           2 : helper_tor_config(const char *conf)
      34             : {
      35           2 :   int ret = -1;
      36           2 :   or_options_t *options = helper_parse_options(conf);
      37           2 :   tt_assert(options);
      38           2 :   ret = hs_config_service_all(options, 0);
      39           2 :  done:
      40           2 :   or_options_free(options);
      41           2 :   return ret;
      42             : }
      43             : 
      44             : static networkstatus_t mock_ns;
      45             : 
      46             : static networkstatus_t *
      47           0 : mock_networkstatus_get_live_consensus(time_t now)
      48             : {
      49           0 :   (void) now;
      50           0 :   return &mock_ns;
      51             : }
      52             : 
      53             : static char *
      54          11 : mock_read_file_to_str(const char *filename, int flags, struct stat *stat_out)
      55             : {
      56          11 :   char *ret = NULL;
      57             : 
      58          11 :   (void) flags;
      59          11 :   (void) stat_out;
      60             : 
      61          11 :   if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR "ob_config"))) {
      62           2 :     if (config_is_good) {
      63           1 :       tor_asprintf(&ret, "MasterOnionAddress %s.onion\n"
      64             :                          "MasterOnionAddress %s.onion\n",
      65             :                          onion_addr_1, onion_addr_2);
      66             :     } else {
      67           1 :       tor_asprintf(&ret, "MasterOnionAddress JUNKJUNKJUNK.onion\n"
      68             :                          "UnknownOption BLAH\n");
      69             :     }
      70           2 :     goto done;
      71             :   }
      72             : 
      73           9 :  done:
      74          11 :   return ret;
      75             : }
      76             : 
      77             : static void
      78           1 : test_parse_config_file(void *arg)
      79             : {
      80           1 :   int ret;
      81           1 :   char *conf = NULL;
      82           1 :   const ed25519_public_key_t *pkey;
      83             : 
      84           1 :   (void) arg;
      85             : 
      86           1 :   hs_init();
      87             : 
      88           1 :   MOCK(read_file_to_str, mock_read_file_to_str);
      89             : 
      90             : #define fmt_conf            \
      91             :   "HiddenServiceDir %s\n"   \
      92             :   "HiddenServicePort 22\n"  \
      93             :   "HiddenServiceOnionBalanceInstance 1\n"
      94           1 :   tor_asprintf(&conf, fmt_conf, get_fname("hs3"));
      95             : #undef fmt_conf
      96             : 
      97             :   /* Build the OB frontend onion addresses. */
      98           1 :   ed25519_keypair_generate(&onion_addr_kp_1, 0);
      99           1 :   hs_build_address(&onion_addr_kp_1.pubkey, HS_VERSION_THREE, onion_addr_1);
     100           1 :   ed25519_keypair_generate(&onion_addr_kp_2, 0);
     101           1 :   hs_build_address(&onion_addr_kp_2.pubkey, HS_VERSION_THREE, onion_addr_2);
     102             : 
     103           1 :   ret = helper_tor_config(conf);
     104           1 :   tor_free(conf);
     105           1 :   tt_int_op(ret, OP_EQ, 0);
     106             : 
     107             :   /* Load the keys for the service. After that, the v3 service should be
     108             :    * registered in the global map and we'll be able to access it. */
     109           1 :   tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1);
     110           1 :   hs_service_load_all_keys();
     111           1 :   tt_int_op(get_hs_service_map_size(), OP_EQ, 1);
     112           1 :   const hs_service_t *s = get_first_service();
     113           1 :   tt_assert(s);
     114           1 :   tt_assert(s->config.ob_master_pubkeys);
     115           1 :   tt_assert(hs_ob_service_is_instance(s));
     116           1 :   tt_assert(smartlist_len(s->config.ob_master_pubkeys) == 2);
     117             : 
     118             :   /* Test the public keys we've added. */
     119           1 :   pkey = smartlist_get(s->config.ob_master_pubkeys, 0);
     120           1 :   tt_mem_op(&onion_addr_kp_1.pubkey, OP_EQ, pkey, ED25519_PUBKEY_LEN);
     121           1 :   pkey = smartlist_get(s->config.ob_master_pubkeys, 1);
     122           1 :   tt_mem_op(&onion_addr_kp_2.pubkey, OP_EQ, pkey, ED25519_PUBKEY_LEN);
     123             : 
     124           1 :  done:
     125           1 :   hs_free_all();
     126             : 
     127           1 :   UNMOCK(read_file_to_str);
     128           1 : }
     129             : 
     130             : static void
     131           1 : test_parse_config_file_bad(void *arg)
     132             : {
     133           1 :   int ret;
     134           1 :   char *conf = NULL;
     135             : 
     136           1 :   (void) arg;
     137             : 
     138           1 :   hs_init();
     139             : 
     140           1 :   MOCK(read_file_to_str, mock_read_file_to_str);
     141             : 
     142             :   /* Indicate mock_read_file_to_str() to use the bad config. */
     143           1 :   config_is_good = false;
     144             : 
     145             : #define fmt_conf            \
     146             :   "HiddenServiceDir %s\n"   \
     147             :   "HiddenServicePort 22\n"  \
     148             :   "HiddenServiceOnionBalanceInstance 1\n"
     149           1 :   tor_asprintf(&conf, fmt_conf, get_fname("hs3"));
     150             : #undef fmt_conf
     151             : 
     152           1 :   setup_full_capture_of_logs(LOG_INFO);
     153           1 :   ret = helper_tor_config(conf);
     154           1 :   tor_free(conf);
     155           1 :   tt_int_op(ret, OP_EQ, -1);
     156           1 :   expect_log_msg_containing("OnionBalance: MasterOnionAddress "
     157           1 :                             "JUNKJUNKJUNK.onion is invalid");
     158           1 :   expect_log_msg_containing("Found unrecognized option \'UnknownOption\'; "
     159           1 :                             "saving it.");
     160           1 :   teardown_capture_of_logs();
     161             : 
     162           1 :  done:
     163           1 :   hs_free_all();
     164             : 
     165           1 :   UNMOCK(read_file_to_str);
     166           1 : }
     167             : 
     168             : static void
     169           1 : test_get_subcredentials(void *arg)
     170             : {
     171           1 :   int ret;
     172           1 :   hs_service_t *service = NULL;
     173           1 :   hs_service_config_t config;
     174           1 :   hs_subcredential_t *subcreds = NULL;
     175             : 
     176           1 :   (void) arg;
     177             : 
     178           1 :   MOCK(networkstatus_get_live_consensus,
     179             :        mock_networkstatus_get_live_consensus);
     180             : 
     181             :   /* Setup consensus with proper time so we can compute the time period. */
     182           1 :   ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
     183             :                            &mock_ns.valid_after);
     184           1 :   tt_int_op(ret, OP_EQ, 0);
     185           1 :   ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
     186             :                            &mock_ns.fresh_until);
     187           1 :   tt_int_op(ret, OP_EQ, 0);
     188             : 
     189           1 :   config.ob_master_pubkeys = smartlist_new();
     190           1 :   tt_assert(config.ob_master_pubkeys);
     191             : 
     192             :   /* Set up an instance */
     193           1 :   service = tor_malloc_zero(sizeof(hs_service_t));
     194           1 :   service->config = config;
     195             :   /* Setup the service descriptors */
     196           1 :   service->desc_current = service_descriptor_new();
     197           1 :   service->desc_next = service_descriptor_new();
     198             : 
     199             :   /* First try to compute subcredentials but with no OB keys. Make sure that
     200             :    * subcreds get NULLed. To do this check we first poison subcreds. */
     201           1 :   subcreds = (void*)999;
     202           1 :   tt_ptr_op(subcreds, OP_NE, NULL);
     203           1 :   size_t num = compute_subcredentials(service, &subcreds);
     204           1 :   tt_ptr_op(subcreds, OP_EQ, NULL);
     205             : 
     206             :   /* Generate a keypair to add to the OB keys list. */
     207           1 :   ed25519_keypair_generate(&onion_addr_kp_1, 0);
     208           1 :   smartlist_add(config.ob_master_pubkeys, &onion_addr_kp_1.pubkey);
     209             : 
     210             :   /* Set up the instance subcredentials */
     211           1 :   char current_subcred[SUBCRED_LEN];
     212           1 :   char next_subcred[SUBCRED_LEN];
     213           1 :   memset(current_subcred, 'C', SUBCRED_LEN);
     214           1 :   memset(next_subcred, 'N', SUBCRED_LEN);
     215           1 :   memcpy(service->desc_current->desc->subcredential.subcred, current_subcred,
     216             :          SUBCRED_LEN);
     217           1 :   memcpy(service->desc_next->desc->subcredential.subcred, next_subcred,
     218             :          SUBCRED_LEN);
     219             : 
     220             :   /* See that subcreds are computed properly */
     221           1 :   num = compute_subcredentials(service, &subcreds);
     222             :   /* 5 subcredentials: 3 for the frontend, 2 for the instance */
     223           1 :   tt_uint_op(num, OP_EQ, 5);
     224           1 :   tt_ptr_op(subcreds, OP_NE, NULL);
     225             : 
     226             :   /* Validate the subcredentials we just got. We'll build them oursevles with
     227             :    * the right time period steps and compare. */
     228           1 :   const uint64_t tp = hs_get_time_period_num(0);
     229           1 :   const int steps[3] = {0, -1, 1};
     230             : 
     231           1 :   unsigned int i;
     232           4 :   for (i = 0; i < 3; i++) {
     233           3 :     hs_subcredential_t subcredential;
     234           3 :     ed25519_public_key_t blinded_pubkey;
     235           3 :     hs_build_blinded_pubkey(&onion_addr_kp_1.pubkey, NULL, 0, tp + steps[i],
     236             :                             &blinded_pubkey);
     237           3 :     hs_get_subcredential(&onion_addr_kp_1.pubkey, &blinded_pubkey,
     238             :                          &subcredential);
     239           3 :     tt_mem_op(subcreds[i].subcred, OP_EQ, subcredential.subcred,
     240           3 :               SUBCRED_LEN);
     241             :   }
     242             : 
     243           1 :   tt_mem_op(subcreds[i++].subcred, OP_EQ, current_subcred, SUBCRED_LEN);
     244           1 :   tt_mem_op(subcreds[i++].subcred, OP_EQ, next_subcred, SUBCRED_LEN);
     245             : 
     246           1 :  done:
     247           1 :   tor_free(subcreds);
     248             : 
     249           1 :   smartlist_free(config.ob_master_pubkeys);
     250           1 :   if (service) {
     251           1 :     memset(&service->config, 0, sizeof(hs_service_config_t));
     252           1 :     hs_service_free(service);
     253             :   }
     254             : 
     255           1 :   UNMOCK(networkstatus_get_live_consensus);
     256           1 : }
     257             : 
     258             : struct testcase_t hs_ob_tests[] = {
     259             :   { "parse_config_file", test_parse_config_file, TT_FORK,
     260             :     NULL, NULL },
     261             :   { "parse_config_file_bad", test_parse_config_file_bad, TT_FORK,
     262             :     NULL, NULL },
     263             : 
     264             :   { "get_subcredentials", test_get_subcredentials, TT_FORK,
     265             :     NULL, NULL },
     266             : 
     267             :   END_OF_TESTCASES
     268             : };

Generated by: LCOV version 1.14