static void test_md_reject_cache(void *arg) { (void) arg; microdesc_cache_t *mc = NULL ; smartlist_t *added = NULL, *wanted = smartlist_new(); or_options_t *options = get_options_mutable(); char buf[DIGEST256_LEN]; tor_free(options->DataDirectory); options->DataDirectory = tor_strdup(get_fname("md_datadir_test_rej")); mock_rgsbd_val_a = tor_malloc_zero(sizeof(routerstatus_t)); mock_rgsbd_val_b = tor_malloc_zero(sizeof(routerstatus_t)); mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t)); mock_ns_val->valid_after = time(NULL) - 86400; mock_ns_val->valid_until = time(NULL) + 86400; mock_ns_val->flavor = FLAV_MICRODESC; #ifdef _WIN32 tt_int_op(0, OP_EQ, mkdir(options->DataDirectory)); #else tt_int_op(0, OP_EQ, mkdir(options->DataDirectory, 0700)); #endif MOCK(router_get_mutable_consensus_status_by_descriptor_digest, mock_router_get_status_by_digest); MOCK(networkstatus_get_latest_consensus_by_flavor, mock_ns_get_by_flavor); mc = get_microdesc_cache(); #define ADD(hex) \ do { \ tt_int_op(0,OP_EQ,base16_decode(buf,sizeof(buf),hex,strlen(hex))); \ smartlist_add(wanted, tor_memdup(buf, DIGEST256_LEN)); \ } while (0) /* invalid,0 */ ADD("5d76bf1c6614e885614a1e0ad074e1ab4ea14655ebeefb1736a71b5ed8a15a51"); /* invalid,2 */ ADD("20d1576c5ab11bbcff0dedb1db4a3cfcc8bc8dd839d8cbfef92d00a1a7d7b294"); /* valid, 6 */ ADD("53f740bd222ab37f19f604b1d3759aa65eff1fbce9ac254bd0fa50d4af9b1bae"); /* valid, 8 */ ADD("a0a155562d8093d8fd0feb7b93b7226e17f056c2142aab7a4ea8c5867a0376d5"); added = microdescs_add_to_cache(mc, MD_PARSE_TEST_DATA, NULL, SAVED_NOWHERE, 0, time(NULL), wanted); tt_int_op(smartlist_len(added), OP_EQ, 2); tt_int_op(mock_rgsbd_called, OP_EQ, 2); tt_int_op(mock_rgsbd_val_a->dl_status.n_download_failures, OP_EQ, 255); tt_int_op(mock_rgsbd_val_b->dl_status.n_download_failures, OP_EQ, 255); done: UNMOCK(networkstatus_get_latest_consensus_by_flavor); UNMOCK(router_get_mutable_consensus_status_by_descriptor_digest); tor_free(options->DataDirectory); microdesc_free_all(); smartlist_free(added); SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp)); smartlist_free(wanted); tor_free(mock_rgsbd_val_a); tor_free(mock_rgsbd_val_b); tor_free(mock_ns_val); }
static void test_md_cache(void *data) { or_options_t *options = NULL; microdesc_cache_t *mc = NULL ; smartlist_t *added = NULL, *wanted = NULL; microdesc_t *md1, *md2, *md3; char d1[DIGEST256_LEN], d2[DIGEST256_LEN], d3[DIGEST256_LEN]; const char *test_md3_noannotation = strchr(test_md3, '\n')+1; time_t time1, time2, time3; char *fn = NULL, *s = NULL; (void)data; options = get_options_mutable(); tt_assert(options); time1 = time(NULL); time2 = time(NULL) - 2*24*60*60; time3 = time(NULL) - 15*24*60*60; /* Possibly, turn this into a test setup/cleanup pair */ tor_free(options->DataDirectory); options->DataDirectory = tor_strdup(get_fname("md_datadir_test")); #ifdef _WIN32 tt_int_op(0, OP_EQ, mkdir(options->DataDirectory)); #else tt_int_op(0, OP_EQ, mkdir(options->DataDirectory, 0700)); #endif tt_assert(!strcmpstart(test_md3_noannotation, "onion-key")); crypto_digest256(d1, test_md1, strlen(test_md1), DIGEST_SHA256); crypto_digest256(d2, test_md2, strlen(test_md1), DIGEST_SHA256); crypto_digest256(d3, test_md3_noannotation, strlen(test_md3_noannotation), DIGEST_SHA256); mc = get_microdesc_cache(); added = microdescs_add_to_cache(mc, test_md1, NULL, SAVED_NOWHERE, 0, time1, NULL); tt_int_op(1, OP_EQ, smartlist_len(added)); md1 = smartlist_get(added, 0); smartlist_free(added); added = NULL; wanted = smartlist_new(); added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0, time2, wanted); /* Should fail, since we didn't list test_md2's digest in wanted */ tt_int_op(0, OP_EQ, smartlist_len(added)); smartlist_free(added); added = NULL; smartlist_add(wanted, tor_memdup(d2, DIGEST256_LEN)); smartlist_add(wanted, tor_memdup(d3, DIGEST256_LEN)); added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0, time2, wanted); /* Now it can work. md2 should have been added */ tt_int_op(1, OP_EQ, smartlist_len(added)); md2 = smartlist_get(added, 0); /* And it should have gotten removed from 'wanted' */ tt_int_op(smartlist_len(wanted), OP_EQ, 1); tt_mem_op(smartlist_get(wanted, 0), OP_EQ, d3, DIGEST256_LEN); smartlist_free(added); added = NULL; added = microdescs_add_to_cache(mc, test_md3, NULL, SAVED_NOWHERE, 0, -1, NULL); /* Must fail, since SAVED_NOWHERE precludes annotations */ tt_int_op(0, OP_EQ, smartlist_len(added)); smartlist_free(added); added = NULL; added = microdescs_add_to_cache(mc, test_md3_noannotation, NULL, SAVED_NOWHERE, 0, time3, NULL); /* Now it can work */ tt_int_op(1, OP_EQ, smartlist_len(added)); md3 = smartlist_get(added, 0); smartlist_free(added); added = NULL; /* Okay. We added 1...3. Let's poke them to see how they look, and make * sure they're really in the journal. */ tt_ptr_op(md1, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d1)); tt_ptr_op(md2, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d2)); tt_ptr_op(md3, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d3)); tt_int_op(md1->last_listed, OP_EQ, time1); tt_int_op(md2->last_listed, OP_EQ, time2); tt_int_op(md3->last_listed, OP_EQ, time3); tt_int_op(md1->saved_location, OP_EQ, SAVED_IN_JOURNAL); tt_int_op(md2->saved_location, OP_EQ, SAVED_IN_JOURNAL); tt_int_op(md3->saved_location, OP_EQ, SAVED_IN_JOURNAL); tt_int_op(md1->bodylen, OP_EQ, strlen(test_md1)); tt_int_op(md2->bodylen, OP_EQ, strlen(test_md2)); tt_int_op(md3->bodylen, OP_EQ, strlen(test_md3_noannotation)); tt_mem_op(md1->body, OP_EQ, test_md1, strlen(test_md1)); tt_mem_op(md2->body, OP_EQ, test_md2, strlen(test_md2)); tt_mem_op(md3->body, OP_EQ, test_md3_noannotation, strlen(test_md3_noannotation)); tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs.new", options->DataDirectory); s = read_file_to_str(fn, RFTS_BIN, NULL); tt_assert(s); tt_mem_op(md1->body, OP_EQ, s + md1->off, md1->bodylen); tt_mem_op(md2->body, OP_EQ, s + md2->off, md2->bodylen); tt_mem_op(md3->body, OP_EQ, s + md3->off, md3->bodylen); tt_ptr_op(md1->family, OP_EQ, NULL); tt_ptr_op(md3->family, OP_NE, NULL); tt_int_op(smartlist_len(md3->family), OP_EQ, 3); tt_str_op(smartlist_get(md3->family, 0), OP_EQ, "nodeX"); /* Now rebuild the cache! */ tt_int_op(microdesc_cache_rebuild(mc, 1), OP_EQ, 0); tt_int_op(md1->saved_location, OP_EQ, SAVED_IN_CACHE); tt_int_op(md2->saved_location, OP_EQ, SAVED_IN_CACHE); tt_int_op(md3->saved_location, OP_EQ, SAVED_IN_CACHE); /* The journal should be empty now */ tor_free(s); s = read_file_to_str(fn, RFTS_BIN, NULL); tt_str_op(s, OP_EQ, ""); tor_free(s); tor_free(fn); /* read the cache. */ tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs", options->DataDirectory); s = read_file_to_str(fn, RFTS_BIN, NULL); tt_mem_op(md1->body, OP_EQ, s + md1->off, strlen(test_md1)); tt_mem_op(md2->body, OP_EQ, s + md2->off, strlen(test_md2)); tt_mem_op(md3->body, OP_EQ, s + md3->off, strlen(test_md3_noannotation)); /* Okay, now we are going to forget about the cache entirely, and reload it * from the disk. */ microdesc_free_all(); mc = get_microdesc_cache(); md1 = microdesc_cache_lookup_by_digest256(mc, d1); md2 = microdesc_cache_lookup_by_digest256(mc, d2); md3 = microdesc_cache_lookup_by_digest256(mc, d3); tt_assert(md1); tt_assert(md2); tt_assert(md3); tt_mem_op(md1->body, OP_EQ, s + md1->off, strlen(test_md1)); tt_mem_op(md2->body, OP_EQ, s + md2->off, strlen(test_md2)); tt_mem_op(md3->body, OP_EQ, s + md3->off, strlen(test_md3_noannotation)); tt_int_op(md1->last_listed, OP_EQ, time1); tt_int_op(md2->last_listed, OP_EQ, time2); tt_int_op(md3->last_listed, OP_EQ, time3); /* Okay, now we are going to clear out everything older than a week old. * In practice, that means md3 */ microdesc_cache_clean(mc, time(NULL)-7*24*60*60, 1/*force*/); tt_ptr_op(md1, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d1)); tt_ptr_op(md2, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d2)); tt_ptr_op(NULL, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d3)); md3 = NULL; /* it's history now! */ /* rebuild again, make sure it stays gone. */ tt_int_op(microdesc_cache_rebuild(mc, 1), OP_EQ, 0); tt_ptr_op(md1, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d1)); tt_ptr_op(md2, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d2)); tt_ptr_op(NULL, OP_EQ, microdesc_cache_lookup_by_digest256(mc, d3)); /* Re-add md3, and make sure we can rebuild the cache. */ added = microdescs_add_to_cache(mc, test_md3_noannotation, NULL, SAVED_NOWHERE, 0, time3, NULL); tt_int_op(1, OP_EQ, smartlist_len(added)); md3 = smartlist_get(added, 0); smartlist_free(added); added = NULL; tt_int_op(md1->saved_location, OP_EQ, SAVED_IN_CACHE); tt_int_op(md2->saved_location, OP_EQ, SAVED_IN_CACHE); tt_int_op(md3->saved_location, OP_EQ, SAVED_IN_JOURNAL); tt_int_op(microdesc_cache_rebuild(mc, 1), OP_EQ, 0); tt_int_op(md3->saved_location, OP_EQ, SAVED_IN_CACHE); done: if (options) tor_free(options->DataDirectory); microdesc_free_all(); smartlist_free(added); if (wanted) SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp)); smartlist_free(wanted); tor_free(s); tor_free(fn); }
/** Test that we will use our directory guards to fetch mds even if we don't * have any dirinfo (tests bug #23862). */ static void test_directory_guard_fetch_with_no_dirinfo(void *arg) { int retval; char *consensus_text_md = NULL; or_options_t *options = get_options_mutable(); time_t now = time(NULL); (void) arg; hibernate_set_state_for_testing_(HIBERNATE_STATE_LIVE); /* Initialize the SRV subsystem */ MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m); mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1, strlen(AUTHORITY_CERT_1), NULL); sr_init(0); UNMOCK(get_my_v3_authority_cert); /* Initialize the entry node configuration from the ticket */ options->UseEntryGuards = 1; options->StrictNodes = 1; get_options_mutable()->EntryNodes = routerset_new(); routerset_parse(get_options_mutable()->EntryNodes, "2121212121212121212121212121212121212121", "foo"); /* Mock some functions */ dummy_state = tor_malloc_zero(sizeof(or_state_t)); MOCK(get_or_state, get_or_state_replacement); MOCK(directory_initiate_request, mock_directory_initiate_request); /* we need to mock this one to avoid memleaks */ MOCK(circuit_guard_state_new, mock_circuit_guard_state_new); /* Call guards_update_all() to simulate loading our state file (see * entry_guards_load_guards_from_state() and ticket #23989). */ guards_update_all(); /* Test logic: Simulate the arrival of a new consensus when we have no * dirinfo at all. Tor will need to fetch the mds from the consensus. Make * sure that Tor will use the specified entry guard instead of relying on the * fallback directories. */ /* Fixup the dirconn that will deliver the consensus */ dir_connection_t *conn = dir_connection_new(AF_INET); tor_addr_from_ipv4h(&conn->base_.addr, 0x7f000001); conn->base_.port = 8800; TO_CONN(conn)->address = tor_strdup("127.0.0.1"); conn->base_.purpose = DIR_PURPOSE_FETCH_CONSENSUS; conn->requested_resource = tor_strdup("ns"); /* Construct a consensus */ construct_consensus(&consensus_text_md, now); tt_assert(consensus_text_md); /* Place the consensus in the dirconn */ response_handler_args_t args; memset(&args, 0, sizeof(response_handler_args_t)); args.status_code = 200; args.body = consensus_text_md; args.body_len = strlen(consensus_text_md); /* Update approx time so that the consensus is considered live */ update_approx_time(now+1010); setup_capture_of_logs(LOG_DEBUG); /* Now handle the consensus */ retval = handle_response_fetch_consensus(conn, &args); tt_int_op(retval, OP_EQ, 0); /* Make sure that our primary guard was chosen */ expect_log_msg_containing("Selected primary guard router3"); done: tor_free(consensus_text_md); tor_free(dummy_state); connection_free_minimal(TO_CONN(conn)); entry_guards_free_all(); teardown_capture_of_logs(); }
static void test_rend_cache_store_v2_desc_as_dir(void *data) { (void)data; rend_cache_store_status_t ret; rend_encoded_v2_service_descriptor_t *desc_holder = NULL; char *service_id = NULL; NS_MOCK(router_get_my_routerinfo); NS_MOCK(hid_serv_responsible_for_desc_id); rend_cache_init(); // Test when we are not an HS dir mock_routerinfo = NULL; ret = rend_cache_store_v2_desc_as_dir(""); tt_int_op(ret, OP_EQ, RCS_NOTDIR); // Test when we can't parse the descriptor mock_routerinfo = tor_malloc(sizeof(routerinfo_t)); hid_serv_responsible_for_desc_id_response = 1; ret = rend_cache_store_v2_desc_as_dir("unparseable"); tt_int_op(ret, OP_EQ, RCS_BADDESC); // Test when we are not responsible for an HS hid_serv_responsible_for_desc_id_response = 0; generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); ret = rend_cache_store_v2_desc_as_dir(desc_holder->desc_str); tt_int_op(ret, OP_EQ, RCS_OKAY); rend_encoded_v2_service_descriptor_free(desc_holder); tor_free(service_id); // Test when we have an old descriptor hid_serv_responsible_for_desc_id_response = 1; generate_desc(TIME_IN_THE_PAST, &desc_holder, &service_id, 3); ret = rend_cache_store_v2_desc_as_dir(desc_holder->desc_str); tt_int_op(ret, OP_EQ, RCS_OKAY); rend_encoded_v2_service_descriptor_free(desc_holder); tor_free(service_id); // Test when we have a descriptor in the future generate_desc(TIME_IN_THE_FUTURE, &desc_holder, &service_id, 3); ret = rend_cache_store_v2_desc_as_dir(desc_holder->desc_str); tt_int_op(ret, OP_EQ, RCS_OKAY); rend_encoded_v2_service_descriptor_free(desc_holder); tor_free(service_id); // Test when two descriptors generate_desc(TIME_IN_THE_FUTURE, &desc_holder, &service_id, 3); ret = rend_cache_store_v2_desc_as_dir(desc_holder->desc_str); tt_int_op(ret, OP_EQ, RCS_OKAY); rend_encoded_v2_service_descriptor_free(desc_holder); tor_free(service_id); // Test when asking for hidden service statistics HiddenServiceStatistics rend_cache_purge(); generate_desc(RECENT_TIME, &desc_holder, &service_id, 3); get_options_mutable()->HiddenServiceStatistics = 1; ret = rend_cache_store_v2_desc_as_dir(desc_holder->desc_str); tt_int_op(ret, OP_EQ, RCS_OKAY); done: NS_UNMOCK(router_get_my_routerinfo); NS_UNMOCK(hid_serv_responsible_for_desc_id); rend_encoded_v2_service_descriptor_free(desc_holder); tor_free(service_id); rend_cache_free_all(); tor_free(mock_routerinfo); }
static void test_routerkeys_ed_keys_init_all(void *arg) { (void)arg; char *dir = tor_strdup(get_fname("test_ed_keys_init_all")); char *keydir = tor_strdup(get_fname("test_ed_keys_init_all/KEYS")); or_options_t *options = tor_malloc_zero(sizeof(or_options_t)); time_t now = time(NULL); ed25519_public_key_t id; ed25519_keypair_t sign, auth; tor_cert_t *link_cert = NULL; get_options_mutable()->ORPort_set = 1; crypto_pk_t *rsa = pk_generate(0); set_server_identity_key(rsa); set_client_identity_key(rsa); router_initialize_tls_context(); options->SigningKeyLifetime = 30*86400; options->TestingAuthKeyLifetime = 2*86400; options->TestingLinkCertLifetime = 2*86400; options->TestingSigningKeySlop = 2*86400; options->TestingAuthKeySlop = 2*3600; options->TestingLinkKeySlop = 2*3600; #ifdef _WIN32 mkdir(dir); mkdir(keydir); #else mkdir(dir, 0700); mkdir(keydir, 0700); #endif /* defined(_WIN32) */ options->DataDirectory = dir; options->KeyDirectory = keydir; tt_int_op(1, OP_EQ, load_ed_keys(options, now)); tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now, 0)); tt_assert(get_master_identity_key()); tt_assert(get_master_identity_key()); tt_assert(get_master_signing_keypair()); tt_assert(get_current_auth_keypair()); tt_assert(get_master_signing_key_cert()); tt_assert(get_current_link_cert_cert()); tt_assert(get_current_auth_key_cert()); memcpy(&id, get_master_identity_key(), sizeof(id)); memcpy(&sign, get_master_signing_keypair(), sizeof(sign)); memcpy(&auth, get_current_auth_keypair(), sizeof(auth)); link_cert = tor_cert_dup(get_current_link_cert_cert()); /* Call load_ed_keys again, but nothing has changed. */ tt_int_op(0, OP_EQ, load_ed_keys(options, now)); tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now, 0)); tt_mem_op(&id, OP_EQ, get_master_identity_key(), sizeof(id)); tt_mem_op(&sign, OP_EQ, get_master_signing_keypair(), sizeof(sign)); tt_mem_op(&auth, OP_EQ, get_current_auth_keypair(), sizeof(auth)); tt_assert(tor_cert_eq(link_cert, get_current_link_cert_cert())); /* Force a reload: we make new link/auth keys. */ routerkeys_free_all(); tt_int_op(1, OP_EQ, load_ed_keys(options, now)); tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now, 0)); tt_mem_op(&id, OP_EQ, get_master_identity_key(), sizeof(id)); tt_mem_op(&sign, OP_EQ, get_master_signing_keypair(), sizeof(sign)); tt_assert(tor_cert_eq(link_cert, get_current_link_cert_cert())); tt_mem_op(&auth, OP_NE, get_current_auth_keypair(), sizeof(auth)); tt_assert(get_master_signing_key_cert()); tt_assert(get_current_link_cert_cert()); tt_assert(get_current_auth_key_cert()); tor_cert_free(link_cert); link_cert = tor_cert_dup(get_current_link_cert_cert()); memcpy(&auth, get_current_auth_keypair(), sizeof(auth)); /* Force a link/auth-key regeneration by advancing time. */ tt_int_op(0, OP_EQ, load_ed_keys(options, now+3*86400)); tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now+3*86400, 0)); tt_mem_op(&id, OP_EQ, get_master_identity_key(), sizeof(id)); tt_mem_op(&sign, OP_EQ, get_master_signing_keypair(), sizeof(sign)); tt_assert(! tor_cert_eq(link_cert, get_current_link_cert_cert())); tt_mem_op(&auth, OP_NE, get_current_auth_keypair(), sizeof(auth)); tt_assert(get_master_signing_key_cert()); tt_assert(get_current_link_cert_cert()); tt_assert(get_current_auth_key_cert()); tor_cert_free(link_cert); link_cert = tor_cert_dup(get_current_link_cert_cert()); memcpy(&auth, get_current_auth_keypair(), sizeof(auth)); /* Force a signing-key regeneration by advancing time. */ tt_int_op(1, OP_EQ, load_ed_keys(options, now+100*86400)); tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now+100*86400, 0)); tt_mem_op(&id, OP_EQ, get_master_identity_key(), sizeof(id)); tt_mem_op(&sign, OP_NE, get_master_signing_keypair(), sizeof(sign)); tt_assert(! tor_cert_eq(link_cert, get_current_link_cert_cert())); tt_mem_op(&auth, OP_NE, get_current_auth_keypair(), sizeof(auth)); tt_assert(get_master_signing_key_cert()); tt_assert(get_current_link_cert_cert()); tt_assert(get_current_auth_key_cert()); memcpy(&sign, get_master_signing_keypair(), sizeof(sign)); tor_cert_free(link_cert); link_cert = tor_cert_dup(get_current_link_cert_cert()); memcpy(&auth, get_current_auth_keypair(), sizeof(auth)); /* Demonstrate that we can start up with no secret identity key */ routerkeys_free_all(); unlink(get_fname("test_ed_keys_init_all/KEYS/" "ed25519_master_id_secret_key")); tt_int_op(1, OP_EQ, load_ed_keys(options, now)); tt_int_op(0, OP_EQ, generate_ed_link_cert(options, now, 0)); tt_mem_op(&id, OP_EQ, get_master_identity_key(), sizeof(id)); tt_mem_op(&sign, OP_EQ, get_master_signing_keypair(), sizeof(sign)); tt_assert(! tor_cert_eq(link_cert, get_current_link_cert_cert())); tt_mem_op(&auth, OP_NE, get_current_auth_keypair(), sizeof(auth)); tt_assert(get_master_signing_key_cert()); tt_assert(get_current_link_cert_cert()); tt_assert(get_current_auth_key_cert()); /* But we're in trouble if we have no id key and our signing key has expired. */ log_global_min_severity_ = LOG_ERR; /* Suppress warnings. * XXX (better way to do this)? */ routerkeys_free_all(); tt_int_op(-1, OP_EQ, load_ed_keys(options, now+200*86400)); done: tor_free(dir); tor_free(keydir); tor_free(options); tor_cert_free(link_cert); routerkeys_free_all(); }
static void test_router_pick_directory_server_impl(void *arg) { (void)arg; networkstatus_t *con_md = NULL; char *consensus_text_md = NULL; int flags = PDS_IGNORE_FASCISTFIREWALL|PDS_RETRY_IF_NO_SERVERS; or_options_t *options = get_options_mutable(); const routerstatus_t *rs = NULL; options->UseMicrodescriptors = 1; char *router1_id = NULL, *router2_id = NULL, *router3_id = NULL; node_t *node_router1 = NULL, *node_router2 = NULL, *node_router3 = NULL; config_line_t *policy_line = NULL; time_t now = time(NULL); int tmp_dirport1, tmp_dirport3; (void)arg; MOCK(usable_consensus_flavor, mock_usable_consensus_flavor); /* With no consensus, we must be bootstrapping, regardless of time or flavor */ mock_usable_consensus_flavor_value = FLAV_NS; tt_assert(networkstatus_consensus_is_bootstrapping(now)); tt_assert(networkstatus_consensus_is_bootstrapping(now + 2000)); tt_assert(networkstatus_consensus_is_bootstrapping(now + 2*24*60*60)); tt_assert(networkstatus_consensus_is_bootstrapping(now - 2*24*60*60)); mock_usable_consensus_flavor_value = FLAV_MICRODESC; tt_assert(networkstatus_consensus_is_bootstrapping(now)); tt_assert(networkstatus_consensus_is_bootstrapping(now + 2000)); tt_assert(networkstatus_consensus_is_bootstrapping(now + 2*24*60*60)); tt_assert(networkstatus_consensus_is_bootstrapping(now - 2*24*60*60)); /* Init SR subsystem. */ MOCK(get_my_v3_authority_cert, get_my_v3_authority_cert_m); mock_cert = authority_cert_parse_from_string(AUTHORITY_CERT_1, strlen(AUTHORITY_CERT_1), NULL); sr_init(0); UNMOCK(get_my_v3_authority_cert); /* No consensus available, fail early */ rs = router_pick_directory_server_impl(V3_DIRINFO, (const int) 0, NULL); tt_ptr_op(rs, OP_EQ, NULL); construct_consensus(&consensus_text_md, now); tt_assert(consensus_text_md); con_md = networkstatus_parse_vote_from_string(consensus_text_md, strlen(consensus_text_md), NULL, NS_TYPE_CONSENSUS); tt_assert(con_md); tt_int_op(con_md->flavor,OP_EQ, FLAV_MICRODESC); tt_assert(con_md->routerstatus_list); tt_int_op(smartlist_len(con_md->routerstatus_list), OP_EQ, 3); tt_assert(!networkstatus_set_current_consensus_from_ns(con_md, "microdesc")); /* If the consensus time or flavor doesn't match, we are still * bootstrapping */ mock_usable_consensus_flavor_value = FLAV_NS; tt_assert(networkstatus_consensus_is_bootstrapping(now)); tt_assert(networkstatus_consensus_is_bootstrapping(now + 2000)); tt_assert(networkstatus_consensus_is_bootstrapping(now + 2*24*60*60)); tt_assert(networkstatus_consensus_is_bootstrapping(now - 2*24*60*60)); /* With a valid consensus for the current time and flavor, we stop * bootstrapping, even if we have no certificates */ mock_usable_consensus_flavor_value = FLAV_MICRODESC; tt_assert(!networkstatus_consensus_is_bootstrapping(now + 2000)); tt_assert(!networkstatus_consensus_is_bootstrapping(con_md->valid_after)); tt_assert(!networkstatus_consensus_is_bootstrapping(con_md->valid_until)); tt_assert(!networkstatus_consensus_is_bootstrapping(con_md->valid_until + 24*60*60)); /* These times are outside the test validity period */ tt_assert(networkstatus_consensus_is_bootstrapping(now + 2*24*60*60)); tt_assert(networkstatus_consensus_is_bootstrapping(now - 2*24*60*60)); nodelist_set_consensus(con_md); nodelist_assert_ok(); rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); /* We should not fail now we have a consensus and routerstatus_list * and nodelist are populated. */ tt_ptr_op(rs, OP_NE, NULL); /* Manipulate the nodes so we get the dir server we expect */ router1_id = tor_malloc(DIGEST_LEN); memset(router1_id, TEST_DIR_ROUTER_ID_1, DIGEST_LEN); router2_id = tor_malloc(DIGEST_LEN); memset(router2_id, TEST_DIR_ROUTER_ID_2, DIGEST_LEN); router3_id = tor_malloc(DIGEST_LEN); memset(router3_id, TEST_DIR_ROUTER_ID_3, DIGEST_LEN); node_router1 = node_get_mutable_by_id(router1_id); node_router2 = node_get_mutable_by_id(router2_id); node_router3 = node_get_mutable_by_id(router3_id); node_router1->is_possible_guard = 1; node_router1->is_running = 0; node_router3->is_running = 0; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_ptr_op(rs, OP_NE, NULL); tt_assert(tor_memeq(rs->identity_digest, router2_id, DIGEST_LEN)); rs = NULL; node_router1->is_running = 1; node_router3->is_running = 1; node_router1->rs->is_v2_dir = 0; node_router3->rs->is_v2_dir = 0; tmp_dirport1 = node_router1->rs->dir_port; tmp_dirport3 = node_router3->rs->dir_port; node_router1->rs->dir_port = 0; node_router3->rs->dir_port = 0; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_ptr_op(rs, OP_NE, NULL); tt_assert(tor_memeq(rs->identity_digest, router2_id, DIGEST_LEN)); rs = NULL; node_router1->rs->is_v2_dir = 1; node_router3->rs->is_v2_dir = 1; node_router1->rs->dir_port = tmp_dirport1; node_router3->rs->dir_port = tmp_dirport3; node_router1->is_valid = 0; node_router3->is_valid = 0; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_ptr_op(rs, OP_NE, NULL); tt_assert(tor_memeq(rs->identity_digest, router2_id, DIGEST_LEN)); rs = NULL; node_router1->is_valid = 1; node_router3->is_valid = 1; /* Manipulate overloaded */ node_router2->rs->last_dir_503_at = now; node_router3->rs->last_dir_503_at = now; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_ptr_op(rs, OP_NE, NULL); tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN)); node_router2->rs->last_dir_503_at = 0; node_router3->rs->last_dir_503_at = 0; /* Set a Fascist firewall */ flags &= ~ PDS_IGNORE_FASCISTFIREWALL; policy_line = tor_malloc_zero(sizeof(config_line_t)); policy_line->key = tor_strdup("ReachableORAddresses"); policy_line->value = tor_strdup("accept *:442, reject *:*"); options->ReachableORAddresses = policy_line; policies_parse_from_options(options); node_router1->rs->or_port = 444; node_router2->rs->or_port = 443; node_router3->rs->or_port = 442; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_ptr_op(rs, OP_NE, NULL); tt_assert(tor_memeq(rs->identity_digest, router3_id, DIGEST_LEN)); node_router1->rs->or_port = 442; node_router2->rs->or_port = 443; node_router3->rs->or_port = 444; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_ptr_op(rs, OP_NE, NULL); tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN)); /* Fascist firewall and overloaded */ node_router1->rs->or_port = 442; node_router2->rs->or_port = 443; node_router3->rs->or_port = 442; node_router3->rs->last_dir_503_at = now; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_ptr_op(rs, OP_NE, NULL); tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN)); node_router3->rs->last_dir_503_at = 0; /* Fascists against OR and Dir */ policy_line = tor_malloc_zero(sizeof(config_line_t)); policy_line->key = tor_strdup("ReachableAddresses"); policy_line->value = tor_strdup("accept *:80, reject *:*"); options->ReachableDirAddresses = policy_line; policies_parse_from_options(options); node_router1->rs->or_port = 442; node_router2->rs->or_port = 441; node_router3->rs->or_port = 443; node_router1->rs->dir_port = 80; node_router2->rs->dir_port = 80; node_router3->rs->dir_port = 81; node_router1->rs->last_dir_503_at = now; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_ptr_op(rs, OP_NE, NULL); tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN)); node_router1->rs->last_dir_503_at = 0; done: UNMOCK(usable_consensus_flavor); if (router1_id) tor_free(router1_id); if (router2_id) tor_free(router2_id); if (router3_id) tor_free(router3_id); if (options->ReachableORAddresses || options->ReachableDirAddresses) policies_free_all(); tor_free(consensus_text_md); networkstatus_vote_free(con_md); }
static void test_routerkeys_write_fingerprint(void *arg) { crypto_pk_t *key = pk_generate(2); or_options_t *options = get_options_mutable(); const char *ddir = get_fname("write_fingerprint"); char *cp = NULL, *cp2 = NULL; char fp[FINGERPRINT_LEN+1]; (void)arg; tt_assert(key); options->ORPort_set = 1; /* So that we can get the server ID key */ tor_free(options->DataDirectory); options->DataDirectory = tor_strdup(ddir); options->Nickname = tor_strdup("haflinger"); set_server_identity_key(key); set_client_identity_key(crypto_pk_dup_key(key)); tt_int_op(0, OP_EQ, check_private_dir(ddir, CPD_CREATE, NULL)); tt_int_op(crypto_pk_cmp_keys(get_server_identity_key(),key),OP_EQ,0); /* Write fingerprint file */ tt_int_op(0, OP_EQ, router_write_fingerprint(0)); cp = read_file_to_str(get_fname("write_fingerprint/fingerprint"), 0, NULL); crypto_pk_get_fingerprint(key, fp, 0); tor_asprintf(&cp2, "haflinger %s\n", fp); tt_str_op(cp, OP_EQ, cp2); tor_free(cp); tor_free(cp2); /* Write hashed-fingerprint file */ tt_int_op(0, OP_EQ, router_write_fingerprint(1)); cp = read_file_to_str(get_fname("write_fingerprint/hashed-fingerprint"), 0, NULL); crypto_pk_get_hashed_fingerprint(key, fp); tor_asprintf(&cp2, "haflinger %s\n", fp); tt_str_op(cp, OP_EQ, cp2); tor_free(cp); tor_free(cp2); /* Replace outdated file */ write_str_to_file(get_fname("write_fingerprint/hashed-fingerprint"), "junk goes here", 0); tt_int_op(0, OP_EQ, router_write_fingerprint(1)); cp = read_file_to_str(get_fname("write_fingerprint/hashed-fingerprint"), 0, NULL); crypto_pk_get_hashed_fingerprint(key, fp); tor_asprintf(&cp2, "haflinger %s\n", fp); tt_str_op(cp, OP_EQ, cp2); tor_free(cp); tor_free(cp2); done: crypto_pk_free(key); set_client_identity_key(NULL); tor_free(cp); tor_free(cp2); }
/** Run unit tests for buffers.c */ static void test_oom_streambuf(void *arg) { or_options_t *options = get_options_mutable(); circuit_t *c1 = NULL, *c2 = NULL, *c3 = NULL, *c4 = NULL, *c5 = NULL; struct timeval tv = { 1389641159, 0 }; uint32_t tvms; int i; smartlist_t *edgeconns = smartlist_new(); (void) arg; MOCK(circuit_mark_for_close_, circuit_mark_for_close_dummy_); /* Far too low for real life. */ options->MaxMemInQueues = 81*packed_cell_mem_cost() + 4096 * 34; options->CellStatistics = 0; tt_int_op(cell_queues_check_size(), OP_EQ, 0); /* We don't start out OOM. */ tt_int_op(cell_queues_get_total_allocation(), OP_EQ, 0); tt_int_op(buf_get_total_allocation(), OP_EQ, 0); /* Start all circuits with a bit of data queued in cells */ tv.tv_usec = 500*1000; /* go halfway into the second. */ tor_gettimeofday_cache_set(&tv); c1 = dummy_or_circuit_new(10,10); tv.tv_usec = 510*1000; tor_gettimeofday_cache_set(&tv); c2 = dummy_origin_circuit_new(20); tv.tv_usec = 520*1000; tor_gettimeofday_cache_set(&tv); c3 = dummy_or_circuit_new(20,20); tv.tv_usec = 530*1000; tor_gettimeofday_cache_set(&tv); c4 = dummy_or_circuit_new(0,0); tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * 80); tv.tv_usec = 600*1000; tor_gettimeofday_cache_set(&tv); /* Add some connections to c1...c4. */ for (i = 0; i < 4; ++i) { edge_connection_t *ec; /* link it to a circuit */ tv.tv_usec += 10*1000; tor_gettimeofday_cache_set(&tv); ec = dummy_edge_conn_new(c1, CONN_TYPE_EXIT, 1000, 1000); tt_assert(ec); smartlist_add(edgeconns, ec); tv.tv_usec += 10*1000; tor_gettimeofday_cache_set(&tv); ec = dummy_edge_conn_new(c2, CONN_TYPE_AP, 1000, 1000); tt_assert(ec); smartlist_add(edgeconns, ec); tv.tv_usec += 10*1000; tor_gettimeofday_cache_set(&tv); ec = dummy_edge_conn_new(c4, CONN_TYPE_EXIT, 1000, 1000); /* Yes, 4 twice*/ tt_assert(ec); smartlist_add(edgeconns, ec); tv.tv_usec += 10*1000; tor_gettimeofday_cache_set(&tv); ec = dummy_edge_conn_new(c4, CONN_TYPE_EXIT, 1000, 1000); smartlist_add(edgeconns, ec); tt_assert(ec); } tv.tv_sec += 1; tv.tv_usec = 0; tvms = (uint32_t) tv_to_msec(&tv); tt_int_op(circuit_max_queued_cell_age(c1, tvms), OP_EQ, 500); tt_int_op(circuit_max_queued_cell_age(c2, tvms), OP_EQ, 490); tt_int_op(circuit_max_queued_cell_age(c3, tvms), OP_EQ, 480); tt_int_op(circuit_max_queued_cell_age(c4, tvms), OP_EQ, 0); tt_int_op(circuit_max_queued_data_age(c1, tvms), OP_EQ, 390); tt_int_op(circuit_max_queued_data_age(c2, tvms), OP_EQ, 380); tt_int_op(circuit_max_queued_data_age(c3, tvms), OP_EQ, 0); tt_int_op(circuit_max_queued_data_age(c4, tvms), OP_EQ, 370); tt_int_op(circuit_max_queued_item_age(c1, tvms), OP_EQ, 500); tt_int_op(circuit_max_queued_item_age(c2, tvms), OP_EQ, 490); tt_int_op(circuit_max_queued_item_age(c3, tvms), OP_EQ, 480); tt_int_op(circuit_max_queued_item_age(c4, tvms), OP_EQ, 370); tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * 80); tt_int_op(buf_get_total_allocation(), OP_EQ, 4096*16*2); /* Now give c4 a very old buffer of modest size */ { edge_connection_t *ec; tv.tv_sec -= 1; tv.tv_usec = 0; tor_gettimeofday_cache_set(&tv); ec = dummy_edge_conn_new(c4, CONN_TYPE_EXIT, 1000, 1000); tt_assert(ec); smartlist_add(edgeconns, ec); } tt_int_op(buf_get_total_allocation(), OP_EQ, 4096*17*2); tt_int_op(circuit_max_queued_item_age(c4, tvms), OP_EQ, 1000); tt_int_op(cell_queues_check_size(), OP_EQ, 0); /* And run over the limit. */ tv.tv_usec = 800*1000; tor_gettimeofday_cache_set(&tv); c5 = dummy_or_circuit_new(0,5); tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * 85); tt_int_op(buf_get_total_allocation(), OP_EQ, 4096*17*2); tt_int_op(cell_queues_check_size(), OP_EQ, 1); /* We are now OOM */ /* C4 should have died. */ tt_assert(! c1->marked_for_close); tt_assert(! c2->marked_for_close); tt_assert(! c3->marked_for_close); tt_assert(c4->marked_for_close); tt_assert(! c5->marked_for_close); tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * 85); tt_int_op(buf_get_total_allocation(), OP_EQ, 4096*8*2); done: circuit_free(c1); circuit_free(c2); circuit_free(c3); circuit_free(c4); circuit_free(c5); SMARTLIST_FOREACH(edgeconns, edge_connection_t *, ec, connection_free_(TO_CONN(ec))); smartlist_free(edgeconns); UNMOCK(circuit_mark_for_close_); }
/** Run unit tests for buffers.c */ static void test_oom_circbuf(void *arg) { or_options_t *options = get_options_mutable(); circuit_t *c1 = NULL, *c2 = NULL, *c3 = NULL, *c4 = NULL; struct timeval tv = { 1389631048, 0 }; (void) arg; MOCK(circuit_mark_for_close_, circuit_mark_for_close_dummy_); /* Far too low for real life. */ options->MaxMemInQueues = 256*packed_cell_mem_cost(); options->CellStatistics = 0; tt_int_op(cell_queues_check_size(), OP_EQ, 0); /* We don't start out OOM. */ tt_int_op(cell_queues_get_total_allocation(), OP_EQ, 0); tt_int_op(buf_get_total_allocation(), OP_EQ, 0); /* Now we're going to fake up some circuits and get them added to the global circuit list. */ tv.tv_usec = 0; tor_gettimeofday_cache_set(&tv); c1 = dummy_origin_circuit_new(30); tv.tv_usec = 10*1000; tor_gettimeofday_cache_set(&tv); c2 = dummy_or_circuit_new(20, 20); tt_int_op(packed_cell_mem_cost(), OP_EQ, sizeof(packed_cell_t)); tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * 70); tt_int_op(cell_queues_check_size(), OP_EQ, 0); /* We are still not OOM */ tv.tv_usec = 20*1000; tor_gettimeofday_cache_set(&tv); c3 = dummy_or_circuit_new(100, 85); tt_int_op(cell_queues_check_size(), OP_EQ, 0); /* We are still not OOM */ tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * 255); tv.tv_usec = 30*1000; tor_gettimeofday_cache_set(&tv); /* Adding this cell will trigger our OOM handler. */ c4 = dummy_or_circuit_new(2, 0); tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * 257); tt_int_op(cell_queues_check_size(), OP_EQ, 1); /* We are now OOM */ tt_assert(c1->marked_for_close); tt_assert(! c2->marked_for_close); tt_assert(! c3->marked_for_close); tt_assert(! c4->marked_for_close); tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * (257 - 30)); circuit_free(c1); tv.tv_usec = 0; tor_gettimeofday_cache_set(&tv); /* go back in time */ c1 = dummy_or_circuit_new(90, 0); tv.tv_usec = 40*1000; /* go back to the future */ tor_gettimeofday_cache_set(&tv); tt_int_op(cell_queues_check_size(), OP_EQ, 1); /* We are now OOM */ tt_assert(c1->marked_for_close); tt_assert(! c2->marked_for_close); tt_assert(! c3->marked_for_close); tt_assert(! c4->marked_for_close); tt_int_op(cell_queues_get_total_allocation(), OP_EQ, packed_cell_mem_cost() * (257 - 30)); done: circuit_free(c1); circuit_free(c2); circuit_free(c3); circuit_free(c4); UNMOCK(circuit_mark_for_close_); }
/** Run unit tests for private dir permission enforcement logic. */ static void test_checkdir_perms(void *testdata) { (void)testdata; or_options_t *options = get_options_mutable(); const char *subdir = "test_checkdir"; char *testdir = NULL; cpd_check_t cpd_chkopts; cpd_check_t unix_create_opts; cpd_check_t unix_verify_optsmask; struct stat st; umask(022); /* setup data directory before tests. */ tor_free(options->DataDirectory); options->DataDirectory = tor_strdup(get_fname(subdir)); tt_int_op(mkdir(options->DataDirectory, 0750), OP_EQ, 0); /* test: create new dir, no flags. */ testdir = get_datadir_fname("checkdir_new_none"); cpd_chkopts = CPD_CREATE; unix_verify_optsmask = 0077; tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL)); tt_int_op(0, OP_EQ, stat(testdir, &st)); tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask)); tor_free(testdir); /* test: create new dir, CPD_GROUP_OK option set. */ testdir = get_datadir_fname("checkdir_new_groupok"); cpd_chkopts = CPD_CREATE|CPD_GROUP_OK; unix_verify_optsmask = 0077; tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL)); tt_int_op(0, OP_EQ, stat(testdir, &st)); tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask)); tor_free(testdir); /* test: should get an error on existing dir with wrong perms */ testdir = get_datadir_fname("checkdir_new_groupok_err"); tt_int_op(0, OP_EQ, mkdir(testdir, 027)); cpd_chkopts = CPD_CHECK_MODE_ONLY|CPD_CREATE|CPD_GROUP_OK; tt_int_op_nowin(-1, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL)); tor_free(testdir); /* test: create new dir, CPD_GROUP_READ option set. */ testdir = get_datadir_fname("checkdir_new_groupread"); cpd_chkopts = CPD_CREATE|CPD_GROUP_READ; unix_verify_optsmask = 0027; tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL)); tt_int_op(0, OP_EQ, stat(testdir, &st)); tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask)); tor_free(testdir); /* test: check existing dir created with defaults, and verify with CPD_CREATE only. */ testdir = get_datadir_fname("checkdir_exists_none"); cpd_chkopts = CPD_CREATE; unix_create_opts = 0700; (void)unix_create_opts; unix_verify_optsmask = 0077; tt_int_op(0, OP_EQ, mkdir(testdir, unix_create_opts)); tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL)); tt_int_op(0, OP_EQ, stat(testdir, &st)); tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask)); tor_free(testdir); /* test: check existing dir created with defaults, and verify with CPD_GROUP_OK option set. */ testdir = get_datadir_fname("checkdir_exists_groupok"); cpd_chkopts = CPD_CREATE; unix_verify_optsmask = 0077; tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL)); cpd_chkopts = CPD_GROUP_OK; tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL)); tt_int_op(0, OP_EQ, stat(testdir, &st)); tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask)); tor_free(testdir); /* test: check existing dir created with defaults, and verify with CPD_GROUP_READ option set. */ testdir = get_datadir_fname("checkdir_exists_groupread"); cpd_chkopts = CPD_CREATE; unix_verify_optsmask = 0027; tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL)); cpd_chkopts = CPD_GROUP_READ; tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL)); tt_int_op(0, OP_EQ, stat(testdir, &st)); tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask)); tor_free(testdir); /* test: check existing dir created with CPD_GROUP_READ, and verify with CPD_GROUP_OK option set. */ testdir = get_datadir_fname("checkdir_existsread_groupok"); cpd_chkopts = CPD_CREATE|CPD_GROUP_READ; unix_verify_optsmask = 0027; tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL)); cpd_chkopts = CPD_GROUP_OK; tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL)); tt_int_op(0, OP_EQ, stat(testdir, &st)); tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask)); tor_free(testdir); /* test: check existing dir created with CPD_GROUP_READ, and verify with CPD_GROUP_READ option set. */ testdir = get_datadir_fname("checkdir_existsread_groupread"); cpd_chkopts = CPD_CREATE|CPD_GROUP_READ; unix_verify_optsmask = 0027; tt_int_op(0, OP_EQ, check_private_dir(testdir, cpd_chkopts, NULL)); tt_int_op(0, OP_EQ, stat(testdir, &st)); tt_int_op_nowin(0, OP_EQ, (st.st_mode & unix_verify_optsmask)); done: tor_free(testdir); }
static void test_router_pick_directory_server_impl(void *arg) { (void)arg; networkstatus_t *con_md = NULL; const char *consensus_text_md = NULL; int flags = PDS_IGNORE_FASCISTFIREWALL|PDS_RETRY_IF_NO_SERVERS; or_options_t *options = get_options_mutable(); const routerstatus_t *rs = NULL; options->UseMicrodescriptors = 1; char *router1_id = NULL, *router2_id = NULL, *router3_id = NULL; node_t *node_router1 = NULL, *node_router2 = NULL, *node_router3 = NULL; config_line_t *policy_line = NULL; time_t now = time(NULL); int tmp_dirport1, tmp_dirport3; (void)arg; /* No consensus available, fail early */ rs = router_pick_directory_server_impl(V3_DIRINFO, (const int) 0, NULL); tt_assert(rs == NULL); construct_consensus(&consensus_text_md); tt_assert(consensus_text_md); con_md = networkstatus_parse_vote_from_string(consensus_text_md, NULL, NS_TYPE_CONSENSUS); tt_assert(con_md); tt_int_op(con_md->flavor,==, FLAV_MICRODESC); tt_assert(con_md->routerstatus_list); tt_int_op(smartlist_len(con_md->routerstatus_list), ==, 3); tt_assert(!networkstatus_set_current_consensus_from_ns(con_md, "microdesc")); nodelist_set_consensus(con_md); nodelist_assert_ok(); rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); /* We should not fail now we have a consensus and routerstatus_list * and nodelist are populated. */ tt_assert(rs != NULL); /* Manipulate the nodes so we get the dir server we expect */ router1_id = tor_malloc(DIGEST_LEN); memset(router1_id, TEST_DIR_ROUTER_ID_1, DIGEST_LEN); router2_id = tor_malloc(DIGEST_LEN); memset(router2_id, TEST_DIR_ROUTER_ID_2, DIGEST_LEN); router3_id = tor_malloc(DIGEST_LEN); memset(router3_id, TEST_DIR_ROUTER_ID_3, DIGEST_LEN); node_router1 = node_get_mutable_by_id(router1_id); node_router2 = node_get_mutable_by_id(router2_id); node_router3 = node_get_mutable_by_id(router3_id); node_router1->is_possible_guard = 1; node_router1->is_running = 0; node_router3->is_running = 0; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_assert(rs != NULL); tt_assert(tor_memeq(rs->identity_digest, router2_id, DIGEST_LEN)); rs = NULL; node_router1->is_running = 1; node_router3->is_running = 1; node_router1->rs->is_v2_dir = 0; node_router3->rs->is_v2_dir = 0; tmp_dirport1 = node_router1->rs->dir_port; tmp_dirport3 = node_router3->rs->dir_port; node_router1->rs->dir_port = 0; node_router3->rs->dir_port = 0; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_assert(rs != NULL); tt_assert(tor_memeq(rs->identity_digest, router2_id, DIGEST_LEN)); rs = NULL; node_router1->rs->is_v2_dir = 1; node_router3->rs->is_v2_dir = 1; node_router1->rs->dir_port = tmp_dirport1; node_router3->rs->dir_port = tmp_dirport3; node_router1->is_valid = 0; node_router3->is_valid = 0; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_assert(rs != NULL); tt_assert(tor_memeq(rs->identity_digest, router2_id, DIGEST_LEN)); rs = NULL; node_router1->is_valid = 1; node_router3->is_valid = 1; flags |= PDS_FOR_GUARD; node_router1->using_as_guard = 1; node_router2->using_as_guard = 1; node_router3->using_as_guard = 1; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_assert(rs == NULL); node_router1->using_as_guard = 0; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_assert(rs != NULL); tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN)); rs = NULL; node_router2->using_as_guard = 0; node_router3->using_as_guard = 0; /* One not valid, one guard. This should leave one remaining */ node_router1->is_valid = 0; node_router2->using_as_guard = 1; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_assert(rs != NULL); tt_assert(tor_memeq(rs->identity_digest, router3_id, DIGEST_LEN)); rs = NULL; node_router1->is_valid = 1; node_router2->using_as_guard = 0; /* Manipulate overloaded */ node_router2->rs->last_dir_503_at = now; node_router3->rs->last_dir_503_at = now; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_assert(rs != NULL); tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN)); node_router2->rs->last_dir_503_at = 0; node_router3->rs->last_dir_503_at = 0; /* Set a Fascist firewall */ flags &= ! PDS_IGNORE_FASCISTFIREWALL; policy_line = tor_malloc_zero(sizeof(config_line_t)); policy_line->key = tor_strdup("ReachableORAddresses"); policy_line->value = tor_strdup("accept *:442, reject *:*"); options->ReachableORAddresses = policy_line; policies_parse_from_options(options); node_router1->rs->or_port = 444; node_router2->rs->or_port = 443; node_router3->rs->or_port = 442; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_assert(rs != NULL); tt_assert(tor_memeq(rs->identity_digest, router3_id, DIGEST_LEN)); node_router1->rs->or_port = 442; node_router2->rs->or_port = 443; node_router3->rs->or_port = 444; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_assert(rs != NULL); tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN)); /* Fascist firewall and overloaded */ node_router1->rs->or_port = 442; node_router2->rs->or_port = 443; node_router3->rs->or_port = 442; node_router3->rs->last_dir_503_at = now; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_assert(rs != NULL); tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN)); node_router3->rs->last_dir_503_at = 0; /* Fascists against OR and Dir */ policy_line = tor_malloc_zero(sizeof(config_line_t)); policy_line->key = tor_strdup("ReachableAddresses"); policy_line->value = tor_strdup("accept *:80, reject *:*"); options->ReachableDirAddresses = policy_line; policies_parse_from_options(options); node_router1->rs->or_port = 442; node_router2->rs->or_port = 441; node_router3->rs->or_port = 443; node_router1->rs->dir_port = 80; node_router2->rs->dir_port = 80; node_router3->rs->dir_port = 81; node_router1->rs->last_dir_503_at = now; rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL); tt_assert(rs != NULL); tt_assert(tor_memeq(rs->identity_digest, router1_id, DIGEST_LEN)); node_router1->rs->last_dir_503_at = 0; done: if (router1_id) tor_free(router1_id); if (router2_id) tor_free(router2_id); if (router3_id) tor_free(router3_id); if (options->ReachableORAddresses || options->ReachableDirAddresses) policies_free_all(); }