Do not show policy and bw in v2 statuses
[tor/rransom.git] / src / or / dirvote.c
blobb704a94f0876605d7ae481fb7869817591b1bea7
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2008, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 /* $Id$ */
6 const char dirvote_c_id[] =
7 "$Id$";
9 #define DIRVOTE_PRIVATE
10 #include "or.h"
12 /**
13 * \file dirvote.c
14 * \brief Functions to compute directory consensus, and schedule voting.
15 **/
17 static int dirvote_add_signatures_to_pending_consensus(
18 const char *detached_signatures_body,
19 const char **msg_out);
20 static char *list_v3_auth_ids(void);
21 static void dirvote_fetch_missing_votes(void);
22 static void dirvote_fetch_missing_signatures(void);
23 static int dirvote_perform_vote(void);
24 static void dirvote_clear_votes(int all_votes);
25 static int dirvote_compute_consensus(void);
26 static int dirvote_publish_consensus(void);
28 /* =====
29 * Voting
30 * =====*/
32 /** Return a new string containing the string representation of the vote in
33 * <b>v3_ns</b>, signed with our v3 signing key <b>private_signing_key</b>.
34 * For v3 authorities. */
35 char *
36 format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
37 networkstatus_t *v3_ns)
39 size_t len;
40 char *status = NULL;
41 const char *client_versions = NULL, *server_versions = NULL;
42 char *outp, *endp;
43 char fingerprint[FINGERPRINT_LEN+1];
44 char ipaddr[INET_NTOA_BUF_LEN];
45 char digest[DIGEST_LEN];
46 struct in_addr in;
47 uint32_t addr;
48 routerlist_t *rl = router_get_routerlist();
49 char *version_lines = NULL;
50 networkstatus_voter_info_t *voter;
52 tor_assert(private_signing_key);
53 tor_assert(v3_ns->type == NS_TYPE_VOTE || v3_ns->type == NS_TYPE_OPINION);
55 voter = smartlist_get(v3_ns->voters, 0);
57 addr = voter->addr;
58 in.s_addr = htonl(addr);
59 tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
61 base16_encode(fingerprint, sizeof(fingerprint),
62 v3_ns->cert->cache_info.identity_digest, DIGEST_LEN);
63 client_versions = v3_ns->client_versions;
64 server_versions = v3_ns->server_versions;
66 if (client_versions || server_versions) {
67 size_t v_len = 64;
68 char *cp;
69 if (client_versions)
70 v_len += strlen(client_versions);
71 if (server_versions)
72 v_len += strlen(server_versions);
73 version_lines = tor_malloc(v_len);
74 cp = version_lines;
75 if (client_versions) {
76 tor_snprintf(cp, v_len-(cp-version_lines),
77 "client-versions %s\n", client_versions);
78 cp += strlen(cp);
80 if (server_versions)
81 tor_snprintf(cp, v_len-(cp-version_lines),
82 "server-versions %s\n", server_versions);
83 } else {
84 version_lines = tor_strdup("");
87 len = 8192;
88 len += strlen(version_lines);
89 len += (RS_ENTRY_LEN)*smartlist_len(rl->routers);
90 len += v3_ns->cert->cache_info.signed_descriptor_len;
92 status = tor_malloc(len);
94 char published[ISO_TIME_LEN+1];
95 char va[ISO_TIME_LEN+1];
96 char fu[ISO_TIME_LEN+1];
97 char vu[ISO_TIME_LEN+1];
98 char *flags = smartlist_join_strings(v3_ns->known_flags, " ", 0, NULL);
99 authority_cert_t *cert = v3_ns->cert;
100 format_iso_time(published, v3_ns->published);
101 format_iso_time(va, v3_ns->valid_after);
102 format_iso_time(fu, v3_ns->fresh_until);
103 format_iso_time(vu, v3_ns->valid_until);
105 tor_assert(cert);
106 tor_snprintf(status, len,
107 "network-status-version 3\n"
108 "vote-status %s\n"
109 "consensus-methods 1 2 3 4\n"
110 "published %s\n"
111 "valid-after %s\n"
112 "fresh-until %s\n"
113 "valid-until %s\n"
114 "voting-delay %d %d\n"
115 "%s" /* versions */
116 "known-flags %s\n"
117 "dir-source %s %s %s %s %d %d\n"
118 "contact %s\n",
119 v3_ns->type == NS_TYPE_VOTE ? "vote" : "opinion",
120 published, va, fu, vu,
121 v3_ns->vote_seconds, v3_ns->dist_seconds,
122 version_lines,
123 flags,
124 voter->nickname, fingerprint, voter->address,
125 ipaddr, voter->dir_port, voter->or_port, voter->contact);
127 tor_free(flags);
128 outp = status + strlen(status);
129 endp = status + len;
131 if (!tor_digest_is_zero(voter->legacy_id_digest)) {
132 char fpbuf[HEX_DIGEST_LEN+1];
133 base16_encode(fpbuf, sizeof(fpbuf), voter->legacy_id_digest, DIGEST_LEN);
134 tor_snprintf(outp, endp-outp, "legacy-dir-key %s\n", fpbuf);
135 outp += strlen(outp);
138 tor_assert(outp + cert->cache_info.signed_descriptor_len < endp);
139 memcpy(outp, cert->cache_info.signed_descriptor_body,
140 cert->cache_info.signed_descriptor_len);
142 outp += cert->cache_info.signed_descriptor_len;
145 SMARTLIST_FOREACH(v3_ns->routerstatus_list, vote_routerstatus_t *, vrs,
147 if (routerstatus_format_entry(outp, endp-outp, &vrs->status,
148 vrs->version, 0, 0) < 0) {
149 log_warn(LD_BUG, "Unable to print router status.");
150 goto err;
152 outp += strlen(outp);
156 char signing_key_fingerprint[FINGERPRINT_LEN+1];
157 if (tor_snprintf(outp, endp-outp, "directory-signature ")<0) {
158 log_warn(LD_BUG, "Unable to start signature line.");
159 goto err;
161 outp += strlen(outp);
163 if (crypto_pk_get_fingerprint(private_signing_key,
164 signing_key_fingerprint, 0)<0) {
165 log_warn(LD_BUG, "Unable to get fingerprint for signing key");
166 goto err;
168 if (tor_snprintf(outp, endp-outp, "%s %s\n", fingerprint,
169 signing_key_fingerprint)<0) {
170 log_warn(LD_BUG, "Unable to end signature line.");
171 goto err;
173 outp += strlen(outp);
176 if (router_get_networkstatus_v3_hash(status, digest)<0)
177 goto err;
178 note_crypto_pk_op(SIGN_DIR);
179 if (router_append_dirobj_signature(outp,endp-outp,digest,
180 private_signing_key)<0) {
181 log_warn(LD_BUG, "Unable to sign networkstatus vote.");
182 goto err;
186 networkstatus_t *v;
187 if (!(v = networkstatus_parse_vote_from_string(status, NULL,
188 v3_ns->type))) {
189 log_err(LD_BUG,"Generated a networkstatus %s we couldn't parse: "
190 "<<%s>>",
191 v3_ns->type == NS_TYPE_VOTE ? "vote" : "opinion", status);
192 goto err;
194 networkstatus_vote_free(v);
197 goto done;
199 err:
200 tor_free(status);
201 done:
202 tor_free(version_lines);
203 return status;
206 /* =====
207 * Consensus generation
208 * ===== */
210 /** Given a vote <b>vote</b> (not a consensus!), return its associated
211 * networkstatus_voter_info_t. */
212 static networkstatus_voter_info_t *
213 get_voter(const networkstatus_t *vote)
215 tor_assert(vote);
216 tor_assert(vote->type == NS_TYPE_VOTE);
217 tor_assert(vote->voters);
218 tor_assert(smartlist_len(vote->voters) == 1);
219 return smartlist_get(vote->voters, 0);
222 typedef struct {
223 networkstatus_t *v;
224 const char *digest;
225 int is_legacy;
226 } dir_src_ent_t;
228 /** Helper for sorting networkstatus_t votes (not consensuses) by the
229 * hash of their voters' identity digests. */
230 static int
231 _compare_votes_by_authority_id(const void **_a, const void **_b)
233 const networkstatus_t *a = *_a, *b = *_b;
234 return memcmp(get_voter(a)->identity_digest,
235 get_voter(b)->identity_digest, DIGEST_LEN);
238 static int
239 _compare_dir_src_ents_by_authority_id(const void **_a, const void **_b)
241 const dir_src_ent_t *a = *_a, *b = *_b;
242 const networkstatus_voter_info_t *a_v = get_voter(a->v),
243 *b_v = get_voter(b->v);
244 const char *a_id, *b_id;
245 a_id = a->is_legacy ? a_v->legacy_id_digest : a_v->identity_digest;
246 b_id = b->is_legacy ? b_v->legacy_id_digest : b_v->identity_digest;
248 return memcmp(a_id, b_id, DIGEST_LEN);
251 /** Given a sorted list of strings <b>in</b>, add every member to <b>out</b>
252 * that occurs more than <b>min</b> times. */
253 static void
254 get_frequent_members(smartlist_t *out, smartlist_t *in, int min)
256 char *cur = NULL;
257 int count = 0;
258 SMARTLIST_FOREACH(in, char *, cp,
260 if (cur && !strcmp(cp, cur)) {
261 ++count;
262 } else {
263 if (count > min)
264 smartlist_add(out, cur);
265 cur = cp;
266 count = 1;
269 if (count > min)
270 smartlist_add(out, cur);
273 /** Given a sorted list of strings <b>lst</b>, return the member that appears
274 * most. Break ties in favor of later-occurring members. */
275 static const char *
276 get_most_frequent_member(smartlist_t *lst)
278 const char *most_frequent = NULL;
279 int most_frequent_count = 0;
281 const char *cur = NULL;
282 int count = 0;
284 SMARTLIST_FOREACH(lst, const char *, s,
286 if (cur && !strcmp(s, cur)) {
287 ++count;
288 } else {
289 if (count >= most_frequent_count) {
290 most_frequent = cur;
291 most_frequent_count = count;
293 cur = s;
294 count = 1;
297 if (count >= most_frequent_count) {
298 most_frequent = cur;
299 most_frequent_count = count;
301 return most_frequent;
304 /** Return 0 if and only if <b>a</b> and <b>b</b> are routerstatuses
305 * that come from the same routerinfo, with the same derived elements.
307 static int
308 compare_vote_rs(const vote_routerstatus_t *a, const vote_routerstatus_t *b)
310 int r;
311 if ((r = memcmp(a->status.identity_digest, b->status.identity_digest,
312 DIGEST_LEN)))
313 return r;
314 if ((r = memcmp(a->status.descriptor_digest, b->status.descriptor_digest,
315 DIGEST_LEN)))
316 return r;
317 if ((r = (int)(b->status.published_on - a->status.published_on)))
318 return r;
319 if ((r = strcmp(b->status.nickname, a->status.nickname)))
320 return r;
321 if ((r = (((int)b->status.addr) - ((int)a->status.addr))))
322 return r;
323 if ((r = (((int)b->status.or_port) - ((int)a->status.or_port))))
324 return r;
325 if ((r = (((int)b->status.dir_port) - ((int)a->status.dir_port))))
326 return r;
327 return 0;
330 /** Helper for sorting routerlists based on compare_vote_rs. */
331 static int
332 _compare_vote_rs(const void **_a, const void **_b)
334 const vote_routerstatus_t *a = *_a, *b = *_b;
335 return compare_vote_rs(a,b);
338 /** Given a list of vote_routerstatus_t, all for the same router identity,
339 * return whichever is most frequent, breaking ties in favor of more
340 * recently published vote_routerstatus_t and in case of ties there,
341 * in favour of smaller descriptor digest.
343 static vote_routerstatus_t *
344 compute_routerstatus_consensus(smartlist_t *votes)
346 vote_routerstatus_t *most = NULL, *cur = NULL;
347 int most_n = 0, cur_n = 0;
348 time_t most_published = 0;
350 /* _compare_vote_rs() sorts the items by identity digest (all the same),
351 * then by SD digest. That way, if we have a tie that the published_on
352 * date cannot tie, we use the descriptor with the smaller digest.
354 smartlist_sort(votes, _compare_vote_rs);
355 SMARTLIST_FOREACH(votes, vote_routerstatus_t *, rs,
357 if (cur && !compare_vote_rs(cur, rs)) {
358 ++cur_n;
359 } else {
360 if (cur_n > most_n ||
361 (cur && cur_n == most_n &&
362 cur->status.published_on > most_published)) {
363 most = cur;
364 most_n = cur_n;
365 most_published = cur->status.published_on;
367 cur_n = 1;
368 cur = rs;
372 if (cur_n > most_n ||
373 (cur && cur_n == most_n && cur->status.published_on > most_published)) {
374 most = cur;
375 most_n = cur_n;
376 most_published = cur->status.published_on;
379 tor_assert(most);
380 return most;
383 /** Given a list of strings in <b>lst</b>, set the DIGEST_LEN-byte digest at
384 * <b>digest_out</b> to the hash of the concatenation of those strings. */
385 static void
386 hash_list_members(char *digest_out, smartlist_t *lst)
388 crypto_digest_env_t *d = crypto_new_digest_env();
389 SMARTLIST_FOREACH(lst, const char *, cp,
390 crypto_digest_add_bytes(d, cp, strlen(cp)));
391 crypto_digest_get_digest(d, digest_out, DIGEST_LEN);
392 crypto_free_digest_env(d);
395 /** Sorting helper: compare two strings based on their values as base-ten
396 * positive integers. (Non-integers are treated as prior to all integers, and
397 * compared lexically.) */
398 static int
399 _cmp_int_strings(const void **_a, const void **_b)
401 const char *a = *_a, *b = *_b;
402 int ai = (int)tor_parse_long(a, 10, 1, INT_MAX, NULL, NULL);
403 int bi = (int)tor_parse_long(b, 10, 1, INT_MAX, NULL, NULL);
404 if (ai<bi) {
405 return -1;
406 } else if (ai==bi) {
407 if (ai == 0) /* Parsing failed. */
408 return strcmp(a, b);
409 return 0;
410 } else {
411 return 1;
415 /** Given a list of networkstatus_t votes, determine and return the number of
416 * the highest consensus method that is supported by 2/3 of the voters. */
417 static int
418 compute_consensus_method(smartlist_t *votes)
420 smartlist_t *all_methods = smartlist_create();
421 smartlist_t *acceptable_methods = smartlist_create();
422 smartlist_t *tmp = smartlist_create();
423 int min = (smartlist_len(votes) * 2) / 3;
424 int n_ok;
425 int result;
426 SMARTLIST_FOREACH(votes, networkstatus_t *, vote,
428 tor_assert(vote->supported_methods);
429 smartlist_add_all(tmp, vote->supported_methods);
430 smartlist_sort(tmp, _cmp_int_strings);
431 smartlist_uniq(tmp, _cmp_int_strings, NULL);
432 smartlist_add_all(all_methods, tmp);
433 smartlist_clear(tmp);
436 smartlist_sort(all_methods, _cmp_int_strings);
437 get_frequent_members(acceptable_methods, all_methods, min);
438 n_ok = smartlist_len(acceptable_methods);
439 if (n_ok) {
440 const char *best = smartlist_get(acceptable_methods, n_ok-1);
441 result = (int)tor_parse_long(best, 10, 1, INT_MAX, NULL, NULL);
442 } else {
443 result = 1;
445 smartlist_free(tmp);
446 smartlist_free(all_methods);
447 smartlist_free(acceptable_methods);
448 return result;
451 /** Return true iff <b>method</b> is a consensus method that we support. */
452 static int
453 consensus_method_is_supported(int method)
455 return (method >= 1) && (method <= 4);
458 /** Given a list of vote networkstatus_t in <b>votes</b>, our public
459 * authority <b>identity_key</b>, our private authority <b>signing_key</b>,
460 * and the number of <b>total_authorities</b> that we believe exist in our
461 * voting quorum, generate the text of a new v3 consensus vote, and return the
462 * value in a newly allocated string.
464 * Note: this function DOES NOT check whether the votes are from
465 * recognized authorities. (dirvote_add_vote does that.) */
466 char *
467 networkstatus_compute_consensus(smartlist_t *votes,
468 int total_authorities,
469 crypto_pk_env_t *identity_key,
470 crypto_pk_env_t *signing_key,
471 const char *legacy_id_key_digest,
472 crypto_pk_env_t *legacy_signing_key)
474 smartlist_t *chunks;
475 char *result = NULL;
476 int consensus_method;
478 time_t valid_after, fresh_until, valid_until;
479 int vote_seconds, dist_seconds;
480 char *client_versions = NULL, *server_versions = NULL;
481 smartlist_t *flags;
482 tor_assert(total_authorities >= smartlist_len(votes));
484 if (!smartlist_len(votes)) {
485 log_warn(LD_DIR, "Can't compute a consensus from no votes.");
486 return NULL;
488 flags = smartlist_create();
490 consensus_method = compute_consensus_method(votes);
491 if (consensus_method_is_supported(consensus_method)) {
492 log_info(LD_DIR, "Generating consensus using method %d.",
493 consensus_method);
494 } else {
495 log_warn(LD_DIR, "The other authorities will use consensus method %d, "
496 "which I don't support. Maybe I should upgrade!",
497 consensus_method);
498 consensus_method = 1;
501 /* Compute medians of time-related things, and figure out how many
502 * routers we might need to talk about. */
504 int n_votes = smartlist_len(votes);
505 time_t *va_times = tor_malloc(n_votes * sizeof(time_t));
506 time_t *fu_times = tor_malloc(n_votes * sizeof(time_t));
507 time_t *vu_times = tor_malloc(n_votes * sizeof(time_t));
508 int *votesec_list = tor_malloc(n_votes * sizeof(int));
509 int *distsec_list = tor_malloc(n_votes * sizeof(int));
510 int n_versioning_clients = 0, n_versioning_servers = 0;
511 smartlist_t *combined_client_versions = smartlist_create();
512 smartlist_t *combined_server_versions = smartlist_create();
513 int j;
514 SMARTLIST_FOREACH(votes, networkstatus_t *, v,
516 tor_assert(v->type == NS_TYPE_VOTE);
517 va_times[v_sl_idx] = v->valid_after;
518 fu_times[v_sl_idx] = v->fresh_until;
519 vu_times[v_sl_idx] = v->valid_until;
520 votesec_list[v_sl_idx] = v->vote_seconds;
521 distsec_list[v_sl_idx] = v->dist_seconds;
522 if (v->client_versions) {
523 smartlist_t *cv = smartlist_create();
524 ++n_versioning_clients;
525 smartlist_split_string(cv, v->client_versions, ",",
526 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
527 sort_version_list(cv, 1);
528 smartlist_add_all(combined_client_versions, cv);
529 smartlist_free(cv); /* elements get freed later. */
531 if (v->server_versions) {
532 smartlist_t *sv = smartlist_create();
533 ++n_versioning_servers;
534 smartlist_split_string(sv, v->server_versions, ",",
535 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
536 sort_version_list(sv, 1);
537 smartlist_add_all(combined_server_versions, sv);
538 smartlist_free(sv); /* elements get freed later. */
540 SMARTLIST_FOREACH(v->known_flags, const char *, cp,
541 smartlist_add(flags, tor_strdup(cp)));
543 valid_after = median_time(va_times, n_votes);
544 fresh_until = median_time(fu_times, n_votes);
545 valid_until = median_time(vu_times, n_votes);
546 vote_seconds = median_int(votesec_list, n_votes);
547 dist_seconds = median_int(distsec_list, n_votes);
549 tor_assert(valid_after+MIN_VOTE_INTERVAL <= fresh_until);
550 tor_assert(fresh_until+MIN_VOTE_INTERVAL <= valid_until);
551 tor_assert(vote_seconds >= MIN_VOTE_SECONDS);
552 tor_assert(dist_seconds >= MIN_DIST_SECONDS);
554 for (j = 0; j < 2; ++j) {
555 smartlist_t *lst =
556 j ? combined_server_versions : combined_client_versions;
557 int min = (j ? n_versioning_servers : n_versioning_clients) / 2;
558 smartlist_t *good = smartlist_create();
559 char *res;
560 sort_version_list(lst, 0);
561 get_frequent_members(good, lst, min);
562 res = smartlist_join_strings(good, ",", 0, NULL);
563 if (j)
564 server_versions = res;
565 else
566 client_versions = res;
567 SMARTLIST_FOREACH(lst, char *, cp, tor_free(cp));
568 smartlist_free(good);
569 smartlist_free(lst);
572 smartlist_sort_strings(flags);
573 smartlist_uniq_strings(flags);
575 tor_free(va_times);
576 tor_free(fu_times);
577 tor_free(vu_times);
578 tor_free(votesec_list);
579 tor_free(distsec_list);
582 chunks = smartlist_create();
585 char buf[1024];
586 char va_buf[ISO_TIME_LEN+1], fu_buf[ISO_TIME_LEN+1],
587 vu_buf[ISO_TIME_LEN+1];
588 char *flaglist;
589 format_iso_time(va_buf, valid_after);
590 format_iso_time(fu_buf, fresh_until);
591 format_iso_time(vu_buf, valid_until);
592 flaglist = smartlist_join_strings(flags, " ", 0, NULL);
594 smartlist_add(chunks, tor_strdup("network-status-version 3\n"
595 "vote-status consensus\n"));
597 if (consensus_method >= 2) {
598 tor_snprintf(buf, sizeof(buf), "consensus-method %d\n",
599 consensus_method);
600 smartlist_add(chunks, tor_strdup(buf));
603 tor_snprintf(buf, sizeof(buf),
604 "valid-after %s\n"
605 "fresh-until %s\n"
606 "valid-until %s\n"
607 "voting-delay %d %d\n"
608 "client-versions %s\n"
609 "server-versions %s\n"
610 "known-flags %s\n",
611 va_buf, fu_buf, vu_buf,
612 vote_seconds, dist_seconds,
613 client_versions, server_versions, flaglist);
614 smartlist_add(chunks, tor_strdup(buf));
616 tor_free(flaglist);
619 /* Sort the votes. */
620 smartlist_sort(votes, _compare_votes_by_authority_id);
621 /* Add the authority sections. */
623 smartlist_t *dir_sources = smartlist_create();
624 SMARTLIST_FOREACH(votes, networkstatus_t *, v,
626 dir_src_ent_t *e = tor_malloc_zero(sizeof(dir_src_ent_t));
627 e->v = v;
628 e->digest = get_voter(v)->identity_digest;
629 e->is_legacy = 0;
630 smartlist_add(dir_sources, e);
631 if (consensus_method >= 3 &&
632 !tor_digest_is_zero(get_voter(v)->legacy_id_digest)) {
633 dir_src_ent_t *e_legacy = tor_malloc_zero(sizeof(dir_src_ent_t));
634 e_legacy->v = v;
635 e_legacy->digest = get_voter(v)->legacy_id_digest;
636 e_legacy->is_legacy = 1;
637 smartlist_add(dir_sources, e_legacy);
640 smartlist_sort(dir_sources, _compare_dir_src_ents_by_authority_id);
642 SMARTLIST_FOREACH(dir_sources, const dir_src_ent_t *, e,
644 char buf[1024];
645 struct in_addr in;
646 char ip[INET_NTOA_BUF_LEN];
647 char fingerprint[HEX_DIGEST_LEN+1];
648 char votedigest[HEX_DIGEST_LEN+1];
649 networkstatus_t *v = e->v;
650 networkstatus_voter_info_t *voter = get_voter(v);
652 if (e->is_legacy)
653 tor_assert(consensus_method >= 2);
655 in.s_addr = htonl(voter->addr);
656 tor_inet_ntoa(&in, ip, sizeof(ip));
657 base16_encode(fingerprint, sizeof(fingerprint), e->digest, DIGEST_LEN);
658 base16_encode(votedigest, sizeof(votedigest), voter->vote_digest,
659 DIGEST_LEN);
661 tor_snprintf(buf, sizeof(buf),
662 "dir-source %s%s %s %s %s %d %d\n",
663 voter->nickname, e->is_legacy ? "-legacy" : "",
664 fingerprint, voter->address, ip,
665 voter->dir_port,
666 voter->or_port);
667 smartlist_add(chunks, tor_strdup(buf));
668 if (! e->is_legacy) {
669 tor_snprintf(buf, sizeof(buf),
670 "contact %s\n"
671 "vote-digest %s\n",
672 voter->contact,
673 votedigest);
674 smartlist_add(chunks, tor_strdup(buf));
677 SMARTLIST_FOREACH(dir_sources, dir_src_ent_t *, e, tor_free(e));
678 smartlist_free(dir_sources);
681 /* Add the actual router entries. */
683 int *index; /* index[j] is the current index into votes[j]. */
684 int *size; /* size[j] is the number of routerstatuses in votes[j]. */
685 int *flag_counts; /* The number of voters that list flag[j] for the
686 * currently considered router. */
687 int i;
688 smartlist_t *matching_descs = smartlist_create();
689 smartlist_t *chosen_flags = smartlist_create();
690 smartlist_t *versions = smartlist_create();
692 int *n_voter_flags; /* n_voter_flags[j] is the number of flags that
693 * votes[j] knows about. */
694 int *n_flag_voters; /* n_flag_voters[f] is the number of votes that care
695 * about flags[f]. */
696 int **flag_map; /* flag_map[j][b] is an index f such that flag_map[f]
697 * is the same flag as votes[j]->known_flags[b]. */
698 int *named_flag; /* Index of the flag "Named" for votes[j] */
699 int *unnamed_flag; /* Index of the flag "Unnamed" for votes[j] */
700 int chosen_named_idx, chosen_unnamed_idx;
702 strmap_t *name_to_id_map = strmap_new();
703 char conflict[DIGEST_LEN];
704 char unknown[DIGEST_LEN];
705 memset(conflict, 0, sizeof(conflict));
706 memset(unknown, 0xff, sizeof(conflict));
708 index = tor_malloc_zero(sizeof(int)*smartlist_len(votes));
709 size = tor_malloc_zero(sizeof(int)*smartlist_len(votes));
710 n_voter_flags = tor_malloc_zero(sizeof(int) * smartlist_len(votes));
711 n_flag_voters = tor_malloc_zero(sizeof(int) * smartlist_len(flags));
712 flag_map = tor_malloc_zero(sizeof(int*) * smartlist_len(votes));
713 named_flag = tor_malloc_zero(sizeof(int) * smartlist_len(votes));
714 unnamed_flag = tor_malloc_zero(sizeof(int) * smartlist_len(votes));
715 for (i = 0; i < smartlist_len(votes); ++i)
716 unnamed_flag[i] = named_flag[i] = -1;
717 chosen_named_idx = smartlist_string_pos(flags, "Named");
718 chosen_unnamed_idx = smartlist_string_pos(flags, "Unnamed");
720 /* Build the flag index. */
721 SMARTLIST_FOREACH(votes, networkstatus_t *, v,
723 flag_map[v_sl_idx] = tor_malloc_zero(
724 sizeof(int)*smartlist_len(v->known_flags));
725 SMARTLIST_FOREACH(v->known_flags, const char *, fl,
727 int p = smartlist_string_pos(flags, fl);
728 tor_assert(p >= 0);
729 flag_map[v_sl_idx][fl_sl_idx] = p;
730 ++n_flag_voters[p];
731 if (!strcmp(fl, "Named"))
732 named_flag[v_sl_idx] = fl_sl_idx;
733 if (!strcmp(fl, "Unnamed"))
734 unnamed_flag[v_sl_idx] = fl_sl_idx;
736 n_voter_flags[v_sl_idx] = smartlist_len(v->known_flags);
737 size[v_sl_idx] = smartlist_len(v->routerstatus_list);
740 /* Named and Unnamed get treated specially */
741 if (consensus_method >= 2) {
742 SMARTLIST_FOREACH(votes, networkstatus_t *, v,
744 uint64_t nf;
745 if (named_flag[v_sl_idx]<0)
746 continue;
747 nf = U64_LITERAL(1) << named_flag[v_sl_idx];
748 SMARTLIST_FOREACH(v->routerstatus_list, vote_routerstatus_t *, rs,
750 if ((rs->flags & nf) != 0) {
751 const char *d = strmap_get_lc(name_to_id_map, rs->status.nickname);
752 if (!d) {
753 /* We have no name officially mapped to this digest. */
754 strmap_set_lc(name_to_id_map, rs->status.nickname,
755 rs->status.identity_digest);
756 } else if (d != conflict &&
757 memcmp(d, rs->status.identity_digest, DIGEST_LEN)) {
758 /* Authorities disagree about this nickname. */
759 strmap_set_lc(name_to_id_map, rs->status.nickname, conflict);
760 } else {
761 /* It's already a conflict, or it's already this ID. */
766 SMARTLIST_FOREACH(votes, networkstatus_t *, v,
768 uint64_t uf;
769 if (unnamed_flag[v_sl_idx]<0)
770 continue;
771 uf = U64_LITERAL(1) << unnamed_flag[v_sl_idx];
772 SMARTLIST_FOREACH(v->routerstatus_list, vote_routerstatus_t *, rs,
774 if ((rs->flags & uf) != 0) {
775 const char *d = strmap_get_lc(name_to_id_map, rs->status.nickname);
776 if (d == conflict || d == unknown) {
777 /* Leave it alone; we know what it is. */
778 } else if (!d) {
779 /* We have no name officially mapped to this digest. */
780 strmap_set_lc(name_to_id_map, rs->status.nickname, unknown);
781 } else if (!memcmp(d, rs->status.identity_digest, DIGEST_LEN)) {
782 /* Authorities disagree about this nickname. */
783 strmap_set_lc(name_to_id_map, rs->status.nickname, conflict);
784 } else {
785 /* It's mapped to a different name. */
792 /* Now go through all the votes */
793 flag_counts = tor_malloc(sizeof(int) * smartlist_len(flags));
794 while (1) {
795 vote_routerstatus_t *rs;
796 routerstatus_t rs_out;
797 const char *lowest_id = NULL;
798 const char *chosen_version;
799 const char *chosen_name = NULL;
800 int is_named = 0, is_unnamed = 0, is_running = 0;
801 int naming_conflict = 0;
802 int n_listing = 0;
803 int i;
804 char buf[256];
806 /* Of the next-to-be-considered digest in each voter, which is first? */
807 SMARTLIST_FOREACH(votes, networkstatus_t *, v, {
808 if (index[v_sl_idx] < size[v_sl_idx]) {
809 rs = smartlist_get(v->routerstatus_list, index[v_sl_idx]);
810 if (!lowest_id ||
811 memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN) < 0)
812 lowest_id = rs->status.identity_digest;
815 if (!lowest_id) /* we're out of routers. */
816 break;
818 memset(flag_counts, 0, sizeof(int)*smartlist_len(flags));
819 smartlist_clear(matching_descs);
820 smartlist_clear(chosen_flags);
821 smartlist_clear(versions);
823 /* Okay, go through all the entries for this digest. */
824 SMARTLIST_FOREACH(votes, networkstatus_t *, v, {
825 if (index[v_sl_idx] >= size[v_sl_idx])
826 continue; /* out of entries. */
827 rs = smartlist_get(v->routerstatus_list, index[v_sl_idx]);
828 if (memcmp(rs->status.identity_digest, lowest_id, DIGEST_LEN))
829 continue; /* doesn't include this router. */
830 /* At this point, we know that we're looking at a routersatus with
831 * identity "lowest".
833 ++index[v_sl_idx];
834 ++n_listing;
836 smartlist_add(matching_descs, rs);
837 if (rs->version && rs->version[0])
838 smartlist_add(versions, rs->version);
840 /* Tally up all the flags. */
841 for (i = 0; i < n_voter_flags[v_sl_idx]; ++i) {
842 if (rs->flags & (U64_LITERAL(1) << i))
843 ++flag_counts[flag_map[v_sl_idx][i]];
845 if (rs->flags & (U64_LITERAL(1) << named_flag[v_sl_idx])) {
846 if (chosen_name && strcmp(chosen_name, rs->status.nickname)) {
847 log_notice(LD_DIR, "Conflict on naming for router: %s vs %s",
848 chosen_name, rs->status.nickname);
849 naming_conflict = 1;
851 chosen_name = rs->status.nickname;
855 /* We don't include this router at all unless more than half of
856 * the authorities we believe in list it. */
857 if (n_listing <= total_authorities/2)
858 continue;
860 /* Figure out the most popular opinion of what the most recent
861 * routerinfo and its contents are. */
862 rs = compute_routerstatus_consensus(matching_descs);
863 /* Copy bits of that into rs_out. */
864 tor_assert(!memcmp(lowest_id, rs->status.identity_digest, DIGEST_LEN));
865 memcpy(rs_out.identity_digest, lowest_id, DIGEST_LEN);
866 memcpy(rs_out.descriptor_digest, rs->status.descriptor_digest,
867 DIGEST_LEN);
868 rs_out.addr = rs->status.addr;
869 rs_out.published_on = rs->status.published_on;
870 rs_out.dir_port = rs->status.dir_port;
871 rs_out.or_port = rs->status.or_port;
873 if (chosen_name && !naming_conflict) {
874 strlcpy(rs_out.nickname, chosen_name, sizeof(rs_out.nickname));
875 } else {
876 strlcpy(rs_out.nickname, rs->status.nickname, sizeof(rs_out.nickname));
879 if (consensus_method == 1) {
880 is_named = chosen_named_idx >= 0 &&
881 (!naming_conflict && flag_counts[chosen_named_idx]);
882 } else {
883 const char *d = strmap_get_lc(name_to_id_map, rs_out.nickname);
884 if (!d) {
885 is_named = is_unnamed = 0;
886 } else if (!memcmp(d, lowest_id, DIGEST_LEN)) {
887 is_named = 1; is_unnamed = 0;
888 } else {
889 is_named = 0; is_unnamed = 1;
893 /* Set the flags. */
894 smartlist_add(chosen_flags, (char*)"s"); /* for the start of the line. */
895 SMARTLIST_FOREACH(flags, const char *, fl,
897 if (!strcmp(fl, "Named")) {
898 if (is_named)
899 smartlist_add(chosen_flags, (char*)fl);
900 } else if (!strcmp(fl, "Unnamed") && consensus_method >= 2) {
901 if (is_unnamed)
902 smartlist_add(chosen_flags, (char*)fl);
903 } else {
904 if (flag_counts[fl_sl_idx] > n_flag_voters[fl_sl_idx]/2) {
905 smartlist_add(chosen_flags, (char*)fl);
906 if (!strcmp(fl, "Running"))
907 is_running = 1;
912 /* Starting with consensus method 4 we do not list servers
913 * that are not running in a consensus. See Proposal 138 */
914 if (consensus_method >= 4 && !is_running)
915 continue;
917 /* Pick the version. */
918 if (smartlist_len(versions)) {
919 sort_version_list(versions, 0);
920 chosen_version = get_most_frequent_member(versions);
921 } else {
922 chosen_version = NULL;
925 /* Okay!! Now we can write the descriptor... */
926 /* First line goes into "buf". */
927 routerstatus_format_entry(buf, sizeof(buf), &rs_out, NULL, 1, 0);
928 smartlist_add(chunks, tor_strdup(buf));
929 /* Second line is all flags. The "\n" is missing. */
930 smartlist_add(chunks,
931 smartlist_join_strings(chosen_flags, " ", 0, NULL));
932 /* Now the version line. */
933 if (chosen_version) {
934 smartlist_add(chunks, tor_strdup("\nv "));
935 smartlist_add(chunks, tor_strdup(chosen_version));
937 smartlist_add(chunks, tor_strdup("\n"));
939 /* And the loop is over and we move on to the next router */
942 tor_free(index);
943 tor_free(size);
944 tor_free(n_voter_flags);
945 tor_free(n_flag_voters);
946 for (i = 0; i < smartlist_len(votes); ++i)
947 tor_free(flag_map[i]);
948 tor_free(flag_map);
949 tor_free(flag_counts);
950 tor_free(named_flag);
951 tor_free(unnamed_flag);
952 strmap_free(name_to_id_map, NULL);
953 smartlist_free(matching_descs);
954 smartlist_free(chosen_flags);
955 smartlist_free(versions);
958 /* Add a signature. */
960 char digest[DIGEST_LEN];
961 char fingerprint[HEX_DIGEST_LEN+1];
962 char signing_key_fingerprint[HEX_DIGEST_LEN+1];
964 char buf[4096];
965 smartlist_add(chunks, tor_strdup("directory-signature "));
967 /* Compute the hash of the chunks. */
968 hash_list_members(digest, chunks);
970 /* Get the fingerprints */
971 crypto_pk_get_fingerprint(identity_key, fingerprint, 0);
972 crypto_pk_get_fingerprint(signing_key, signing_key_fingerprint, 0);
974 /* add the junk that will go at the end of the line. */
975 tor_snprintf(buf, sizeof(buf), "%s %s\n", fingerprint,
976 signing_key_fingerprint);
977 /* And the signature. */
978 if (router_append_dirobj_signature(buf, sizeof(buf), digest,
979 signing_key)) {
980 log_warn(LD_BUG, "Couldn't sign consensus networkstatus.");
981 return NULL; /* This leaks, but it should never happen. */
983 smartlist_add(chunks, tor_strdup(buf));
985 if (legacy_id_key_digest && legacy_signing_key && consensus_method >= 3) {
986 smartlist_add(chunks, tor_strdup("directory-signature "));
987 base16_encode(fingerprint, sizeof(fingerprint),
988 legacy_id_key_digest, DIGEST_LEN);
989 crypto_pk_get_fingerprint(legacy_signing_key,
990 signing_key_fingerprint, 0);
991 tor_snprintf(buf, sizeof(buf), "%s %s\n", fingerprint,
992 signing_key_fingerprint);
993 if (router_append_dirobj_signature(buf, sizeof(buf), digest,
994 legacy_signing_key)) {
995 log_warn(LD_BUG, "Couldn't sign consensus networkstatus.");
996 return NULL; /* This leaks, but it should never happen. */
998 smartlist_add(chunks, tor_strdup(buf));
1002 result = smartlist_join_strings(chunks, "", 0, NULL);
1004 tor_free(client_versions);
1005 tor_free(server_versions);
1006 smartlist_free(flags);
1007 SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
1008 smartlist_free(chunks);
1011 networkstatus_t *c;
1012 if (!(c = networkstatus_parse_vote_from_string(result, NULL,
1013 NS_TYPE_CONSENSUS))) {
1014 log_err(LD_BUG,"Generated a networkstatus consensus we couldn't "
1015 "parse.");
1016 tor_free(result);
1017 return NULL;
1019 networkstatus_vote_free(c);
1022 return result;
1025 /** Given a consensus vote <b>target</b> and a set of detached signatures in
1026 * <b>sigs</b> that correspond to the same consensus, check whether there are
1027 * any new signatures in <b>src_voter_list</b> that should be added to
1028 * <b>target. (A signature should be added if we have no signature for that
1029 * voter in <b>target</b> yet, or if we have no verifiable signature and the
1030 * new signature is verifiable.) Return the number of signatures added or
1031 * changed, or -1 if the document signed by <b>sigs</b> isn't the same
1032 * document as <b>target</b>. */
1034 networkstatus_add_detached_signatures(networkstatus_t *target,
1035 ns_detached_signatures_t *sigs,
1036 const char **msg_out)
1038 int r = 0;
1039 tor_assert(sigs);
1040 tor_assert(target);
1041 tor_assert(target->type == NS_TYPE_CONSENSUS);
1043 /* Do the times seem right? */
1044 if (target->valid_after != sigs->valid_after) {
1045 *msg_out = "Valid-After times do not match "
1046 "when adding detached signatures to consensus";
1047 return -1;
1049 if (target->fresh_until != sigs->fresh_until) {
1050 *msg_out = "Fresh-until times do not match "
1051 "when adding detached signatures to consensus";
1052 return -1;
1054 if (target->valid_until != sigs->valid_until) {
1055 *msg_out = "Valid-until times do not match "
1056 "when adding detached signatures to consensus";
1057 return -1;
1059 /* Are they the same consensus? */
1060 if (memcmp(target->networkstatus_digest, sigs->networkstatus_digest,
1061 DIGEST_LEN)) {
1062 *msg_out = "Digest mismatch when adding detached signatures to consensus";
1063 return -1;
1066 /* For each voter in src... */
1067 SMARTLIST_FOREACH(sigs->signatures, networkstatus_voter_info_t *, src_voter,
1069 char voter_identity[HEX_DIGEST_LEN+1];
1070 networkstatus_voter_info_t *target_voter =
1071 networkstatus_get_voter_by_id(target, src_voter->identity_digest);
1072 authority_cert_t *cert;
1074 base16_encode(voter_identity, sizeof(voter_identity),
1075 src_voter->identity_digest, DIGEST_LEN);
1076 log_info(LD_DIR, "Looking at signature from %s", voter_identity);
1077 /* If the target doesn't know about this voter, then forget it. */
1078 if (!target_voter) {
1079 log_info(LD_DIR, "We do not know about %s", voter_identity);
1080 continue;
1083 /* If the target already has a good signature from this voter, then skip
1084 * this one. */
1085 if (target_voter->good_signature) {
1086 log_info(LD_DIR, "We already have a good signature from %s",
1087 voter_identity);
1088 continue;
1091 /* Try checking the signature if we haven't already. */
1092 if (!src_voter->good_signature && !src_voter->bad_signature) {
1093 cert = authority_cert_get_by_digests(src_voter->identity_digest,
1094 src_voter->signing_key_digest);
1095 if (cert) {
1096 networkstatus_check_voter_signature(target, src_voter, cert);
1099 /* If this signature is good, or we don't have any signature yet,
1100 * then add it. */
1101 if (src_voter->good_signature || !target_voter->signature) {
1102 log_info(LD_DIR, "Adding signature from %s", voter_identity);
1103 ++r;
1104 tor_free(target_voter->signature);
1105 target_voter->signature =
1106 tor_memdup(src_voter->signature, src_voter->signature_len);
1107 memcpy(target_voter->signing_key_digest, src_voter->signing_key_digest,
1108 DIGEST_LEN);
1109 target_voter->signature_len = src_voter->signature_len;
1110 target_voter->good_signature = 1;
1111 target_voter->bad_signature = 0;
1112 } else {
1113 log_info(LD_DIR, "Not adding signature from %s", voter_identity);
1117 return r;
1120 /** Return a newly allocated string holding the detached-signatures document
1121 * corresponding to the signatures on <b>consensus</b>. */
1122 char *
1123 networkstatus_get_detached_signatures(networkstatus_t *consensus)
1125 smartlist_t *elements;
1126 char buf[4096];
1127 char *result = NULL;
1128 int n_sigs = 0;
1129 tor_assert(consensus);
1130 tor_assert(consensus->type == NS_TYPE_CONSENSUS);
1132 elements = smartlist_create();
1135 char va_buf[ISO_TIME_LEN+1], fu_buf[ISO_TIME_LEN+1],
1136 vu_buf[ISO_TIME_LEN+1];
1137 char d[HEX_DIGEST_LEN+1];
1139 base16_encode(d, sizeof(d), consensus->networkstatus_digest, DIGEST_LEN);
1140 format_iso_time(va_buf, consensus->valid_after);
1141 format_iso_time(fu_buf, consensus->fresh_until);
1142 format_iso_time(vu_buf, consensus->valid_until);
1144 tor_snprintf(buf, sizeof(buf),
1145 "consensus-digest %s\n"
1146 "valid-after %s\n"
1147 "fresh-until %s\n"
1148 "valid-until %s\n", d, va_buf, fu_buf, vu_buf);
1149 smartlist_add(elements, tor_strdup(buf));
1152 SMARTLIST_FOREACH(consensus->voters, networkstatus_voter_info_t *, v,
1154 char sk[HEX_DIGEST_LEN+1];
1155 char id[HEX_DIGEST_LEN+1];
1156 if (!v->signature || v->bad_signature)
1157 continue;
1158 ++n_sigs;
1159 base16_encode(sk, sizeof(sk), v->signing_key_digest, DIGEST_LEN);
1160 base16_encode(id, sizeof(id), v->identity_digest, DIGEST_LEN);
1161 tor_snprintf(buf, sizeof(buf),
1162 "directory-signature %s %s\n-----BEGIN SIGNATURE-----\n",
1163 id, sk);
1164 smartlist_add(elements, tor_strdup(buf));
1165 base64_encode(buf, sizeof(buf), v->signature, v->signature_len);
1166 strlcat(buf, "-----END SIGNATURE-----\n", sizeof(buf));
1167 smartlist_add(elements, tor_strdup(buf));
1170 result = smartlist_join_strings(elements, "", 0, NULL);
1172 SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
1173 smartlist_free(elements);
1174 if (!n_sigs)
1175 tor_free(result);
1176 return result;
1179 /** Release all storage held in <b>s</b>. */
1180 void
1181 ns_detached_signatures_free(ns_detached_signatures_t *s)
1183 if (s->signatures) {
1184 SMARTLIST_FOREACH(s->signatures, networkstatus_voter_info_t *, v,
1186 tor_free(v->signature);
1187 tor_free(v);
1189 smartlist_free(s->signatures);
1191 tor_free(s);
1194 /* =====
1195 * Certificate functions
1196 * ===== */
1198 /** Allocate and return a new authority_cert_t with the same contents as
1199 * <b>cert</b>. */
1200 authority_cert_t *
1201 authority_cert_dup(authority_cert_t *cert)
1203 authority_cert_t *out = tor_malloc(sizeof(authority_cert_t));
1204 tor_assert(cert);
1206 memcpy(out, cert, sizeof(authority_cert_t));
1207 /* Now copy pointed-to things. */
1208 out->cache_info.signed_descriptor_body =
1209 tor_strndup(cert->cache_info.signed_descriptor_body,
1210 cert->cache_info.signed_descriptor_len);
1211 out->cache_info.saved_location = SAVED_NOWHERE;
1212 out->identity_key = crypto_pk_dup_key(cert->identity_key);
1213 out->signing_key = crypto_pk_dup_key(cert->signing_key);
1215 return out;
1218 /* =====
1219 * Vote scheduling
1220 * ===== */
1222 /** Set *<b>timing_out</b> to the intervals at which we would like to vote.
1223 * Note that these aren't the intervals we'll use to vote; they're the ones
1224 * that we'll vote to use. */
1225 void
1226 dirvote_get_preferred_voting_intervals(vote_timing_t *timing_out)
1228 or_options_t *options = get_options();
1230 tor_assert(timing_out);
1232 timing_out->vote_interval = options->V3AuthVotingInterval;
1233 timing_out->n_intervals_valid = options->V3AuthNIntervalsValid;
1234 timing_out->vote_delay = options->V3AuthVoteDelay;
1235 timing_out->dist_delay = options->V3AuthDistDelay;
1238 /** Return the start of the next interval of size <b>interval</b> (in seconds)
1239 * after <b>now</b>. Midnight always starts a fresh interval, and if the last
1240 * interval of a day would be truncated to less than half its size, it is
1241 * rolled into the previous interval. */
1242 time_t
1243 dirvote_get_start_of_next_interval(time_t now, int interval)
1245 struct tm tm;
1246 time_t midnight_today;
1247 time_t midnight_tomorrow;
1248 time_t next;
1250 tor_gmtime_r(&now, &tm);
1251 tm.tm_hour = 0;
1252 tm.tm_min = 0;
1253 tm.tm_sec = 0;
1255 midnight_today = tor_timegm(&tm);
1256 midnight_tomorrow = midnight_today + (24*60*60);
1258 next = midnight_today + ((now-midnight_today)/interval + 1)*interval;
1260 /* Intervals never cross midnight. */
1261 if (next > midnight_tomorrow)
1262 next = midnight_tomorrow;
1264 /* If the interval would only last half as long as it's supposed to, then
1265 * skip over to the next day. */
1266 if (next + interval/2 > midnight_tomorrow)
1267 next = midnight_tomorrow;
1269 return next;
1272 /** Scheduling information for a voting interval. */
1273 static struct {
1274 /** When do we generate and distribute our vote for this interval? */
1275 time_t voting_starts;
1276 /** When do we send an HTTP request for any votes that we haven't
1277 * been posted yet?*/
1278 time_t fetch_missing_votes;
1279 /** When do we give up on getting more votes and generate a consensus? */
1280 time_t voting_ends;
1281 /** When do we send an HTTP request for any signatures we're expecting to
1282 * see on the consensus? */
1283 time_t fetch_missing_signatures;
1284 /** When do we publish the consensus? */
1285 time_t interval_starts;
1287 /* True iff we have generated and distributed our vote. */
1288 int have_voted;
1289 /* True iff we've requested missing votes. */
1290 int have_fetched_missing_votes;
1291 /* True iff we have built a consensus and sent the signatures around. */
1292 int have_built_consensus;
1293 /* True iff we've fetched missing signatures. */
1294 int have_fetched_missing_signatures;
1295 /* True iff we have published our consensus. */
1296 int have_published_consensus;
1297 } voting_schedule = {0,0,0,0,0,0,0,0,0,0};
1299 /** Set voting_schedule to hold the timing for the next vote we should be
1300 * doing. */
1301 void
1302 dirvote_recalculate_timing(or_options_t *options, time_t now)
1304 int interval, vote_delay, dist_delay;
1305 time_t start;
1306 time_t end;
1307 networkstatus_t *consensus;
1309 if (!authdir_mode_v3(options))
1310 return;
1312 consensus = networkstatus_get_live_consensus(now);
1314 memset(&voting_schedule, 0, sizeof(voting_schedule));
1316 if (consensus) {
1317 interval = (int)( consensus->fresh_until - consensus->valid_after );
1318 vote_delay = consensus->vote_seconds;
1319 dist_delay = consensus->dist_seconds;
1320 } else {
1321 interval = options->TestingV3AuthInitialVotingInterval;
1322 vote_delay = options->TestingV3AuthInitialVoteDelay;
1323 dist_delay = options->TestingV3AuthInitialDistDelay;
1326 tor_assert(interval > 0);
1328 if (vote_delay + dist_delay > interval/2)
1329 vote_delay = dist_delay = interval / 4;
1331 start = voting_schedule.interval_starts =
1332 dirvote_get_start_of_next_interval(now,interval);
1333 end = dirvote_get_start_of_next_interval(start+1, interval);
1335 tor_assert(end > start);
1337 voting_schedule.fetch_missing_signatures = start - (dist_delay/2);
1338 voting_schedule.voting_ends = start - dist_delay;
1339 voting_schedule.fetch_missing_votes = start - dist_delay - (vote_delay/2);
1340 voting_schedule.voting_starts = start - dist_delay - vote_delay;
1343 char tbuf[ISO_TIME_LEN+1];
1344 format_iso_time(tbuf, voting_schedule.interval_starts);
1345 log_notice(LD_DIR,"Choosing expected valid-after time as %s: "
1346 "consensus_set=%d, interval=%d",
1347 tbuf, consensus?1:0, interval);
1351 /** Entry point: Take whatever voting actions are pending as of <b>now</b>. */
1352 void
1353 dirvote_act(or_options_t *options, time_t now)
1355 if (!authdir_mode_v3(options))
1356 return;
1357 if (!voting_schedule.voting_starts) {
1358 char *keys = list_v3_auth_ids();
1359 authority_cert_t *c = get_my_v3_authority_cert();
1360 log_notice(LD_DIR, "Scheduling voting. Known authority IDs are %s. "
1361 "Mine is %s.",
1362 keys, hex_str(c->cache_info.identity_digest, DIGEST_LEN));
1363 tor_free(keys);
1364 dirvote_recalculate_timing(options, now);
1366 if (voting_schedule.voting_starts < now && !voting_schedule.have_voted) {
1367 log_notice(LD_DIR, "Time to vote.");
1368 dirvote_perform_vote();
1369 voting_schedule.have_voted = 1;
1371 if (voting_schedule.fetch_missing_votes < now &&
1372 !voting_schedule.have_fetched_missing_votes) {
1373 log_notice(LD_DIR, "Time to fetch any votes that we're missing.");
1374 dirvote_fetch_missing_votes();
1375 voting_schedule.have_fetched_missing_votes = 1;
1377 if (voting_schedule.voting_ends < now &&
1378 !voting_schedule.have_built_consensus) {
1379 log_notice(LD_DIR, "Time to compute a consensus.");
1380 dirvote_compute_consensus();
1381 /* XXXX We will want to try again later if we haven't got enough
1382 * votes yet. Implement this if it turns out to ever happen. */
1383 voting_schedule.have_built_consensus = 1;
1385 if (voting_schedule.fetch_missing_signatures < now &&
1386 !voting_schedule.have_fetched_missing_signatures) {
1387 log_notice(LD_DIR, "Time to fetch any signatures that we're missing.");
1388 dirvote_fetch_missing_signatures();
1389 voting_schedule.have_fetched_missing_signatures = 1;
1391 if (voting_schedule.interval_starts < now &&
1392 !voting_schedule.have_published_consensus) {
1393 log_notice(LD_DIR, "Time to publish the consensus and discard old votes");
1394 dirvote_publish_consensus();
1395 dirvote_clear_votes(0);
1396 voting_schedule.have_published_consensus = 1;
1397 /* XXXX We will want to try again later if we haven't got enough
1398 * signatures yet. Implement this if it turns out to ever happen. */
1399 dirvote_recalculate_timing(options, now);
1403 /** A vote networkstatus_t and its unparsed body: held around so we can
1404 * use it to generate a consensus (at voting_ends) and so we can serve it to
1405 * other authorities that might want it. */
1406 typedef struct pending_vote_t {
1407 cached_dir_t *vote_body;
1408 networkstatus_t *vote;
1409 } pending_vote_t;
1411 /** List of pending_vote_t for the current vote. Before we've used them to
1412 * build a consensus, the votes go here. */
1413 static smartlist_t *pending_vote_list = NULL;
1414 /** List of pending_vote_t for the previous vote. After we've used them to
1415 * build a consensus, the votes go here for the next period. */
1416 static smartlist_t *previous_vote_list = NULL;
1417 /** The body of the consensus that we're currently building. Once we
1418 * have it built, it goes into dirserv.c */
1419 static char *pending_consensus_body = NULL;
1420 /** The detached signatures for the consensus that we're currently
1421 * building. */
1422 static char *pending_consensus_signatures = NULL;
1423 /** The parsed in-progress consensus document. */
1424 static networkstatus_t *pending_consensus = NULL;
1425 /** List of ns_detached_signatures_t: hold signatures that get posted to us
1426 * before we have generated the consensus on our own. */
1427 static smartlist_t *pending_consensus_signature_list = NULL;
1429 /** Generate a networkstatus vote and post it to all the v3 authorities.
1430 * (V3 Authority only) */
1431 static int
1432 dirvote_perform_vote(void)
1434 crypto_pk_env_t *key = get_my_v3_authority_signing_key();
1435 authority_cert_t *cert = get_my_v3_authority_cert();
1436 networkstatus_t *ns;
1437 char *contents;
1438 pending_vote_t *pending_vote;
1440 int status;
1441 const char *msg = "";
1443 if (!cert || !key) {
1444 log_warn(LD_NET, "Didn't find key/certificate to generate v3 vote");
1445 return -1;
1447 if (!(ns = dirserv_generate_networkstatus_vote_obj(key, cert)))
1448 return -1;
1450 contents = format_networkstatus_vote(key, ns);
1451 networkstatus_vote_free(ns);
1452 if (!contents)
1453 return -1;
1455 pending_vote = dirvote_add_vote(contents, &msg, &status);
1456 tor_free(contents);
1457 if (!pending_vote) {
1458 log_warn(LD_DIR, "Couldn't store my own vote! (I told myself, '%s'.)",
1459 msg);
1460 return -1;
1463 directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_VOTE,
1464 ROUTER_PURPOSE_GENERAL,
1465 V3_AUTHORITY,
1466 pending_vote->vote_body->dir,
1467 pending_vote->vote_body->dir_len, 0);
1468 log_notice(LD_DIR, "Vote posted.");
1469 return 0;
1472 /** Send an HTTP request to every other v3 authority, for the votes of every
1473 * authority for which we haven't received a vote yet in this period. (V3
1474 * authority only) */
1475 static void
1476 dirvote_fetch_missing_votes(void)
1478 smartlist_t *missing_fps = smartlist_create();
1479 char *resource;
1481 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1482 trusted_dir_server_t *, ds,
1484 if (!(ds->type & V3_AUTHORITY))
1485 continue;
1486 if (!dirvote_get_vote(ds->v3_identity_digest,
1487 DGV_BY_ID|DGV_INCLUDE_PENDING)) {
1488 char *cp = tor_malloc(HEX_DIGEST_LEN+1);
1489 base16_encode(cp, HEX_DIGEST_LEN+1, ds->v3_identity_digest,
1490 DIGEST_LEN);
1491 smartlist_add(missing_fps, cp);
1495 if (!smartlist_len(missing_fps)) {
1496 smartlist_free(missing_fps);
1497 return;
1499 log_notice(LOG_NOTICE, "We're missing votes from %d authorities. Asking "
1500 "every other authority for a copy.", smartlist_len(missing_fps));
1501 resource = smartlist_join_strings(missing_fps, "+", 0, NULL);
1502 directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE,
1503 0, resource);
1504 tor_free(resource);
1505 SMARTLIST_FOREACH(missing_fps, char *, cp, tor_free(cp));
1506 smartlist_free(missing_fps);
1509 /** Send a request to every other authority for its detached signatures,
1510 * unless we have signatures from all other v3 authorities already. */
1511 static void
1512 dirvote_fetch_missing_signatures(void)
1514 if (!pending_consensus)
1515 return;
1516 if (networkstatus_check_consensus_signature(pending_consensus, -1) == 1)
1517 return; /* we have a signature from everybody. */
1519 directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES,
1520 0, NULL);
1523 /** Drop all currently pending votes, consensus, and detached signatures. */
1524 static void
1525 dirvote_clear_votes(int all_votes)
1527 if (!previous_vote_list)
1528 previous_vote_list = smartlist_create();
1529 if (!pending_vote_list)
1530 pending_vote_list = smartlist_create();
1532 /* All "previous" votes are now junk. */
1533 SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, v, {
1534 cached_dir_decref(v->vote_body);
1535 v->vote_body = NULL;
1536 networkstatus_vote_free(v->vote);
1537 tor_free(v);
1539 smartlist_clear(previous_vote_list);
1541 if (all_votes) {
1542 /* If we're dumping all the votes, we delete the pending ones. */
1543 SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, {
1544 cached_dir_decref(v->vote_body);
1545 v->vote_body = NULL;
1546 networkstatus_vote_free(v->vote);
1547 tor_free(v);
1549 } else {
1550 /* Otherwise, we move them into "previous". */
1551 smartlist_add_all(previous_vote_list, pending_vote_list);
1553 smartlist_clear(pending_vote_list);
1555 if (pending_consensus_signature_list) {
1556 SMARTLIST_FOREACH(pending_consensus_signature_list, char *, cp,
1557 tor_free(cp));
1558 smartlist_clear(pending_consensus_signature_list);
1560 tor_free(pending_consensus_body);
1561 tor_free(pending_consensus_signatures);
1562 if (pending_consensus) {
1563 networkstatus_vote_free(pending_consensus);
1564 pending_consensus = NULL;
1568 /** Return a newly allocated string containing the hex-encoded v3 authority
1569 identity digest of every recognized v3 authority. */
1570 static char *
1571 list_v3_auth_ids(void)
1573 smartlist_t *known_v3_keys = smartlist_create();
1574 char *keys;
1575 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
1576 trusted_dir_server_t *, ds,
1577 if ((ds->type & V3_AUTHORITY) &&
1578 !tor_digest_is_zero(ds->v3_identity_digest))
1579 smartlist_add(known_v3_keys,
1580 tor_strdup(hex_str(ds->v3_identity_digest, DIGEST_LEN))));
1581 keys = smartlist_join_strings(known_v3_keys, ", ", 0, NULL);
1582 SMARTLIST_FOREACH(known_v3_keys, char *, cp, tor_free(cp));
1583 smartlist_free(known_v3_keys);
1584 return keys;
1587 /** Called when we have received a networkstatus vote in <b>vote_body</b>.
1588 * Parse and validate it, and on success store it as a pending vote (which we
1589 * then return). Return NULL on failure. Sets *<b>msg_out</b> and
1590 * *<b>status_out</b> to an HTTP response and status code. (V3 authority
1591 * only) */
1592 pending_vote_t *
1593 dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out)
1595 networkstatus_t *vote;
1596 networkstatus_voter_info_t *vi;
1597 trusted_dir_server_t *ds;
1598 pending_vote_t *pending_vote = NULL;
1599 const char *end_of_vote = NULL;
1600 int any_failed = 0;
1601 tor_assert(vote_body);
1602 tor_assert(msg_out);
1603 tor_assert(status_out);
1605 if (!pending_vote_list)
1606 pending_vote_list = smartlist_create();
1607 *status_out = 0;
1608 *msg_out = NULL;
1610 again:
1611 vote = networkstatus_parse_vote_from_string(vote_body, &end_of_vote,
1612 NS_TYPE_VOTE);
1613 if (!end_of_vote)
1614 end_of_vote = vote_body + strlen(vote_body);
1615 if (!vote) {
1616 log_warn(LD_DIR, "Couldn't parse vote: length was %d",
1617 (int)strlen(vote_body));
1618 *msg_out = "Unable to parse vote";
1619 goto err;
1621 tor_assert(smartlist_len(vote->voters) == 1);
1622 vi = get_voter(vote);
1623 tor_assert(vi->good_signature == 1);
1624 ds = trusteddirserver_get_by_v3_auth_digest(vi->identity_digest);
1625 if (!ds) {
1626 char *keys = list_v3_auth_ids();
1627 log_warn(LD_DIR, "Got a vote from an authority (nickname %s, address %s) "
1628 "with authority key ID %s. "
1629 "This key ID is not recognized. Known v3 key IDs are: %s",
1630 vi->nickname, vi->address,
1631 hex_str(vi->identity_digest, DIGEST_LEN), keys);
1632 tor_free(keys);
1633 *msg_out = "Vote not from a recognized v3 authority";
1634 goto err;
1636 tor_assert(vote->cert);
1637 if (!authority_cert_get_by_digests(vote->cert->cache_info.identity_digest,
1638 vote->cert->signing_key_digest)) {
1639 /* Hey, it's a new cert! */
1640 trusted_dirs_load_certs_from_string(
1641 vote->cert->cache_info.signed_descriptor_body,
1642 0 /* from_store */, 1 /*flush*/);
1643 if (!authority_cert_get_by_digests(vote->cert->cache_info.identity_digest,
1644 vote->cert->signing_key_digest)) {
1645 log_warn(LD_BUG, "We added a cert, but still couldn't find it.");
1649 /* Is it for the right period? */
1650 if (vote->valid_after != voting_schedule.interval_starts) {
1651 char tbuf1[ISO_TIME_LEN+1], tbuf2[ISO_TIME_LEN+1];
1652 format_iso_time(tbuf1, vote->valid_after);
1653 format_iso_time(tbuf2, voting_schedule.interval_starts);
1654 log_warn(LD_DIR, "Rejecting vote from %s with valid-after time of %s; "
1655 "we were expecting %s", vi->address, tbuf1, tbuf2);
1656 *msg_out = "Bad valid-after time";
1657 goto err;
1660 /* Now see whether we already h<ave a vote from this authority.*/
1661 SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, {
1662 if (! memcmp(v->vote->cert->cache_info.identity_digest,
1663 vote->cert->cache_info.identity_digest,
1664 DIGEST_LEN)) {
1665 networkstatus_voter_info_t *vi_old = get_voter(v->vote);
1666 if (!memcmp(vi_old->vote_digest, vi->vote_digest, DIGEST_LEN)) {
1667 /* Ah, it's the same vote. Not a problem. */
1668 log_info(LD_DIR, "Discarding a vote we already have.");
1669 if (*status_out < 200)
1670 *status_out = 200;
1671 goto discard;
1672 } else if (v->vote->published < vote->published) {
1673 log_notice(LD_DIR, "Replacing an older pending vote from this "
1674 "directory.");
1675 cached_dir_decref(v->vote_body);
1676 networkstatus_vote_free(v->vote);
1677 v->vote_body = new_cached_dir(tor_strndup(vote_body,
1678 end_of_vote-vote_body),
1679 vote->published);
1680 v->vote = vote;
1681 if (end_of_vote &&
1682 !strcmpstart(end_of_vote, "network-status-version"))
1683 goto again;
1685 if (*status_out < 200)
1686 *status_out = 200;
1687 if (!*msg_out)
1688 *msg_out = "OK";
1689 return v;
1690 } else {
1691 *msg_out = "Already have a newer pending vote";
1692 goto err;
1697 pending_vote = tor_malloc_zero(sizeof(pending_vote_t));
1698 pending_vote->vote_body = new_cached_dir(tor_strndup(vote_body,
1699 end_of_vote-vote_body),
1700 vote->published);
1701 pending_vote->vote = vote;
1702 smartlist_add(pending_vote_list, pending_vote);
1704 if (!strcmpstart(end_of_vote, "network-status-version ")) {
1705 vote_body = end_of_vote;
1706 goto again;
1709 goto done;
1711 err:
1712 any_failed = 1;
1713 if (!*msg_out)
1714 *msg_out = "Error adding vote";
1715 if (*status_out < 400)
1716 *status_out = 400;
1718 discard:
1719 if (vote)
1720 networkstatus_vote_free(vote);
1722 if (end_of_vote && !strcmpstart(end_of_vote, "network-status-version ")) {
1723 vote_body = end_of_vote;
1724 goto again;
1727 done:
1729 if (*status_out < 200)
1730 *status_out = 200;
1731 if (!*msg_out) {
1732 if (!any_failed && !pending_vote) {
1733 *msg_out = "Duplicate discarded";
1734 } else {
1735 *msg_out = "ok";
1739 return any_failed ? NULL : pending_vote;
1742 /** Try to compute a v3 networkstatus consensus from the currently pending
1743 * votes. Return 0 on success, -1 on failure. Store the consensus in
1744 * pending_consensus: it won't be ready to be published until we have
1745 * everybody else's signatures collected too. (V3 Authoritity only) */
1746 static int
1747 dirvote_compute_consensus(void)
1749 /* Have we got enough votes to try? */
1750 int n_votes, n_voters;
1751 smartlist_t *votes = NULL;
1752 char *consensus_body = NULL, *signatures = NULL;
1753 networkstatus_t *consensus = NULL;
1754 authority_cert_t *my_cert;
1756 if (!pending_vote_list)
1757 pending_vote_list = smartlist_create();
1759 n_voters = get_n_authorities(V3_AUTHORITY);
1760 n_votes = smartlist_len(pending_vote_list);
1761 if (n_votes <= n_voters/2) {
1762 log_warn(LD_DIR, "We don't have enough votes to generate a consensus: "
1763 "%d of %d", n_votes, n_voters/2);
1764 goto err;
1767 if (!(my_cert = get_my_v3_authority_cert())) {
1768 log_warn(LD_DIR, "Can't generate consensus without a certificate.");
1769 goto err;
1772 votes = smartlist_create();
1773 SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v,
1774 smartlist_add(votes, v->vote));
1777 char legacy_dbuf[DIGEST_LEN];
1778 crypto_pk_env_t *legacy_sign=NULL;
1779 char *legacy_id_digest = NULL;
1780 if (get_options()->V3AuthUseLegacyKey) {
1781 authority_cert_t *cert = get_my_v3_legacy_cert();
1782 legacy_sign = get_my_v3_legacy_signing_key();
1783 if (cert) {
1784 crypto_pk_get_digest(cert->identity_key, legacy_dbuf);
1785 legacy_id_digest = legacy_dbuf;
1788 consensus_body = networkstatus_compute_consensus(
1789 votes, n_voters,
1790 my_cert->identity_key,
1791 get_my_v3_authority_signing_key(), legacy_id_digest, legacy_sign);
1793 if (!consensus_body) {
1794 log_warn(LD_DIR, "Couldn't generate a consensus at all!");
1795 goto err;
1797 consensus = networkstatus_parse_vote_from_string(consensus_body, NULL,
1798 NS_TYPE_CONSENSUS);
1799 if (!consensus) {
1800 log_warn(LD_DIR, "Couldn't parse consensus we generated!");
1801 goto err;
1803 /* 'Check' our own signature, to mark it valid. */
1804 networkstatus_check_consensus_signature(consensus, -1);
1806 signatures = networkstatus_get_detached_signatures(consensus);
1807 if (!signatures) {
1808 log_warn(LD_DIR, "Couldn't extract signatures.");
1809 goto err;
1812 tor_free(pending_consensus_body);
1813 pending_consensus_body = consensus_body;
1814 tor_free(pending_consensus_signatures);
1815 pending_consensus_signatures = signatures;
1817 if (pending_consensus)
1818 networkstatus_vote_free(pending_consensus);
1819 pending_consensus = consensus;
1821 if (pending_consensus_signature_list) {
1822 int n_sigs = 0;
1823 /* we may have gotten signatures for this consensus before we built
1824 * it ourself. Add them now. */
1825 SMARTLIST_FOREACH(pending_consensus_signature_list, char *, sig,
1827 const char *msg = NULL;
1828 int r = dirvote_add_signatures_to_pending_consensus(sig, &msg);
1829 if (r >= 0)
1830 n_sigs += r;
1831 else
1832 log_warn(LD_DIR,
1833 "Could not add queued signature to new consensus: %s",
1834 msg);
1835 tor_free(sig);
1837 if (n_sigs)
1838 log_notice(LD_DIR, "Added %d pending signatures while building "
1839 "consensus.", n_sigs);
1840 smartlist_clear(pending_consensus_signature_list);
1843 log_notice(LD_DIR, "Consensus computed; uploading signature(s)");
1845 directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_SIGNATURES,
1846 ROUTER_PURPOSE_GENERAL,
1847 V3_AUTHORITY,
1848 pending_consensus_signatures,
1849 strlen(pending_consensus_signatures), 0);
1850 log_notice(LD_DIR, "Signature(s) posted.");
1852 return 0;
1853 err:
1854 if (votes)
1855 smartlist_free(votes);
1856 tor_free(consensus_body);
1857 tor_free(signatures);
1858 networkstatus_vote_free(consensus);
1860 return -1;
1863 /** Helper: we just got the <b>detached_signatures_body</b> sent to us as
1864 * signatures on the currently pending consensus. Add them to the consensus
1865 * as appropriate. Return the number of signatures added. (?) */
1866 static int
1867 dirvote_add_signatures_to_pending_consensus(
1868 const char *detached_signatures_body,
1869 const char **msg_out)
1871 ns_detached_signatures_t *sigs = NULL;
1872 int r = -1;
1874 tor_assert(detached_signatures_body);
1875 tor_assert(msg_out);
1877 /* Only call if we have a pending consensus right now. */
1878 tor_assert(pending_consensus);
1879 tor_assert(pending_consensus_body);
1880 tor_assert(pending_consensus_signatures);
1882 *msg_out = NULL;
1884 if (!(sigs = networkstatus_parse_detached_signatures(
1885 detached_signatures_body, NULL))) {
1886 *msg_out = "Couldn't parse detached signatures.";
1887 goto err;
1890 log_info(LD_DIR, "Have %d signatures for adding to consensus.",
1891 smartlist_len(sigs->signatures));
1892 r = networkstatus_add_detached_signatures(pending_consensus,
1893 sigs, msg_out);
1894 log_info(LD_DIR,"Added %d signatures to consensus.", r);
1896 if (r >= 0) {
1897 char *new_detached =
1898 networkstatus_get_detached_signatures(pending_consensus);
1899 const char *src;
1900 char *dst, *dst_end;
1901 size_t new_consensus_len =
1902 strlen(pending_consensus_body) + strlen(new_detached) + 1;
1903 pending_consensus_body = tor_realloc(pending_consensus_body,
1904 new_consensus_len);
1905 dst_end = pending_consensus_body + new_consensus_len;
1906 dst = strstr(pending_consensus_body, "directory-signature ");
1907 tor_assert(dst);
1908 src = strstr(new_detached, "directory-signature ");
1909 tor_assert(src);
1910 strlcpy(dst, src, dst_end-dst);
1912 /* We remove this block once it has failed to crash for a while. But
1913 * unless it shows up in profiles, we're probably better leaving it in,
1914 * just in case we break detached signature processing at some point. */
1916 ns_detached_signatures_t *sigs =
1917 networkstatus_parse_detached_signatures(new_detached, NULL);
1918 networkstatus_t *v = networkstatus_parse_vote_from_string(
1919 pending_consensus_body, NULL,
1920 NS_TYPE_CONSENSUS);
1921 tor_assert(sigs);
1922 ns_detached_signatures_free(sigs);
1923 tor_assert(v);
1924 networkstatus_vote_free(v);
1926 tor_free(pending_consensus_signatures);
1927 pending_consensus_signatures = new_detached;
1928 *msg_out = "Signatures added";
1929 } else {
1930 goto err;
1933 goto done;
1934 err:
1935 if (!msg_out)
1936 *msg_out = "Unrecognized error while adding detached signatures.";
1937 done:
1938 if (sigs)
1939 ns_detached_signatures_free(sigs);
1940 return r;
1943 /** Helper: we just got the <b>deteached_signatures_body</b> sent to us as
1944 * signatures on the currently pending consensus. Add them to the pending
1945 * consensus (if we have one); otherwise queue them until we have a
1946 * consensus. Return negative on failure, nonnegative on success. */
1948 dirvote_add_signatures(const char *detached_signatures_body,
1949 const char *source,
1950 const char **msg)
1952 if (pending_consensus) {
1953 log_notice(LD_DIR, "Got a signature from %s. "
1954 "Adding it to the pending consensus.", source);
1955 return dirvote_add_signatures_to_pending_consensus(
1956 detached_signatures_body, msg);
1957 } else {
1958 log_notice(LD_DIR, "Got a signature from %s. "
1959 "Queueing it for the next consensus.", source);
1960 if (!pending_consensus_signature_list)
1961 pending_consensus_signature_list = smartlist_create();
1962 smartlist_add(pending_consensus_signature_list,
1963 tor_strdup(detached_signatures_body));
1964 *msg = "Signature queued";
1965 return 0;
1969 /** Replace the consensus that we're currently serving with the one that we've
1970 * been building. (V3 Authority only) */
1971 static int
1972 dirvote_publish_consensus(void)
1974 /* Can we actually publish it yet? */
1975 if (!pending_consensus ||
1976 networkstatus_check_consensus_signature(pending_consensus, 1)<0) {
1977 log_warn(LD_DIR, "Not enough info to publish pending consensus");
1978 return -1;
1981 if (networkstatus_set_current_consensus(pending_consensus_body, 0))
1982 log_warn(LD_DIR, "Error publishing consensus");
1983 else
1984 log_notice(LD_DIR, "Consensus published.");
1986 return 0;
1989 /** Release all static storage held in dirvote.c */
1990 void
1991 dirvote_free_all(void)
1993 dirvote_clear_votes(1);
1994 /* now empty as a result of clear_pending_votes. */
1995 smartlist_free(pending_vote_list);
1996 pending_vote_list = NULL;
1997 smartlist_free(previous_vote_list);
1998 previous_vote_list = NULL;
2000 tor_free(pending_consensus_body);
2001 tor_free(pending_consensus_signatures);
2002 if (pending_consensus) {
2003 networkstatus_vote_free(pending_consensus);
2004 pending_consensus = NULL;
2006 if (pending_consensus_signature_list) {
2007 /* now empty as a result of clear_pending_votes. */
2008 smartlist_free(pending_consensus_signature_list);
2009 pending_consensus_signature_list = NULL;
2013 /* ====
2014 * Access to pending items.
2015 * ==== */
2017 /** Return the body of the consensus that we're currently trying to build. */
2018 const char *
2019 dirvote_get_pending_consensus(void)
2021 return pending_consensus_body;
2024 /** Return the signatures that we know for the consensus that we're currently
2025 * trying to build */
2026 const char *
2027 dirvote_get_pending_detached_signatures(void)
2029 return pending_consensus_signatures;
2032 /** Return a given vote specified by <b>fp</b>. If <b>by_id</b>, return the
2033 * vote for the authority with the v3 authority identity key digest <b>fp</b>;
2034 * if <b>by_id</b> is false, return the vote whose digest is <b>fp</b>. If
2035 * <b>fp</b> is NULL, return our own vote. If <b>include_previous</b> is
2036 * false, do not consider any votes for a consensus that's already been built.
2037 * If <b>include_pending</b> is false, do not consider any votes for the
2038 * consensus that's in progress. May return NULL if we have no vote for the
2039 * authority in question. */
2040 const cached_dir_t *
2041 dirvote_get_vote(const char *fp, int flags)
2043 int by_id = flags & DGV_BY_ID;
2044 const int include_pending = flags & DGV_INCLUDE_PENDING;
2045 const int include_previous = flags & DGV_INCLUDE_PREVIOUS;
2047 if (!pending_vote_list && !previous_vote_list)
2048 return NULL;
2049 if (fp == NULL) {
2050 authority_cert_t *c = get_my_v3_authority_cert();
2051 if (c) {
2052 fp = c->cache_info.identity_digest;
2053 by_id = 1;
2054 } else
2055 return NULL;
2057 if (by_id) {
2058 if (pending_vote_list && include_pending) {
2059 SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv,
2060 if (!memcmp(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN))
2061 return pv->vote_body);
2063 if (previous_vote_list && include_previous) {
2064 SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, pv,
2065 if (!memcmp(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN))
2066 return pv->vote_body);
2068 } else {
2069 if (pending_vote_list && include_pending) {
2070 SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv,
2071 if (!memcmp(pv->vote->networkstatus_digest, fp, DIGEST_LEN))
2072 return pv->vote_body);
2074 if (previous_vote_list && include_previous) {
2075 SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, pv,
2076 if (!memcmp(pv->vote->networkstatus_digest, fp, DIGEST_LEN))
2077 return pv->vote_body);
2080 return NULL;