Loading src/or/directory.c +46 −0 Original line number Diff line number Diff line Loading @@ -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 || Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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))", Loading Loading @@ -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"); Loading src/or/dirserv.c +4 −2 Original line number Diff line number Diff line Loading @@ -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)); Loading Loading @@ -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(); Loading src/or/dirvote.c +154 −0 Original line number Diff line number Diff line Loading @@ -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; } src/or/or.h +20 −2 Original line number Diff line number Diff line Loading @@ -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. */ Loading Loading @@ -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 * Loading @@ -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, Loading @@ -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); Loading @@ -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, Loading Loading @@ -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); Loading src/or/router.c +8 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
src/or/directory.c +46 −0 Original line number Diff line number Diff line Loading @@ -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 || Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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))", Loading Loading @@ -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"); Loading
src/or/dirserv.c +4 −2 Original line number Diff line number Diff line Loading @@ -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)); Loading Loading @@ -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(); Loading
src/or/dirvote.c +154 −0 Original line number Diff line number Diff line Loading @@ -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; }
src/or/or.h +20 −2 Original line number Diff line number Diff line Loading @@ -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. */ Loading Loading @@ -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 * Loading @@ -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, Loading @@ -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); Loading @@ -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, Loading Loading @@ -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); Loading
src/or/router.c +8 −0 Original line number Diff line number Diff line Loading @@ -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