Merge remote-tracking branch 'public/bug10758'

This commit is contained in:
Nick Mathewson 2014-02-03 11:05:29 -05:00
commit c6c87fb6d1
18 changed files with 59 additions and 1877 deletions

4
changes/bug10758 Normal file
View File

@ -0,0 +1,4 @@
o Removed code
- Remove all code that existed to support the v2 directory system:
There are no longer any v2 directory authorities. Resolves
bug 10758.

View File

@ -215,7 +215,7 @@ static config_var_t option_vars_[] = {
V(DisableAllSwap, BOOL, "0"),
V(DisableDebuggerAttachment, BOOL, "1"),
V(DisableIOCP, BOOL, "1"),
V(DisableV2DirectoryInfo_, BOOL, "0"),
OBSOLETE("DisableV2DirectoryInfo_"),
V(DynamicDHGroups, BOOL, "0"),
VPORT(DNSPort, LINELIST, NULL),
V(DNSListenAddress, LINELIST, NULL),
@ -248,7 +248,7 @@ static config_var_t option_vars_[] = {
V(FetchServerDescriptors, BOOL, "1"),
V(FetchHidServDescriptors, BOOL, "1"),
V(FetchUselessDescriptors, BOOL, "0"),
V(FetchV2Networkstatus, BOOL, "0"),
OBSOLETE("FetchV2Networkstatus"),
V(GeoIPExcludeUnknown, AUTOBOOL, "auto"),
#ifdef _WIN32
V(GeoIPFile, FILENAME, "<default>"),
@ -419,7 +419,7 @@ static config_var_t option_vars_[] = {
V(User, STRING, NULL),
V(UserspaceIOCPBuffers, BOOL, "0"),
VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
VAR("V2AuthoritativeDirectory",BOOL, V2AuthoritativeDir, "0"),
OBSOLETE("V2AuthoritativeDirectory"),
VAR("V3AuthoritativeDirectory",BOOL, V3AuthoritativeDir, "0"),
V(TestingV3AuthInitialVotingInterval, INTERVAL, "30 minutes"),
V(TestingV3AuthInitialVoteDelay, INTERVAL, "5 minutes"),
@ -982,7 +982,7 @@ consider_adding_dir_servers(const or_options_t *options,
if (!options->AlternateBridgeAuthority)
type |= BRIDGE_DIRINFO;
if (!options->AlternateDirAuthority)
type |= V1_DIRINFO | V2_DIRINFO | V3_DIRINFO | EXTRAINFO_DIRINFO |
type |= V1_DIRINFO | V3_DIRINFO | EXTRAINFO_DIRINFO |
MICRODESC_DIRINFO;
if (!options->AlternateHSAuthority)
type |= HIDSERV_DIRINFO;
@ -1136,20 +1136,6 @@ options_act_reversible(const or_options_t *old_options, char **msg)
/* No need to roll back, since you can't change the value. */
}
if (directory_caches_v2_dir_info(options)) {
char *fn = NULL;
tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-status",
options->DataDirectory);
if (check_private_dir(fn, running_tor ? CPD_CREATE : CPD_CHECK,
options->User) < 0) {
tor_asprintf(msg,
"Couldn't access/create private data directory \"%s\"", fn);
tor_free(fn);
goto done;
}
tor_free(fn);
}
/* Bail out at this point if we're not going to be a client or server:
* we don't run Tor itself. */
if (!running_tor)
@ -2378,9 +2364,9 @@ compute_publishserverdescriptor(or_options_t *options)
if (options->BridgeRelay)
*auth |= BRIDGE_DIRINFO;
else
*auth |= V2_DIRINFO | V3_DIRINFO;
*auth |= V3_DIRINFO;
else if (!strcasecmp(string, "v2"))
*auth |= V2_DIRINFO;
/* obsolete */;
else if (!strcasecmp(string, "v3"))
*auth |= V3_DIRINFO;
else if (!strcasecmp(string, "bridge"))
@ -2552,10 +2538,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("TokenBucketRefillInterval must be between 1 and 1000 inclusive.");
}
if (options->DisableV2DirectoryInfo_ && ! authdir_mode(options)) {
REJECT("DisableV2DirectoryInfo_ set, but we aren't an authority.");
}
if (options->ExcludeExitNodes || options->ExcludeNodes) {
options->ExcludeExitNodesUnion_ = routerset_new();
routerset_union(options->ExcludeExitNodesUnion_,options->ExcludeExitNodes);
@ -2613,7 +2595,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
options->DownloadExtraInfo = 1;
}
if (!(options->BridgeAuthoritativeDir || options->HSAuthoritativeDir ||
options->V1AuthoritativeDir || options->V2AuthoritativeDir ||
options->V1AuthoritativeDir ||
options->V3AuthoritativeDir))
REJECT("AuthoritativeDir is set, but none of "
"(Bridge/HS/V1/V2/V3)AuthoritativeDir is set.");
@ -2826,7 +2808,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
if ((options->BridgeRelay
|| options->PublishServerDescriptor_ & BRIDGE_DIRINFO)
&& (options->PublishServerDescriptor_
& (V1_DIRINFO|V2_DIRINFO|V3_DIRINFO))) {
& (V1_DIRINFO|V3_DIRINFO))) {
REJECT("Bridges are not supposed to publish router descriptors to the "
"directory authorities. Please correct your "
"PublishServerDescriptor line.");
@ -5037,8 +5019,8 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type,
uint16_t dir_port = 0, or_port = 0;
char digest[DIGEST_LEN];
char v3_digest[DIGEST_LEN];
dirinfo_type_t type = V2_DIRINFO;
int is_not_hidserv_authority = 0, is_not_v2_authority = 0;
dirinfo_type_t type = 0;
int is_not_hidserv_authority = 0;
double weight = 1.0;
items = smartlist_new();
@ -5066,8 +5048,6 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type,
is_not_hidserv_authority = 1;
} else if (!strcasecmp(flag, "bridge")) {
type |= BRIDGE_DIRINFO;
} else if (!strcasecmp(flag, "no-v2")) {
is_not_v2_authority = 1;
} else if (!strcasecmpstart(flag, "orport=")) {
int ok;
char *portstring = flag + strlen("orport=");
@ -5101,8 +5081,6 @@ parse_dir_authority_line(const char *line, dirinfo_type_t required_type,
}
if (is_not_hidserv_authority)
type &= ~HIDSERV_DIRINFO;
if (is_not_v2_authority)
type &= ~V2_DIRINFO;
if (smartlist_len(items) < 2) {
log_warn(LD_CONFIG, "Too few arguments to DirAuthority line.");

View File

@ -1747,39 +1747,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
tor_free(url);
smartlist_free(descs);
} else if (!strcmpstart(question, "dir/status/")) {
if (directory_permits_controller_requests(get_options())) {
size_t len=0;
char *cp;
smartlist_t *status_list = smartlist_new();
dirserv_get_networkstatus_v2(status_list,
question+strlen("dir/status/"));
SMARTLIST_FOREACH(status_list, cached_dir_t *, d, len += d->dir_len);
cp = *answer = tor_malloc(len+1);
SMARTLIST_FOREACH(status_list, cached_dir_t *, d, {
memcpy(cp, d->dir, d->dir_len);
cp += d->dir_len;
});
*cp = '\0';
smartlist_free(status_list);
} else {
smartlist_t *fp_list = smartlist_new();
smartlist_t *status_list = smartlist_new();
dirserv_get_networkstatus_v2_fingerprints(
fp_list, question+strlen("dir/status/"));
SMARTLIST_FOREACH(fp_list, const char *, fp, {
char *s;
char *fname = networkstatus_get_cache_filename(fp);
s = read_file_to_str(fname, 0, NULL);
if (s)
smartlist_add(status_list, s);
tor_free(fname);
});
SMARTLIST_FOREACH(fp_list, char *, fp, tor_free(fp));
smartlist_free(fp_list);
*answer = smartlist_join_strings(status_list, "", 0, NULL);
SMARTLIST_FOREACH(status_list, char *, s, tor_free(s));
smartlist_free(status_list);
}
*answer = tor_strdup("");
} else if (!strcmp(question, "dir/status-vote/current/consensus")) { /* v3 */
if (directory_caches_dir_info(get_options())) {
const cached_dir_t *consensus = dirserv_get_consensus("ns");

View File

@ -67,15 +67,11 @@ static int purpose_needs_anonymity(uint8_t dir_purpose,
uint8_t router_purpose);
static char *http_get_header(const char *headers, const char *which);
static void http_set_address_origin(const char *headers, connection_t *conn);
static void connection_dir_download_v2_networkstatus_failed(
dir_connection_t *conn, int status_code);
static void connection_dir_download_routerdesc_failed(dir_connection_t *conn);
static void connection_dir_bridge_routerdesc_failed(dir_connection_t *conn);
static void connection_dir_download_cert_failed(
dir_connection_t *conn, int status_code);
static void connection_dir_retry_bridges(smartlist_t *descs);
static void dir_networkstatus_download_failed(smartlist_t *failed,
int status_code);
static void dir_routerdesc_download_failed(smartlist_t *failed,
int status_code,
int router_purpose,
@ -135,7 +131,6 @@ purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
if (dir_purpose == DIR_PURPOSE_UPLOAD_DIR ||
dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES ||
dir_purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS ||
dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES ||
dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS ||
@ -156,8 +151,6 @@ authdir_type_to_string(dirinfo_type_t auth)
smartlist_t *lst = smartlist_new();
if (auth & V1_DIRINFO)
smartlist_add(lst, (void*)"V1");
if (auth & V2_DIRINFO)
smartlist_add(lst, (void*)"V2");
if (auth & V3_DIRINFO)
smartlist_add(lst, (void*)"V3");
if (auth & BRIDGE_DIRINFO)
@ -189,8 +182,6 @@ dir_conn_purpose_to_string(int purpose)
return "server vote upload";
case DIR_PURPOSE_UPLOAD_SIGNATURES:
return "consensus signature upload";
case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
return "network-status fetch";
case DIR_PURPOSE_FETCH_SERVERDESC:
return "server descriptor fetch";
case DIR_PURPOSE_FETCH_EXTRAINFO:
@ -263,8 +254,8 @@ directories_have_accepted_server_descriptor(void)
* <b>router_purpose</b> describes the type of descriptor we're
* publishing, if we're publishing a descriptor -- e.g. general or bridge.
*
* <b>type</b> specifies what sort of dir authorities (V1, V2,
* HIDSERV, BRIDGE) we should upload to.
* <b>type</b> specifies what sort of dir authorities (V1, V3,
* HIDSERV, BRIDGE, etc) we should upload to.
*
* If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
* <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
@ -350,8 +341,7 @@ should_use_directory_guards(const or_options_t *options)
/* If we're configured to fetch directory info aggressively or of a
* nonstandard type, don't use directory guards. */
if (options->DownloadExtraInfo || options->FetchDirInfoEarly ||
options->FetchDirInfoExtraEarly || options->FetchUselessDescriptors ||
options->FetchV2Networkstatus)
options->FetchDirInfoExtraEarly || options->FetchUselessDescriptors)
return 0;
if (! options->PreferTunneledDirConns)
return 0;
@ -414,11 +404,6 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
(router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
V3_DIRINFO);
break;
case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
type = V2_DIRINFO;
prefer_authority = 1; /* Only v2 authorities have these anyway. */
require_authority = 1; /* Don't fallback to asking a non-authority */
break;
case DIR_PURPOSE_FETCH_SERVERDESC:
type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
V3_DIRINFO);
@ -719,11 +704,7 @@ connection_dir_request_failed(dir_connection_t *conn)
}
if (!entry_list_is_constrained(get_options()))
router_set_status(conn->identity_digest, 0); /* don't try him again */
if (conn->base_.purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS) {
log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
conn->base_.address);
connection_dir_download_v2_networkstatus_failed(conn, -1);
} else if (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
if (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
log_info(LD_DIR, "Giving up on serverdesc/extrainfo fetch from "
"directory server at '%s'; retrying",
@ -752,43 +733,6 @@ connection_dir_request_failed(dir_connection_t *conn)
}
}
/** Called when an attempt to download one or more network status
* documents on connection <b>conn</b> failed. Decide whether to
* retry the fetch now, later, or never.
*/
static void
connection_dir_download_v2_networkstatus_failed(dir_connection_t *conn,
int status_code)
{
if (!conn->requested_resource) {
/* We never reached directory_send_command, which means that we never
* opened a network connection. Either we're out of sockets, or the
* network is down. Either way, retrying would be pointless. */
return;
}
if (!strcmpstart(conn->requested_resource, "all")) {
/* We're a non-authoritative directory cache; try again. Ignore status
* code, since we don't want to keep trying forever in a tight loop
* if all the authorities are shutting us out. */
const smartlist_t *trusted_dirs = router_get_trusted_dir_servers();
SMARTLIST_FOREACH(trusted_dirs, dir_server_t *, ds,
download_status_failed(&ds->v2_ns_dl_status, 0));
directory_get_from_dirserver(conn->base_.purpose, conn->router_purpose,
"all.z", 0 /* don't retry_if_no_servers */);
} else if (!strcmpstart(conn->requested_resource, "fp/")) {
/* We were trying to download by fingerprint; mark them all as having
* failed, and possibly retry them later.*/
smartlist_t *failed = smartlist_new();
dir_split_resource_into_fingerprints(conn->requested_resource+3,
failed, NULL, 0);
if (smartlist_len(failed)) {
dir_networkstatus_download_failed(failed, status_code);
SMARTLIST_FOREACH(failed, char *, cp, tor_free(cp));
}
smartlist_free(failed);
}
}
/** Helper: Attempt to fetch directly the descriptors of each bridge
* listed in <b>failed</b>.
*/
@ -1250,11 +1194,6 @@ directory_send_command(dir_connection_t *conn,
}
switch (purpose) {
case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
tor_assert(resource);
httpcommand = "GET";
tor_asprintf(&url, "/tor/status/%s", resource);
break;
case DIR_PURPOSE_FETCH_CONSENSUS:
/* resource is optional. If present, it's a flavor name */
tor_assert(!payload);
@ -1824,77 +1763,6 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
}
}
if (conn->base_.purpose == DIR_PURPOSE_FETCH_V2_NETWORKSTATUS) {
smartlist_t *which = NULL;
v2_networkstatus_source_t source;
char *cp;
log_info(LD_DIR,"Received networkstatus objects (size %d) from server "
"'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port);
if (status_code != 200) {
static ratelim_t warning_limit = RATELIM_INIT(3600);
char *m;
if ((m = rate_limit_log(&warning_limit, now))) {
log_warn(LD_DIR,
"Received http status code %d (%s) from server "
"'%s:%d' while fetching \"/tor/status/%s\". "
"I'll try again soon.%s",
status_code, escaped(reason), conn->base_.address,
conn->base_.port, conn->requested_resource, m);
tor_free(m);
}
tor_free(body); tor_free(headers); tor_free(reason);
connection_dir_download_v2_networkstatus_failed(conn, status_code);
return -1;
}
if (conn->requested_resource &&
!strcmpstart(conn->requested_resource,"fp/")) {
source = NS_FROM_DIR_BY_FP;
which = smartlist_new();
dir_split_resource_into_fingerprints(conn->requested_resource+3,
which, NULL, 0);
} else if (conn->requested_resource &&
!strcmpstart(conn->requested_resource, "all")) {
source = NS_FROM_DIR_ALL;
which = smartlist_new();
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
dir_server_t *, ds,
{
char *hex = tor_malloc(HEX_DIGEST_LEN+1);
base16_encode(hex, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
smartlist_add(which, hex);
});
} else {
/* XXXX Can we even end up here? -- weasel*/
source = NS_FROM_DIR_BY_FP;
log_warn(LD_BUG, "We received a networkstatus but we didn't ask "
"for it by fp, nor did we ask for all.");
}
cp = body;
while (*cp) {
char *next = strstr(cp, "\nnetwork-status-version");
if (next)
next[1] = '\0';
/* learn from it, and then remove it from 'which' */
if (router_set_networkstatus_v2(cp, now, source, which)<0)
break;
if (next) {
next[1] = 'n';
cp = next+1;
} else
break;
}
/* launches router downloads as needed */
routers_update_all_from_networkstatus(now, 2);
directory_info_has_arrived(now, 0);
if (which) {
if (smartlist_len(which)) {
dir_networkstatus_download_failed(which, status_code);
}
SMARTLIST_FOREACH(which, char *, s, tor_free(s));
smartlist_free(which);
}
}
if (conn->base_.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
int r;
const char *flavname = conn->requested_resource;
@ -2563,7 +2431,6 @@ note_client_request(int purpose, int compressed, size_t bytes)
char *key;
const char *kind = NULL;
switch (purpose) {
case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS: kind = "dl/status"; break;
case DIR_PURPOSE_FETCH_CONSENSUS: kind = "dl/consensus"; break;
case DIR_PURPOSE_FETCH_CERTIFICATE: kind = "dl/cert"; break;
case DIR_PURPOSE_FETCH_STATUS_VOTE: kind = "dl/vote"; break;
@ -2857,40 +2724,13 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
goto done;
}
if (!strcmpstart(url,"/tor/status/")
|| !strcmpstart(url, "/tor/status-vote/current/consensus")) {
/* v2 or v3 network status fetch. */
if (!strcmpstart(url, "/tor/status-vote/current/consensus")) {
/* v3 network status fetch. */
smartlist_t *dir_fps = smartlist_new();
int is_v3 = !strcmpstart(url, "/tor/status-vote");
const char *request_type = NULL;
const char *key = url + strlen("/tor/status/");
long lifetime = NETWORKSTATUS_CACHE_LIFETIME;
if (options->DisableV2DirectoryInfo_ && !is_v3) {
static ratelim_t reject_v2_ratelim = RATELIM_INIT(1800);
char *m;
write_http_status_line(conn, 404, "Not found");
smartlist_free(dir_fps);
geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
if ((m = rate_limit_log(&reject_v2_ratelim, approx_time()))) {
log_notice(LD_DIR, "Rejected a v2 networkstatus request.%s", m);
tor_free(m);
}
goto done;
}
if (!is_v3) {
dirserv_get_networkstatus_v2_fingerprints(dir_fps, key);
if (!strcmpstart(key, "fp/"))
request_type = compressed?"/tor/status/fp.z":"/tor/status/fp";
else if (!strcmpstart(key, "authority"))
request_type = compressed?"/tor/status/authority.z":
"/tor/status/authority";
else if (!strcmpstart(key, "all"))
request_type = compressed?"/tor/status/all.z":"/tor/status/all";
else
request_type = "/tor/status/?";
} else {
if (1) {
networkstatus_t *v;
time_t now = time(NULL);
const char *want_fps = NULL;
@ -2943,8 +2783,7 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
if (!smartlist_len(dir_fps)) { /* we failed to create/cache cp */
write_http_status_line(conn, 503, "Network status object unavailable");
smartlist_free(dir_fps);
if (is_v3)
geoip_note_ns_response(GEOIP_REJECT_UNAVAILABLE);
geoip_note_ns_response(GEOIP_REJECT_UNAVAILABLE);
goto done;
}
@ -2952,15 +2791,13 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
write_http_status_line(conn, 404, "Not found");
SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
smartlist_free(dir_fps);
if (is_v3)
geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
goto done;
} else if (!smartlist_len(dir_fps)) {
write_http_status_line(conn, 304, "Not modified");
SMARTLIST_FOREACH(dir_fps, char *, cp, tor_free(cp));
smartlist_free(dir_fps);
if (is_v3)
geoip_note_ns_response(GEOIP_REJECT_NOT_MODIFIED);
geoip_note_ns_response(GEOIP_REJECT_NOT_MODIFIED);
goto done;
}
@ -2972,12 +2809,12 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
write_http_status_line(conn, 503, "Directory busy, try again later");
SMARTLIST_FOREACH(dir_fps, char *, fp, tor_free(fp));
smartlist_free(dir_fps);
if (is_v3)
geoip_note_ns_response(GEOIP_REJECT_BUSY);
geoip_note_ns_response(GEOIP_REJECT_BUSY);
goto done;
}
if (is_v3) {
if (1) {
struct in_addr in;
tor_addr_t addr;
if (tor_inet_aton((TO_CONN(conn))->address, &in)) {
@ -3718,29 +3555,6 @@ connection_dir_finished_connecting(dir_connection_t *conn)
return 0;
}
/** Called when one or more networkstatus fetches have failed (with uppercase
* fingerprints listed in <b>failed</b>). Mark those fingerprints as having
* failed once, unless they failed with status code 503. */
static void
dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
{
if (status_code == 503)
return;
SMARTLIST_FOREACH_BEGIN(failed, const char *, fp) {
char digest[DIGEST_LEN];
dir_server_t *dir;
if (base16_decode(digest, DIGEST_LEN, fp, strlen(fp))<0) {
log_warn(LD_BUG, "Called with bad fingerprint in list: %s",
escaped(fp));
continue;
}
dir = router_get_fallback_dirserver_by_digest(digest);
if (dir)
download_status_failed(&dir->v2_ns_dl_status, status_code);
} SMARTLIST_FOREACH_END(fp);
}
/** Decide which download schedule we want to use based on descriptor type
* in <b>dls</b> and whether we are acting as directory <b>server</b>, and
* then return a list of int pointers defining download delays in seconds.

View File

@ -1272,14 +1272,6 @@ directory_fetches_dir_info_later(const or_options_t *options)
return options->UseBridges != 0;
}
/** Return 1 if we want to cache v2 dir info (each status file).
*/
int
directory_caches_v2_dir_info(const or_options_t *options)
{
return options->DirPort_set;
}
/** Return true iff we want to fetch and keep certificates for authorities
* that we don't acknowledge as aurthorities ourself.
*/
@ -1348,10 +1340,6 @@ static cached_dir_t *cached_directory = NULL;
* if requested. */
static cached_dir_t cached_runningrouters;
/** Used for other dirservers' v2 network statuses. Map from hexdigest to
* cached_dir_t. */
static digestmap_t *cached_v2_networkstatus = NULL;
/** Map from flavor name to the cached_dir_t for the v3 consensuses that we're
* currently serving. */
static strmap_t *cached_consensuses = NULL;
@ -1452,70 +1440,6 @@ dirserv_set_cached_directory(const char *directory, time_t published)
cached_directory = new_cached_dir(tor_strdup(directory), published);
}
/** If <b>networkstatus</b> is non-NULL, we've just received a v2
* network-status for an authoritative directory with identity digest
* <b>identity</b> published at <b>published</b> -- store it so we can
* serve it to others.
*
* If <b>networkstatus</b> is NULL, remove the entry with the given
* identity fingerprint from the v2 cache.
*/
void
dirserv_set_cached_networkstatus_v2(const char *networkstatus,
const char *identity,
time_t published)
{
cached_dir_t *d, *old_d;
if (!cached_v2_networkstatus)
cached_v2_networkstatus = digestmap_new();
old_d = digestmap_get(cached_v2_networkstatus, identity);
if (!old_d && !networkstatus)
return;
if (networkstatus) {
if (!old_d || published > old_d->published) {
d = new_cached_dir(tor_strdup(networkstatus), published);
digestmap_set(cached_v2_networkstatus, identity, d);
if (old_d)
cached_dir_decref(old_d);
}
} else {
if (old_d) {
digestmap_remove(cached_v2_networkstatus, identity);
cached_dir_decref(old_d);
}
}
/* Now purge old entries. */
if (digestmap_size(cached_v2_networkstatus) >
get_n_authorities(V2_DIRINFO) + MAX_UNTRUSTED_NETWORKSTATUSES) {
/* We need to remove the oldest untrusted networkstatus. */
const char *oldest = NULL;
time_t oldest_published = TIME_MAX;
digestmap_iter_t *iter;
for (iter = digestmap_iter_init(cached_v2_networkstatus);
!digestmap_iter_done(iter);
iter = digestmap_iter_next(cached_v2_networkstatus, iter)) {
const char *ident;
void *val;
digestmap_iter_get(iter, &ident, &val);
d = val;
if (d->published < oldest_published &&
!router_digest_is_trusted_dir(ident)) {
oldest = ident;
oldest_published = d->published;
}
}
tor_assert(oldest);
d = digestmap_remove(cached_v2_networkstatus, oldest);
if (d)
cached_dir_decref(d);
}
}
/** Replace the v3 consensus networkstatus of type <b>flavor_name</b> that
* we're serving with <b>networkstatus</b>, published at <b>published</b>. No
* validation is performed. */
@ -1538,30 +1462,6 @@ dirserv_set_cached_consensus_networkstatus(const char *networkstatus,
cached_dir_decref(old_networkstatus);
}
/** Remove any v2 networkstatus from the directory cache that was published
* before <b>cutoff</b>. */
void
dirserv_clear_old_networkstatuses(time_t cutoff)
{
if (!cached_v2_networkstatus)
return;
DIGESTMAP_FOREACH_MODIFY(cached_v2_networkstatus, id, cached_dir_t *, dir) {
if (dir->published < cutoff) {
char *fname;
fname = networkstatus_get_cache_filename(id);
if (file_status(fname) == FN_FILE) {
log_info(LD_DIR, "Removing too-old untrusted networkstatus in %s",
fname);
unlink(fname);
}
tor_free(fname);
cached_dir_decref(dir);
MAP_DEL_CURRENT(id);
}
} DIGESTMAP_FOREACH_END
}
/** Remove any v1 info from the directory cache that was published
* too long ago. */
void
@ -1590,8 +1490,7 @@ dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
dirinfo_type_t auth_type)
{
const or_options_t *options = get_options();
int authority = (auth_type == V1_DIRINFO && authdir_mode_v1(options)) ||
(auth_type == V2_DIRINFO && authdir_mode_v2(options));
int authority = (auth_type == V1_DIRINFO && authdir_mode_v1(options));
if (!authority || authdir_mode_bridge(options)) {
return cache_src;
@ -1728,19 +1627,6 @@ dirserv_get_consensus(const char *flavor_name)
return strmap_get(cached_consensuses, flavor_name);
}
/** For authoritative directories: the current (v2) network status. */
static cached_dir_t *the_v2_networkstatus = NULL;
/** Return true iff our opinion of the routers has been stale for long
* enough that we should generate a new v2 network status doc. */
static int
should_generate_v2_networkstatus(void)
{
return authdir_mode_v2(get_options()) &&
the_v2_networkstatus_is_dirty &&
the_v2_networkstatus_is_dirty + DIR_REGEN_SLACK_TIME < time(NULL);
}
/** If a router's uptime is at least this value, then it is always
* considered stable, regardless of the rest of the network. This
* way we resist attacks where an attacker doubles the size of the
@ -2411,7 +2297,7 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version,
rs->is_flagged_running?" Running":"",
rs->is_stable?" Stable":"",
rs->is_unnamed?" Unnamed":"",
rs->is_v2_dir?" V2Dir":"",
(rs->dir_port!=0)?" V2Dir":"",
rs->is_valid?" Valid":"");
/* length of "opt v \n" */
@ -2735,7 +2621,6 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
rs->is_bad_exit = listbadexits && node->is_bad_exit;
node->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, node, now);
rs->is_hs_dir = vote_on_hsdirs && node->is_hs_dir;
rs->is_v2_dir = ri->dir_port != 0;
if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME))
rs->is_named = rs->is_unnamed = 0;
@ -2766,7 +2651,7 @@ static void
clear_status_flags_on_sybil(routerstatus_t *rs)
{
rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
rs->is_flagged_running = rs->is_named = rs->is_valid = rs->is_v2_dir =
rs->is_flagged_running = rs->is_named = rs->is_valid =
rs->is_hs_dir = rs->is_possible_guard = rs->is_bad_exit =
rs->is_bad_directory = 0;
/* FFFF we might want some mechanism to check later on if we
@ -3190,270 +3075,6 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
return v3_out;
}
/** For v2 authoritative directories only: Replace the contents of
* <b>the_v2_networkstatus</b> with a newly generated network status
* object. */
STATIC cached_dir_t *
generate_v2_networkstatus_opinion(void)
{
cached_dir_t *r = NULL;
size_t identity_pkey_len;
char *status = NULL, *client_versions = NULL, *server_versions = NULL,
*identity_pkey = NULL, *hostname = NULL;
const or_options_t *options = get_options();
char fingerprint[FINGERPRINT_LEN+1];
char published[ISO_TIME_LEN+1];
char digest[DIGEST_LEN];
uint32_t addr;
crypto_pk_t *private_key;
routerlist_t *rl = router_get_routerlist();
time_t now = time(NULL);
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
int naming = options->NamingAuthoritativeDir;
int versioning = options->VersioningAuthoritativeDir;
int listbaddirs = options->AuthDirListBadDirs;
int listbadexits = options->AuthDirListBadExits;
int vote_on_hsdirs = options->VoteOnHidServDirectoriesV2;
const char *contact;
char *version_lines = NULL;
smartlist_t *routers = NULL;
digestmap_t *omit_as_sybil = NULL;
smartlist_t *chunks = NULL;
private_key = get_server_identity_key();
if (resolve_my_address(LOG_WARN, options, &addr, NULL, &hostname)<0) {
log_warn(LD_NET, "Couldn't resolve my hostname");
goto done;
}
if (!hostname)
hostname = tor_dup_ip(addr);
format_iso_time(published, now);
client_versions = format_versions_list(options->RecommendedClientVersions);
server_versions = format_versions_list(options->RecommendedServerVersions);
if (crypto_pk_write_public_key_to_string(private_key, &identity_pkey,
&identity_pkey_len)<0) {
log_warn(LD_BUG,"Writing public key to string failed.");
goto done;
}
if (crypto_pk_get_fingerprint(private_key, fingerprint, 0)<0) {
log_err(LD_BUG, "Error computing fingerprint");
goto done;
}
contact = options->ContactInfo;
if (!contact)
contact = "(none)";
if (versioning) {
tor_asprintf(&version_lines,
"client-versions %s\nserver-versions %s\n",
client_versions, server_versions);
} else {
version_lines = tor_strdup("");
}
chunks = smartlist_new();
smartlist_add_asprintf(chunks,
"network-status-version 2\n"
"dir-source %s %s %d\n"
"fingerprint %s\n"
"contact %s\n"
"published %s\n"
"dir-options%s%s%s%s\n"
"%s" /* client version line, server version line. */
"dir-signing-key\n%s",
hostname, fmt_addr32(addr),
(int)router_get_advertised_dir_port(options, 0),
fingerprint,
contact,
published,
naming ? " Names" : "",
listbaddirs ? " BadDirectories" : "",
listbadexits ? " BadExits" : "",
versioning ? " Versions" : "",
version_lines,
identity_pkey);
/* precompute this part, since we need it to decide what "stable"
* means. */
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
dirserv_set_router_is_running(ri, now);
});
routers = smartlist_new();
smartlist_add_all(routers, rl->routers);
routers_sort_by_identity(routers);
omit_as_sybil = get_possible_sybil_list(routers);
dirserv_compute_performance_thresholds(rl, omit_as_sybil);
SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
if (ri->cache_info.published_on >= cutoff) {
routerstatus_t rs;
char *version = version_from_platform(ri->platform);
node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
if (!node) {
tor_free(version);
continue;
}
set_routerstatus_from_routerinfo(&rs, node, ri, now,
naming, listbadexits, listbaddirs,
vote_on_hsdirs);
if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
clear_status_flags_on_sybil(&rs);
{
char *rsf = routerstatus_format_entry(&rs, version, NS_V2, NULL);
if (rsf)
smartlist_add(chunks, rsf);
}
tor_free(version);
}
} SMARTLIST_FOREACH_END(ri);
smartlist_add_asprintf(chunks, "directory-signature %s\n",
options->Nickname);
crypto_digest_smartlist(digest, DIGEST_LEN, chunks, "", DIGEST_SHA1);
note_crypto_pk_op(SIGN_DIR);
{
char *sig;
if (!(sig = router_get_dirobj_signature(digest,DIGEST_LEN,
private_key))) {
log_warn(LD_BUG, "Unable to sign router status.");
goto done;
}
smartlist_add(chunks, sig);
}
status = smartlist_join_strings(chunks, "", 0, NULL);
{
networkstatus_v2_t *ns;
if (!(ns = networkstatus_v2_parse_from_string(status))) {
log_err(LD_BUG,"Generated a networkstatus we couldn't parse.");
goto done;
}
networkstatus_v2_free(ns);
}
{
cached_dir_t **ns_ptr = &the_v2_networkstatus;
if (*ns_ptr)
cached_dir_decref(*ns_ptr);
*ns_ptr = new_cached_dir(status, now);
status = NULL; /* So it doesn't get double-freed. */
the_v2_networkstatus_is_dirty = 0;
router_set_networkstatus_v2((*ns_ptr)->dir, now, NS_GENERATED, NULL);
r = *ns_ptr;
}
done:
if (chunks) {
SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
smartlist_free(chunks);
}
tor_free(client_versions);
tor_free(server_versions);
tor_free(version_lines);
tor_free(status);
tor_free(hostname);
tor_free(identity_pkey);
smartlist_free(routers);
digestmap_free(omit_as_sybil, NULL);
return r;
}
/** Given the portion of a networkstatus request URL after "tor/status/" in
* <b>key</b>, append to <b>result</b> the digests of the identity keys of the
* networkstatus objects that the client has requested. */
void
dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result,
const char *key)
{
tor_assert(result);
if (!cached_v2_networkstatus)
cached_v2_networkstatus = digestmap_new();
if (should_generate_v2_networkstatus())
generate_v2_networkstatus_opinion();
if (!strcmp(key,"authority")) {
if (authdir_mode_v2(get_options())) {
const routerinfo_t *me = router_get_my_routerinfo();
if (me)
smartlist_add(result,
tor_memdup(me->cache_info.identity_digest, DIGEST_LEN));
}
} else if (!strcmp(key, "all")) {
if (digestmap_size(cached_v2_networkstatus)) {
digestmap_iter_t *iter;
iter = digestmap_iter_init(cached_v2_networkstatus);
while (!digestmap_iter_done(iter)) {
const char *ident;
void *val;
digestmap_iter_get(iter, &ident, &val);
smartlist_add(result, tor_memdup(ident, DIGEST_LEN));
iter = digestmap_iter_next(cached_v2_networkstatus, iter);
}
} else {
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
dir_server_t *, ds,
if (ds->type & V2_DIRINFO)
smartlist_add(result, tor_memdup(ds->digest, DIGEST_LEN)));
}
smartlist_sort_digests(result);
if (smartlist_len(result) == 0)
log_info(LD_DIRSERV,
"Client requested 'all' network status objects; we have none.");
} else if (!strcmpstart(key, "fp/")) {
dir_split_resource_into_fingerprints(key+3, result, NULL,
DSR_HEX|DSR_SORT_UNIQ);
}
}
/** Look for a network status object as specified by <b>key</b>, which should
* be either "authority" (to find a network status generated by us), a hex
* identity digest (to find a network status generated by given directory), or
* "all" (to return all the v2 network status objects we have).
*/
void
dirserv_get_networkstatus_v2(smartlist_t *result,
const char *key)
{
cached_dir_t *cached;
smartlist_t *fingerprints = smartlist_new();
tor_assert(result);
if (!cached_v2_networkstatus)
cached_v2_networkstatus = digestmap_new();
dirserv_get_networkstatus_v2_fingerprints(fingerprints, key);
SMARTLIST_FOREACH_BEGIN(fingerprints, const char *, fp) {
if (router_digest_is_me(fp) && should_generate_v2_networkstatus())
generate_v2_networkstatus_opinion();
cached = digestmap_get(cached_v2_networkstatus, fp);
if (cached) {
smartlist_add(result, cached);
} else {
char hexbuf[HEX_DIGEST_LEN+1];
base16_encode(hexbuf, sizeof(hexbuf), fp, DIGEST_LEN);
log_info(LD_DIRSERV, "Don't know about any network status with "
"fingerprint '%s'", hexbuf);
}
} SMARTLIST_FOREACH_END(fp);
SMARTLIST_FOREACH(fingerprints, char *, cp, tor_free(cp));
smartlist_free(fingerprints);
}
/** As dirserv_get_routerdescs(), but instead of getting signed_descriptor_t
* pointers, adds copies of digests to fps_out, and doesn't use the
* /tor/server/ prefix. For a /d/ request, adds descriptor digests; for other
@ -3753,15 +3374,12 @@ static cached_dir_t *
lookup_cached_dir_by_fp(const char *fp)
{
cached_dir_t *d = NULL;
if (tor_digest_is_zero(fp) && cached_consensuses)
if (tor_digest_is_zero(fp) && cached_consensuses) {
d = strmap_get(cached_consensuses, "ns");
else if (memchr(fp, '\0', DIGEST_LEN) && cached_consensuses &&
} else if (memchr(fp, '\0', DIGEST_LEN) && cached_consensuses &&
(d = strmap_get(cached_consensuses, fp))) {
/* this here interface is a nasty hack XXXX024 */;
} else if (router_digest_is_me(fp) && the_v2_networkstatus)
d = the_v2_networkstatus;
else if (cached_v2_networkstatus)
d = digestmap_get(cached_v2_networkstatus, fp);
}
return d;
}
@ -4156,12 +3774,9 @@ dirserv_free_all(void)
cached_dir_decref(the_directory);
clear_cached_dir(&the_runningrouters);
cached_dir_decref(the_v2_networkstatus);
cached_dir_decref(cached_directory);
clear_cached_dir(&cached_runningrouters);
digestmap_free(cached_v2_networkstatus, free_cached_dir_);
cached_v2_networkstatus = NULL;
strmap_free(cached_consensuses, free_cached_dir_);
cached_consensuses = NULL;

