tor

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

test_sendme.c (12248B)


      1 /* Copyright (c) 2014-2021, The Tor Project, Inc. */
      2 /* See LICENSE for licensing information */
      3 
      4 /* Unit tests for handling different kinds of relay cell */
      5 
      6 #define CIRCUITLIST_PRIVATE
      7 #define NETWORKSTATUS_PRIVATE
      8 #define SENDME_PRIVATE
      9 #define RELAY_PRIVATE
     10 #define RELAY_CELL_PRIVATE
     11 
     12 #include "core/or/circuit_st.h"
     13 #include "core/or/or_circuit_st.h"
     14 #include "core/or/origin_circuit_st.h"
     15 #include "core/or/circuitlist.h"
     16 #include "core/or/relay.h"
     17 #include "core/or/sendme.h"
     18 
     19 #include "feature/nodelist/networkstatus.h"
     20 #include "feature/nodelist/networkstatus_st.h"
     21 
     22 #include "lib/crypt_ops/crypto_digest.h"
     23 
     24 #include "test/test.h"
     25 #include "test/log_test_helpers.h"
     26 
     27 static void
     28 setup_mock_consensus(void)
     29 {
     30  current_md_consensus = current_ns_consensus =
     31    tor_malloc_zero(sizeof(networkstatus_t));
     32  current_md_consensus->net_params = smartlist_new();
     33  current_md_consensus->routerstatus_list = smartlist_new();
     34 }
     35 
     36 static void
     37 free_mock_consensus(void)
     38 {
     39  SMARTLIST_FOREACH(current_md_consensus->routerstatus_list, void *, r,
     40                    tor_free(r));
     41  smartlist_free(current_md_consensus->routerstatus_list);
     42  smartlist_free(current_ns_consensus->net_params);
     43  tor_free(current_ns_consensus);
     44 }
     45 
     46 static void
     47 test_v1_record_digest(void *arg)
     48 {
     49  or_circuit_t *or_circ = NULL;
     50  circuit_t *circ = NULL;
     51 
     52  (void) arg;
     53 
     54  /* Create our dummy circuit. */
     55  or_circ = or_circuit_new(1, NULL);
     56  /* Points it to the OR circuit now. */
     57  circ = TO_CIRCUIT(or_circ);
     58 
     59  /* The package window has to be a multiple of CIRCWINDOW_INCREMENT minus 1
     60   * in order to catch the CIRCWINDOW_INCREMENT-nth cell. Try something that
     61   * shouldn't be noted. */
     62  circ->package_window = CIRCWINDOW_INCREMENT;
     63  sendme_record_cell_digest_on_circ(circ, NULL);
     64  tt_assert(!circ->sendme_last_digests);
     65 
     66  /* This should work now. Package window at CIRCWINDOW_INCREMENT + 1. */
     67  circ->package_window++;
     68  sendme_record_cell_digest_on_circ(circ, NULL);
     69  tt_assert(circ->sendme_last_digests);
     70  tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 1);
     71 
     72  /* Next cell in the package window shouldn't do anything. */
     73  circ->package_window++;
     74  sendme_record_cell_digest_on_circ(circ, NULL);
     75  tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 1);
     76 
     77  /* The next CIRCWINDOW_INCREMENT should add one more digest. */
     78  circ->package_window = (CIRCWINDOW_INCREMENT * 2) + 1;
     79  sendme_record_cell_digest_on_circ(circ, NULL);
     80  tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 2);
     81 
     82 done:
     83  circuit_free_(circ);
     84 }
     85 
     86 static void
     87 test_v1_consensus_params(void *arg)
     88 {
     89  (void) arg;
     90 
     91  setup_mock_consensus();
     92  tt_assert(current_md_consensus);
     93 
     94  /* Both zeroes. */
     95  smartlist_add(current_md_consensus->net_params,
     96                (void *) "sendme_emit_min_version=0");
     97  smartlist_add(current_md_consensus->net_params,
     98                (void *) "sendme_accept_min_version=0");
     99  tt_int_op(get_emit_min_version(), OP_EQ, 0);
    100  tt_int_op(get_accept_min_version(), OP_EQ, 0);
    101  smartlist_clear(current_md_consensus->net_params);
    102 
    103  /* Both ones. */
    104  smartlist_add(current_md_consensus->net_params,
    105                (void *) "sendme_emit_min_version=1");
    106  smartlist_add(current_md_consensus->net_params,
    107                (void *) "sendme_accept_min_version=1");
    108  tt_int_op(get_emit_min_version(), OP_EQ, 1);
    109  tt_int_op(get_accept_min_version(), OP_EQ, 1);
    110  smartlist_clear(current_md_consensus->net_params);
    111 
    112  /* Different values from each other. */
    113  smartlist_add(current_md_consensus->net_params,
    114                (void *) "sendme_emit_min_version=1");
    115  smartlist_add(current_md_consensus->net_params,
    116                (void *) "sendme_accept_min_version=0");
    117  tt_int_op(get_emit_min_version(), OP_EQ, 1);
    118  tt_int_op(get_accept_min_version(), OP_EQ, 0);
    119  smartlist_clear(current_md_consensus->net_params);
    120 
    121  /* Validate is the cell version is coherent with our internal default value
    122   * and the one in the consensus. */
    123  smartlist_add(current_md_consensus->net_params,
    124                (void *) "sendme_accept_min_version=1");
    125  /* Minimum acceptable value is 1. */
    126  tt_int_op(cell_version_can_be_handled(1), OP_EQ, true);
    127  /* Minimum acceptable value is 1 so a cell version of 0 is refused. */
    128  tt_int_op(cell_version_can_be_handled(0), OP_EQ, false);
    129 
    130 done:
    131  free_mock_consensus();
    132 }
    133 
    134 static void
    135 test_v1_build_cell(void *arg)
    136 {
    137  uint8_t payload[RELAY_PAYLOAD_SIZE], digest[DIGEST_LEN];
    138  ssize_t ret;
    139  crypto_digest_t *cell_digest = NULL;
    140  or_circuit_t *or_circ = NULL;
    141  circuit_t *circ = NULL;
    142 
    143  (void) arg;
    144 
    145  or_circ = or_circuit_new(1, NULL);
    146  circ = TO_CIRCUIT(or_circ);
    147  circ->sendme_last_digests = smartlist_new();
    148 
    149  cell_digest = crypto_digest_new();
    150  tt_assert(cell_digest);
    151  crypto_digest_add_bytes(cell_digest, "AAAAAAAAAAAAAAAAAAAA", 20);
    152  crypto_digest_get_digest(cell_digest, (char *) digest, sizeof(digest));
    153  smartlist_add(circ->sendme_last_digests, tor_memdup(digest, sizeof(digest)));
    154 
    155  /* SENDME v1 payload is 3 bytes + 20 bytes digest. See spec. */
    156  ret = build_cell_payload_v1(digest, 20, payload);
    157  tt_int_op(ret, OP_EQ, 23);
    158 
    159  /* Validation. */
    160 
    161  /* An empty payload means SENDME version 0 thus valid. */
    162  tt_int_op(sendme_is_valid(circ, NULL, payload, 0), OP_EQ, true);
    163  /* Current phoney digest should have been popped. */
    164  tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 0);
    165 
    166  /* An unparseable cell means invalid. */
    167  setup_full_capture_of_logs(LOG_INFO);
    168  tt_int_op(sendme_is_valid(circ, NULL, (const uint8_t *) "A", 1),
    169            OP_EQ, false);
    170  expect_log_msg_containing("Unparseable SENDME cell received. "
    171                            "Closing circuit.");
    172  teardown_capture_of_logs();
    173 
    174  /* No cell digest recorded for this. */
    175  setup_full_capture_of_logs(LOG_INFO);
    176  tt_int_op(sendme_is_valid(circ, NULL, payload, sizeof(payload)),
    177            OP_EQ, false);
    178  expect_log_msg_containing("We received a SENDME but we have no cell digests "
    179                            "to match. Closing circuit.");
    180  teardown_capture_of_logs();
    181 
    182  /* Note the wrong digest in the circuit, cell should fail validation. */
    183  circ->package_window = CIRCWINDOW_INCREMENT + 1;
    184  sendme_record_cell_digest_on_circ(circ, NULL);
    185  tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 1);
    186  setup_full_capture_of_logs(LOG_INFO);
    187  tt_int_op(sendme_is_valid(circ, NULL, payload, sizeof(payload)),
    188            OP_EQ, false);
    189  /* After a validation, the last digests is always popped out. */
    190  tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 0);
    191  expect_log_msg_containing("SENDME v1 cell digest do not match.");
    192  teardown_capture_of_logs();
    193 
    194  /* Record the cell digest into the circuit, cell should validate. */
    195  memcpy(or_circ->crypto.c.tor1.sendme_digest, digest, sizeof(digest));
    196  circ->package_window = CIRCWINDOW_INCREMENT + 1;
    197  sendme_record_cell_digest_on_circ(circ, NULL);
    198  tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 1);
    199  tt_int_op(sendme_is_valid(circ, NULL, payload, sizeof(payload)),
    200            OP_EQ, true);
    201  /* After a validation, the last digests is always popped out. */
    202  tt_int_op(smartlist_len(circ->sendme_last_digests), OP_EQ, 0);
    203 
    204 done:
    205  crypto_digest_free(cell_digest);
    206  circuit_free_(circ);
    207 }
    208 
    209 static void
    210 test_cell_version_validation(void *arg)
    211 {
    212  (void) arg;
    213 
    214  /* We currently only support up to SENDME_MAX_SUPPORTED_VERSION so we are
    215   * going to test the boundaries there. */
    216 
    217  tt_assert(cell_version_can_be_handled(SENDME_MAX_SUPPORTED_VERSION));
    218 
    219  /* Version below our supported should pass. */
    220  tt_assert(cell_version_can_be_handled(SENDME_MAX_SUPPORTED_VERSION - 1));
    221 
    222  /* Extra version from our supported should fail. */
    223  tt_assert(!cell_version_can_be_handled(SENDME_MAX_SUPPORTED_VERSION + 1));
    224 
    225  /* Simple check for version 0. */
    226  tt_assert(cell_version_can_be_handled(0));
    227 
    228  /* We MUST handle the default cell version that we emit or accept. */
    229  tt_assert(cell_version_can_be_handled(SENDME_EMIT_MIN_VERSION_DEFAULT));
    230  tt_assert(cell_version_can_be_handled(SENDME_ACCEPT_MIN_VERSION_DEFAULT));
    231 
    232 done:
    233  ;
    234 }
    235 
    236 /* check our decisions about how much stuff to put into relay cells. */
    237 static void
    238 test_package_payload_len(void *arg)
    239 {
    240  (void)arg;
    241  or_circuit_t *or_circ = or_circuit_new(0, NULL);
    242  crypt_path_t *cpath = NULL;
    243  circuit_t *c = TO_CIRCUIT(or_circ);
    244 
    245  or_circ->relay_cell_format = RELAY_CELL_FORMAT_V0;
    246 
    247  /* check initial conditions. */
    248  circuit_reset_sendme_randomness(c);
    249  tt_assert(! c->have_sent_sufficiently_random_cell);
    250  tt_int_op(c->send_randomness_after_n_cells, OP_GE, CIRCWINDOW_INCREMENT / 2);
    251  tt_int_op(c->send_randomness_after_n_cells, OP_LT, CIRCWINDOW_INCREMENT);
    252 
    253  /* We have a bunch of cells before we need to send randomness, so the first
    254   * few can be packaged full. */
    255  int initial = c->send_randomness_after_n_cells;
    256  size_t n = connection_edge_get_inbuf_bytes_to_package(10000, 0, c, cpath);
    257  tt_uint_op(RELAY_PAYLOAD_SIZE, OP_EQ, n);
    258  n = connection_edge_get_inbuf_bytes_to_package(95000, 1, c, cpath);
    259  tt_uint_op(RELAY_PAYLOAD_SIZE, OP_EQ, n);
    260  tt_int_op(c->send_randomness_after_n_cells, OP_EQ, initial - 2);
    261 
    262  /* If package_partial isn't set, we won't package a partially full cell at
    263   * all. */
    264  n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-1, 0,
    265                                                 c, cpath);
    266  tt_int_op(n, OP_EQ, 0);
    267  /* no change in our state, since nothing was sent. */
    268  tt_assert(! c->have_sent_sufficiently_random_cell);
    269  tt_int_op(c->send_randomness_after_n_cells, OP_EQ, initial - 2);
    270 
    271  /* If package_partial is set and the partial cell is not going to have
    272   * _enough_ randomness, we package it, but we don't consider ourselves to
    273   * have sent a sufficiently random cell. */
    274  n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-1, 1,
    275                                                 c, cpath);
    276  tt_int_op(n, OP_EQ, RELAY_PAYLOAD_SIZE-1);
    277  tt_assert(! c->have_sent_sufficiently_random_cell);
    278  tt_int_op(c->send_randomness_after_n_cells, OP_EQ, initial - 3);
    279 
    280  /* Make sure we set have_set_sufficiently_random_cell as appropriate. */
    281  n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-64, 1,
    282                                                 c, cpath);
    283  tt_int_op(n, OP_EQ, RELAY_PAYLOAD_SIZE-64);
    284  tt_assert(c->have_sent_sufficiently_random_cell);
    285  tt_int_op(c->send_randomness_after_n_cells, OP_EQ, initial - 4);
    286 
    287  /* Now let's look at what happens when we get down to zero. Since we have
    288   * sent a sufficiently random cell, we will not force this one to have a gap.
    289   */
    290  c->send_randomness_after_n_cells = 0;
    291  n = connection_edge_get_inbuf_bytes_to_package(10000, 1, c, cpath);
    292  tt_int_op(n, OP_EQ, RELAY_PAYLOAD_SIZE);
    293  /* Now these will be reset. */
    294  tt_assert(! c->have_sent_sufficiently_random_cell);
    295  tt_int_op(c->send_randomness_after_n_cells, OP_GE,
    296            CIRCWINDOW_INCREMENT / 2 - 1);
    297 
    298  /* What would happen if we hadn't sent a sufficiently random cell? */
    299  c->send_randomness_after_n_cells = 0;
    300  n = connection_edge_get_inbuf_bytes_to_package(10000, 1, c, cpath);
    301  const size_t reduced_payload_size = RELAY_PAYLOAD_SIZE - 4 - 16;
    302  tt_int_op(n, OP_EQ, reduced_payload_size);
    303  /* Now these will be reset. */
    304  tt_assert(! c->have_sent_sufficiently_random_cell);
    305  tt_int_op(c->send_randomness_after_n_cells, OP_GE,
    306            CIRCWINDOW_INCREMENT / 2 - 1);
    307 
    308  /* Here is a fun case: if it's time to package a small cell, then
    309   * package_partial==0 should mean we accept that many bytes.
    310   */
    311  c->send_randomness_after_n_cells = 0;
    312  n = connection_edge_get_inbuf_bytes_to_package(reduced_payload_size, 0,
    313                                                 c, cpath);
    314  tt_int_op(n, OP_EQ, reduced_payload_size);
    315 
    316 done:
    317  circuit_free(c);
    318 }
    319 
    320 struct testcase_t sendme_tests[] = {
    321  { "v1_record_digest", test_v1_record_digest, TT_FORK,
    322    NULL, NULL },
    323  { "v1_consensus_params", test_v1_consensus_params, TT_FORK,
    324    NULL, NULL },
    325  { "v1_build_cell", test_v1_build_cell, TT_FORK,
    326    NULL, NULL },
    327  { "cell_version_validation", test_cell_version_validation, TT_FORK,
    328    NULL, NULL },
    329  { "package_payload_len", test_package_payload_len, 0, NULL, NULL },
    330 
    331  END_OF_TESTCASES
    332 };