Line data Source code
1 : /* Copyright (c) 2014-2021, The Tor Project, Inc. */
2 : /* See LICENSE for licensing information */
3 :
4 : #include "orconfig.h"
5 : #include <math.h>
6 : #include <time.h>
7 :
8 : #define CONNECTION_PRIVATE
9 : #define DIRCLIENT_PRIVATE
10 : #define DIRVOTE_PRIVATE
11 : #define ENTRYNODES_PRIVATE
12 : #define HIBERNATE_PRIVATE
13 : #define NETWORKSTATUS_PRIVATE
14 : #define ROUTERLIST_PRIVATE
15 : #define NODE_SELECT_PRIVATE
16 : #define TOR_UNIT_TESTING
17 : #include "core/or/or.h"
18 : #include "app/config/config.h"
19 : #include "core/mainloop/connection.h"
20 : #include "feature/control/control.h"
21 : #include "lib/crypt_ops/crypto_rand.h"
22 : #include "feature/dircommon/directory.h"
23 : #include "feature/dirclient/dirclient.h"
24 : #include "feature/dirauth/dirvote.h"
25 : #include "feature/client/entrynodes.h"
26 : #include "feature/hibernate/hibernate.h"
27 : #include "feature/nodelist/microdesc.h"
28 : #include "feature/nodelist/networkstatus.h"
29 : #include "feature/nodelist/nodelist.h"
30 : #include "core/or/policies.h"
31 : #include "feature/relay/router.h"
32 : #include "feature/nodelist/authcert.h"
33 : #include "feature/nodelist/node_select.h"
34 : #include "feature/nodelist/routerlist.h"
35 : #include "feature/nodelist/routerset.h"
36 : #include "feature/dirparse/authcert_parse.h"
37 : #include "feature/dirparse/ns_parse.h"
38 : #include "feature/dirauth/shared_random.h"
39 : #include "app/config/statefile.h"
40 :
41 : #include "feature/nodelist/authority_cert_st.h"
42 : #include "feature/dircommon/dir_connection_st.h"
43 : #include "feature/nodelist/networkstatus_st.h"
44 : #include "feature/nodelist/node_st.h"
45 : #include "app/config/or_state_st.h"
46 : #include "feature/nodelist/routerstatus_st.h"
47 :
48 : #include "lib/encoding/confline.h"
49 : #include "lib/buf/buffers.h"
50 :
51 : #include "test/test.h"
52 : #include "test/test_dir_common.h"
53 : #include "test/log_test_helpers.h"
54 :
55 : static authority_cert_t *mock_cert;
56 :
57 : static authority_cert_t *
58 1 : get_my_v3_authority_cert_m(void)
59 : {
60 1 : tor_assert(mock_cert);
61 1 : return mock_cert;
62 : }
63 :
64 : /* 4 digests + 3 sep + pre + post + NULL */
65 : static char output[4*BASE64_DIGEST256_LEN+3+2+2+1];
66 :
67 : static void
68 1 : mock_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
69 : const char *resource, int pds_flags,
70 : download_want_authority_t want_authority)
71 : {
72 1 : (void)dir_purpose;
73 1 : (void)router_purpose;
74 1 : (void)pds_flags;
75 1 : (void)want_authority;
76 1 : tt_assert(resource);
77 1 : strlcpy(output, resource, sizeof(output));
78 1 : done:
79 1 : ;
80 1 : }
81 :
82 : static void
83 1 : test_routerlist_initiate_descriptor_downloads(void *arg)
84 : {
85 1 : const char *prose = "unhurried and wise, we perceive.";
86 1 : smartlist_t *digests = smartlist_new();
87 1 : (void)arg;
88 :
89 21 : for (int i = 0; i < 20; i++) {
90 20 : smartlist_add(digests, (char*)prose);
91 : }
92 :
93 1 : MOCK(directory_get_from_dirserver, mock_get_from_dirserver);
94 1 : initiate_descriptor_downloads(NULL, DIR_PURPOSE_FETCH_MICRODESC,
95 : digests, 3, 7, 0);
96 1 : UNMOCK(directory_get_from_dirserver);
97 :
98 1 : tt_str_op(output, OP_EQ, "d/"
99 : "dW5odXJyaWVkIGFuZCB3aXNlLCB3ZSBwZXJjZWl2ZS4-"
100 : "dW5odXJyaWVkIGFuZCB3aXNlLCB3ZSBwZXJjZWl2ZS4-"
101 : "dW5odXJyaWVkIGFuZCB3aXNlLCB3ZSBwZXJjZWl2ZS4-"
102 : "dW5odXJyaWVkIGFuZCB3aXNlLCB3ZSBwZXJjZWl2ZS4"
103 : ".z");
104 :
105 1 : done:
106 1 : smartlist_free(digests);
107 1 : }
108 :
109 : static int count = 0;
110 :
111 : static void
112 3 : mock_initiate_descriptor_downloads(const routerstatus_t *source,
113 : int purpose, smartlist_t *digests,
114 : int lo, int hi, int pds_flags)
115 : {
116 3 : (void)source;
117 3 : (void)purpose;
118 3 : (void)digests;
119 3 : (void)pds_flags;
120 3 : (void)hi;
121 3 : (void)lo;
122 3 : count += 1;
123 3 : }
124 :
125 : static void
126 1 : test_routerlist_launch_descriptor_downloads(void *arg)
127 : {
128 1 : smartlist_t *downloadable = smartlist_new();
129 1 : time_t now = time(NULL);
130 1 : char *cp;
131 1 : (void)arg;
132 :
133 101 : for (int i = 0; i < 100; i++) {
134 100 : cp = tor_malloc(DIGEST256_LEN);
135 100 : tt_assert(cp);
136 100 : crypto_rand(cp, DIGEST256_LEN);
137 100 : smartlist_add(downloadable, cp);
138 : }
139 :
140 1 : MOCK(initiate_descriptor_downloads, mock_initiate_descriptor_downloads);
141 1 : launch_descriptor_downloads(DIR_PURPOSE_FETCH_MICRODESC, downloadable,
142 : NULL, now);
143 1 : tt_int_op(3, OP_EQ, count);
144 1 : UNMOCK(initiate_descriptor_downloads);
145 :
146 1 : done:
147 101 : SMARTLIST_FOREACH(downloadable, char *, cp1, tor_free(cp1));
148 1 : smartlist_free(downloadable);
149 1 : }
150 :
151 : static void
152 6 : construct_consensus(char **consensus_text_md, time_t now)
153 : {
154 6 : networkstatus_t *vote = NULL;
155 6 : networkstatus_t *v1 = NULL, *v2 = NULL, *v3 = NULL;
156 6 : networkstatus_voter_info_t *voter = NULL;
157 6 : authority_cert_t *cert1=NULL, *cert2=NULL, *cert3=NULL;
158 6 : crypto_pk_t *sign_skey_1=NULL, *sign_skey_2=NULL, *sign_skey_3=NULL;
159 6 : crypto_pk_t *sign_skey_leg=NULL;
160 6 : smartlist_t *votes = NULL;
161 6 : int n_vrs;
162 :
163 6 : tt_assert(!dir_common_authority_pk_init(&cert1, &cert2, &cert3,
164 : &sign_skey_1, &sign_skey_2,
165 : &sign_skey_3));
166 6 : sign_skey_leg = pk_generate(4);
167 :
168 6 : dir_common_construct_vote_1(&vote, cert1, sign_skey_1,
169 : &dir_common_gen_routerstatus_for_v3ns,
170 : &v1, &n_vrs, now, 1);
171 6 : networkstatus_vote_free(vote);
172 6 : tt_assert(v1);
173 6 : tt_int_op(n_vrs, OP_EQ, 4);
174 6 : tt_int_op(smartlist_len(v1->routerstatus_list), OP_EQ, 4);
175 :
176 6 : dir_common_construct_vote_2(&vote, cert2, sign_skey_2,
177 : &dir_common_gen_routerstatus_for_v3ns,
178 : &v2, &n_vrs, now, 1);
179 6 : networkstatus_vote_free(vote);
180 6 : tt_assert(v2);
181 6 : tt_int_op(n_vrs, OP_EQ, 4);
182 6 : tt_int_op(smartlist_len(v2->routerstatus_list), OP_EQ, 4);
183 :
184 6 : dir_common_construct_vote_3(&vote, cert3, sign_skey_3,
185 : &dir_common_gen_routerstatus_for_v3ns,
186 : &v3, &n_vrs, now, 1);
187 :
188 6 : tt_assert(v3);
189 6 : tt_int_op(n_vrs, OP_EQ, 4);
190 6 : tt_int_op(smartlist_len(v3->routerstatus_list), OP_EQ, 4);
191 6 : networkstatus_vote_free(vote);
192 6 : votes = smartlist_new();
193 6 : smartlist_add(votes, v1);
194 6 : smartlist_add(votes, v2);
195 6 : smartlist_add(votes, v3);
196 :
197 12 : *consensus_text_md = networkstatus_compute_consensus(votes, 3,
198 6 : cert1->identity_key,
199 : sign_skey_1,
200 : "AAAAAAAAAAAAAAAAAAAA",
201 : sign_skey_leg,
202 : FLAV_MICRODESC);
203 :
204 6 : tt_assert(*consensus_text_md);
205 :
206 6 : done:
207 6 : tor_free(voter);
208 6 : networkstatus_vote_free(v1);
209 6 : networkstatus_vote_free(v2);
210 6 : networkstatus_vote_free(v3);
211 6 : smartlist_free(votes);
212 6 : authority_cert_free(cert1);
213 6 : authority_cert_free(cert2);
214 6 : authority_cert_free(cert3);
215 6 : crypto_pk_free(sign_skey_1);
216 6 : crypto_pk_free(sign_skey_2);
217 6 : crypto_pk_free(sign_skey_3);
218 6 : crypto_pk_free(sign_skey_leg);
219 6 : }
220 :
221 : static int mock_usable_consensus_flavor_value = FLAV_NS;
222 :
223 : static int
224 45 : mock_usable_consensus_flavor(void)
225 : {
226 45 : return mock_usable_consensus_flavor_value;
227 : }
228 :
229 : static void
230 1 : test_router_pick_directory_server_impl(void *arg)
231 : {
232 1 : (void)arg;
233 :
234 1 : networkstatus_t *con_md = NULL;
235 1 : char *consensus_text_md = NULL;
236 1 : int flags = PDS_IGNORE_FASCISTFIREWALL|PDS_RETRY_IF_NO_SERVERS;
237 1 : or_options_t *options = get_options_mutable();
238 1 : const routerstatus_t *rs = NULL;
239 1 : options->UseMicrodescriptors = 1;
240 1 : char *router1_id = NULL, *router2_id = NULL, *router3_id = NULL;
241 1 : node_t *node_router1 = NULL, *node_router2 = NULL, *node_router3 = NULL;
242 1 : config_line_t *policy_line = NULL;
243 1 : time_t now = time(NULL);
244 1 : int tmp_dirport1, tmp_dirport3;
245 :
246 1 : (void)arg;
247 :
248 1 : MOCK(usable_consensus_flavor, mock_usable_consensus_flavor);
249 :
250 : /* With no consensus, we must be bootstrapping, regardless of time or flavor
251 : */
252 1 : mock_usable_consensus_flavor_value = FLAV_NS;
253 1 : tt_assert(networkstatus_consensus_is_bootstrapping(now));
254 1 : tt_assert(networkstatus_consensus_is_bootstrapping(now + 2000));
255 1 : tt_assert(networkstatus_consensus_is_bootstrapping(now + 2*24*60*60));
256 1 : tt_assert(networkstatus_consensus_is_bootstrapping(now - 2*24*60*60));
257 :
258 1 : mock_usable_consensus_flavor_value = FLAV_MICRODESC;
259 1 : tt_assert(networkstatus_consensus_is_bootstrapping(now));
260 1 : tt_assert(networkstatus_consensus_is_bootstrapping(now + 2000));
261 1 : tt_assert(networkstatus_consensus_is_bootstrapping(now + 2*24*60*60));
262 1 : tt_assert(networkstatus_consensus_is_bootstrapping(now - 2*24*60*60));
263 :
264 : /* Init SR subsystem. */
265 1 : MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
266 1 : mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1,
267 : strlen(AUTHORITY_CERT_1),
268 : NULL);
269 1 : sr_init(0);
270 1 : UNMOCK(get_my_v3_authority_cert);
271 :
272 : /* No consensus available, fail early */
273 1 : rs = router_pick_directory_server_impl(V3_DIRINFO, (const int) 0, NULL);
274 1 : tt_ptr_op(rs, OP_EQ, NULL);
275 :
276 1 : construct_consensus(&consensus_text_md, now);
277 1 : tt_assert(consensus_text_md);
278 1 : con_md = networkstatus_parse_vote_from_string(consensus_text_md,
279 : strlen(consensus_text_md),
280 : NULL,
281 : NS_TYPE_CONSENSUS);
282 1 : tt_assert(con_md);
283 1 : tt_int_op(con_md->flavor,OP_EQ, FLAV_MICRODESC);
284 1 : tt_assert(con_md->routerstatus_list);
285 1 : tt_int_op(smartlist_len(con_md->routerstatus_list), OP_EQ, 3);
286 1 : tt_assert(!networkstatus_set_current_consensus_from_ns(con_md,
287 : "microdesc"));
288 :
289 : /* If the consensus time or flavor doesn't match, we are still
290 : * bootstrapping */
291 1 : mock_usable_consensus_flavor_value = FLAV_NS;
292 1 : tt_assert(networkstatus_consensus_is_bootstrapping(now));
293 1 : tt_assert(networkstatus_consensus_is_bootstrapping(now + 2000));
294 1 : tt_assert(networkstatus_consensus_is_bootstrapping(now + 2*24*60*60));
295 1 : tt_assert(networkstatus_consensus_is_bootstrapping(now - 2*24*60*60));
296 :
297 : /* With a valid consensus for the current time and flavor, we stop
298 : * bootstrapping, even if we have no certificates */
299 1 : mock_usable_consensus_flavor_value = FLAV_MICRODESC;
300 1 : tt_assert(!networkstatus_consensus_is_bootstrapping(now + 2000));
301 1 : tt_assert(!networkstatus_consensus_is_bootstrapping(con_md->valid_after));
302 1 : tt_assert(!networkstatus_consensus_is_bootstrapping(con_md->valid_until));
303 1 : tt_assert(!networkstatus_consensus_is_bootstrapping(con_md->valid_until
304 : + 24*60*60));
305 : /* These times are outside the test validity period */
306 1 : tt_assert(networkstatus_consensus_is_bootstrapping(now + 2*24*60*60));
307 1 : tt_assert(networkstatus_consensus_is_bootstrapping(now - 2*24*60*60));
308 :
309 1 : nodelist_set_consensus(con_md);
310 1 : nodelist_assert_ok();
311 :
312 1 : rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
313 : /* We should not fail now we have a consensus and routerstatus_list
314 : * and nodelist are populated. */
315 1 : tt_ptr_op(rs, OP_NE, NULL);
316 :
317 : /* Manipulate the nodes so we get the dir server we expect */
318 1 : router1_id = tor_malloc(DIGEST_LEN);
319 1 : memset(router1_id, TEST_DIR_ROUTER_ID_1, DIGEST_LEN);
320 1 : router2_id = tor_malloc(DIGEST_LEN);
321 1 : memset(router2_id, TEST_DIR_ROUTER_ID_2, DIGEST_LEN);
322 1 : router3_id = tor_malloc(DIGEST_LEN);
323 1 : memset(router3_id, TEST_DIR_ROUTER_ID_3, DIGEST_LEN);
324 :
325 1 : node_router1 = node_get_mutable_by_id(router1_id);
326 1 : node_router2 = node_get_mutable_by_id(router2_id);
327 1 : node_router3 = node_get_mutable_by_id(router3_id);
328 :
329 1 : node_router1->is_possible_guard = 1;
330 :
331 1 : node_router1->is_running = 0;
332 1 : node_router3->is_running = 0;
333 1 : rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
334 1 : tt_ptr_op(rs, OP_NE, NULL);
335 1 : tt_assert(tor_memeq(rs->identity_digest, router2_id, DIGEST_LEN));
336 1 : rs = NULL;
337 1 : node_router1->is_running = 1;
338 1 : node_router3->is_running = 1;
339 :
340 1 : node_router1->rs->is_v2_dir = 0;
341 1 : node_router3->rs->is_v2_dir = 0;
342 1 : tmp_dirport1 = node_router1->rs->ipv4_dirport;
343 1 : tmp_dirport3 = node_router3->rs->ipv4_dirport;
344 1 : node_router1->rs->ipv4_dirport = 0;
345 1 : node_router3->rs->ipv4_dirport = 0;
346 1 : rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
347 1 : tt_ptr_op(rs, OP_NE, NULL);
348 1 : tt_assert(tor_memeq(rs->identity_digest, router2_id, DIGEST_LEN));
349 1 : rs = NULL;
350 1 : node_router1->rs->is_v2_dir = 1;
351 1 : node_router3->rs->is_v2_dir = 1;
352 1 : node_router1->rs->ipv4_dirport = tmp_dirport1;
353 1 : node_router3->rs->ipv4_dirport = tmp_dirport3;
354 :
355 1 : node_router1->is_valid = 0;
356 1 : node_router3->is_valid = 0;
357 1 : rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
358 1 : tt_ptr_op(rs, OP_NE, NULL);
359 1 : tt_assert(tor_memeq(rs->identity_digest, router2_id, DIGEST_LEN));
360 1 : rs = NULL;
361 1 : node_router1->is_valid = 1;
362 1 : node_router3->is_valid = 1;
363 :
364 : /* Manipulate overloaded */
365 :
366 1 : node_router2->rs->last_dir_503_at = now;
367 1 : node_router3->rs->last_dir_503_at = now;
368 1 : rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
369 1 : tt_ptr_op(rs, OP_NE, NULL);
370 1 : tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN));
371 1 : node_router2->rs->last_dir_503_at = 0;
372 1 : node_router3->rs->last_dir_503_at = 0;
373 :
374 : /* Set a Fascist firewall */
375 1 : flags &= ~ PDS_IGNORE_FASCISTFIREWALL;
376 1 : policy_line = tor_malloc_zero(sizeof(config_line_t));
377 1 : policy_line->key = tor_strdup("ReachableORAddresses");
378 1 : policy_line->value = tor_strdup("accept *:442, reject *:*");
379 1 : options->ReachableORAddresses = policy_line;
380 1 : policies_parse_from_options(options);
381 :
382 1 : node_router1->rs->ipv4_orport = 444;
383 1 : node_router2->rs->ipv4_orport = 443;
384 1 : node_router3->rs->ipv4_orport = 442;
385 1 : rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
386 1 : tt_ptr_op(rs, OP_NE, NULL);
387 1 : tt_assert(tor_memeq(rs->identity_digest, router3_id, DIGEST_LEN));
388 1 : node_router1->rs->ipv4_orport = 442;
389 1 : node_router2->rs->ipv4_orport = 443;
390 1 : node_router3->rs->ipv4_orport = 444;
391 1 : rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
392 1 : tt_ptr_op(rs, OP_NE, NULL);
393 1 : tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN));
394 :
395 : /* Fascist firewall and overloaded */
396 1 : node_router1->rs->ipv4_orport = 442;
397 1 : node_router2->rs->ipv4_orport = 443;
398 1 : node_router3->rs->ipv4_orport = 442;
399 1 : node_router3->rs->last_dir_503_at = now;
400 1 : rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
401 1 : tt_ptr_op(rs, OP_NE, NULL);
402 1 : tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN));
403 1 : node_router3->rs->last_dir_503_at = 0;
404 :
405 : /* Fascists against OR and Dir */
406 1 : policy_line = tor_malloc_zero(sizeof(config_line_t));
407 1 : policy_line->key = tor_strdup("ReachableAddresses");
408 1 : policy_line->value = tor_strdup("accept *:80, reject *:*");
409 1 : options->ReachableDirAddresses = policy_line;
410 1 : policies_parse_from_options(options);
411 1 : node_router1->rs->ipv4_orport = 442;
412 1 : node_router2->rs->ipv4_orport = 441;
413 1 : node_router3->rs->ipv4_orport = 443;
414 1 : node_router1->rs->ipv4_dirport = 80;
415 1 : node_router2->rs->ipv4_dirport = 80;
416 1 : node_router3->rs->ipv4_dirport = 81;
417 1 : node_router1->rs->last_dir_503_at = now;
418 1 : rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
419 1 : tt_ptr_op(rs, OP_NE, NULL);
420 1 : tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN));
421 1 : node_router1->rs->last_dir_503_at = 0;
422 :
423 1 : done:
424 1 : UNMOCK(usable_consensus_flavor);
425 :
426 1 : if (router1_id)
427 1 : tor_free(router1_id);
428 1 : if (router2_id)
429 1 : tor_free(router2_id);
430 1 : if (router3_id)
431 1 : tor_free(router3_id);
432 1 : if (options->ReachableORAddresses ||
433 0 : options->ReachableDirAddresses)
434 1 : policies_free_all();
435 1 : tor_free(consensus_text_md);
436 1 : networkstatus_vote_free(con_md);
437 1 : }
438 :
439 : static or_state_t *dummy_state = NULL;
440 : static or_state_t *
441 2 : get_or_state_replacement(void)
442 : {
443 2 : return dummy_state;
444 : }
445 :
446 : static void
447 1 : mock_directory_initiate_request(directory_request_t *req)
448 : {
449 1 : (void)req;
450 1 : return;
451 : }
452 :
453 : static circuit_guard_state_t *
454 1 : mock_circuit_guard_state_new(entry_guard_t *guard, unsigned state,
455 : entry_guard_restriction_t *rst)
456 : {
457 1 : (void) guard;
458 1 : (void) state;
459 1 : (void) rst;
460 1 : return NULL;
461 : }
462 :
463 : /** Test that we will use our directory guards to fetch mds even if we don't
464 : * have any dirinfo (tests bug #23862). */
465 : static void
466 1 : test_directory_guard_fetch_with_no_dirinfo(void *arg)
467 : {
468 1 : int retval;
469 1 : char *consensus_text_md = NULL;
470 1 : or_options_t *options = get_options_mutable();
471 1 : time_t now = time(NULL);
472 :
473 1 : (void) arg;
474 :
475 1 : hibernate_set_state_for_testing_(HIBERNATE_STATE_LIVE);
476 :
477 : /* Initialize the SRV subsystem */
478 1 : MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
479 1 : mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1,
480 : strlen(AUTHORITY_CERT_1),
481 : NULL);
482 1 : sr_init(0);
483 1 : UNMOCK(get_my_v3_authority_cert);
484 :
485 : /* Initialize the entry node configuration from the ticket */
486 1 : options->UseEntryGuards = 1;
487 1 : options->StrictNodes = 1;
488 1 : get_options_mutable()->EntryNodes = routerset_new();
489 1 : routerset_parse(get_options_mutable()->EntryNodes,
490 : "2121212121212121212121212121212121212121", "foo");
491 :
492 : /* Mock some functions */
493 1 : dummy_state = tor_malloc_zero(sizeof(or_state_t));
494 1 : MOCK(get_or_state, get_or_state_replacement);
495 1 : MOCK(directory_initiate_request, mock_directory_initiate_request);
496 : /* we need to mock this one to avoid memleaks */
497 1 : MOCK(circuit_guard_state_new, mock_circuit_guard_state_new);
498 :
499 : /* Call guards_update_all() to simulate loading our state file (see
500 : * entry_guards_load_guards_from_state() and ticket #23989). */
501 1 : guards_update_all();
502 :
503 : /* Test logic: Simulate the arrival of a new consensus when we have no
504 : * dirinfo at all. Tor will need to fetch the mds from the consensus. Make
505 : * sure that Tor will use the specified entry guard instead of relying on the
506 : * fallback directories. */
507 :
508 : /* Fixup the dirconn that will deliver the consensus */
509 1 : dir_connection_t *conn = dir_connection_new(AF_INET);
510 1 : tor_addr_from_ipv4h(&conn->base_.addr, 0x7f000001);
511 1 : conn->base_.port = 8800;
512 1 : TO_CONN(conn)->address = tor_strdup("127.0.0.1");
513 1 : conn->base_.purpose = DIR_PURPOSE_FETCH_CONSENSUS;
514 1 : conn->requested_resource = tor_strdup("ns");
515 :
516 : /* Construct a consensus */
517 1 : construct_consensus(&consensus_text_md, now);
518 1 : tt_assert(consensus_text_md);
519 :
520 : /* Place the consensus in the dirconn */
521 1 : response_handler_args_t args;
522 1 : memset(&args, 0, sizeof(response_handler_args_t));
523 1 : args.status_code = 200;
524 1 : args.body = consensus_text_md;
525 1 : args.body_len = strlen(consensus_text_md);
526 :
527 : /* Update approx time so that the consensus is considered live */
528 1 : update_approx_time(now+1010);
529 :
530 1 : setup_capture_of_logs(LOG_DEBUG);
531 :
532 : /* Now handle the consensus */
533 1 : retval = handle_response_fetch_consensus(conn, &args);
534 1 : tt_int_op(retval, OP_EQ, 0);
535 :
536 : /* Make sure that our primary guard was chosen */
537 1 : expect_log_msg_containing("Selected primary guard router3");
538 :
539 1 : done:
540 1 : tor_free(consensus_text_md);
541 1 : tor_free(dummy_state);
542 1 : connection_free_minimal(TO_CONN(conn));
543 1 : entry_guards_free_all();
544 1 : teardown_capture_of_logs();
545 1 : }
546 :
547 : static connection_t *mocked_connection = NULL;
548 :
549 : /* Mock connection_get_by_type_addr_port_purpose by returning
550 : * mocked_connection. */
551 : static connection_t *
552 9 : mock_connection_get_by_type_addr_port_purpose(int type,
553 : const tor_addr_t *addr,
554 : uint16_t port, int purpose)
555 : {
556 9 : (void)type;
557 9 : (void)addr;
558 9 : (void)port;
559 9 : (void)purpose;
560 :
561 9 : return mocked_connection;
562 : }
563 :
564 : #define TEST_ADDR_STR "127.0.0.1"
565 : #define TEST_DIR_PORT 12345
566 :
567 : static void
568 1 : test_routerlist_router_is_already_dir_fetching(void *arg)
569 : {
570 1 : (void)arg;
571 1 : tor_addr_port_t test_ap, null_addr_ap, zero_port_ap;
572 :
573 : /* Setup */
574 1 : tor_addr_parse(&test_ap.addr, TEST_ADDR_STR);
575 1 : test_ap.port = TEST_DIR_PORT;
576 1 : tor_addr_make_null(&null_addr_ap.addr, AF_INET6);
577 1 : null_addr_ap.port = TEST_DIR_PORT;
578 1 : tor_addr_parse(&zero_port_ap.addr, TEST_ADDR_STR);
579 1 : zero_port_ap.port = 0;
580 1 : MOCK(connection_get_by_type_addr_port_purpose,
581 : mock_connection_get_by_type_addr_port_purpose);
582 :
583 : /* Test that we never get 1 from a NULL connection */
584 1 : mocked_connection = NULL;
585 1 : tt_int_op(router_is_already_dir_fetching(&test_ap, 1, 1), OP_EQ, 0);
586 1 : tt_int_op(router_is_already_dir_fetching(&test_ap, 1, 0), OP_EQ, 0);
587 1 : tt_int_op(router_is_already_dir_fetching(&test_ap, 0, 1), OP_EQ, 0);
588 : /* We always expect 0 in these cases */
589 1 : tt_int_op(router_is_already_dir_fetching(&test_ap, 0, 0), OP_EQ, 0);
590 1 : tt_int_op(router_is_already_dir_fetching(NULL, 1, 1), OP_EQ, 0);
591 1 : tt_int_op(router_is_already_dir_fetching(&null_addr_ap, 1, 1), OP_EQ, 0);
592 1 : tt_int_op(router_is_already_dir_fetching(&zero_port_ap, 1, 1), OP_EQ, 0);
593 :
594 : /* Test that we get 1 with a connection in the appropriate circumstances */
595 1 : mocked_connection = connection_new(CONN_TYPE_DIR, AF_INET);
596 1 : tt_int_op(router_is_already_dir_fetching(&test_ap, 1, 1), OP_EQ, 1);
597 1 : tt_int_op(router_is_already_dir_fetching(&test_ap, 1, 0), OP_EQ, 1);
598 1 : tt_int_op(router_is_already_dir_fetching(&test_ap, 0, 1), OP_EQ, 1);
599 :
600 : /* Test that we get 0 even with a connection in the appropriate
601 : * circumstances */
602 1 : tt_int_op(router_is_already_dir_fetching(&test_ap, 0, 0), OP_EQ, 0);
603 1 : tt_int_op(router_is_already_dir_fetching(NULL, 1, 1), OP_EQ, 0);
604 1 : tt_int_op(router_is_already_dir_fetching(&null_addr_ap, 1, 1), OP_EQ, 0);
605 1 : tt_int_op(router_is_already_dir_fetching(&zero_port_ap, 1, 1), OP_EQ, 0);
606 :
607 1 : done:
608 : /* If a connection is never set up, connection_free chokes on it. */
609 1 : if (mocked_connection) {
610 1 : buf_free(mocked_connection->inbuf);
611 1 : buf_free(mocked_connection->outbuf);
612 : }
613 1 : tor_free(mocked_connection);
614 1 : UNMOCK(connection_get_by_type_addr_port_purpose);
615 1 : }
616 :
617 : #undef TEST_ADDR_STR
618 : #undef TEST_DIR_PORT
619 :
620 : static long mock_apparent_skew = 0;
621 :
622 : /** Store apparent_skew and assert that the other arguments are as
623 : * expected. */
624 : static void
625 3 : mock_clock_skew_warning(const connection_t *conn, long apparent_skew,
626 : int trusted, log_domain_mask_t domain,
627 : const char *received, const char *source)
628 : {
629 3 : (void)conn;
630 3 : mock_apparent_skew = apparent_skew;
631 3 : tt_int_op(trusted, OP_EQ, 1);
632 3 : tt_i64_op(domain, OP_EQ, LD_GENERAL);
633 3 : tt_str_op(received, OP_EQ, "microdesc flavor consensus");
634 3 : tt_str_op(source, OP_EQ, "CONSENSUS");
635 3 : done:
636 3 : ;
637 3 : }
638 :
639 : /** Do common setup for test_timely_consensus() and
640 : * test_early_consensus(). Call networkstatus_set_current_consensus()
641 : * on a constructed consensus and with an appropriately-modified
642 : * approx_time. Callers expect presence or absence of appropriate log
643 : * messages and control events. */
644 : static int
645 4 : test_skew_common(void *arg, time_t now, unsigned long *offset)
646 : {
647 4 : char *consensus = NULL;
648 4 : int retval = 0;
649 :
650 4 : *offset = strtoul(arg, NULL, 10);
651 :
652 : /* Initialize the SRV subsystem */
653 4 : MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m);
654 4 : mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1,
655 : strlen(AUTHORITY_CERT_1),
656 : NULL);
657 4 : sr_init(0);
658 4 : UNMOCK(get_my_v3_authority_cert);
659 :
660 4 : construct_consensus(&consensus, now);
661 4 : tt_assert(consensus);
662 :
663 4 : update_approx_time(now + *offset);
664 :
665 4 : mock_apparent_skew = 0;
666 : /* Caller will call UNMOCK() */
667 4 : MOCK(clock_skew_warning, mock_clock_skew_warning);
668 : /* Caller will call teardown_capture_of_logs() */
669 4 : setup_capture_of_logs(LOG_WARN);
670 4 : retval = networkstatus_set_current_consensus(consensus, strlen(consensus),
671 : "microdesc", 0,
672 : NULL);
673 :
674 4 : done:
675 4 : tor_free(consensus);
676 4 : return retval;
677 : }
678 :
679 : /** Test non-early consensus */
680 : static void
681 3 : test_timely_consensus(void *arg)
682 : {
683 3 : time_t now = time(NULL);
684 3 : unsigned long offset = 0;
685 3 : int retval = 0;
686 :
687 3 : retval = test_skew_common(arg, now, &offset);
688 3 : (void)offset;
689 3 : expect_no_log_msg_containing("behind the time published in the consensus");
690 3 : tt_int_op(retval, OP_EQ, 0);
691 3 : tt_int_op(mock_apparent_skew, OP_EQ, 0);
692 3 : done:
693 3 : teardown_capture_of_logs();
694 3 : UNMOCK(clock_skew_warning);
695 3 : }
696 :
697 : /** Test early consensus */
698 : static void
699 1 : test_early_consensus(void *arg)
700 : {
701 1 : time_t now = time(NULL);
702 1 : unsigned long offset = 0;
703 1 : int retval = 0;
704 :
705 1 : retval = test_skew_common(arg, now, &offset);
706 : /* Can't use expect_single_log_msg() because of unrecognized authorities */
707 1 : expect_log_msg_containing("behind the time published in the consensus");
708 1 : tt_int_op(retval, OP_EQ, 0);
709 : /* This depends on construct_consensus() setting valid_after=now+1000 */
710 1 : tt_int_op(mock_apparent_skew, OP_EQ, offset - 1000);
711 1 : done:
712 1 : teardown_capture_of_logs();
713 1 : UNMOCK(clock_skew_warning);
714 1 : }
715 :
716 : /** Test warn_early_consensus(), expecting no warning */
717 : static void
718 4 : test_warn_early_consensus_no(const networkstatus_t *c, time_t now,
719 : long offset)
720 : {
721 4 : mock_apparent_skew = 0;
722 4 : setup_capture_of_logs(LOG_WARN);
723 4 : warn_early_consensus(c, "microdesc", now + offset);
724 4 : expect_no_log_msg_containing("behind the time published in the consensus");
725 4 : tt_int_op(mock_apparent_skew, OP_EQ, 0);
726 4 : done:
727 4 : teardown_capture_of_logs();
728 4 : }
729 :
730 : /** Test warn_early_consensus(), expecting a warning */
731 : static void
732 2 : test_warn_early_consensus_yes(const networkstatus_t *c, time_t now,
733 : long offset)
734 : {
735 2 : mock_apparent_skew = 0;
736 2 : setup_capture_of_logs(LOG_WARN);
737 2 : warn_early_consensus(c, "microdesc", now + offset);
738 : /* Can't use expect_single_log_msg() because of unrecognized authorities */
739 2 : expect_log_msg_containing("behind the time published in the consensus");
740 2 : tt_int_op(mock_apparent_skew, OP_EQ, offset);
741 2 : done:
742 2 : teardown_capture_of_logs();
743 2 : }
744 :
745 : /**
746 : * Test warn_early_consensus() directly, checking both the non-warning
747 : * case (consensus is not early) and the warning case (consensus is
748 : * early). Depends on EARLY_CONSENSUS_NOTICE_SKEW=60.
749 : */
750 : static void
751 1 : test_warn_early_consensus(void *arg)
752 : {
753 1 : networkstatus_t *c = NULL;
754 1 : time_t now = time(NULL);
755 :
756 1 : (void)arg;
757 1 : c = tor_malloc_zero(sizeof *c);
758 1 : c->valid_after = now;
759 1 : c->dist_seconds = 300;
760 1 : mock_apparent_skew = 0;
761 1 : MOCK(clock_skew_warning, mock_clock_skew_warning);
762 1 : test_warn_early_consensus_no(c, now, 60);
763 1 : test_warn_early_consensus_no(c, now, 0);
764 1 : test_warn_early_consensus_no(c, now, -60);
765 1 : test_warn_early_consensus_no(c, now, -360);
766 1 : test_warn_early_consensus_yes(c, now, -361);
767 1 : test_warn_early_consensus_yes(c, now, -600);
768 1 : UNMOCK(clock_skew_warning);
769 1 : tor_free(c);
770 1 : }
771 :
772 : #define NODE(name, flags) \
773 : { #name, test_routerlist_##name, (flags), NULL, NULL }
774 : #define ROUTER(name,flags) \
775 : { #name, test_router_##name, (flags), NULL, NULL }
776 :
777 : #define TIMELY(name, arg) \
778 : { name, test_timely_consensus, TT_FORK, &passthrough_setup, \
779 : (char *)(arg) }
780 : #define EARLY(name, arg) \
781 : { name, test_early_consensus, TT_FORK, &passthrough_setup, \
782 : (char *)(arg) }
783 :
784 : struct testcase_t routerlist_tests[] = {
785 : NODE(initiate_descriptor_downloads, 0),
786 : NODE(launch_descriptor_downloads, 0),
787 : NODE(router_is_already_dir_fetching, TT_FORK),
788 : ROUTER(pick_directory_server_impl, TT_FORK),
789 : { "directory_guard_fetch_with_no_dirinfo",
790 : test_directory_guard_fetch_with_no_dirinfo, TT_FORK, NULL, NULL },
791 : /* These depend on construct_consensus() setting
792 : * valid_after=now+1000 and dist_seconds=250 */
793 : TIMELY("timely_consensus1", "1010"),
794 : TIMELY("timely_consensus2", "1000"),
795 : TIMELY("timely_consensus3", "690"),
796 : EARLY("early_consensus1", "689"),
797 : { "warn_early_consensus", test_warn_early_consensus, 0, NULL, NULL },
798 : END_OF_TESTCASES
799 : };
|