View File

@ -56,7 +56,6 @@ void dirserv_compute_bridge_flag_thresholds(routerlist_t *rl);
int directory_fetches_from_authorities(const or_options_t *options);
int directory_fetches_dir_info_early(const or_options_t *options);
int directory_fetches_dir_info_later(const or_options_t *options);
int directory_caches_v2_dir_info(const or_options_t *options);
int directory_caches_unknown_auth_certs(const or_options_t *options);
int directory_caches_dir_info(const or_options_t *options);
int directory_permits_begindir_requests(const or_options_t *options);
@ -68,18 +67,12 @@ void directory_set_dirty(void);
cached_dir_t *dirserv_get_directory(void);
cached_dir_t *dirserv_get_runningrouters(void);
cached_dir_t *dirserv_get_consensus(const char *flavor_name);
void dirserv_set_cached_networkstatus_v2(const char *directory,
const char *identity,
time_t published);
void dirserv_set_cached_consensus_networkstatus(const char *consensus,
const char *flavor_name,
const digests_t *digests,
time_t published);
void dirserv_clear_old_networkstatuses(time_t cutoff);
void dirserv_clear_old_v1_info(time_t now);
void dirserv_get_networkstatus_v2(smartlist_t *result, const char *key);
void dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result,
const char *key);
int dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
const char **msg,
int for_unencrypted_conn,
@ -136,7 +129,6 @@ STATIC int dirserv_query_measured_bw_cache_kb(const char *node_id,
long *bw_out,
time_t *as_of_out);
STATIC int dirserv_has_measured_bw(const char *node_id);
STATIC cached_dir_t *generate_v2_networkstatus_opinion(void);
#endif
int dirserv_read_measured_bandwidths(const char *from_file,

View File

@ -1458,8 +1458,6 @@ run_scheduled_events(time_t now)
/* If any networkstatus documents are no longer recent, we need to
* update all the descriptors' running status. */
/* purge obsolete entries */
networkstatus_v2_list_clean(now);
/* Remove dead routers. */
routerlist_remove_old_routers();
}
@ -1948,9 +1946,6 @@ do_main_loop(void)
log_warn(LD_DIR,
"Couldn't load all cached v3 certificates. Starting anyway.");
}
if (router_reload_v2_networkstatus()) {
return -1;
}
if (router_reload_consensus_networkstatus()) {
return -1;
}

