test_router.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. /* Copyright (c) 2017-2019, The Tor Project, Inc. */
  2. /* Copyright (c) 2017, isis agora lovecruft */
  3. /* See LICENSE for licensing information */
  4. /**
  5. * \file test_router.c
  6. * \brief Unittests for code in router.c
  7. **/
  8. #define CONFIG_PRIVATE
  9. #define ROUTER_PRIVATE
  10. #include "core/or/or.h"
  11. #include "app/config/config.h"
  12. #include "core/mainloop/mainloop.h"
  13. #include "feature/hibernate/hibernate.h"
  14. #include "feature/nodelist/networkstatus.h"
  15. #include "feature/nodelist/networkstatus_st.h"
  16. #include "feature/nodelist/node_st.h"
  17. #include "feature/nodelist/nodelist.h"
  18. #include "feature/nodelist/routerinfo_st.h"
  19. #include "feature/nodelist/routerlist.h"
  20. #include "feature/nodelist/routerstatus_st.h"
  21. #include "feature/relay/router.h"
  22. #include "feature/stats/rephist.h"
  23. #include "lib/crypt_ops/crypto_curve25519.h"
  24. #include "lib/crypt_ops/crypto_ed25519.h"
  25. #include "lib/encoding/confline.h"
  26. /* Test suite stuff */
  27. #include "test/test.h"
  28. #include "test/log_test_helpers.h"
  29. NS_DECL(const routerinfo_t *, router_get_my_routerinfo, (void));
  30. static routerinfo_t* mock_routerinfo;
  31. static const routerinfo_t*
  32. NS(router_get_my_routerinfo)(void)
  33. {
  34. crypto_pk_t* ident_key;
  35. crypto_pk_t* tap_key;
  36. time_t now;
  37. if (!mock_routerinfo) {
  38. /* Mock the published timestamp, otherwise router_dump_router_to_string()
  39. * will poop its pants. */
  40. time(&now);
  41. /* We'll need keys, or router_dump_router_to_string() would return NULL. */
  42. ident_key = pk_generate(0);
  43. tap_key = pk_generate(0);
  44. tor_assert(ident_key != NULL);
  45. tor_assert(tap_key != NULL);
  46. mock_routerinfo = tor_malloc_zero(sizeof(routerinfo_t));
  47. mock_routerinfo->nickname = tor_strdup("ConlonNancarrow");
  48. mock_routerinfo->addr = 123456789;
  49. mock_routerinfo->or_port = 443;
  50. mock_routerinfo->platform = tor_strdup("unittest");
  51. mock_routerinfo->cache_info.published_on = now;
  52. mock_routerinfo->identity_pkey = crypto_pk_dup_key(ident_key);
  53. router_set_rsa_onion_pkey(tap_key, &mock_routerinfo->onion_pkey,
  54. &mock_routerinfo->onion_pkey_len);
  55. mock_routerinfo->bandwidthrate = 9001;
  56. mock_routerinfo->bandwidthburst = 9002;
  57. crypto_pk_free(ident_key);
  58. crypto_pk_free(tap_key);
  59. }
  60. return mock_routerinfo;
  61. }
  62. /* If no distribution option was set, then check_bridge_distribution_setting()
  63. * should have set it to "any". */
  64. static void
  65. test_router_dump_router_to_string_no_bridge_distribution_method(void *arg)
  66. {
  67. const char* needle = "bridge-distribution-request any";
  68. or_options_t* options = get_options_mutable();
  69. routerinfo_t* router = NULL;
  70. curve25519_keypair_t ntor_keypair;
  71. ed25519_keypair_t signing_keypair;
  72. char* desc = NULL;
  73. char* found = NULL;
  74. (void)arg;
  75. NS_MOCK(router_get_my_routerinfo);
  76. options->ORPort_set = 1;
  77. options->BridgeRelay = 1;
  78. /* Generate keys which router_dump_router_to_string() expects to exist. */
  79. tt_int_op(0, ==, curve25519_keypair_generate(&ntor_keypair, 0));
  80. tt_int_op(0, ==, ed25519_keypair_generate(&signing_keypair, 0));
  81. /* Set up part of our routerinfo_t so that we don't trigger any other
  82. * assertions in router_dump_router_to_string(). */
  83. router = (routerinfo_t*)router_get_my_routerinfo();
  84. tt_ptr_op(router, !=, NULL);
  85. /* The real router_get_my_routerinfo() looks up onion_curve25519_pkey using
  86. * get_current_curve25519_keypair(), but we don't initialise static data in
  87. * this test. */
  88. router->onion_curve25519_pkey = &ntor_keypair.pubkey;
  89. /* Generate our server descriptor and ensure that the substring
  90. * "bridge-distribution-request any" occurs somewhere within it. */
  91. crypto_pk_t *onion_pkey = router_get_rsa_onion_pkey(router->onion_pkey,
  92. router->onion_pkey_len);
  93. desc = router_dump_router_to_string(router,
  94. router->identity_pkey,
  95. onion_pkey,
  96. &ntor_keypair,
  97. &signing_keypair);
  98. crypto_pk_free(onion_pkey);
  99. tt_ptr_op(desc, !=, NULL);
  100. found = strstr(desc, needle);
  101. tt_ptr_op(found, !=, NULL);
  102. done:
  103. NS_UNMOCK(router_get_my_routerinfo);
  104. tor_free(desc);
  105. }
  106. static routerinfo_t *mock_router_get_my_routerinfo_result = NULL;
  107. static const routerinfo_t *
  108. mock_router_get_my_routerinfo(void)
  109. {
  110. return mock_router_get_my_routerinfo_result;
  111. }
  112. static long
  113. mock_get_uptime_3h(void)
  114. {
  115. return 3*60*60;
  116. }
  117. static long
  118. mock_get_uptime_1d(void)
  119. {
  120. return 24*60*60;
  121. }
  122. static int
  123. mock_rep_hist_bandwidth_assess(void)
  124. {
  125. return 20001;
  126. }
  127. static int
  128. mock_we_are_not_hibernating(void)
  129. {
  130. return 0;
  131. }
  132. static int
  133. mock_we_are_hibernating(void)
  134. {
  135. return 0;
  136. }
  137. static void
  138. test_router_check_descriptor_bandwidth_changed(void *arg)
  139. {
  140. (void)arg;
  141. routerinfo_t routerinfo;
  142. memset(&routerinfo, 0, sizeof(routerinfo));
  143. mock_router_get_my_routerinfo_result = NULL;
  144. MOCK(we_are_hibernating, mock_we_are_not_hibernating);
  145. MOCK(router_get_my_routerinfo, mock_router_get_my_routerinfo);
  146. mock_router_get_my_routerinfo_result = &routerinfo;
  147. /* When uptime is less than 24h, no previous bandwidth, no last_changed
  148. * Uptime: 10800, last_changed: 0, Previous bw: 0, Current bw: 0 */
  149. routerinfo.bandwidthcapacity = 0;
  150. MOCK(get_uptime, mock_get_uptime_3h);
  151. setup_full_capture_of_logs(LOG_INFO);
  152. check_descriptor_bandwidth_changed(time(NULL));
  153. expect_log_msg_not_containing(
  154. "Measured bandwidth has changed; rebuilding descriptor.");
  155. teardown_capture_of_logs();
  156. /* When uptime is less than 24h, previous bandwidth,
  157. * last_changed more than 3h ago
  158. * Uptime: 10800, last_changed: 0, Previous bw: 10000, Current bw: 0 */
  159. routerinfo.bandwidthcapacity = 10000;
  160. setup_full_capture_of_logs(LOG_INFO);
  161. check_descriptor_bandwidth_changed(time(NULL));
  162. expect_log_msg_containing(
  163. "Measured bandwidth has changed; rebuilding descriptor.");
  164. teardown_capture_of_logs();
  165. /* When uptime is less than 24h, previous bandwidth,
  166. * last_changed more than 3h ago, and hibernating
  167. * Uptime: 10800, last_changed: 0, Previous bw: 10000, Current bw: 0 */
  168. UNMOCK(we_are_hibernating);
  169. MOCK(we_are_hibernating, mock_we_are_hibernating);
  170. routerinfo.bandwidthcapacity = 10000;
  171. setup_full_capture_of_logs(LOG_INFO);
  172. check_descriptor_bandwidth_changed(time(NULL));
  173. expect_log_msg_not_containing(
  174. "Measured bandwidth has changed; rebuilding descriptor.");
  175. teardown_capture_of_logs();
  176. UNMOCK(we_are_hibernating);
  177. MOCK(we_are_hibernating, mock_we_are_not_hibernating);
  178. /* When uptime is less than 24h, last_changed is not more than 3h ago
  179. * Uptime: 10800, last_changed: x, Previous bw: 10000, Current bw: 0 */
  180. setup_full_capture_of_logs(LOG_INFO);
  181. check_descriptor_bandwidth_changed(time(NULL));
  182. expect_log_msg_not_containing(
  183. "Measured bandwidth has changed; rebuilding descriptor.");
  184. teardown_capture_of_logs();
  185. /* When uptime is less than 24h and bandwidthcapacity does not change
  186. * Uptime: 10800, last_changed: x, Previous bw: 10000, Current bw: 20001 */
  187. MOCK(rep_hist_bandwidth_assess, mock_rep_hist_bandwidth_assess);
  188. setup_full_capture_of_logs(LOG_INFO);
  189. check_descriptor_bandwidth_changed(time(NULL) + 6*60*60 + 1);
  190. expect_log_msg_containing(
  191. "Measured bandwidth has changed; rebuilding descriptor.");
  192. UNMOCK(get_uptime);
  193. UNMOCK(rep_hist_bandwidth_assess);
  194. teardown_capture_of_logs();
  195. /* When uptime is more than 24h */
  196. MOCK(get_uptime, mock_get_uptime_1d);
  197. setup_full_capture_of_logs(LOG_INFO);
  198. check_descriptor_bandwidth_changed(time(NULL));
  199. expect_log_msg_not_containing(
  200. "Measured bandwidth has changed; rebuilding descriptor.");
  201. teardown_capture_of_logs();
  202. done:
  203. UNMOCK(get_uptime);
  204. UNMOCK(router_get_my_routerinfo);
  205. UNMOCK(we_are_hibernating);
  206. }
  207. static networkstatus_t *mock_ns = NULL;
  208. static networkstatus_t *
  209. mock_networkstatus_get_live_consensus(time_t now)
  210. {
  211. (void)now;
  212. return mock_ns;
  213. }
  214. static routerstatus_t *mock_rs = NULL;
  215. static const routerstatus_t *
  216. mock_networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest)
  217. {
  218. (void)ns;
  219. (void)digest;
  220. return mock_rs;
  221. }
  222. static void
  223. test_router_mark_if_too_old(void *arg)
  224. {
  225. (void)arg;
  226. time_t now = approx_time();
  227. MOCK(networkstatus_get_live_consensus,
  228. mock_networkstatus_get_live_consensus);
  229. MOCK(networkstatus_vote_find_entry, mock_networkstatus_vote_find_entry);
  230. routerstatus_t rs;
  231. networkstatus_t ns;
  232. memset(&rs, 0, sizeof(rs));
  233. memset(&ns, 0, sizeof(ns));
  234. mock_ns = &ns;
  235. mock_ns->valid_after = now-3600;
  236. mock_rs = &rs;
  237. mock_rs->published_on = now - 10;
  238. // no reason to mark this time.
  239. desc_clean_since = now-10;
  240. desc_dirty_reason = NULL;
  241. mark_my_descriptor_dirty_if_too_old(now);
  242. tt_i64_op(desc_clean_since, OP_EQ, now-10);
  243. // Doesn't appear in consensus? Still don't mark it.
  244. mock_ns = NULL;
  245. mark_my_descriptor_dirty_if_too_old(now);
  246. tt_i64_op(desc_clean_since, OP_EQ, now-10);
  247. mock_ns = &ns;
  248. // No new descriptor in a long time? Mark it.
  249. desc_clean_since = now - 3600 * 96;
  250. mark_my_descriptor_dirty_if_too_old(now);
  251. tt_i64_op(desc_clean_since, OP_EQ, 0);
  252. tt_str_op(desc_dirty_reason, OP_EQ, "time for new descriptor");
  253. // Version in consensus published a long time ago? We won't mark it
  254. // if it's been clean for only a short time.
  255. desc_clean_since = now - 10;
  256. desc_dirty_reason = NULL;
  257. mock_rs->published_on = now - 3600 * 96;
  258. mark_my_descriptor_dirty_if_too_old(now);
  259. tt_i64_op(desc_clean_since, OP_EQ, now - 10);
  260. // ... but if it's been clean a while, we mark.
  261. desc_clean_since = now - 2 * 3600;
  262. mark_my_descriptor_dirty_if_too_old(now);
  263. tt_i64_op(desc_clean_since, OP_EQ, 0);
  264. tt_str_op(desc_dirty_reason, OP_EQ,
  265. "version listed in consensus is quite old");
  266. // same deal if we're marked stale.
  267. desc_clean_since = now - 2 * 3600;
  268. desc_dirty_reason = NULL;
  269. mock_rs->published_on = now - 10;
  270. mock_rs->is_staledesc = 1;
  271. mark_my_descriptor_dirty_if_too_old(now);
  272. tt_i64_op(desc_clean_since, OP_EQ, 0);
  273. tt_str_op(desc_dirty_reason, OP_EQ,
  274. "listed as stale in consensus");
  275. // same deal if we're absent from the consensus.
  276. desc_clean_since = now - 2 * 3600;
  277. desc_dirty_reason = NULL;
  278. mock_rs = NULL;
  279. mark_my_descriptor_dirty_if_too_old(now);
  280. tt_i64_op(desc_clean_since, OP_EQ, 0);
  281. tt_str_op(desc_dirty_reason, OP_EQ,
  282. "not listed in consensus");
  283. done:
  284. UNMOCK(networkstatus_get_live_consensus);
  285. UNMOCK(networkstatus_vote_find_entry);
  286. }
  287. static node_t fake_node;
  288. static const node_t *
  289. mock_node_get_by_nickname(const char *name, unsigned flags)
  290. {
  291. (void)flags;
  292. if (!strcasecmp(name, "crumpet"))
  293. return &fake_node;
  294. else
  295. return NULL;
  296. }
  297. static void
  298. test_router_get_my_family(void *arg)
  299. {
  300. (void)arg;
  301. or_options_t *options = options_new();
  302. smartlist_t *sl = NULL;
  303. char *join = NULL;
  304. // Overwrite the result of router_get_my_identity_digest(). This
  305. // happens to be okay, but only for testing.
  306. set_server_identity_key_digest_testing(
  307. (const uint8_t*)"holeinthebottomofthe");
  308. setup_capture_of_logs(LOG_WARN);
  309. // No family listed -- so there's no list.
  310. sl = get_my_declared_family(options);
  311. tt_ptr_op(sl, OP_EQ, NULL);
  312. expect_no_log_entry();
  313. #define CLEAR() do { \
  314. if (sl) { \
  315. SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); \
  316. smartlist_free(sl); \
  317. } \
  318. tor_free(join); \
  319. mock_clean_saved_logs(); \
  320. } while (0)
  321. // Add a single nice friendly hex member. This should be enough
  322. // to have our own ID added.
  323. tt_ptr_op(options->MyFamily, OP_EQ, NULL);
  324. config_line_append(&options->MyFamily, "MyFamily",
  325. "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
  326. sl = get_my_declared_family(options);
  327. tt_ptr_op(sl, OP_NE, NULL);
  328. tt_int_op(smartlist_len(sl), OP_EQ, 2);
  329. join = smartlist_join_strings(sl, " ", 0, NULL);
  330. tt_str_op(join, OP_EQ,
  331. "$686F6C65696E746865626F74746F6D6F66746865 "
  332. "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
  333. expect_no_log_entry();
  334. CLEAR();
  335. // Add a hex member with a ~. The ~ part should get removed.
  336. config_line_append(&options->MyFamily, "MyFamily",
  337. "$0123456789abcdef0123456789abcdef01234567~Muffin");
  338. sl = get_my_declared_family(options);
  339. tt_ptr_op(sl, OP_NE, NULL);
  340. tt_int_op(smartlist_len(sl), OP_EQ, 3);
  341. join = smartlist_join_strings(sl, " ", 0, NULL);
  342. tt_str_op(join, OP_EQ,
  343. "$0123456789ABCDEF0123456789ABCDEF01234567 "
  344. "$686F6C65696E746865626F74746F6D6F66746865 "
  345. "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
  346. expect_no_log_entry();
  347. CLEAR();
  348. // Nickname lookup will fail, so a nickname will appear verbatim.
  349. config_line_append(&options->MyFamily, "MyFamily",
  350. "BAGEL");
  351. sl = get_my_declared_family(options);
  352. tt_ptr_op(sl, OP_NE, NULL);
  353. tt_int_op(smartlist_len(sl), OP_EQ, 4);
  354. join = smartlist_join_strings(sl, " ", 0, NULL);
  355. tt_str_op(join, OP_EQ,
  356. "$0123456789ABCDEF0123456789ABCDEF01234567 "
  357. "$686F6C65696E746865626F74746F6D6F66746865 "
  358. "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
  359. "bagel");
  360. expect_single_log_msg_containing(
  361. "There is a router named \"BAGEL\" in my declared family, but "
  362. "I have no descriptor for it.");
  363. CLEAR();
  364. // A bogus digest should fail entirely.
  365. config_line_append(&options->MyFamily, "MyFamily",
  366. "$painauchocolat");
  367. sl = get_my_declared_family(options);
  368. tt_ptr_op(sl, OP_NE, NULL);
  369. tt_int_op(smartlist_len(sl), OP_EQ, 4);
  370. join = smartlist_join_strings(sl, " ", 0, NULL);
  371. tt_str_op(join, OP_EQ,
  372. "$0123456789ABCDEF0123456789ABCDEF01234567 "
  373. "$686F6C65696E746865626F74746F6D6F66746865 "
  374. "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
  375. "bagel");
  376. // "BAGEL" is still there, but it won't make a warning, because we already
  377. // warned about it.
  378. expect_single_log_msg_containing(
  379. "There is a router named \"$painauchocolat\" in my declared "
  380. "family, but that isn't a legal digest or nickname. Skipping it.");
  381. CLEAR();
  382. // Let's introduce a node we can look up by nickname
  383. memset(&fake_node, 0, sizeof(fake_node));
  384. memcpy(fake_node.identity, "whydoyouasknonononon", DIGEST_LEN);
  385. MOCK(node_get_by_nickname, mock_node_get_by_nickname);
  386. config_line_append(&options->MyFamily, "MyFamily",
  387. "CRUmpeT");
  388. sl = get_my_declared_family(options);
  389. tt_ptr_op(sl, OP_NE, NULL);
  390. tt_int_op(smartlist_len(sl), OP_EQ, 5);
  391. join = smartlist_join_strings(sl, " ", 0, NULL);
  392. tt_str_op(join, OP_EQ,
  393. "$0123456789ABCDEF0123456789ABCDEF01234567 "
  394. "$686F6C65696E746865626F74746F6D6F66746865 "
  395. "$776879646F796F7561736B6E6F6E6F6E6F6E6F6E "
  396. "$AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "
  397. "bagel");
  398. // "BAGEL" is still there, but it won't make a warning, because we already
  399. // warned about it. Some with "$painauchocolat".
  400. expect_single_log_msg_containing(
  401. "There is a router named \"CRUmpeT\" in my declared "
  402. "family, but it wasn't listed by digest. Please consider saying "
  403. "$776879646F796F7561736B6E6F6E6F6E6F6E6F6E instead, if that's "
  404. "what you meant.");
  405. CLEAR();
  406. UNMOCK(node_get_by_nickname);
  407. // Try a singleton list containing only us: It should give us NULL.
  408. config_free_lines(options->MyFamily);
  409. config_line_append(&options->MyFamily, "MyFamily",
  410. "$686F6C65696E746865626F74746F6D6F66746865");
  411. sl = get_my_declared_family(options);
  412. tt_ptr_op(sl, OP_EQ, NULL);
  413. expect_no_log_entry();
  414. done:
  415. or_options_free(options);
  416. teardown_capture_of_logs();
  417. CLEAR();
  418. UNMOCK(node_get_by_nickname);
  419. #undef CLEAR
  420. }
  421. #define ROUTER_TEST(name, flags) \
  422. { #name, test_router_ ## name, flags, NULL, NULL }
  423. struct testcase_t router_tests[] = {
  424. ROUTER_TEST(check_descriptor_bandwidth_changed, TT_FORK),
  425. ROUTER_TEST(dump_router_to_string_no_bridge_distribution_method, TT_FORK),
  426. ROUTER_TEST(mark_if_too_old, TT_FORK),
  427. ROUTER_TEST(get_my_family, TT_FORK),
  428. END_OF_TESTCASES
  429. };