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
test_protover_parse(void * arg)23 test_protover_parse(void *arg)
24 {
25   (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   char *re_encoded = NULL;
34 
35   const char *orig = "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16";
36   smartlist_t *elts = parse_protocol_list(orig);
37 
38   tt_assert(elts);
39   tt_int_op(smartlist_len(elts), OP_EQ, 4);
40 
41   const proto_entry_t *e;
42   e = smartlist_get(elts, 0);
43   tt_str_op(e->name, OP_EQ, "Foo");
44   tt_int_op(e->bitmask, OP_EQ, 0x0a);
45 
46   e = smartlist_get(elts, 1);
47   tt_str_op(e->name, OP_EQ, "Bar");
48   tt_int_op(e->bitmask, OP_EQ, 0x08);
49 
50   e = smartlist_get(elts, 2);
51   tt_str_op(e->name, OP_EQ, "Baz");
52   tt_int_op(e->bitmask, OP_EQ, 0x00);
53 
54   e = smartlist_get(elts, 3);
55   tt_str_op(e->name, OP_EQ, "Quux");
56   tt_int_op(e->bitmask, OP_EQ, 0x1de00);
57 
58   re_encoded = encode_protocol_list(elts);
59   tt_assert(re_encoded);
60   tt_str_op(re_encoded, OP_EQ, "Foo=1,3 Bar=3 Baz= Quux=9-12,14-16");
61 
62  done:
63   if (elts)
64     SMARTLIST_FOREACH(elts, proto_entry_t *, ent, proto_entry_free(ent));
65   smartlist_free(elts);
66   tor_free(re_encoded);
67 #endif /* defined(HAVE_RUST) */
68 }
69 
70 static void
test_protover_parse_fail(void * arg)71 test_protover_parse_fail(void *arg)
72 {
73   (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   smartlist_t *elts;
80 
81   /* random junk */
82   elts = parse_protocol_list("!!3@*");
83   tt_ptr_op(elts, OP_EQ, NULL);
84 
85   /* Missing equals sign in an entry */
86   elts = parse_protocol_list("Link=4 Haprauxymatyve Desc=9");
87   tt_ptr_op(elts, OP_EQ, NULL);
88 
89   /* Missing word. */
90   elts = parse_protocol_list("Link=4 =3 Desc=9");
91   tt_ptr_op(elts, OP_EQ, NULL);
92 
93   /* Broken numbers */
94   elts = parse_protocol_list("Link=fred");
95   tt_ptr_op(elts, OP_EQ, NULL);
96   elts = parse_protocol_list("Link=1,fred");
97   tt_ptr_op(elts, OP_EQ, NULL);
98   elts = parse_protocol_list("Link=1,fred,3");
99   tt_ptr_op(elts, OP_EQ, NULL);
100 
101   /* Broken range */
102   elts = parse_protocol_list("Link=1,9-8,3");
103   tt_ptr_op(elts, OP_EQ, NULL);
104 
105   /* Protocol name too long */
106   elts = parse_protocol_list("DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
107                            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
108                            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
109   tt_ptr_op(elts, OP_EQ, NULL);
110 
111 #endif /* defined(HAVE_RUST) */
112  done:
113   ;
114 }
115 
116 static void
test_protover_vote(void * arg)117 test_protover_vote(void *arg)
118 {
119   (void) arg;
120 
121   smartlist_t *lst = smartlist_new();
122   char *result = protover_compute_vote(lst, 1);
123 
124   tt_str_op(result, OP_EQ, "");
125   tor_free(result);
126 
127   smartlist_add(lst, (void*) "Foo=1-10,63 Bar=1,3-7,8");
128   result = protover_compute_vote(lst, 1);
129   tt_str_op(result, OP_EQ, "Bar=1,3-8 Foo=1-10,63");
130   tor_free(result);
131 
132   smartlist_add(lst, (void*) "Quux=12-45 Bar=2-6,8 Foo=9");
133   result = protover_compute_vote(lst, 1);
134   tt_str_op(result, OP_EQ, "Bar=1-8 Foo=1-10,63 Quux=12-45");
135   tor_free(result);
136 
137   result = protover_compute_vote(lst, 2);
138   tt_str_op(result, OP_EQ, "Bar=3-6,8 Foo=9");
139   tor_free(result);
140 
141   /* High threshold */
142   result = protover_compute_vote(lst, 3);
143   tt_str_op(result, OP_EQ, "");
144   tor_free(result);
145 
146   /* Don't count double-voting. */
147   smartlist_clear(lst);
148   smartlist_add(lst, (void*) "Foo=1 Foo=1");
149   smartlist_add(lst, (void*) "Bar=1-2,2-3");
150   result = protover_compute_vote(lst, 2);
151   tt_str_op(result, OP_EQ, "");
152   tor_free(result);
153 
154   /* Bad votes: the result must be empty */
155   smartlist_clear(lst);
156   smartlist_add(lst, (void*) "Faux=10-5");
157   result = protover_compute_vote(lst, 1);
158   tt_str_op(result, OP_EQ, "");
159   tor_free(result);
160 
161   /* This fails, since "-0" is not valid. */
162   smartlist_clear(lst);
163   smartlist_add(lst, (void*) "Faux=-0");
164   result = protover_compute_vote(lst, 1);
165   tt_str_op(result, OP_EQ, "");
166   tor_free(result);
167 
168   /* Vote large protover lists that are just below the threshold */
169 
170   /* Just below the threshold: Rust */
171   smartlist_clear(lst);
172   smartlist_add(lst, (void*) "Sleen=1-50");
173   result = protover_compute_vote(lst, 1);
174   tt_str_op(result, OP_EQ, "Sleen=1-50");
175   tor_free(result);
176 
177   /* Just below the threshold: C */
178   smartlist_clear(lst);
179   smartlist_add(lst, (void*) "Sleen=1-63");
180   result = protover_compute_vote(lst, 1);
181   tt_str_op(result, OP_EQ, "Sleen=1-63");
182   tor_free(result);
183 
184   /* Protocol name too long */
185   smartlist_clear(lst);
186   smartlist_add(lst, (void*) "DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
187                          "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
188                          "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
189   result = protover_compute_vote(lst, 1);
190   tt_str_op(result, OP_EQ, "");
191   tor_free(result);
192 
193  done:
194   tor_free(result);
195   smartlist_free(lst);
196 }
197 
198 static void
test_protover_all_supported(void * arg)199 test_protover_all_supported(void *arg)
200 {
201   (void)arg;
202   char *msg = NULL;
203 
204   tt_assert(protover_all_supported(NULL, &msg));
205   tt_ptr_op(msg, OP_EQ, NULL);
206 
207   tt_assert(protover_all_supported("", &msg));
208   tt_ptr_op(msg, OP_EQ, NULL);
209 
210   // Some things that we do support
211   tt_assert(protover_all_supported("Link=3-4", &msg));
212   tt_ptr_op(msg, OP_EQ, NULL);
213   tt_assert(protover_all_supported("Link=3-4 Desc=2", &msg));
214   tt_ptr_op(msg, OP_EQ, NULL);
215 
216   // Some things we don't support
217   tt_assert(! protover_all_supported("Wombat=9", NULL));
218   tt_assert(! protover_all_supported("Wombat=9", &msg));
219   tt_str_op(msg, OP_EQ, "Wombat=9");
220   tor_free(msg);
221   tt_assert(! protover_all_supported("Link=60", &msg));
222   tt_str_op(msg, OP_EQ, "Link=60");
223   tor_free(msg);
224 
225   // Mix of things we support and things we don't
226   tt_assert(! protover_all_supported("Link=3-4 Wombat=9", &msg));
227   tt_str_op(msg, OP_EQ, "Wombat=9");
228   tor_free(msg);
229 
230   /* Mix of things we support and don't support within a single protocol
231    * which we do support */
232   tt_assert(! protover_all_supported("Link=3-60", &msg));
233   tt_str_op(msg, OP_EQ, "Link=6-60");
234   tor_free(msg);
235   tt_assert(! protover_all_supported("Link=1-3,50-63", &msg));
236   tt_str_op(msg, OP_EQ, "Link=50-63");
237   tor_free(msg);
238   tt_assert(! protover_all_supported("Link=1-3,5-12", &msg));
239   tt_str_op(msg, OP_EQ, "Link=6-12");
240   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   tt_assert(! protover_all_supported("Link=1-3,5-12 Quokka=40-41", &msg));
245   tt_str_op(msg, OP_EQ, "Link=6-12 Quokka=40-41");
246   tor_free(msg);
247 
248   /* If we get a (barely) valid (but unsupported list, we say "yes, that's
249    * supported." */
250   tt_assert(protover_all_supported("Fribble=", &msg));
251   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   tor_capture_bugs_(1);
257   tt_assert(protover_all_supported("Fribble", &msg));
258   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   tor_capture_bugs_(1);
263   tt_assert(protover_all_supported("Sleen=1-4294967295", &msg));
264   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   tor_capture_bugs_(1);
270   tt_assert(protover_all_supported(
271                  "DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
272                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
273                  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
274                  "aaaaaaaaaaaa=1-65536", &msg));
275   tor_end_capture_bugs_();
276 #endif /* !defined(HAVE_RUST) && !defined(ALL_BUGS_ARE_FATAL) */
277 
278  done:
279   tor_end_capture_bugs_();
280   tor_free(msg);
281 }
282 
283 static void
test_protover_list_supports_protocol_returns_true(void * arg)284 test_protover_list_supports_protocol_returns_true(void *arg)
285 {
286   (void)arg;
287 
288   const char *protocols = "Link=1";
289   int is_supported = protocol_list_supports_protocol(protocols, PRT_LINK, 1);
290   tt_int_op(is_supported, OP_EQ, 1);
291 
292  done:
293   ;
294 }
295 
296 static void
test_protover_list_supports_protocol_for_unsupported_returns_false(void * arg)297 test_protover_list_supports_protocol_for_unsupported_returns_false(void *arg)
298 {
299   (void)arg;
300 
301   const char *protocols = "Link=1";
302   int is_supported = protocol_list_supports_protocol(protocols, PRT_LINK, 10);
303   tt_int_op(is_supported, OP_EQ, 0);
304 
305  done:
306   ;
307 }
308 
309 static void
test_protover_supports_version(void * arg)310 test_protover_supports_version(void *arg)
311 {
312   (void)arg;
313 
314   tt_assert(protocol_list_supports_protocol("Link=3-6", PRT_LINK, 3));
315   tt_assert(protocol_list_supports_protocol("Link=3-6", PRT_LINK, 6));
316   tt_assert(!protocol_list_supports_protocol("Link=3-6", PRT_LINK, 7));
317   tt_assert(!protocol_list_supports_protocol("Link=3-6", PRT_LINKAUTH, 3));
318 
319   tt_assert(!protocol_list_supports_protocol("Link=4-6 LinkAuth=3",
320                                             PRT_LINKAUTH, 2));
321   tt_assert(protocol_list_supports_protocol("Link=4-6 LinkAuth=3",
322                                             PRT_LINKAUTH, 3));
323   tt_assert(!protocol_list_supports_protocol("Link=4-6 LinkAuth=3",
324                                              PRT_LINKAUTH, 4));
325   tt_assert(!protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
326                                              PRT_LINKAUTH, 4));
327   tt_assert(protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
328                                              PRT_LINKAUTH, 3));
329   tt_assert(protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
330                                              PRT_LINKAUTH, 2));
331 
332   tt_assert(!protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
333                                                       PRT_DESC, 2));
334  done:
335  ;
336 }
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
test_protover_supported_protocols(void * arg)378 test_protover_supported_protocols(void *arg)
379 {
380   (void)arg;
381 
382   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   tt_assert(protocol_list_supports_protocol(supported_protocols,
387                                             PRT_LINK,
388                                             MAX_LINK_PROTO));
389   for (uint16_t i = 0; i < MAX_PROTOCOLS_TO_TEST; i++) {
390       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   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   tt_assert(!protocol_list_supports_protocol(supported_protocols,
405                                              PRT_LINKAUTH,
406                                              PROTOVER_LINKAUTH_V2));
407   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   tt_assert(protocol_list_supports_protocol(supported_protocols,
414                                             PRT_RELAY,
415                                             PROTOVER_RELAY_V1));
416   tt_assert(protocol_list_supports_protocol(supported_protocols,
417                                             PRT_RELAY,
418                                             PROTOVER_RELAY_EXTEND2));
419   tt_assert(protocol_list_supports_protocol(supported_protocols,
420                                             PRT_RELAY,
421                                             PROTOVER_RELAY_ACCEPT_IPV6));
422   tt_assert(protocol_list_supports_protocol(supported_protocols,
423                                             PRT_RELAY,
424                                             PROTOVER_RELAY_EXTEND_IPV6));
425   tt_assert(protocol_list_supports_protocol(supported_protocols,
426                                             PRT_RELAY,
427                                             PROTOVER_RELAY_CANONICAL_IPV6));
428 
429   /* These HSIntro versions are deprecated */
430   tt_assert(!protocol_list_supports_protocol(supported_protocols,
431                                             PRT_HSINTRO,
432                                             PROTOVER_HS_INTRO_DEPRECATED_1));
433   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   tt_assert(protocol_list_supports_protocol(supported_protocols,
440                                             PRT_HSINTRO,
441                                             PROTOVER_HS_INTRO_V2));
442   /* Test for HSv3 HSIntro */
443   tt_assert(protocol_list_supports_protocol(supported_protocols,
444                                             PRT_HSINTRO,
445                                             PROTOVER_HS_INTRO_V3));
446   /* Test for HSIntro DoS */
447   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   tt_assert(protocol_list_supports_protocol(supported_protocols,
453                                             PRT_HSREND,
454                                             PROTOVER_HS_RENDEZVOUS_POINT_V2));
455   /* Test for HSv3 HSRend */
456   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   tt_assert(protocol_list_supports_protocol(supported_protocols,
462                                             PRT_HSDIR,
463                                             PROTOVER_HSDIR_V2));
464   /* Test for HSv3 HSDir */
465   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   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   tt_assert(protocol_list_supports_protocol(supported_protocols,
476                                             PRT_DESC,
477                                             PROTOVER_DESC_V1));
478   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   tt_assert(protocol_list_supports_protocol(supported_protocols,
485                                             PRT_MICRODESC,
486                                             PROTOVER_MICRODESC_V1));
487   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   tt_assert(protocol_list_supports_protocol(supported_protocols,
493                                             PRT_CONS,
494                                             PROTOVER_CONS_V1));
495   tt_assert(protocol_list_supports_protocol(supported_protocols,
496                                             PRT_CONS,
497                                             PROTOVER_CONS_V2));
498 
499   /* Padding=1 is deprecated. */
500   tt_assert(!protocol_list_supports_protocol(supported_protocols,
501                                              PRT_PADDING,
502                                              PROTOVER_PADDING_V1));
503   tt_assert(protocol_list_supports_protocol(supported_protocols,
504                                             PRT_PADDING,
505                                             PROTOVER_HS_SETUP_PADDING));
506 
507   /* FlowCtrl */
508   tt_assert(protocol_list_supports_protocol(supported_protocols,
509                                             PRT_FLOWCTRL,
510                                             PROTOVER_FLOWCTRL_V1));
511 
512  done:
513  ;
514 }
515 
516 static void
test_protover_vote_roundtrip(void * args)517 test_protover_vote_roundtrip(void *args)
518 {
519   (void) args;
520   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   unsigned u;
579   smartlist_t *votes = smartlist_new();
580   char *result = NULL;
581 
582   for (u = 0; u < ARRAY_LENGTH(examples); ++u) {
583     const char *input = examples[u].input;
584     const char *expected_output = examples[u].expected_output;
585 
586     smartlist_add(votes, (void*)input);
587     result = protover_compute_vote(votes, 1);
588     if (expected_output != NULL) {
589       tt_str_op(result, OP_EQ, expected_output);
590     } else {
591       tt_str_op(result, OP_EQ, "");
592     }
593 
594     smartlist_clear(votes);
595     tor_free(result);
596   }
597 
598  done:
599   smartlist_free(votes);
600   tor_free(result);
601 }
602 
603 static void
test_protover_vote_roundtrip_ours(void * args)604 test_protover_vote_roundtrip_ours(void *args)
605 {
606   (void) args;
607   const char *examples[] = {
608     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   unsigned u;
615   smartlist_t *votes = smartlist_new();
616   char *result = NULL;
617 
618   for (u = 0; u < ARRAY_LENGTH(examples); ++u) {
619     tt_assert(examples[u]);
620     const char *input = examples[u];
621     const char *expected_output = examples[u];
622 
623     smartlist_add(votes, (void*)input);
624     result = protover_compute_vote(votes, 1);
625     if (expected_output != NULL) {
626       tt_str_op(result, OP_EQ, expected_output);
627     } else {
628       tt_str_op(result, OP_EQ, "");
629     }
630 
631     smartlist_clear(votes);
632     tor_free(result);
633   }
634 
635  done:
636   smartlist_free(votes);
637   tor_free(result);
638 }
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
test_protover_summarize_flags(void * args)701 test_protover_summarize_flags(void *args)
702 {
703   (void) args;
704   char pv[30];
705   memset(&pv, 0, sizeof(pv));
706 
707   protover_summary_cache_free_all();
708 
709   protover_summary_flags_t zero_flags;
710   memset(&zero_flags, 0, sizeof(zero_flags));
711   protover_summary_flags_t flags;
712 
713   memset(&flags, 0, sizeof(flags));
714   summarize_protover_flags(&flags, NULL, NULL);
715   DEBUG_PROTOVER(flags);
716   tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
717 
718   memset(&flags, 0, sizeof(flags));
719   summarize_protover_flags(&flags, "", "");
720   DEBUG_PROTOVER(flags);
721   tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
722 
723   /* Now check version exceptions */
724 
725   /* EXTEND2 cell support */
726   memset(&flags, 0, sizeof(flags));
727   summarize_protover_flags(&flags, NULL, "Tor 0.2.4.8-alpha");
728   DEBUG_PROTOVER(flags);
729   tt_int_op(flags.protocols_known, OP_EQ, 1);
730   tt_int_op(flags.supports_extend2_cells, OP_EQ, 1);
731   /* Now clear those flags, and check the rest are zero */
732   flags.protocols_known = 0;
733   flags.supports_extend2_cells = 0;
734   tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
735 
736   /* disabling HSDir v3 support for buggy versions */
737   memset(&flags, 0, sizeof(flags));
738   summarize_protover_flags(&flags,
739                            PROTOVER("HSDir", PROTOVER_HSDIR_V3),
740                            NULL);
741   DEBUG_PROTOVER(flags);
742   tt_int_op(flags.protocols_known, OP_EQ, 1);
743   tt_int_op(flags.supports_v3_hsdir, OP_EQ, 1);
744   /* Now clear those flags, and check the rest are zero */
745   flags.protocols_known = 0;
746   flags.supports_v3_hsdir = 0;
747   tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
748 
749   memset(&flags, 0, sizeof(flags));
750   summarize_protover_flags(&flags,
751                            PROTOVER("HSDir", PROTOVER_HSDIR_V3),
752                            "Tor 0.3.0.7");
753   DEBUG_PROTOVER(flags);
754   tt_int_op(flags.protocols_known, OP_EQ, 1);
755   /* Now clear that flag, and check the rest are zero */
756   flags.protocols_known = 0;
757   tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
758 
759   /* Now check standard summaries */
760 
761   /* LinkAuth */
762   memset(&flags, 0, sizeof(flags));
763   summarize_protover_flags(&flags,
764                            PROTOVER("LinkAuth",
765                                     PROTOVER_LINKAUTH_ED25519_HANDSHAKE),
766                            NULL);
767   DEBUG_PROTOVER(flags);
768   tt_int_op(flags.protocols_known, OP_EQ, 1);
769   tt_int_op(flags.supports_ed25519_link_handshake_compat, OP_EQ, 1);
770   tt_int_op(flags.supports_ed25519_link_handshake_any, OP_EQ, 1);
771   /* Now clear those flags, and check the rest are zero */
772   flags.protocols_known = 0;
773   flags.supports_ed25519_link_handshake_compat = 0;
774   flags.supports_ed25519_link_handshake_any = 0;
775   tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
776 
777   /* Test one greater */
778   memset(&flags, 0, sizeof(flags));
779   snprintf(pv, sizeof(pv),
780            "%s=%d", "LinkAuth", PROTOVER_LINKAUTH_ED25519_HANDSHAKE + 1);
781   summarize_protover_flags(&flags, pv, NULL);
782   DEBUG_PROTOVER(flags);
783   tt_int_op(flags.protocols_known, OP_EQ, 1);
784   tt_int_op(flags.supports_ed25519_link_handshake_compat, OP_EQ, 0);
785   tt_int_op(flags.supports_ed25519_link_handshake_any, OP_EQ, 1);
786   /* Now clear those flags, and check the rest are zero */
787   flags.protocols_known = 0;
788   flags.supports_ed25519_link_handshake_compat = 0;
789   flags.supports_ed25519_link_handshake_any = 0;
790   tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
791 
792   /* Test one less */
793   memset(&flags, 0, sizeof(flags));
794   snprintf(pv, sizeof(pv),
795            "%s=%d", "LinkAuth", PROTOVER_LINKAUTH_ED25519_HANDSHAKE - 1);
796   summarize_protover_flags(&flags, pv, NULL);
797   DEBUG_PROTOVER(flags);
798   tt_int_op(flags.protocols_known, OP_EQ, 1);
799   tt_int_op(flags.supports_ed25519_link_handshake_compat, OP_EQ, 0);
800   tt_int_op(flags.supports_ed25519_link_handshake_any, OP_EQ, 0);
801   /* Now clear those flags, and check the rest are zero */
802   flags.protocols_known = 0;
803   flags.supports_ed25519_link_handshake_compat = 0;
804   flags.supports_ed25519_link_handshake_any = 0;
805   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   memset(&flags, 0, sizeof(flags));
812   /* This test relies on these versions being equal */
813   tt_int_op(PROTOVER_RELAY_EXTEND2, OP_EQ, PROTOVER_RELAY_ACCEPT_IPV6);
814   summarize_protover_flags(&flags,
815                            PROTOVER("Relay", PROTOVER_RELAY_EXTEND2), NULL);
816   DEBUG_PROTOVER(flags);
817   tt_int_op(flags.protocols_known, OP_EQ, 1);
818   tt_int_op(flags.supports_extend2_cells, OP_EQ, 1);
819   tt_int_op(flags.supports_accepting_ipv6_extends, OP_EQ, 1);
820   /* Now clear those flags, and check the rest are zero */
821   flags.protocols_known = 0;
822   flags.supports_extend2_cells = 0;
823   flags.supports_accepting_ipv6_extends = 0;
824   tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
825 
826   memset(&flags, 0, sizeof(flags));
827   /* This test relies on these versions being equal */
828   tt_int_op(PROTOVER_RELAY_EXTEND_IPV6, OP_EQ, PROTOVER_RELAY_CANONICAL_IPV6);
829   summarize_protover_flags(&flags,
830                            PROTOVER("Relay", PROTOVER_RELAY_EXTEND_IPV6),
831                            NULL);
832   DEBUG_PROTOVER(flags);
833   tt_int_op(flags.protocols_known, OP_EQ, 1);
834   tt_int_op(flags.supports_accepting_ipv6_extends, OP_EQ, 1);
835   tt_int_op(flags.supports_initiating_ipv6_extends, OP_EQ, 1);
836   tt_int_op(flags.supports_canonical_ipv6_conns, OP_EQ, 1);
837   /* Now clear those flags, and check the rest are zero */
838   flags.protocols_known = 0;
839   flags.supports_accepting_ipv6_extends = 0;
840   flags.supports_initiating_ipv6_extends = 0;
841   flags.supports_canonical_ipv6_conns = 0;
842   tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
843 
844   TEST_PROTOVER("HSIntro", PROTOVER_HS_INTRO_V3,
845                 supports_ed25519_hs_intro);
846   TEST_PROTOVER("HSIntro", PROTOVER_HS_INTRO_DOS,
847                 supports_establish_intro_dos_extension);
848 
849   TEST_PROTOVER("HSRend", PROTOVER_HS_RENDEZVOUS_POINT_V3,
850                 supports_v3_rendezvous_point);
851 
852   TEST_PROTOVER("HSDir", PROTOVER_HSDIR_V3,
853                 supports_v3_hsdir);
854 
855   TEST_PROTOVER("Padding", PROTOVER_HS_SETUP_PADDING,
856                 supports_hs_setup_padding);
857 
858  done:
859   ;
860 }
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 };
880