tor

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

test_protover.c (29884B)


      1 /* Copyright (c) 2016-2021, The Tor Project, Inc. */
      2 /* See LICENSE for licensing information */
      3 
      4 #define PROTOVER_PRIVATE
      5 #define DIRVOTE_PRIVATE
      6 
      7 #include "orconfig.h"
      8 #include "test/test.h"
      9 
     10 #include "lib/tls/tortls.h"
     11 
     12 #include "core/or/or.h"
     13 
     14 #include "core/or/connection_or.h"
     15 #include "core/or/protover.h"
     16 #include "core/or/versions.h"
     17 
     18 #include "feature/dirauth/dirvote.h"
     19 
     20 #include "feature/relay/relay_handshake.h"
     21 
     22 static void
     23 test_protover_parse(void *arg)
     24 {
     25  (void) arg;
     26  char *re_encoded = NULL;
     27 
     28  const char *orig = "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16";
     29  smartlist_t *elts = parse_protocol_list(orig);
     30 
     31  tt_assert(elts);
     32  tt_int_op(smartlist_len(elts), OP_EQ, 4);
     33 
     34  const proto_entry_t *e;
     35  e = smartlist_get(elts, 0);
     36  tt_str_op(e->name, OP_EQ, "Foo");
     37  tt_int_op(e->bitmask, OP_EQ, 0x0a);
     38 
     39  e = smartlist_get(elts, 1);
     40  tt_str_op(e->name, OP_EQ, "Bar");
     41  tt_int_op(e->bitmask, OP_EQ, 0x08);
     42 
     43  e = smartlist_get(elts, 2);
     44  tt_str_op(e->name, OP_EQ, "Baz");
     45  tt_int_op(e->bitmask, OP_EQ, 0x00);
     46 
     47  e = smartlist_get(elts, 3);
     48  tt_str_op(e->name, OP_EQ, "Quux");
     49  tt_int_op(e->bitmask, OP_EQ, 0x1de00);
     50 
     51  re_encoded = encode_protocol_list(elts);
     52  tt_assert(re_encoded);
     53  tt_str_op(re_encoded, OP_EQ, "Foo=1,3 Bar=3 Baz= Quux=9-12,14-16");
     54 
     55 done:
     56  if (elts)
     57    SMARTLIST_FOREACH(elts, proto_entry_t *, ent, proto_entry_free(ent));
     58  smartlist_free(elts);
     59  tor_free(re_encoded);
     60 }
     61 
     62 static void
     63 test_protover_parse_fail(void *arg)
     64 {
     65  (void)arg;
     66  smartlist_t *elts;
     67 
     68  /* random junk */
     69  elts = parse_protocol_list("!!3@*");
     70  tt_ptr_op(elts, OP_EQ, NULL);
     71 
     72  /* Missing equals sign in an entry */
     73  elts = parse_protocol_list("Link=4 Haprauxymatyve Desc=9");
     74  tt_ptr_op(elts, OP_EQ, NULL);
     75 
     76  /* Missing word. */
     77  elts = parse_protocol_list("Link=4 =3 Desc=9");
     78  tt_ptr_op(elts, OP_EQ, NULL);
     79 
     80  /* Broken numbers */
     81  elts = parse_protocol_list("Link=fred");
     82  tt_ptr_op(elts, OP_EQ, NULL);
     83  elts = parse_protocol_list("Link=1,fred");
     84  tt_ptr_op(elts, OP_EQ, NULL);
     85  elts = parse_protocol_list("Link=1,fred,3");
     86  tt_ptr_op(elts, OP_EQ, NULL);
     87 
     88  /* Broken range */
     89  elts = parse_protocol_list("Link=1,9-8,3");
     90  tt_ptr_op(elts, OP_EQ, NULL);
     91 
     92  /* Protocol name too long */
     93  elts = parse_protocol_list("DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
     94                           "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
     95                           "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
     96  tt_ptr_op(elts, OP_EQ, NULL);
     97 
     98 done:
     99  ;
    100 }
    101 
    102 static void
    103 test_protover_vote(void *arg)
    104 {
    105  (void) arg;
    106 
    107  smartlist_t *lst = smartlist_new();
    108  char *result = protover_compute_vote(lst, 1);
    109 
    110  tt_str_op(result, OP_EQ, "");
    111  tor_free(result);
    112 
    113  smartlist_add(lst, (void*) "Foo=1-10,63 Bar=1,3-7,8");
    114  result = protover_compute_vote(lst, 1);
    115  tt_str_op(result, OP_EQ, "Bar=1,3-8 Foo=1-10,63");
    116  tor_free(result);
    117 
    118  smartlist_add(lst, (void*) "Quux=12-45 Bar=2-6,8 Foo=9");
    119  result = protover_compute_vote(lst, 1);
    120  tt_str_op(result, OP_EQ, "Bar=1-8 Foo=1-10,63 Quux=12-45");
    121  tor_free(result);
    122 
    123  result = protover_compute_vote(lst, 2);
    124  tt_str_op(result, OP_EQ, "Bar=3-6,8 Foo=9");
    125  tor_free(result);
    126 
    127  /* High threshold */
    128  result = protover_compute_vote(lst, 3);
    129  tt_str_op(result, OP_EQ, "");
    130  tor_free(result);
    131 
    132  /* Don't count double-voting. */
    133  smartlist_clear(lst);
    134  smartlist_add(lst, (void*) "Foo=1 Foo=1");
    135  smartlist_add(lst, (void*) "Bar=1-2,2-3");
    136  result = protover_compute_vote(lst, 2);
    137  tt_str_op(result, OP_EQ, "");
    138  tor_free(result);
    139 
    140  /* Bad votes: the result must be empty */
    141  smartlist_clear(lst);
    142  smartlist_add(lst, (void*) "Faux=10-5");
    143  result = protover_compute_vote(lst, 1);
    144  tt_str_op(result, OP_EQ, "");
    145  tor_free(result);
    146 
    147  /* This fails, since "-0" is not valid. */
    148  smartlist_clear(lst);
    149  smartlist_add(lst, (void*) "Faux=-0");
    150  result = protover_compute_vote(lst, 1);
    151  tt_str_op(result, OP_EQ, "");
    152  tor_free(result);
    153 
    154  /* Vote large protover lists that are just below the threshold */
    155 
    156  /* Just below the threshold: Rust */
    157  smartlist_clear(lst);
    158  smartlist_add(lst, (void*) "Sleen=1-50");
    159  result = protover_compute_vote(lst, 1);
    160  tt_str_op(result, OP_EQ, "Sleen=1-50");
    161  tor_free(result);
    162 
    163  /* Just below the threshold: C */
    164  smartlist_clear(lst);
    165  smartlist_add(lst, (void*) "Sleen=1-63");
    166  result = protover_compute_vote(lst, 1);
    167  tt_str_op(result, OP_EQ, "Sleen=1-63");
    168  tor_free(result);
    169 
    170  /* Protocol name too long */
    171  smartlist_clear(lst);
    172  smartlist_add(lst, (void*) "DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    173                         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    174                         "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
    175  result = protover_compute_vote(lst, 1);
    176  tt_str_op(result, OP_EQ, "");
    177  tor_free(result);
    178 
    179 done:
    180  tor_free(result);
    181  smartlist_free(lst);
    182 }
    183 
    184 static void
    185 test_protover_all_supported(void *arg)
    186 {
    187  (void)arg;
    188  char *msg = NULL;
    189 
    190  tt_assert(protover_all_supported(NULL, &msg));
    191  tt_ptr_op(msg, OP_EQ, NULL);
    192 
    193  tt_assert(protover_all_supported("", &msg));
    194  tt_ptr_op(msg, OP_EQ, NULL);
    195 
    196  // Some things that we do support
    197  tt_assert(protover_all_supported("Link=3-4", &msg));
    198  tt_ptr_op(msg, OP_EQ, NULL);
    199  tt_assert(protover_all_supported("Link=3-4 Desc=2", &msg));
    200  tt_ptr_op(msg, OP_EQ, NULL);
    201 
    202  // Some things we don't support
    203  tt_assert(! protover_all_supported("Wombat=9", NULL));
    204  tt_assert(! protover_all_supported("Wombat=9", &msg));
    205  tt_str_op(msg, OP_EQ, "Wombat=9");
    206  tor_free(msg);
    207  tt_assert(! protover_all_supported("Link=60", &msg));
    208  tt_str_op(msg, OP_EQ, "Link=60");
    209  tor_free(msg);
    210 
    211  // Mix of things we support and things we don't
    212  tt_assert(! protover_all_supported("Link=3-4 Wombat=9", &msg));
    213  tt_str_op(msg, OP_EQ, "Wombat=9");
    214  tor_free(msg);
    215 
    216  /* Mix of things we support and don't support within a single protocol
    217   * which we do support */
    218  tt_assert(! protover_all_supported("Link=3-60", &msg));
    219  tt_str_op(msg, OP_EQ, "Link=6-60");
    220  tor_free(msg);
    221  tt_assert(! protover_all_supported("Link=1-3,50-63", &msg));
    222  tt_str_op(msg, OP_EQ, "Link=1-2,50-63");
    223  tor_free(msg);
    224  tt_assert(! protover_all_supported("Link=1-3,5-12", &msg));
    225  tt_str_op(msg, OP_EQ, "Link=1-2,6-12");
    226  tor_free(msg);
    227 
    228  /* Mix of protocols we do support and some we don't, where the protocols
    229   * we do support have some versions we don't support. */
    230  tt_assert(! protover_all_supported("Link=3,5-12 Quokka=40-41", &msg));
    231  tt_str_op(msg, OP_EQ, "Link=6-12 Quokka=40-41");
    232  tor_free(msg);
    233 
    234  /* If we get a (barely) valid (but unsupported list, we say "yes, that's
    235   * supported." */
    236  tt_assert(protover_all_supported("Fribble=", &msg));
    237  tt_ptr_op(msg, OP_EQ, NULL);
    238 
    239 #ifndef ALL_BUGS_ARE_FATAL
    240  /* If we get a completely unparseable list, protover_all_supported should
    241   * hit a fatal assertion for BUG(entries == NULL). */
    242  tor_capture_bugs_(1);
    243  tt_assert(protover_all_supported("Fribble", &msg));
    244  tor_end_capture_bugs_();
    245 
    246  /* If we get a completely unparseable list, protover_all_supported should
    247   * hit a fatal assertion for BUG(entries == NULL). */
    248  tor_capture_bugs_(1);
    249  tt_assert(protover_all_supported("Sleen=1-4294967295", &msg));
    250  tor_end_capture_bugs_();
    251 #endif /* !defined(ALL_BUGS_ARE_FATAL) */
    252 
    253  /* Protocol name too long */
    254 #if !defined(ALL_BUGS_ARE_FATAL)
    255  tor_capture_bugs_(1);
    256  tt_assert(protover_all_supported(
    257                 "DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    258                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    259                 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    260                 "aaaaaaaaaaaa=1-65536", &msg));
    261  tor_end_capture_bugs_();
    262 #endif /* !defined(ALL_BUGS_ARE_FATAL) */
    263 
    264 done:
    265  tor_end_capture_bugs_();
    266  tor_free(msg);
    267 }
    268 
    269 static void
    270 test_protover_list_supports_protocol_returns_true(void *arg)
    271 {
    272  (void)arg;
    273 
    274  const char *protocols = "Link=1";
    275  int is_supported = protocol_list_supports_protocol(protocols, PRT_LINK, 1);
    276  tt_int_op(is_supported, OP_EQ, 1);
    277 
    278 done:
    279  ;
    280 }
    281 
    282 static void
    283 test_protover_list_supports_protocol_for_unsupported_returns_false(void *arg)
    284 {
    285  (void)arg;
    286 
    287  const char *protocols = "Link=1";
    288  int is_supported = protocol_list_supports_protocol(protocols, PRT_LINK, 10);
    289  tt_int_op(is_supported, OP_EQ, 0);
    290 
    291 done:
    292  ;
    293 }
    294 
    295 static void
    296 test_protover_supports_version(void *arg)
    297 {
    298  (void)arg;
    299 
    300  tt_assert(protocol_list_supports_protocol("Link=3-6", PRT_LINK, 3));
    301  tt_assert(protocol_list_supports_protocol("Link=3-6", PRT_LINK, 6));
    302  tt_assert(!protocol_list_supports_protocol("Link=3-6", PRT_LINK, 7));
    303  tt_assert(!protocol_list_supports_protocol("Link=3-6", PRT_LINKAUTH, 3));
    304 
    305  tt_assert(!protocol_list_supports_protocol("Link=4-6 LinkAuth=3",
    306                                            PRT_LINKAUTH, 2));
    307  tt_assert(protocol_list_supports_protocol("Link=4-6 LinkAuth=3",
    308                                            PRT_LINKAUTH, 3));
    309  tt_assert(!protocol_list_supports_protocol("Link=4-6 LinkAuth=3",
    310                                             PRT_LINKAUTH, 4));
    311  tt_assert(!protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
    312                                             PRT_LINKAUTH, 4));
    313  tt_assert(protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
    314                                             PRT_LINKAUTH, 3));
    315  tt_assert(protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
    316                                             PRT_LINKAUTH, 2));
    317 
    318  tt_assert(!protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
    319                                                      PRT_DESC, 2));
    320 done:
    321 ;
    322 }
    323 
    324 /* This could be MAX_PROTOCOLS_TO_EXPAND, but that's not exposed by protover */
    325 #define MAX_PROTOCOLS_TO_TEST 1024
    326 
    327 /* LinkAuth and Relay protocol versions.
    328 * Hard-coded here, because they are not in the code, or not exposed in the
    329 * headers. */
    330 #define PROTOVER_LINKAUTH_V1 1
    331 #define PROTOVER_LINKAUTH_V2 2
    332 #define PROTOVER_RELAY_V2 2
    333 
    334 /* Deprecated HSIntro versions */
    335 #define PROTOVER_HS_INTRO_DEPRECATED_1 1
    336 #define PROTOVER_HS_INTRO_DEPRECATED_2 2
    337 
    338 /* HSv2 Rend and HSDir protocol versions. */
    339 #define PROTOVER_HS_RENDEZVOUS_POINT_V2 1
    340 #define PROTOVER_HSDIR_V2 2
    341 
    342 /* DirCache, Desc, Microdesc, and Cons protocol versions. */
    343 #define PROTOVER_DIRCACHE_V1 1
    344 #define PROTOVER_DIRCACHE_V2 2
    345 
    346 #define PROTOVER_DESC_V1 1
    347 #define PROTOVER_DESC_V2 2
    348 
    349 #define PROTOVER_MICRODESC_V1 1
    350 #define PROTOVER_MICRODESC_V2 2
    351 
    352 #define PROTOVER_CONS_V1 1
    353 #define PROTOVER_CONS_V2 2
    354 
    355 #define PROTOVER_PADDING_V1 1
    356 
    357 #define PROTOVER_FLOWCTRL_V1 1
    358 
    359 #define PROTOVER_RELAY_NTOR_V3 4
    360 
    361 /* Make sure we haven't forgotten any supported protocols */
    362 static void
    363 test_protover_supported_protocols(void *arg)
    364 {
    365  (void)arg;
    366 
    367  const char *supported_protocols = protover_get_supported_protocols();
    368 
    369  /* Test for new Link in the code, that hasn't been added to supported
    370   * protocols */
    371  tt_assert(protocol_list_supports_protocol(supported_protocols,
    372                                            PRT_LINK,
    373                                            MAX_LINK_PROTO));
    374  for (uint16_t i = 0; i < MAX_PROTOCOLS_TO_TEST; i++) {
    375      tt_int_op(protocol_list_supports_protocol(supported_protocols,
    376                                                PRT_LINK,
    377                                                i),
    378                OP_EQ,
    379                is_or_protocol_version_known(i));
    380  }
    381 
    382  /* Legacy LinkAuth is only supported on OpenSSL and similar. */
    383  tt_int_op(protocol_list_supports_protocol(supported_protocols,
    384                                            PRT_LINKAUTH,
    385                                            PROTOVER_LINKAUTH_V1),
    386            OP_EQ,
    387            authchallenge_type_is_supported(AUTHTYPE_RSA_SHA256_TLSSECRET));
    388  /* LinkAuth=2 is unused */
    389  tt_assert(!protocol_list_supports_protocol(supported_protocols,
    390                                             PRT_LINKAUTH,
    391                                             PROTOVER_LINKAUTH_V2));
    392  tt_assert(
    393      protocol_list_supports_protocol(supported_protocols,
    394                                     PRT_LINKAUTH,
    395                                     PROTOVER_LINKAUTH_ED25519_HANDSHAKE));
    396 
    397  /* Relay protovers do not appear anywhere in the code. */
    398  tt_assert(protocol_list_supports_protocol(supported_protocols,
    399                                            PRT_RELAY,
    400                                            PROTOVER_RELAY_V2));
    401  tt_assert(protocol_list_supports_protocol(supported_protocols,
    402                                            PRT_RELAY,
    403                                            PROTOVER_RELAY_EXTEND2));
    404  tt_assert(protocol_list_supports_protocol(supported_protocols,
    405                                            PRT_RELAY,
    406                                            PROTOVER_RELAY_ACCEPT_IPV6));
    407  tt_assert(protocol_list_supports_protocol(supported_protocols,
    408                                            PRT_RELAY,
    409                                            PROTOVER_RELAY_EXTEND_IPV6));
    410  tt_assert(protocol_list_supports_protocol(supported_protocols,
    411                                            PRT_RELAY,
    412                                            PROTOVER_RELAY_CANONICAL_IPV6));
    413 
    414  /* These HSIntro versions are deprecated */
    415  tt_assert(!protocol_list_supports_protocol(supported_protocols,
    416                                            PRT_HSINTRO,
    417                                            PROTOVER_HS_INTRO_DEPRECATED_1));
    418  tt_assert(!protocol_list_supports_protocol(supported_protocols,
    419                                            PRT_HSINTRO,
    420                                            PROTOVER_HS_INTRO_DEPRECATED_2));
    421  /* Test for HSv3 HSIntro */
    422  tt_assert(protocol_list_supports_protocol(supported_protocols,
    423                                            PRT_HSINTRO,
    424                                            PROTOVER_HS_INTRO_V3));
    425  /* Test for HSIntro DoS */
    426  tt_assert(protocol_list_supports_protocol(supported_protocols,
    427                                            PRT_HSINTRO,
    428                                            PROTOVER_HS_INTRO_DOS));
    429 
    430  /* Legacy HSRend does not appear anywhere in the code. */
    431  tt_assert(protocol_list_supports_protocol(supported_protocols,
    432                                            PRT_HSREND,
    433                                            PROTOVER_HS_RENDEZVOUS_POINT_V2));
    434  /* Test for HSv3 HSRend */
    435  tt_assert(protocol_list_supports_protocol(supported_protocols,
    436                                            PRT_HSREND,
    437                                            PROTOVER_HS_RENDEZVOUS_POINT_V3));
    438 
    439  /* Legacy HSDir does not appear anywhere in the code. */
    440  tt_assert(protocol_list_supports_protocol(supported_protocols,
    441                                            PRT_HSDIR,
    442                                            PROTOVER_HSDIR_V2));
    443  /* Test for HSv3 HSDir */
    444  tt_assert(protocol_list_supports_protocol(supported_protocols,
    445                                            PRT_HSDIR,
    446                                            PROTOVER_HSDIR_V3));
    447 
    448  /* No DirCache versions appear anywhere in the code. */
    449  tt_assert(protocol_list_supports_protocol(supported_protocols,
    450                                            PRT_DIRCACHE,
    451                                            PROTOVER_DIRCACHE_V2));
    452 
    453  /* No Desc versions appear anywhere in the code. */
    454  tt_assert(protocol_list_supports_protocol(supported_protocols,
    455                                            PRT_DESC,
    456                                            PROTOVER_DESC_V1));
    457  tt_assert(protocol_list_supports_protocol(supported_protocols,
    458                                            PRT_DESC,
    459                                            PROTOVER_DESC_V2));
    460  /* Is there any way to test for new Desc? */
    461 
    462  /* No Microdesc versions appear anywhere in the code. */
    463  tt_assert(protocol_list_supports_protocol(supported_protocols,
    464                                            PRT_MICRODESC,
    465                                            PROTOVER_MICRODESC_V1));
    466  tt_assert(protocol_list_supports_protocol(supported_protocols,
    467                                            PRT_MICRODESC,
    468                                            PROTOVER_MICRODESC_V2));
    469 
    470  /* No Cons versions appear anywhere in the code. */
    471  tt_assert(protocol_list_supports_protocol(supported_protocols,
    472                                            PRT_CONS,
    473                                            PROTOVER_CONS_V1));
    474  tt_assert(protocol_list_supports_protocol(supported_protocols,
    475                                            PRT_CONS,
    476                                            PROTOVER_CONS_V2));
    477 
    478  /* Padding=1 is deprecated. */
    479  tt_assert(!protocol_list_supports_protocol(supported_protocols,
    480                                             PRT_PADDING,
    481                                             PROTOVER_PADDING_V1));
    482  tt_assert(protocol_list_supports_protocol(supported_protocols,
    483                                            PRT_PADDING,
    484                                            PROTOVER_HS_SETUP_PADDING));
    485 
    486  /* FlowCtrl */
    487  tt_assert(protocol_list_supports_protocol(supported_protocols,
    488                                            PRT_FLOWCTRL,
    489                                            PROTOVER_FLOWCTRL_V1));
    490 
    491 done:
    492 ;
    493 }
    494 
    495 static void
    496 test_protover_vote_roundtrip(void *args)
    497 {
    498  (void) args;
    499  static const struct {
    500    const char *input;
    501    const char *expected_output;
    502  } examples[] = {
    503    { "Risqu\u00e9=1", NULL },
    504    { ",,,=1", NULL },
    505    { "\xc1=1", NULL },
    506    { "Foo_Bar=1", NULL },
    507    { "Fkrkljdsf", NULL },
    508    { "Zn=4294967295", NULL },
    509    { "Zn=4294967295-1", NULL },
    510    { "Zn=4294967293-4294967295", NULL },
    511    /* Will fail because of 4294967295. */
    512    { "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,900 Zn=1,4294967295",
    513       NULL },
    514    { "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,50 Zn=1,42",
    515      "Bar=3 Foo=1,3 Quux=9-12,14-16,50 Zn=1,42" },
    516    { "Zu16=1,63", "Zu16=1,63" },
    517    { "N-1=1,2", "N-1=1-2" },
    518    { "-1=4294967295", NULL },
    519    { "-1=3", "-1=3" },
    520    { "Foo=,", NULL },
    521    { "Foo=,1", NULL },
    522    { "Foo=1,,3", NULL },
    523    { "Foo=1,3,", NULL },
    524    /* junk. */
    525    { "!!3@*", NULL },
    526    /* Missing equals sign */
    527    { "Link=4 Haprauxymatyve Desc=9", NULL },
    528    { "Link=4 Haprauxymatyve=7 Desc=9",
    529      "Desc=9 Haprauxymatyve=7 Link=4" },
    530    { "=10-11", NULL },
    531    { "X=10-11", "X=10-11" },
    532    { "Link=4 =3 Desc=9", NULL },
    533    { "Link=4 Z=3 Desc=9", "Desc=9 Link=4 Z=3" },
    534    { "Link=fred", NULL },
    535    { "Link=1,fred", NULL },
    536    { "Link=1,fred,3", NULL },
    537    { "Link=1,9-8,3", NULL },
    538    { "Faux=-0", NULL },
    539    { "Faux=0--0", NULL },
    540    { "Faux=-1", NULL },
    541    { "Faux=-1-3", NULL },
    542    { "Faux=1--1", NULL },
    543    { "Link=1-2-", NULL },
    544    { "Link=1-2-3", NULL },
    545    { "Faux=1-2-", NULL },
    546    { "Faux=1-2-3", NULL },
    547    { "Link=\t1,3", NULL },
    548    { "Link=1\n,3", NULL },
    549    { "Faux=1,\r3", NULL },
    550    { "Faux=1,3\f", NULL },
    551    /* Large integers */
    552    { "Link=4294967296", NULL },
    553    /* Large range */
    554    { "Sleen=1-63", "Sleen=1-63" },
    555    { "Sleen=1-65537", NULL },
    556  };
    557  unsigned u;
    558  smartlist_t *votes = smartlist_new();
    559  char *result = NULL;
    560 
    561  for (u = 0; u < ARRAY_LENGTH(examples); ++u) {
    562    const char *input = examples[u].input;
    563    const char *expected_output = examples[u].expected_output;
    564 
    565    smartlist_add(votes, (void*)input);
    566    result = protover_compute_vote(votes, 1);
    567    if (expected_output != NULL) {
    568      tt_str_op(result, OP_EQ, expected_output);
    569    } else {
    570      tt_str_op(result, OP_EQ, "");
    571    }
    572 
    573    smartlist_clear(votes);
    574    tor_free(result);
    575  }
    576 
    577 done:
    578  smartlist_free(votes);
    579  tor_free(result);
    580 }
    581 
    582 static void
    583 test_protover_vote_roundtrip_ours(void *args)
    584 {
    585  (void) args;
    586  const char *examples[] = {
    587    protover_get_supported_protocols(),
    588    protover_get_recommended_client_protocols(),
    589    protover_get_recommended_relay_protocols(),
    590    protover_get_required_client_protocols(),
    591    protover_get_required_relay_protocols(),
    592  };
    593  unsigned u;
    594  smartlist_t *votes = smartlist_new();
    595  char *result = NULL;
    596 
    597  for (u = 0; u < ARRAY_LENGTH(examples); ++u) {
    598    tt_assert(examples[u]);
    599    const char *input = examples[u];
    600    const char *expected_output = examples[u];
    601 
    602    smartlist_add(votes, (void*)input);
    603    result = protover_compute_vote(votes, 1);
    604    if (expected_output != NULL) {
    605      tt_str_op(result, OP_EQ, expected_output);
    606    } else {
    607      tt_str_op(result, OP_EQ, "");
    608    }
    609 
    610    smartlist_clear(votes);
    611    tor_free(result);
    612  }
    613 
    614 done:
    615  smartlist_free(votes);
    616  tor_free(result);
    617 }
    618 
    619 /* Stringifies its argument.
    620 * 4 -> "4" */
    621 #define STR(x) #x
    622 
    623 #ifdef COCCI
    624 #define PROTOVER(proto_string, version_macro)
    625 #else
    626 /* Generate a protocol version string using proto_string and version_macro.
    627 * PROTOVER("HSIntro", PROTOVER_HS_INTRO_DOS) -> "HSIntro" "=" "5"
    628 * Uses two levels of macros to turn PROTOVER_HS_INTRO_DOS into "5".
    629 */
    630 #define PROTOVER(proto_string, version_macro) \
    631  (proto_string "=" STR(version_macro))
    632 #endif /* defined(COCCI) */
    633 
    634 #define DEBUG_PROTOVER(flags) \
    635  STMT_BEGIN \
    636  log_debug(LD_GENERAL, \
    637            "protovers:\n" \
    638            "protocols_known: %d,\n" \
    639            "supports_extend2_cells: %d,\n" \
    640            "supports_accepting_ipv6_extends: %d,\n" \
    641            "supports_initiating_ipv6_extends: %d,\n" \
    642            "supports_canonical_ipv6_conns: %d,\n" \
    643            "supports_ed25519_link_handshake_compat: %d,\n" \
    644            "supports_ed25519_link_handshake_any: %d,\n" \
    645            "supports_ed25519_hs_intro: %d,\n" \
    646            "supports_establish_intro_dos_extension: %d,\n" \
    647            "supports_v3_hsdir: %d,\n" \
    648            "supports_v3_rendezvous_point: %d,\n" \
    649            "supports_hs_setup_padding: %d,\n" \
    650            "supports_congestion_control: %d.", \
    651            (flags).protocols_known, \
    652            (flags).supports_extend2_cells, \
    653            (flags).supports_accepting_ipv6_extends, \
    654            (flags).supports_initiating_ipv6_extends, \
    655            (flags).supports_canonical_ipv6_conns, \
    656            (flags).supports_ed25519_link_handshake_compat, \
    657            (flags).supports_ed25519_link_handshake_any, \
    658            (flags).supports_ed25519_hs_intro, \
    659            (flags).supports_establish_intro_dos_extension, \
    660            (flags).supports_v3_hsdir, \
    661            (flags).supports_v3_rendezvous_point, \
    662            (flags).supports_hs_setup_padding, \
    663            (flags).supports_congestion_control); \
    664    STMT_END
    665 
    666 /* Test that the proto_string version version_macro sets summary_flag. */
    667 #define TEST_PROTOVER(proto_string, version_macro, summary_flag) \
    668  STMT_BEGIN \
    669  memset(&flags, 0, sizeof(flags)); \
    670  summarize_protover_flags(&flags, \
    671                           PROTOVER(proto_string, version_macro), \
    672                           NULL); \
    673  DEBUG_PROTOVER(flags); \
    674  tt_int_op(flags.protocols_known, OP_EQ, 1); \
    675  tt_int_op(flags.summary_flag, OP_EQ, 1); \
    676  flags.protocols_known = 0; \
    677  flags.summary_flag = 0; \
    678  tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags)); \
    679  STMT_END
    680 
    681 static void
    682 test_protover_summarize_flags(void *args)
    683 {
    684  (void) args;
    685  char pv[30];
    686  memset(&pv, 0, sizeof(pv));
    687 
    688  protover_summary_cache_free_all();
    689 
    690  protover_summary_flags_t zero_flags;
    691  memset(&zero_flags, 0, sizeof(zero_flags));
    692  protover_summary_flags_t flags;
    693 
    694  memset(&flags, 0, sizeof(flags));
    695  summarize_protover_flags(&flags, NULL, NULL);
    696  DEBUG_PROTOVER(flags);
    697  tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
    698 
    699  memset(&flags, 0, sizeof(flags));
    700  summarize_protover_flags(&flags, "", "");
    701  DEBUG_PROTOVER(flags);
    702  tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
    703 
    704  /* Now check version exceptions */
    705 
    706  /* EXTEND2 cell support */
    707  memset(&flags, 0, sizeof(flags));
    708  summarize_protover_flags(&flags, NULL, "Tor 0.2.4.8-alpha");
    709  DEBUG_PROTOVER(flags);
    710  tt_int_op(flags.protocols_known, OP_EQ, 1);
    711  tt_int_op(flags.supports_extend2_cells, OP_EQ, 1);
    712  /* Now clear those flags, and check the rest are zero */
    713  flags.protocols_known = 0;
    714  flags.supports_extend2_cells = 0;
    715  tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
    716 
    717  /* disabling HSDir v3 support for buggy versions */
    718  memset(&flags, 0, sizeof(flags));
    719  summarize_protover_flags(&flags,
    720                           PROTOVER("HSDir", PROTOVER_HSDIR_V3),
    721                           NULL);
    722  DEBUG_PROTOVER(flags);
    723  tt_int_op(flags.protocols_known, OP_EQ, 1);
    724  tt_int_op(flags.supports_v3_hsdir, OP_EQ, 1);
    725  /* Now clear those flags, and check the rest are zero */
    726  flags.protocols_known = 0;
    727  flags.supports_v3_hsdir = 0;
    728  tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
    729 
    730  memset(&flags, 0, sizeof(flags));
    731  summarize_protover_flags(&flags,
    732                           PROTOVER("HSDir", PROTOVER_HSDIR_V3),
    733                           "Tor 0.3.0.7");
    734  DEBUG_PROTOVER(flags);
    735  tt_int_op(flags.protocols_known, OP_EQ, 1);
    736  /* Now clear that flag, and check the rest are zero */
    737  flags.protocols_known = 0;
    738  tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
    739 
    740  /* Now check standard summaries */
    741 
    742  /* LinkAuth */
    743  memset(&flags, 0, sizeof(flags));
    744  summarize_protover_flags(&flags,
    745                           PROTOVER("LinkAuth",
    746                                    PROTOVER_LINKAUTH_ED25519_HANDSHAKE),
    747                           NULL);
    748  DEBUG_PROTOVER(flags);
    749  tt_int_op(flags.protocols_known, OP_EQ, 1);
    750  tt_int_op(flags.supports_ed25519_link_handshake_compat, OP_EQ, 1);
    751  tt_int_op(flags.supports_ed25519_link_handshake_any, OP_EQ, 1);
    752  /* Now clear those flags, and check the rest are zero */
    753  flags.protocols_known = 0;
    754  flags.supports_ed25519_link_handshake_compat = 0;
    755  flags.supports_ed25519_link_handshake_any = 0;
    756  tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
    757 
    758  /* Test one greater */
    759  memset(&flags, 0, sizeof(flags));
    760  snprintf(pv, sizeof(pv),
    761           "%s=%d", "LinkAuth", PROTOVER_LINKAUTH_ED25519_HANDSHAKE + 1);
    762  summarize_protover_flags(&flags, pv, NULL);
    763  DEBUG_PROTOVER(flags);
    764  tt_int_op(flags.protocols_known, OP_EQ, 1);
    765  tt_int_op(flags.supports_ed25519_link_handshake_compat, OP_EQ, 0);
    766  tt_int_op(flags.supports_ed25519_link_handshake_any, OP_EQ, 1);
    767  /* Now clear those flags, and check the rest are zero */
    768  flags.protocols_known = 0;
    769  flags.supports_ed25519_link_handshake_compat = 0;
    770  flags.supports_ed25519_link_handshake_any = 0;
    771  tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
    772 
    773  /* Test one less */
    774  memset(&flags, 0, sizeof(flags));
    775  snprintf(pv, sizeof(pv),
    776           "%s=%d", "LinkAuth", PROTOVER_LINKAUTH_ED25519_HANDSHAKE - 1);
    777  summarize_protover_flags(&flags, pv, NULL);
    778  DEBUG_PROTOVER(flags);
    779  tt_int_op(flags.protocols_known, OP_EQ, 1);
    780  tt_int_op(flags.supports_ed25519_link_handshake_compat, OP_EQ, 0);
    781  tt_int_op(flags.supports_ed25519_link_handshake_any, OP_EQ, 0);
    782  /* Now clear those flags, and check the rest are zero */
    783  flags.protocols_known = 0;
    784  flags.supports_ed25519_link_handshake_compat = 0;
    785  flags.supports_ed25519_link_handshake_any = 0;
    786  tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
    787 
    788  /* We don't test "one more" and "one less" for each protocol version.
    789   * But that could be a useful thing to add. */
    790 
    791  /* Relay */
    792  memset(&flags, 0, sizeof(flags));
    793  /* This test relies on these versions being equal */
    794  tt_int_op(PROTOVER_RELAY_EXTEND2, OP_EQ, PROTOVER_RELAY_ACCEPT_IPV6);
    795  summarize_protover_flags(&flags,
    796                           PROTOVER("Relay", PROTOVER_RELAY_EXTEND2), NULL);
    797  DEBUG_PROTOVER(flags);
    798  tt_int_op(flags.protocols_known, OP_EQ, 1);
    799  tt_int_op(flags.supports_extend2_cells, OP_EQ, 1);
    800  tt_int_op(flags.supports_accepting_ipv6_extends, OP_EQ, 1);
    801  /* Now clear those flags, and check the rest are zero */
    802  flags.protocols_known = 0;
    803  flags.supports_extend2_cells = 0;
    804  flags.supports_accepting_ipv6_extends = 0;
    805  tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
    806 
    807  memset(&flags, 0, sizeof(flags));
    808  /* This test relies on these versions being equal */
    809  tt_int_op(PROTOVER_RELAY_EXTEND_IPV6, OP_EQ, PROTOVER_RELAY_CANONICAL_IPV6);
    810  summarize_protover_flags(&flags,
    811                           PROTOVER("Relay", PROTOVER_RELAY_EXTEND_IPV6),
    812                           NULL);
    813  DEBUG_PROTOVER(flags);
    814  tt_int_op(flags.protocols_known, OP_EQ, 1);
    815  tt_int_op(flags.supports_accepting_ipv6_extends, OP_EQ, 1);
    816  tt_int_op(flags.supports_initiating_ipv6_extends, OP_EQ, 1);
    817  tt_int_op(flags.supports_canonical_ipv6_conns, OP_EQ, 1);
    818  /* Now clear those flags, and check the rest are zero */
    819  flags.protocols_known = 0;
    820  flags.supports_accepting_ipv6_extends = 0;
    821  flags.supports_initiating_ipv6_extends = 0;
    822  flags.supports_canonical_ipv6_conns = 0;
    823  tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
    824 
    825  TEST_PROTOVER("HSIntro", PROTOVER_HS_INTRO_V3,
    826                supports_ed25519_hs_intro);
    827  TEST_PROTOVER("HSIntro", PROTOVER_HS_INTRO_DOS,
    828                supports_establish_intro_dos_extension);
    829 
    830  TEST_PROTOVER("HSRend", PROTOVER_HS_RENDEZVOUS_POINT_V3,
    831                supports_v3_rendezvous_point);
    832 
    833  TEST_PROTOVER("HSDir", PROTOVER_HSDIR_V3,
    834                supports_v3_hsdir);
    835 
    836  TEST_PROTOVER("Padding", PROTOVER_HS_SETUP_PADDING,
    837                supports_hs_setup_padding);
    838 
    839 done:
    840  ;
    841 }
    842 
    843 #define PV_TEST(name, flags)                       \
    844  { #name, test_protover_ ##name, (flags), NULL, NULL }
    845 
    846 struct testcase_t protover_tests[] = {
    847  PV_TEST(parse, 0),
    848  PV_TEST(parse_fail, 0),
    849  PV_TEST(vote, 0),
    850  PV_TEST(all_supported, 0),
    851  PV_TEST(list_supports_protocol_for_unsupported_returns_false, 0),
    852  PV_TEST(list_supports_protocol_returns_true, 0),
    853  PV_TEST(supports_version, 0),
    854  PV_TEST(supported_protocols, 0),
    855  PV_TEST(vote_roundtrip, 0),
    856  PV_TEST(vote_roundtrip_ours, 0),
    857  /* fork, because we memoize flags internally */
    858  PV_TEST(summarize_flags, TT_FORK),
    859  END_OF_TESTCASES
    860 };