Update copyrights to 2021, using "make update-copyright"
[tor.git] / src / test / test_protover.c
blob696f7a706168b3f84e404ab038c90ace2c207b68
1 /* Copyright (c) 2016-2021, 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";
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 e = smartlist_get(elts, 0);
43 tt_str_op(e->name, OP_EQ, "Foo");
44 tt_int_op(e->bitmask, OP_EQ, 0x0a);
46 e = smartlist_get(elts, 1);
47 tt_str_op(e->name, OP_EQ, "Bar");
48 tt_int_op(e->bitmask, OP_EQ, 0x08);
50 e = smartlist_get(elts, 2);
51 tt_str_op(e->name, OP_EQ, "Baz");
52 tt_int_op(e->bitmask, OP_EQ, 0x00);
54 e = smartlist_get(elts, 3);
55 tt_str_op(e->name, OP_EQ, "Quux");
56 tt_int_op(e->bitmask, OP_EQ, 0x1de00);
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");
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) */
70 static void
71 test_protover_parse_fail(void *arg)
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;
81 /* random junk */
82 elts = parse_protocol_list("!!3@*");
83 tt_ptr_op(elts, OP_EQ, NULL);
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);
89 /* Missing word. */
90 elts = parse_protocol_list("Link=4 =3 Desc=9");
91 tt_ptr_op(elts, OP_EQ, NULL);
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);
101 /* Broken range */
102 elts = parse_protocol_list("Link=1,9-8,3");
103 tt_ptr_op(elts, OP_EQ, NULL);
105 /* Protocol name too long */
106 elts = parse_protocol_list("DoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
107 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
108 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
109 tt_ptr_op(elts, OP_EQ, NULL);
111 #endif /* defined(HAVE_RUST) */
112 done:
116 static void
117 test_protover_vote(void *arg)
119 (void) arg;
121 smartlist_t *lst = smartlist_new();
122 char *result = protover_compute_vote(lst, 1);
124 tt_str_op(result, OP_EQ, "");
125 tor_free(result);
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);
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);
137 result = protover_compute_vote(lst, 2);
138 tt_str_op(result, OP_EQ, "Bar=3-6,8 Foo=9");
139 tor_free(result);
141 /* High threshold */
142 result = protover_compute_vote(lst, 3);
143 tt_str_op(result, OP_EQ, "");
144 tor_free(result);
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);
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);
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);
168 /* Vote large protover lists that are just below the threshold */
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);
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);
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);
193 done:
194 tor_free(result);
195 smartlist_free(lst);
198 static void
199 test_protover_all_supported(void *arg)
201 (void)arg;
202 char *msg = NULL;
204 tt_assert(protover_all_supported(NULL, &msg));
205 tt_ptr_op(msg, OP_EQ, NULL);
207 tt_assert(protover_all_supported("", &msg));
208 tt_ptr_op(msg, OP_EQ, NULL);
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);
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);
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);
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);
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);
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);
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_();
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) */
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) */
278 done:
279 tor_end_capture_bugs_();
280 tor_free(msg);
283 static void
284 test_protover_list_supports_protocol_returns_true(void *arg)
286 (void)arg;
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);
292 done:
296 static void
297 test_protover_list_supports_protocol_for_unsupported_returns_false(void *arg)
299 (void)arg;
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);
305 done:
309 static void
310 test_protover_supports_version(void *arg)
312 (void)arg;
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));
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));
332 tt_assert(!protocol_list_supports_protocol_or_later("Link=4-6 LinkAuth=3",
333 PRT_DESC, 2));
334 done:
338 /* This could be MAX_PROTOCOLS_TO_EXPAND, but that's not exposed by protover */
339 #define MAX_PROTOCOLS_TO_TEST 1024
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
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
355 /* HSv2 Rend and HSDir protocol versions. */
356 #define PROTOVER_HS_RENDEZVOUS_POINT_V2 1
357 #define PROTOVER_HSDIR_V2 1
359 /* DirCache, Desc, Microdesc, and Cons protocol versions. */
360 #define PROTOVER_DIRCACHE_V1 1
361 #define PROTOVER_DIRCACHE_V2 2
363 #define PROTOVER_DESC_V1 1
364 #define PROTOVER_DESC_V2 2
366 #define PROTOVER_MICRODESC_V1 1
367 #define PROTOVER_MICRODESC_V2 2
369 #define PROTOVER_CONS_V1 1
370 #define PROTOVER_CONS_V2 2
372 #define PROTOVER_PADDING_V1 1
374 #define PROTOVER_FLOWCTRL_V1 1
376 /* Make sure we haven't forgotten any supported protocols */
377 static void
378 test_protover_supported_protocols(void *arg)
380 (void)arg;
382 const char *supported_protocols = protover_get_supported_protocols();
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,
393 OP_EQ,
394 is_or_protocol_version_known(i));
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));
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));
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));
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));
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));
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));
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? */
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));
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));
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));
507 /* FlowCtrl */
508 tt_assert(protocol_list_supports_protocol(supported_protocols,
509 PRT_FLOWCTRL,
510 PROTOVER_FLOWCTRL_V1));
512 done:
516 static void
517 test_protover_vote_roundtrip(void *args)
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 },
578 unsigned u;
579 smartlist_t *votes = smartlist_new();
580 char *result = NULL;
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;
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, "");
594 smartlist_clear(votes);
595 tor_free(result);
598 done:
599 smartlist_free(votes);
600 tor_free(result);
603 static void
604 test_protover_vote_roundtrip_ours(void *args)
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,
614 unsigned u;
615 smartlist_t *votes = smartlist_new();
616 char *result = NULL;
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];
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, "");
631 smartlist_clear(votes);
632 tor_free(result);
635 done:
636 smartlist_free(votes);
637 tor_free(result);
640 /* Stringifies its argument.
641 * 4 -> "4" */
642 #define STR(x) #x
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".
651 #define PROTOVER(proto_string, version_macro) \
652 (proto_string "=" STR(version_macro))
653 #endif
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
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
700 static void
701 test_protover_summarize_flags(void *args)
703 (void) args;
704 char pv[30];
705 memset(&pv, 0, sizeof(pv));
707 protover_summary_cache_free_all();
709 protover_summary_flags_t zero_flags;
710 memset(&zero_flags, 0, sizeof(zero_flags));
711 protover_summary_flags_t flags;
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));
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));
723 /* Now check version exceptions */
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));
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));
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));
759 /* Now check standard summaries */
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));
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));
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));
807 /* We don't test "one more" and "one less" for each protocol version.
808 * But that could be a useful thing to add. */
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));
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));
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);
849 TEST_PROTOVER("HSRend", PROTOVER_HS_RENDEZVOUS_POINT_V3,
850 supports_v3_rendezvous_point);
852 TEST_PROTOVER("HSDir", PROTOVER_HSDIR_V3,
853 supports_v3_hsdir);
855 TEST_PROTOVER("Padding", PROTOVER_HS_SETUP_PADDING,
856 supports_hs_setup_padding);
858 done:
862 #define PV_TEST(name, flags) \
863 { #name, test_protover_ ##name, (flags), NULL, NULL }
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