tor

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

test_proto_misc.c (8281B)


      1 /* Copyright (c) 2017-2021, The Tor Project, Inc. */
      2 /* See LICENSE for licensing information */
      3 
      4 /**
      5 * \file test_proto_misc.c
      6 * \brief Test our smaller buffer-based protocol functions
      7 */
      8 
      9 #include "core/or/or.h"
     10 #include "test/test.h"
     11 #include "lib/buf/buffers.h"
     12 #include "core/or/connection_or.h"
     13 #include "feature/relay/ext_orport.h"
     14 #include "core/proto/proto_cell.h"
     15 #include "core/proto/proto_control0.h"
     16 #include "core/proto/proto_ext_or.h"
     17 
     18 #include "core/or/var_cell_st.h"
     19 
     20 static void
     21 test_proto_var_cell(void *arg)
     22 {
     23  (void)arg;
     24  char *mem_op_hex_tmp = NULL;
     25  char tmp[1024];
     26  buf_t *buf = NULL;
     27  var_cell_t *cell = NULL;
     28 
     29  buf = buf_new();
     30  memset(tmp, 0xf0, sizeof(tmp));
     31 
     32  /* Short little commands will make us say "no cell yet." */
     33  tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
     34  tt_ptr_op(cell, OP_EQ, NULL);
     35  buf_add(buf, "\x01\x02\x02\0x2", 4);
     36  tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
     37  /* An incomplete fixed-length cell makes us say "no cell yet". */
     38  buf_add(buf, "\x03", 1);
     39  tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
     40  /* A complete fixed length-cell makes us say "not a variable-length cell" */
     41  buf_add(buf, tmp, 509);
     42  tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
     43  buf_clear(buf);
     44 
     45  /* An incomplete versions cell is a variable-length cell that isn't ready
     46   * yet. */
     47  buf_add(buf,
     48          "\x01\x02\x03\x04" /* circid */
     49          "\x07" /* VERSIONS */
     50          "\x00\x04" /* 4 bytes long */
     51          "\x00" /* incomplete */, 8);
     52  tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
     53  tt_ptr_op(cell, OP_EQ, NULL);
     54  /* Complete it, and it's a variable-length cell. Leave a byte on the end for
     55   * fun. */
     56  buf_add(buf, "\x09\x00\x25\ff", 4);
     57  tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 4));
     58  tt_ptr_op(cell, OP_NE, NULL);
     59  tt_int_op(cell->command, OP_EQ, CELL_VERSIONS);
     60  tt_uint_op(cell->circ_id, OP_EQ, 0x01020304);
     61  tt_int_op(cell->payload_len, OP_EQ, 4);
     62  test_mem_op_hex(cell->payload, OP_EQ, "00090025");
     63  var_cell_free(cell);
     64  cell = NULL;
     65  tt_int_op(buf_datalen(buf), OP_EQ, 1);
     66  buf_clear(buf);
     67 
     68  /* In link protocol 3 and earlier, circid fields were two bytes long. Let's
     69   * ensure that gets handled correctly. */
     70  buf_add(buf,
     71          "\x23\x45\x81\x00\x06" /* command 81; 6 bytes long */
     72          "coraje", 11);
     73  tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 3));
     74  tt_ptr_op(cell, OP_NE, NULL);
     75  tt_int_op(cell->command, OP_EQ, 129);
     76  tt_uint_op(cell->circ_id, OP_EQ, 0x2345);
     77  tt_int_op(cell->payload_len, OP_EQ, 6);
     78  tt_mem_op(cell->payload, OP_EQ, "coraje", 6);
     79  var_cell_free(cell);
     80  cell = NULL;
     81  tt_int_op(buf_datalen(buf), OP_EQ, 0);
     82 
     83  /* In link protocol 2, only VERSIONS cells counted as variable-length */
     84  buf_add(buf,
     85          "\x23\x45\x81\x00\x06"
     86          "coraje", 11); /* As above */
     87  tt_int_op(0, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 2));
     88  buf_clear(buf);
     89  buf_add(buf,
     90          "\x23\x45\x07\x00\x06"
     91          "futuro", 11);
     92  tt_int_op(1, OP_EQ, fetch_var_cell_from_buf(buf, &cell, 2));
     93  tt_ptr_op(cell, OP_NE, NULL);
     94  tt_int_op(cell->command, OP_EQ, 7);
     95  tt_uint_op(cell->circ_id, OP_EQ, 0x2345);
     96  tt_int_op(cell->payload_len, OP_EQ, 6);
     97  tt_mem_op(cell->payload, OP_EQ, "futuro", 6);
     98  var_cell_free(cell);
     99  cell = NULL;
    100 
    101 done:
    102  buf_free(buf);
    103  var_cell_free(cell);
    104  tor_free(mem_op_hex_tmp);
    105 }
    106 
    107 static void
    108 test_proto_control0(void *arg)
    109 {
    110  (void)arg;
    111  buf_t *buf = buf_new();
    112 
    113  /* The only remaining function for the v0 control protocol is the function
    114     that detects whether the user has stumbled across an old controller
    115     that's using it.  The format was:
    116        u16 length;
    117        u16 command;
    118        u8 body[length];
    119  */
    120 
    121  /* Empty buffer -- nothing to do. */
    122  tt_int_op(0, OP_EQ, peek_buf_has_control0_command(buf));
    123  /* 3 chars in buf -- can't tell */
    124  buf_add(buf, "AUT", 3);
    125  tt_int_op(0, OP_EQ, peek_buf_has_control0_command(buf));
    126  /* command in buf -- easy to tell */
    127  buf_add(buf, "HENTICATE ", 10);
    128  tt_int_op(0, OP_EQ, peek_buf_has_control0_command(buf));
    129 
    130  /* Control0 command header in buf: make sure we detect it. */
    131  buf_clear(buf);
    132  buf_add(buf, "\x09\x05" "\x00\x05" "blah", 8);
    133  tt_int_op(1, OP_EQ, peek_buf_has_control0_command(buf));
    134 
    135 done:
    136  buf_free(buf);
    137 }
    138 
    139 static void
    140 test_proto_ext_or_cmd(void *arg)
    141 {
    142  ext_or_cmd_t *cmd = NULL;
    143  buf_t *buf = buf_new();
    144  char *tmp = NULL;
    145  (void) arg;
    146 
    147  /* Empty -- should give "not there. */
    148  tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
    149  tt_ptr_op(NULL, OP_EQ, cmd);
    150 
    151  /* Three bytes: shouldn't work. */
    152  buf_add(buf, "\x00\x20\x00", 3);
    153  tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
    154  tt_ptr_op(NULL, OP_EQ, cmd);
    155  tt_int_op(3, OP_EQ, buf_datalen(buf));
    156 
    157  /* 0020 0000: That's a nil command. It should work. */
    158  buf_add(buf, "\x00", 1);
    159  tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
    160  tt_ptr_op(NULL, OP_NE, cmd);
    161  tt_int_op(0x20, OP_EQ, cmd->cmd);
    162  tt_int_op(0, OP_EQ, cmd->len);
    163  tt_int_op(0, OP_EQ, buf_datalen(buf));
    164  ext_or_cmd_free(cmd);
    165  cmd = NULL;
    166 
    167  /* Now try a length-6 command with one byte missing. */
    168  buf_add(buf, "\x10\x21\x00\x06""abcde", 9);
    169  tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
    170  tt_ptr_op(NULL, OP_EQ, cmd);
    171  buf_add(buf, "f", 1);
    172  tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
    173  tt_ptr_op(NULL, OP_NE, cmd);
    174  tt_int_op(0x1021, OP_EQ, cmd->cmd);
    175  tt_int_op(6, OP_EQ, cmd->len);
    176  tt_mem_op("abcdef", OP_EQ, cmd->body, 6);
    177  tt_int_op(0, OP_EQ, buf_datalen(buf));
    178  ext_or_cmd_free(cmd);
    179  cmd = NULL;
    180 
    181  /* Now try a length-10 command with 4 extra bytes. */
    182  buf_add(buf, "\xff\xff\x00\x0aloremipsum\x10\x00\xff\xff", 18);
    183  tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
    184  tt_ptr_op(NULL, OP_NE, cmd);
    185  tt_int_op(0xffff, OP_EQ, cmd->cmd);
    186  tt_int_op(10, OP_EQ, cmd->len);
    187  tt_mem_op("loremipsum", OP_EQ, cmd->body, 10);
    188  tt_int_op(4, OP_EQ, buf_datalen(buf));
    189  ext_or_cmd_free(cmd);
    190  cmd = NULL;
    191 
    192  /* Finally, let's try a maximum-length command. We already have the header
    193   * waiting. */
    194  tt_int_op(0, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
    195  tmp = tor_malloc_zero(65535);
    196  buf_add(buf, tmp, 65535);
    197  tt_int_op(1, OP_EQ, fetch_ext_or_command_from_buf(buf, &cmd));
    198  tt_ptr_op(NULL, OP_NE, cmd);
    199  tt_int_op(0x1000, OP_EQ, cmd->cmd);
    200  tt_int_op(0xffff, OP_EQ, cmd->len);
    201  tt_mem_op(tmp, OP_EQ, cmd->body, 65535);
    202  tt_int_op(0, OP_EQ, buf_datalen(buf));
    203  ext_or_cmd_free(cmd);
    204  cmd = NULL;
    205 
    206 done:
    207  ext_or_cmd_free(cmd);
    208  buf_free(buf);
    209  tor_free(tmp);
    210 }
    211 
    212 static void
    213 test_proto_line(void *arg)
    214 {
    215  (void)arg;
    216  char tmp[60];
    217  buf_t *buf = buf_new();
    218 #define S(str) str, sizeof(str)-1
    219  const struct {
    220    const char *input;
    221    size_t input_len;
    222    size_t line_len;
    223    const char *output;
    224    int returnval;
    225  } cases[] = {
    226    { S("Hello world"), 0, NULL, 0 },
    227    { S("Hello world\n"), 12, "Hello world\n", 1 },
    228    { S("Hello world\nMore"), 12, "Hello world\n", 1 },
    229    { S("\n oh hello world\nMore"), 1, "\n", 1 },
    230    { S("Hello worpd\n\nMore"), 12, "Hello worpd\n", 1 },
    231    { S("------------------------------------------------------------\n"), 0,
    232      NULL, -1 },
    233  };
    234  unsigned i;
    235  for (i = 0; i < ARRAY_LENGTH(cases); ++i) {
    236    buf_add(buf, cases[i].input, cases[i].input_len);
    237    memset(tmp, 0xfe, sizeof(tmp));
    238    size_t sz = sizeof(tmp);
    239    int rv = buf_get_line(buf, tmp, &sz);
    240    tt_int_op(rv, OP_EQ, cases[i].returnval);
    241    if (rv == 1) {
    242      tt_int_op(sz, OP_LT, sizeof(tmp));
    243      tt_mem_op(cases[i].output, OP_EQ, tmp, sz+1);
    244      tt_int_op(buf_datalen(buf), OP_EQ, cases[i].input_len - strlen(tmp));
    245      tt_int_op(sz, OP_EQ, cases[i].line_len);
    246    } else {
    247      tt_int_op(buf_datalen(buf), OP_EQ, cases[i].input_len);
    248      // tt_int_op(sz, OP_EQ, sizeof(tmp));
    249    }
    250    buf_clear(buf);
    251  }
    252 
    253 done:
    254  buf_free(buf);
    255 }
    256 
    257 struct testcase_t proto_misc_tests[] = {
    258  { "var_cell", test_proto_var_cell, 0, NULL, NULL },
    259  { "control0", test_proto_control0, 0, NULL, NULL },
    260  { "ext_or_cmd", test_proto_ext_or_cmd, TT_FORK, NULL, NULL },
    261  { "line", test_proto_line, 0, NULL, NULL },
    262 
    263  END_OF_TESTCASES
    264 };