diff --git a/doc/spec/dir-spec.txt b/doc/spec/dir-spec.txt index 4342a67f01..b95f23531b 100644 --- a/doc/spec/dir-spec.txt +++ b/doc/spec/dir-spec.txt @@ -1139,7 +1139,7 @@ $Id$ An authority SHOULD publish its vote immediately at the start of each voting period (minus VoteSeconds+DistSeconds). It does this by making it available at - http:///tor/status-vote/current/authority.z + http:///tor/status-vote/next/authority.z and sending it in an HTTP POST request to each other authority at the URL http:///tor/post/vote @@ -1149,7 +1149,7 @@ $Id$ Once an authority has a vote from another authority, it makes it available at - http:///tor/status-vote/current/.z + http:///tor/status-vote/next/.z where is the fingerprint of the other authority's identity key. The consensus status, along with as many signatures as the server diff --git a/src/or/directory.c b/src/or/directory.c index 32b33eec66..1813721cbb 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -86,6 +86,10 @@ purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose) dir_purpose == DIR_PURPOSE_UPLOAD_SIGNATURES || dir_purpose == DIR_PURPOSE_FETCH_RUNNING_LIST || dir_purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS || + dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE || + dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES || + dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS || + dir_purpose == DIR_PURPOSE_FETCH_CERTIFICATE || dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC || dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO) return 0; @@ -115,6 +119,46 @@ authority_type_to_string(authority_type_t auth) return result; } +/** Return a string describing a given directory connection purpose. */ +static const char * +dir_conn_purpose_to_string(int purpose) +{ + switch (purpose) + { + case DIR_PURPOSE_FETCH_DIR: + return "v1 directory fetch"; + case DIR_PURPOSE_FETCH_RENDDESC: + return "hidden-service descriptor fetch"; + case DIR_PURPOSE_UPLOAD_DIR: + return "server descriptor upload"; + case DIR_PURPOSE_UPLOAD_RENDDESC: + return "hidden-service descriptor upload"; + case DIR_PURPOSE_UPLOAD_VOTE: + return "server vote upload"; + case DIR_PURPOSE_UPLOAD_SIGNATURES: + return "consensus signature upload"; + case DIR_PURPOSE_FETCH_RUNNING_LIST: + return "running-routers fetch"; + case DIR_PURPOSE_FETCH_NETWORKSTATUS: + return "network-status fetch"; + case DIR_PURPOSE_FETCH_SERVERDESC: + return "server descriptor fetch"; + case DIR_PURPOSE_FETCH_EXTRAINFO: + return "extra-info fetch"; + case DIR_PURPOSE_FETCH_CONSENSUS: + return "consensus network-status fetch"; + case DIR_PURPOSE_FETCH_CERTIFICATE: + return "authority cert fetch"; + case DIR_PURPOSE_FETCH_STATUS_VOTE: + return "status vote fetch"; + case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES: + return "consensus signature fetch"; + } + + log_warn(LD_BUG, "Called with unknown purpose %d", purpose); + return "(unknown)"; +} + /** Return true iff identity_digest is the digest of a router we * believe to support extrainfo downloads. (If is_authority we do * additional checking that's only valid for authorities.) */ @@ -234,6 +278,12 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, case DIR_PURPOSE_FETCH_RENDDESC: type = HIDSERV_AUTHORITY; break; + case DIR_PURPOSE_FETCH_STATUS_VOTE: + case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES: + case DIR_PURPOSE_FETCH_CONSENSUS: + case DIR_PURPOSE_FETCH_CERTIFICATE: + type = V3_AUTHORITY; + break; default: log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose); return; @@ -267,18 +317,8 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, rs = router_pick_directory_server(1, 1, type, retry_if_no_servers); if (!rs) { - const char *which; - if (dir_purpose == DIR_PURPOSE_FETCH_DIR) - which = "directory"; - else if (dir_purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) - which = "status list"; - else if (dir_purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) - which = "network status"; - else // if (dir_purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) - which = "server descriptors"; - log_info(LD_DIR, - "No router found for %s; falling back to dirserver list", - which); + log_info(LD_DIR, "No router found for %s; falling back to " + "dirserver list.", dir_conn_purpose_to_string(dir_purpose)); rs = router_pick_trusteddirserver(type, 1, 1, retry_if_no_servers); if (!rs) @@ -410,6 +450,8 @@ connection_dir_request_failed(dir_connection_t *conn) log_info(LD_DIR, "Giving up on directory server at '%s'; retrying", conn->_base.address); connection_dir_download_routerdesc_failed(conn); + } else { + /* XXXX020 handle failing: votes. signatures. certificates. consensus. */ } } @@ -494,41 +536,7 @@ directory_initiate_command(const char *address, uint32_t addr, log_debug(LD_DIR, "anonymized %d, want_to_tunnel %d.", anonymized_connection, want_to_tunnel); - switch (dir_purpose) { - case DIR_PURPOSE_FETCH_DIR: - log_debug(LD_DIR,"initiating directory fetch"); - break; - case DIR_PURPOSE_FETCH_RENDDESC: - log_debug(LD_DIR,"initiating hidden-service descriptor fetch"); - break; - case DIR_PURPOSE_UPLOAD_DIR: - log_debug(LD_OR,"initiating server descriptor upload"); - break; - case DIR_PURPOSE_UPLOAD_RENDDESC: - log_debug(LD_REND,"initiating hidden-service descriptor upload"); - break; - case DIR_PURPOSE_UPLOAD_VOTE: - log_debug(LD_OR,"initiating server vote upload"); - break; - case DIR_PURPOSE_UPLOAD_SIGNATURES: - log_debug(LD_OR,"initiating consensus signature upload"); - break; - case DIR_PURPOSE_FETCH_RUNNING_LIST: - log_debug(LD_DIR,"initiating running-routers fetch"); - break; - case DIR_PURPOSE_FETCH_NETWORKSTATUS: - log_debug(LD_DIR,"initiating network-status fetch"); - break; - case DIR_PURPOSE_FETCH_SERVERDESC: - log_debug(LD_DIR,"initiating server descriptor fetch"); - break; - case DIR_PURPOSE_FETCH_EXTRAINFO: - log_debug(LD_DIR,"initiating extra-info fetch"); - break; - default: - log_err(LD_BUG, "Unrecognized directory connection purpose."); - tor_assert(0); - } + log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose)); conn = TO_DIR_CONN(connection_new(CONN_TYPE_DIR, AF_INET)); @@ -679,6 +687,34 @@ directory_send_command(dir_connection_t *conn, url = tor_malloc(len); tor_snprintf(url, len, "/tor/status/%s", resource); break; + case DIR_PURPOSE_FETCH_CONSENSUS: + tor_assert(!resource); + tor_assert(!payload); + httpcommand = "GET"; + url = tor_strdup("/tor/status-vote/current/consensus.z"); + break; + case DIR_PURPOSE_FETCH_CERTIFICATE: + tor_assert(resource); + tor_assert(!payload); + httpcommand = "GET"; + len = strlen(resource)+32; + url = tor_malloc(len); + tor_snprintf(url, len, "/tor/keys/%s", resource); + break; + case DIR_PURPOSE_FETCH_STATUS_VOTE: + tor_assert(resource); + tor_assert(!payload); + httpcommand = "GET"; + len = strlen(resource)+32; + url = tor_malloc(len); + tor_snprintf(url, len, "/tor/status-vote/next/%s", resource); + break; + case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES: + tor_assert(!resource); + tor_assert(!payload); + httpcommand = "GET"; + url = tor_strdup("/tor/status-vote/next/consensus-signatures.z"); + break; case DIR_PURPOSE_FETCH_SERVERDESC: httpcommand = "GET"; len = strlen(resource)+32; @@ -1258,6 +1294,19 @@ connection_dir_client_reached_eof(dir_connection_t *conn) } } + if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) { + /*XXXX020*/; + } + if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) { + /*XXXX020*/; + } + if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) { + /*XXXX020*/; + } + if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) { + /*XXXX020*/; + } + if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC || conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) { int was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO; @@ -1953,17 +2002,17 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, * since it wants to be spooled. */ if ((item = dirvote_get_pending_consensus())) smartlist_add(items, (char*)item); - } else if (current && !strcmp(url, "consensus-signatures")) { + } else if (!current && !strcmp(url, "consensus-signatures")) { /* XXXX020 the spec says that we should implement * currrent/consensus-signatures too. Why? */ const char *item; if ((item=dirvote_get_pending_detached_signatures())) smartlist_add(items, (char*)item); - } else if (current && !strcmp(url, "authority")) { + } else if (!current && !strcmp(url, "authority")) { const cached_dir_t *d; if ((d=dirvote_get_vote(NULL))) smartlist_add(dir_items, (cached_dir_t*)d); - } else if (current) { + } else if (!current) { const cached_dir_t *d; smartlist_t *fps = smartlist_create(); dir_split_resource_into_fingerprints(url, fps, NULL, 1, 1); diff --git a/src/or/or.h b/src/or/or.h index 24dfe99951..ebaa0546a9 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -381,10 +381,22 @@ typedef enum { #define DIR_PURPOSE_FETCH_VOTE 11 /** A connection to a directory server: upload a v3 consensus signature */ #define DIR_PURPOSE_UPLOAD_SIGNATURES 12 +/** A connection to a directory server: download one or more network-status + * objects */ +#define DIR_PURPOSE_FETCH_STATUS_VOTE 13 +/** A connection to a directory server: download one or more network-status + * objects */ +#define DIR_PURPOSE_FETCH_DETACHED_SIGNATURES 14 +/** A connection to a directory server: download one or more network-status + * objects */ +#define DIR_PURPOSE_FETCH_CONSENSUS 15 +/** A connection to a directory server: download one or more network-status + * objects */ +#define DIR_PURPOSE_FETCH_CERTIFICATE 16 /** Purpose for connection at a directory server. */ -#define DIR_PURPOSE_SERVER 13 -#define _DIR_PURPOSE_MAX 13 +#define DIR_PURPOSE_SERVER 17 +#define _DIR_PURPOSE_MAX 17 #define _EXIT_PURPOSE_MIN 1 /** This exit stream wants to do an ordinary connect. */ @@ -393,7 +405,7 @@ typedef enum { #define EXIT_PURPOSE_RESOLVE 2 #define _EXIT_PURPOSE_MAX 2 -/* !!!! If any connection purpose is ever over over 15, we must grow the type +/* !!!! If any connection purpose is ever over over 31, we must grow the type * field in connection_t. */ /** Circuit state: I'm the origin, still haven't done all my handshakes. */ @@ -763,7 +775,7 @@ typedef struct connection_t { uint8_t state; /**< Current state of this connection. */ uint8_t type:4; /**< What kind of connection is this? */ - uint8_t purpose:4; /**< Only used for DIR and EXIT types currently. */ + uint8_t purpose:5; /**< Only used for DIR and EXIT types currently. */ /* The next fields are all one-bit booleans. Some are only applicable to * connection subtypes, but we hold them here anyway, to save space.