mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
r13902@catbus: nickm | 2007-07-25 17:43:52 -0400
Some dirvote code to handle generating votes and slinging them around. More code is still needed. svn:r10927
This commit is contained in:
parent
1b7a704c34
commit
a66f259354
@ -78,6 +78,7 @@ purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
|
||||
return 1; /* if we have to ask, better make it anonymous */
|
||||
if (dir_purpose == DIR_PURPOSE_FETCH_DIR ||
|
||||
dir_purpose == DIR_PURPOSE_UPLOAD_DIR ||
|
||||
dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
|
||||
dir_purpose == DIR_PURPOSE_FETCH_RUNNING_LIST ||
|
||||
dir_purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS ||
|
||||
dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
|
||||
@ -501,6 +502,9 @@ directory_initiate_command(const char *address, uint32_t addr,
|
||||
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_FETCH_RUNNING_LIST:
|
||||
log_debug(LD_DIR,"initiating running-routers fetch");
|
||||
break;
|
||||
@ -685,6 +689,12 @@ directory_send_command(dir_connection_t *conn,
|
||||
httpcommand = "POST";
|
||||
url = tor_strdup("/tor/");
|
||||
break;
|
||||
case DIR_PURPOSE_UPLOAD_VOTE:
|
||||
tor_assert(!resource);
|
||||
tor_assert(payload);
|
||||
httpcommand = "POST";
|
||||
url = tor_strdup("/tor/post/vote");
|
||||
break;
|
||||
case DIR_PURPOSE_FETCH_RENDDESC:
|
||||
tor_assert(resource);
|
||||
tor_assert(!payload);
|
||||
@ -1367,6 +1377,30 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
|
||||
* dirservers down just because they don't like us. */
|
||||
}
|
||||
|
||||
if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_VOTE) {
|
||||
switch (status_code) {
|
||||
case 200: {
|
||||
log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d",
|
||||
conn->_base.address, conn->_base.port);
|
||||
}
|
||||
break;
|
||||
case 400:
|
||||
log_warn(LD_GENERAL,"http status 400 (%s) response after uploading "
|
||||
"vote to dirserver '%s:%d'. Please correct.",
|
||||
escaped(reason), conn->_base.address, conn->_base.port);
|
||||
break;
|
||||
default:
|
||||
log_warn(LD_GENERAL,
|
||||
"http status %d (%s) reason unexpected while uploading "
|
||||
"vote to server '%s:%d').",
|
||||
status_code, escaped(reason), conn->_base.address,
|
||||
conn->_base.port);
|
||||
break;
|
||||
}
|
||||
/* return 0 in all cases, since we don't want to mark any
|
||||
* dirservers down just because they don't like us. */
|
||||
}
|
||||
|
||||
if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
|
||||
log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
|
||||
"(%s))",
|
||||
@ -2075,6 +2109,18 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers,
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (authdir_mode_v3(options) &&
|
||||
!strcmp(url,"/tor/post/vote")) { /* server descriptor post */
|
||||
const char *msg = "OK";
|
||||
if (dirserv_add_vote(body, &msg)) {
|
||||
write_http_status_line(conn, 200, "Vote stored");
|
||||
} else {
|
||||
tor_assert(msg);
|
||||
write_http_status_line(conn, 400, msg);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* we didn't recognize the url */
|
||||
write_http_status_line(conn, 404, "Not found");
|
||||
|
||||
|
@ -1116,7 +1116,7 @@ cached_dir_decref(cached_dir_t *d)
|
||||
|
||||
/** Allocate and return a new cached_dir_t containing the string <b>s</b>,
|
||||
* published at <b>published</b>. */
|
||||
static cached_dir_t *
|
||||
cached_dir_t *
|
||||
new_cached_dir(char *s, time_t published)
|
||||
{
|
||||
cached_dir_t *d = tor_malloc_zero(sizeof(cached_dir_t));
|
||||
@ -2075,7 +2075,9 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
|
||||
return status;
|
||||
}
|
||||
|
||||
static cached_dir_t *
|
||||
/** DOCDOC */
|
||||
/* XXXX020 possibly rename and relocate to dirvote.c? */
|
||||
cached_dir_t *
|
||||
generate_v3_networkstatus(void)
|
||||
{
|
||||
crypto_pk_env_t *key = get_my_v3_authority_signing_key();
|
||||
|
154
src/or/dirvote.c
154
src/or/dirvote.c
@ -866,3 +866,157 @@ dirvote_recalculate_timing(time_t now)
|
||||
voting_schedule.voting_starts = start - vote_delay - dist_delay;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
typedef struct pending_vote_t {
|
||||
cached_dir_t *vote_body;
|
||||
networkstatus_vote_t *vote;
|
||||
} pending_vote_t;
|
||||
|
||||
/** DOCDOC */
|
||||
static smartlist_t *pending_vote_list = NULL;
|
||||
/** DOCDOC */
|
||||
static char *pending_consensus_body = NULL;
|
||||
|
||||
/** DOCDOC */
|
||||
void
|
||||
dirvote_perform_vote(void)
|
||||
{
|
||||
cached_dir_t *new_vote = generate_v3_networkstatus();
|
||||
pending_vote_t *pending_vote;
|
||||
const char *msg = "";
|
||||
|
||||
if ((pending_vote = dirvote_add_vote(tor_memdup(new_vote->dir,
|
||||
new_vote->dir_len), &msg))) {
|
||||
log_warn(LD_DIR, "Couldn't store my own vote! (I told myself, '%s'.)",
|
||||
msg);
|
||||
return;
|
||||
}
|
||||
|
||||
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_VOTE,
|
||||
ROUTER_PURPOSE_GENERAL,
|
||||
V3_AUTHORITY,
|
||||
pending_vote->vote_body->dir,
|
||||
pending_vote->vote_body->dir_len, 0);
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
void
|
||||
dirvote_clear_pending_votes(void)
|
||||
{
|
||||
if (!pending_vote_list)
|
||||
return;
|
||||
SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, {
|
||||
cached_dir_decref(v->vote_body);
|
||||
v->vote_body = NULL;
|
||||
networkstatus_vote_free(v->vote);
|
||||
tor_free(v);
|
||||
});
|
||||
smartlist_clear(pending_vote_list);
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
pending_vote_t *
|
||||
dirvote_add_vote(char *vote_body, const char **msg_out)
|
||||
{
|
||||
networkstatus_vote_t *vote;
|
||||
networkstatus_voter_info_t *vi;
|
||||
trusted_dir_server_t *ds;
|
||||
pending_vote_t *pending_vote = NULL;
|
||||
tor_assert(vote_body);
|
||||
tor_assert(msg_out);
|
||||
|
||||
if (!pending_vote_list)
|
||||
pending_vote_list = smartlist_create();
|
||||
*msg_out = NULL;
|
||||
|
||||
vote = networkstatus_parse_vote_from_string(vote_body, 1);
|
||||
if (!vote) {
|
||||
*msg_out = "Unable to parse vote";
|
||||
goto err;
|
||||
}
|
||||
tor_assert(smartlist_len(vote->voters) == 1);
|
||||
vi = smartlist_get(vote->voters, 0);
|
||||
tor_assert(vi->good_signature == 1);
|
||||
ds = trusteddirserver_get_by_v3_auth_digest(vi->identity_digest);
|
||||
if (!ds || !(ds->type & V3_AUTHORITY)) {
|
||||
*msg_out = "Vote not from a recognized v3 authority";
|
||||
goto err;
|
||||
}
|
||||
/* XXXX020 check times; make sure epochs match. */
|
||||
|
||||
SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, {
|
||||
if (! memcmp(v->vote->cert->cache_info.identity_digest,
|
||||
vote->cert->cache_info.identity_digest,
|
||||
DIGEST_LEN)) {
|
||||
log_notice(LD_DIR, "We already have a pending vote from this dir");
|
||||
if (v->vote->published < vote->published) {
|
||||
cached_dir_decref(v->vote_body);
|
||||
networkstatus_vote_free(v->vote);
|
||||
v->vote_body = new_cached_dir(vote_body, vote->published);
|
||||
v->vote = vote;
|
||||
*msg_out = "ok";
|
||||
return v;
|
||||
} else {
|
||||
*msg_out = "Already have a newer pending vote";
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
pending_vote = tor_malloc_zero(sizeof(pending_vote_t));
|
||||
pending_vote->vote_body = new_cached_dir(vote_body, vote->published);
|
||||
pending_vote->vote = vote;
|
||||
smartlist_add(pending_vote_list, pending_vote);
|
||||
|
||||
*msg_out = "ok";
|
||||
return pending_vote;
|
||||
err:
|
||||
tor_free(vote_body);
|
||||
if (vote)
|
||||
networkstatus_vote_free(vote);
|
||||
if (!*msg_out)
|
||||
*msg_out = "Error adding vote";
|
||||
/*XXXX020 free other fields */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
int
|
||||
dirvote_compute_consensus(void)
|
||||
{
|
||||
/* Have we got enough votes to try? */
|
||||
int n_votes, n_voters;
|
||||
smartlist_t *votes = NULL;
|
||||
char *consensus_body = NULL;
|
||||
authority_cert_t *my_cert;
|
||||
|
||||
if (!pending_vote_list)
|
||||
pending_vote_list = smartlist_create();
|
||||
|
||||
n_voters = get_n_authorities(V3_AUTHORITY);
|
||||
n_votes = smartlist_len(pending_vote_list);
|
||||
/* XXXX020 see if there are enough to go ahead. */
|
||||
|
||||
if (!(my_cert = get_my_v3_authority_cert())) {
|
||||
log_warn(LD_DIR, "Can't generate consensus without a certificate.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
votes = smartlist_create();
|
||||
SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v,
|
||||
smartlist_add(votes, v->vote));
|
||||
|
||||
consensus_body = networkstatus_compute_consensus(
|
||||
votes, n_voters,
|
||||
my_cert->identity_key,
|
||||
get_my_v3_authority_signing_key());
|
||||
|
||||
tor_free(pending_consensus_body);
|
||||
pending_consensus_body = consensus_body;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
if (votes)
|
||||
smartlist_free(votes);
|
||||
return -1;
|
||||
}
|
||||
|
22
src/or/or.h
22
src/or/or.h
@ -368,9 +368,14 @@ typedef enum {
|
||||
/** A connection to a directory server: upload a rendezvous
|
||||
* descriptor. */
|
||||
#define DIR_PURPOSE_UPLOAD_RENDDESC 9
|
||||
/** A connection to a directory server: upload a v3 networkstatus vote. */
|
||||
#define DIR_PURPOSE_UPLOAD_VOTE 10
|
||||
/** A connection to a directory server: fetch a v3 networkstatus vote. */
|
||||
#define DIR_PURPOSE_FETCH_VOTE 11
|
||||
|
||||
/** Purpose for connection at a directory server. */
|
||||
#define DIR_PURPOSE_SERVER 10
|
||||
#define _DIR_PURPOSE_MAX 10
|
||||
#define DIR_PURPOSE_SERVER 12
|
||||
#define _DIR_PURPOSE_MAX 12
|
||||
|
||||
#define _EXIT_PURPOSE_MIN 1
|
||||
/** This exit stream wants to do an ordinary connect. */
|
||||
@ -2765,6 +2770,9 @@ int routerstatus_format_entry(char *buf, size_t buf_len,
|
||||
int first_line_only);
|
||||
void dirserv_free_all(void);
|
||||
void cached_dir_decref(cached_dir_t *d);
|
||||
cached_dir_t *new_cached_dir(char *s, time_t published);
|
||||
|
||||
cached_dir_t *generate_v3_networkstatus(void);
|
||||
|
||||
#ifdef DIRSERV_PRIVATE
|
||||
char *
|
||||
@ -2774,6 +2782,7 @@ format_networkstatus_vote(crypto_pk_env_t *private_key,
|
||||
|
||||
/********************************* dirvote.c ************************/
|
||||
|
||||
/* vote manipulation */
|
||||
void networkstatus_vote_free(networkstatus_vote_t *ns);
|
||||
char *networkstatus_compute_consensus(smartlist_t *votes,
|
||||
int total_authorities,
|
||||
@ -2784,6 +2793,7 @@ networkstatus_voter_info_t *networkstatus_get_voter_by_id(
|
||||
const char *identity);
|
||||
int networkstatus_check_consensus_signature(networkstatus_vote_t *consensus);
|
||||
|
||||
/* cert manipulation */
|
||||
void authority_cert_free(authority_cert_t *cert);
|
||||
authority_cert_t *authority_cert_dup(authority_cert_t *cert);
|
||||
|
||||
@ -2794,10 +2804,17 @@ typedef struct vote_timing_t {
|
||||
int vote_delay;
|
||||
int dist_delay;
|
||||
} vote_timing_t;
|
||||
/* vote scheduling */
|
||||
void dirvote_get_preferred_voting_intervals(vote_timing_t *timing_out);
|
||||
time_t dirvote_get_start_of_next_interval(time_t now, int interval);
|
||||
void dirvote_recalculate_timing(time_t now);
|
||||
|
||||
/* invoked on timers and by outside triggers. */
|
||||
void dirvote_perform_vote(void);
|
||||
void dirvote_clear_pending_votes(void);
|
||||
struct pending_vote_t * dirvote_add_vote(char *vote_body,const char **msg_out);
|
||||
int dirvote_compute_consensus(void);
|
||||
|
||||
#ifdef DIRVOTE_PRIVATE
|
||||
int networkstatus_check_voter_signature(networkstatus_vote_t *consensus,
|
||||
networkstatus_voter_info_t *voter,
|
||||
@ -3187,6 +3204,7 @@ void router_perform_bandwidth_test(int num_circs, time_t now);
|
||||
int authdir_mode(or_options_t *options);
|
||||
int authdir_mode_v1(or_options_t *options);
|
||||
int authdir_mode_v2(or_options_t *options);
|
||||
int authdir_mode_v3(or_options_t *options);
|
||||
int authdir_mode_handles_descs(or_options_t *options);
|
||||
int authdir_mode_publishes_statuses(or_options_t *options);
|
||||
int authdir_mode_tests_reachability(or_options_t *options);
|
||||
|
@ -714,6 +714,14 @@ authdir_mode_v2(or_options_t *options)
|
||||
{
|
||||
return authdir_mode(options) && options->V2AuthoritativeDir != 0;
|
||||
}
|
||||
/** Return true iff we believe ourselves to be a v3 authoritative
|
||||
* directory server.
|
||||
*/
|
||||
int
|
||||
authdir_mode_v3(or_options_t *options)
|
||||
{
|
||||
return authdir_mode(options) && options->V3AuthoritativeDir != 0;
|
||||
}
|
||||
/** Return true iff we are an authoritative directory server that
|
||||
* is willing to receive or serve descriptors on its dirport.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user