tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

shared_random_client.c (10810B)


      1 /* Copyright (c) 2018-2021, The Tor Project, Inc. */
      2 /* See LICENSE for licensing information */
      3 
      4 /**
      5 * \file shared_random_client.c
      6 * \brief This file contains functions that are from the shared random
      7 *        subsystem but used by many part of tor. The full feature is built
      8 *        as part of the dirauth module.
      9 **/
     10 
     11 #include "feature/hs_common/shared_random_client.h"
     12 
     13 #include "app/config/config.h"
     14 #include "feature/dirauth/authmode.h"
     15 #include "feature/dirauth/voting_schedule.h"
     16 #include "feature/nodelist/microdesc.h"
     17 #include "feature/nodelist/networkstatus.h"
     18 #include "lib/encoding/binascii.h"
     19 
     20 #include "feature/nodelist/networkstatus_st.h"
     21 
     22 /** Convert a given srv object to a string for the control port. This doesn't
     23 * fail and the srv object MUST be valid. */
     24 static char *
     25 srv_to_control_string(const sr_srv_t *srv)
     26 {
     27  char *srv_str;
     28  char srv_hash_encoded[SR_SRV_VALUE_BASE64_LEN + 1];
     29  tor_assert(srv);
     30 
     31  sr_srv_encode(srv_hash_encoded, sizeof(srv_hash_encoded), srv);
     32  tor_asprintf(&srv_str, "%s", srv_hash_encoded);
     33  return srv_str;
     34 }
     35 
     36 /**
     37 * If we have no consensus and we are not an authority, assume that this is the
     38 * voting interval. This can be used while bootstrapping as a relay and we are
     39 * asked to initialize HS stats (see rep_hist_hs_stats_init()) */
     40 #define DEFAULT_NETWORK_VOTING_INTERVAL (3600)
     41 #define TESTING_DEFAULT_NETWORK_VOTING_INTERVAL (20)
     42 
     43 /* This is an unpleasing workaround for tests.  Our unit tests assume that we
     44 * are scheduling all of our shared random stuff as if we were a directory
     45 * authority, but they do not always set V3AuthoritativeDir.
     46 */
     47 #ifdef TOR_UNIT_TESTS
     48 #define ASSUME_AUTHORITY_SCHEDULING 1
     49 #else
     50 #define ASSUME_AUTHORITY_SCHEDULING 0
     51 #endif
     52 
     53 /** Return the voting interval of the tor vote subsystem. */
     54 int
     55 get_voting_interval(void)
     56 {
     57  int interval;
     58  networkstatus_t *consensus =
     59    networkstatus_get_reasonably_live_consensus(time(NULL),
     60                                                usable_consensus_flavor());
     61 
     62  if (consensus) {
     63    /* Ideally we have a live consensus and we can just use that. */
     64    interval = (int)(consensus->fresh_until - consensus->valid_after);
     65  } else if (authdir_mode(get_options()) || ASSUME_AUTHORITY_SCHEDULING) {
     66    /* If we don't have a live consensus and we're an authority,
     67     * we should believe our own view of what the schedule ought to be. */
     68    interval = dirauth_sched_get_configured_interval();
     69  } else if ((consensus = networkstatus_get_latest_consensus())) {
     70    /* If we're a client, then maybe a latest consensus is good enough?
     71     * It's better than falling back to the non-consensus case. */
     72    interval = (int)(consensus->fresh_until - consensus->valid_after);
     73  } else {
     74    /* We can reach this as a relay when bootstrapping and we are asked to
     75     * initialize HS stats (see rep_hist_hs_stats_init()). */
     76    if (get_options()->TestingTorNetwork) {
     77      interval = TESTING_DEFAULT_NETWORK_VOTING_INTERVAL;
     78    } else {
     79      interval = DEFAULT_NETWORK_VOTING_INTERVAL;
     80    }
     81  }
     82  tor_assert(interval > 0);
     83  return interval;
     84 }
     85 
     86 /*
     87 * Public API
     88 */
     89 
     90 /** Encode the given shared random value and put it in dst. Destination
     91 * buffer must be at least SR_SRV_VALUE_BASE64_LEN plus the NULL byte. */
     92 void
     93 sr_srv_encode(char *dst, size_t dst_len, const sr_srv_t *srv)
     94 {
     95  int ret;
     96  /* Extra byte for the NULL terminated char. */
     97  char buf[SR_SRV_VALUE_BASE64_LEN + 1];
     98 
     99  tor_assert(dst);
    100  tor_assert(srv);
    101  tor_assert(dst_len >= sizeof(buf));
    102 
    103  ret = base64_encode(buf, sizeof(buf), (const char *) srv->value,
    104                      sizeof(srv->value), 0);
    105  /* Always expect the full length without the NULL byte. */
    106  tor_assert(ret == (sizeof(buf) - 1));
    107  tor_assert(ret <= (int) dst_len);
    108  strlcpy(dst, buf, dst_len);
    109 }
    110 
    111 /** Return the current SRV string representation for the control port. Return a
    112 * newly allocated string on success containing the value else "" if not found
    113 * or if we don't have a valid consensus yet. */
    114 char *
    115 sr_get_current_for_control(void)
    116 {
    117  char *srv_str;
    118  const networkstatus_t *c = networkstatus_get_latest_consensus();
    119  if (c && c->sr_info.current_srv) {
    120    srv_str = srv_to_control_string(c->sr_info.current_srv);
    121  } else {
    122    srv_str = tor_strdup("");
    123  }
    124  return srv_str;
    125 }
    126 
    127 /** Return the previous SRV string representation for the control port. Return
    128 * a newly allocated string on success containing the value else "" if not
    129 * found or if we don't have a valid consensus yet. */
    130 char *
    131 sr_get_previous_for_control(void)
    132 {
    133  char *srv_str;
    134  const networkstatus_t *c = networkstatus_get_latest_consensus();
    135  if (c && c->sr_info.previous_srv) {
    136    srv_str = srv_to_control_string(c->sr_info.previous_srv);
    137  } else {
    138    srv_str = tor_strdup("");
    139  }
    140  return srv_str;
    141 }
    142 
    143 /** Return current shared random value from the latest consensus. Caller can
    144 * NOT keep a reference to the returned pointer. Return NULL if none. */
    145 const sr_srv_t *
    146 sr_get_current(const networkstatus_t *ns)
    147 {
    148  const networkstatus_t *consensus;
    149 
    150  /* Use provided ns else get a live one */
    151  if (ns) {
    152    consensus = ns;
    153  } else {
    154    consensus = networkstatus_get_reasonably_live_consensus(approx_time(),
    155                                                  usable_consensus_flavor());
    156  }
    157  /* Ideally we would never be asked for an SRV without a live consensus. Make
    158   * sure this assumption is correct. */
    159  tor_assert_nonfatal(consensus);
    160 
    161  if (consensus) {
    162    return consensus->sr_info.current_srv;
    163  }
    164  return NULL;
    165 }
    166 
    167 /** Return previous shared random value from the latest consensus. Caller can
    168 * NOT keep a reference to the returned pointer. Return NULL if none. */
    169 const sr_srv_t *
    170 sr_get_previous(const networkstatus_t *ns)
    171 {
    172  const networkstatus_t *consensus;
    173 
    174  /* Use provided ns else get a live one */
    175  if (ns) {
    176    consensus = ns;
    177  } else {
    178    consensus = networkstatus_get_reasonably_live_consensus(approx_time(),
    179                                                  usable_consensus_flavor());
    180  }
    181  /* Ideally we would never be asked for an SRV without a live consensus. Make
    182   * sure this assumption is correct. */
    183  tor_assert_nonfatal(consensus);
    184 
    185  if (consensus) {
    186    return consensus->sr_info.previous_srv;
    187  }
    188  return NULL;
    189 }
    190 
    191 /** Parse a list of arguments from a SRV value either from a vote, consensus
    192 * or from our disk state and return a newly allocated srv object. NULL is
    193 * returned on error.
    194 *
    195 * The arguments' order:
    196 *    num_reveals, value
    197 */
    198 sr_srv_t *
    199 sr_parse_srv(const smartlist_t *args)
    200 {
    201  char *value;
    202  int ok, ret;
    203  uint64_t num_reveals;
    204  sr_srv_t *srv = NULL;
    205 
    206  tor_assert(args);
    207 
    208  if (smartlist_len(args) < 2) {
    209    goto end;
    210  }
    211 
    212  /* First argument is the number of reveal values */
    213  num_reveals = tor_parse_uint64(smartlist_get(args, 0),
    214                                 10, 0, UINT64_MAX, &ok, NULL);
    215  if (!ok) {
    216    goto end;
    217  }
    218  /* Second and last argument is the shared random value it self. */
    219  value = smartlist_get(args, 1);
    220  if (strlen(value) != SR_SRV_VALUE_BASE64_LEN) {
    221    goto end;
    222  }
    223 
    224  srv = tor_malloc_zero(sizeof(*srv));
    225  srv->num_reveals = num_reveals;
    226  /* We subtract one byte from the srclen because the function ignores the
    227   * '=' character in the given buffer. This is broken but it's a documented
    228   * behavior of the implementation. */
    229  ret = base64_decode((char *) srv->value, sizeof(srv->value), value,
    230                      SR_SRV_VALUE_BASE64_LEN - 1);
    231  if (ret != sizeof(srv->value)) {
    232    tor_free(srv);
    233    srv = NULL;
    234    goto end;
    235  }
    236 end:
    237  return srv;
    238 }
    239 
    240 /** Return the start time of the current SR protocol run using the times from
    241 *  the current consensus. For example, if the latest consensus valid-after is
    242 *  23/06/2017 23:00:00 and a full SR protocol run is 24 hours, this function
    243 *  returns 23/06/2017 00:00:00. */
    244 time_t
    245 sr_state_get_start_time_of_current_protocol_run(void)
    246 {
    247  int total_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
    248  int voting_interval = get_voting_interval();
    249  time_t beginning_of_curr_round;
    250 
    251  /* This function is not used for voting purposes, so if we have a reasonably
    252   * live consensus, use its valid-after as the beginning of the current
    253   * round. If we have no consensus but we're an authority, use our own
    254   * schedule. Otherwise, try using our view of the voting interval to figure
    255   * out when the current round _should_ be starting. */
    256  networkstatus_t *ns =
    257    networkstatus_get_reasonably_live_consensus(approx_time(),
    258                                                usable_consensus_flavor());
    259  if (ns) {
    260    beginning_of_curr_round = ns->valid_after;
    261  } else if (authdir_mode(get_options()) || ASSUME_AUTHORITY_SCHEDULING) {
    262    beginning_of_curr_round = dirauth_sched_get_cur_valid_after_time();
    263  } else {
    264    /* voting_interval comes from get_voting_interval(), so if we're in
    265     * this case as a client, we already tried to get the voting interval
    266     * from the latest_consensus and gave a bug warning if we couldn't.
    267     *
    268     * We wouldn't want to look at the latest consensus's valid_after time,
    269     * since that would be out of date. */
    270    beginning_of_curr_round = voting_sched_get_start_of_interval_after(
    271                                             approx_time() - voting_interval,
    272                                             voting_interval,
    273                                             0);
    274  }
    275 
    276  /* Get current SR protocol round */
    277  int curr_round_slot;
    278  curr_round_slot = (beginning_of_curr_round / voting_interval) % total_rounds;
    279 
    280  /* Get start time by subtracting the time elapsed from the beginning of the
    281     protocol run */
    282  time_t time_elapsed_since_start_of_run = curr_round_slot * voting_interval;
    283 
    284  return beginning_of_curr_round - time_elapsed_since_start_of_run;
    285 }
    286 
    287 /** Return the start time of the previous SR protocol run. See
    288 *  sr_state_get_start_time_of_current_protocol_run() for more details.  */
    289 time_t
    290 sr_state_get_start_time_of_previous_protocol_run(void)
    291 {
    292  time_t start_time_of_current_run =
    293    sr_state_get_start_time_of_current_protocol_run();
    294 
    295  /* We get the start time of previous protocol run, by getting the start time
    296   * of current run and the subtracting a full protocol run from that. */
    297  return start_time_of_current_run - sr_state_get_protocol_run_duration();
    298 }
    299 
    300 /** Return the time (in seconds) it takes to complete a full SR protocol phase
    301 *  (e.g. the commit phase). */
    302 unsigned int
    303 sr_state_get_phase_duration(void)
    304 {
    305  return SHARED_RANDOM_N_ROUNDS * get_voting_interval();
    306 }
    307 
    308 /** Return the time (in seconds) it takes to complete a full SR protocol run */
    309 unsigned int
    310 sr_state_get_protocol_run_duration(void)
    311 {
    312  int total_protocol_rounds = SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES;
    313  return total_protocol_rounds * get_voting_interval();
    314 }