View File

@ -32,18 +32,6 @@
#include "routerlist.h"
#include "routerparse.h"
/* For tracking v2 networkstatus documents. Only caches do this now. */
/** Map from descriptor digest of routers listed in the v2 networkstatus
* documents to download_status_t* */
static digestmap_t *v2_download_status_map = NULL;
/** Global list of all of the current v2 network_status documents that we know
* about. This list is kept sorted by published_on. */
static smartlist_t *networkstatus_v2_list = NULL;
/** True iff any member of networkstatus_v2_list has changed since the last
* time we called download_status_map_update_from_v2_networkstatus() */
static int networkstatus_v2_list_has_changed = 0;
/** Map from lowercase nickname to identity digest of named server, if any. */
static strmap_t *named_server_map = NULL;
/** Map from lowercase nickname to (void*)1 for all names that are listed
@ -88,11 +76,6 @@ typedef struct consensus_waiting_for_certs_t {
static consensus_waiting_for_certs_t
consensus_waiting_for_certs[N_CONSENSUS_FLAVORS];
/** The last time we tried to download a networkstatus, or 0 for "never". We
* use this to rate-limit download attempts for directory caches (including
* mirrors). Clients don't use this now. */
static time_t last_networkstatus_download_attempted = 0;
/** A time before which we shouldn't try to replace the current consensus:
* this will be at some point after the next consensus becomes valid, but
* before the current consensus becomes invalid. */
@ -107,7 +90,6 @@ static int have_warned_about_old_version = 0;
* listed by the authorities. */
static int have_warned_about_new_version = 0;
static void download_status_map_update_from_v2_networkstatus(void);
static void routerstatus_list_update_named_server_map(void);
/** Forget that we've warned about anything networkstatus-related, so we will
@ -131,86 +113,9 @@ void
networkstatus_reset_download_failures(void)
{
int i;
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
SMARTLIST_FOREACH_BEGIN(networkstatus_v2_list, networkstatus_v2_t *, ns) {
SMARTLIST_FOREACH_BEGIN(ns->entries, routerstatus_t *, rs) {
if (!router_get_by_descriptor_digest(rs->descriptor_digest))
rs->need_to_mirror = 1;
} SMARTLIST_FOREACH_END(rs);
} SMARTLIST_FOREACH_END(ns);
for (i=0; i < N_CONSENSUS_FLAVORS; ++i)
download_status_reset(&consensus_dl_status[i]);
if (v2_download_status_map) {
digestmap_iter_t *iter;
digestmap_t *map = v2_download_status_map;
const char *key;
void *val;
download_status_t *dls;
for (iter = digestmap_iter_init(map); !digestmap_iter_done(iter);
iter = digestmap_iter_next(map, iter) ) {
digestmap_iter_get(iter, &key, &val);
dls = val;
download_status_reset(dls);
}
}
}
/** Repopulate our list of network_status_t objects from the list cached on
* disk. Return 0 on success, -1 on failure. */
int
router_reload_v2_networkstatus(void)
{
smartlist_t *entries;
struct stat st;
char *s;
char *filename = get_datadir_fname("cached-status");
int maybe_delete = !directory_caches_v2_dir_info(get_options());
time_t now = time(NULL);
if (!networkstatus_v2_list)
networkstatus_v2_list = smartlist_new();
entries = tor_listdir(filename);
if (!entries) { /* dir doesn't exist */
tor_free(filename);
return 0;
} else if (!smartlist_len(entries) && maybe_delete) {
rmdir(filename);
tor_free(filename);
smartlist_free(entries);
return 0;
}
tor_free(filename);
SMARTLIST_FOREACH_BEGIN(entries, const char *, fn) {
char buf[DIGEST_LEN];
if (maybe_delete) {
filename = get_datadir_fname2("cached-status", fn);
remove_file_if_very_old(filename, now);
tor_free(filename);
continue;
}
if (strlen(fn) != HEX_DIGEST_LEN ||
base16_decode(buf, sizeof(buf), fn, strlen(fn))) {
log_info(LD_DIR,
"Skipping cached-status file with unexpected name \"%s\"",fn);
continue;
}
filename = get_datadir_fname2("cached-status", fn);
s = read_file_to_str(filename, 0, &st);
if (s) {
if (router_set_networkstatus_v2(s, st.st_mtime, NS_FROM_CACHE,
NULL)<0) {
log_warn(LD_FS, "Couldn't load networkstatus from \"%s\"",filename);
}
tor_free(s);
}
tor_free(filename);
} SMARTLIST_FOREACH_END(fn);
SMARTLIST_FOREACH(entries, char *, fn, tor_free(fn));
smartlist_free(entries);
networkstatus_v2_list_clean(time(NULL));
routers_update_all_from_networkstatus(time(NULL), 2);
return 0;
}
/** Read every cached v3 consensus networkstatus from the disk. */
@ -303,26 +208,6 @@ routerstatus_free(routerstatus_t *rs)
tor_free(rs);
}
/** Free all storage held by the networkstatus object <b>ns</b>. */
void
networkstatus_v2_free(networkstatus_v2_t *ns)
{
if (!ns)
return;
tor_free(ns->source_address);
tor_free(ns->contact);
if (ns->signing_key)
crypto_pk_free(ns->signing_key);
tor_free(ns->client_versions);
tor_free(ns->server_versions);
if (ns->entries) {
SMARTLIST_FOREACH(ns->entries, routerstatus_t *, rs,
routerstatus_free(rs));
smartlist_free(ns->entries);
}
tor_free(ns);
}
/** Free all storage held in <b>sig</b> */
void
document_signature_free(document_signature_t *sig)
@ -647,286 +532,10 @@ networkstatus_get_cache_filename(const char *identity_digest)
return get_datadir_fname2("cached-status", fp);
}
/** Helper for smartlist_sort: Compare two networkstatus objects by
* publication date. */
static int
compare_networkstatus_v2_published_on_(const void **_a, const void **_b)
{
const networkstatus_v2_t *a = *_a, *b = *_b;
if (a->published_on < b->published_on)
return -1;
else if (a->published_on > b->published_on)
return 1;
else
return 0;
}
/** Add the parsed v2 networkstatus in <b>ns</b> (with original document in
* <b>s</b>) to the disk cache (and the in-memory directory server cache) as
* appropriate. */
static int
add_networkstatus_to_cache(const char *s,
v2_networkstatus_source_t source,
networkstatus_v2_t *ns)
{
if (source != NS_FROM_CACHE) {
char *fn = networkstatus_get_cache_filename(ns->identity_digest);
if (write_str_to_file(fn, s, 0)<0) {
log_notice(LD_FS, "Couldn't write cached network status to \"%s\"", fn);
}
tor_free(fn);
}
if (directory_caches_v2_dir_info(get_options()))
dirserv_set_cached_networkstatus_v2(s,
ns->identity_digest,
ns->published_on);
return 0;
}
/** How far in the future do we allow a network-status to get before removing
* it? (seconds) */
#define NETWORKSTATUS_ALLOW_SKEW (24*60*60)
/** Given a string <b>s</b> containing a network status that we received at
* <b>arrived_at</b> from <b>source</b>, try to parse it, see if we want to
* store it, and put it into our cache as necessary.
*
* If <b>source</b> is NS_FROM_DIR or NS_FROM_CACHE, do not replace our
* own networkstatus_t (if we're an authoritative directory server).
*
* If <b>source</b> is NS_FROM_CACHE, do not write our networkstatus_t to the
* cache.
*
* If <b>requested_fingerprints</b> is provided, it must contain a list of
* uppercased identity fingerprints. Do not update any networkstatus whose
* fingerprint is not on the list; after updating a networkstatus, remove its
* fingerprint from the list.
*
* Return 0 on success, -1 on failure.
*
* Callers should make sure that routers_update_all_from_networkstatus() is
* invoked after this function succeeds.
*/
int
router_set_networkstatus_v2(const char *s, time_t arrived_at,
v2_networkstatus_source_t source,
smartlist_t *requested_fingerprints)
{
networkstatus_v2_t *ns;
int i, found;
time_t now;
int skewed = 0;
dir_server_t *trusted_dir = NULL;
const char *source_desc = NULL;
char fp[HEX_DIGEST_LEN+1];
char published[ISO_TIME_LEN+1];
if (!directory_caches_v2_dir_info(get_options()))
return 0; /* Don't bother storing it. */
ns = networkstatus_v2_parse_from_string(s);
if (!ns) {
log_warn(LD_DIR, "Couldn't parse network status.");
return -1;
}
base16_encode(fp, HEX_DIGEST_LEN+1, ns->identity_digest, DIGEST_LEN);
if (!(trusted_dir =
router_get_trusteddirserver_by_digest(ns->identity_digest)) ||
!(trusted_dir->type & V2_DIRINFO)) {
log_info(LD_DIR, "Network status was signed, but not by an authoritative "
"directory we recognize.");
source_desc = fp;
} else {
source_desc = trusted_dir->description;
}
now = time(NULL);
if (arrived_at > now)
arrived_at = now;
ns->received_on = arrived_at;
format_iso_time(published, ns->published_on);
if (ns->published_on > now + NETWORKSTATUS_ALLOW_SKEW) {
char dbuf[64];
long delta = now - ns->published_on;
format_time_interval(dbuf, sizeof(dbuf), delta);
log_warn(LD_GENERAL, "Network status from %s was published %s in the "
"future (%s UTC). Check your time and date settings! "
"Not caching.",
source_desc, dbuf, published);
control_event_general_status(LOG_WARN,
"CLOCK_SKEW MIN_SKEW=%ld SOURCE=NETWORKSTATUS:%s:%d",
delta, ns->source_address, ns->source_dirport);
skewed = 1;
}
if (!networkstatus_v2_list)
networkstatus_v2_list = smartlist_new();
if ( (source == NS_FROM_DIR_BY_FP || source == NS_FROM_DIR_ALL) &&
router_digest_is_me(ns->identity_digest)) {
/* Don't replace our own networkstatus when we get it from somebody else.*/
networkstatus_v2_free(ns);
return 0;
}
if (requested_fingerprints) {
if (smartlist_contains_string(requested_fingerprints, fp)) {
smartlist_string_remove(requested_fingerprints, fp);
} else {
if (source != NS_FROM_DIR_ALL) {
char *requested =
smartlist_join_strings(requested_fingerprints," ",0,NULL);
log_warn(LD_DIR,
"We received a network status with a fingerprint (%s) that we "
"never requested. (We asked for: %s.) Dropping.",
fp, requested);
tor_free(requested);
return 0;
}
}
}
if (!trusted_dir) {
if (!skewed) {
/* We got a non-trusted networkstatus, and we're a directory cache.
* This means that we asked an authority, and it told us about another
* authority we didn't recognize. */
log_info(LD_DIR,
"We do not recognize authority (%s) but we are willing "
"to cache it.", fp);
add_networkstatus_to_cache(s, source, ns);
networkstatus_v2_free(ns);
}
return 0;
}
found = 0;
for (i=0; i < smartlist_len(networkstatus_v2_list); ++i) {
networkstatus_v2_t *old_ns = smartlist_get(networkstatus_v2_list, i);
if (tor_memeq(old_ns->identity_digest, ns->identity_digest, DIGEST_LEN)) {
if (tor_memeq(old_ns->networkstatus_digest,
ns->networkstatus_digest, DIGEST_LEN)) {
/* Same one we had before. */
networkstatus_v2_free(ns);
tor_assert(trusted_dir);
log_info(LD_DIR,
"Not replacing network-status from %s (published %s); "
"we already have it.",
trusted_dir->description, published);
if (old_ns->received_on < arrived_at) {
if (source != NS_FROM_CACHE) {
char *fn;
fn = networkstatus_get_cache_filename(old_ns->identity_digest);
/* We use mtime to tell when it arrived, so update that. */
touch_file(fn);
tor_free(fn);
}
old_ns->received_on = arrived_at;
}
download_status_failed(&trusted_dir->v2_ns_dl_status, 0);
return 0;
} else if (old_ns->published_on >= ns->published_on) {
char old_published[ISO_TIME_LEN+1];
format_iso_time(old_published, old_ns->published_on);
tor_assert(trusted_dir);
log_info(LD_DIR,
"Not replacing network-status from %s (published %s);"
" we have a newer one (published %s) for this authority.",
trusted_dir->description, published,
old_published);
networkstatus_v2_free(ns);
download_status_failed(&trusted_dir->v2_ns_dl_status, 0);
return 0;
} else {
networkstatus_v2_free(old_ns);
smartlist_set(networkstatus_v2_list, i, ns);
found = 1;
break;
}
}
}
if (source != NS_FROM_CACHE && trusted_dir) {
download_status_reset(&trusted_dir->v2_ns_dl_status);
}
if (!found)
smartlist_add(networkstatus_v2_list, ns);
/** Retain any routerinfo mentioned in a V2 networkstatus for at least this
* long. */
#define V2_NETWORKSTATUS_ROUTER_LIFETIME (3*60*60)
{
time_t live_until = ns->published_on + V2_NETWORKSTATUS_ROUTER_LIFETIME;
SMARTLIST_FOREACH_BEGIN(ns->entries, routerstatus_t *, rs) {
signed_descriptor_t *sd =
router_get_by_descriptor_digest(rs->descriptor_digest);
if (sd) {
if (sd->last_listed_as_valid_until < live_until)
sd->last_listed_as_valid_until = live_until;
} else {
rs->need_to_mirror = 1;
}
} SMARTLIST_FOREACH_END(rs);
}
log_info(LD_DIR, "Setting networkstatus %s %s (published %s)",
source == NS_FROM_CACHE?"cached from":
((source == NS_FROM_DIR_BY_FP || source == NS_FROM_DIR_ALL) ?
"downloaded from":"generated for"),
trusted_dir->description, published);
networkstatus_v2_list_has_changed = 1;
smartlist_sort(networkstatus_v2_list,
compare_networkstatus_v2_published_on_);
if (!skewed)
add_networkstatus_to_cache(s, source, ns);
return 0;
}
/** Remove all very-old network_status_t objects from memory and from the
* disk cache. */
void
networkstatus_v2_list_clean(time_t now)
{
int i;
if (!networkstatus_v2_list)
return;
for (i = 0; i < smartlist_len(networkstatus_v2_list); ++i) {
networkstatus_v2_t *ns = smartlist_get(networkstatus_v2_list, i);
char *fname = NULL;
if (ns->published_on + MAX_NETWORKSTATUS_AGE > now)
continue;
/* Okay, this one is too old. Remove it from the list, and delete it
* from the cache. */
smartlist_del(networkstatus_v2_list, i--);
fname = networkstatus_get_cache_filename(ns->identity_digest);
if (file_status(fname) == FN_FILE) {
log_info(LD_DIR, "Removing too-old networkstatus in %s", fname);
unlink(fname);
}
tor_free(fname);
if (directory_caches_v2_dir_info(get_options())) {
dirserv_set_cached_networkstatus_v2(NULL, ns->identity_digest, 0);
}
networkstatus_v2_free(ns);
}
/* And now go through the directory cache for any cached untrusted
* networkstatuses and other network info. */
dirserv_clear_old_networkstatuses(now - MAX_NETWORKSTATUS_AGE);
dirserv_clear_old_v1_info(now);
}
/** Helper for bsearching a list of routerstatus_t pointers: compare a
* digest in the key to the identity digest of a routerstatus_t. */
int
@ -948,22 +557,6 @@ compare_digest_to_vote_routerstatus_entry(const void *_key,
return tor_memcmp(key, vrs->status.identity_digest, DIGEST_LEN);
}
/** As networkstatus_v2_find_entry, but do not return a const pointer */
routerstatus_t *
networkstatus_v2_find_mutable_entry(networkstatus_v2_t *ns, const char *digest)
{
return smartlist_bsearch(ns->entries, digest,
compare_digest_to_routerstatus_entry);
}
/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
* NULL if none was found. */
const routerstatus_t *
networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest)
{
return networkstatus_v2_find_mutable_entry(ns, digest);
}
/** As networkstatus_find_entry, but do not return a const pointer */
routerstatus_t *
networkstatus_vote_find_mutable_entry(networkstatus_t *ns, const char *digest)
@ -993,15 +586,6 @@ networkstatus_vote_find_entry_idx(networkstatus_t *ns,
found_out);
}
/** Return a list of the v2 networkstatus documents. */
const smartlist_t *
networkstatus_get_v2_list(void)
{
if (!networkstatus_v2_list)
networkstatus_v2_list = smartlist_new();
return networkstatus_v2_list;
}
/** As router_get_consensus_status_by_descriptor_digest, but does not return
* a const pointer. */
routerstatus_t *
@ -1046,8 +630,6 @@ router_get_dl_status_by_descriptor_digest(const char *d)
if ((rs = router_get_mutable_consensus_status_by_descriptor_digest(
current_ns_consensus, d)))
return &rs->dl_status;
if (v2_download_status_map)
return digestmap_get(v2_download_status_map, d);
return NULL;
}
@ -1113,72 +695,6 @@ networkstatus_nickname_is_unnamed(const char *nickname)
* networkstatus documents? */
#define NONAUTHORITY_NS_CACHE_INTERVAL (60*60)
/** We are a directory server, and so cache network_status documents.
* Initiate downloads as needed to update them. For v2 authorities,
* this means asking each trusted directory for its network-status.
* For caches, this means asking a random v2 authority for all
* network-statuses.
*/
static void
update_v2_networkstatus_cache_downloads(time_t now)
{
int authority = authdir_mode_v2(get_options());
int interval =
authority ? AUTHORITY_NS_CACHE_INTERVAL : NONAUTHORITY_NS_CACHE_INTERVAL;
const smartlist_t *trusted_dir_servers = router_get_trusted_dir_servers();
if (last_networkstatus_download_attempted + interval >= now)
return;
last_networkstatus_download_attempted = now;
if (authority) {
/* An authority launches a separate connection for everybody. */
SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, dir_server_t *, ds)
{
char resource[HEX_DIGEST_LEN+6]; /* fp/hexdigit.z\0 */
tor_addr_t addr;
if (!(ds->type & V2_DIRINFO))
continue;
if (router_digest_is_me(ds->digest))
continue;
tor_addr_from_ipv4h(&addr, ds->addr);
/* Is this quite sensible with IPv6 or multiple addresses? */
if (connection_get_by_type_addr_port_purpose(
CONN_TYPE_DIR, &addr, ds->dir_port,
DIR_PURPOSE_FETCH_V2_NETWORKSTATUS)) {
/* XXX the above dir_port won't be accurate if we're
* doing a tunneled conn. In that case it should be or_port.
* How to guess from here? Maybe make the function less general
* and have it know that it's looking for dir conns. -RD */
/* Only directory caches download v2 networkstatuses, and they
* don't use tunneled connections. I think it's okay to ignore
* this. */
continue;
}
strlcpy(resource, "fp/", sizeof(resource));
base16_encode(resource+3, sizeof(resource)-3, ds->digest, DIGEST_LEN);
strlcat(resource, ".z", sizeof(resource));
directory_initiate_command_routerstatus(
&ds->fake_status, DIR_PURPOSE_FETCH_V2_NETWORKSTATUS,
ROUTER_PURPOSE_GENERAL,
DIRIND_ONEHOP,
resource,
NULL, 0 /* No payload. */,
0 /* No I-M-S. */);
}
SMARTLIST_FOREACH_END(ds);
} else {
/* A non-authority cache launches one connection to a random authority. */
/* (Check whether we're currently fetching network-status objects.) */
if (!connection_get_by_type_purpose(CONN_TYPE_DIR,
DIR_PURPOSE_FETCH_V2_NETWORKSTATUS))
directory_get_from_dirserver(DIR_PURPOSE_FETCH_V2_NETWORKSTATUS,
ROUTER_PURPOSE_GENERAL, "all.z",
PDS_RETRY_IF_NO_SERVERS);
}
}
/** Return true iff, given the options listed in <b>options</b>, <b>flavor</b>
* is the flavor of a consensus networkstatus that we would like to fetch. */
static int
@ -1397,8 +913,6 @@ update_networkstatus_downloads(time_t now)
const or_options_t *options = get_options();
if (should_delay_dir_fetches(options))
return;
if (authdir_mode_any_main(options) || options->FetchV2Networkstatus)
update_v2_networkstatus_cache_downloads(now);
update_consensus_networkstatus_downloads(now);
update_certificate_downloads(now);
}
@ -1505,7 +1019,6 @@ routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b)
a->is_named != b->is_named ||
a->is_unnamed != b->is_unnamed ||
a->is_valid != b->is_valid ||
a->is_v2_dir != b->is_v2_dir ||
a->is_possible_guard != b->is_possible_guard ||
a->is_bad_exit != b->is_bad_exit ||
a->is_bad_directory != b->is_bad_directory ||
@ -1900,9 +1413,6 @@ routers_update_all_from_networkstatus(time_t now, int dir_version)
networkstatus_t *consensus = networkstatus_get_reasonably_live_consensus(now,
FLAV_NS);
if (networkstatus_v2_list_has_changed)
download_status_map_update_from_v2_networkstatus();
if (!consensus || dir_version < 3) /* nothing more we should do */
return;
@ -1957,35 +1467,6 @@ routers_update_all_from_networkstatus(time_t now, int dir_version)
}
}
/** Update v2_download_status_map to contain an entry for every router
* descriptor listed in the v2 networkstatuses. */
static void
download_status_map_update_from_v2_networkstatus(void)
{
digestmap_t *dl_status;
if (!networkstatus_v2_list)
return;
if (!v2_download_status_map)
v2_download_status_map = digestmap_new();
dl_status = digestmap_new();
SMARTLIST_FOREACH_BEGIN(networkstatus_v2_list, networkstatus_v2_t *, ns) {
SMARTLIST_FOREACH_BEGIN(ns->entries, const routerstatus_t *, rs) {
const char *d = rs->descriptor_digest;
download_status_t *s;
if (digestmap_get(dl_status, d))
continue;
if (!(s = digestmap_remove(v2_download_status_map, d))) {
s = tor_malloc_zero(sizeof(download_status_t));
}
digestmap_set(dl_status, d, s);
} SMARTLIST_FOREACH_END(rs);
} SMARTLIST_FOREACH_END(ns);
digestmap_free(v2_download_status_map, tor_free_);
v2_download_status_map = dl_status;
networkstatus_v2_list_has_changed = 0;
}
/** Update our view of the list of named servers from the most recently
* retrieved networkstatus consensus. */
static void
@ -2017,14 +1498,11 @@ void
routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
int reset_failures)
{
dir_server_t *ds;
const or_options_t *options = get_options();
int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
int authdir = authdir_mode_v3(options);
networkstatus_t *ns = current_consensus;
if (!ns || !smartlist_len(ns->routerstatus_list))
return;
if (!networkstatus_v2_list)
networkstatus_v2_list = smartlist_new();
routers_sort_by_identity(routers);
@ -2034,11 +1512,6 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
router->cache_info.identity_digest, DIGEST_LEN),
{
}) {
/* We have a routerstatus for this router. */
const char *digest = router->cache_info.identity_digest;
ds = router_get_fallback_dirserver_by_digest(digest);
/* Is it the same descriptor, or only the same identity? */
if (tor_memeq(router->cache_info.signed_descriptor_digest,
rs->descriptor_digest, DIGEST_LEN)) {
@ -2056,30 +1529,11 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
dirserv_should_launch_reachability_test(router, old_router);
}
}
if (rs->is_flagged_running && ds) {
download_status_reset(&ds->v2_ns_dl_status);
}
if (reset_failures) {
download_status_reset(&rs->dl_status);
}
} SMARTLIST_FOREACH_JOIN_END(rs, router);
/* Now update last_listed_as_valid_until from v2 networkstatuses. */
SMARTLIST_FOREACH_BEGIN(networkstatus_v2_list, networkstatus_v2_t *, ns) {
time_t live_until = ns->published_on + V2_NETWORKSTATUS_ROUTER_LIFETIME;
SMARTLIST_FOREACH_JOIN(ns->entries, const routerstatus_t *, rs,
routers, routerinfo_t *, ri,
tor_memcmp(rs->identity_digest,
ri->cache_info.identity_digest, DIGEST_LEN),
STMT_NIL) {
if (tor_memeq(ri->cache_info.signed_descriptor_digest,
rs->descriptor_digest, DIGEST_LEN)) {
if (live_until > ri->cache_info.last_listed_as_valid_until)
ri->cache_info.last_listed_as_valid_until = live_until;
}
} SMARTLIST_FOREACH_JOIN_END(rs, ri);
} SMARTLIST_FOREACH_END(ns);
router_dir_info_changed();
}
@ -2398,15 +1852,6 @@ void
networkstatus_free_all(void)
{
int i;
if (networkstatus_v2_list) {
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
networkstatus_v2_free(ns));
smartlist_free(networkstatus_v2_list);
networkstatus_v2_list = NULL;
}
digestmap_free(v2_download_status_map, tor_free_);
v2_download_status_map = NULL;
networkstatus_vote_free(current_ns_consensus);
networkstatus_vote_free(current_md_consensus);
current_md_consensus = current_ns_consensus = NULL;

