|
@@ -37,7 +37,6 @@ const char directory_c_id[] =
|
|
|
static void directory_send_command(dir_connection_t *conn,
|
|
|
int purpose, int direct, const char *resource,
|
|
|
const char *payload, size_t payload_len,
|
|
|
- int supports_conditional_consensus,
|
|
|
time_t if_modified_since);
|
|
|
static int directory_handle_command(dir_connection_t *conn);
|
|
|
static int body_is_plausible(const char *body, size_t body_len, int purpose);
|
|
@@ -58,7 +57,6 @@ static void dir_routerdesc_download_failed(smartlist_t *failed,
|
|
|
int was_extrainfo,
|
|
|
int was_descriptor_digests);
|
|
|
static void note_request(const char *key, size_t bytes);
|
|
|
-static int client_likes_consensus(networkstatus_t *v, const char *want_url);
|
|
|
|
|
|
/********* START VARIABLES **********/
|
|
|
|
|
@@ -340,13 +338,10 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
|
|
|
/* want to ask a running bridge for which we have a descriptor. */
|
|
|
/* XXX021 we assume that all of our bridges can answer any
|
|
|
* possible directory question. This won't be true forever. -RD */
|
|
|
- /* It certainly is not true with conditional consensus downloading,
|
|
|
- * so, for now, never assume the server supports that. */
|
|
|
routerinfo_t *ri = choose_random_entry(NULL);
|
|
|
if (ri) {
|
|
|
directory_initiate_command(ri->address, ri->addr,
|
|
|
ri->or_port, 0,
|
|
|
- 0, /* don't use conditional consensus url */
|
|
|
1, ri->cache_info.identity_digest,
|
|
|
dir_purpose,
|
|
|
router_purpose,
|
|
@@ -468,7 +463,6 @@ directory_initiate_command_routerstatus(routerstatus_t *status,
|
|
|
}
|
|
|
directory_initiate_command(address, status->addr,
|
|
|
status->or_port, status->dir_port,
|
|
|
- status->version_supports_conditional_consensus,
|
|
|
status->version_supports_begindir,
|
|
|
status->identity_digest,
|
|
|
dir_purpose, router_purpose,
|
|
@@ -650,7 +644,6 @@ directory_command_should_use_begindir(or_options_t *options, uint32_t addr,
|
|
|
void
|
|
|
directory_initiate_command(const char *address, uint32_t addr,
|
|
|
uint16_t or_port, uint16_t dir_port,
|
|
|
- int supports_conditional_consensus,
|
|
|
int supports_begindir, const char *digest,
|
|
|
uint8_t dir_purpose, uint8_t router_purpose,
|
|
|
int anonymized_connection, const char *resource,
|
|
@@ -713,9 +706,7 @@ directory_initiate_command(const char *address, uint32_t addr,
|
|
|
case 0:
|
|
|
/* queue the command on the outbuf */
|
|
|
directory_send_command(conn, dir_purpose, 1, resource,
|
|
|
- payload, payload_len,
|
|
|
- supports_conditional_consensus,
|
|
|
- if_modified_since);
|
|
|
+ payload, payload_len, if_modified_since);
|
|
|
connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
|
|
|
/* writable indicates finish, readable indicates broken link,
|
|
|
error indicates broken link in windowsland. */
|
|
@@ -752,9 +743,7 @@ directory_initiate_command(const char *address, uint32_t addr,
|
|
|
conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
|
|
|
/* queue the command on the outbuf */
|
|
|
directory_send_command(conn, dir_purpose, 0, resource,
|
|
|
- payload, payload_len,
|
|
|
- supports_conditional_consensus,
|
|
|
- if_modified_since);
|
|
|
+ payload, payload_len, if_modified_since);
|
|
|
connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
|
|
|
connection_start_reading(TO_CONN(linked_conn));
|
|
|
}
|
|
@@ -773,63 +762,6 @@ connection_dir_is_encrypted(dir_connection_t *conn)
|
|
|
return TO_CONN(conn)->linked;
|
|
|
}
|
|
|
|
|
|
-/** Helper for sorting
|
|
|
- *
|
|
|
- * sort strings alphabetically
|
|
|
- */
|
|
|
-static int
|
|
|
-_compare_strs(const void **a, const void **b)
|
|
|
-{
|
|
|
- const char *s1 = *a, *s2 = *b;
|
|
|
- return strcmp(s1, s2);
|
|
|
-}
|
|
|
-
|
|
|
-/** Return the URL we should use for a consensus download.
|
|
|
- *
|
|
|
- * This url depends on whether or not the server we go to
|
|
|
- * is sufficiently new to support conditional consensus downloading,
|
|
|
- * i.e. GET .../consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>
|
|
|
- */
|
|
|
-#define CONDITIONAL_CONSENSUS_FPR_LEN 3
|
|
|
-#if (CONDITIONAL_CONSENSUS_FPR_LEN > DIGEST_LEN)
|
|
|
-#error "conditional consensus fingerprint length is larger than digest length
|
|
|
-#endif
|
|
|
-static char *
|
|
|
-directory_get_consensus_url(int supports_conditional_consensus)
|
|
|
-{
|
|
|
- char *url;
|
|
|
- int len;
|
|
|
-
|
|
|
- if (supports_conditional_consensus) {
|
|
|
- char *authority_id_list;
|
|
|
- smartlist_t *authority_digets = smartlist_create();
|
|
|
-
|
|
|
- SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
|
|
|
- trusted_dir_server_t *, ds,
|
|
|
- {
|
|
|
- char *hex = tor_malloc(2*CONDITIONAL_CONSENSUS_FPR_LEN+1);
|
|
|
- base16_encode(hex, 2*CONDITIONAL_CONSENSUS_FPR_LEN+1,
|
|
|
- ds->digest, CONDITIONAL_CONSENSUS_FPR_LEN);
|
|
|
- smartlist_add(authority_digets, hex);
|
|
|
- });
|
|
|
- smartlist_sort(authority_digets, _compare_strs);
|
|
|
- authority_id_list = smartlist_join_strings(authority_digets,
|
|
|
- "+", 0, NULL);
|
|
|
-
|
|
|
- len = strlen(authority_id_list)+64;
|
|
|
- url = tor_malloc(len);
|
|
|
- tor_snprintf(url, len, "/tor/status-vote/current/consensus/%s.z",
|
|
|
- authority_id_list);
|
|
|
-
|
|
|
- SMARTLIST_FOREACH(authority_digets, char *, cp, tor_free(cp));
|
|
|
- smartlist_free(authority_digets);
|
|
|
- tor_free(authority_id_list);
|
|
|
- } else {
|
|
|
- url = tor_strdup("/tor/status-vote/current/consensus.z");
|
|
|
- }
|
|
|
- return url;
|
|
|
-}
|
|
|
-
|
|
|
/** Queue an appropriate HTTP command on conn-\>outbuf. The other args
|
|
|
* are as in directory_initiate_command.
|
|
|
*/
|
|
@@ -837,7 +769,6 @@ static void
|
|
|
directory_send_command(dir_connection_t *conn,
|
|
|
int purpose, int direct, const char *resource,
|
|
|
const char *payload, size_t payload_len,
|
|
|
- int supports_conditional_consensus,
|
|
|
time_t if_modified_since)
|
|
|
{
|
|
|
char proxystring[256];
|
|
@@ -920,10 +851,7 @@ directory_send_command(dir_connection_t *conn,
|
|
|
tor_assert(!resource);
|
|
|
tor_assert(!payload);
|
|
|
httpcommand = "GET";
|
|
|
- url = directory_get_consensus_url(supports_conditional_consensus);
|
|
|
- /* XXX021: downgrade/remove once done with conditional consensus fu */
|
|
|
- log_notice(LD_DIR, "Downloading consensus from %s using %s",
|
|
|
- hoststring, url);
|
|
|
+ url = tor_strdup("/tor/status-vote/current/consensus.z");
|
|
|
break;
|
|
|
case DIR_PURPOSE_FETCH_CERTIFICATE:
|
|
|
tor_assert(resource);
|
|
@@ -2236,58 +2164,6 @@ directory_dump_request_log(void)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-/** Decide whether a client would accept the consensus we have
|
|
|
- *
|
|
|
- * Clients can say they only want a consensus if it's signed by more
|
|
|
- * than half the authorities in a list. They pass this list in
|
|
|
- * the url as "...consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>".
|
|
|
- *
|
|
|
- * <b>fpr<b/> may be an abbreviated fingerprint, i.e. only a left substring
|
|
|
- * of the full authority identity digest. (Only strings of even length,
|
|
|
- * i.e. encodings of full bytes, are handled correctly. In the case
|
|
|
- * of an odd number of hex digits the last one is silently ignored.)
|
|
|
- *
|
|
|
- * Returns 1 if more than half of the requested authorities signed the
|
|
|
- * consensus, 0 otherwise.
|
|
|
- */
|
|
|
-int
|
|
|
-client_likes_consensus(networkstatus_t *v, const char *want_url)
|
|
|
-{
|
|
|
- smartlist_t *want_authorities = smartlist_create();
|
|
|
- int need_at_least;
|
|
|
- int have = 0;
|
|
|
-
|
|
|
- dir_split_resource_into_fingerprints(want_url, want_authorities, NULL, 0, 0);
|
|
|
- need_at_least = smartlist_len(want_authorities)/2+1;
|
|
|
- SMARTLIST_FOREACH(want_authorities, const char *, d, {
|
|
|
- char want_digest[DIGEST_LEN];
|
|
|
- int want_len = strlen(d)/2;
|
|
|
- if (want_len > DIGEST_LEN)
|
|
|
- want_len = DIGEST_LEN;
|
|
|
-
|
|
|
- if (base16_decode(want_digest, DIGEST_LEN, d, want_len*2) < 0) {
|
|
|
- log_warn(LD_DIR,"Failed to decode requested authority digest %s.", d);
|
|
|
- continue;
|
|
|
- };
|
|
|
-
|
|
|
- SMARTLIST_FOREACH(v->voters, networkstatus_voter_info_t *, vi, {
|
|
|
- if (vi->signature &&
|
|
|
- !memcmp(vi->identity_digest, want_digest, want_len)) {
|
|
|
- have++;
|
|
|
- break;
|
|
|
- };
|
|
|
- });
|
|
|
-
|
|
|
- /* early exit, if we already have enough */
|
|
|
- if (have >= need_at_least)
|
|
|
- break;
|
|
|
- });
|
|
|
-
|
|
|
- SMARTLIST_FOREACH(want_authorities, char *, d, tor_free(d));
|
|
|
- smartlist_free(want_authorities);
|
|
|
- return (have >= need_at_least);
|
|
|
-}
|
|
|
-
|
|
|
/** Helper function: called when a dirserver gets a complete HTTP GET
|
|
|
* request. Look for a request for a directory or for a rendezvous
|
|
|
* service descriptor. On finding one, write a response into
|
|
@@ -2415,7 +2291,7 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
|
|
|
}
|
|
|
|
|
|
if (!strcmpstart(url,"/tor/status/")
|
|
|
- || !strcmpstart(url, "/tor/status-vote/current/consensus")) {
|
|
|
+ || !strcmp(url, "/tor/status-vote/current/consensus")) {
|
|
|
/* v2 or v3 network status fetch. */
|
|
|
smartlist_t *dir_fps = smartlist_create();
|
|
|
int is_v3 = !strcmpstart(url, "/tor/status-vote");
|
|
@@ -2436,15 +2312,6 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
|
|
|
} else {
|
|
|
networkstatus_t *v = networkstatus_get_latest_consensus();
|
|
|
time_t now = time(NULL);
|
|
|
- #define CONSENSUS_URL_PREFIX "/tor/status-vote/current/consensus/"
|
|
|
- if (!strcmpstart(url, CONSENSUS_URL_PREFIX) &&
|
|
|
- !client_likes_consensus(v, url + strlen(CONSENSUS_URL_PREFIX))) {
|
|
|
- write_http_status_line(conn, 404, "Consensus not signed by sufficient "
|
|
|
- "number of requested authorities");
|
|
|
- smartlist_free(dir_fps);
|
|
|
- goto done;
|
|
|
- }
|
|
|
-
|
|
|
smartlist_add(dir_fps, tor_memdup("\0\0\0\0\0\0\0\0\0\0"
|
|
|
"\0\0\0\0\0\0\0\0\0\0", 20));
|
|
|
request_type = compressed?"v3.z":"v3";
|