LCOV - code coverage report
Current view: top level - test - test_hs_service.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 1392 1398 99.6 %
Date: 2021-11-24 03:28:48 Functions: 45 46 97.8 %

          Line data    Source code
       1             : /* Copyright (c) 2016-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * \file test_hs_service.c
       6             :  * \brief Test hidden service functionality.
       7             :  */
       8             : 
       9             : #define CIRCUITBUILD_PRIVATE
      10             : #define CIRCUITLIST_PRIVATE
      11             : #define CONFIG_PRIVATE
      12             : #define CONNECTION_PRIVATE
      13             : #define CONNECTION_EDGE_PRIVATE
      14             : #define CRYPTO_PRIVATE
      15             : #define HS_COMMON_PRIVATE
      16             : #define HS_SERVICE_PRIVATE
      17             : #define HS_INTROPOINT_PRIVATE
      18             : #define HS_CIRCUIT_PRIVATE
      19             : #define MAINLOOP_PRIVATE
      20             : #define NETWORKSTATUS_PRIVATE
      21             : #define STATEFILE_PRIVATE
      22             : #define CHANNEL_OBJECT_PRIVATE
      23             : #define HS_CLIENT_PRIVATE
      24             : #define CRYPT_PATH_PRIVATE
      25             : 
      26             : #include "test/test.h"
      27             : #include "test/test_helpers.h"
      28             : #include "test/log_test_helpers.h"
      29             : #include "test/hs_test_helpers.h"
      30             : 
      31             : #include "core/or/or.h"
      32             : #include "app/config/config.h"
      33             : #include "app/config/statefile.h"
      34             : #include "core/crypto/hs_ntor.h"
      35             : #include "core/mainloop/connection.h"
      36             : #include "core/mainloop/mainloop.h"
      37             : #include "core/or/circuitbuild.h"
      38             : #include "core/or/circuitlist.h"
      39             : #include "core/or/circuituse.h"
      40             : #include "core/or/connection_edge.h"
      41             : #include "core/or/edge_connection_st.h"
      42             : #include "core/or/relay.h"
      43             : #include "core/or/versions.h"
      44             : #include "feature/dirauth/dirvote.h"
      45             : #include "feature/dirauth/shared_random_state.h"
      46             : #include "feature/dirauth/voting_schedule.h"
      47             : #include "feature/hs/hs_circuit.h"
      48             : #include "feature/hs/hs_circuitmap.h"
      49             : #include "feature/hs/hs_client.h"
      50             : #include "feature/hs/hs_common.h"
      51             : #include "feature/hs/hs_config.h"
      52             : #include "feature/hs/hs_ident.h"
      53             : #include "feature/hs/hs_ob.h"
      54             : #include "feature/hs/hs_cell.h"
      55             : #include "feature/hs/hs_intropoint.h"
      56             : #include "feature/hs/hs_metrics.h"
      57             : #include "feature/hs/hs_service.h"
      58             : #include "feature/nodelist/networkstatus.h"
      59             : #include "feature/nodelist/nodelist.h"
      60             : #include "lib/crypt_ops/crypto_rand.h"
      61             : #include "lib/fs/dir.h"
      62             : 
      63             : #include "core/or/cpath_build_state_st.h"
      64             : #include "core/or/crypt_path_st.h"
      65             : #include "core/or/crypt_path.h"
      66             : #include "feature/nodelist/networkstatus_st.h"
      67             : #include "feature/nodelist/node_st.h"
      68             : #include "core/or/origin_circuit_st.h"
      69             : #include "app/config/or_state_st.h"
      70             : #include "feature/nodelist/routerinfo_st.h"
      71             : 
      72             : /* Trunnel */
      73             : #include "trunnel/hs/cell_establish_intro.h"
      74             : 
      75             : #ifdef HAVE_SYS_STAT_H
      76             : #include <sys/stat.h>
      77             : #endif
      78             : #ifdef HAVE_UNISTD_H
      79             : #include <unistd.h>
      80             : #endif
      81             : 
      82             : static networkstatus_t mock_ns;
      83             : 
      84             : static networkstatus_t *
      85         116 : mock_networkstatus_get_reasonably_live_consensus(time_t now, int flavor)
      86             : {
      87         116 :   (void) now;
      88         116 :   (void) flavor;
      89         116 :   return &mock_ns;
      90             : }
      91             : 
      92             : static networkstatus_t *
      93           2 : mock_networkstatus_get_reasonably_live_consensus_null(time_t now, int flavor)
      94             : {
      95           2 :   (void) now;
      96           2 :   (void) flavor;
      97           2 :   return NULL;
      98             : }
      99             : 
     100             : static or_state_t *dummy_state = NULL;
     101             : 
     102             : /* Mock function to get fake or state (used for rev counters) */
     103             : static or_state_t *
     104           0 : get_or_state_replacement(void)
     105             : {
     106           0 :   return dummy_state;
     107             : }
     108             : 
     109             : /* Mock function because we are not trying to test the close circuit that does
     110             :  * an awful lot of checks on the circuit object. */
     111             : static void
     112           7 : mock_circuit_mark_for_close(circuit_t *circ, int reason, int line,
     113             :                             const char *file)
     114             : {
     115           7 :   (void) circ;
     116           7 :   (void) reason;
     117           7 :   (void) line;
     118           7 :   (void) file;
     119           7 :   return;
     120             : }
     121             : 
     122             : static size_t relay_payload_len;
     123             : static char relay_payload[RELAY_PAYLOAD_SIZE];
     124             : 
     125             : static int
     126           6 : mock_relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ,
     127             :                                   uint8_t relay_command, const char *payload,
     128             :                                   size_t payload_len,
     129             :                                   crypt_path_t *cpath_layer,
     130             :                                   const char *filename, int lineno)
     131             : {
     132           6 :   (void) stream_id;
     133           6 :   (void) circ;
     134           6 :   (void) relay_command;
     135           6 :   (void) payload;
     136           6 :   (void) payload_len;
     137           6 :   (void) cpath_layer;
     138           6 :   (void) filename;
     139           6 :   (void) lineno;
     140             : 
     141           6 :   memcpy(relay_payload, payload, payload_len);
     142           6 :   relay_payload_len = payload_len;
     143             : 
     144           6 :   return 0;
     145             : }
     146             : 
     147             : static unsigned int num_intro_points = 0;
     148             : static unsigned int
     149          10 : mock_count_desc_circuit_established(const hs_service_descriptor_t *desc)
     150             : {
     151          10 :   (void) desc;
     152          10 :   return num_intro_points;
     153             : }
     154             : 
     155             : static int
     156           6 : mock_router_have_minimum_dir_info_false(void)
     157             : {
     158           6 :   return 0;
     159             : }
     160             : 
     161             : /* Helper: from a set of options in conf, configure a service which will add
     162             :  * it to the staging list of the HS subsystem. */
     163             : static int
     164           3 : helper_config_service(const char *conf)
     165             : {
     166           3 :   int ret = 0;
     167           3 :   or_options_t *options = NULL;
     168           3 :   tt_assert(conf);
     169           3 :   options = helper_parse_options(conf);
     170           3 :   tt_assert(options);
     171           3 :   ret = hs_config_service_all(options, 0);
     172           3 :  done:
     173           3 :   or_options_free(options);
     174           3 :   return ret;
     175             : }
     176             : 
     177             : /* Test: Ensure that setting up rendezvous circuits works correctly. */
     178             : static void
     179           1 : test_e2e_rend_circuit_setup(void *arg)
     180             : {
     181           1 :   ed25519_public_key_t service_pk;
     182           1 :   origin_circuit_t *or_circ;
     183           1 :   int retval;
     184             : 
     185             :   /** In this test we create a v3 prop224 service-side rendezvous circuit.
     186             :    *  We simulate an HS ntor key exchange with a client, and check that
     187             :    *  the circuit was setup correctly and is ready to accept rendezvous data */
     188             : 
     189           1 :   (void) arg;
     190             : 
     191             :   /* Now make dummy circuit */
     192             :   {
     193           1 :     or_circ = origin_circuit_new();
     194             : 
     195           1 :     or_circ->base_.purpose = CIRCUIT_PURPOSE_S_CONNECT_REND;
     196             : 
     197           1 :     or_circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
     198           1 :     or_circ->build_state->is_internal = 1;
     199             : 
     200             :     /* prop224: Setup hs conn identifier on the stream */
     201           1 :     ed25519_secret_key_t sk;
     202           1 :     tt_int_op(0, OP_EQ, ed25519_secret_key_generate(&sk, 0));
     203           1 :     tt_int_op(0, OP_EQ, ed25519_public_key_generate(&service_pk, &sk));
     204             : 
     205           1 :     or_circ->hs_ident = hs_ident_circuit_new(&service_pk);
     206             : 
     207           1 :     TO_CIRCUIT(or_circ)->state = CIRCUIT_STATE_OPEN;
     208             :   }
     209             : 
     210             :   /* Check number of hops */
     211           1 :   retval = cpath_get_n_hops(&or_circ->cpath);
     212           1 :   tt_int_op(retval, OP_EQ, 0);
     213             : 
     214             :   /* Setup the circuit: do the ntor key exchange */
     215             :   {
     216           1 :     uint8_t ntor_key_seed[DIGEST256_LEN] = {2};
     217           1 :     retval = hs_circuit_setup_e2e_rend_circ(or_circ, ntor_key_seed,
     218             :                                             sizeof(ntor_key_seed), 1);
     219           1 :     tt_int_op(retval, OP_EQ, 0);
     220             :   }
     221             : 
     222             :   /* See that a hop was added to the circuit's cpath */
     223           1 :   retval = cpath_get_n_hops(&or_circ->cpath);
     224           1 :   tt_int_op(retval, OP_EQ, 1);
     225             : 
     226             :   /* Check the digest algo */
     227           1 :   tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.f_digest),
     228             :             OP_EQ, DIGEST_SHA3_256);
     229           1 :   tt_int_op(crypto_digest_get_algorithm(or_circ->cpath->pvt_crypto.b_digest),
     230             :             OP_EQ, DIGEST_SHA3_256);
     231           1 :   tt_assert(or_circ->cpath->pvt_crypto.f_crypto);
     232           1 :   tt_assert(or_circ->cpath->pvt_crypto.b_crypto);
     233             : 
     234             :   /* Ensure that circ purpose was changed */
     235           1 :   tt_int_op(or_circ->base_.purpose, OP_EQ, CIRCUIT_PURPOSE_S_REND_JOINED);
     236             : 
     237           1 :  done:
     238           1 :   circuit_free_(TO_CIRCUIT(or_circ));
     239           1 : }
     240             : 
     241             : /* Helper: Return a newly allocated and initialized origin circuit with
     242             :  * purpose and flags. A default HS identifier is set to an ed25519
     243             :  * authentication key for introduction point. */
     244             : static origin_circuit_t *
     245           7 : helper_create_origin_circuit(int purpose, int flags)
     246             : {
     247           7 :   origin_circuit_t *circ = NULL;
     248             : 
     249           7 :   circ = origin_circuit_init(purpose, flags);
     250           7 :   tor_assert(circ);
     251           7 :   circ->cpath = tor_malloc_zero(sizeof(crypt_path_t));
     252           7 :   circ->cpath->magic = CRYPT_PATH_MAGIC;
     253           7 :   circ->cpath->state = CPATH_STATE_OPEN;
     254           7 :   circ->cpath->package_window = circuit_initial_package_window();
     255           7 :   circ->cpath->deliver_window = CIRCWINDOW_START;
     256           7 :   circ->cpath->prev = circ->cpath;
     257             :   /* Random nonce. */
     258           7 :   crypto_rand(circ->cpath->prev->rend_circ_nonce, DIGEST_LEN);
     259             :   /* Create a default HS identifier. */
     260           7 :   circ->hs_ident = tor_malloc_zero(sizeof(hs_ident_circuit_t));
     261             : 
     262           7 :   return circ;
     263             : }
     264             : 
     265             : /* Helper: Return a newly allocated authorized client object with
     266             :  * and a newly generated public key. */
     267             : static hs_service_authorized_client_t *
     268          62 : helper_create_authorized_client(void)
     269             : {
     270          62 :   int ret;
     271          62 :   hs_service_authorized_client_t *client;
     272          62 :   curve25519_secret_key_t seckey;
     273          62 :   client = tor_malloc_zero(sizeof(hs_service_authorized_client_t));
     274             : 
     275          62 :   ret = curve25519_secret_key_generate(&seckey, 0);
     276          62 :   tt_int_op(ret, OP_EQ, 0);
     277          62 :   curve25519_public_key_generate(&client->client_pk, &seckey);
     278             : 
     279          62 :  done:
     280          62 :   return client;
     281             : }
     282             : 
     283             : /* Helper: Return a newly allocated authorized client object with the
     284             :  * same client name and the same public key as the given client. */
     285             : static hs_service_authorized_client_t *
     286           5 : helper_clone_authorized_client(const hs_service_authorized_client_t *client)
     287             : {
     288           5 :   hs_service_authorized_client_t *client_out;
     289             : 
     290           5 :   tor_assert(client);
     291             : 
     292           5 :   client_out = tor_malloc_zero(sizeof(hs_service_authorized_client_t));
     293           5 :   memcpy(client_out->client_pk.public_key,
     294           5 :          client->client_pk.public_key, CURVE25519_PUBKEY_LEN);
     295             : 
     296           5 :   return client_out;
     297             : }
     298             : 
     299             : /* Helper: Return a newly allocated service object with the identity keypair
     300             :  * sets and the current descriptor. Then register it to the global map.
     301             :  * Caller should use hs_free_all() to free this service or remove it from the
     302             :  * global map before freeing. */
     303             : static hs_service_t *
     304          15 : helper_create_service(void)
     305             : {
     306             :   /* Set a service for this circuit. */
     307          15 :   hs_service_t *service = hs_service_new(get_options());
     308          15 :   tor_assert(service);
     309          15 :   service->config.version = HS_VERSION_THREE;
     310          15 :   ed25519_secret_key_generate(&service->keys.identity_sk, 0);
     311          15 :   ed25519_public_key_generate(&service->keys.identity_pk,
     312             :                               &service->keys.identity_sk);
     313          15 :   service->desc_current = service_descriptor_new();
     314          15 :   tt_assert(service->desc_current);
     315             :   /* Register service to global map. */
     316          15 :   int ret = register_service(get_hs_service_map(), service);
     317          15 :   tt_int_op(ret, OP_EQ, 0);
     318             : 
     319          15 :  done:
     320          15 :   return service;
     321             : }
     322             : 
     323             : /* Helper: Deallocate a given service object, its child objects and
     324             :  * remove it from onion service map.
     325             :  * */
     326             : static void
     327           5 : helper_destroy_service(hs_service_t *service)
     328             : {
     329           5 :   if (!service)
     330             :     return;
     331             : 
     332           4 :   remove_service(get_hs_service_map(), service);
     333             : 
     334           4 :   hs_service_free(service);
     335             : }
     336             : 
     337             : /* Helper: Return a newly allocated service object with clients. */
     338             : static hs_service_t *
     339           3 : helper_create_service_with_clients(int num_clients)
     340             : {
     341           3 :   int i;
     342           3 :   hs_service_t *service = helper_create_service();
     343           3 :   tt_assert(service);
     344           3 :   service->config.clients = smartlist_new();
     345             : 
     346          55 :   for (i = 0; i < num_clients; i++) {
     347          52 :     hs_service_authorized_client_t *client;
     348          52 :     client = helper_create_authorized_client();
     349          52 :     smartlist_add(service->config.clients, client);
     350             :   }
     351             : 
     352           3 :  done:
     353           3 :   return service;
     354             : }
     355             : 
     356             : /* Helper: Return a newly allocated service intro point with two link
     357             :  * specifiers, one IPv4 and one legacy ID set to As. */
     358             : static hs_service_intro_point_t *
     359          10 : helper_create_service_ip(void)
     360             : {
     361          10 :   link_specifier_t *ls;
     362          10 :   hs_service_intro_point_t *ip = service_intro_point_new(NULL);
     363          10 :   tor_assert(ip);
     364             :   /* Add a first unused link specifier. */
     365          10 :   ls = link_specifier_new();
     366          10 :   link_specifier_set_ls_type(ls, LS_IPV4);
     367          10 :   smartlist_add(ip->base.link_specifiers, ls);
     368             :   /* Add a second link specifier used by a test. */
     369          10 :   ls = link_specifier_new();
     370          10 :   link_specifier_set_ls_type(ls, LS_LEGACY_ID);
     371          10 :   memset(link_specifier_getarray_un_legacy_id(ls), 'A',
     372             :          link_specifier_getlen_un_legacy_id(ls));
     373          10 :   smartlist_add(ip->base.link_specifiers, ls);
     374             : 
     375          10 :   return ip;
     376             : }
     377             : 
     378             : static void
     379           1 : test_load_keys(void *arg)
     380             : {
     381           1 :   int ret;
     382           1 :   char *conf = NULL;
     383           1 :   char *hsdir_v3 = tor_strdup(get_fname("hs3"));
     384           1 :   char addr[HS_SERVICE_ADDR_LEN_BASE32 + 1];
     385             : 
     386           1 :   (void) arg;
     387             : 
     388             :   /* We'll register one service then we'll load keys and validate that both
     389             :    * are in a correct state. */
     390             : 
     391           1 :   hs_init();
     392             : 
     393             : #define conf_fmt \
     394             :   "HiddenServiceDir %s\n" \
     395             :   "HiddenServiceVersion %d\n" \
     396             :   "HiddenServicePort 65535\n"
     397             : 
     398             :   /* v3 service. */
     399           1 :   tor_asprintf(&conf, conf_fmt, hsdir_v3, HS_VERSION_THREE);
     400           1 :   ret = helper_config_service(conf);
     401           1 :   tor_free(conf);
     402           1 :   tt_int_op(ret, OP_EQ, 0);
     403             :   /* It's in staging? */
     404           1 :   tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1);
     405             : 
     406             : #undef conf_fmt
     407             : 
     408             :   /* Load the keys for these. After that, the v3 service should be registered
     409             :    * in the global map. */
     410           1 :   hs_service_load_all_keys();
     411           1 :   tt_int_op(get_hs_service_map_size(), OP_EQ, 1);
     412           1 :   hs_service_t *s = get_first_service();
     413           1 :   tt_assert(s);
     414             : 
     415             :   /* Ok we have the service object. Validate few things. */
     416           1 :   tt_assert(!fast_mem_is_zero(s->onion_address, sizeof(s->onion_address)));
     417           1 :   tt_int_op(hs_address_is_valid(s->onion_address), OP_EQ, 1);
     418           1 :   tt_assert(!fast_mem_is_zero((char *) s->keys.identity_sk.seckey,
     419             :                              ED25519_SECKEY_LEN));
     420           1 :   tt_assert(!fast_mem_is_zero((char *) s->keys.identity_pk.pubkey,
     421             :                              ED25519_PUBKEY_LEN));
     422             :   /* Check onion address from identity key. */
     423           1 :   hs_build_address(&s->keys.identity_pk, s->config.version, addr);
     424           1 :   tt_int_op(hs_address_is_valid(addr), OP_EQ, 1);
     425           1 :   tt_str_op(addr, OP_EQ, s->onion_address);
     426             : 
     427           1 :  done:
     428           1 :   tor_free(hsdir_v3);
     429           1 :   hs_free_all();
     430           1 : }
     431             : 
     432             : static void
     433           1 : test_client_filename_is_valid(void *arg)
     434             : {
     435           1 :   (void) arg;
     436             : 
     437             :   /* Valid file name. */
     438           1 :   tt_assert(client_filename_is_valid("a.auth"));
     439             :   /* Valid file name with special character. */
     440           1 :   tt_assert(client_filename_is_valid("a-.auth"));
     441             :   /* Invalid extension. */
     442           1 :   tt_assert(!client_filename_is_valid("a.ath"));
     443             :   /* Nothing before the extension. */
     444           1 :   tt_assert(!client_filename_is_valid(".auth"));
     445             : 
     446           1 :  done:
     447           1 :   ;
     448           1 : }
     449             : 
     450             : static void
     451           1 : test_parse_authorized_client(void *arg)
     452             : {
     453           1 :   hs_service_authorized_client_t *client = NULL;
     454             : 
     455           1 :   (void) arg;
     456             : 
     457             :   /* Valid authorized client. */
     458           1 :   client = parse_authorized_client(
     459             :     "descriptor:x25519:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja");
     460           1 :   tt_assert(client);
     461             : 
     462             :   /* Wrong number of fields. */
     463           1 :   tt_assert(!parse_authorized_client("a:b:c:d:e"));
     464             :   /* Wrong auth type. */
     465           1 :   tt_assert(!parse_authorized_client(
     466             :     "x:x25519:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"));
     467             :   /* Wrong key type. */
     468           1 :   tt_assert(!parse_authorized_client(
     469             :     "descriptor:x:dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"));
     470             :   /* Some malformed string. */
     471           1 :   tt_assert(!parse_authorized_client("descriptor:x25519:aa=="));
     472           1 :   tt_assert(!parse_authorized_client("descriptor:"));
     473           1 :   tt_assert(!parse_authorized_client("descriptor:x25519"));
     474           1 :   tt_assert(!parse_authorized_client("descriptor:x25519:"));
     475           1 :   tt_assert(!parse_authorized_client(""));
     476             : 
     477           1 :  done:
     478           1 :   service_authorized_client_free(client);
     479           1 : }
     480             : 
     481             : static char *
     482           7 : mock_read_file_to_str(const char *filename, int flags, struct stat *stat_out)
     483             : {
     484           7 :   char *ret = NULL;
     485             : 
     486           7 :   (void) flags;
     487           7 :   (void) stat_out;
     488             : 
     489           7 :   if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR
     490             :                                   "authorized_clients" PATH_SEPARATOR
     491             :                                   "client1.auth"))) {
     492           1 :     ret = tor_strdup("descriptor:x25519:"
     493             :                   "dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja");
     494           1 :     goto done;
     495             :   }
     496             : 
     497           6 :   if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR
     498             :                                   "authorized_clients" PATH_SEPARATOR
     499             :                                   "dummy.xxx"))) {
     500           0 :     ret = tor_strdup("descriptor:x25519:"
     501             :                   "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
     502           0 :     goto done;
     503             :   }
     504             : 
     505           6 :   if (!strcmp(filename, get_fname("hs3" PATH_SEPARATOR
     506             :                                   "authorized_clients" PATH_SEPARATOR
     507             :                                   "client2.auth"))) {
     508           1 :     ret = tor_strdup("descriptor:x25519:"
     509             :                   "okoi2gml3wd6x7jganlk5d66xxyjgg24sxw4y7javx4giqr66zta");
     510           1 :     goto done;
     511             :   }
     512             : 
     513           5 :  done:
     514           7 :   return ret;
     515             : }
     516             : 
     517             : static smartlist_t *
     518           1 : mock_tor_listdir(const char *dirname)
     519             : {
     520           1 :   smartlist_t *file_list = smartlist_new();
     521             : 
     522           1 :   (void) dirname;
     523             : 
     524           1 :   smartlist_add(file_list, tor_strdup("client1.auth"));
     525           1 :   smartlist_add(file_list, tor_strdup("dummy.xxx"));
     526           1 :   smartlist_add(file_list, tor_strdup("client2.auth"));
     527             : 
     528           1 :   return file_list;
     529             : }
     530             : 
     531             : static void
     532           1 : test_load_keys_with_client_auth(void *arg)
     533             : {
     534           1 :   int ret;
     535           1 :   char *conf = NULL;
     536           1 :   smartlist_t *pubkey_b32_list = smartlist_new();
     537           1 :   char *hsdir_v3 = tor_strdup(get_fname("hs3"));
     538           1 :   hs_service_t *service;
     539             : 
     540           1 :   (void) arg;
     541             : 
     542           1 :   hs_init();
     543           1 :   smartlist_add(pubkey_b32_list, tor_strdup(
     544             :                 "dz4q5xqlb4ldnbs72iarrml4ephk3du4i7o2cgiva5lwr6wkquja"));
     545           1 :   smartlist_add(pubkey_b32_list, tor_strdup(
     546             :                 "okoi2gml3wd6x7jganlk5d66xxyjgg24sxw4y7javx4giqr66zta"));
     547             : 
     548             : #define conf_fmt \
     549             :   "HiddenServiceDir %s\n" \
     550             :   "HiddenServiceVersion %d\n" \
     551             :   "HiddenServicePort 65534\n"
     552             : 
     553           1 :   tor_asprintf(&conf, conf_fmt, hsdir_v3, HS_VERSION_THREE);
     554           1 :   ret = helper_config_service(conf);
     555           1 :   tor_free(conf);
     556           1 :   tt_int_op(ret, OP_EQ, 0);
     557             :   /* It's in staging? */
     558           1 :   tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1);
     559             : 
     560             : #undef conf_fmt
     561             : 
     562           1 :   MOCK(read_file_to_str, mock_read_file_to_str);
     563           1 :   MOCK(tor_listdir, mock_tor_listdir);
     564             : 
     565             :   /* Load the keys for these. After that, the v3 service should be registered
     566             :    * in the global map. */
     567           1 :   hs_service_load_all_keys();
     568           1 :   tt_int_op(get_hs_service_map_size(), OP_EQ, 1);
     569             : 
     570           1 :   service = get_first_service();
     571           1 :   tt_assert(service);
     572           1 :   tt_assert(service->config.clients);
     573           1 :   tt_int_op(smartlist_len(service->config.clients), OP_EQ,
     574             :             smartlist_len(pubkey_b32_list));
     575             : 
     576             :   /* Test that the keys in clients are correct. */
     577           3 :   SMARTLIST_FOREACH_BEGIN(pubkey_b32_list, char *, pubkey_b32) {
     578             : 
     579           2 :     curve25519_public_key_t pubkey;
     580             :     /* This flag will be set if the key is found in clients. */
     581           2 :     int is_found = 0;
     582           2 :     base32_decode((char *) pubkey.public_key, sizeof(pubkey.public_key),
     583             :                   pubkey_b32, strlen(pubkey_b32));
     584             : 
     585           3 :     SMARTLIST_FOREACH_BEGIN(service->config.clients,
     586             :                             hs_service_authorized_client_t *, client) {
     587           3 :       if (tor_memeq(&pubkey, &client->client_pk, sizeof(pubkey))) {
     588             :         is_found = 1;
     589             :         break;
     590             :       }
     591           1 :     } SMARTLIST_FOREACH_END(client);
     592             : 
     593           2 :     tt_assert(is_found);
     594             : 
     595           2 :   } SMARTLIST_FOREACH_END(pubkey_b32);
     596             : 
     597           1 :  done:
     598           3 :   SMARTLIST_FOREACH(pubkey_b32_list, char *, s, tor_free(s));
     599           1 :   smartlist_free(pubkey_b32_list);
     600           1 :   tor_free(hsdir_v3);
     601           1 :   hs_free_all();
     602           1 :   UNMOCK(read_file_to_str);
     603           1 :   UNMOCK(tor_listdir);
     604           1 : }
     605             : 
     606             : static void
     607           1 : test_access_service(void *arg)
     608             : {
     609           1 :   int ret;
     610           1 :   char *conf = NULL;
     611           1 :   char *hsdir_v3 = tor_strdup(get_fname("hs3"));
     612           1 :   hs_service_ht *global_map;
     613           1 :   hs_service_t *s = NULL;
     614             : 
     615           1 :   (void) arg;
     616             : 
     617             :   /* We'll register one service then we'll load keys and validate that both
     618             :    * are in a correct state. */
     619             : 
     620           1 :   hs_init();
     621             : 
     622             : #define conf_fmt \
     623             :   "HiddenServiceDir %s\n" \
     624             :   "HiddenServiceVersion %d\n" \
     625             :   "HiddenServicePort 65535\n"
     626             : 
     627             :   /* v3 service. */
     628           1 :   tor_asprintf(&conf, conf_fmt, hsdir_v3, HS_VERSION_THREE);
     629           1 :   ret = helper_config_service(conf);
     630           1 :   tor_free(conf);
     631           1 :   tt_int_op(ret, OP_EQ, 0);
     632             :   /* It's in staging? */
     633           1 :   tt_int_op(get_hs_service_staging_list_size(), OP_EQ, 1);
     634             : 
     635             :   /* Load the keys for these. After that, the v3 service should be registered
     636             :    * in the global map. */
     637           1 :   hs_service_load_all_keys();
     638           1 :   tt_int_op(get_hs_service_map_size(), OP_EQ, 1);
     639           1 :   s = get_first_service();
     640           1 :   tt_assert(s);
     641           1 :   global_map = get_hs_service_map();
     642           1 :   tt_assert(global_map);
     643             : 
     644             :   /* From here, we'll try the service accessors. */
     645           1 :   hs_service_t *query = find_service(global_map, &s->keys.identity_pk);
     646           1 :   tt_assert(query);
     647           1 :   tt_mem_op(query, OP_EQ, s, sizeof(hs_service_t));
     648             :   /* Remove service, check if it actually works and then put it back. */
     649           1 :   remove_service(global_map, s);
     650           1 :   hs_metrics_service_free(s);
     651           1 :   tt_int_op(get_hs_service_map_size(), OP_EQ, 0);
     652           1 :   query = find_service(global_map, &s->keys.identity_pk);
     653           1 :   tt_ptr_op(query, OP_EQ, NULL);
     654             : 
     655             :   /* Register back the service in the map. */
     656           1 :   ret = register_service(global_map, s);
     657           1 :   tt_int_op(ret, OP_EQ, 0);
     658           1 :   tt_int_op(get_hs_service_map_size(), OP_EQ, 1);
     659             :   /* Twice should fail. */
     660           1 :   hs_metrics_service_free(s); /* Avoid BUG() on metrics init. */
     661           1 :   ret = register_service(global_map, s);
     662           1 :   tt_int_op(ret, OP_EQ, -1);
     663             :   /* Remove service from map so we don't double free on cleanup. */
     664           1 :   remove_service(global_map, s);
     665           1 :   tt_int_op(get_hs_service_map_size(), OP_EQ, 0);
     666           1 :   query = find_service(global_map, &s->keys.identity_pk);
     667           1 :   tt_ptr_op(query, OP_EQ, NULL);
     668             :   /* Let's try to remove twice for fun. */
     669           1 :   setup_full_capture_of_logs(LOG_WARN);
     670           1 :   remove_service(global_map, s);
     671           1 :   expect_log_msg_containing("Could not find service in the global map");
     672           1 :   teardown_capture_of_logs();
     673             : 
     674           1 :  done:
     675           1 :   hs_service_free(s);
     676           1 :   tor_free(hsdir_v3);
     677           1 :   hs_free_all();
     678           1 : }
     679             : 
     680             : /** Test that we can create intro point objects, index them and find them */
     681             : static void
     682           1 : test_service_intro_point(void *arg)
     683             : {
     684           1 :   hs_service_t *service = NULL;
     685           1 :   hs_service_intro_point_t *ip = NULL;
     686             : 
     687           1 :   (void) arg;
     688             : 
     689           1 :   update_approx_time(1481621834);
     690             : 
     691             :   /* Test simple creation of an object. */
     692             :   {
     693           1 :     time_t now = approx_time();
     694           1 :     ip = helper_create_service_ip();
     695           1 :     tt_assert(ip);
     696             :     /* Make sure the authentication keypair is not zeroes. */
     697           1 :     tt_int_op(fast_mem_is_zero((const char *) &ip->auth_key_kp,
     698             :                               sizeof(ed25519_keypair_t)), OP_EQ, 0);
     699             :     /* The introduce2_max MUST be in that range. */
     700           1 :     tt_u64_op(ip->introduce2_max, OP_GE,
     701             :               INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS);
     702           1 :     tt_u64_op(ip->introduce2_max, OP_LE,
     703             :               INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS);
     704             :     /* Time to expire MUST also be in that range. We subtract 500 seconds
     705             :      * because there could be a gap between setting now and the time taken in
     706             :      * service_intro_point_new. On ARM and other older CPUs, it can be
     707             :      * surprisingly slow... */
     708           1 :     tt_u64_op(ip->time_to_expire, OP_GE,
     709             :               now + INTRO_POINT_LIFETIME_MIN_SECONDS - 500);
     710             :     /* We add 500 seconds, because this time we're testing against the
     711             :      * maximum allowed time. */
     712           1 :     tt_u64_op(ip->time_to_expire, OP_LE,
     713             :               now + INTRO_POINT_LIFETIME_MAX_SECONDS + 500);
     714           1 :     tt_assert(ip->replay_cache);
     715           1 :     tt_assert(ip->base.link_specifiers);
     716             :     /* By default, this is NOT a legacy object. */
     717           1 :     tt_int_op(ip->base.is_only_legacy, OP_EQ, 0);
     718             :   }
     719             : 
     720             :   /* Test functions that uses a service intropoints map with that previously
     721             :    * created object (non legacy). */
     722             :   {
     723           1 :     ed25519_public_key_t garbage = { {0} };
     724           1 :     hs_service_intro_point_t *query;
     725             : 
     726           1 :     service = hs_service_new(get_options());
     727           1 :     tt_assert(service);
     728           1 :     service->desc_current = service_descriptor_new();
     729           1 :     tt_assert(service->desc_current);
     730             :     /* Add intropoint to descriptor map. */
     731           1 :     service_intro_point_add(service->desc_current->intro_points.map, ip);
     732           1 :     query = service_intro_point_find(service, &ip->auth_key_kp.pubkey);
     733           1 :     tt_mem_op(query, OP_EQ, ip, sizeof(hs_service_intro_point_t));
     734           1 :     query = service_intro_point_find(service, &garbage);
     735           1 :     tt_ptr_op(query, OP_EQ, NULL);
     736             : 
     737             :     /* While at it, can I find the descriptor with the intro point? */
     738           1 :     hs_service_descriptor_t *desc_lookup =
     739           1 :       service_desc_find_by_intro(service, ip);
     740           1 :     tt_mem_op(service->desc_current, OP_EQ, desc_lookup,
     741           1 :               sizeof(hs_service_descriptor_t));
     742             : 
     743             :     /* Remove object from service descriptor and make sure it is out. */
     744           1 :     service_intro_point_remove(service, ip);
     745           1 :     query = service_intro_point_find(service, &ip->auth_key_kp.pubkey);
     746           1 :     tt_ptr_op(query, OP_EQ, NULL);
     747             :   }
     748             : 
     749           1 :  done:
     750             :   /* If the test succeed, this object is no longer referenced in the service
     751             :    * so we can free it without use after free. Else, it might explode because
     752             :    * it's still in the service descriptor map. */
     753           1 :   service_intro_point_free(ip);
     754           1 :   hs_service_free(service);
     755           1 : }
     756             : 
     757             : static node_t mock_node;
     758             : static const node_t *
     759           2 : mock_node_get_by_id(const char *digest)
     760             : {
     761           2 :   (void) digest;
     762           2 :   memset(mock_node.identity, 'A', DIGEST_LEN);
     763             :   /* Only return the matching identity of As */
     764           2 :   if (!tor_memcmp(mock_node.identity, digest, DIGEST_LEN)) {
     765           1 :     return &mock_node;
     766             :   }
     767             :   return NULL;
     768             : }
     769             : 
     770             : static void
     771           1 : test_helper_functions(void *arg)
     772             : {
     773           1 :   int ret;
     774           1 :   hs_service_t *service = NULL;
     775           1 :   hs_service_intro_point_t *ip = NULL;
     776           1 :   hs_ident_circuit_t ident;
     777             : 
     778           1 :   (void) arg;
     779             : 
     780           1 :   MOCK(node_get_by_id, mock_node_get_by_id);
     781             : 
     782           1 :   hs_service_init();
     783           1 :   time_t now = time(NULL);
     784           1 :   update_approx_time(now);
     785             : 
     786           1 :   service = helper_create_service();
     787             : 
     788           1 :   ip = helper_create_service_ip();
     789             :   /* Immediately add the intro point to the service so the free service at the
     790             :    * end cleans it as well. */
     791           1 :   service_intro_point_add(service->desc_current->intro_points.map, ip);
     792             : 
     793             :   /* Setup the circuit identifier. */
     794           1 :   ed25519_pubkey_copy(&ident.intro_auth_pk, &ip->auth_key_kp.pubkey);
     795           1 :   ed25519_pubkey_copy(&ident.identity_pk, &service->keys.identity_pk);
     796             : 
     797             :   /* Testing get_objects_from_ident(). */
     798             :   {
     799           1 :     hs_service_t *s_lookup = NULL;
     800           1 :     hs_service_intro_point_t *ip_lookup = NULL;
     801           1 :     hs_service_descriptor_t *desc_lookup = NULL;
     802             : 
     803           1 :     get_objects_from_ident(&ident, &s_lookup, &ip_lookup, &desc_lookup);
     804           1 :     tt_mem_op(s_lookup, OP_EQ, service, sizeof(hs_service_t));
     805           1 :     tt_mem_op(ip_lookup, OP_EQ, ip, sizeof(hs_service_intro_point_t));
     806           1 :     tt_mem_op(desc_lookup, OP_EQ, service->desc_current,
     807           1 :               sizeof(hs_service_descriptor_t));
     808             :     /* Reset */
     809           1 :     s_lookup = NULL; ip_lookup = NULL; desc_lookup = NULL;
     810             : 
     811             :     /* NULL parameter should work. */
     812           1 :     get_objects_from_ident(&ident, NULL, &ip_lookup, &desc_lookup);
     813           1 :     tt_mem_op(ip_lookup, OP_EQ, ip, sizeof(hs_service_intro_point_t));
     814           1 :     tt_mem_op(desc_lookup, OP_EQ, service->desc_current,
     815           1 :               sizeof(hs_service_descriptor_t));
     816             :     /* Reset. */
     817           1 :     s_lookup = NULL; ip_lookup = NULL; desc_lookup = NULL;
     818             : 
     819             :     /* Break the ident and we should find nothing. */
     820           1 :     memset(&ident, 0, sizeof(ident));
     821           1 :     get_objects_from_ident(&ident, &s_lookup, &ip_lookup, &desc_lookup);
     822           1 :     tt_ptr_op(s_lookup, OP_EQ, NULL);
     823           1 :     tt_ptr_op(ip_lookup, OP_EQ, NULL);
     824           1 :     tt_ptr_op(desc_lookup, OP_EQ, NULL);
     825             :   }
     826             : 
     827             :   /* Testing get_node_from_intro_point() */
     828             :   {
     829           1 :     const node_t *node = get_node_from_intro_point(ip);
     830           1 :     tt_ptr_op(node, OP_EQ, &mock_node);
     831           3 :     SMARTLIST_FOREACH_BEGIN(ip->base.link_specifiers,
     832             :                             link_specifier_t *, ls) {
     833           2 :       if (link_specifier_get_ls_type(ls) == LS_LEGACY_ID) {
     834             :         /* Change legacy id in link specifier which is not the mock node. */
     835           1 :         memset(link_specifier_getarray_un_legacy_id(ls), 'B',
     836             :                link_specifier_getlen_un_legacy_id(ls));
     837             :       }
     838           2 :     } SMARTLIST_FOREACH_END(ls);
     839           1 :     node = get_node_from_intro_point(ip);
     840           1 :     tt_ptr_op(node, OP_EQ, NULL);
     841             :   }
     842             : 
     843             :   /* Testing can_service_launch_intro_circuit() */
     844             :   {
     845             :     /* Put the start of the retry period back in time, we should be allowed.
     846             :      * to launch intro circuit. */
     847           1 :     service->state.num_intro_circ_launched = 2;
     848           1 :     service->state.intro_circ_retry_started_time =
     849           1 :       (now - INTRO_CIRC_RETRY_PERIOD - 1);
     850           1 :     ret = can_service_launch_intro_circuit(service, now);
     851           1 :     tt_int_op(ret, OP_EQ, 1);
     852           1 :     tt_u64_op(service->state.intro_circ_retry_started_time, OP_EQ, now);
     853           1 :     tt_u64_op(service->state.num_intro_circ_launched, OP_EQ, 0);
     854             :     /* Call it again, we should still be allowed because we are under
     855             :      * MAX_INTRO_CIRCS_PER_PERIOD which been set to 0 previously. */
     856           1 :     ret = can_service_launch_intro_circuit(service, now);
     857           1 :     tt_int_op(ret, OP_EQ, 1);
     858           1 :     tt_u64_op(service->state.intro_circ_retry_started_time, OP_EQ, now);
     859           1 :     tt_u64_op(service->state.num_intro_circ_launched, OP_EQ, 0);
     860             :     /* Too many intro circuit launched means we are not allowed. */
     861           1 :     service->state.num_intro_circ_launched = 20;
     862           1 :     ret = can_service_launch_intro_circuit(service, now);
     863           1 :     tt_int_op(ret, OP_EQ, 0);
     864             :   }
     865             : 
     866             :   /* Testing intro_point_should_expire(). */
     867             :   {
     868             :     /* Just some basic test of the current state. */
     869           1 :     tt_u64_op(ip->introduce2_max, OP_GE,
     870             :               INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS);
     871           1 :     tt_u64_op(ip->introduce2_max, OP_LE,
     872             :               INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS);
     873           1 :     tt_u64_op(ip->time_to_expire, OP_GE,
     874             :               now + INTRO_POINT_LIFETIME_MIN_SECONDS);
     875           1 :     tt_u64_op(ip->time_to_expire, OP_LE,
     876             :               now + INTRO_POINT_LIFETIME_MAX_SECONDS);
     877             : 
     878             :     /* This newly created IP from above shouldn't expire now. */
     879           1 :     ret = intro_point_should_expire(ip, now);
     880           1 :     tt_int_op(ret, OP_EQ, 0);
     881             :     /* Maximum number of INTRODUCE2 cell reached, it should expire. */
     882           1 :     ip->introduce2_count = INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS + 1;
     883           1 :     ret = intro_point_should_expire(ip, now);
     884           1 :     tt_int_op(ret, OP_EQ, 1);
     885           1 :     ip->introduce2_count = 0;
     886             :     /* It should expire if time to expire has been reached. */
     887           1 :     ip->time_to_expire = now - 1000;
     888           1 :     ret = intro_point_should_expire(ip, now);
     889           1 :     tt_int_op(ret, OP_EQ, 1);
     890             :   }
     891             : 
     892           1 :  done:
     893             :   /* This will free the service and all objects associated to it. */
     894           1 :   if (service) {
     895           1 :     remove_service(get_hs_service_map(), service);
     896           1 :     hs_service_free(service);
     897             :   }
     898           1 :   hs_service_free_all();
     899           1 :   UNMOCK(node_get_by_id);
     900           1 : }
     901             : 
     902             : /** Test that we do the right operations when an intro circuit opens */
     903             : static void
     904           1 : test_intro_circuit_opened(void *arg)
     905             : {
     906           1 :   int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
     907           1 :   hs_service_t *service = NULL;
     908           1 :   origin_circuit_t *circ = NULL;
     909             : 
     910           1 :   (void) arg;
     911             : 
     912           1 :   hs_init();
     913           1 :   MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close);
     914           1 :   MOCK(relay_send_command_from_edge_, mock_relay_send_command_from_edge);
     915             : 
     916           1 :   circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO,
     917             :                                       flags);
     918             : 
     919             :   /* No service associated with this circuit. */
     920           1 :   setup_full_capture_of_logs(LOG_WARN);
     921           1 :   hs_service_circuit_has_opened(circ);
     922           1 :   expect_log_msg_containing("Unknown service identity key");
     923           1 :   teardown_capture_of_logs();
     924             : 
     925             :   /* Set a service for this circuit. */
     926             :   {
     927           1 :     service = helper_create_service();
     928           1 :     ed25519_pubkey_copy(&circ->hs_ident->identity_pk,
     929           1 :                         &service->keys.identity_pk);
     930             : 
     931             :     /* No intro point associated with this circuit. */
     932           1 :     setup_full_capture_of_logs(LOG_WARN);
     933           1 :     hs_service_circuit_has_opened(circ);
     934           1 :     expect_log_msg_containing("Unknown introduction point auth key");
     935           1 :     teardown_capture_of_logs();
     936             :   }
     937             : 
     938             :   /* Set an IP object now for this circuit. */
     939             :   {
     940           1 :     hs_service_intro_point_t *ip = helper_create_service_ip();
     941           1 :     service_intro_point_add(service->desc_current->intro_points.map, ip);
     942             :     /* Update ident to contain the intro point auth key. */
     943           1 :     ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk,
     944           1 :                         &ip->auth_key_kp.pubkey);
     945             :   }
     946             : 
     947             :   /* This one should go all the way. */
     948           1 :   setup_full_capture_of_logs(LOG_INFO);
     949           1 :   hs_service_circuit_has_opened(circ);
     950           1 :   expect_log_msg_containing("Introduction circuit 0 established for service");
     951           1 :   teardown_capture_of_logs();
     952             : 
     953           1 :  done:
     954           1 :   circuit_free_(TO_CIRCUIT(circ));
     955           1 :   if (service) {
     956           1 :     remove_service(get_hs_service_map(), service);
     957           1 :     hs_service_free(service);
     958             :   }
     959           1 :   hs_free_all();
     960           1 :   UNMOCK(circuit_mark_for_close_);
     961           1 :   UNMOCK(relay_send_command_from_edge_);
     962           1 : }
     963             : 
     964             : /** Test the operations we do on a circuit after we learn that we successfully
     965             :  *  established an intro point on it */
     966             : static void
     967           1 : test_intro_established(void *arg)
     968             : {
     969           1 :   int ret;
     970           1 :   int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
     971           1 :   uint8_t payload[RELAY_PAYLOAD_SIZE] = {0};
     972           1 :   origin_circuit_t *circ = NULL;
     973           1 :   hs_service_t *service = NULL;
     974           1 :   hs_service_intro_point_t *ip = NULL;
     975             : 
     976           1 :   (void) arg;
     977             : 
     978           1 :   hs_init();
     979           1 :   MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close);
     980             : 
     981           1 :   circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO,
     982             :                                       flags);
     983           1 :   tt_assert(circ);
     984             : 
     985             :   /* Test a wrong purpose. */
     986           1 :   TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_S_INTRO;
     987           1 :   setup_full_capture_of_logs(LOG_WARN);
     988           1 :   ret = hs_service_receive_intro_established(circ, payload, sizeof(payload));
     989           1 :   tt_int_op(ret, OP_EQ, -1);
     990           1 :   expect_log_msg_containing("Received an INTRO_ESTABLISHED cell on a "
     991           1 :                             "non introduction circuit of purpose");
     992           1 :   teardown_capture_of_logs();
     993             : 
     994             :   /* Back to normal. */
     995           1 :   TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_S_ESTABLISH_INTRO;
     996             : 
     997             :   /* No service associated to it. */
     998           1 :   setup_full_capture_of_logs(LOG_WARN);
     999           1 :   ret = hs_service_receive_intro_established(circ, payload, sizeof(payload));
    1000           1 :   tt_int_op(ret, OP_EQ, -1);
    1001           1 :   expect_log_msg_containing("Unknown service identity key");
    1002           1 :   teardown_capture_of_logs();
    1003             : 
    1004             :   /* Set a service for this circuit. */
    1005           1 :   service = helper_create_service();
    1006           1 :   ed25519_pubkey_copy(&circ->hs_ident->identity_pk,
    1007           1 :                       &service->keys.identity_pk);
    1008             :   /* No introduction point associated to it. */
    1009           1 :   setup_full_capture_of_logs(LOG_WARN);
    1010           1 :   ret = hs_service_receive_intro_established(circ, payload, sizeof(payload));
    1011           1 :   tt_int_op(ret, OP_EQ, -1);
    1012           1 :   expect_log_msg_containing("Introduction circuit established without an "
    1013           1 :                             "intro point object on circuit");
    1014           1 :   teardown_capture_of_logs();
    1015             : 
    1016             :   /* Set an IP object now for this circuit. */
    1017             :   {
    1018           1 :     ip = helper_create_service_ip();
    1019           1 :     service_intro_point_add(service->desc_current->intro_points.map, ip);
    1020             :     /* Update ident to contain the intro point auth key. */
    1021           1 :     ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk,
    1022           1 :                         &ip->auth_key_kp.pubkey);
    1023             :   }
    1024             : 
    1025             :   /* Send an empty payload. INTRO_ESTABLISHED cells are basically zeroes. */
    1026           1 :   ret = hs_service_receive_intro_established(circ, payload, sizeof(payload));
    1027           1 :   tt_int_op(ret, OP_EQ, 0);
    1028           1 :   tt_int_op(TO_CIRCUIT(circ)->purpose, OP_EQ, CIRCUIT_PURPOSE_S_INTRO);
    1029             : 
    1030           1 :  done:
    1031           1 :   if (circ)
    1032           1 :     circuit_free_(TO_CIRCUIT(circ));
    1033           1 :   if (service) {
    1034           1 :     remove_service(get_hs_service_map(), service);
    1035           1 :     hs_service_free(service);
    1036             :   }
    1037           1 :   hs_free_all();
    1038           1 :   UNMOCK(circuit_mark_for_close_);
    1039           1 : }
    1040             : 
    1041             : /** Check the operations we do on a rendezvous circuit after we learn it's
    1042             :  *  open */
    1043             : static void
    1044           1 : test_rdv_circuit_opened(void *arg)
    1045             : {
    1046           1 :   int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
    1047           1 :   origin_circuit_t *circ = NULL;
    1048           1 :   hs_service_t *service = NULL;
    1049             : 
    1050           1 :   (void) arg;
    1051             : 
    1052           1 :   hs_init();
    1053           1 :   MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close);
    1054           1 :   MOCK(relay_send_command_from_edge_, mock_relay_send_command_from_edge);
    1055             : 
    1056           1 :   circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_CONNECT_REND, flags);
    1057           1 :   crypto_rand((char *) circ->hs_ident->rendezvous_cookie, REND_COOKIE_LEN);
    1058           1 :   crypto_rand((char *) circ->hs_ident->rendezvous_handshake_info,
    1059             :               sizeof(circ->hs_ident->rendezvous_handshake_info));
    1060             : 
    1061             :   /* No service associated with this circuit. */
    1062           1 :   setup_full_capture_of_logs(LOG_WARN);
    1063           1 :   hs_service_circuit_has_opened(circ);
    1064           1 :   expect_log_msg_containing("Unknown service identity key");
    1065           1 :   teardown_capture_of_logs();
    1066             :   /* This should be set to a non zero timestamp. */
    1067           1 :   tt_u64_op(TO_CIRCUIT(circ)->timestamp_dirty, OP_NE, 0);
    1068             : 
    1069             :   /* Set a service for this circuit. */
    1070           1 :   service = helper_create_service();
    1071           1 :   ed25519_pubkey_copy(&circ->hs_ident->identity_pk,
    1072           1 :                       &service->keys.identity_pk);
    1073             :   /* Should be all good. */
    1074           1 :   hs_service_circuit_has_opened(circ);
    1075           1 :   tt_int_op(TO_CIRCUIT(circ)->purpose, OP_EQ, CIRCUIT_PURPOSE_S_REND_JOINED);
    1076             : 
    1077           1 :  done:
    1078           1 :   circuit_free_(TO_CIRCUIT(circ));
    1079           1 :   if (service) {
    1080           1 :     remove_service(get_hs_service_map(), service);
    1081           1 :     hs_service_free(service);
    1082             :   }
    1083           1 :   hs_free_all();
    1084           1 :   UNMOCK(circuit_mark_for_close_);
    1085           1 :   UNMOCK(relay_send_command_from_edge_);
    1086           1 : }
    1087             : 
    1088             : static void
    1089           1 : mock_assert_circuit_ok(const circuit_t *c)
    1090             : {
    1091           1 :   (void) c;
    1092           1 :   return;
    1093             : }
    1094             : 
    1095             : /** Test for the general mechanism for closing intro circs.
    1096             :  *  Also a way to identify that #23603 has been fixed. */
    1097             : static void
    1098           1 : test_closing_intro_circs(void *arg)
    1099             : {
    1100           1 :   hs_service_t *service = NULL;
    1101           1 :   hs_service_intro_point_t *ip = NULL, *entry = NULL;
    1102           1 :   origin_circuit_t *intro_circ = NULL, *tmp_circ;
    1103           1 :   int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
    1104             : 
    1105           1 :   (void) arg;
    1106             : 
    1107           1 :   MOCK(assert_circuit_ok, mock_assert_circuit_ok);
    1108             : 
    1109           1 :   hs_init();
    1110             : 
    1111             :   /* Initialize service */
    1112           1 :   service = helper_create_service();
    1113             :   /* Initialize intro point */
    1114           1 :   ip = helper_create_service_ip();
    1115           1 :   tt_assert(ip);
    1116           1 :   service_intro_point_add(service->desc_current->intro_points.map, ip);
    1117             : 
    1118             :   /* Initialize intro circuit */
    1119           1 :   intro_circ = origin_circuit_init(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, flags);
    1120           1 :   intro_circ->hs_ident = hs_ident_circuit_new(&service->keys.identity_pk);
    1121             :   /* Register circuit in the circuitmap . */
    1122           1 :   hs_circuitmap_register_intro_circ_v3_service_side(intro_circ,
    1123           1 :                                                     &ip->auth_key_kp.pubkey);
    1124           1 :   tmp_circ =
    1125           1 :     hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey);
    1126           1 :   tt_ptr_op(tmp_circ, OP_EQ, intro_circ);
    1127             : 
    1128             :   /* Pretend that intro point has failed too much */
    1129           1 :   ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES+1;
    1130             : 
    1131             :   /* Now pretend we are freeing this intro circuit. We want to see that our
    1132             :    * destructor is not gonna kill our intro point structure since that's the
    1133             :    * job of the cleanup routine. */
    1134           1 :   circuit_free_(TO_CIRCUIT(intro_circ));
    1135           1 :   intro_circ = NULL;
    1136           1 :   entry = service_intro_point_find(service, &ip->auth_key_kp.pubkey);
    1137           1 :   tt_assert(entry);
    1138             :   /* The free should also remove the circuit from the circuitmap. */
    1139           1 :   tmp_circ =
    1140           1 :     hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey);
    1141           1 :   tt_assert(!tmp_circ);
    1142             : 
    1143             :   /* Now pretend that a new intro point circ was launched and opened. Check
    1144             :    * that the intro point will be established correctly. */
    1145           1 :   intro_circ = origin_circuit_init(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, flags);
    1146           1 :   intro_circ->hs_ident = hs_ident_circuit_new(&service->keys.identity_pk);
    1147           1 :   ed25519_pubkey_copy(&intro_circ->hs_ident->intro_auth_pk,
    1148             :                       &ip->auth_key_kp.pubkey);
    1149             :   /* Register circuit in the circuitmap . */
    1150           1 :   hs_circuitmap_register_intro_circ_v3_service_side(intro_circ,
    1151             :                                                     &ip->auth_key_kp.pubkey);
    1152           1 :   tmp_circ =
    1153           1 :     hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey);
    1154           1 :   tt_ptr_op(tmp_circ, OP_EQ, intro_circ);
    1155           1 :   tt_int_op(TO_CIRCUIT(intro_circ)->marked_for_close, OP_EQ, 0);
    1156           1 :   circuit_mark_for_close(TO_CIRCUIT(intro_circ), END_CIRC_REASON_INTERNAL);
    1157           1 :   tt_int_op(TO_CIRCUIT(intro_circ)->marked_for_close, OP_NE, 0);
    1158             :   /* At this point, we should not be able to find it in the circuitmap. */
    1159           1 :   tmp_circ =
    1160           1 :     hs_circuitmap_get_intro_circ_v3_service_side(&ip->auth_key_kp.pubkey);
    1161           1 :   tt_assert(!tmp_circ);
    1162             : 
    1163           1 :  done:
    1164           0 :   if (intro_circ) {
    1165           1 :     circuit_free_(TO_CIRCUIT(intro_circ));
    1166             :   }
    1167             :   /* Frees the service object. */
    1168           1 :   if (service) {
    1169           1 :     remove_service(get_hs_service_map(), service);
    1170           1 :     hs_service_free(service);
    1171             :   }
    1172           1 :   hs_free_all();
    1173           1 :   UNMOCK(assert_circuit_ok);
    1174           1 : }
    1175             : 
    1176             : /** Test sending and receiving introduce2 cells */
    1177             : static void
    1178           1 : test_bad_introduce2(void *arg)
    1179             : {
    1180           1 :   int ret;
    1181           1 :   int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
    1182           1 :   uint8_t payload[RELAY_PAYLOAD_SIZE] = {0};
    1183           1 :   origin_circuit_t *circ = NULL;
    1184           1 :   hs_service_t *service = NULL;
    1185           1 :   hs_service_intro_point_t *ip = NULL;
    1186             : 
    1187           1 :   (void) arg;
    1188             : 
    1189           1 :   hs_init();
    1190           1 :   MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close);
    1191           1 :   MOCK(get_or_state,
    1192             :        get_or_state_replacement);
    1193             : 
    1194           1 :   dummy_state = or_state_new();
    1195             : 
    1196           1 :   circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_INTRO, flags);
    1197           1 :   tt_assert(circ);
    1198             : 
    1199             :   /* Test a wrong purpose. */
    1200           1 :   TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_S_ESTABLISH_INTRO;
    1201           1 :   setup_full_capture_of_logs(LOG_WARN);
    1202           1 :   ret = hs_service_receive_introduce2(circ, payload, sizeof(payload));
    1203           1 :   tt_int_op(ret, OP_EQ, -1);
    1204           1 :   expect_log_msg_containing("Received an INTRODUCE2 cell on a "
    1205           1 :                             "non introduction circuit of purpose");
    1206           1 :   teardown_capture_of_logs();
    1207             : 
    1208             :   /* Back to normal. */
    1209           1 :   TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_S_INTRO;
    1210             : 
    1211             :   /* No service associated to it. */
    1212           1 :   setup_full_capture_of_logs(LOG_WARN);
    1213           1 :   ret = hs_service_receive_introduce2(circ, payload, sizeof(payload));
    1214           1 :   tt_int_op(ret, OP_EQ, -1);
    1215           1 :   expect_log_msg_containing("Unknown service identity key");
    1216           1 :   teardown_capture_of_logs();
    1217             : 
    1218             :   /* Set a service for this circuit. */
    1219           1 :   service = helper_create_service();
    1220           1 :   ed25519_pubkey_copy(&circ->hs_ident->identity_pk,
    1221           1 :                       &service->keys.identity_pk);
    1222             :   /* No introduction point associated to it. */
    1223           1 :   setup_full_capture_of_logs(LOG_WARN);
    1224           1 :   ret = hs_service_receive_introduce2(circ, payload, sizeof(payload));
    1225           1 :   tt_int_op(ret, OP_EQ, -1);
    1226           1 :   expect_log_msg_containing("Unknown introduction auth key when handling "
    1227           1 :                             "an INTRODUCE2 cell on circuit");
    1228           1 :   teardown_capture_of_logs();
    1229             : 
    1230             :   /* Set an IP object now for this circuit. */
    1231             :   {
    1232           1 :     ip = helper_create_service_ip();
    1233           1 :     service_intro_point_add(service->desc_current->intro_points.map, ip);
    1234             :     /* Update ident to contain the intro point auth key. */
    1235           1 :     ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk,
    1236           1 :                         &ip->auth_key_kp.pubkey);
    1237             :   }
    1238             : 
    1239             :   /* This will fail because receiving an INTRODUCE2 cell implies a valid cell
    1240             :    * and then launching circuits so let's not do that and instead test that
    1241             :    * behaviour differently. */
    1242           1 :   ret = hs_service_receive_introduce2(circ, payload, sizeof(payload));
    1243           1 :   tt_int_op(ret, OP_EQ, -1);
    1244           1 :   tt_u64_op(ip->introduce2_count, OP_EQ, 0);
    1245             : 
    1246           1 :  done:
    1247           1 :   or_state_free(dummy_state);
    1248           1 :   dummy_state = NULL;
    1249           1 :   if (circ)
    1250           1 :     circuit_free_(TO_CIRCUIT(circ));
    1251           1 :   if (service) {
    1252           1 :     remove_service(get_hs_service_map(), service);
    1253           1 :     hs_service_free(service);
    1254             :   }
    1255           1 :   hs_free_all();
    1256           1 :   UNMOCK(circuit_mark_for_close_);
    1257           1 : }
    1258             : 
    1259             : /** Test basic hidden service housekeeping operations (maintaining intro
    1260             :  *  points, etc) */
    1261             : static void
    1262           1 : test_service_event(void *arg)
    1263             : {
    1264           1 :   int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
    1265           1 :   time_t now = time(NULL);
    1266           1 :   hs_service_t *service;
    1267           1 :   origin_circuit_t *circ = NULL;
    1268             : 
    1269           1 :   (void) arg;
    1270             : 
    1271           1 :   hs_init();
    1272           1 :   MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close);
    1273             : 
    1274           1 :   circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_INTRO, flags);
    1275             : 
    1276             :   /* Set a service for this circuit. */
    1277           1 :   service = helper_create_service();
    1278           1 :   tt_assert(service);
    1279           1 :   ed25519_pubkey_copy(&circ->hs_ident->identity_pk,
    1280           1 :                       &service->keys.identity_pk);
    1281             : 
    1282             :   /* Currently this consists of cleaning invalid intro points. So adding IPs
    1283             :    * here that should get cleaned up. */
    1284             :   {
    1285           1 :     hs_service_intro_point_t *ip = helper_create_service_ip();
    1286           1 :     service_intro_point_add(service->desc_current->intro_points.map, ip);
    1287             :     /* This run will remove the IP because we have no circuits nor node_t
    1288             :      * associated with it. */
    1289           1 :     run_housekeeping_event(now);
    1290           1 :     tt_int_op(digest256map_size(service->desc_current->intro_points.map),
    1291             :               OP_EQ, 0);
    1292             :     /* We'll trigger a removal because we've reached our maximum amount of
    1293             :      * times we should retry a circuit. For this, we need to have a node_t
    1294             :      * that matches the identity of this IP. */
    1295           1 :     routerinfo_t ri;
    1296           1 :     memset(&ri, 0, sizeof(ri));
    1297           1 :     ip = helper_create_service_ip();
    1298           1 :     service_intro_point_add(service->desc_current->intro_points.map, ip);
    1299           1 :     memset(ri.cache_info.identity_digest, 'A', DIGEST_LEN);
    1300             :     /* This triggers a node_t creation. */
    1301           1 :     tt_assert(nodelist_set_routerinfo(&ri, NULL));
    1302           1 :     ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES + 1;
    1303           1 :     run_housekeeping_event(now);
    1304           1 :     tt_int_op(digest256map_size(service->desc_current->intro_points.map),
    1305             :               OP_EQ, 0);
    1306             :     /* No removal but no circuit so this means the IP object will stay in the
    1307             :      * descriptor map so we can retry it. */
    1308           1 :     ip = helper_create_service_ip();
    1309           1 :     service_intro_point_add(service->desc_current->intro_points.map, ip);
    1310           1 :     run_housekeeping_event(now);
    1311           1 :     tt_int_op(digest256map_size(service->desc_current->intro_points.map),
    1312             :               OP_EQ, 1);
    1313             :     /* Remove the IP object at once for the next test. */
    1314           1 :     ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES + 1;
    1315           1 :     run_housekeeping_event(now);
    1316           1 :     tt_int_op(digest256map_size(service->desc_current->intro_points.map),
    1317             :               OP_EQ, 0);
    1318             :     /* Now, we'll create an IP with a registered circuit. The IP object
    1319             :      * shouldn't go away. */
    1320           1 :     ip = helper_create_service_ip();
    1321           1 :     service_intro_point_add(service->desc_current->intro_points.map, ip);
    1322           1 :     ed25519_pubkey_copy(&circ->hs_ident->intro_auth_pk,
    1323           1 :                         &ip->auth_key_kp.pubkey);
    1324           1 :     hs_circuitmap_register_intro_circ_v3_service_side(
    1325             :                                          circ, &ip->auth_key_kp.pubkey);
    1326           1 :     run_housekeeping_event(now);
    1327           1 :     tt_int_op(digest256map_size(service->desc_current->intro_points.map),
    1328             :               OP_EQ, 1);
    1329             :     /* We'll mangle the IP object to expire. */
    1330           1 :     ip->time_to_expire = now;
    1331           1 :     run_housekeeping_event(now);
    1332           1 :     tt_int_op(digest256map_size(service->desc_current->intro_points.map),
    1333             :               OP_EQ, 0);
    1334             :   }
    1335             : 
    1336           1 :  done:
    1337           1 :   hs_circuitmap_remove_circuit(TO_CIRCUIT(circ));
    1338           1 :   circuit_free_(TO_CIRCUIT(circ));
    1339           1 :   if (service) {
    1340           1 :     remove_service(get_hs_service_map(), service);
    1341           1 :     hs_service_free(service);
    1342             :   }
    1343           1 :   hs_free_all();
    1344           1 :   UNMOCK(circuit_mark_for_close_);
    1345           1 : }
    1346             : 
    1347             : /** Test that we rotate descriptors correctly. */
    1348             : static void
    1349           1 : test_rotate_descriptors(void *arg)
    1350             : {
    1351           1 :   int ret;
    1352           1 :   time_t next_rotation_time, now;
    1353           1 :   hs_service_t *service = NULL;
    1354           1 :   hs_service_descriptor_t *desc_next;
    1355             : 
    1356           1 :   (void) arg;
    1357             : 
    1358           1 :   dummy_state = or_state_new();
    1359             : 
    1360           1 :   hs_init();
    1361           1 :   MOCK(get_or_state, get_or_state_replacement);
    1362           1 :   MOCK(circuit_mark_for_close_, mock_circuit_mark_for_close);
    1363           1 :   MOCK(networkstatus_get_reasonably_live_consensus,
    1364             :        mock_networkstatus_get_reasonably_live_consensus);
    1365             : 
    1366             :   /* Descriptor rotation happens with a consensus with a new SRV. */
    1367             : 
    1368           1 :   ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
    1369             :                            &mock_ns.valid_after);
    1370           1 :   tt_int_op(ret, OP_EQ, 0);
    1371           1 :   ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
    1372             :                            &mock_ns.fresh_until);
    1373           1 :   tt_int_op(ret, OP_EQ, 0);
    1374           1 :   dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after);
    1375             : 
    1376           1 :   update_approx_time(mock_ns.valid_after+1);
    1377           1 :   now = mock_ns.valid_after+1;
    1378             : 
    1379             :   /* Create a service with a default descriptor and state. It's added to the
    1380             :    * global map. */
    1381           1 :   service = helper_create_service();
    1382           1 :   service_descriptor_free(service->desc_current);
    1383           1 :   service->desc_current = NULL;
    1384             :   /* This triggers a build for both descriptors. The time now is only used in
    1385             :    * the descriptor certificate which is important to be now else the decoding
    1386             :    * will complain that the cert has expired if we use valid_after. */
    1387           1 :   build_all_descriptors(now);
    1388           1 :   tt_assert(service->desc_current);
    1389           1 :   tt_assert(service->desc_next);
    1390             : 
    1391             :   /* Tweak our service next rotation time so we can use a custom time. */
    1392           1 :   service->state.next_rotation_time = next_rotation_time =
    1393           1 :     mock_ns.valid_after + (11 * 60 * 60);
    1394             : 
    1395             :   /* Nothing should happen, we are not at a new SRV. Our next rotation time
    1396             :    * should be untouched. */
    1397           1 :   rotate_all_descriptors(mock_ns.valid_after);
    1398           1 :   tt_u64_op(service->state.next_rotation_time, OP_EQ, next_rotation_time);
    1399           1 :   tt_assert(service->desc_current);
    1400           1 :   tt_assert(service->desc_next);
    1401           1 :   tt_u64_op(service->desc_current->time_period_num, OP_EQ,
    1402             :             hs_get_previous_time_period_num(0));
    1403           1 :   tt_u64_op(service->desc_next->time_period_num, OP_EQ,
    1404             :             hs_get_time_period_num(0));
    1405             :   /* Keep a reference so we can compare it after rotation to the current. */
    1406           1 :   desc_next = service->desc_next;
    1407             : 
    1408             :   /* Going right after a new SRV. */
    1409           1 :   ret = parse_rfc1123_time("Sat, 27 Oct 1985 01:00:00 UTC",
    1410             :                            &mock_ns.valid_after);
    1411           1 :   tt_int_op(ret, OP_EQ, 0);
    1412           1 :   ret = parse_rfc1123_time("Sat, 27 Oct 1985 02:00:00 UTC",
    1413             :                            &mock_ns.fresh_until);
    1414           1 :   tt_int_op(ret, OP_EQ, 0);
    1415           1 :   dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after);
    1416             : 
    1417           1 :   update_approx_time(mock_ns.valid_after+1);
    1418           1 :   now = mock_ns.valid_after+1;
    1419             : 
    1420             :   /* Note down what to expect for the next rotation time which is 01:00 + 23h
    1421             :    * meaning 00:00:00. */
    1422           1 :   next_rotation_time = mock_ns.valid_after + (23 * 60 * 60);
    1423             :   /* We should have our next rotation time modified, our current descriptor
    1424             :    * cleaned up and the next descriptor becoming the current. */
    1425           1 :   rotate_all_descriptors(mock_ns.valid_after);
    1426           1 :   tt_u64_op(service->state.next_rotation_time, OP_EQ, next_rotation_time);
    1427           1 :   tt_mem_op(service->desc_current, OP_EQ, desc_next, sizeof(*desc_next));
    1428           1 :   tt_assert(service->desc_next == NULL);
    1429             : 
    1430             :   /* A second time should do nothing. */
    1431           1 :   rotate_all_descriptors(mock_ns.valid_after);
    1432           1 :   tt_u64_op(service->state.next_rotation_time, OP_EQ, next_rotation_time);
    1433           1 :   tt_mem_op(service->desc_current, OP_EQ, desc_next, sizeof(*desc_next));
    1434           1 :   tt_assert(service->desc_next == NULL);
    1435             : 
    1436           1 :   build_all_descriptors(now);
    1437           1 :   tt_mem_op(service->desc_current, OP_EQ, desc_next, sizeof(*desc_next));
    1438           1 :   tt_u64_op(service->desc_current->time_period_num, OP_EQ,
    1439             :             hs_get_time_period_num(0));
    1440           1 :   tt_u64_op(service->desc_next->time_period_num, OP_EQ,
    1441             :             hs_get_next_time_period_num(0));
    1442           1 :   tt_assert(service->desc_next);
    1443             : 
    1444           1 :  done:
    1445           0 :   if (service) {
    1446           1 :     remove_service(get_hs_service_map(), service);
    1447           1 :     hs_service_free(service);
    1448             :   }
    1449           1 :   hs_free_all();
    1450           1 :   UNMOCK(get_or_state);
    1451           1 :   UNMOCK(circuit_mark_for_close_);
    1452           1 :   UNMOCK(networkstatus_get_reasonably_live_consensus);
    1453           1 : }
    1454             : 
    1455             : /** Test building descriptors: picking intro points, setting up their link
    1456             :  *  specifiers, etc. */
    1457             : static void
    1458           1 : test_build_update_descriptors(void *arg)
    1459             : {
    1460           1 :   int ret;
    1461           1 :   node_t *node;
    1462           1 :   hs_service_t *service = NULL;
    1463           1 :   hs_service_intro_point_t *ip_cur, *ip_next;
    1464           1 :   routerinfo_t ri;
    1465             : 
    1466           1 :   (void) arg;
    1467             : 
    1468           1 :   hs_init();
    1469             : 
    1470           1 :   MOCK(get_or_state,
    1471             :        get_or_state_replacement);
    1472           1 :   MOCK(networkstatus_get_reasonably_live_consensus,
    1473             :        mock_networkstatus_get_reasonably_live_consensus);
    1474             : 
    1475           1 :   dummy_state = or_state_new();
    1476             : 
    1477           1 :   ret = parse_rfc1123_time("Sat, 26 Oct 1985 03:00:00 UTC",
    1478             :                            &mock_ns.valid_after);
    1479           1 :   tt_int_op(ret, OP_EQ, 0);
    1480           1 :   ret = parse_rfc1123_time("Sat, 26 Oct 1985 04:00:00 UTC",
    1481             :                            &mock_ns.fresh_until);
    1482           1 :   tt_int_op(ret, OP_EQ, 0);
    1483           1 :   dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after);
    1484             : 
    1485           1 :   update_approx_time(mock_ns.valid_after+1);
    1486             : 
    1487           1 :   time_t now = mock_ns.valid_after+1;
    1488             : 
    1489             :   /* Create a service without a current descriptor to trigger a build. */
    1490           1 :   service = helper_create_service();
    1491           1 :   tt_assert(service);
    1492             :   /* Unfortunately, the helper creates a dummy descriptor so get rid of it. */
    1493           1 :   service_descriptor_free(service->desc_current);
    1494           1 :   service->desc_current = NULL;
    1495             : 
    1496             :   /* We have a fresh service so this should trigger a build for both
    1497             :    * descriptors for specific time period that we'll test. */
    1498           1 :   build_all_descriptors(now);
    1499             :   /* Check *current* descriptor. */
    1500           1 :   tt_assert(service->desc_current);
    1501           1 :   tt_assert(service->desc_current->desc);
    1502           1 :   tt_assert(service->desc_current->intro_points.map);
    1503             :   /* The current time period is the one expected when starting at 03:00. */
    1504           1 :   tt_u64_op(service->desc_current->time_period_num, OP_EQ,
    1505             :             hs_get_time_period_num(0));
    1506             :   /* This should be untouched, the update descriptor process changes it. */
    1507           1 :   tt_u64_op(service->desc_current->next_upload_time, OP_EQ, 0);
    1508             : 
    1509             :   /* Check *next* descriptor. */
    1510           1 :   tt_assert(service->desc_next);
    1511           1 :   tt_assert(service->desc_next->desc);
    1512           1 :   tt_assert(service->desc_next->intro_points.map);
    1513           1 :   tt_assert(service->desc_current != service->desc_next);
    1514           1 :   tt_u64_op(service->desc_next->time_period_num, OP_EQ,
    1515             :             hs_get_next_time_period_num(0));
    1516             :   /* This should be untouched, the update descriptor process changes it. */
    1517           1 :   tt_u64_op(service->desc_next->next_upload_time, OP_EQ, 0);
    1518             : 
    1519             :   /* Time to test the update of those descriptors. At first, we have no node
    1520             :    * in the routerlist so this will find NO suitable node for the IPs. */
    1521           1 :   setup_full_capture_of_logs(LOG_INFO);
    1522           1 :   update_all_descriptors_intro_points(now);
    1523           1 :   expect_log_msg_containing("Unable to find a suitable node to be an "
    1524           1 :                             "introduction point for service");
    1525           1 :   teardown_capture_of_logs();
    1526           1 :   tt_int_op(digest256map_size(service->desc_current->intro_points.map),
    1527             :             OP_EQ, 0);
    1528           1 :   tt_int_op(digest256map_size(service->desc_next->intro_points.map),
    1529             :             OP_EQ, 0);
    1530             : 
    1531             :   /* Now, we'll setup a node_t. */
    1532             :   {
    1533           1 :     curve25519_secret_key_t curve25519_secret_key;
    1534             : 
    1535           1 :     memset(&ri, 0, sizeof(routerinfo_t));
    1536             : 
    1537           1 :     tor_addr_parse(&ri.ipv4_addr, "127.0.0.1");
    1538           1 :     ri.ipv4_orport = 1337;
    1539           1 :     ri.purpose = ROUTER_PURPOSE_GENERAL;
    1540             :     /* Ugly yes but we never free the "ri" object so this just makes things
    1541             :      * easier. */
    1542           1 :     ri.protocol_list = (char *) "HSDir=1-2 LinkAuth=3";
    1543           1 :     summarize_protover_flags(&ri.pv, ri.protocol_list, NULL);
    1544           1 :     ret = curve25519_secret_key_generate(&curve25519_secret_key, 0);
    1545           1 :     tt_int_op(ret, OP_EQ, 0);
    1546           2 :     ri.onion_curve25519_pkey =
    1547           1 :       tor_malloc_zero(sizeof(curve25519_public_key_t));
    1548           1 :     ri.onion_pkey = tor_malloc_zero(140);
    1549           1 :     curve25519_public_key_generate(ri.onion_curve25519_pkey,
    1550             :                                    &curve25519_secret_key);
    1551           1 :     memset(ri.cache_info.identity_digest, 'A', DIGEST_LEN);
    1552             :     /* Setup ed25519 identity */
    1553           1 :     ed25519_keypair_t kp1;
    1554           1 :     ed25519_keypair_generate(&kp1, 0);
    1555           1 :     ri.cache_info.signing_key_cert = tor_malloc_zero(sizeof(tor_cert_t));
    1556           1 :     tt_assert(ri.cache_info.signing_key_cert);
    1557           1 :     ed25519_pubkey_copy(&ri.cache_info.signing_key_cert->signing_key,
    1558             :                         &kp1.pubkey);
    1559           1 :     nodelist_set_routerinfo(&ri, NULL);
    1560           1 :     node = node_get_mutable_by_id(ri.cache_info.identity_digest);
    1561           1 :     tt_assert(node);
    1562           1 :     node->is_running = node->is_valid = node->is_fast = node->is_stable = 1;
    1563             :   }
    1564             : 
    1565             :   /* We have to set this, or the lack of microdescriptors for these
    1566             :    * nodes will make them unusable. */
    1567           1 :   get_options_mutable()->UseMicrodescriptors = 0;
    1568             : 
    1569             :   /* We expect to pick only one intro point from the node above. */
    1570           1 :   setup_full_capture_of_logs(LOG_INFO);
    1571           1 :   update_all_descriptors_intro_points(now);
    1572           1 :   tor_free(node->ri->onion_curve25519_pkey); /* Avoid memleak. */
    1573           1 :   tor_free(node->ri->cache_info.signing_key_cert);
    1574           1 :   tor_free(node->ri->onion_pkey);
    1575           1 :   expect_log_msg_containing("just picked 1 intro points and wanted 3 for next "
    1576             :                             "descriptor. It currently has 0 intro points. "
    1577           1 :                             "Launching ESTABLISH_INTRO circuit shortly.");
    1578           1 :   teardown_capture_of_logs();
    1579           1 :   tt_int_op(digest256map_size(service->desc_current->intro_points.map),
    1580             :             OP_EQ, 1);
    1581           1 :   tt_int_op(digest256map_size(service->desc_next->intro_points.map),
    1582             :             OP_EQ, 1);
    1583             :   /* Get the IP object. Because we don't have the auth key of the IP, we can't
    1584             :    * query it so get the first element in the map. */
    1585             :   {
    1586           1 :     void *obj = NULL;
    1587           1 :     const uint8_t *key;
    1588           1 :     digest256map_iter_t *iter =
    1589           1 :       digest256map_iter_init(service->desc_current->intro_points.map);
    1590           1 :     digest256map_iter_get(iter, &key, &obj);
    1591           1 :     tt_assert(obj);
    1592           1 :     ip_cur = obj;
    1593             :     /* Get also the IP from the next descriptor. We'll make sure it's not the
    1594             :      * same object as in the current descriptor. */
    1595           1 :     iter = digest256map_iter_init(service->desc_next->intro_points.map);
    1596           1 :     digest256map_iter_get(iter, &key, &obj);
    1597           1 :     tt_assert(obj);
    1598           1 :     ip_next = obj;
    1599             :   }
    1600           1 :   tt_mem_op(ip_cur, OP_NE, ip_next, sizeof(hs_desc_intro_point_t));
    1601             : 
    1602             :   /* We won't test the service IP object because there is a specific test
    1603             :    * already for this but we'll make sure that the state is coherent.*/
    1604             : 
    1605             :   /* Three link specifiers are mandatory so make sure we do have them. */
    1606           1 :   tt_int_op(smartlist_len(ip_cur->base.link_specifiers), OP_EQ, 3);
    1607             :   /* Make sure we have a valid encryption keypair generated when we pick an
    1608             :    * intro point in the update process. */
    1609           1 :   tt_assert(!fast_mem_is_zero((char *) ip_cur->enc_key_kp.seckey.secret_key,
    1610             :                              CURVE25519_SECKEY_LEN));
    1611           1 :   tt_assert(!fast_mem_is_zero((char *) ip_cur->enc_key_kp.pubkey.public_key,
    1612             :                              CURVE25519_PUBKEY_LEN));
    1613           1 :   tt_u64_op(ip_cur->time_to_expire, OP_GE, now +
    1614             :             INTRO_POINT_LIFETIME_MIN_SECONDS);
    1615           1 :   tt_u64_op(ip_cur->time_to_expire, OP_LE, now +
    1616             :             INTRO_POINT_LIFETIME_MAX_SECONDS);
    1617             : 
    1618             :   /* Now, we will try to set up a service after a new time period has started
    1619             :    * and see if it behaves as expected. */
    1620             : 
    1621           1 :   ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
    1622             :                            &mock_ns.valid_after);
    1623           1 :   tt_int_op(ret, OP_EQ, 0);
    1624           1 :   ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
    1625             :                            &mock_ns.fresh_until);
    1626           1 :   tt_int_op(ret, OP_EQ, 0);
    1627             : 
    1628           1 :   update_approx_time(mock_ns.valid_after+1);
    1629           1 :   now = mock_ns.valid_after+1;
    1630             : 
    1631             :   /* Create a service without a current descriptor to trigger a build. */
    1632           1 :   service = helper_create_service();
    1633           1 :   tt_assert(service);
    1634             :   /* Unfortunately, the helper creates a dummy descriptor so get rid of it. */
    1635           1 :   service_descriptor_free(service->desc_current);
    1636           1 :   service->desc_current = NULL;
    1637             : 
    1638             :   /* We have a fresh service so this should trigger a build for both
    1639             :    * descriptors for specific time period that we'll test. */
    1640           1 :   build_all_descriptors(now);
    1641             :   /* Check *current* descriptor. */
    1642           1 :   tt_assert(service->desc_current);
    1643           1 :   tt_assert(service->desc_current->desc);
    1644           1 :   tt_assert(service->desc_current->intro_points.map);
    1645             :   /* This should be for the previous time period. */
    1646           1 :   tt_u64_op(service->desc_current->time_period_num, OP_EQ,
    1647             :             hs_get_previous_time_period_num(0));
    1648             :   /* This should be untouched, the update descriptor process changes it. */
    1649           1 :   tt_u64_op(service->desc_current->next_upload_time, OP_EQ, 0);
    1650             : 
    1651             :   /* Check *next* descriptor. */
    1652           1 :   tt_assert(service->desc_next);
    1653           1 :   tt_assert(service->desc_next->desc);
    1654           1 :   tt_assert(service->desc_next->intro_points.map);
    1655           1 :   tt_assert(service->desc_current != service->desc_next);
    1656           1 :   tt_u64_op(service->desc_next->time_period_num, OP_EQ,
    1657             :             hs_get_time_period_num(0));
    1658             :   /* This should be untouched, the update descriptor process changes it. */
    1659           1 :   tt_u64_op(service->desc_next->next_upload_time, OP_EQ, 0);
    1660             : 
    1661             :   /* Let's remove the next descriptor to simulate a rotation. */
    1662           1 :   service_descriptor_free(service->desc_next);
    1663           1 :   service->desc_next = NULL;
    1664             : 
    1665           1 :   build_all_descriptors(now);
    1666             :   /* Check *next* descriptor. */
    1667           1 :   tt_assert(service->desc_next);
    1668           1 :   tt_assert(service->desc_next->desc);
    1669           1 :   tt_assert(service->desc_next->intro_points.map);
    1670           1 :   tt_assert(service->desc_current != service->desc_next);
    1671           1 :   tt_u64_op(service->desc_next->time_period_num, OP_EQ,
    1672             :             hs_get_next_time_period_num(0));
    1673             :   /* This should be untouched, the update descriptor process changes it. */
    1674           1 :   tt_u64_op(service->desc_next->next_upload_time, OP_EQ, 0);
    1675             : 
    1676           1 :  done:
    1677           1 :   if (service) {
    1678           1 :     remove_service(get_hs_service_map(), service);
    1679           1 :     hs_service_free(service);
    1680             :   }
    1681           1 :   hs_free_all();
    1682           1 :   nodelist_free_all();
    1683           1 : }
    1684             : 
    1685             : /** Test building descriptors. We use this separate function instead of
    1686             :  *  using test_build_update_descriptors because that function is too complex
    1687             :  *  and also too interactive. */
    1688             : static void
    1689           1 : test_build_descriptors(void *arg)
    1690             : {
    1691           1 :   int ret;
    1692           1 :   time_t now = time(NULL);
    1693           1 :   hs_service_t *last_service = NULL;
    1694             : 
    1695           1 :   (void) arg;
    1696             : 
    1697           1 :   hs_init();
    1698             : 
    1699           1 :   MOCK(get_or_state,
    1700             :        get_or_state_replacement);
    1701           1 :   MOCK(networkstatus_get_reasonably_live_consensus,
    1702             :        mock_networkstatus_get_reasonably_live_consensus);
    1703             : 
    1704           1 :   dummy_state = or_state_new();
    1705             : 
    1706           1 :   ret = parse_rfc1123_time("Sat, 26 Oct 1985 03:00:00 UTC",
    1707             :                            &mock_ns.valid_after);
    1708           1 :   tt_int_op(ret, OP_EQ, 0);
    1709           1 :   ret = parse_rfc1123_time("Sat, 26 Oct 1985 04:00:00 UTC",
    1710             :                            &mock_ns.fresh_until);
    1711           1 :   tt_int_op(ret, OP_EQ, 0);
    1712           1 :   dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after);
    1713             : 
    1714             :   /* Generate a valid number of fake auth clients when a client authorization
    1715             :    * is disabled. */
    1716             :   {
    1717           1 :     hs_service_t *service = helper_create_service();
    1718           1 :     last_service = service;
    1719           1 :     service_descriptor_free(service->desc_current);
    1720           1 :     service->desc_current = NULL;
    1721             : 
    1722           1 :     build_all_descriptors(now);
    1723           1 :     tt_assert(service->desc_current);
    1724           1 :     tt_assert(service->desc_current->desc);
    1725             : 
    1726           1 :     hs_desc_superencrypted_data_t *superencrypted;
    1727           1 :     superencrypted = &service->desc_current->desc->superencrypted_data;
    1728           1 :     tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 16);
    1729             : 
    1730           1 :     helper_destroy_service(service);
    1731           1 :     last_service = NULL;
    1732             :   }
    1733             : 
    1734             :   /* Generate a valid number of fake auth clients when the number of
    1735             :    * clients is zero. */
    1736             :   {
    1737           1 :     hs_service_t *service = helper_create_service_with_clients(0);
    1738           1 :     last_service = service;
    1739           1 :     service_descriptor_free(service->desc_current);
    1740           1 :     service->desc_current = NULL;
    1741             : 
    1742           1 :     build_all_descriptors(now);
    1743           1 :     hs_desc_superencrypted_data_t *superencrypted;
    1744           1 :     superencrypted = &service->desc_current->desc->superencrypted_data;
    1745           1 :     tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 16);
    1746             : 
    1747           1 :     helper_destroy_service(service);
    1748           1 :     last_service = NULL;
    1749             :   }
    1750             : 
    1751             :   /* Generate a valid number of fake auth clients when the number of
    1752             :    * clients is not a multiple of 16. */
    1753             :   {
    1754           1 :     hs_service_t *service = helper_create_service_with_clients(20);
    1755           1 :     last_service = service;
    1756           1 :     service_descriptor_free(service->desc_current);
    1757           1 :     service->desc_current = NULL;
    1758             : 
    1759           1 :     build_all_descriptors(now);
    1760           1 :     hs_desc_superencrypted_data_t *superencrypted;
    1761           1 :     superencrypted = &service->desc_current->desc->superencrypted_data;
    1762           1 :     tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 32);
    1763             : 
    1764           1 :     helper_destroy_service(service);
    1765           1 :     last_service = NULL;
    1766             :   }
    1767             : 
    1768             :   /* Do not generate any fake desc client when the number of clients is
    1769             :    * a multiple of 16 but not zero. */
    1770             :   {
    1771           1 :     hs_service_t *service = helper_create_service_with_clients(32);
    1772           1 :     last_service = service;
    1773           1 :     service_descriptor_free(service->desc_current);
    1774           1 :     service->desc_current = NULL;
    1775             : 
    1776           1 :     build_all_descriptors(now);
    1777           1 :     hs_desc_superencrypted_data_t *superencrypted;
    1778           1 :     superencrypted = &service->desc_current->desc->superencrypted_data;
    1779           1 :     tt_int_op(smartlist_len(superencrypted->clients), OP_EQ, 32);
    1780             : 
    1781           1 :     helper_destroy_service(service);
    1782           1 :     last_service = NULL;
    1783             :   }
    1784             : 
    1785           1 :  done:
    1786           1 :   helper_destroy_service(last_service);
    1787           1 :   hs_free_all();
    1788           1 : }
    1789             : 
    1790             : static void
    1791           1 : test_upload_descriptors(void *arg)
    1792             : {
    1793           1 :   int ret;
    1794           1 :   time_t now;
    1795           1 :   hs_service_t *service;
    1796             : 
    1797           1 :   (void) arg;
    1798             : 
    1799           1 :   hs_init();
    1800           1 :   MOCK(get_or_state,
    1801             :        get_or_state_replacement);
    1802           1 :   MOCK(networkstatus_get_reasonably_live_consensus,
    1803             :        mock_networkstatus_get_reasonably_live_consensus);
    1804             : 
    1805           1 :   dummy_state = or_state_new();
    1806             : 
    1807           1 :   ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
    1808             :                            &mock_ns.valid_after);
    1809           1 :   tt_int_op(ret, OP_EQ, 0);
    1810           1 :   ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
    1811             :                            &mock_ns.fresh_until);
    1812           1 :   tt_int_op(ret, OP_EQ, 0);
    1813           1 :   dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after);
    1814             : 
    1815           1 :   update_approx_time(mock_ns.valid_after+1);
    1816           1 :   now = mock_ns.valid_after+1;
    1817             : 
    1818             :   /* Create a service with no descriptor. It's added to the global map. */
    1819           1 :   service = hs_service_new(get_options());
    1820           1 :   tt_assert(service);
    1821           1 :   service->config.version = HS_VERSION_THREE;
    1822           1 :   ed25519_secret_key_generate(&service->keys.identity_sk, 0);
    1823           1 :   ed25519_public_key_generate(&service->keys.identity_pk,
    1824             :                               &service->keys.identity_sk);
    1825             :   /* Register service to global map. */
    1826           1 :   ret = register_service(get_hs_service_map(), service);
    1827           1 :   tt_int_op(ret, OP_EQ, 0);
    1828             :   /* But first, build our descriptor. */
    1829           1 :   build_all_descriptors(now);
    1830             : 
    1831             :   /* Nothing should happen because we have 0 introduction circuit established
    1832             :    * and we want (by default) 3 intro points. */
    1833           1 :   run_upload_descriptor_event(now);
    1834             :   /* If no upload happened, this should be untouched. */
    1835           1 :   tt_u64_op(service->desc_current->next_upload_time, OP_EQ, 0);
    1836             :   /* We'll simulate that we've opened our intro point circuit and that we only
    1837             :    * want one intro point. */
    1838           1 :   service->config.num_intro_points = 1;
    1839             : 
    1840             :   /* Set our next upload time after now which will skip the upload. */
    1841           1 :   service->desc_current->next_upload_time = now + 1000;
    1842           1 :   run_upload_descriptor_event(now);
    1843             :   /* If no upload happened, this should be untouched. */
    1844           1 :   tt_u64_op(service->desc_current->next_upload_time, OP_EQ, now + 1000);
    1845             : 
    1846           1 :  done:
    1847           1 :   hs_free_all();
    1848           1 :   UNMOCK(get_or_state);
    1849           1 : }
    1850             : 
    1851             : /** Global vars used by test_rendezvous1_parsing() */
    1852             : static char rend1_payload[RELAY_PAYLOAD_SIZE];
    1853             : static size_t rend1_payload_len = 0;
    1854             : 
    1855             : /** Mock for relay_send_command_from_edge() to send a RENDEZVOUS1 cell. Instead
    1856             :  *  of sending it to the network, instead save it to the global `rend1_payload`
    1857             :  *  variable so that we can inspect it in the test_rendezvous1_parsing()
    1858             :  *  test. */
    1859             : static int
    1860           1 : mock_relay_send_rendezvous1(streamid_t stream_id, circuit_t *circ,
    1861             :                             uint8_t relay_command, const char *payload,
    1862             :                             size_t payload_len,
    1863             :                             crypt_path_t *cpath_layer,
    1864             :                             const char *filename, int lineno)
    1865             : {
    1866           1 :   (void) stream_id;
    1867           1 :   (void) circ;
    1868           1 :   (void) relay_command;
    1869           1 :   (void) cpath_layer;
    1870           1 :   (void) filename;
    1871           1 :   (void) lineno;
    1872             : 
    1873           1 :   memcpy(rend1_payload, payload, payload_len);
    1874           1 :   rend1_payload_len = payload_len;
    1875             : 
    1876           1 :   return 0;
    1877             : }
    1878             : 
    1879             : /** Send a RENDEZVOUS1 as a service, and parse it as a client. */
    1880             : static void
    1881           1 : test_rendezvous1_parsing(void *arg)
    1882             : {
    1883           1 :   int retval;
    1884           1 :   static const char *test_addr =
    1885             :     "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad.onion";
    1886           1 :   hs_service_t *service = NULL;
    1887           1 :   origin_circuit_t *service_circ = NULL;
    1888           1 :   origin_circuit_t *client_circ = NULL;
    1889           1 :   ed25519_keypair_t ip_auth_kp;
    1890           1 :   curve25519_keypair_t ephemeral_kp;
    1891           1 :   curve25519_keypair_t client_kp;
    1892           1 :   curve25519_keypair_t ip_enc_kp;
    1893           1 :   int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
    1894             : 
    1895           1 :   (void) arg;
    1896             : 
    1897           1 :   MOCK(relay_send_command_from_edge_, mock_relay_send_rendezvous1);
    1898             : 
    1899             :   {
    1900             :     /* Let's start by setting up the service that will start the rend */
    1901           1 :     service = tor_malloc_zero(sizeof(hs_service_t));
    1902           1 :     ed25519_secret_key_generate(&service->keys.identity_sk, 0);
    1903           1 :     ed25519_public_key_generate(&service->keys.identity_pk,
    1904             :                                 &service->keys.identity_sk);
    1905           1 :     memcpy(service->onion_address, test_addr, sizeof(service->onion_address));
    1906           1 :     tt_assert(service);
    1907             :   }
    1908             : 
    1909             :   {
    1910             :     /* Now let's set up the service rendezvous circuit and its keys. */
    1911           1 :     service_circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_CONNECT_REND,
    1912             :                                                 flags);
    1913           1 :     tor_free(service_circ->hs_ident);
    1914           1 :     hs_ntor_rend_cell_keys_t hs_ntor_rend_cell_keys;
    1915           1 :     uint8_t rendezvous_cookie[HS_REND_COOKIE_LEN];
    1916           1 :     curve25519_keypair_generate(&ip_enc_kp, 0);
    1917           1 :     curve25519_keypair_generate(&ephemeral_kp, 0);
    1918           1 :     curve25519_keypair_generate(&client_kp, 0);
    1919           1 :     ed25519_keypair_generate(&ip_auth_kp, 0);
    1920           1 :     retval = hs_ntor_service_get_rendezvous1_keys(&ip_auth_kp.pubkey,
    1921             :                                                   &ip_enc_kp,
    1922             :                                                   &ephemeral_kp,
    1923             :                                                   &client_kp.pubkey,
    1924             :                                                   &hs_ntor_rend_cell_keys);
    1925           1 :     tt_int_op(retval, OP_EQ, 0);
    1926             : 
    1927           1 :     memset(rendezvous_cookie, 2, sizeof(rendezvous_cookie));
    1928           2 :     service_circ->hs_ident =
    1929           1 :       create_rp_circuit_identifier(service, rendezvous_cookie,
    1930             :                                    &ephemeral_kp.pubkey,
    1931             :                                    &hs_ntor_rend_cell_keys);
    1932             :   }
    1933             : 
    1934             :   /* Send out the RENDEZVOUS1 and make sure that our mock func worked */
    1935           1 :   tt_assert(fast_mem_is_zero(rend1_payload, 32));
    1936           1 :   hs_circ_service_rp_has_opened(service, service_circ);
    1937           1 :   tt_assert(!fast_mem_is_zero(rend1_payload, 32));
    1938           1 :   tt_int_op(rend1_payload_len, OP_EQ, HS_LEGACY_RENDEZVOUS_CELL_SIZE);
    1939             : 
    1940             :   /******************************/
    1941             : 
    1942             :   /** Now let's create the client rendezvous circuit */
    1943           1 :   client_circ =
    1944           1 :     helper_create_origin_circuit(CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED,
    1945             :                                  flags);
    1946             :   /* fix up its circ ident */
    1947           1 :   ed25519_pubkey_copy(&client_circ->hs_ident->intro_auth_pk,
    1948             :                       &ip_auth_kp.pubkey);
    1949           1 :   memcpy(&client_circ->hs_ident->rendezvous_client_kp,
    1950             :          &client_kp, sizeof(client_circ->hs_ident->rendezvous_client_kp));
    1951           1 :   memcpy(&client_circ->hs_ident->intro_enc_pk.public_key,
    1952             :          &ip_enc_kp.pubkey.public_key,
    1953             :          sizeof(client_circ->hs_ident->intro_enc_pk.public_key));
    1954             : 
    1955             :   /* Now parse the rendezvous2 circuit and make sure it was fine. We are
    1956             :    * skipping 20 bytes off its payload, since that's the rendezvous cookie
    1957             :    * which is only present in REND1. */
    1958           1 :   retval = handle_rendezvous2(client_circ,
    1959             :                               (uint8_t*)rend1_payload+20,
    1960             :                               rend1_payload_len-20);
    1961           1 :   tt_int_op(retval, OP_EQ, 0);
    1962             : 
    1963             :   /* TODO: We are only simulating client/service here. We could also simulate
    1964             :    * the rendezvous point by plugging in rend_mid_establish_rendezvous(). We
    1965             :    * would need an extra circuit and some more stuff but it's doable. */
    1966             : 
    1967           1 :  done:
    1968           1 :   circuit_free_(TO_CIRCUIT(service_circ));
    1969           1 :   circuit_free_(TO_CIRCUIT(client_circ));
    1970           1 :   hs_service_free(service);
    1971           1 :   hs_free_all();
    1972           1 :   UNMOCK(relay_send_command_from_edge_);
    1973           1 : }
    1974             : 
    1975             : static void
    1976           1 : test_authorized_client_config_equal(void *arg)
    1977             : {
    1978           1 :   int ret;
    1979           1 :   hs_service_config_t *config1, *config2;
    1980             : 
    1981           1 :   (void) arg;
    1982             : 
    1983           1 :   config1 = tor_malloc_zero(sizeof(*config1));
    1984           1 :   config2 = tor_malloc_zero(sizeof(*config2));
    1985             : 
    1986             :   /* Both configs are empty. */
    1987             :   {
    1988           1 :     config1->clients = smartlist_new();
    1989           1 :     config2->clients = smartlist_new();
    1990             : 
    1991           1 :     ret = service_authorized_client_config_equal(config1, config2);
    1992           1 :     tt_int_op(ret, OP_EQ, 1);
    1993             : 
    1994           1 :     service_clear_config(config1);
    1995           1 :     service_clear_config(config2);
    1996             :   }
    1997             : 
    1998             :   /* Both configs have exactly the same client config. */
    1999             :   {
    2000           1 :     config1->clients = smartlist_new();
    2001           1 :     config2->clients = smartlist_new();
    2002             : 
    2003           1 :     hs_service_authorized_client_t *client1, *client2;
    2004           1 :     client1 = helper_create_authorized_client();
    2005           1 :     client2 = helper_create_authorized_client();
    2006             : 
    2007           1 :     smartlist_add(config1->clients, client1);
    2008           1 :     smartlist_add(config1->clients, client2);
    2009             : 
    2010             :     /* We should swap the order of clients here to test that the order
    2011             :      * does not matter. */
    2012           1 :     smartlist_add(config2->clients, helper_clone_authorized_client(client2));
    2013           1 :     smartlist_add(config2->clients, helper_clone_authorized_client(client1));
    2014             : 
    2015           1 :     ret = service_authorized_client_config_equal(config1, config2);
    2016           1 :     tt_int_op(ret, OP_EQ, 1);
    2017             : 
    2018           1 :     service_clear_config(config1);
    2019           1 :     service_clear_config(config2);
    2020             :   }
    2021             : 
    2022             :   /* The numbers of clients in both configs are not equal. */
    2023             :   {
    2024           1 :     config1->clients = smartlist_new();
    2025           1 :     config2->clients = smartlist_new();
    2026             : 
    2027           1 :     hs_service_authorized_client_t *client1, *client2;
    2028           1 :     client1 = helper_create_authorized_client();
    2029           1 :     client2 = helper_create_authorized_client();
    2030             : 
    2031           1 :     smartlist_add(config1->clients, client1);
    2032           1 :     smartlist_add(config1->clients, client2);
    2033             : 
    2034           1 :     smartlist_add(config2->clients, helper_clone_authorized_client(client1));
    2035             : 
    2036           1 :     ret = service_authorized_client_config_equal(config1, config2);
    2037           1 :     tt_int_op(ret, OP_EQ, 0);
    2038             : 
    2039           1 :     service_clear_config(config1);
    2040           1 :     service_clear_config(config2);
    2041             :   }
    2042             : 
    2043             :   /* The first config has two distinct clients while the second config
    2044             :    * has two clients but they are duplicate. */
    2045             :   {
    2046           1 :     config1->clients = smartlist_new();
    2047           1 :     config2->clients = smartlist_new();
    2048             : 
    2049           1 :     hs_service_authorized_client_t *client1, *client2;
    2050           1 :     client1 = helper_create_authorized_client();
    2051           1 :     client2 = helper_create_authorized_client();
    2052             : 
    2053           1 :     smartlist_add(config1->clients, client1);
    2054           1 :     smartlist_add(config1->clients, client2);
    2055             : 
    2056           1 :     smartlist_add(config2->clients, helper_clone_authorized_client(client1));
    2057           1 :     smartlist_add(config2->clients, helper_clone_authorized_client(client1));
    2058             : 
    2059           1 :     ret = service_authorized_client_config_equal(config1, config2);
    2060           1 :     tt_int_op(ret, OP_EQ, 0);
    2061             : 
    2062           1 :     service_clear_config(config1);
    2063           1 :     service_clear_config(config2);
    2064             :   }
    2065             : 
    2066             :   /* Both configs have totally distinct clients. */
    2067             :   {
    2068           1 :     config1->clients = smartlist_new();
    2069           1 :     config2->clients = smartlist_new();
    2070             : 
    2071           1 :     hs_service_authorized_client_t *client1, *client2, *client3, *client4;
    2072           1 :     client1 = helper_create_authorized_client();
    2073           1 :     client2 = helper_create_authorized_client();
    2074           1 :     client3 = helper_create_authorized_client();
    2075           1 :     client4 = helper_create_authorized_client();
    2076             : 
    2077           1 :     smartlist_add(config1->clients, client1);
    2078           1 :     smartlist_add(config1->clients, client2);
    2079             : 
    2080           1 :     smartlist_add(config2->clients, client3);
    2081           1 :     smartlist_add(config2->clients, client4);
    2082             : 
    2083           1 :     ret = service_authorized_client_config_equal(config1, config2);
    2084           1 :     tt_int_op(ret, OP_EQ, 0);
    2085             : 
    2086           1 :     service_clear_config(config1);
    2087           1 :     service_clear_config(config2);
    2088             :   }
    2089             : 
    2090           1 :  done:
    2091           1 :   tor_free(config1);
    2092           1 :   tor_free(config2);
    2093           1 : }
    2094             : 
    2095             : /** Test that client circuit ID gets correctly exported */
    2096             : static void
    2097           1 : test_export_client_circuit_id(void *arg)
    2098             : {
    2099           1 :   origin_circuit_t *or_circ = NULL;
    2100           1 :   size_t sz;
    2101           1 :   char *cp1=NULL, *cp2=NULL;
    2102           1 :   connection_t *conn = NULL;
    2103             : 
    2104           1 :   (void) arg;
    2105             : 
    2106           1 :   MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock);
    2107             : 
    2108           1 :   hs_service_init();
    2109             : 
    2110             :   /* Create service */
    2111           1 :   hs_service_t *service = helper_create_service();
    2112             :   /* Check that export circuit ID detection works */
    2113           1 :   service->config.circuit_id_protocol = HS_CIRCUIT_ID_PROTOCOL_NONE;
    2114           1 :   tt_int_op(0, OP_EQ,
    2115             :             hs_service_exports_circuit_id(&service->keys.identity_pk));
    2116           1 :   service->config.circuit_id_protocol = HS_CIRCUIT_ID_PROTOCOL_HAPROXY;
    2117           1 :   tt_int_op(1, OP_EQ,
    2118             :             hs_service_exports_circuit_id(&service->keys.identity_pk));
    2119             : 
    2120             :   /* Create client connection */
    2121           1 :   conn = test_conn_get_connection(AP_CONN_STATE_CIRCUIT_WAIT, CONN_TYPE_AP, 0);
    2122             : 
    2123             :   /* Create client edge conn hs_ident */
    2124           1 :   edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
    2125           1 :   edge_conn->hs_ident = hs_ident_edge_conn_new(&service->keys.identity_pk);
    2126           1 :   edge_conn->hs_ident->orig_virtual_port = 42;
    2127             : 
    2128             :   /* Create rend circuit */
    2129           1 :   or_circ = origin_circuit_new();
    2130           1 :   or_circ->base_.purpose = CIRCUIT_PURPOSE_C_REND_JOINED;
    2131           1 :   edge_conn->on_circuit = TO_CIRCUIT(or_circ);
    2132           1 :   or_circ->global_identifier = 666;
    2133             : 
    2134             :   /* Export circuit ID */
    2135           1 :   export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol);
    2136             : 
    2137             :   /* Check contents */
    2138           1 :   cp1 = buf_get_contents(conn->outbuf, &sz);
    2139           1 :   tt_str_op(cp1, OP_EQ,
    2140             :             "PROXY TCP6 fc00:dead:beef:4dad::0:29a ::1 666 42\r\n");
    2141             : 
    2142             :   /* Change circ GID and see that the reported circuit ID also changes */
    2143           1 :   or_circ->global_identifier = 22;
    2144             : 
    2145             :   /* check changes */
    2146           1 :   export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol);
    2147           1 :   cp2 = buf_get_contents(conn->outbuf, &sz);
    2148           1 :   tt_str_op(cp1, OP_NE, cp2);
    2149           1 :   tor_free(cp1);
    2150             : 
    2151             :   /* Check that GID with UINT32_MAX works. */
    2152           1 :   or_circ->global_identifier = UINT32_MAX;
    2153             : 
    2154           1 :   export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol);
    2155           1 :   cp1 = buf_get_contents(conn->outbuf, &sz);
    2156           1 :   tt_str_op(cp1, OP_EQ,
    2157             :             "PROXY TCP6 fc00:dead:beef:4dad::ffff:ffff ::1 65535 42\r\n");
    2158           1 :   tor_free(cp1);
    2159             : 
    2160             :   /* Check that GID with UINT16_MAX works. */
    2161           1 :   or_circ->global_identifier = UINT16_MAX;
    2162             : 
    2163           1 :   export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol);
    2164           1 :   cp1 = buf_get_contents(conn->outbuf, &sz);
    2165           1 :   tt_str_op(cp1, OP_EQ,
    2166             :             "PROXY TCP6 fc00:dead:beef:4dad::0:ffff ::1 65535 42\r\n");
    2167           1 :   tor_free(cp1);
    2168             : 
    2169             :   /* Check that GID with UINT16_MAX + 7 works. */
    2170           1 :   or_circ->global_identifier = UINT16_MAX + 7;
    2171             : 
    2172           1 :   export_hs_client_circuit_id(edge_conn, service->config.circuit_id_protocol);
    2173           1 :   cp1 = buf_get_contents(conn->outbuf, &sz);
    2174           1 :   tt_str_op(cp1, OP_EQ, "PROXY TCP6 fc00:dead:beef:4dad::1:6 ::1 6 42\r\n");
    2175             : 
    2176           1 :  done:
    2177           1 :   UNMOCK(connection_write_to_buf_impl_);
    2178           1 :   circuit_free_(TO_CIRCUIT(or_circ));
    2179           1 :   connection_free_minimal(conn);
    2180           1 :   hs_service_free(service);
    2181           1 :   tor_free(cp1);
    2182           1 :   tor_free(cp2);
    2183           1 : }
    2184             : 
    2185             : static smartlist_t *
    2186           5 : mock_node_get_link_specifier_smartlist(const node_t *node, bool direct_conn)
    2187             : {
    2188           5 :   (void) node;
    2189           5 :   (void) direct_conn;
    2190             : 
    2191           5 :   smartlist_t *lspecs = smartlist_new();
    2192           5 :   link_specifier_t *ls_legacy = link_specifier_new();
    2193           5 :   smartlist_add(lspecs, ls_legacy);
    2194             : 
    2195           5 :   return lspecs;
    2196             : }
    2197             : 
    2198             : static node_t *fake_node = NULL;
    2199             : 
    2200             : static const node_t *
    2201           4 : mock_build_state_get_exit_node(cpath_build_state_t *state)
    2202             : {
    2203           4 :   (void) state;
    2204             : 
    2205           4 :   if (!fake_node) {
    2206           1 :     curve25519_secret_key_t seckey;
    2207           1 :     curve25519_secret_key_generate(&seckey, 0);
    2208             : 
    2209           1 :     fake_node = tor_malloc_zero(sizeof(node_t));
    2210           1 :     fake_node->ri = tor_malloc_zero(sizeof(routerinfo_t));
    2211           2 :     fake_node->ri->onion_curve25519_pkey =
    2212           1 :       tor_malloc_zero(sizeof(curve25519_public_key_t));
    2213           1 :     curve25519_public_key_generate(fake_node->ri->onion_curve25519_pkey,
    2214             :                                    &seckey);
    2215             :   }
    2216             : 
    2217           4 :   return fake_node;
    2218             : }
    2219             : 
    2220             : static void
    2221           4 : mock_launch_rendezvous_point_circuit(const hs_service_t *service,
    2222             :                                      const hs_service_intro_point_t *ip,
    2223             :                                      const hs_cell_introduce2_data_t *data)
    2224             : {
    2225           4 :   (void) service;
    2226           4 :   (void) ip;
    2227           4 :   (void) data;
    2228           4 :   return;
    2229             : }
    2230             : 
    2231             : /**
    2232             :  *  Test that INTRO2 cells are handled well by onion services in the normal
    2233             :  *  case and also when onionbalance is enabled.
    2234             :  */
    2235             : static void
    2236           1 : test_intro2_handling(void *arg)
    2237             : {
    2238           1 :   (void)arg;
    2239             : 
    2240           1 :   MOCK(build_state_get_exit_node, mock_build_state_get_exit_node);
    2241           1 :   MOCK(relay_send_command_from_edge_, mock_relay_send_command_from_edge);
    2242           1 :   MOCK(node_get_link_specifier_smartlist,
    2243             :        mock_node_get_link_specifier_smartlist);
    2244           1 :   MOCK(launch_rendezvous_point_circuit, mock_launch_rendezvous_point_circuit);
    2245             : 
    2246           1 :   memset(relay_payload, 0, sizeof(relay_payload));
    2247             : 
    2248           1 :   int retval;
    2249           1 :   time_t now = 0101010101;
    2250           1 :   update_approx_time(now);
    2251             : 
    2252             :   /** OK this is the play:
    2253             :    *
    2254             :    *  In Act I, we have a standalone onion service X (without onionbalance
    2255             :    *  enabled). We test that X can properly handle INTRO2 cells sent by a
    2256             :    *  client Alice.
    2257             :    *
    2258             :    *  In Act II, we create an onionbalance setup with frontend being Z which
    2259             :    *  includes instances X and Y. We then setup onionbalance on X and test that
    2260             :    *  Alice who addresses Z can communicate with X through INTRO2 cells.
    2261             :    *
    2262             :    *  In Act III, we test that Alice can also communicate with X
    2263             :    *  directly even tho onionbalance is enabled.
    2264             :    *
    2265             :    *  And finally in Act IV, we check various cases where the INTRO2 cell
    2266             :    *  should not go through because the subcredentials don't line up
    2267             :    *  (e.g. Alice sends INTRO2 to X using Y's subcredential).
    2268             :    */
    2269             : 
    2270             :   /** Let's start with some setup! Create the instances and the frontend
    2271             :       service, create Alice, etc:  */
    2272             : 
    2273             :   /* Create instance X */
    2274           1 :   hs_service_t x_service;
    2275           1 :   memset(&x_service, 0, sizeof(hs_service_t));
    2276             :   /* Disable onionbalance */
    2277           1 :   x_service.config.ob_master_pubkeys = NULL;
    2278           1 :   x_service.state.replay_cache_rend_cookie = replaycache_new(0,0);
    2279             : 
    2280             :   /* Create subcredential for x: */
    2281           1 :   ed25519_keypair_t x_identity_keypair;
    2282           1 :   hs_subcredential_t x_subcred;
    2283           1 :   ed25519_keypair_generate(&x_identity_keypair, 0);
    2284           1 :   hs_helper_get_subcred_from_identity_keypair(&x_identity_keypair,
    2285             :                                               &x_subcred);
    2286             : 
    2287             :   /* Create the x instance's intro point */
    2288           1 :   hs_service_intro_point_t *x_ip = NULL;
    2289             :   {
    2290           1 :     curve25519_secret_key_t seckey;
    2291           1 :     curve25519_public_key_t pkey;
    2292           1 :     curve25519_secret_key_generate(&seckey, 0);
    2293           1 :     curve25519_public_key_generate(&pkey, &seckey);
    2294             : 
    2295           1 :     node_t intro_node;
    2296           1 :     memset(&intro_node, 0, sizeof(intro_node));
    2297           1 :     routerinfo_t ri;
    2298           1 :     memset(&ri, 0, sizeof(routerinfo_t));
    2299           1 :     ri.onion_curve25519_pkey = &pkey;
    2300           1 :     intro_node.ri = &ri;
    2301             : 
    2302           1 :     x_ip = service_intro_point_new(&intro_node);
    2303             :   }
    2304             : 
    2305             :   /* Create z frontend's subcredential */
    2306           1 :   ed25519_keypair_t z_identity_keypair;
    2307           1 :   hs_subcredential_t z_subcred;
    2308           1 :   ed25519_keypair_generate(&z_identity_keypair, 0);
    2309           1 :   hs_helper_get_subcred_from_identity_keypair(&z_identity_keypair,
    2310             :                                               &z_subcred);
    2311             : 
    2312             :   /* Create y instance's subcredential */
    2313           1 :   ed25519_keypair_t y_identity_keypair;
    2314           1 :   hs_subcredential_t y_subcred;
    2315           1 :   ed25519_keypair_generate(&y_identity_keypair, 0);
    2316           1 :   hs_helper_get_subcred_from_identity_keypair(&y_identity_keypair,
    2317             :                                               &y_subcred);
    2318             : 
    2319             :   /* Create Alice's intro point */
    2320           1 :   hs_desc_intro_point_t *alice_ip;
    2321           1 :   ed25519_keypair_t signing_kp;
    2322           1 :   ed25519_keypair_generate(&signing_kp, 0);
    2323           2 :   alice_ip = hs_helper_build_intro_point(&signing_kp, now, "1.2.3.4", 0,
    2324           1 :                                          &x_ip->auth_key_kp,
    2325           1 :                                          &x_ip->enc_key_kp);
    2326             : 
    2327             :   /* Create Alice's intro and rend circuits */
    2328           1 :   origin_circuit_t *intro_circ = origin_circuit_new();
    2329           1 :   intro_circ->cpath = tor_malloc_zero(sizeof(crypt_path_t));
    2330           1 :   intro_circ->cpath->prev = intro_circ->cpath;
    2331           1 :   intro_circ->hs_ident = tor_malloc_zero(sizeof(*intro_circ->hs_ident));
    2332           1 :   origin_circuit_t rend_circ;
    2333           1 :   rend_circ.hs_ident = tor_malloc_zero(sizeof(*rend_circ.hs_ident));
    2334           1 :   curve25519_keypair_generate(&rend_circ.hs_ident->rendezvous_client_kp, 0);
    2335           1 :   memset(rend_circ.hs_ident->rendezvous_cookie, 'r', HS_REND_COOKIE_LEN);
    2336             : 
    2337             :   /* ************************************************************ */
    2338             : 
    2339             :   /* Act I:
    2340             :    *
    2341             :    * Where Alice connects to X without onionbalance in the picture */
    2342             : 
    2343             :   /* Create INTRODUCE1 */
    2344           1 :   tt_assert(fast_mem_is_zero(relay_payload, sizeof(relay_payload)));
    2345           1 :   retval = hs_circ_send_introduce1(intro_circ, &rend_circ,
    2346             :                                    alice_ip, &x_subcred);
    2347             : 
    2348             :   /* Check that the payload was written successfully */
    2349           1 :   tt_int_op(retval, OP_EQ, 0);
    2350           1 :   tt_assert(!fast_mem_is_zero(relay_payload, sizeof(relay_payload)));
    2351           1 :   tt_int_op(relay_payload_len, OP_NE, 0);
    2352             : 
    2353             :   /* Handle the cell */
    2354           1 :   retval = hs_circ_handle_introduce2(&x_service,
    2355             :                                     intro_circ, x_ip,
    2356             :                                     &x_subcred,
    2357             :                                     (uint8_t*)relay_payload,relay_payload_len);
    2358           1 :   tt_int_op(retval, OP_EQ, 0);
    2359             : 
    2360             :   /* ************************************************************ */
    2361             : 
    2362             :   /* Act II:
    2363             :    *
    2364             :    * We now create an onionbalance setup with Z being the frontend and X and Y
    2365             :    * being the backend instances. Make sure that Alice can talk with the
    2366             :    * backend instance X even tho she thinks she is talking to the frontend Z.
    2367             :    */
    2368             : 
    2369             :   /* Now configure the X instance to do onionbalance with Z as the frontend */
    2370           1 :   x_service.config.ob_master_pubkeys = smartlist_new();
    2371           1 :   smartlist_add(x_service.config.ob_master_pubkeys,
    2372             :                 &z_identity_keypair.pubkey);
    2373             : 
    2374             :   /* Create descriptors for x and load next descriptor with the x's
    2375             :    * subcredential so that it can accept connections for itself. */
    2376           1 :   x_service.desc_current = service_descriptor_new();
    2377           1 :   memset(x_service.desc_current->desc->subcredential.subcred, 'C',SUBCRED_LEN);
    2378           1 :   x_service.desc_next = service_descriptor_new();
    2379           1 :   memcpy(&x_service.desc_next->desc->subcredential, &x_subcred, SUBCRED_LEN);
    2380             : 
    2381             :   /* Refresh OB keys */
    2382           1 :   hs_ob_refresh_keys(&x_service);
    2383             : 
    2384             :   /* Create INTRODUCE1 from Alice to X through Z */
    2385           1 :   memset(relay_payload, 0, sizeof(relay_payload));
    2386           1 :   retval = hs_circ_send_introduce1(intro_circ, &rend_circ,
    2387             :                                    alice_ip, &z_subcred);
    2388             : 
    2389             :   /* Check that the payload was written successfully */
    2390           1 :   tt_int_op(retval, OP_EQ, 0);
    2391           1 :   tt_assert(!fast_mem_is_zero(relay_payload, sizeof(relay_payload)));
    2392           1 :   tt_int_op(relay_payload_len, OP_NE, 0);
    2393             : 
    2394             :   /* Deliver INTRODUCE1 to X even tho it carries Z's subcredential */
    2395           1 :   replaycache_free(x_service.state.replay_cache_rend_cookie);
    2396           1 :   x_service.state.replay_cache_rend_cookie = replaycache_new(0, 0);
    2397             : 
    2398           1 :   retval = hs_circ_handle_introduce2(&x_service,
    2399             :                                    intro_circ, x_ip,
    2400             :                                    &z_subcred,
    2401             :                                    (uint8_t*)relay_payload, relay_payload_len);
    2402           1 :   tt_int_op(retval, OP_EQ, 0);
    2403             : 
    2404           1 :   replaycache_free(x_ip->replay_cache);
    2405           1 :   x_ip->replay_cache = replaycache_new(0, 0);
    2406             : 
    2407           1 :   replaycache_free(x_service.state.replay_cache_rend_cookie);
    2408           1 :   x_service.state.replay_cache_rend_cookie = replaycache_new(0, 0);
    2409             : 
    2410             :   /* ************************************************************ */
    2411             : 
    2412             :   /* Act III:
    2413             :    *
    2414             :    * Now send a direct INTRODUCE cell from Alice to X using X's subcredential
    2415             :    * and check that it succeeds even with onionbalance enabled.
    2416             :    */
    2417             : 
    2418             :   /* Refresh OB keys (just to check for memleaks) */
    2419           1 :   hs_ob_refresh_keys(&x_service);
    2420             : 
    2421             :   /* Create INTRODUCE1 from Alice to X using X's subcred. */
    2422           1 :   memset(relay_payload, 0, sizeof(relay_payload));
    2423           1 :   retval = hs_circ_send_introduce1(intro_circ, &rend_circ,
    2424             :                                    alice_ip, &x_subcred);
    2425             : 
    2426             :   /* Check that the payload was written successfully */
    2427           1 :   tt_int_op(retval, OP_EQ, 0);
    2428           1 :   tt_assert(!fast_mem_is_zero(relay_payload, sizeof(relay_payload)));
    2429           1 :   tt_int_op(relay_payload_len, OP_NE, 0);
    2430             : 
    2431             :   /* Send INTRODUCE1 to X with X's subcredential (should succeed) */
    2432           1 :   replaycache_free(x_service.state.replay_cache_rend_cookie);
    2433           1 :   x_service.state.replay_cache_rend_cookie = replaycache_new(0, 0);
    2434             : 
    2435           1 :   retval = hs_circ_handle_introduce2(&x_service,
    2436             :                                    intro_circ, x_ip,
    2437             :                                    &x_subcred,
    2438             :                                    (uint8_t*)relay_payload, relay_payload_len);
    2439           1 :   tt_int_op(retval, OP_EQ, 0);
    2440             : 
    2441             :   /* ************************************************************ */
    2442             : 
    2443             :   /* Act IV:
    2444             :    *
    2445             :    * Test cases where the INTRO2 cell should not be able to decode.
    2446             :    */
    2447             : 
    2448             :   /* Try sending the exact same INTRODUCE2 cell again and see that the intro
    2449             :    * point replay cache triggers: */
    2450           1 :   setup_full_capture_of_logs(LOG_WARN);
    2451           1 :   retval = hs_circ_handle_introduce2(&x_service,
    2452             :                                    intro_circ, x_ip,
    2453             :                                    &x_subcred,
    2454             :                                    (uint8_t*)relay_payload, relay_payload_len);
    2455           1 :   tt_int_op(retval, OP_EQ, -1);
    2456           1 :   expect_log_msg_containing("with the same ENCRYPTED section");
    2457           1 :   teardown_capture_of_logs();
    2458             : 
    2459             :   /* Now cleanup the intro point replay cache but not the service replay cache
    2460             :      and see that this one triggers this time. */
    2461           1 :   replaycache_free(x_ip->replay_cache);
    2462           1 :   x_ip->replay_cache = replaycache_new(0, 0);
    2463           1 :   setup_full_capture_of_logs(LOG_INFO);
    2464           1 :   retval = hs_circ_handle_introduce2(&x_service,
    2465             :                                    intro_circ, x_ip,
    2466             :                                    &x_subcred,
    2467             :                                    (uint8_t*)relay_payload, relay_payload_len);
    2468           1 :   tt_int_op(retval, OP_EQ, -1);
    2469           1 :   expect_log_msg_containing("with same REND_COOKIE");
    2470           1 :   teardown_capture_of_logs();
    2471             : 
    2472             :   /* Now just to make sure cleanup both replay caches and make sure that the
    2473             :      cell gets through */
    2474           1 :   replaycache_free(x_ip->replay_cache);
    2475           1 :   x_ip->replay_cache = replaycache_new(0, 0);
    2476           1 :   replaycache_free(x_service.state.replay_cache_rend_cookie);
    2477           1 :   x_service.state.replay_cache_rend_cookie = replaycache_new(0, 0);
    2478           1 :   retval = hs_circ_handle_introduce2(&x_service,
    2479             :                                    intro_circ, x_ip,
    2480             :                                    &x_subcred,
    2481             :                                    (uint8_t*)relay_payload, relay_payload_len);
    2482           1 :   tt_int_op(retval, OP_EQ, 0);
    2483             : 
    2484             :   /* As a final thing, create an INTRODUCE1 cell from Alice to X using Y's
    2485             :    * subcred (should fail since Y is just another instance and not the frontend
    2486             :    * service!) */
    2487           1 :   memset(relay_payload, 0, sizeof(relay_payload));
    2488           1 :   retval = hs_circ_send_introduce1(intro_circ, &rend_circ,
    2489             :                                    alice_ip, &y_subcred);
    2490           1 :   tt_int_op(retval, OP_EQ, 0);
    2491             : 
    2492             :   /* Check that the payload was written successfully */
    2493           1 :   tt_assert(!fast_mem_is_zero(relay_payload, sizeof(relay_payload)));
    2494           1 :   tt_int_op(relay_payload_len, OP_NE, 0);
    2495             : 
    2496           1 :   retval = hs_circ_handle_introduce2(&x_service,
    2497             :                                    intro_circ, x_ip,
    2498             :                                    &y_subcred,
    2499             :                                    (uint8_t*)relay_payload, relay_payload_len);
    2500           1 :   tt_int_op(retval, OP_EQ, -1);
    2501             : 
    2502           1 :  done:
    2503             :   /* Start cleaning up X */
    2504           1 :   replaycache_free(x_service.state.replay_cache_rend_cookie);
    2505           1 :   smartlist_free(x_service.config.ob_master_pubkeys);
    2506           1 :   tor_free(x_service.state.ob_subcreds);
    2507           1 :   service_descriptor_free(x_service.desc_current);
    2508           1 :   service_descriptor_free(x_service.desc_next);
    2509           1 :   service_intro_point_free(x_ip);
    2510             : 
    2511             :   /* Clean up Alice */
    2512           1 :   hs_desc_intro_point_free(alice_ip);
    2513           1 :   tor_free(rend_circ.hs_ident);
    2514             : 
    2515           1 :   if (fake_node) {
    2516           1 :     tor_free(fake_node->ri->onion_curve25519_pkey);
    2517           1 :     tor_free(fake_node->ri);
    2518           1 :     tor_free(fake_node);
    2519             :   }
    2520             : 
    2521           1 :   UNMOCK(build_state_get_exit_node);
    2522           1 :   UNMOCK(relay_send_command_from_edge_);
    2523           1 :   UNMOCK(node_get_link_specifier_smartlist);
    2524           1 :   UNMOCK(launch_rendezvous_point_circuit);
    2525           1 : }
    2526             : 
    2527             : static void
    2528           1 : test_cannot_upload_descriptors(void *arg)
    2529             : {
    2530           1 :   int ret;
    2531           1 :   time_t now;
    2532           1 :   hs_service_t *service;
    2533             : 
    2534           1 :   (void) arg;
    2535             : 
    2536           1 :   hs_init();
    2537           1 :   MOCK(get_or_state,
    2538             :        get_or_state_replacement);
    2539           1 :   MOCK(networkstatus_get_reasonably_live_consensus,
    2540             :        mock_networkstatus_get_reasonably_live_consensus);
    2541             : 
    2542           1 :   dummy_state = or_state_new();
    2543             : 
    2544           1 :   ret = parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
    2545             :                            &mock_ns.valid_after);
    2546           1 :   tt_int_op(ret, OP_EQ, 0);
    2547           1 :   ret = parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
    2548             :                            &mock_ns.fresh_until);
    2549           1 :   tt_int_op(ret, OP_EQ, 0);
    2550           1 :   dirauth_sched_recalculate_timing(get_options(), mock_ns.valid_after);
    2551             : 
    2552           1 :   update_approx_time(mock_ns.valid_after + 1);
    2553           1 :   now = mock_ns.valid_after + 1;
    2554             : 
    2555             :   /* Create a service with no descriptor. It's added to the global map. */
    2556           1 :   service = hs_service_new(get_options());
    2557           1 :   tt_assert(service);
    2558           1 :   service->config.version = HS_VERSION_THREE;
    2559           1 :   ed25519_secret_key_generate(&service->keys.identity_sk, 0);
    2560           1 :   ed25519_public_key_generate(&service->keys.identity_pk,
    2561             :                               &service->keys.identity_sk);
    2562             :   /* Register service to global map. */
    2563           1 :   ret = register_service(get_hs_service_map(), service);
    2564           1 :   tt_int_op(ret, OP_EQ, 0);
    2565             :   /* But first, build our descriptor. */
    2566           1 :   build_all_descriptors(now);
    2567             : 
    2568             :   /* 1. Testing missing intro points reason. */
    2569             :   {
    2570           1 :     digest256map_t *cur = service->desc_current->intro_points.map;
    2571           1 :     digest256map_t *tmp = digest256map_new();
    2572           1 :     service->desc_current->intro_points.map = tmp;
    2573           1 :     service->desc_current->missing_intro_points = 1;
    2574           1 :     setup_full_capture_of_logs(LOG_INFO);
    2575           1 :     run_upload_descriptor_event(now);
    2576           1 :     digest256map_free(tmp, tor_free_);
    2577           1 :     service->desc_current->intro_points.map = cur;
    2578           1 :     expect_log_msg_containing(
    2579             :       "Service [scrubbed] can't upload its current descriptor: "
    2580           1 :       "Missing intro points");
    2581           1 :     teardown_capture_of_logs();
    2582             :     /* Reset. */
    2583           1 :     service->desc_current->missing_intro_points = 0;
    2584             :   }
    2585             : 
    2586             :   /* 2. Testing non established intro points. */
    2587             :   {
    2588           1 :     setup_full_capture_of_logs(LOG_INFO);
    2589           1 :     run_upload_descriptor_event(now);
    2590           1 :     expect_log_msg_containing(
    2591             :       "Service [scrubbed] can't upload its current descriptor: "
    2592           1 :       "Intro circuits aren't yet all established (0/3).");
    2593           1 :     teardown_capture_of_logs();
    2594             :   }
    2595             : 
    2596             :   /* We need to pass the established circuit tests and thus from now on, we
    2597             :    * MOCK this to return 3 intro points. */
    2598           1 :   MOCK(count_desc_circuit_established, mock_count_desc_circuit_established);
    2599           1 :   num_intro_points = 3;
    2600             : 
    2601             :   /* 3. Testing non established intro points. */
    2602             :   {
    2603           1 :     service->desc_current->next_upload_time = now + 1000;
    2604           1 :     setup_full_capture_of_logs(LOG_INFO);
    2605           1 :     run_upload_descriptor_event(now);
    2606           1 :     expect_log_msg_containing(
    2607             :       "Service [scrubbed] can't upload its current descriptor: "
    2608           1 :       "Next upload time is");
    2609           1 :     teardown_capture_of_logs();
    2610             :     /* Reset. */
    2611           1 :     service->desc_current->next_upload_time = 0;
    2612             :   }
    2613             : 
    2614             :   /* 4. Testing missing live consensus. */
    2615             :   {
    2616           1 :     MOCK(networkstatus_get_reasonably_live_consensus,
    2617             :          mock_networkstatus_get_reasonably_live_consensus_null);
    2618           1 :     setup_full_capture_of_logs(LOG_INFO);
    2619           1 :     run_upload_descriptor_event(now);
    2620           1 :     expect_log_msg_containing(
    2621             :       "Service [scrubbed] can't upload its current descriptor: "
    2622           1 :       "No reasonably live consensus");
    2623           1 :     teardown_capture_of_logs();
    2624             :     /* Reset. */
    2625           1 :     MOCK(networkstatus_get_reasonably_live_consensus,
    2626             :          mock_networkstatus_get_reasonably_live_consensus);
    2627             :   }
    2628             : 
    2629             :   /* 5. Test missing minimum directory information. */
    2630             :   {
    2631           1 :     MOCK(router_have_minimum_dir_info,
    2632             :          mock_router_have_minimum_dir_info_false);
    2633           1 :     setup_full_capture_of_logs(LOG_INFO);
    2634           1 :     run_upload_descriptor_event(now);
    2635           1 :     expect_log_msg_containing(
    2636             :       "Service [scrubbed] can't upload its current descriptor: "
    2637           1 :       "Not enough directory information");
    2638           1 :     teardown_capture_of_logs();
    2639             : 
    2640             :     /* Running it again shouldn't trigger anything due to rate limitation. */
    2641           1 :     setup_full_capture_of_logs(LOG_INFO);
    2642           1 :     run_upload_descriptor_event(now);
    2643           1 :     expect_no_log_entry();
    2644           1 :     teardown_capture_of_logs();
    2645           1 :     UNMOCK(router_have_minimum_dir_info);
    2646             :   }
    2647             : 
    2648             :   /* Increase time and redo test (5) in order to test the rate limiting. */
    2649           1 :   update_approx_time(mock_ns.valid_after + 61);
    2650             :   {
    2651           1 :     MOCK(router_have_minimum_dir_info,
    2652             :          mock_router_have_minimum_dir_info_false);
    2653           1 :     setup_full_capture_of_logs(LOG_INFO);
    2654           1 :     run_upload_descriptor_event(now);
    2655           1 :     expect_log_msg_containing(
    2656             :       "Service [scrubbed] can't upload its current descriptor: "
    2657           1 :       "Not enough directory information");
    2658           1 :     teardown_capture_of_logs();
    2659           1 :     UNMOCK(router_have_minimum_dir_info);
    2660             :   }
    2661             : 
    2662           1 :  done:
    2663           1 :   hs_free_all();
    2664           1 :   UNMOCK(count_desc_circuit_established);
    2665           1 :   UNMOCK(networkstatus_get_reasonably_live_consensus);
    2666           1 :   UNMOCK(get_or_state);
    2667           1 : }
    2668             : 
    2669             : struct testcase_t hs_service_tests[] = {
    2670             :   { "e2e_rend_circuit_setup", test_e2e_rend_circuit_setup, TT_FORK,
    2671             :     NULL, NULL },
    2672             :   { "load_keys", test_load_keys, TT_FORK,
    2673             :     NULL, NULL },
    2674             :   { "client_filename_is_valid", test_client_filename_is_valid, TT_FORK,
    2675             :     NULL, NULL },
    2676             :   { "parse_authorized_client", test_parse_authorized_client, TT_FORK,
    2677             :     NULL, NULL },
    2678             :   { "load_keys_with_client_auth", test_load_keys_with_client_auth, TT_FORK,
    2679             :     NULL, NULL },
    2680             :   { "access_service", test_access_service, TT_FORK,
    2681             :     NULL, NULL },
    2682             :   { "service_intro_point", test_service_intro_point, TT_FORK,
    2683             :     NULL, NULL },
    2684             :   { "helper_functions", test_helper_functions, TT_FORK,
    2685             :     NULL, NULL },
    2686             :   { "intro_circuit_opened", test_intro_circuit_opened, TT_FORK,
    2687             :     NULL, NULL },
    2688             :   { "intro_established", test_intro_established, TT_FORK,
    2689             :     NULL, NULL },
    2690             :   { "closing_intro_circs", test_closing_intro_circs, TT_FORK,
    2691             :     NULL, NULL },
    2692             :   { "rdv_circuit_opened", test_rdv_circuit_opened, TT_FORK,
    2693             :     NULL, NULL },
    2694             :   { "bad_introduce2", test_bad_introduce2, TT_FORK,
    2695             :     NULL, NULL },
    2696             :   { "service_event", test_service_event, TT_FORK,
    2697             :     NULL, NULL },
    2698             :   { "rotate_descriptors", test_rotate_descriptors, TT_FORK,
    2699             :     NULL, NULL },
    2700             :   { "build_update_descriptors", test_build_update_descriptors, TT_FORK,
    2701             :     NULL, NULL },
    2702             :   { "build_descriptors", test_build_descriptors, TT_FORK,
    2703             :     NULL, NULL },
    2704             :   { "upload_descriptors", test_upload_descriptors, TT_FORK,
    2705             :     NULL, NULL },
    2706             :   { "cannot_upload_descriptors", test_cannot_upload_descriptors, TT_FORK,
    2707             :     NULL, NULL },
    2708             :   { "rendezvous1_parsing", test_rendezvous1_parsing, TT_FORK,
    2709             :     NULL, NULL },
    2710             :   { "authorized_client_config_equal", test_authorized_client_config_equal,
    2711             :     TT_FORK, NULL, NULL },
    2712             :   { "export_client_circuit_id", test_export_client_circuit_id, TT_FORK,
    2713             :     NULL, NULL },
    2714             :   { "intro2_handling", test_intro2_handling, TT_FORK, NULL, NULL },
    2715             : 
    2716             :   END_OF_TESTCASES
    2717             : };

Generated by: LCOV version 1.14