View File

@ -12,16 +12,10 @@
#ifndef TOR_NETWORKSTATUS_H
#define TOR_NETWORKSTATUS_H
/** How old do we allow a v2 network-status to get before removing it
* completely? */
#define MAX_NETWORKSTATUS_AGE (10*24*60*60)
void networkstatus_reset_warnings(void);
void networkstatus_reset_download_failures(void);
int router_reload_v2_networkstatus(void);
int router_reload_consensus_networkstatus(void);
void routerstatus_free(routerstatus_t *rs);
void networkstatus_v2_free(networkstatus_v2_t *ns);
void networkstatus_vote_free(networkstatus_t *ns);
networkstatus_voter_info_t *networkstatus_get_voter_by_id(
networkstatus_t *vote,
@ -32,25 +26,16 @@ int networkstatus_check_document_signature(const networkstatus_t *consensus,
document_signature_t *sig,
const authority_cert_t *cert);
char *networkstatus_get_cache_filename(const char *identity_digest);
int router_set_networkstatus_v2(const char *s, time_t arrived_at,
v2_networkstatus_source_t source,
smartlist_t *requested_fingerprints);
void networkstatus_v2_list_clean(time_t now);
int compare_digest_to_routerstatus_entry(const void *_key,
const void **_member);
int compare_digest_to_vote_routerstatus_entry(const void *_key,
const void **_member);
const routerstatus_t *networkstatus_v2_find_entry(networkstatus_v2_t *ns,
const char *digest);
const routerstatus_t *networkstatus_vote_find_entry(networkstatus_t *ns,
const char *digest);
routerstatus_t *networkstatus_v2_find_mutable_entry(networkstatus_v2_t *ns,
const char *digest);
routerstatus_t *networkstatus_vote_find_mutable_entry(networkstatus_t *ns,
const char *digest);
int networkstatus_vote_find_entry_idx(networkstatus_t *ns,
const char *digest, int *found_out);
const smartlist_t *networkstatus_get_v2_list(void);
download_status_t *router_get_dl_status_by_descriptor_digest(const char *d);
const routerstatus_t *router_get_consensus_status_by_id(const char *digest);
routerstatus_t *router_get_mutable_consensus_status_by_id(

View File

@ -213,7 +213,7 @@ void
nodelist_set_consensus(networkstatus_t *ns)
{
const or_options_t *options = get_options();
int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
int authdir = authdir_mode_v3(options);
int client = !server_mode(options);
init_nodelist();
@ -1333,7 +1333,7 @@ compute_frac_paths_available(const networkstatus_t *consensus,
smartlist_t *myexits= smartlist_new();
double f_guard, f_mid, f_exit, f_myexit;
int np, nu; /* Ignored */
const int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
const int authdir = authdir_mode_v3(options);
count_usable_descriptors(num_present_out, num_usable_out,
mid, consensus, options, now, NULL, 0);

View File

@ -407,9 +407,6 @@ typedef enum {
/** A connection to a directory server: set after a rendezvous
* descriptor is downloaded. */
#define DIR_PURPOSE_HAS_FETCHED_RENDDESC 4
/** A connection to a directory server: download one or more v2
* network-status objects */
#define DIR_PURPOSE_FETCH_V2_NETWORKSTATUS 5
/** A connection to a directory server: download one or more server
* descriptors. */
#define DIR_PURPOSE_FETCH_SERVERDESC 6
@ -2036,9 +2033,7 @@ typedef struct signed_descriptor_t {
* routerlist->old_routers? -1 for none. */
int routerlist_index;
/** The valid-until time of the most recent consensus that listed this
* descriptor, or a bit after the publication time of the most recent v2
* networkstatus that listed it. 0 for "never listed in a consensus or
* status, so far as we know." */
* descriptor. 0 for "never listed in a consensus, so far as we know." */
time_t last_listed_as_valid_until;
/* If true, we do not ever try to save this object in the cache. */
unsigned int do_not_cache : 1;
@ -2175,10 +2170,6 @@ typedef struct routerstatus_t {
unsigned int is_unnamed:1; /**< True iff "nickname" belongs to another
* router. */
unsigned int is_valid:1; /**< True iff this router isn't invalid. */
unsigned int is_v2_dir:1; /**< True iff this router can serve directory
* information with v2 of the directory
* protocol. (All directory caches cache v1
* directories.) */
unsigned int is_possible_guard:1; /**< True iff this router would be a good
* choice as an entry guard. */
unsigned int is_bad_exit:1; /**< True iff this node is a bad choice for
@ -2215,12 +2206,6 @@ typedef struct routerstatus_t {
/* ---- The fields below aren't derived from the networkstatus; they
* hold local information only. */
/** True if we, as a directory mirror, want to download the corresponding
* routerinfo from the authority who gave us this routerstatus. (That is,
* if we don't have the routerinfo, and if we haven't already tried to get it
* from this authority.) Applies in v2 networkstatus document only.
*/
unsigned int need_to_mirror:1;
time_t last_dir_503_at; /**< When did this router last tell us that it
* was too busy to serve directory info? */
download_status_t dl_status;
@ -2385,44 +2370,6 @@ typedef struct node_t {
} node_t;
/** Contents of a v2 (non-consensus, non-vote) network status object. */
typedef struct networkstatus_v2_t {
/** When did we receive the network-status document? */
time_t received_on;
/** What was the digest of the document? */
char networkstatus_digest[DIGEST_LEN];
/* These fields come from the actual network-status document.*/
time_t published_on; /**< Declared publication date. */
char *source_address; /**< Canonical directory server hostname. */
uint32_t source_addr; /**< Canonical directory server IP. */
uint16_t source_dirport; /**< Canonical directory server dirport. */
unsigned int binds_names:1; /**< True iff this directory server binds
* names. */
unsigned int recommends_versions:1; /**< True iff this directory server
* recommends client and server software
* versions. */
unsigned int lists_bad_exits:1; /**< True iff this directory server marks
* malfunctioning exits as bad. */
/** True iff this directory server marks malfunctioning directories as
* bad. */
unsigned int lists_bad_directories:1;
char identity_digest[DIGEST_LEN]; /**< Digest of signing key. */
char *contact; /**< How to contact directory admin? (may be NULL). */
crypto_pk_t *signing_key; /**< Key used to sign this directory. */
char *client_versions; /**< comma-separated list of recommended client
* versions. */
char *server_versions; /**< comma-separated list of recommended server
* versions. */
smartlist_t *entries; /**< List of routerstatus_t*. This list is kept
* sorted by identity_digest. */
} networkstatus_v2_t;
/** Linked list of microdesc hash lines for a single router in a directory
* vote.
*/
@ -2686,8 +2633,6 @@ typedef enum {
/** Serves/signs v1 directory information: Big lists of routers, and short
* routerstatus documents. */
V1_DIRINFO = 1 << 0,
/** Serves/signs v2 directory information: i.e. v2 networkstatus documents */
V2_DIRINFO = 1 << 1,
/** Serves/signs v3 directory information: votes, consensuses, certs */
V3_DIRINFO = 1 << 2,
/** Serves hidden service descriptors. */
@ -3593,8 +3538,6 @@ typedef struct {
int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */
int V1AuthoritativeDir; /**< Boolean: is this an authoritative directory
* for version 1 directories? */
int V2AuthoritativeDir; /**< Boolean: is this an authoritative directory
* for version 2 directories? */
int V3AuthoritativeDir; /**< Boolean: is this an authoritative directory
* for version 3 directories? */
int HSAuthoritativeDir; /**< Boolean: does this an authoritative directory
@ -3649,8 +3592,6 @@ typedef struct {
int PublishHidServDescriptors;
int FetchServerDescriptors; /**< Do we fetch server descriptors as normal? */
int FetchHidServDescriptors; /**< and hidden service descriptors? */
int FetchV2Networkstatus; /**< Do we fetch v2 networkstatus documents when
* we don't need to? */
int HidServDirectoryV2; /**< Do we participate in the HS DHT? */
int VoteOnHidServDirectoriesV2; /**< As a directory authority, vote on
@ -4284,16 +4225,6 @@ typedef struct {
/** Fraction: */
double PathsNeededToBuildCircuits;
/** Do we serve v2 directory info at all? This is a temporary option, since
* we'd like to disable v2 directory serving entirely, but we need a way to
* make it temporarily disableable, in order to do fast testing and be
* able to turn it back on if it turns out to be non-workable.
*
* XXXX025 Make this always-on, or always-off. Right now, it's only
* enableable for authorities.
*/
int DisableV2DirectoryInfo_;
/** What expiry time shall we place on our SSL certs? "0" means we
* should guess a suitable value. */
int SSLKeyLifetime;
@ -4805,11 +4736,6 @@ typedef struct microdesc_cache_t microdesc_cache_t;
/********************************* networkstatus.c *********************/
/** Location where we found a v2 networkstatus. */
typedef enum {
NS_FROM_CACHE, NS_FROM_DIR_BY_FP, NS_FROM_DIR_ALL, NS_GENERATED
} v2_networkstatus_source_t;
/** Possible statuses of a version of Tor, given opinions from the directory
* servers. */
typedef enum version_status_t {
@ -5010,8 +4936,6 @@ typedef struct dir_server_t {
/** What kind of authority is this? (Bitfield.) */
dirinfo_type_t type;
download_status_t v2_ns_dl_status; /**< Status of downloading this server's
* v2 network status. */
time_t addr_current_at; /**< When was the document that we derived the
* address information from published? */

View File

@ -933,7 +933,6 @@ init_keys(void)
/* 6b. [authdirserver only] add own key to approved directories. */
crypto_pk_get_digest(get_server_identity_key(), digest);
type = ((options->V1AuthoritativeDir ? V1_DIRINFO : NO_DIRINFO) |
(options->V2AuthoritativeDir ? V2_DIRINFO : NO_DIRINFO) |
(options->V3AuthoritativeDir ?
(V3_DIRINFO|MICRODESC_DIRINFO|EXTRAINFO_DIRINFO) : NO_DIRINFO) |
(options->BridgeAuthoritativeDir ? BRIDGE_DIRINFO : NO_DIRINFO) |
@ -1260,14 +1259,6 @@ authdir_mode_v1(const or_options_t *options)
{
return authdir_mode(options) && options->V1AuthoritativeDir != 0;
}
/** Return true iff we believe ourselves to be a v2 authoritative
* directory server.
*/
int
authdir_mode_v2(const or_options_t *options)
{
return authdir_mode(options) && options->V2AuthoritativeDir != 0;
}
/** Return true iff we believe ourselves to be a v3 authoritative
* directory server.
*/
@ -1276,12 +1267,11 @@ authdir_mode_v3(const or_options_t *options)
{
return authdir_mode(options) && options->V3AuthoritativeDir != 0;
}
/** Return true iff we are a v1, v2, or v3 directory authority. */
/** Return true iff we are a v1 or v3 directory authority. */
int
authdir_mode_any_main(const or_options_t *options)
{
return options->V1AuthoritativeDir ||
options->V2AuthoritativeDir ||
options->V3AuthoritativeDir;
}
/** Return true if we believe ourselves to be any kind of

View File

@ -51,7 +51,6 @@ int net_is_disabled(void);
int authdir_mode(const or_options_t *options);
int authdir_mode_v1(const or_options_t *options);
int authdir_mode_v2(const or_options_t *options);
int authdir_mode_v3(const or_options_t *options);
int authdir_mode_any_main(const or_options_t *options);
int authdir_mode_any_nonhidserv(const or_options_t *options);

View File

@ -220,8 +220,6 @@ download_status_is_ready_by_sk_in_cl(cert_list_t *cl,
return rv;
}
#define get_n_v2_authorities() get_n_authorities(V2_DIRINFO)
/** Helper: Return the cert_list_t for an authority whose authority ID is
* <b>id_digest</b>, allocating a new list if necessary. */
static cert_list_t *
@ -1272,18 +1270,18 @@ router_pick_directory_server(dirinfo_type_t type, int flags)
return choice;
}
/** Try to determine which fraction of v2 and v3 directory requests aimed at
* caches will be sent to us. Set *<b>v2_share_out</b> and
* *<b>v3_share_out</b> to the fractions of v2 and v3 protocol shares we
* expect to see, respectively. Return 0 on success, negative on failure. */
/** Try to determine which fraction ofv3 directory requests aimed at
* caches will be sent to us. Set
* *<b>v3_share_out</b> to the fraction of v3 protocol shares we
* expect to see. Return 0 on success, negative on failure. */
/* XXXX This function is unused. */
int
router_get_my_share_of_directory_requests(double *v2_share_out,
double *v3_share_out)
router_get_my_share_of_directory_requests(double *v3_share_out)
{
const routerinfo_t *me = router_get_my_routerinfo();
const routerstatus_t *rs;
const int pds_flags = PDS_ALLOW_SELF|PDS_IGNORE_FASCISTFIREWALL;
*v2_share_out = *v3_share_out = 0.0;
*v3_share_out = 0.0;
if (!me)
return -1;
rs = router_get_consensus_status_by_id(me->cache_info.identity_digest);
@ -1292,15 +1290,6 @@ router_get_my_share_of_directory_requests(double *v2_share_out,
/* Calling for side effect */
/* XXXX This is a bit of a kludge */
if (rs->is_v2_dir) {
sl_last_total_weighted_bw = 0;
router_pick_directory_server(V2_DIRINFO, pds_flags);
if (sl_last_total_weighted_bw != 0) {
*v2_share_out = U64_TO_DBL(sl_last_weighted_bw_of_me) /
U64_TO_DBL(sl_last_total_weighted_bw);
}
}
{
sl_last_total_weighted_bw = 0;
router_pick_directory_server(V3_DIRINFO, pds_flags);
@ -1472,8 +1461,6 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags)
if (requireother && router_digest_is_me(node->identity))
continue;
is_trusted = router_digest_is_trusted_dir(node->identity);
if ((type & V2_DIRINFO) && !(node->rs->is_v2_dir || is_trusted))
continue;
if ((type & EXTRAINFO_DIRINFO) &&
!router_supports_extrainfo(node->identity, 0))
continue;
@ -1700,7 +1687,6 @@ mark_all_dirservers_up(smartlist_t *server_list)
routerstatus_t *rs;
node_t *node;
dir->is_running = 1;
download_status_reset(&dir->v2_ns_dl_status);
node = node_get_mutable_by_id(dir->digest);
if (node)
node->is_running = 1;
@ -3354,7 +3340,6 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
routerinfo_t *old_router;
networkstatus_t *consensus =
networkstatus_get_latest_consensus_by_flavor(FLAV_NS);
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
int in_consensus = 0;
tor_assert(msg);
@ -3425,15 +3410,6 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
}
/* We no longer need a router with this descriptor digest. */
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
{
routerstatus_t *rs =
networkstatus_v2_find_mutable_entry(ns, id_digest);
if (rs && tor_memeq(rs->descriptor_digest,
router->cache_info.signed_descriptor_digest,
DIGEST_LEN))
rs->need_to_mirror = 0;
});
if (consensus) {
routerstatus_t *rs = networkstatus_vote_find_mutable_entry(
consensus, id_digest);
@ -3441,7 +3417,6 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
router->cache_info.signed_descriptor_digest,
DIGEST_LEN)) {
in_consensus = 1;
rs->need_to_mirror = 0;
}
}
@ -3680,11 +3655,7 @@ routerlist_remove_old_routers(void)
routerinfo_t *router;
signed_descriptor_t *sd;
digestset_t *retain;
int caches = directory_caches_dir_info(get_options());
const networkstatus_t *consensus = networkstatus_get_latest_consensus();
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
int have_enough_v2;
const or_options_t *options = get_options();
trusted_dirs_remove_old_certs();
@ -3700,38 +3671,10 @@ routerlist_remove_old_routers(void)
{
/* We'll probably retain everything in the consensus. */
int n_max_retain = smartlist_len(consensus->routerstatus_list);
if (caches && networkstatus_v2_list) {
/* If we care about v2 statuses, we'll retain at most as many as are
listed any of the v2 statues. This will be at least the length of
the largest v2 networkstatus, and in the worst case, this set will be
equal to the sum of the lengths of all v2 consensuses. Take the
worst case.
*/
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
n_max_retain += smartlist_len(ns->entries));
}
retain = digestset_new(n_max_retain);
}
cutoff = now - OLD_ROUTER_DESC_MAX_AGE;
/* Build a list of all the descriptors that _anybody_ lists. */
if (caches && networkstatus_v2_list) {
SMARTLIST_FOREACH_BEGIN(networkstatus_v2_list, networkstatus_v2_t *, ns) {
/* XXXX The inner loop here gets pretty expensive, and actually shows up
* on some profiles. It may be the reason digestmap_set shows up in
* profiles too. If instead we kept a per-descriptor digest count of
* how many networkstatuses recommended each descriptor, and changed
* that only when the networkstatuses changed, that would be a speed
* improvement, possibly 1-4% if it also removes digestmap_set from the
* profile. Not worth it for 0.1.2.x, though. The new directory
* system will obsolete this whole thing in 0.2.0.x. */
SMARTLIST_FOREACH_BEGIN(ns->entries, routerstatus_t *, rs) {
if (rs->published_on >= cutoff)
digestset_add(retain, rs->descriptor_digest);
} SMARTLIST_FOREACH_END(rs);
} SMARTLIST_FOREACH_END(ns);
}
/* Retain anything listed in the consensus. */
if (consensus) {
SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
@ -3739,18 +3682,13 @@ routerlist_remove_old_routers(void)
digestset_add(retain, rs->descriptor_digest));
}
/* If we have a consensus, and nearly as many v2 networkstatuses as we want,
/* If we have a consensus,
* we should consider pruning current routers that are too old and that
* nobody recommends. (If we don't have a consensus or enough v2
* networkstatuses, then we should get more before we decide to kill
* routers.) */
/* we set this to true iff we don't care about v2 info, or we have enough. */
have_enough_v2 = !caches ||
!(authdir_mode_any_main(options) || options->FetchV2Networkstatus) ||
(networkstatus_v2_list &&
smartlist_len(networkstatus_v2_list) > get_n_v2_authorities() / 2);
if (have_enough_v2 && consensus) {
if (consensus) {
cutoff = now - ROUTER_MAX_AGE;
/* Remove too-old unrecommended members of routerlist->routers. */
for (i = 0; i < smartlist_len(routerlist->routers); ++i) {
@ -4049,8 +3987,6 @@ signed_desc_digest_is_recognized(signed_descriptor_t *desc)
{
const routerstatus_t *rs;
networkstatus_t *consensus = networkstatus_get_latest_consensus();
int caches = directory_caches_dir_info(get_options());
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
if (consensus) {
rs = networkstatus_vote_find_entry(consensus, desc->identity_digest);
@ -4058,16 +3994,6 @@ signed_desc_digest_is_recognized(signed_descriptor_t *desc)
desc->signed_descriptor_digest, DIGEST_LEN))
return 1;
}
if (caches && networkstatus_v2_list) {
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
{
if (!(rs = networkstatus_v2_find_entry(ns, desc->identity_digest)))
continue;
if (tor_memeq(rs->descriptor_digest,
desc->signed_descriptor_digest, DIGEST_LEN))
return 1;
});
}
return 0;
}
@ -4083,7 +4009,7 @@ update_all_descriptor_downloads(time_t now)
launch_dummy_descriptor_download_as_needed(now, get_options());
}
/** Clear all our timeouts for fetching v2 and v3 directory stuff, and then
/** Clear all our timeouts for fetching v3 directory stuff, and then
* give it all a try again. */
void
routerlist_retry_directory_downloads(time_t now)
@ -4564,152 +4490,6 @@ launch_descriptor_downloads(int purpose,
}
}
/** Launch downloads for router status as needed, using the strategy used by
* authorities and caches: based on the v2 networkstatuses we have, download
* every descriptor we don't have but would serve, from a random authority
* that lists it. */
static void
update_router_descriptor_cache_downloads_v2(time_t now)
{
smartlist_t **downloadable; /* For each authority, what can we dl from it? */
smartlist_t **download_from; /* ... and, what will we dl from it? */
digestmap_t *map; /* Which descs are in progress, or assigned? */
int i, j, n;
int n_download;
const or_options_t *options = get_options();
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
if (! directory_fetches_dir_info_early(options)) {
log_warn(LD_BUG, "Called update_router_descriptor_cache_downloads_v2() "
"on a non-dir-mirror?");
}
if (!networkstatus_v2_list || !smartlist_len(networkstatus_v2_list))
return;
map = digestmap_new();
n = smartlist_len(networkstatus_v2_list);
downloadable = tor_malloc_zero(sizeof(smartlist_t*) * n);
download_from = tor_malloc_zero(sizeof(smartlist_t*) * n);
/* Set map[d]=1 for the digest of every descriptor that we are currently
* downloading. */
list_pending_descriptor_downloads(map, 0);
/* For the digest of every descriptor that we don't have, and that we aren't
* downloading, add d to downloadable[i] if the i'th networkstatus knows
* about that descriptor, and we haven't already failed to get that
* descriptor from the corresponding authority.
*/
n_download = 0;
SMARTLIST_FOREACH_BEGIN(networkstatus_v2_list, networkstatus_v2_t *, ns) {
dir_server_t *ds;
smartlist_t *dl;
dl = downloadable[ns_sl_idx] = smartlist_new();
download_from[ns_sl_idx] = smartlist_new();
if (ns->published_on + MAX_NETWORKSTATUS_AGE+10*60 < now) {
/* Don't download if the networkstatus is almost ancient. */
/* Actually, I suspect what's happening here is that we ask
* for the descriptor when we have a given networkstatus,
* and then we get a newer networkstatus, and then we receive
* the descriptor. Having a networkstatus actually expire is
* probably a rare event, and we'll probably be happiest if
* we take this clause out. -RD */
continue;
}
/* Don't try dirservers that we think are down -- we might have
* just tried them and just marked them as down. */
ds = router_get_trusteddirserver_by_digest(ns->identity_digest);
if (ds && !ds->is_running)
continue;
SMARTLIST_FOREACH_BEGIN(ns->entries, routerstatus_t * , rs) {
if (!rs->need_to_mirror)
continue;
if (router_get_by_descriptor_digest(rs->descriptor_digest)) {
log_warn(LD_BUG,
"We have a router descriptor, but need_to_mirror=1.");
rs->need_to_mirror = 0;
continue;
}
if (authdir_mode(options) && dirserv_would_reject_router(rs)) {
rs->need_to_mirror = 0;
continue;
}
if (digestmap_get(map, rs->descriptor_digest)) {
/* We're downloading it already. */
continue;
} else {
/* We could download it from this guy. */
smartlist_add(dl, rs->descriptor_digest);
++n_download;
}
} SMARTLIST_FOREACH_END(rs);
} SMARTLIST_FOREACH_END(ns);
/* At random, assign descriptors to authorities such that:
* - if d is a member of some downloadable[x], d is a member of some
* download_from[y]. (Everything we want to download, we try to download
* from somebody.)
* - If d is a member of download_from[y], d is a member of downloadable[y].
* (We only try to download descriptors from authorities who claim to have
* them.)
* - No d is a member of download_from[x] and download_from[y] s.t. x != y.
* (We don't try to download anything from two authorities concurrently.)
*/
while (n_download) {
int which_ns = crypto_rand_int(n);
smartlist_t *dl = downloadable[which_ns];
int idx;
char *d;
if (!smartlist_len(dl))
continue;
idx = crypto_rand_int(smartlist_len(dl));
d = smartlist_get(dl, idx);
if (! digestmap_get(map, d)) {
smartlist_add(download_from[which_ns], d);
digestmap_set(map, d, (void*) 1);
}
smartlist_del(dl, idx);
--n_download;
}
/* Now, we can actually launch our requests. */
for (i=0; i<n; ++i) {
networkstatus_v2_t *ns = smartlist_get(networkstatus_v2_list, i);
dir_server_t *ds =
router_get_trusteddirserver_by_digest(ns->identity_digest);
smartlist_t *dl = download_from[i];
int pds_flags = PDS_RETRY_IF_NO_SERVERS;
if (! authdir_mode_any_nonhidserv(options))
pds_flags |= PDS_NO_EXISTING_SERVERDESC_FETCH; /* XXXX ignored*/
if (!ds) {
log_info(LD_DIR, "Networkstatus with no corresponding authority!");
continue;
}
if (! smartlist_len(dl))
continue;
log_info(LD_DIR, "Requesting %d descriptors from authority \"%s\"",
smartlist_len(dl), ds->nickname);
for (j=0; j < smartlist_len(dl); j += MAX_DL_PER_REQUEST) {
initiate_descriptor_downloads(&(ds->fake_status),
DIR_PURPOSE_FETCH_SERVERDESC, dl, j,
j+MAX_DL_PER_REQUEST, pds_flags);
}
}
for (i=0; i<n; ++i) {
smartlist_free(download_from[i]);
smartlist_free(downloadable[i]);
}
tor_free(download_from);
tor_free(downloadable);
digestmap_free(map,NULL);
}
/** For any descriptor that we want that's currently listed in
* <b>consensus</b>, download it as appropriate. */
void
@ -4874,9 +4654,6 @@ update_router_descriptor_downloads(time_t now)
return;
if (!we_fetch_router_descriptors(options))
return;
if (directory_fetches_dir_info_early(options)) {
update_router_descriptor_cache_downloads_v2(now);
}
update_consensus_router_descriptor_downloads(now, 0,
networkstatus_get_reasonably_live_consensus(now, FLAV_NS));

View File

@ -54,8 +54,7 @@ const routerstatus_t *router_pick_trusteddirserver(dirinfo_type_t type,
int flags);
const routerstatus_t *router_pick_fallback_dirserver(dirinfo_type_t type,
int flags);
int router_get_my_share_of_directory_requests(double *v2_share_out,
double *v3_share_out);
int router_get_my_share_of_directory_requests(double *v3_share_out);
void router_reset_status_download_failures(void);
int routers_have_same_or_addrs(const routerinfo_t *r1, const routerinfo_t *r2);
const routerinfo_t *routerlist_find_my_routerinfo(void);

View File

@ -353,31 +353,6 @@ static token_rule_t rtrstatus_token_table[] = {
END_OF_TABLE
};
/** List of tokens recognized in the header part of v2 networkstatus documents.
*/
static token_rule_t netstatus_token_table[] = {
T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
T1( "dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
T1( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
GE(1), NO_OBJ ),
T1( "dir-source", K_DIR_SOURCE, GE(3), NO_OBJ ),
T01("dir-options", K_DIR_OPTIONS, ARGS, NO_OBJ ),
T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
END_OF_TABLE
};
/** List of tokens recognized in the footer of v1/v2 directory/networkstatus
* footers. */
static token_rule_t dir_footer_token_table[] = {
T1("directory-signature", K_DIRECTORY_SIGNATURE, EQ(1), NEED_OBJ ),
END_OF_TABLE
};
/** List of tokens common to V3 authority certificates and V3 consensuses. */
#define CERTIFICATE_MEMBERS \
T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
@ -640,17 +615,6 @@ router_get_runningrouters_hash(const char *s, char *digest)
DIGEST_SHA1);
}
/** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
* string in <b>s</b>. Return 0 on success, -1 on failure. */
int
router_get_networkstatus_v2_hash(const char *s, char *digest)
{
return router_get_hash_impl(s, strlen(s), digest,
"network-status-version","\ndirectory-signature",
'\n',
DIGEST_SHA1);
}
/** Set <b>digests</b> to all the digests of the consensus document in
* <b>s</b> */
int
@ -1943,8 +1907,6 @@ routerstatus_parse_entry_from_string(memarea_t *area,
rs->is_named = 1;
else if (!strcmp(tok->args[i], "Valid"))
rs->is_valid = 1;
else if (!strcmp(tok->args[i], "V2Dir"))
rs->is_v2_dir = 1;
else if (!strcmp(tok->args[i], "Guard"))
rs->is_possible_guard = 1;
else if (!strcmp(tok->args[i], "BadExit"))
@ -2095,188 +2057,6 @@ compare_vote_routerstatus_entries(const void **_a, const void **_b)
DIGEST_LEN);
}
/** Helper: used in call to _smartlist_uniq to clear out duplicate entries. */
static void
free_duplicate_routerstatus_entry_(void *e)
{
log_warn(LD_DIR,
"Network-status has two entries for the same router. "
"Dropping one.");
routerstatus_free(e);
}
/** Given a v2 network-status object in <b>s</b>, try to
* parse it and return the result. Return NULL on failure. Check the
* signature of the network status, but do not (yet) check the signing key for
* authority.
*/
networkstatus_v2_t *
networkstatus_v2_parse_from_string(const char *s)
{
const char *eos, *s_dup = s;
smartlist_t *tokens = smartlist_new();
smartlist_t *footer_tokens = smartlist_new();
networkstatus_v2_t *ns = NULL;
char ns_digest[DIGEST_LEN];
char tmp_digest[DIGEST_LEN];
struct in_addr in;
directory_token_t *tok;
int i;
memarea_t *area = NULL;
if (router_get_networkstatus_v2_hash(s, ns_digest)) {
log_warn(LD_DIR, "Unable to compute digest of network-status");
goto err;
}
area = memarea_new();
eos = find_start_of_next_routerstatus(s);
if (tokenize_string(area, s, eos, tokens, netstatus_token_table,0)) {
log_warn(LD_DIR, "Error tokenizing network-status header.");
goto err;
}
ns = tor_malloc_zero(sizeof(networkstatus_v2_t));
memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN);
tok = find_by_keyword(tokens, K_NETWORK_STATUS_VERSION);
tor_assert(tok->n_args >= 1);
if (strcmp(tok->args[0], "2")) {
log_warn(LD_BUG, "Got a non-v2 networkstatus. Version was "
"%s", escaped(tok->args[0]));
goto err;
}
tok = find_by_keyword(tokens, K_DIR_SOURCE);
tor_assert(tok->n_args >= 3);
ns->source_address = tor_strdup(tok->args[0]);
if (tor_inet_aton(tok->args[1], &in) == 0) {
log_warn(LD_DIR, "Error parsing network-status source address %s",
escaped(tok->args[1]));
goto err;
}
ns->source_addr = ntohl(in.s_addr);
ns->source_dirport =
(uint16_t) tor_parse_long(tok->args[2],10,0,65535,NULL,NULL);
if (ns->source_dirport == 0) {
log_warn(LD_DIR, "Directory source without dirport; skipping.");
goto err;
}
tok = find_by_keyword(tokens, K_FINGERPRINT);
tor_assert(tok->n_args);
if (base16_decode(ns->identity_digest, DIGEST_LEN, tok->args[0],
strlen(tok->args[0]))) {
log_warn(LD_DIR, "Couldn't decode networkstatus fingerprint %s",
escaped(tok->args[0]));
goto err;
}
if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
tor_assert(tok->n_args);
ns->contact = tor_strdup(tok->args[0]);
}
tok = find_by_keyword(tokens, K_DIR_SIGNING_KEY);
tor_assert(tok->key);
ns->signing_key = tok->key;
tok->key = NULL;
if (crypto_pk_get_digest(ns->signing_key, tmp_digest)<0) {
log_warn(LD_DIR, "Couldn't compute signing key digest");
goto err;
}
if (tor_memneq(tmp_digest, ns->identity_digest, DIGEST_LEN)) {
log_warn(LD_DIR,
"network-status fingerprint did not match dir-signing-key");
goto err;
}
if ((tok = find_opt_by_keyword(tokens, K_DIR_OPTIONS))) {
for (i=0; i < tok->n_args; ++i) {
if (!strcmp(tok->args[i], "Names"))
ns->binds_names = 1;
if (!strcmp(tok->args[i], "Versions"))
ns->recommends_versions = 1;
if (!strcmp(tok->args[i], "BadExits"))
ns->lists_bad_exits = 1;
if (!strcmp(tok->args[i], "BadDirectories"))
ns->lists_bad_directories = 1;
}
}
if (ns->recommends_versions) {
if (!(tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
log_warn(LD_DIR, "Missing client-versions on versioning directory");
goto err;
}
ns->client_versions = tor_strdup(tok->args[0]);
if (!(tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS)) ||
tok->n_args<1) {
log_warn(LD_DIR, "Missing server-versions on versioning directory");
goto err;
}
ns->server_versions = tor_strdup(tok->args[0]);
}
tok = find_by_keyword(tokens, K_PUBLISHED);
tor_assert(tok->n_args == 1);
if (parse_iso_time(tok->args[0], &ns->published_on) < 0) {
goto err;
}
ns->entries = smartlist_new();
s = eos;
SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
smartlist_clear(tokens);
memarea_clear(area);
while (!strcmpstart(s, "r ")) {
routerstatus_t *rs;
if ((rs = routerstatus_parse_entry_from_string(area, &s, tokens,
NULL, NULL, 0, 0)))
smartlist_add(ns->entries, rs);
}
smartlist_sort(ns->entries, compare_routerstatus_entries);
smartlist_uniq(ns->entries, compare_routerstatus_entries,
free_duplicate_routerstatus_entry_);
if (tokenize_string(area,s, NULL, footer_tokens, dir_footer_token_table,0)) {
log_warn(LD_DIR, "Error tokenizing network-status footer.");
goto err;
}
if (smartlist_len(footer_tokens) < 1) {
log_warn(LD_DIR, "Too few items in network-status footer.");
goto err;
}
tok = smartlist_get(footer_tokens, smartlist_len(footer_tokens)-1);
if (tok->tp != K_DIRECTORY_SIGNATURE) {
log_warn(LD_DIR,
"Expected network-status footer to end with a signature.");
goto err;
}
note_crypto_pk_op(VERIFY_DIR);
if (check_signature_token(ns_digest, DIGEST_LEN, tok, ns->signing_key, 0,
"network-status") < 0)
goto err;
goto done;
err:
dump_desc(s_dup, "v2 networkstatus");
networkstatus_v2_free(ns);
ns = NULL;
done:
SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
smartlist_free(tokens);
SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_clear(t));
smartlist_free(footer_tokens);
if (area) {
DUMP_AREA(area, "v2 networkstatus");
memarea_drop_all(area);
}
return ns;
}
/** Verify the bandwidth weights of a network status document */
int
networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)

