Merge branch 'tor-github/pr/1939'
[tor.git] / src / test / test_protover.c
blob5e74265550e484ca654bf6240b01b354f67a398d
1 /* Copyright (c) 2016-2020, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 #define PROTOVER_PRIVATE
5 #define DIRVOTE_PRIVATE
7 #include "orconfig.h"
8 #include "test/test.h"
10 #include "lib/tls/tortls.h"
12 #include "core/or/or.h"
14 #include "core/or/connection_or.h"
15 #include "core/or/protover.h"
16 #include "core/or/versions.h"
18 #include "feature/dirauth/dirvote.h"
20 #include "feature/relay/relay_handshake.h"
22 static void
23 test_protover_parse(void *arg)
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:
32 #else /* !defined(HAVE_RUST) */
33 char *re_encoded = NULL;
35 const char *orig = "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,900";
36 smartlist_t *elts = parse_protocol_list(orig);
38 tt_assert(elts);
39 tt_int_op(smartlist_len(elts), OP_EQ, 4);
41 const proto_entry_t *e;
42 const proto_range_t *r;
43 e = smartlist_get(elts, 0);
44 tt_str_op(e->name, OP_EQ, "Foo");
45 tt_int_op(smartlist_len(e->ranges), OP_EQ, 2);
47 r = smartlist_get(e->ranges, 0);
48 tt_int_op(r->low, OP_EQ, 1);
49 tt_int_op(r->high, OP_EQ, 1);
51 r = smartlist_get(e->ranges, 1);
52 tt_int_op(r->low, OP_EQ, 3);
53 tt_int_op(r->high, OP_EQ, 3);
56 e = smartlist_get(elts, 1);
57 tt_str_op(e->name, OP_EQ, "Bar");
58 tt_int_op(smartlist_len(e->ranges), OP_EQ, 1);
60 r = smartlist_get(e->ranges, 0);
61 tt_int_op(r->low, OP_EQ, 3);
62 tt_int_op(r->high, OP_EQ, 3);
65 e = smartlist_get(elts, 2);
66 tt_str_op(e->name, OP_EQ, "Baz");
67 tt_int_op(smartlist_len(e->ranges), OP_EQ, 0);
69 e = smartlist_get(elts, 3);
70 tt_str_op(e->name, OP_EQ, "Quux");
71 tt_int_op(smartlist_len(e->ranges), OP_EQ, 4);
73 r = smartlist_get(e->ranges, 0);
74 tt_int_op(r->low, OP_EQ, 9);
75 tt_int_op(r->high, OP_EQ, 12);
77 r = smartlist_get(e->ranges, 1);
78 tt_int_op(r->low, OP_EQ, 14);
79 tt_int_op(r->high, OP_EQ, 14);
81 r = smartlist_get(e->ranges, 2);
82 tt_int_op(r->low, OP_EQ, 15);
83 tt_int_op(r->high, OP_EQ, 16);
85 r = smartlist_get(e->ranges, 3);
86 tt_int_op(r->low, OP_EQ, 900);
87 tt_int_op(r->high, OP_EQ, 900);
90 re_encoded = encode_protocol_list(elts);
91 tt_assert(re_encoded);
92 tt_str_op(re_encoded, OP_EQ, orig);
94 done:
95 if (elts)
96 SMARTLIST_FOREACH(elts, proto_entry_t *, ent, proto_entry_free(ent));
97 smartlist_free(elts);
98 tor_free(re_encoded);
99 #endif /* defined(HAVE_RUST) */
102 static void
103 test_protover_parse_fail(void *arg)
105 (void)arg;
106 #ifdef HAVE_RUST
107 /** This test is disabled on rust builds, because it only exists to test
108 * internal C functions. */
109 tt_skip();
110 #else
111 smartlist_t *elts;
113 /* random junk */
114 elts = parse_protocol_list("!!3@*");
115 tt_ptr_op(elts, OP_EQ, NULL);
117 /* Missing equals sign in an entry */
118 elts = parse_protocol_list("Link=4 Haprauxymatyve Desc=9");
119 tt_ptr_op(elts, OP_EQ, NULL);
121 /* Missing word. */
122 elts = parse_protocol_list("Link=4 =3 Desc=9");
123 tt_ptr_op(elts, OP_EQ, NULL);
125 /* Broken numbers */
126 elts = parse_protocol_list("Link=fred");
127 tt_ptr_op(elts, OP_EQ, NULL);
128 elts = parse_protocol_list("Link=1,fred");
129 tt_ptr_op(elts, OP_EQ, NULL);
130 elts = parse_protocol_list("Link=1,fred,3");
131 tt_ptr_op(elts, OP_EQ, NULL);
133 /* Broken range */
134 elts = parse_protocol_list("Link=1,9-8,3");
135 tt_ptr_op(elts, OP_EQ, NULL);
137 /* Protocol name too long */
138 elts = parse_protocol_list("DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
139 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
140 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
141 tt_ptr_op(elts, OP_EQ, NULL);
143 #endif /* defined(HAVE_RUST) */
144 done:
148 static void
149 test_protover_vote(void *arg)
151 (void) arg;
153 smartlist_t *lst = smartlist_new();
154 char *result = protover_compute_vote(lst, 1);
156 tt_str_op(result, OP_EQ, "");
157 tor_free(result);
159 smartlist_add(lst, (void*) "Foo=1-10,500 Bar=1,3-7,8");
160 result = protover_compute_vote(lst, 1);
161 tt_str_op(result, OP_EQ, "Bar=1,3-8 Foo=1-10,500");
162 tor_free(result);
164 smartlist_add(lst, (void*) "Quux=123-456,78 Bar=2-6,8 Foo=9");
165 result = protover_compute_vote(lst, 1);
166 tt_str_op(result, OP_EQ, "Bar=1-8 Foo=1-10,500 Quux=78,123-456");
167 tor_free(result);
169 result = protover_compute_vote(lst, 2);
170 tt_str_op(result, OP_EQ, "Bar=3-6,8 Foo=9");
171 tor_free(result);
173 /* High threshold */
174 result = protover_compute_vote(lst, 3);
175 tt_str_op(result, OP_EQ, "");
176 tor_free(result);
178 /* Don't count double-voting. */
179 smartlist_clear(lst);
180 smartlist_add(lst, (void*) "Foo=1 Foo=1");
181 smartlist_add(lst, (void*) "Bar=1-2,2-3");
182 result = protover_compute_vote(lst, 2);
183 tt_str_op(result, OP_EQ, "");
184 tor_free(result);
186 /* Bad votes: the result must be empty */
187 smartlist_clear(lst);
188 smartlist_add(lst, (void*) "Faux=10-5");
189 result = protover_compute_vote(lst, 1);
190 tt_str_op(result, OP_EQ, "");
191 tor_free(result);
193 /* This fails, since "-0" is not valid. */
194 smartlist_clear(lst);
195 smartlist_add(lst, (void*) "Faux=-0");
196 result = protover_compute_vote(lst, 1);
197 tt_str_op(result, OP_EQ, "");
198 tor_free(result);
200 /* Vote large protover lists that are just below the threshold */
202 /* Just below the threshold: Rust */
203 smartlist_clear(lst);
204 smartlist_add(lst, (void*) "Sleen=1-500");
205 result = protover_compute_vote(lst, 1);
206 tt_str_op(result, OP_EQ, "Sleen=1-500");
207 tor_free(result);
209 /* Just below the threshold: C */
210 smartlist_clear(lst);
211 smartlist_add(lst, (void*) "Sleen=1-65536");
212 result = protover_compute_vote(lst, 1);
213 tt_str_op(result, OP_EQ, "Sleen=1-65536");
214 tor_free(result);
216 /* Large protover lists that exceed the threshold */
218 /* By adding two votes, C allows us to exceed the limit */
219 smartlist_add(lst, (void*) "Sleen=1-65536");
220 smartlist_add(lst, (void*) "Sleen=100000");
221 result = protover_compute_vote(lst, 1);
222 tt_str_op(result, OP_EQ, "Sleen=1-65536,100000");
223 tor_free(result);
225 /* Large integers */
226 smartlist_clear(lst);
227 smartlist_add(lst, (void*) "Sleen=4294967294");
228 result = protover_compute_vote(lst, 1);
229 tt_str_op(result, OP_EQ, "Sleen=4294967294");
230 tor_free(result);
232 /* This parses, but fails at the vote stage */
233 smartlist_clear(lst);
234 smartlist_add(lst, (void*) "Sleen=4294967295");
235 result = protover_compute_vote(lst, 1);
236 tt_str_op(result, OP_EQ, "");
237 tor_free(result);
239 smartlist_clear(lst);
240 smartlist_add(lst, (void*) "Sleen=4294967296");
241 result = protover_compute_vote(lst, 1);
242 tt_str_op(result, OP_EQ, "");
243 tor_free(result);
245 /* Protocol name too long */
246 smartlist_clear(lst);
247 smartlist_add(lst, (void*) "DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
248 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
249 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
250 result = protover_compute_vote(lst, 1);
251 tt_str_op(result, OP_EQ, "");
252 tor_free(result);
254 done:
255 tor_free(result);
256 smartlist_free(lst);
259 static void
260 test_protover_all_supported(void *arg)
262 (void)arg;
263 char *msg = NULL;
265 tt_assert(protover_all_supported(NULL, &msg));
266 tt_ptr_op(msg, OP_EQ, NULL);
268 tt_assert(protover_all_supported("", &msg));
269 tt_ptr_op(msg, OP_EQ, NULL);
271 // Some things that we do support
272 tt_assert(protover_all_supported("Link=3-4", &msg));
273 tt_ptr_op(msg, OP_EQ, NULL);
274 tt_assert(protover_all_supported("Link=3-4 Desc=2", &msg));
275 tt_ptr_op(msg, OP_EQ, NULL);
277 // Some things we don't support
278 tt_assert(! protover_all_supported("Wombat=9", NULL));
279 tt_assert(! protover_all_supported("Wombat=9", &msg));
280 tt_str_op(msg, OP_EQ, "Wombat=9");
281 tor_free(msg);
282 tt_assert(! protover_all_supported("Link=999", &msg));
283 tt_str_op(msg, OP_EQ, "Link=999");
284 tor_free(msg);
286 // Mix of things we support and things we don't
287 tt_assert(! protover_all_supported("Link=3-4 Wombat=9", &msg));
288 tt_str_op(msg, OP_EQ, "Wombat=9");
289 tor_free(msg);
291 /* Mix of things we support and don't support within a single protocol
292 * which we do support */
293 tt_assert(! protover_all_supported("Link=3-999", &msg));
294 tt_str_op(msg, OP_EQ, "Link=6-999");
295 tor_free(msg);
296 tt_assert(! protover_all_supported("Link=1-3,345-666", &msg));
297 tt_str_op(msg, OP_EQ, "Link=345-666");
298 tor_free(msg);
299 tt_assert(! protover_all_supported("Link=1-3,5-12", &msg));
300 tt_str_op(msg, OP_EQ, "Link=6-12");
301 tor_free(msg);
303 /* Mix of protocols we do support and some we don't, where the protocols
304 * we do support have some versions we don't support. */
305 tt_assert(! protover_all_supported("Link=1-3,5-12 Quokka=9000-9001", &msg));
306 tt_str_op(msg, OP_EQ, "Link=6-12 Quokka=9000-9001");
307 tor_free(msg);
309 /* We shouldn't be able to DoS ourselves parsing a large range. */
310 tt_assert(! protover_all_supported("Sleen=1-2147483648", &msg));
311 tt_str_op(msg, OP_EQ, "Sleen=1-2147483648");
312 tor_free(msg);
314 /* This case is allowed. */
315 tt_assert(! protover_all_supported("Sleen=1-4294967294", &msg));
316 tt_str_op(msg, OP_EQ, "Sleen=1-4294967294");
317 tor_free(msg);
319 /* If we get a (barely) valid (but unsupported list, we say "yes, that's
320 * supported." */
321 tt_assert(protover_all_supported("Fribble=", &msg));
322 tt_ptr_op(msg, OP_EQ, NULL);
324 #ifndef ALL_BUGS_ARE_FATAL
325 /* If we get a completely unparseable list, protover_all_supported should
326 * hit a fatal assertion for BUG(entries == NULL). */
327 tor_capture_bugs_(1);
328 tt_assert(protover_all_supported("Fribble", &msg));
329 tor_end_capture_bugs_();
331 /* If we get a completely unparseable list, protover_all_supported should
332 * hit a fatal assertion for BUG(entries == NULL). */
333 tor_capture_bugs_(1);
334 tt_assert(protover_all_supported("Sleen=1-4294967295", &msg));
335 tor_end_capture_bugs_();
336 #endif /* !defined(ALL_BUGS_ARE_FATAL) */
338 /* Protocol name too long */
339 #if !defined(HAVE_RUST) && !defined(ALL_BUGS_ARE_FATAL)
340 tor_capture_bugs_(1);
341 tt_assert(protover_all_supported(
342 "DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
343 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
344 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
345 "aaaaaaaaaaaa=1-65536", &msg));
346 tor_end_capture_bugs_();
347 #endif /* !defined(HAVE_RUST) && !defined(ALL_BUGS_ARE_FATAL) */
349 done:
350 tor_end_capture_bugs_();
351 tor_free(msg);
354 static void
355 test_protover_list_supports_protocol_returns_true(void *arg)
357 (void)arg;
359 const char *protocols = "Link=1";
360 int is_supported = protocol_list_supports_protocol(protocols, PRT_LINK, 1);
361 tt_int_op(is_supported, OP_EQ, 1);
363 done:
367 static void
368 test_protover_list_supports_protocol_for_unsupported_returns_false(void *arg)
370 (void)arg;
372 const char *protocols = "Link=1";
373 int is_supported = protocol_list_supports_protocol(protocols, PRT_LINK, 10);
374 tt_int_op(is_supported, OP_EQ, 0);
376 done:
380 static void
381 test_protover_supports_version(void *arg)
383 (void)arg;
385 tt_assert(protocol_list_supports_protocol("Link=3-6", PRT_LINK, 3));
386 tt_assert(protocol_list_supports_protocol("Link=3-6", PRT_LINK, 6));
387 tt_assert(!protocol_list_supports_protocol("Link=3-6", PRT_LINK, 7));
388 tt_assert(!protocol_list_supports_protocol("Link=3-6", PRT_LINKAUTH, 3));
390 tt_assert(!protocol_list_supports_protocol("Link=4-6 LinkAuth=3",
391 PRT_LINKAUTH, 2));
392 tt_assert(protocol_list_supports_protocol("Link=4-6 LinkAuth=3",
393 PRT_LINKAUTH, 3));
394 tt_assert(!protocol_list_supports_protocol("Link=4-6 LinkAuth=3",
395 PRT_LINKAUTH, 4));
396 tt_assert(!protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
397 PRT_LINKAUTH, 4));
398 tt_assert(protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
399 PRT_LINKAUTH, 3));
400 tt_assert(protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
401 PRT_LINKAUTH, 2));
403 tt_assert(!protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
404 PRT_DESC, 2));
405 done:
409 /* This could be MAX_PROTOCOLS_TO_EXPAND, but that's not exposed by protover */
410 #define MAX_PROTOCOLS_TO_TEST 1024
412 /* LinkAuth and Relay protocol versions.
413 * Hard-coded here, because they are not in the code, or not exposed in the
414 * headers. */
415 #define PROTOVER_LINKAUTH_V1 1
416 #define PROTOVER_LINKAUTH_V2 2
417 #define PROTOVER_RELAY_V1 1
419 /* Deprecated HSIntro versions */
420 #define PROTOVER_HS_INTRO_DEPRECATED_1 1
421 #define PROTOVER_HS_INTRO_DEPRECATED_2 2
422 /* Highest supported HSv2 introduce protocol version.
423 * It's not clear if we actually support version 2, see #25068. */
424 #define PROTOVER_HS_INTRO_V2 3
426 /* HSv2 Rend and HSDir protocol versions. */
427 #define PROTOVER_HS_RENDEZVOUS_POINT_V2 1
428 #define PROTOVER_HSDIR_V2 1
430 /* DirCache, Desc, Microdesc, and Cons protocol versions. */
431 #define PROTOVER_DIRCACHE_V1 1
432 #define PROTOVER_DIRCACHE_V2 2
434 #define PROTOVER_DESC_V1 1
435 #define PROTOVER_DESC_V2 2
437 #define PROTOVER_MICRODESC_V1 1
438 #define PROTOVER_MICRODESC_V2 2
440 #define PROTOVER_CONS_V1 1
441 #define PROTOVER_CONS_V2 2
443 #define PROTOVER_PADDING_V1 1
445 #define PROTOVER_FLOWCTRL_V1 1
447 /* Make sure we haven't forgotten any supported protocols */
448 static void
449 test_protover_supported_protocols(void *arg)
451 (void)arg;
453 const char *supported_protocols = protover_get_supported_protocols();
455 /* Test for new Link in the code, that hasn't been added to supported
456 * protocols */
457 tt_assert(protocol_list_supports_protocol(supported_protocols,
458 PRT_LINK,
459 MAX_LINK_PROTO));
460 for (uint16_t i = 0; i < MAX_PROTOCOLS_TO_TEST; i++) {
461 tt_int_op(protocol_list_supports_protocol(supported_protocols,
462 PRT_LINK,
464 OP_EQ,
465 is_or_protocol_version_known(i));
468 /* Legacy LinkAuth is only supported on OpenSSL and similar. */
469 tt_int_op(protocol_list_supports_protocol(supported_protocols,
470 PRT_LINKAUTH,
471 PROTOVER_LINKAUTH_V1),
472 OP_EQ,
473 authchallenge_type_is_supported(AUTHTYPE_RSA_SHA256_TLSSECRET));
474 /* LinkAuth=2 is unused */
475 tt_assert(!protocol_list_supports_protocol(supported_protocols,
476 PRT_LINKAUTH,
477 PROTOVER_LINKAUTH_V2));
478 tt_assert(
479 protocol_list_supports_protocol(supported_protocols,
480 PRT_LINKAUTH,
481 PROTOVER_LINKAUTH_ED25519_HANDSHAKE));
483 /* Relay protovers do not appear anywhere in the code. */
484 tt_assert(protocol_list_supports_protocol(supported_protocols,
485 PRT_RELAY,
486 PROTOVER_RELAY_V1));
487 tt_assert(protocol_list_supports_protocol(supported_protocols,
488 PRT_RELAY,
489 PROTOVER_RELAY_EXTEND2));
490 tt_assert(protocol_list_supports_protocol(supported_protocols,
491 PRT_RELAY,
492 PROTOVER_RELAY_ACCEPT_IPV6));
493 tt_assert(protocol_list_supports_protocol(supported_protocols,
494 PRT_RELAY,
495 PROTOVER_RELAY_EXTEND_IPV6));
496 tt_assert(protocol_list_supports_protocol(supported_protocols,
497 PRT_RELAY,
498 PROTOVER_RELAY_CANONICAL_IPV6));
500 /* These HSIntro versions are deprecated */
501 tt_assert(!protocol_list_supports_protocol(supported_protocols,
502 PRT_HSINTRO,
503 PROTOVER_HS_INTRO_DEPRECATED_1));
504 tt_assert(!protocol_list_supports_protocol(supported_protocols,
505 PRT_HSINTRO,
506 PROTOVER_HS_INTRO_DEPRECATED_2));
507 /* We could test legacy HSIntro by calling rend_service_update_descriptor(),
508 * and checking the protocols field. But that's unlikely to change, so
509 * we just use a hard-coded value. */
510 tt_assert(protocol_list_supports_protocol(supported_protocols,
511 PRT_HSINTRO,
512 PROTOVER_HS_INTRO_V2));
513 /* Test for HSv3 HSIntro */
514 tt_assert(protocol_list_supports_protocol(supported_protocols,
515 PRT_HSINTRO,
516 PROTOVER_HS_INTRO_V3));
517 /* Test for HSIntro DoS */
518 tt_assert(protocol_list_supports_protocol(supported_protocols,
519 PRT_HSINTRO,
520 PROTOVER_HS_INTRO_DOS));
522 /* Legacy HSRend does not appear anywhere in the code. */
523 tt_assert(protocol_list_supports_protocol(supported_protocols,
524 PRT_HSREND,
525 PROTOVER_HS_RENDEZVOUS_POINT_V2));
526 /* Test for HSv3 HSRend */
527 tt_assert(protocol_list_supports_protocol(supported_protocols,
528 PRT_HSREND,
529 PROTOVER_HS_RENDEZVOUS_POINT_V3));
531 /* Legacy HSDir does not appear anywhere in the code. */
532 tt_assert(protocol_list_supports_protocol(supported_protocols,
533 PRT_HSDIR,
534 PROTOVER_HSDIR_V2));
535 /* Test for HSv3 HSDir */
536 tt_assert(protocol_list_supports_protocol(supported_protocols,
537 PRT_HSDIR,
538 PROTOVER_HSDIR_V3));
540 /* No DirCache versions appear anywhere in the code. */
541 tt_assert(protocol_list_supports_protocol(supported_protocols,
542 PRT_DIRCACHE,
543 PROTOVER_DIRCACHE_V1));
544 tt_assert(protocol_list_supports_protocol(supported_protocols,
545 PRT_DIRCACHE,
546 PROTOVER_DIRCACHE_V2));
548 /* No Desc versions appear anywhere in the code. */
549 tt_assert(protocol_list_supports_protocol(supported_protocols,
550 PRT_DESC,
551 PROTOVER_DESC_V1));
552 tt_assert(protocol_list_supports_protocol(supported_protocols,
553 PRT_DESC,
554 PROTOVER_DESC_V2));
555 /* Is there any way to test for new Desc? */
557 /* No Microdesc versions appear anywhere in the code. */
558 tt_assert(protocol_list_supports_protocol(supported_protocols,
559 PRT_MICRODESC,
560 PROTOVER_MICRODESC_V1));
561 tt_assert(protocol_list_supports_protocol(supported_protocols,
562 PRT_MICRODESC,
563 PROTOVER_MICRODESC_V2));
565 /* No Cons versions appear anywhere in the code. */
566 tt_assert(protocol_list_supports_protocol(supported_protocols,
567 PRT_CONS,
568 PROTOVER_CONS_V1));
569 tt_assert(protocol_list_supports_protocol(supported_protocols,
570 PRT_CONS,
571 PROTOVER_CONS_V2));
573 /* Padding=1 is deprecated. */
574 tt_assert(!protocol_list_supports_protocol(supported_protocols,
575 PRT_PADDING,
576 PROTOVER_PADDING_V1));
577 tt_assert(protocol_list_supports_protocol(supported_protocols,
578 PRT_PADDING,
579 PROTOVER_HS_SETUP_PADDING));
581 /* FlowCtrl */
582 tt_assert(protocol_list_supports_protocol(supported_protocols,
583 PRT_FLOWCTRL,
584 PROTOVER_FLOWCTRL_V1));
586 done:
590 static void
591 test_protover_vote_roundtrip(void *args)
593 (void) args;
594 static const struct {
595 const char *input;
596 const char *expected_output;
597 } examples[] = {
598 { "Risqu\u00e9=1", NULL },
599 { ",,,=1", NULL },
600 { "\xc1=1", NULL },
601 { "Foo_Bar=1", NULL },
602 { "Fkrkljdsf", NULL },
603 { "Zn=4294967295", NULL },
604 { "Zn=4294967295-1", NULL },
605 { "Zn=4294967293-4294967295", NULL },
606 /* Will fail because of 4294967295. */
607 { "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,900 Zn=1,4294967295",
608 NULL },
609 { "Foo=1,3 Bar=3 Baz= Quux=9-12,14,15-16,900 Zn=1,4294967294",
610 "Bar=3 Foo=1,3 Quux=9-12,14-16,900 Zn=1,4294967294" },
611 { "Zu16=1,65536", "Zu16=1,65536" },
612 { "N-1=1,2", "N-1=1-2" },
613 { "-1=4294967295", NULL },
614 { "-1=3", "-1=3" },
615 /* junk. */
616 { "!!3@*", NULL },
617 /* Missing equals sign */
618 { "Link=4 Haprauxymatyve Desc=9", NULL },
619 { "Link=4 Haprauxymatyve=7 Desc=9",
620 "Desc=9 Haprauxymatyve=7 Link=4" },
621 { "=10-11", NULL },
622 { "X=10-11", "X=10-11" },
623 { "Link=4 =3 Desc=9", NULL },
624 { "Link=4 Z=3 Desc=9", "Desc=9 Link=4 Z=3" },
625 { "Link=fred", NULL },
626 { "Link=1,fred", NULL },
627 { "Link=1,fred,3", NULL },
628 { "Link=1,9-8,3", NULL },
629 { "Faux=-0", NULL },
630 { "Faux=0--0", NULL },
631 { "Faux=-1", NULL },
632 { "Faux=-1-3", NULL },
633 { "Faux=1--1", NULL },
634 { "Link=1-2-", NULL },
635 { "Link=1-2-3", NULL },
636 { "Faux=1-2-", NULL },
637 { "Faux=1-2-3", NULL },
638 { "Link=\t1,3", NULL },
639 { "Link=1\n,3", NULL },
640 { "Faux=1,\r3", NULL },
641 { "Faux=1,3\f", NULL },
642 /* Large integers */
643 { "Link=4294967296", NULL },
644 /* Large range */
645 { "Sleen=1-501", "Sleen=1-501" },
646 { "Sleen=1-65537", NULL },
647 /* Both C/Rust implementations should be able to handle this mild DoS. */
648 { "Sleen=1-2147483648", NULL },
649 /* Rust tests are built in debug mode, so ints are bounds-checked. */
650 { "Sleen=1-4294967295", NULL },
652 unsigned u;
653 smartlist_t *votes = smartlist_new();
654 char *result = NULL;
656 for (u = 0; u < ARRAY_LENGTH(examples); ++u) {
657 const char *input = examples[u].input;
658 const char *expected_output = examples[u].expected_output;
660 smartlist_add(votes, (void*)input);
661 result = protover_compute_vote(votes, 1);
662 if (expected_output != NULL) {
663 tt_str_op(result, OP_EQ, expected_output);
664 } else {
665 tt_str_op(result, OP_EQ, "");
668 smartlist_clear(votes);
669 tor_free(result);
672 done:
673 smartlist_free(votes);
674 tor_free(result);
677 static void
678 test_protover_vote_roundtrip_ours(void *args)
680 (void) args;
681 const char *examples[] = {
682 protover_get_supported_protocols(),
683 DIRVOTE_RECOMMEND_RELAY_PROTO,
684 DIRVOTE_RECOMMEND_CLIENT_PROTO,
685 DIRVOTE_REQUIRE_RELAY_PROTO,
686 DIRVOTE_REQUIRE_CLIENT_PROTO,
688 unsigned u;
689 smartlist_t *votes = smartlist_new();
690 char *result = NULL;
692 for (u = 0; u < ARRAY_LENGTH(examples); ++u) {
693 tt_assert(examples[u]);
694 const char *input = examples[u];
695 const char *expected_output = examples[u];
697 smartlist_add(votes, (void*)input);
698 result = protover_compute_vote(votes, 1);
699 if (expected_output != NULL) {
700 tt_str_op(result, OP_EQ, expected_output);
701 } else {
702 tt_str_op(result, OP_EQ, "");
705 smartlist_clear(votes);
706 tor_free(result);
709 done:
710 smartlist_free(votes);
711 tor_free(result);
714 /* Stringifies its argument.
715 * 4 -> "4" */
716 #define STR(x) #x
718 #ifdef COCCI
719 #define PROTOVER(proto_string, version_macro)
720 #else
721 /* Generate a protocol version string using proto_string and version_macro.
722 * PROTOVER("HSIntro", PROTOVER_HS_INTRO_DOS) -> "HSIntro" "=" "5"
723 * Uses two levels of macros to turn PROTOVER_HS_INTRO_DOS into "5".
725 #define PROTOVER(proto_string, version_macro) \
726 (proto_string "=" STR(version_macro))
727 #endif
729 #define DEBUG_PROTOVER(flags) \
730 STMT_BEGIN \
731 log_debug(LD_GENERAL, \
732 "protovers:\n" \
733 "protocols_known: %d,\n" \
734 "supports_extend2_cells: %d,\n" \
735 "supports_accepting_ipv6_extends: %d,\n" \
736 "supports_initiating_ipv6_extends: %d,\n" \
737 "supports_canonical_ipv6_conns: %d,\n" \
738 "supports_ed25519_link_handshake_compat: %d,\n" \
739 "supports_ed25519_link_handshake_any: %d,\n" \
740 "supports_ed25519_hs_intro: %d,\n" \
741 "supports_establish_intro_dos_extension: %d,\n" \
742 "supports_v3_hsdir: %d,\n" \
743 "supports_v3_rendezvous_point: %d,\n" \
744 "supports_hs_setup_padding: %d.", \
745 (flags).protocols_known, \
746 (flags).supports_extend2_cells, \
747 (flags).supports_accepting_ipv6_extends, \
748 (flags).supports_initiating_ipv6_extends, \
749 (flags).supports_canonical_ipv6_conns, \
750 (flags).supports_ed25519_link_handshake_compat, \
751 (flags).supports_ed25519_link_handshake_any, \
752 (flags).supports_ed25519_hs_intro, \
753 (flags).supports_establish_intro_dos_extension, \
754 (flags).supports_v3_hsdir, \
755 (flags).supports_v3_rendezvous_point, \
756 (flags).supports_hs_setup_padding); \
757 STMT_END
759 /* Test that the proto_string version version_macro sets summary_flag. */
760 #define TEST_PROTOVER(proto_string, version_macro, summary_flag) \
761 STMT_BEGIN \
762 memset(&flags, 0, sizeof(flags)); \
763 summarize_protover_flags(&flags, \
764 PROTOVER(proto_string, version_macro), \
765 NULL); \
766 DEBUG_PROTOVER(flags); \
767 tt_int_op(flags.protocols_known, OP_EQ, 1); \
768 tt_int_op(flags.summary_flag, OP_EQ, 1); \
769 flags.protocols_known = 0; \
770 flags.summary_flag = 0; \
771 tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags)); \
772 STMT_END
774 static void
775 test_protover_summarize_flags(void *args)
777 (void) args;
778 char pv[30];
779 memset(&pv, 0, sizeof(pv));
781 protover_summary_cache_free_all();
783 protover_summary_flags_t zero_flags;
784 memset(&zero_flags, 0, sizeof(zero_flags));
785 protover_summary_flags_t flags;
787 memset(&flags, 0, sizeof(flags));
788 summarize_protover_flags(&flags, NULL, NULL);
789 DEBUG_PROTOVER(flags);
790 tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
792 memset(&flags, 0, sizeof(flags));
793 summarize_protover_flags(&flags, "", "");
794 DEBUG_PROTOVER(flags);
795 tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
797 /* Now check version exceptions */
799 /* EXTEND2 cell support */
800 memset(&flags, 0, sizeof(flags));
801 summarize_protover_flags(&flags, NULL, "Tor 0.2.4.8-alpha");
802 DEBUG_PROTOVER(flags);
803 tt_int_op(flags.protocols_known, OP_EQ, 1);
804 tt_int_op(flags.supports_extend2_cells, OP_EQ, 1);
805 /* Now clear those flags, and check the rest are zero */
806 flags.protocols_known = 0;
807 flags.supports_extend2_cells = 0;
808 tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
810 /* disabling HSDir v3 support for buggy versions */
811 memset(&flags, 0, sizeof(flags));
812 summarize_protover_flags(&flags,
813 PROTOVER("HSDir", PROTOVER_HSDIR_V3),
814 NULL);
815 DEBUG_PROTOVER(flags);
816 tt_int_op(flags.protocols_known, OP_EQ, 1);
817 tt_int_op(flags.supports_v3_hsdir, OP_EQ, 1);
818 /* Now clear those flags, and check the rest are zero */
819 flags.protocols_known = 0;
820 flags.supports_v3_hsdir = 0;
821 tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
823 memset(&flags, 0, sizeof(flags));
824 summarize_protover_flags(&flags,
825 PROTOVER("HSDir", PROTOVER_HSDIR_V3),
826 "Tor 0.3.0.7");
827 DEBUG_PROTOVER(flags);
828 tt_int_op(flags.protocols_known, OP_EQ, 1);
829 /* Now clear that flag, and check the rest are zero */
830 flags.protocols_known = 0;
831 tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
833 /* Now check standard summaries */
835 /* LinkAuth */
836 memset(&flags, 0, sizeof(flags));
837 summarize_protover_flags(&flags,
838 PROTOVER("LinkAuth",
839 PROTOVER_LINKAUTH_ED25519_HANDSHAKE),
840 NULL);
841 DEBUG_PROTOVER(flags);
842 tt_int_op(flags.protocols_known, OP_EQ, 1);
843 tt_int_op(flags.supports_ed25519_link_handshake_compat, OP_EQ, 1);
844 tt_int_op(flags.supports_ed25519_link_handshake_any, OP_EQ, 1);
845 /* Now clear those flags, and check the rest are zero */
846 flags.protocols_known = 0;
847 flags.supports_ed25519_link_handshake_compat = 0;
848 flags.supports_ed25519_link_handshake_any = 0;
849 tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
851 /* Test one greater */
852 memset(&flags, 0, sizeof(flags));
853 snprintf(pv, sizeof(pv),
854 "%s=%d", "LinkAuth", PROTOVER_LINKAUTH_ED25519_HANDSHAKE + 1);
855 summarize_protover_flags(&flags, pv, NULL);
856 DEBUG_PROTOVER(flags);
857 tt_int_op(flags.protocols_known, OP_EQ, 1);
858 tt_int_op(flags.supports_ed25519_link_handshake_compat, OP_EQ, 0);
859 tt_int_op(flags.supports_ed25519_link_handshake_any, OP_EQ, 1);
860 /* Now clear those flags, and check the rest are zero */
861 flags.protocols_known = 0;
862 flags.supports_ed25519_link_handshake_compat = 0;
863 flags.supports_ed25519_link_handshake_any = 0;
864 tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
866 /* Test one less */
867 memset(&flags, 0, sizeof(flags));
868 snprintf(pv, sizeof(pv),
869 "%s=%d", "LinkAuth", PROTOVER_LINKAUTH_ED25519_HANDSHAKE - 1);
870 summarize_protover_flags(&flags, pv, NULL);
871 DEBUG_PROTOVER(flags);
872 tt_int_op(flags.protocols_known, OP_EQ, 1);
873 tt_int_op(flags.supports_ed25519_link_handshake_compat, OP_EQ, 0);
874 tt_int_op(flags.supports_ed25519_link_handshake_any, OP_EQ, 0);
875 /* Now clear those flags, and check the rest are zero */
876 flags.protocols_known = 0;
877 flags.supports_ed25519_link_handshake_compat = 0;
878 flags.supports_ed25519_link_handshake_any = 0;
879 tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
881 /* We don't test "one more" and "one less" for each protocol version.
882 * But that could be a useful thing to add. */
884 /* Relay */
885 memset(&flags, 0, sizeof(flags));
886 /* This test relies on these versions being equal */
887 tt_int_op(PROTOVER_RELAY_EXTEND2, OP_EQ, PROTOVER_RELAY_ACCEPT_IPV6);
888 summarize_protover_flags(&flags,
889 PROTOVER("Relay", PROTOVER_RELAY_EXTEND2), NULL);
890 DEBUG_PROTOVER(flags);
891 tt_int_op(flags.protocols_known, OP_EQ, 1);
892 tt_int_op(flags.supports_extend2_cells, OP_EQ, 1);
893 tt_int_op(flags.supports_accepting_ipv6_extends, OP_EQ, 1);
894 /* Now clear those flags, and check the rest are zero */
895 flags.protocols_known = 0;
896 flags.supports_extend2_cells = 0;
897 flags.supports_accepting_ipv6_extends = 0;
898 tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
900 memset(&flags, 0, sizeof(flags));
901 /* This test relies on these versions being equal */
902 tt_int_op(PROTOVER_RELAY_EXTEND_IPV6, OP_EQ, PROTOVER_RELAY_CANONICAL_IPV6);
903 summarize_protover_flags(&flags,
904 PROTOVER("Relay", PROTOVER_RELAY_EXTEND_IPV6),
905 NULL);
906 DEBUG_PROTOVER(flags);
907 tt_int_op(flags.protocols_known, OP_EQ, 1);
908 tt_int_op(flags.supports_accepting_ipv6_extends, OP_EQ, 1);
909 tt_int_op(flags.supports_initiating_ipv6_extends, OP_EQ, 1);
910 tt_int_op(flags.supports_canonical_ipv6_conns, OP_EQ, 1);
911 /* Now clear those flags, and check the rest are zero */
912 flags.protocols_known = 0;
913 flags.supports_accepting_ipv6_extends = 0;
914 flags.supports_initiating_ipv6_extends = 0;
915 flags.supports_canonical_ipv6_conns = 0;
916 tt_mem_op(&flags, OP_EQ, &zero_flags, sizeof(flags));
918 TEST_PROTOVER("HSIntro", PROTOVER_HS_INTRO_V3,
919 supports_ed25519_hs_intro);
920 TEST_PROTOVER("HSIntro", PROTOVER_HS_INTRO_DOS,
921 supports_establish_intro_dos_extension);
923 TEST_PROTOVER("HSRend", PROTOVER_HS_RENDEZVOUS_POINT_V3,
924 supports_v3_rendezvous_point);
926 TEST_PROTOVER("HSDir", PROTOVER_HSDIR_V3,
927 supports_v3_hsdir);
929 TEST_PROTOVER("Padding", PROTOVER_HS_SETUP_PADDING,
930 supports_hs_setup_padding);
932 done:
936 #define PV_TEST(name, flags) \
937 { #name, test_protover_ ##name, (flags), NULL, NULL }
939 struct testcase_t protover_tests[] = {
940 PV_TEST(parse, 0),
941 PV_TEST(parse_fail, 0),
942 PV_TEST(vote, 0),
943 PV_TEST(all_supported, 0),
944 PV_TEST(list_supports_protocol_for_unsupported_returns_false, 0),
945 PV_TEST(list_supports_protocol_returns_true, 0),
946 PV_TEST(supports_version, 0),
947 PV_TEST(supported_protocols, 0),
948 PV_TEST(vote_roundtrip, 0),
949 PV_TEST(vote_roundtrip_ours, 0),
950 /* fork, because we memoize flags internally */
951 PV_TEST(summarize_flags, TT_FORK),
952 END_OF_TESTCASES