int fuzz_main(const uint8_t *data, size_t sz) { networkstatus_t *ns; char *str = tor_memdup_nulterm(data, sz); const char *eos = NULL; networkstatus_type_t tp = NS_TYPE_CONSENSUS; if (tor_memstr(data, MIN(sz, 1024), "tus vote")) tp = NS_TYPE_VOTE; const char *what = (tp == NS_TYPE_CONSENSUS) ? "consensus" : "vote"; ns = networkstatus_parse_vote_from_string(str, &eos, tp); if (ns) { log_debug(LD_GENERAL, "Parsing as %s okay", what); networkstatus_vote_free(ns); } else { log_debug(LD_GENERAL, "Parsing as %s failed", what); } tor_free(str); return 0; }
static void test_channel_duplicates(void *arg) { channel_t *chan = NULL; routerstatus_t rs; (void) arg; setup_full_capture_of_logs(LOG_INFO); /* Try a flat call with channel nor connections. */ channel_check_for_duplicates(); expect_log_msg_containing( "Found 0 connections to 0 relays. Found 0 current canonical " "connections, in 0 of which we were a non-canonical peer. " "0 relays had more than 1 connection, 0 had more than 2, and " "0 had more than 4 connections."); mock_ns = tor_malloc_zero(sizeof(*mock_ns)); mock_ns->routerstatus_list = smartlist_new(); MOCK(networkstatus_get_latest_consensus, mock_networkstatus_get_latest_consensus); chan = new_fake_channel(); tt_assert(chan); chan->is_canonical = test_chan_is_canonical; memset(chan->identity_digest, 'A', sizeof(chan->identity_digest)); channel_add_to_digest_map(chan); tt_ptr_op(channel_find_by_remote_identity(chan->identity_digest, NULL), OP_EQ, chan); /* No relay has been associated with this channel. */ channel_check_for_duplicates(); expect_log_msg_containing( "Found 0 connections to 0 relays. Found 0 current canonical " "connections, in 0 of which we were a non-canonical peer. " "0 relays had more than 1 connection, 0 had more than 2, and " "0 had more than 4 connections."); /* Associate relay to this connection in the consensus. */ memset(&rs, 0, sizeof(rs)); memset(rs.identity_digest, 'A', sizeof(rs.identity_digest)); smartlist_add(mock_ns->routerstatus_list, &rs); /* Non opened channel. */ chan->state = CHANNEL_STATE_CLOSING; channel_check_for_duplicates(); expect_log_msg_containing( "Found 0 connections to 0 relays. Found 0 current canonical " "connections, in 0 of which we were a non-canonical peer. " "0 relays had more than 1 connection, 0 had more than 2, and " "0 had more than 4 connections."); chan->state = CHANNEL_STATE_OPEN; channel_check_for_duplicates(); expect_log_msg_containing( "Found 1 connections to 1 relays. Found 0 current canonical " "connections, in 0 of which we were a non-canonical peer. " "0 relays had more than 1 connection, 0 had more than 2, and " "0 had more than 4 connections."); test_chan_should_be_canonical = 1; channel_check_for_duplicates(); expect_log_msg_containing( "Found 1 connections to 1 relays. Found 1 current canonical " "connections, in 1 of which we were a non-canonical peer. " "0 relays had more than 1 connection, 0 had more than 2, and " "0 had more than 4 connections."); teardown_capture_of_logs(); done: free_fake_channel(chan); smartlist_clear(mock_ns->routerstatus_list); networkstatus_vote_free(mock_ns); UNMOCK(networkstatus_get_latest_consensus); }
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)); /* 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")); /* 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)); 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_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: 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); }
void construct_consensus(char **consensus_text_md) { networkstatus_t *vote = NULL; networkstatus_t *v1 = NULL, *v2 = NULL, *v3 = NULL; networkstatus_voter_info_t *voter = NULL; authority_cert_t *cert1=NULL, *cert2=NULL, *cert3=NULL; crypto_pk_t *sign_skey_1=NULL, *sign_skey_2=NULL, *sign_skey_3=NULL; crypto_pk_t *sign_skey_leg=NULL; time_t now = time(NULL); smartlist_t *votes = NULL; int n_vrs; tt_assert(!dir_common_authority_pk_init(&cert1, &cert2, &cert3, &sign_skey_1, &sign_skey_2, &sign_skey_3)); sign_skey_leg = pk_generate(4); dir_common_construct_vote_1(&vote, cert1, sign_skey_1, &dir_common_gen_routerstatus_for_v3ns, &v1, &n_vrs, now, 1); networkstatus_vote_free(vote); tt_assert(v1); tt_int_op(n_vrs, ==, 4); tt_int_op(smartlist_len(v1->routerstatus_list), ==, 4); dir_common_construct_vote_2(&vote, cert2, sign_skey_2, &dir_common_gen_routerstatus_for_v3ns, &v2, &n_vrs, now, 1); networkstatus_vote_free(vote); tt_assert(v2); tt_int_op(n_vrs, ==, 4); tt_int_op(smartlist_len(v2->routerstatus_list), ==, 4); dir_common_construct_vote_3(&vote, cert3, sign_skey_3, &dir_common_gen_routerstatus_for_v3ns, &v3, &n_vrs, now, 1); tt_assert(v3); tt_int_op(n_vrs, ==, 4); tt_int_op(smartlist_len(v3->routerstatus_list), ==, 4); networkstatus_vote_free(vote); votes = smartlist_new(); smartlist_add(votes, v1); smartlist_add(votes, v2); smartlist_add(votes, v3); *consensus_text_md = networkstatus_compute_consensus(votes, 3, cert1->identity_key, sign_skey_1, "AAAAAAAAAAAAAAAAAAAA", sign_skey_leg, FLAV_MICRODESC); tt_assert(*consensus_text_md); done: tor_free(voter); networkstatus_vote_free(v1); networkstatus_vote_free(v2); networkstatus_vote_free(v3); smartlist_free(votes); authority_cert_free(cert1); authority_cert_free(cert2); authority_cert_free(cert3); crypto_pk_free(sign_skey_1); crypto_pk_free(sign_skey_2); crypto_pk_free(sign_skey_3); crypto_pk_free(sign_skey_leg); }