View File

@ -15,7 +15,6 @@
int router_get_router_hash(const char *s, size_t s_len, char *digest);
int router_get_dir_hash(const char *s, char *digest);
int router_get_runningrouters_hash(const char *s, char *digest);
int router_get_networkstatus_v2_hash(const char *s, char *digest);
int router_get_networkstatus_v3_hashes(const char *s, digests_t *digests);
int router_get_extrainfo_hash(const char *s, size_t s_len, char *digest);
#define DIROBJ_MAX_SIG_LEN 256
@ -54,7 +53,6 @@ void dump_distinct_digest_count(int severity);
int compare_routerstatus_entries(const void **_a, const void **_b);
int compare_vote_routerstatus_entries(const void **_a, const void **_b);
networkstatus_v2_t *networkstatus_v2_parse_from_string(const char *s);
int networkstatus_verify_bw_weights(networkstatus_t *ns, int);
networkstatus_t *networkstatus_parse_vote_from_string(const char *s,
const char **eos_out,

View File

@ -941,7 +941,7 @@ gen_routerstatus_for_v3ns(int idx, time_t now)
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_v2_dir = rs->is_possible_guard = 1;
rs->is_valid = rs->is_possible_guard = 1;
break;
case 2:
/* Generate the third routerstatus. */
@ -956,7 +956,7 @@ gen_routerstatus_for_v3ns(int idx, time_t now)
rs->or_port = 400;
rs->dir_port = 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_flagged_running = rs->is_valid =
rs->is_possible_guard = 1;
break;
case 3:
@ -1065,7 +1065,7 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now)
test_eq(rs->addr, 0x99008801);
test_eq(rs->or_port, 443);
test_eq(rs->dir_port, 8000);
test_eq(vrs->flags, U64_LITERAL(16)); // no flags except "running"
test_eq(vrs->flags, U64_LITERAL(80)); // no flags except "running"
} else if (tor_memeq(rs->identity_digest,
"\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5"
"\x5\x5\x5\x5",
@ -1090,10 +1090,10 @@ test_vrs_for_v3ns(vote_routerstatus_t *vrs, int voter, time_t now)
test_assert(tor_addr_eq(&rs->ipv6_addr, &addr_ipv6));
test_eq(rs->ipv6_orport, 4711);
if (voter == 1) {
test_eq(vrs->flags, U64_LITERAL(254)); // all flags except "authority."
test_eq(vrs->flags, U64_LITERAL(190)); // all except "authority","v2dir"
} else {
/* 1023 - authority(1) - madeofcheese(16) - madeoftin(32) */
test_eq(vrs->flags, U64_LITERAL(974));
/* 1023 - authority(1) - madeofcheese(16) - madeoftin(32) - v2dir(256) */
test_eq(vrs->flags, U64_LITERAL(718));
}
} else if (tor_memeq(rs->identity_digest,
"\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33"
@ -1161,7 +1161,6 @@ test_routerstatus_for_v3ns(routerstatus_t *rs, time_t now)
test_assert(!rs->is_stable);
/* (If it wasn't running it wouldn't be here) */
test_assert(rs->is_flagged_running);
test_assert(!rs->is_v2_dir);
test_assert(!rs->is_valid);
test_assert(!rs->is_named);
/* XXXX check version */
@ -1188,7 +1187,6 @@ test_routerstatus_for_v3ns(routerstatus_t *rs, time_t now)
test_assert(rs->is_possible_guard);
test_assert(rs->is_stable);
test_assert(rs->is_flagged_running);
test_assert(rs->is_v2_dir);
test_assert(rs->is_valid);
test_assert(!rs->is_named);
/* XXXX check version */
@ -1889,7 +1887,7 @@ gen_routerstatus_for_umbw(int idx, time_t now)
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_v2_dir = rs->is_possible_guard = 1;
rs->is_valid = rs->is_possible_guard = 1;
/*
* This one has measured bandwidth above the clip cutoff, and
* so shouldn't be clipped; we'll have to test that it isn't
@ -1912,7 +1910,7 @@ gen_routerstatus_for_umbw(int idx, time_t now)
rs->or_port = 400;
rs->dir_port = 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_flagged_running = rs->is_valid =
rs->is_possible_guard = 1;
/*
* This one has unmeasured bandwidth above the clip cutoff, and
@ -2148,7 +2146,6 @@ test_routerstatus_for_umbw(routerstatus_t *rs, time_t now)
test_assert(!rs->is_stable);
/* (If it wasn't running it wouldn't be here) */
test_assert(rs->is_flagged_running);
test_assert(!rs->is_v2_dir);
test_assert(!rs->is_valid);
test_assert(!rs->is_named);
/* This one should have measured bandwidth below the clip cutoff */
@ -2179,7 +2176,6 @@ test_routerstatus_for_umbw(routerstatus_t *rs, time_t now)
test_assert(rs->is_possible_guard);
test_assert(rs->is_stable);
test_assert(rs->is_flagged_running);
test_assert(rs->is_v2_dir);
test_assert(rs->is_valid);
test_assert(!rs->is_named);
/* This one should have measured bandwidth above the clip cutoff */
@ -2257,82 +2253,6 @@ test_dir_clip_unmeasured_bw_kb_alt(void)
test_routerstatus_for_umbw);
}
extern time_t time_of_process_start; /* from main.c */
static void
test_dir_v2_dir(void *arg)
{
/* Runs in a forked process: acts like a v2 directory just enough to make and
* sign a v2 networkstatus opinion */
cached_dir_t *v2 = NULL;
or_options_t *options = get_options_mutable();
crypto_pk_t *id_key = pk_generate(4);
(void) arg;
options->ORPort_set = 1; /* So we believe we're a server. */
options->DirPort_set = 1;
options->Address = tor_strdup("99.99.99.99");
options->Nickname = tor_strdup("TestV2Auth");
options->ContactInfo = tor_strdup("TestV2Auth <testv2auth@example.com>");
{
/* Give it a DirPort */
smartlist_t *ports = (smartlist_t *)get_configured_ports();
port_cfg_t *port = tor_malloc_zero(sizeof(port_cfg_t));
port->type = CONN_TYPE_DIR_LISTENER;
port->port = 9999;
smartlist_add(ports, port);
}
set_server_identity_key(id_key);
set_client_identity_key(id_key);
/* Add a router. */
{
was_router_added_t wra;
const char *msg = NULL;
routerinfo_t *r1 = tor_malloc_zero(sizeof(routerinfo_t));
r1->address = tor_strdup("18.244.0.1");
r1->addr = 0xc0a80001u; /* 192.168.0.1 */
r1->cache_info.published_on = time(NULL)-60;
r1->or_port = 9000;
r1->dir_port = 9003;
tor_addr_parse(&r1->ipv6_addr, "1:2:3:4::");
r1->ipv6_orport = 9999;
r1->onion_pkey = pk_generate(1);
r1->identity_pkey = pk_generate(2);
r1->bandwidthrate = 1000;
r1->bandwidthburst = 5000;
r1->bandwidthcapacity = 10000;
r1->exit_policy = NULL;
r1->nickname = tor_strdup("Magri");
r1->platform = tor_strdup("Tor 0.2.7.7-gamma");
r1->cache_info.routerlist_index = -1;
r1->cache_info.signed_descriptor_body =
router_dump_router_to_string(r1, r1->identity_pkey);
r1->cache_info.signed_descriptor_len =
strlen(r1->cache_info.signed_descriptor_body);
wra = router_add_to_routerlist(r1, &msg, 0, 0);
tt_int_op(wra, ==, ROUTER_ADDED_SUCCESSFULLY);
}
/* Prevent call of rep_hist_note_router_unreachable(). */
time_of_process_start = time(NULL);
/* Make a directory so there's somewhere to store the thing */
#ifdef _WIN32
tt_int_op(mkdir(get_fname("cached-status")), ==, 0);
#else
tt_int_op(mkdir(get_fname("cached-status"), 0700), ==, 0);
#endif
v2 = generate_v2_networkstatus_opinion();
tt_assert(v2);
done:
crypto_pk_free(id_key);
cached_dir_decref(v2);
}
static void
test_dir_fmt_control_ns(void *arg)
{
@ -2360,7 +2280,7 @@ test_dir_fmt_control_ns(void *arg)
"r TetsuoMilk U3RhdGVseSwgcGx1bXAgQnVjayA "
"TXVsbGlnYW4gY2FtZSB1cCBmcm8 2013-04-02 17:53:18 "
"32.48.64.80 9001 9002\n"
"s Exit Fast Running\n"
"s Exit Fast Running V2Dir\n"
"w Bandwidth=1000\n");
done:
@ -2455,7 +2375,6 @@ struct testcase_t dir_tests[] = {
DIR(scale_bw, 0),
DIR_LEGACY(clip_unmeasured_bw_kb),
DIR_LEGACY(clip_unmeasured_bw_kb_alt),
DIR(v2_dir, TT_FORK),
DIR(fmt_control_ns, 0),
DIR(http_handling, 0),
END_OF_TESTCASES