LCOV - code coverage report
Current view: top level - test - test_protover.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 366 366 100.0 %
Date: 2021-11-24 03:28:48 Functions: 11 11 100.0 %

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

Generated by: LCOV version 1.14