mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-28 08:54:24 +01:00
This changes a LOT of code but in the end, behavior is the same. Unfortunately, many functions had to be changed to accomodate but in majority of cases, to become simpler. Functions are also removed specifically those that were there to convert an IPv4 as a host format to a tor_addr_t. Those are not needed anymore. The IPv4 address field has been standardized to "ipv4_addr", the ORPort to "ipv4_orport" (currently IPv6 uses ipv6_orport) and DirPort to "ipv4_dirport". This is related to Sponsor 55 work that adds IPv6 support for relays and this work is needed in order to have a common interface between IPv4 and IPv6. Closes #40043. Signed-off-by: David Goulet <dgoulet@torproject.org>
434 lines
16 KiB
C
434 lines
16 KiB
C
/* Copyright (c) 2001-2004, Roger Dingledine.
|
|
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
|
* Copyright (c) 2007-2020, The Tor Project, Inc. */
|
|
/* See LICENSE for licensing information */
|
|
|
|
#include "orconfig.h"
|
|
#define DIRVOTE_PRIVATE
|
|
#include "test/test.h"
|
|
#include "core/or/or.h"
|
|
#include "feature/dirauth/dirvote.h"
|
|
#include "feature/nodelist/nodelist.h"
|
|
#include "feature/nodelist/routerlist.h"
|
|
#include "feature/dirparse/authcert_parse.h"
|
|
#include "feature/dirparse/ns_parse.h"
|
|
#include "test/test_dir_common.h"
|
|
#include "feature/dirauth/voting_schedule.h"
|
|
|
|
#include "feature/nodelist/authority_cert_st.h"
|
|
#include "feature/nodelist/networkstatus_st.h"
|
|
#include "feature/nodelist/networkstatus_voter_info_st.h"
|
|
#include "feature/nodelist/routerinfo_st.h"
|
|
#include "feature/dirauth/vote_microdesc_hash_st.h"
|
|
#include "feature/nodelist/vote_routerstatus_st.h"
|
|
|
|
void dir_common_setup_vote(networkstatus_t **vote, time_t now);
|
|
networkstatus_t * dir_common_add_rs_and_parse(networkstatus_t *vote,
|
|
networkstatus_t **vote_out,
|
|
vote_routerstatus_t * (*vrs_gen)(int idx, time_t now),
|
|
crypto_pk_t *sign_skey, int *n_vrs,
|
|
time_t now, int clear_rl);
|
|
|
|
/** Initialize and set auth certs and keys
|
|
* Returns 0 on success, -1 on failure. Clean up handled by caller.
|
|
*/
|
|
int
|
|
dir_common_authority_pk_init(authority_cert_t **cert1,
|
|
authority_cert_t **cert2,
|
|
authority_cert_t **cert3,
|
|
crypto_pk_t **sign_skey_1,
|
|
crypto_pk_t **sign_skey_2,
|
|
crypto_pk_t **sign_skey_3)
|
|
{
|
|
/* Parse certificates and keys. */
|
|
authority_cert_t *cert;
|
|
cert = authority_cert_parse_from_string(AUTHORITY_CERT_1,
|
|
strlen(AUTHORITY_CERT_1),
|
|
NULL);
|
|
tt_assert(cert);
|
|
tt_assert(cert->identity_key);
|
|
*cert1 = cert;
|
|
tt_assert(*cert1);
|
|
*cert2 = authority_cert_parse_from_string(AUTHORITY_CERT_2,
|
|
strlen(AUTHORITY_CERT_2),
|
|
NULL);
|
|
tt_assert(*cert2);
|
|
*cert3 = authority_cert_parse_from_string(AUTHORITY_CERT_3,
|
|
strlen(AUTHORITY_CERT_3),
|
|
NULL);
|
|
tt_assert(*cert3);
|
|
*sign_skey_1 = crypto_pk_new();
|
|
*sign_skey_2 = crypto_pk_new();
|
|
*sign_skey_3 = crypto_pk_new();
|
|
|
|
tt_assert(!crypto_pk_read_private_key_from_string(*sign_skey_1,
|
|
AUTHORITY_SIGNKEY_1, -1));
|
|
tt_assert(!crypto_pk_read_private_key_from_string(*sign_skey_2,
|
|
AUTHORITY_SIGNKEY_2, -1));
|
|
tt_assert(!crypto_pk_read_private_key_from_string(*sign_skey_3,
|
|
AUTHORITY_SIGNKEY_3, -1));
|
|
|
|
tt_assert(!crypto_pk_cmp_keys(*sign_skey_1, (*cert1)->signing_key));
|
|
tt_assert(!crypto_pk_cmp_keys(*sign_skey_2, (*cert2)->signing_key));
|
|
|
|
return 0;
|
|
done:
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Generate a routerstatus for v3_networkstatus test.
|
|
*/
|
|
vote_routerstatus_t *
|
|
dir_common_gen_routerstatus_for_v3ns(int idx, time_t now)
|
|
{
|
|
vote_routerstatus_t *vrs=NULL;
|
|
routerstatus_t *rs = NULL;
|
|
tor_addr_t addr_ipv6;
|
|
char *method_list = NULL;
|
|
|
|
switch (idx) {
|
|
case 0:
|
|
/* Generate the first routerstatus. */
|
|
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
|
|
rs = &vrs->status;
|
|
vrs->version = tor_strdup("0.1.2.14");
|
|
rs->published_on = now-1500;
|
|
strlcpy(rs->nickname, "router2", sizeof(rs->nickname));
|
|
memset(rs->identity_digest, TEST_DIR_ROUTER_ID_1, DIGEST_LEN);
|
|
memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_1, DIGEST_LEN);
|
|
tor_addr_from_ipv4h(&rs->ipv4_addr, 0x99008801);
|
|
rs->ipv4_orport = 443;
|
|
rs->ipv4_dirport = 8000;
|
|
/* all flags but running and v2dir cleared */
|
|
rs->is_flagged_running = 1;
|
|
rs->is_v2_dir = 1;
|
|
rs->is_valid = 1; /* xxxxx */
|
|
break;
|
|
case 1:
|
|
/* Generate the second routerstatus. */
|
|
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
|
|
rs = &vrs->status;
|
|
vrs->version = tor_strdup("0.2.0.5");
|
|
rs->published_on = now-1000;
|
|
strlcpy(rs->nickname, "router1", sizeof(rs->nickname));
|
|
memset(rs->identity_digest, TEST_DIR_ROUTER_ID_2, DIGEST_LEN);
|
|
memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_2, DIGEST_LEN);
|
|
tor_addr_from_ipv4h(&rs->ipv4_addr, 0x99009901);
|
|
rs->ipv4_orport = 443;
|
|
rs->ipv4_dirport = 0;
|
|
tor_addr_parse(&addr_ipv6, "[1:2:3::4]");
|
|
tor_addr_copy(&rs->ipv6_addr, &addr_ipv6);
|
|
rs->ipv6_orport = 4711;
|
|
rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running =
|
|
rs->is_valid = rs->is_possible_guard = rs->is_v2_dir = 1;
|
|
break;
|
|
case 2:
|
|
/* Generate the third routerstatus. */
|
|
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
|
|
rs = &vrs->status;
|
|
vrs->version = tor_strdup("0.1.0.3");
|
|
rs->published_on = now-1000;
|
|
strlcpy(rs->nickname, "router3", sizeof(rs->nickname));
|
|
memset(rs->identity_digest, TEST_DIR_ROUTER_ID_3, DIGEST_LEN);
|
|
memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_3, DIGEST_LEN);
|
|
tor_addr_from_ipv4h(&rs->ipv4_addr, 0xAA009901);
|
|
rs->ipv4_orport = 400;
|
|
rs->ipv4_dirport = 9999;
|
|
rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
|
|
rs->is_flagged_running = rs->is_valid = rs->is_v2_dir =
|
|
rs->is_possible_guard = 1;
|
|
break;
|
|
case 3:
|
|
/* Generate a fourth routerstatus that is not running. */
|
|
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
|
|
rs = &vrs->status;
|
|
vrs->version = tor_strdup("0.1.6.3");
|
|
rs->published_on = now-1000;
|
|
strlcpy(rs->nickname, "router4", sizeof(rs->nickname));
|
|
memset(rs->identity_digest, TEST_DIR_ROUTER_ID_4, DIGEST_LEN);
|
|
memset(rs->descriptor_digest, TEST_DIR_ROUTER_DD_4, DIGEST_LEN);
|
|
tor_addr_from_ipv4h(&rs->ipv4_addr, 0xC0000203);
|
|
rs->ipv4_orport = 500;
|
|
rs->ipv4_dirport = 1999;
|
|
rs->is_v2_dir = 1;
|
|
/* Running flag (and others) cleared */
|
|
break;
|
|
case 4:
|
|
/* No more for this test; return NULL */
|
|
vrs = NULL;
|
|
break;
|
|
default:
|
|
/* Shouldn't happen */
|
|
tt_abort();
|
|
}
|
|
if (vrs) {
|
|
vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t));
|
|
method_list = make_consensus_method_list(MIN_SUPPORTED_CONSENSUS_METHOD,
|
|
MAX_SUPPORTED_CONSENSUS_METHOD,
|
|
",");
|
|
tor_asprintf(&vrs->microdesc->microdesc_hash_line,
|
|
"m %s "
|
|
"sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa%d\n",
|
|
method_list, idx);
|
|
}
|
|
|
|
done:
|
|
tor_free(method_list);
|
|
return vrs;
|
|
}
|
|
|
|
/** Initialize networkstatus vote object attributes. */
|
|
void
|
|
dir_common_setup_vote(networkstatus_t **vote, time_t now)
|
|
{
|
|
*vote = tor_malloc_zero(sizeof(networkstatus_t));
|
|
(*vote)->type = NS_TYPE_VOTE;
|
|
(*vote)->published = now;
|
|
(*vote)->supported_methods = smartlist_new();
|
|
(*vote)->known_flags = smartlist_new();
|
|
(*vote)->net_params = smartlist_new();
|
|
(*vote)->routerstatus_list = smartlist_new();
|
|
(*vote)->voters = smartlist_new();
|
|
}
|
|
|
|
/** Helper: Make a new routerinfo containing the right information for a
|
|
* given vote_routerstatus_t. */
|
|
routerinfo_t *
|
|
dir_common_generate_ri_from_rs(const vote_routerstatus_t *vrs)
|
|
{
|
|
routerinfo_t *r;
|
|
const routerstatus_t *rs = &vrs->status;
|
|
static time_t published = 0;
|
|
|
|
r = tor_malloc_zero(sizeof(routerinfo_t));
|
|
r->cert_expiration_time = TIME_MAX;
|
|
memcpy(r->cache_info.identity_digest, rs->identity_digest, DIGEST_LEN);
|
|
memcpy(r->cache_info.signed_descriptor_digest, rs->descriptor_digest,
|
|
DIGEST_LEN);
|
|
r->cache_info.do_not_cache = 1;
|
|
r->cache_info.routerlist_index = -1;
|
|
r->cache_info.signed_descriptor_body =
|
|
tor_strdup("123456789012345678901234567890123");
|
|
r->cache_info.signed_descriptor_len =
|
|
strlen(r->cache_info.signed_descriptor_body);
|
|
r->exit_policy = smartlist_new();
|
|
r->cache_info.published_on = ++published + time(NULL);
|
|
if (rs->has_bandwidth) {
|
|
/*
|
|
* Multiply by 1000 because the routerinfo_t and the routerstatus_t
|
|
* seem to use different units (*sigh*) and because we seem stuck on
|
|
* icky and perverse decimal kilobytes (*double sigh*) - see
|
|
* router_get_advertised_bandwidth_capped() of routerlist.c and
|
|
* routerstatus_format_entry() of dirserv.c.
|
|
*/
|
|
r->bandwidthrate = rs->bandwidth_kb * 1000;
|
|
r->bandwidthcapacity = rs->bandwidth_kb * 1000;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
/** Create routerstatuses and signed vote.
|
|
* Create routerstatuses using *vrs_gen* and add them to global routerlist.
|
|
* Next, create signed vote using *sign_skey* and *vote*, which should have
|
|
* predefined header fields.
|
|
* Setting *clear_rl* clears the global routerlist before adding the new
|
|
* routers.
|
|
* Return the signed vote, same as *vote_out*. Save the number of routers added
|
|
* in *n_vrs*.
|
|
*/
|
|
networkstatus_t *
|
|
dir_common_add_rs_and_parse(networkstatus_t *vote, networkstatus_t **vote_out,
|
|
vote_routerstatus_t * (*vrs_gen)(int idx, time_t now),
|
|
crypto_pk_t *sign_skey, int *n_vrs, time_t now,
|
|
int clear_rl)
|
|
{
|
|
vote_routerstatus_t *vrs;
|
|
char *v_text=NULL;
|
|
const char *msg=NULL;
|
|
int idx;
|
|
was_router_added_t router_added = -1;
|
|
*vote_out = NULL;
|
|
|
|
if (clear_rl) {
|
|
nodelist_free_all();
|
|
routerlist_free_all();
|
|
}
|
|
|
|
idx = 0;
|
|
do {
|
|
vrs = vrs_gen(idx, now);
|
|
if (vrs) {
|
|
smartlist_add(vote->routerstatus_list, vrs);
|
|
router_added =
|
|
router_add_to_routerlist(dir_common_generate_ri_from_rs(vrs),
|
|
&msg,0,0);
|
|
tt_assert(router_added >= 0);
|
|
++idx;
|
|
}
|
|
} while (vrs);
|
|
*n_vrs = idx;
|
|
|
|
/* dump the vote and try to parse it. */
|
|
v_text = format_networkstatus_vote(sign_skey, vote);
|
|
tt_assert(v_text);
|
|
*vote_out = networkstatus_parse_vote_from_string(v_text,
|
|
strlen(v_text),
|
|
NULL, NS_TYPE_VOTE);
|
|
|
|
done:
|
|
if (v_text)
|
|
tor_free(v_text);
|
|
|
|
return *vote_out;
|
|
}
|
|
|
|
/** Create a fake *vote* where *cert* describes the signer, *sign_skey*
|
|
* is the signing key, and *vrs_gen* is the function we'll use to create the
|
|
* routers on which we're voting.
|
|
* We pass *vote_out*, *n_vrs*, and *clear_rl* directly to vrs_gen().
|
|
* Return 0 on success, return -1 on failure.
|
|
*/
|
|
int
|
|
dir_common_construct_vote_1(networkstatus_t **vote, authority_cert_t *cert,
|
|
crypto_pk_t *sign_skey,
|
|
vote_routerstatus_t * (*vrs_gen)(int idx, time_t now),
|
|
networkstatus_t **vote_out, int *n_vrs,
|
|
time_t now, int clear_rl)
|
|
{
|
|
networkstatus_voter_info_t *voter;
|
|
|
|
dir_common_setup_vote(vote, now);
|
|
(*vote)->valid_after = now+1000;
|
|
(*vote)->fresh_until = now+2000;
|
|
(*vote)->valid_until = now+3000;
|
|
(*vote)->vote_seconds = 100;
|
|
(*vote)->dist_seconds = 200;
|
|
smartlist_split_string((*vote)->supported_methods, "1 2 3", NULL, 0, -1);
|
|
(*vote)->client_versions = tor_strdup("0.1.2.14,0.1.2.15");
|
|
(*vote)->server_versions = tor_strdup("0.1.2.14,0.1.2.15,0.1.2.16");
|
|
smartlist_split_string((*vote)->known_flags,
|
|
"Authority Exit Fast Guard Running Stable V2Dir Valid",
|
|
0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
|
|
voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
|
|
voter->nickname = tor_strdup("Voter1");
|
|
voter->address = tor_strdup("1.2.3.4");
|
|
tor_addr_from_ipv4h(&voter->ipv4_addr, 0x01020304);
|
|
voter->ipv4_dirport = 80;
|
|
voter->ipv4_orport = 9000;
|
|
voter->contact = tor_strdup("voter@example.com");
|
|
crypto_pk_get_digest(cert->identity_key, voter->identity_digest);
|
|
/*
|
|
* Set up a vote; generate it; try to parse it.
|
|
*/
|
|
smartlist_add((*vote)->voters, voter);
|
|
(*vote)->cert = authority_cert_dup(cert);
|
|
smartlist_split_string((*vote)->net_params, "circuitwindow=101 foo=990",
|
|
NULL, 0, 0);
|
|
*n_vrs = 0;
|
|
/* add routerstatuses */
|
|
if (!dir_common_add_rs_and_parse(*vote, vote_out, vrs_gen, sign_skey,
|
|
n_vrs, now, clear_rl))
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/** See dir_common_construct_vote_1.
|
|
* Produces a vote with slightly different values.
|
|
*/
|
|
int
|
|
dir_common_construct_vote_2(networkstatus_t **vote, authority_cert_t *cert,
|
|
crypto_pk_t *sign_skey,
|
|
vote_routerstatus_t * (*vrs_gen)(int idx, time_t now),
|
|
networkstatus_t **vote_out, int *n_vrs,
|
|
time_t now, int clear_rl)
|
|
{
|
|
networkstatus_voter_info_t *voter;
|
|
|
|
dir_common_setup_vote(vote, now);
|
|
(*vote)->type = NS_TYPE_VOTE;
|
|
(*vote)->published += 1;
|
|
(*vote)->valid_after = now+1000;
|
|
(*vote)->fresh_until = now+3005;
|
|
(*vote)->valid_until = now+3000;
|
|
(*vote)->vote_seconds = 100;
|
|
(*vote)->dist_seconds = 300;
|
|
smartlist_split_string((*vote)->supported_methods, "1 2 3", NULL, 0, -1);
|
|
smartlist_split_string((*vote)->known_flags,
|
|
"Authority Exit Fast Guard MadeOfCheese MadeOfTin "
|
|
"Running Stable V2Dir Valid", 0,
|
|
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
|
|
voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
|
|
voter->nickname = tor_strdup("Voter2");
|
|
voter->address = tor_strdup("2.3.4.5");
|
|
tor_addr_from_ipv4h(&voter->ipv4_addr, 0x02030405);
|
|
voter->ipv4_dirport = 80;
|
|
voter->ipv4_orport = 9000;
|
|
voter->contact = tor_strdup("voter@example.com");
|
|
crypto_pk_get_digest(cert->identity_key, voter->identity_digest);
|
|
/*
|
|
* Set up a vote; generate it; try to parse it.
|
|
*/
|
|
smartlist_add((*vote)->voters, voter);
|
|
(*vote)->cert = authority_cert_dup(cert);
|
|
if (! (*vote)->net_params)
|
|
(*vote)->net_params = smartlist_new();
|
|
smartlist_split_string((*vote)->net_params,
|
|
"bar=2000000000 circuitwindow=20",
|
|
NULL, 0, 0);
|
|
/* add routerstatuses */
|
|
/* dump the vote and try to parse it. */
|
|
dir_common_add_rs_and_parse(*vote, vote_out, vrs_gen, sign_skey,
|
|
n_vrs, now, clear_rl);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/** See dir_common_construct_vote_1.
|
|
* Produces a vote with slightly different values. Adds a legacy key.
|
|
*/
|
|
int
|
|
dir_common_construct_vote_3(networkstatus_t **vote, authority_cert_t *cert,
|
|
crypto_pk_t *sign_skey,
|
|
vote_routerstatus_t * (*vrs_gen)(int idx, time_t now),
|
|
networkstatus_t **vote_out, int *n_vrs,
|
|
time_t now, int clear_rl)
|
|
{
|
|
networkstatus_voter_info_t *voter;
|
|
|
|
dir_common_setup_vote(vote, now);
|
|
(*vote)->valid_after = now+1000;
|
|
(*vote)->fresh_until = now+2003;
|
|
(*vote)->valid_until = now+3000;
|
|
(*vote)->vote_seconds = 100;
|
|
(*vote)->dist_seconds = 250;
|
|
smartlist_split_string((*vote)->supported_methods, "1 2 3 4", NULL, 0, -1);
|
|
(*vote)->client_versions = tor_strdup("0.1.2.14,0.1.2.17");
|
|
(*vote)->server_versions = tor_strdup("0.1.2.10,0.1.2.15,0.1.2.16");
|
|
smartlist_split_string((*vote)->known_flags,
|
|
"Authority Exit Fast Guard Running Stable V2Dir Valid",
|
|
0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
|
|
voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
|
|
voter->nickname = tor_strdup("Voter2");
|
|
voter->address = tor_strdup("3.4.5.6");
|
|
tor_addr_from_ipv4h(&voter->ipv4_addr, 0x03040506);
|
|
voter->ipv4_dirport = 80;
|
|
voter->ipv4_orport = 9000;
|
|
voter->contact = tor_strdup("voter@example.com");
|
|
crypto_pk_get_digest(cert->identity_key, voter->identity_digest);
|
|
memset(voter->legacy_id_digest, (int)'A', DIGEST_LEN);
|
|
/*
|
|
* Set up a vote; generate it; try to parse it.
|
|
*/
|
|
smartlist_add((*vote)->voters, voter);
|
|
(*vote)->cert = authority_cert_dup(cert);
|
|
smartlist_split_string((*vote)->net_params, "circuitwindow=80 foo=660",
|
|
NULL, 0, 0);
|
|
/* add routerstatuses */
|
|
/* dump the vote and try to parse it. */
|
|
dir_common_add_rs_and_parse(*vote, vote_out, vrs_gen, sign_skey,
|
|
n_vrs, now, clear_rl);
|
|
|
|
return 0;
|
|
}
|