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