diff --git a/src/or/config.c b/src/or/config.c index 168d0dbdea..5b562adc71 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -3008,9 +3008,13 @@ options_validate(or_options_t *old_options, or_options_t *options, REJECT("V3AuthVoteDelay and V3AuthDistDelay must be no more than half " "V3AuthVotingInterval"); } - if (options->V3AuthNIntervalsValid < 2) { + if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS) + REJECT("V3AuthVoteDelay is way too low."); + if (options->V3AuthDistDelay < MIN_DIST_SECONDS) + REJECT("V3AuthDistDelay is way too low."); + + if (options->V3AuthNIntervalsValid < 2) REJECT("V3AuthNIntervalsValid must be at least 2."); - } if (options->V3AuthVotingInterval < 300) { REJECT("V3AuthVotingInterval is insanely low."); diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 0827406202..ed3a15061c 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1979,6 +1979,9 @@ generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, (timing.vote_interval * timing.n_intervals_valid); v3_out->vote_seconds = timing.vote_delay; v3_out->dist_seconds = timing.dist_delay; + tor_assert(v3_out->vote_seconds > 0); + tor_assert(v3_out->dist_seconds > 0); + tor_assert(timing.n_intervals_valid > 0); v3_out->client_versions = client_versions; v3_out->server_versions = server_versions; diff --git a/src/or/dirvote.c b/src/or/dirvote.c index 760945c2d2..7416083c75 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -107,7 +107,7 @@ _compare_ints(const void **_a, const void **_b) } /** Given a list of one or more time_t*, return the (low) median. */ -static time_t +/*static*/ time_t median_time(smartlist_t *times) { int idx; @@ -118,7 +118,7 @@ median_time(smartlist_t *times) } /** Given a list of one or more int*, return the (low) median. */ -static int +/*static*/ int median_int(smartlist_t *ints) { int idx; @@ -365,6 +365,19 @@ networkstatus_compute_consensus(smartlist_t *votes, vote_seconds = median_int(votesec_list); dist_seconds = median_int(distsec_list); + /* + SMARTLIST_FOREACH(va_times, int*, i, + printf("VA: %d\n", *i)); + SMARTLIST_FOREACH(fu_times, int*, i, + printf("FU: %d\n", *i)); + printf("%d..%d\n", (int)valid_after, (int)valid_until); + */ + + tor_assert(valid_after+MIN_VOTE_INTERVAL <= fresh_until); + tor_assert(fresh_until+MIN_VOTE_INTERVAL <= valid_until); + tor_assert(vote_seconds >= MIN_VOTE_SECONDS); + tor_assert(dist_seconds >= MIN_DIST_SECONDS); + for (j = 0; j < 2; ++j) { smartlist_t *lst = j ? combined_server_versions : combined_client_versions; @@ -1234,7 +1247,7 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out) goto err; } tor_assert(smartlist_len(vote->voters) == 1); - vi = smartlist_get(vote->voters, 0); + vi = get_voter(vote); tor_assert(vi->good_signature == 1); ds = trusteddirserver_get_by_v3_auth_digest(vi->identity_digest); if (!ds || !(ds->type & V3_AUTHORITY)) { @@ -1260,7 +1273,7 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out) if (! memcmp(v->vote->cert->cache_info.identity_digest, vote->cert->cache_info.identity_digest, DIGEST_LEN)) { - networkstatus_voter_info_t *vi_old = smartlist_get(v->vote->voters, 0); + networkstatus_voter_info_t *vi_old = get_voter(v->vote); if (!memcmp(vi_old->vote_digest, vi->vote_digest, DIGEST_LEN)) { /* Ah, it's the same vote. Not a problem. */ log_info(LD_DIR, "Discarding a vote we already have."); diff --git a/src/or/or.h b/src/or/or.h index f6d7907a90..163b7a4d24 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2824,6 +2824,13 @@ format_networkstatus_vote(crypto_pk_env_t *private_key, /********************************* dirvote.c ************************/ +/* XXXX020 enforce */ +/* XXXX020 document in dir-spec.txt */ +/*DOCDOC*/ +#define MIN_VOTE_SECONDS 20 +#define MIN_DIST_SECONDS 20 +#define MIN_VOTE_INTERVAL 300 + void dirvote_free_all(void); /* vote manipulation */ @@ -2873,6 +2880,8 @@ int dirvote_add_signatures(const char *detached_signatures_body); int dirvote_publish_consensus(void); #ifdef DIRVOTE_PRIVATE +time_t median_time(smartlist_t *times); +int median_int(smartlist_t *times); int networkstatus_check_voter_signature(networkstatus_vote_t *consensus, networkstatus_voter_info_t *voter, authority_cert_t *cert); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index c9a231485f..ccf3e38ddb 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -1874,6 +1874,22 @@ networkstatus_parse_vote_from_string(const char *s, int is_vote) (int) tor_parse_long(tok->args[1], 10, 0, INT_MAX, &ok, NULL); if (!ok) goto err; + if (ns->valid_after + MIN_VOTE_INTERVAL > ns->fresh_until) { + log_warn(LD_DIR, "Vote/consensus freshness interval is too short"); + goto err; + } + if (ns->valid_after + MIN_VOTE_INTERVAL*2 > ns->valid_until) { + log_warn(LD_DIR, "Vote/consensus liveness interval is too short"); + goto err; + } + if (ns->vote_seconds < MIN_VOTE_SECONDS) { + log_warn(LD_DIR, "Vote seconds is too short"); + goto err; + } + if (ns->dist_seconds < MIN_DIST_SECONDS) { + log_warn(LD_DIR, "Dist seconds is too short"); + goto err; + } if ((tok = find_first_by_keyword(tokens, K_CLIENT_VERSIONS))) { ns->client_versions = tok->args[0]; diff --git a/src/or/test.c b/src/or/test.c index f2e38537c2..e10ebc2d27 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -2390,6 +2390,45 @@ test_same_voter(networkstatus_voter_info_t *v1, test_memeq(v1->vote_digest, v2->vote_digest, DIGEST_LEN); } +static void +test_dirvote_helpers(void) +{ + smartlist_t *sl = smartlist_create(); + int a=12,b=24,c=25,d=60,e=77; + time_t v=99, w=150, x=700, y=1000, z=time(NULL); + + test_assert(yis_vote = 1; vote->published = now; - vote->valid_after = now+100; - vote->fresh_until = now+200; - vote->valid_until = now+300; + vote->valid_after = now+1000; + vote->fresh_until = now+2000; + vote->valid_until = now+3000; vote->vote_seconds = 100; vote->dist_seconds = 200; vote->client_versions = tor_strdup("0.1.2.14,0.1.2.15"); @@ -2560,7 +2599,7 @@ test_v3_networkstatus(void) /* Generate second vote. It disagrees on some of the times, * and doesn't list versions, and knows some crazy flags */ vote->published = now+1; - vote->fresh_until = now+205; + vote->fresh_until = now+3005; vote->dist_seconds = 300; authority_cert_free(vote->cert); vote->cert = authority_cert_dup(cert2); @@ -2598,7 +2637,7 @@ test_v3_networkstatus(void) /* Generate the third vote. */ vote->published = now; - vote->fresh_until = now+203; + vote->fresh_until = now+2003; vote->dist_seconds = 250; authority_cert_free(vote->cert); vote->cert = authority_cert_dup(cert3); @@ -2639,9 +2678,9 @@ test_v3_networkstatus(void) /* Check consensus contents. */ test_assert(!con->is_vote); test_eq(con->published, 0); /* this field only appears in votes. */ - test_eq(con->valid_after, now+100); - test_eq(con->fresh_until, now+203); /* median */ - test_eq(con->valid_until, now+300); + test_eq(con->valid_after, now+1000); + test_eq(con->fresh_until, now+2003); /* median */ + test_eq(con->valid_until, now+3000); test_eq(con->vote_seconds, 100); test_eq(con->dist_seconds, 250); /* median */ test_streq(con->client_versions, "0.1.2.14"); @@ -3130,6 +3169,8 @@ main(int c, char**v) test_mmap(); puts("\n--threads"); test_threads(); + puts("\n--dirvote-helpers"); + test_dirvote_helpers(); puts("\n========================= Onion Skins ====================="); test_onion_handshake(); puts("\n========================= Directory Formats ===============");