1 /* Copyright (c) 2017-2020, The Tor Project, Inc. */
2 /* Copyright (c) 2017, isis agora lovecruft */
3 /* See LICENSE for licensing information */
7 * \brief Unittests for code in router.c
10 #define CONFIG_PRIVATE
11 #define CONNECTION_PRIVATE
12 #define ROUTER_PRIVATE
14 #include "core/or/or.h"
15 #include "app/config/config.h"
16 #include "core/mainloop/mainloop.h"
17 #include "core/mainloop/connection.h"
18 #include "feature/hibernate/hibernate.h"
19 #include "feature/nodelist/networkstatus.h"
20 #include "feature/nodelist/networkstatus_st.h"
21 #include "feature/nodelist/node_st.h"
22 #include "feature/nodelist/nodelist.h"
23 #include "feature/nodelist/routerinfo_st.h"
24 #include "feature/nodelist/routerlist.h"
25 #include "feature/nodelist/routerstatus_st.h"
26 #include "feature/nodelist/torcert.h"
27 #include "feature/relay/router.h"
28 #include "feature/stats/bwhist.h"
29 #include "lib/crypt_ops/crypto_curve25519.h"
30 #include "lib/crypt_ops/crypto_ed25519.h"
31 #include "lib/encoding/confline.h"
33 #include "core/or/listener_connection_st.h"
35 /* Test suite stuff */
36 #include "test/test.h"
37 #include "test/log_test_helpers.h"
40 rtr_tests_gen_routerinfo(crypto_pk_t
*ident_key
, crypto_pk_t
*tap_key
)
44 routerinfo_t
*mock_routerinfo
;
46 /* Mock the published timestamp, otherwise router_dump_router_to_string()
47 * will poop its pants. */
50 /* We'll need keys, or router_dump_router_to_string() would return NULL. */
51 tor_assert(ident_key
!= NULL
);
52 tor_assert(tap_key
!= NULL
);
54 mock_routerinfo
= tor_malloc_zero(sizeof(routerinfo_t
));
55 mock_routerinfo
->nickname
= tor_strdup("ConlonNancarrow");
56 tor_addr_from_ipv4h(&mock_routerinfo
->ipv4_addr
, 123456789);
57 mock_routerinfo
->ipv4_orport
= 443;
58 mock_routerinfo
->platform
= tor_strdup("unittest");
59 mock_routerinfo
->cache_info
.published_on
= now
;
60 mock_routerinfo
->identity_pkey
= crypto_pk_dup_key(ident_key
);
61 mock_routerinfo
->protocol_list
=
62 tor_strdup("Cons=1-2 Desc=1-2 DirCache=1-2");
63 router_set_rsa_onion_pkey(tap_key
, &mock_routerinfo
->onion_pkey
,
64 &mock_routerinfo
->onion_pkey_len
);
65 mock_routerinfo
->bandwidthrate
= 9001;
66 mock_routerinfo
->bandwidthburst
= 9002;
68 return mock_routerinfo
;
71 /* If no distribution option was set, then check_bridge_distribution_setting()
72 * should have set it to "any". */
74 test_router_dump_router_to_string_no_bridge_distribution_method(void *arg
)
76 const char* needle
= "bridge-distribution-request any";
77 or_options_t
* options
= get_options_mutable();
78 routerinfo_t
* router
= NULL
;
79 curve25519_keypair_t ntor_keypair
;
80 ed25519_keypair_t signing_keypair
;
81 ed25519_keypair_t identity_keypair
;
85 crypto_pk_t
*ident_key
= pk_generate(0);
86 crypto_pk_t
*tap_key
= pk_generate(0);
88 options
->ORPort_set
= 1;
89 options
->BridgeRelay
= 1;
91 /* Generate keys which router_dump_router_to_string() expects to exist. */
92 tt_int_op(0, OP_EQ
, curve25519_keypair_generate(&ntor_keypair
, 0));
93 tt_int_op(0, OP_EQ
, ed25519_keypair_generate(&signing_keypair
, 0));
94 tt_int_op(0, OP_EQ
, ed25519_keypair_generate(&identity_keypair
, 0));
96 /* Set up part of our routerinfo_t so that we don't trigger any other
97 * assertions in router_dump_router_to_string(). */
98 router
= rtr_tests_gen_routerinfo(ident_key
, tap_key
);
99 tt_ptr_op(router
, OP_NE
, NULL
);
101 router
->cache_info
.signing_key_cert
=
102 tor_cert_create_ed25519(&identity_keypair
,
103 CERT_TYPE_ID_SIGNING
,
104 &signing_keypair
.pubkey
,
107 CERT_FLAG_INCLUDE_SIGNING_KEY
);
109 /* The real router_get_my_routerinfo() looks up onion_curve25519_pkey using
110 * get_current_curve25519_keypair(), but we don't initialise static data in
112 router
->onion_curve25519_pkey
= &ntor_keypair
.pubkey
;
114 /* Generate our server descriptor and ensure that the substring
115 * "bridge-distribution-request any" occurs somewhere within it. */
116 desc
= router_dump_router_to_string(router
,
121 tt_ptr_op(desc
, OP_NE
, NULL
);
122 found
= strstr(desc
, needle
);
123 tt_ptr_op(found
, OP_NE
, NULL
);
127 router
->onion_curve25519_pkey
= NULL
; // avoid double-free
128 routerinfo_free(router
);
130 crypto_pk_free(ident_key
);
131 crypto_pk_free(tap_key
);
134 static routerinfo_t
*mock_router_get_my_routerinfo_result
= NULL
;
136 static const routerinfo_t
*
137 mock_router_get_my_routerinfo(void)
139 return mock_router_get_my_routerinfo_result
;
143 mock_get_uptime_3h(void)
149 mock_get_uptime_1d(void)
155 mock_rep_hist_bandwidth_assess(void)
161 mock_we_are_not_hibernating(void)
167 mock_we_are_hibernating(void)
173 test_router_check_descriptor_bandwidth_changed(void *arg
)
176 routerinfo_t routerinfo
;
177 memset(&routerinfo
, 0, sizeof(routerinfo
));
178 mock_router_get_my_routerinfo_result
= NULL
;
180 MOCK(we_are_hibernating
, mock_we_are_not_hibernating
);
181 MOCK(router_get_my_routerinfo
, mock_router_get_my_routerinfo
);
182 mock_router_get_my_routerinfo_result
= &routerinfo
;
184 /* When uptime is less than 24h, no previous bandwidth, no last_changed
185 * Uptime: 10800, last_changed: 0, Previous bw: 0, Current bw: 0 */
186 routerinfo
.bandwidthcapacity
= 0;
187 MOCK(get_uptime
, mock_get_uptime_3h
);
188 setup_full_capture_of_logs(LOG_INFO
);
189 check_descriptor_bandwidth_changed(time(NULL
));
190 expect_log_msg_not_containing(
191 "Measured bandwidth has changed; rebuilding descriptor.");
192 teardown_capture_of_logs();
194 /* When uptime is less than 24h, previous bandwidth,
195 * last_changed more than 3h ago
196 * Uptime: 10800, last_changed: 0, Previous bw: 10000, Current bw: 0 */
197 routerinfo
.bandwidthcapacity
= 10000;
198 setup_full_capture_of_logs(LOG_INFO
);
199 check_descriptor_bandwidth_changed(time(NULL
));
200 expect_log_msg_containing(
201 "Measured bandwidth has changed; rebuilding descriptor.");
202 teardown_capture_of_logs();
204 /* When uptime is less than 24h, previous bandwidth,
205 * last_changed more than 3h ago, and hibernating
206 * Uptime: 10800, last_changed: 0, Previous bw: 10000, Current bw: 0 */
208 UNMOCK(we_are_hibernating
);
209 MOCK(we_are_hibernating
, mock_we_are_hibernating
);
210 routerinfo
.bandwidthcapacity
= 10000;
211 setup_full_capture_of_logs(LOG_INFO
);
212 check_descriptor_bandwidth_changed(time(NULL
));
213 expect_log_msg_not_containing(
214 "Measured bandwidth has changed; rebuilding descriptor.");
215 teardown_capture_of_logs();
216 UNMOCK(we_are_hibernating
);
217 MOCK(we_are_hibernating
, mock_we_are_not_hibernating
);
219 /* When uptime is less than 24h, last_changed is not more than 3h ago
220 * Uptime: 10800, last_changed: x, Previous bw: 10000, Current bw: 0 */
221 setup_full_capture_of_logs(LOG_INFO
);
222 check_descriptor_bandwidth_changed(time(NULL
));
223 expect_log_msg_not_containing(
224 "Measured bandwidth has changed; rebuilding descriptor.");
225 teardown_capture_of_logs();
227 /* When uptime is less than 24h and bandwidthcapacity does not change
228 * Uptime: 10800, last_changed: x, Previous bw: 10000, Current bw: 20001 */
229 MOCK(bwhist_bandwidth_assess
, mock_rep_hist_bandwidth_assess
);
230 setup_full_capture_of_logs(LOG_INFO
);
231 check_descriptor_bandwidth_changed(time(NULL
) + 6*60*60 + 1);
232 expect_log_msg_containing(
233 "Measured bandwidth has changed; rebuilding descriptor.");
235 UNMOCK(bwhist_bandwidth_assess
);
236 teardown_capture_of_logs();
238 /* When uptime is more than 24h */
239 MOCK(get_uptime
, mock_get_uptime_1d
);
240 setup_full_capture_of_logs(LOG_INFO
);
241 check_descriptor_bandwidth_changed(time(NULL
));
242 expect_log_msg_not_containing(
243 "Measured bandwidth has changed; rebuilding descriptor.");
244 teardown_capture_of_logs();
248 UNMOCK(router_get_my_routerinfo
);
249 UNMOCK(we_are_hibernating
);
252 static networkstatus_t
*mock_ns
= NULL
;
253 static networkstatus_t
*
254 mock_networkstatus_get_live_consensus(time_t now
)
260 static routerstatus_t
*mock_rs
= NULL
;
261 static const routerstatus_t
*
262 mock_networkstatus_vote_find_entry(networkstatus_t
*ns
, const char *digest
)
270 test_router_mark_if_too_old(void *arg
)
273 time_t now
= approx_time();
274 MOCK(networkstatus_get_live_consensus
,
275 mock_networkstatus_get_live_consensus
);
276 MOCK(networkstatus_vote_find_entry
, mock_networkstatus_vote_find_entry
);
280 memset(&rs
, 0, sizeof(rs
));
281 memset(&ns
, 0, sizeof(ns
));
283 mock_ns
->valid_after
= now
-3600;
285 mock_rs
->published_on
= now
- 10;
287 // no reason to mark this time.
288 desc_clean_since
= now
-10;
289 desc_dirty_reason
= NULL
;
290 mark_my_descriptor_dirty_if_too_old(now
);
291 tt_i64_op(desc_clean_since
, OP_EQ
, now
-10);
293 // Doesn't appear in consensus? Still don't mark it.
295 mark_my_descriptor_dirty_if_too_old(now
);
296 tt_i64_op(desc_clean_since
, OP_EQ
, now
-10);
299 // No new descriptor in a long time? Mark it.
300 desc_clean_since
= now
- 3600 * 96;
301 mark_my_descriptor_dirty_if_too_old(now
);
302 tt_i64_op(desc_clean_since
, OP_EQ
, 0);
303 tt_str_op(desc_dirty_reason
, OP_EQ
, "time for new descriptor");
305 // Version in consensus published a long time ago? We won't mark it
306 // if it's been clean for only a short time.
307 desc_clean_since
= now
- 10;
308 desc_dirty_reason
= NULL
;
309 mock_rs
->published_on
= now
- 3600 * 96;
310 mark_my_descriptor_dirty_if_too_old(now
);
311 tt_i64_op(desc_clean_since
, OP_EQ
, now
- 10);
313 // ... but if it's been clean a while, we mark.
314 desc_clean_since
= now
- 2 * 3600;
315 mark_my_descriptor_dirty_if_too_old(now
);
316 tt_i64_op(desc_clean_since
, OP_EQ
, 0);
317 tt_str_op(desc_dirty_reason
, OP_EQ
,
318 "version listed in consensus is quite old");
320 // same deal if we're marked stale.
321 desc_clean_since
= now
- 2 * 3600;
322 desc_dirty_reason
= NULL
;
323 mock_rs
->published_on
= now
- 10;
324 mock_rs
->is_staledesc
= 1;
325 mark_my_descriptor_dirty_if_too_old(now
);
326 tt_i64_op(desc_clean_since
, OP_EQ
, 0);
327 tt_str_op(desc_dirty_reason
, OP_EQ
,
328 "listed as stale in consensus");
330 // same deal if we're absent from the consensus.
331 desc_clean_since
= now
- 2 * 3600;
332 desc_dirty_reason
= NULL
;
334 mark_my_descriptor_dirty_if_too_old(now
);
335 tt_i64_op(desc_clean_since
, OP_EQ
, 0);
336 tt_str_op(desc_dirty_reason
, OP_EQ
,
337 "not listed in consensus");
340 UNMOCK(networkstatus_get_live_consensus
);
341 UNMOCK(networkstatus_vote_find_entry
);
344 static node_t fake_node
;
345 static const node_t
*
346 mock_node_get_by_nickname(const char *name
, unsigned flags
)
349 if (!strcasecmp(name
, "crumpet"))
356 test_router_get_my_family(void *arg
)
359 or_options_t
*options
= options_new();
360 smartlist_t
*sl
= NULL
;
362 // Overwrite the result of router_get_my_identity_digest(). This
363 // happens to be okay, but only for testing.
364 set_server_identity_key_digest_testing(
365 (const uint8_t*)"holeinthebottomofthe");
367 setup_capture_of_logs(LOG_WARN
);
369 // No family listed -- so there's no list.
370 sl
= get_my_declared_family(options
);
371 tt_ptr_op(sl
, OP_EQ
, NULL
);
372 expect_no_log_entry();
374 #define CLEAR() do { \
376 SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); \
377 smartlist_free(sl); \
380 mock_clean_saved_logs(); \
383 // Add a single nice friendly hex member. This should be enough
384 // to have our own ID added.
385 tt_ptr_op(options
->MyFamily
, OP_EQ
, NULL
);
386 config_line_append(&options
->MyFamily
, "MyFamily",
387 "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
389 sl
= get_my_declared_family(options
);
390 tt_ptr_op(sl
, OP_NE
, NULL
);
391 tt_int_op(smartlist_len(sl
), OP_EQ
, 2);
392 join
= smartlist_join_strings(sl
, " ", 0, NULL
);
393 tt_str_op(join
, OP_EQ
,
394 "$686F6C65696E746865626F74746F6D6F66746865 "
395 "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
396 expect_no_log_entry();
399 // Add a hex member with a ~. The ~ part should get removed.
400 config_line_append(&options
->MyFamily
, "MyFamily",
401 "$0123456789abcdef0123456789abcdef01234567~Muffin");
402 sl
= get_my_declared_family(options
);
403 tt_ptr_op(sl
, OP_NE
, NULL
);
404 tt_int_op(smartlist_len(sl
), OP_EQ
, 3);
405 join
= smartlist_join_strings(sl
, " ", 0, NULL
);
406 tt_str_op(join
, OP_EQ
,
407 "$0123456789ABCDEF0123456789ABCDEF01234567 "
408 "$686F6C65696E746865626F74746F6D6F66746865 "
409 "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
410 expect_no_log_entry();
413 // Nickname lookup will fail, so a nickname will appear verbatim.
414 config_line_append(&options
->MyFamily
, "MyFamily",
416 sl
= get_my_declared_family(options
);
417 tt_ptr_op(sl
, OP_NE
, NULL
);
418 tt_int_op(smartlist_len(sl
), OP_EQ
, 4);
419 join
= smartlist_join_strings(sl
, " ", 0, NULL
);
420 tt_str_op(join
, OP_EQ
,
421 "$0123456789ABCDEF0123456789ABCDEF01234567 "
422 "$686F6C65696E746865626F74746F6D6F66746865 "
423 "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
425 expect_single_log_msg_containing(
426 "There is a router named \"BAGEL\" in my declared family, but "
427 "I have no descriptor for it.");
430 // A bogus digest should fail entirely.
431 config_line_append(&options
->MyFamily
, "MyFamily",
433 sl
= get_my_declared_family(options
);
434 tt_ptr_op(sl
, OP_NE
, NULL
);
435 tt_int_op(smartlist_len(sl
), OP_EQ
, 4);
436 join
= smartlist_join_strings(sl
, " ", 0, NULL
);
437 tt_str_op(join
, OP_EQ
,
438 "$0123456789ABCDEF0123456789ABCDEF01234567 "
439 "$686F6C65696E746865626F74746F6D6F66746865 "
440 "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
442 // "BAGEL" is still there, but it won't make a warning, because we already
444 expect_single_log_msg_containing(
445 "There is a router named \"$painauchocolat\" in my declared "
446 "family, but that isn't a legal digest or nickname. Skipping it.");
449 // Let's introduce a node we can look up by nickname
450 memset(&fake_node
, 0, sizeof(fake_node
));
451 memcpy(fake_node
.identity
, "whydoyouasknonononon", DIGEST_LEN
);
452 MOCK(node_get_by_nickname
, mock_node_get_by_nickname
);
454 config_line_append(&options
->MyFamily
, "MyFamily",
456 sl
= get_my_declared_family(options
);
457 tt_ptr_op(sl
, OP_NE
, NULL
);
458 tt_int_op(smartlist_len(sl
), OP_EQ
, 5);
459 join
= smartlist_join_strings(sl
, " ", 0, NULL
);
460 tt_str_op(join
, OP_EQ
,
461 "$0123456789ABCDEF0123456789ABCDEF01234567 "
462 "$686F6C65696E746865626F74746F6D6F66746865 "
463 "$776879646F796F7561736B6E6F6E6F6E6F6E6F6E "
464 "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
466 // "BAGEL" is still there, but it won't make a warning, because we already
467 // warned about it. Some with "$painauchocolat".
468 expect_single_log_msg_containing(
469 "There is a router named \"CRUmpeT\" in my declared "
470 "family, but it wasn't listed by digest. Please consider saying "
471 "$776879646F796F7561736B6E6F6E6F6E6F6E6F6E instead, if that's "
474 UNMOCK(node_get_by_nickname
);
476 // Try a singleton list containing only us: It should give us NULL.
477 config_free_lines(options
->MyFamily
);
478 config_line_append(&options
->MyFamily
, "MyFamily",
479 "$686F6C65696E746865626F74746F6D6F66746865");
480 sl
= get_my_declared_family(options
);
481 tt_ptr_op(sl
, OP_EQ
, NULL
);
482 expect_no_log_entry();
485 or_options_free(options
);
486 teardown_capture_of_logs();
488 UNMOCK(node_get_by_nickname
);
493 static smartlist_t
*fake_connection_array
= NULL
;
495 mock_get_connection_array(void)
497 return fake_connection_array
;
501 test_router_get_advertised_or_port(void *arg
)
506 or_options_t
*opts
= options_new();
507 listener_connection_t
*listener
= NULL
;
508 tor_addr_port_t ipv6
;
510 // Test one failing case of routerconf_find_ipv6_or_ap().
511 routerconf_find_ipv6_or_ap(opts
, &ipv6
);
512 tt_str_op(fmt_addrport(&ipv6
.addr
, ipv6
.port
), OP_EQ
, "[::]:0");
514 // And one failing case of routerconf_find_or_port().
515 tt_int_op(0, OP_EQ
, routerconf_find_or_port(opts
, AF_INET
));
517 // Set up a couple of configured ports.
518 config_line_append(&opts
->ORPort_lines
, "ORPort", "[1234::5678]:auto");
519 config_line_append(&opts
->ORPort_lines
, "ORPort", "5.6.7.8:9999");
520 r
= parse_ports(opts
, 0, &msg
, &n
, &w
);
523 // There are no listeners, so the "auto" case will turn up no results.
524 tt_int_op(0, OP_EQ
, routerconf_find_or_port(opts
, AF_INET6
));
525 routerconf_find_ipv6_or_ap(opts
, &ipv6
);
526 tt_str_op(fmt_addrport(&ipv6
.addr
, ipv6
.port
), OP_EQ
, "[::]:0");
528 // This will return the matching value from the configured port.
529 tt_int_op(9999, OP_EQ
, routerconf_find_or_port(opts
, AF_INET
));
531 // Now set up a dummy listener.
532 MOCK(get_connection_array
, mock_get_connection_array
);
533 fake_connection_array
= smartlist_new();
534 listener
= listener_connection_new(CONN_TYPE_OR_LISTENER
, AF_INET6
);
535 TO_CONN(listener
)->port
= 54321;
536 smartlist_add(fake_connection_array
, TO_CONN(listener
));
538 // We should get a port this time.
539 tt_int_op(54321, OP_EQ
, routerconf_find_or_port(opts
, AF_INET6
));
541 // Test one succeeding case of routerconf_find_ipv6_or_ap().
542 routerconf_find_ipv6_or_ap(opts
, &ipv6
);
543 tt_str_op(fmt_addrport(&ipv6
.addr
, ipv6
.port
), OP_EQ
,
544 "[1234::5678]:54321");
546 // This will return the matching value from the configured port.
547 tt_int_op(9999, OP_EQ
, routerconf_find_or_port(opts
, AF_INET
));
550 or_options_free(opts
);
552 smartlist_free(fake_connection_array
);
553 connection_free_minimal(TO_CONN(listener
));
554 UNMOCK(get_connection_array
);
558 test_router_get_advertised_or_port_localhost(void *arg
)
563 or_options_t
*opts
= options_new();
564 tor_addr_port_t ipv6
;
566 // Set up a couple of configured ports on localhost.
567 config_line_append(&opts
->ORPort_lines
, "ORPort", "[::1]:9999");
568 config_line_append(&opts
->ORPort_lines
, "ORPort", "127.0.0.1:8888");
569 r
= parse_ports(opts
, 0, &msg
, &n
, &w
);
572 // We should refuse to advertise them, since we have default dirauths.
573 routerconf_find_ipv6_or_ap(opts
, &ipv6
);
574 tt_str_op(fmt_addrport(&ipv6
.addr
, ipv6
.port
), OP_EQ
, "[::]:0");
575 // But the lower-level function should still report the correct value
576 tt_int_op(9999, OP_EQ
, routerconf_find_or_port(opts
, AF_INET6
));
578 // The IPv4 checks are done in resolve_my_address(), which doesn't use
579 // ORPorts so we can't test them here. (See #33681.) Both these lower-level
580 // functions should still report the correct value.
581 tt_int_op(8888, OP_EQ
, routerconf_find_or_port(opts
, AF_INET
));
583 // Now try with a fake authority set up.
584 config_line_append(&opts
->DirAuthorities
, "DirAuthority",
586 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
588 tt_int_op(9999, OP_EQ
, routerconf_find_or_port(opts
, AF_INET6
));
589 routerconf_find_ipv6_or_ap(opts
, &ipv6
);
590 tt_str_op(fmt_addrport(&ipv6
.addr
, ipv6
.port
), OP_EQ
, "[::1]:9999");
592 tt_int_op(8888, OP_EQ
, routerconf_find_or_port(opts
, AF_INET
));
595 or_options_free(opts
);
599 #define ROUTER_TEST(name, flags) \
600 { #name, test_router_ ## name, flags, NULL, NULL }
602 struct testcase_t router_tests
[] = {
603 ROUTER_TEST(check_descriptor_bandwidth_changed
, TT_FORK
),
604 ROUTER_TEST(dump_router_to_string_no_bridge_distribution_method
, TT_FORK
),
605 ROUTER_TEST(mark_if_too_old
, TT_FORK
),
606 ROUTER_TEST(get_my_family
, TT_FORK
),
607 ROUTER_TEST(get_advertised_or_port
, TT_FORK
),
608 ROUTER_TEST(get_advertised_or_port_localhost
, TT_FORK
),