Merge remote-tracking branch 'public/bug23985_029' into maint-0.2.9
[tor.git] / src / or / dirvote.c
blob738ab35bc1d26c44e88aa2e4f8a54e191b875557
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2016, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
6 #define DIRVOTE_PRIVATE
7 #include "or.h"
8 #include "config.h"
9 #include "dircollate.h"
10 #include "directory.h"
11 #include "dirserv.h"
12 #include "dirvote.h"
13 #include "microdesc.h"
14 #include "networkstatus.h"
15 #include "policies.h"
16 #include "protover.h"
17 #include "rephist.h"
18 #include "router.h"
19 #include "routerkeys.h"
20 #include "routerlist.h"
21 #include "routerparse.h"
22 #include "entrynodes.h" /* needed for guardfraction methods */
23 #include "torcert.h"
24 #include "shared_random_state.h"
26 /**
27 * \file dirvote.c
28 * \brief Functions to compute directory consensus, and schedule voting.
29 **/
31 /** A consensus that we have built and are appending signatures to. Once it's
32 * time to publish it, it will become an active consensus if it accumulates
33 * enough signatures. */
34 typedef struct pending_consensus_t {
35 /** The body of the consensus that we're currently building. Once we
36 * have it built, it goes into dirserv.c */
37 char *body;
38 /** The parsed in-progress consensus document. */
39 networkstatus_t *consensus;
40 } pending_consensus_t;
42 /* DOCDOC dirvote_add_signatures_to_all_pending_consensuses */
43 static int dirvote_add_signatures_to_all_pending_consensuses(
44 const char *detached_signatures_body,
45 const char *source,
46 const char **msg_out);
47 static int dirvote_add_signatures_to_pending_consensus(
48 pending_consensus_t *pc,
49 ns_detached_signatures_t *sigs,
50 const char *source,
51 int severity,
52 const char **msg_out);
53 static char *list_v3_auth_ids(void);
54 static void dirvote_fetch_missing_votes(void);
55 static void dirvote_fetch_missing_signatures(void);
56 static int dirvote_perform_vote(void);
57 static void dirvote_clear_votes(int all_votes);
58 static int dirvote_compute_consensuses(void);
59 static int dirvote_publish_consensus(void);
61 /* =====
62 * Voting
63 * =====*/
65 /* If <b>opt_value</b> is non-NULL, return "keyword opt_value\n" in a new
66 * string. Otherwise return a new empty string. */
67 static char *
68 format_line_if_present(const char *keyword, const char *opt_value)
70 if (opt_value) {
71 char *result = NULL;
72 tor_asprintf(&result, "%s %s\n", keyword, opt_value);
73 return result;
74 } else {
75 return tor_strdup("");
79 /** Format the recommended/required-relay-client protocols lines for a vote in
80 * a newly allocated string, and return that string. */
81 static char *
82 format_protocols_lines_for_vote(const networkstatus_t *v3_ns)
84 char *recommended_relay_protocols_line = NULL;
85 char *recommended_client_protocols_line = NULL;
86 char *required_relay_protocols_line = NULL;
87 char *required_client_protocols_line = NULL;
89 recommended_relay_protocols_line =
90 format_line_if_present("recommended-relay-protocols",
91 v3_ns->recommended_relay_protocols);
92 recommended_client_protocols_line =
93 format_line_if_present("recommended-client-protocols",
94 v3_ns->recommended_client_protocols);
95 required_relay_protocols_line =
96 format_line_if_present("required-relay-protocols",
97 v3_ns->required_relay_protocols);
98 required_client_protocols_line =
99 format_line_if_present("required-client-protocols",
100 v3_ns->required_client_protocols);
102 char *result = NULL;
103 tor_asprintf(&result, "%s%s%s%s",
104 recommended_relay_protocols_line,
105 recommended_client_protocols_line,
106 required_relay_protocols_line,
107 required_client_protocols_line);
109 tor_free(recommended_relay_protocols_line);
110 tor_free(recommended_client_protocols_line);
111 tor_free(required_relay_protocols_line);
112 tor_free(required_client_protocols_line);
114 return result;
117 /** Return a new string containing the string representation of the vote in
118 * <b>v3_ns</b>, signed with our v3 signing key <b>private_signing_key</b>.
119 * For v3 authorities. */
120 STATIC char *
121 format_networkstatus_vote(crypto_pk_t *private_signing_key,
122 networkstatus_t *v3_ns)
124 smartlist_t *chunks = smartlist_new();
125 char *packages = NULL;
126 char fingerprint[FINGERPRINT_LEN+1];
127 char digest[DIGEST_LEN];
128 uint32_t addr;
129 char *protocols_lines = NULL;
130 char *client_versions_line = NULL, *server_versions_line = NULL;
131 char *shared_random_vote_str = NULL;
132 networkstatus_voter_info_t *voter;
133 char *status = NULL;
135 tor_assert(private_signing_key);
136 tor_assert(v3_ns->type == NS_TYPE_VOTE || v3_ns->type == NS_TYPE_OPINION);
138 voter = smartlist_get(v3_ns->voters, 0);
140 addr = voter->addr;
142 base16_encode(fingerprint, sizeof(fingerprint),
143 v3_ns->cert->cache_info.identity_digest, DIGEST_LEN);
145 client_versions_line = format_line_if_present("client-versions",
146 v3_ns->client_versions);
147 server_versions_line = format_line_if_present("server-versions",
148 v3_ns->server_versions);
149 protocols_lines = format_protocols_lines_for_vote(v3_ns);
151 if (v3_ns->package_lines) {
152 smartlist_t *tmp = smartlist_new();
153 SMARTLIST_FOREACH(v3_ns->package_lines, const char *, p,
154 if (validate_recommended_package_line(p))
155 smartlist_add_asprintf(tmp, "package %s\n", p));
156 smartlist_sort_strings(tmp);
157 packages = smartlist_join_strings(tmp, "", 0, NULL);
158 SMARTLIST_FOREACH(tmp, char *, cp, tor_free(cp));
159 smartlist_free(tmp);
160 } else {
161 packages = tor_strdup("");
164 /* Get shared random commitments/reveals line(s). */
165 shared_random_vote_str = sr_get_string_for_vote();
168 char published[ISO_TIME_LEN+1];
169 char va[ISO_TIME_LEN+1];
170 char fu[ISO_TIME_LEN+1];
171 char vu[ISO_TIME_LEN+1];
172 char *flags = smartlist_join_strings(v3_ns->known_flags, " ", 0, NULL);
173 /* XXXX Abstraction violation: should be pulling a field out of v3_ns.*/
174 char *flag_thresholds = dirserv_get_flag_thresholds_line();
175 char *params;
176 authority_cert_t *cert = v3_ns->cert;
177 char *methods =
178 make_consensus_method_list(MIN_SUPPORTED_CONSENSUS_METHOD,
179 MAX_SUPPORTED_CONSENSUS_METHOD, " ");
180 format_iso_time(published, v3_ns->published);
181 format_iso_time(va, v3_ns->valid_after);
182 format_iso_time(fu, v3_ns->fresh_until);
183 format_iso_time(vu, v3_ns->valid_until);
185 if (v3_ns->net_params)
186 params = smartlist_join_strings(v3_ns->net_params, " ", 0, NULL);
187 else
188 params = tor_strdup("");
190 tor_assert(cert);
191 smartlist_add_asprintf(chunks,
192 "network-status-version 3\n"
193 "vote-status %s\n"
194 "consensus-methods %s\n"
195 "published %s\n"
196 "valid-after %s\n"
197 "fresh-until %s\n"
198 "valid-until %s\n"
199 "voting-delay %d %d\n"
200 "%s%s" /* versions */
201 "%s" /* protocols */
202 "%s" /* packages */
203 "known-flags %s\n"
204 "flag-thresholds %s\n"
205 "params %s\n"
206 "dir-source %s %s %s %s %d %d\n"
207 "contact %s\n"
208 "%s", /* shared randomness information */
209 v3_ns->type == NS_TYPE_VOTE ? "vote" : "opinion",
210 methods,
211 published, va, fu, vu,
212 v3_ns->vote_seconds, v3_ns->dist_seconds,
213 client_versions_line,
214 server_versions_line,
215 protocols_lines,
216 packages,
217 flags,
218 flag_thresholds,
219 params,
220 voter->nickname, fingerprint, voter->address,
221 fmt_addr32(addr), voter->dir_port, voter->or_port,
222 voter->contact,
223 shared_random_vote_str ?
224 shared_random_vote_str : "");
226 tor_free(params);
227 tor_free(flags);
228 tor_free(flag_thresholds);
229 tor_free(methods);
230 tor_free(shared_random_vote_str);
232 if (!tor_digest_is_zero(voter->legacy_id_digest)) {
233 char fpbuf[HEX_DIGEST_LEN+1];
234 base16_encode(fpbuf, sizeof(fpbuf), voter->legacy_id_digest, DIGEST_LEN);
235 smartlist_add_asprintf(chunks, "legacy-dir-key %s\n", fpbuf);
238 smartlist_add(chunks, tor_strndup(cert->cache_info.signed_descriptor_body,
239 cert->cache_info.signed_descriptor_len));
242 SMARTLIST_FOREACH_BEGIN(v3_ns->routerstatus_list, vote_routerstatus_t *,
243 vrs) {
244 char *rsf;
245 vote_microdesc_hash_t *h;
246 rsf = routerstatus_format_entry(&vrs->status,
247 vrs->version, vrs->protocols,
248 NS_V3_VOTE, vrs);
249 if (rsf)
250 smartlist_add(chunks, rsf);
252 for (h = vrs->microdesc; h; h = h->next) {
253 smartlist_add(chunks, tor_strdup(h->microdesc_hash_line));
255 } SMARTLIST_FOREACH_END(vrs);
257 smartlist_add(chunks, tor_strdup("directory-footer\n"));
259 /* The digest includes everything up through the space after
260 * directory-signature. (Yuck.) */
261 crypto_digest_smartlist(digest, DIGEST_LEN, chunks,
262 "directory-signature ", DIGEST_SHA1);
265 char signing_key_fingerprint[FINGERPRINT_LEN+1];
266 if (crypto_pk_get_fingerprint(private_signing_key,
267 signing_key_fingerprint, 0)<0) {
268 log_warn(LD_BUG, "Unable to get fingerprint for signing key");
269 goto err;
272 smartlist_add_asprintf(chunks, "directory-signature %s %s\n", fingerprint,
273 signing_key_fingerprint);
276 note_crypto_pk_op(SIGN_DIR);
278 char *sig = router_get_dirobj_signature(digest, DIGEST_LEN,
279 private_signing_key);
280 if (!sig) {
281 log_warn(LD_BUG, "Unable to sign networkstatus vote.");
282 goto err;
284 smartlist_add(chunks, sig);
287 status = smartlist_join_strings(chunks, "", 0, NULL);
290 networkstatus_t *v;
291 if (!(v = networkstatus_parse_vote_from_string(status, NULL,
292 v3_ns->type))) {
293 log_err(LD_BUG,"Generated a networkstatus %s we couldn't parse: "
294 "<<%s>>",
295 v3_ns->type == NS_TYPE_VOTE ? "vote" : "opinion", status);
296 goto err;
298 networkstatus_vote_free(v);
301 goto done;
303 err:
304 tor_free(status);
305 done:
306 tor_free(client_versions_line);
307 tor_free(server_versions_line);
308 tor_free(protocols_lines);
309 tor_free(packages);
311 SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
312 smartlist_free(chunks);
313 return status;
316 /* =====
317 * Consensus generation
318 * ===== */
320 /** Given a vote <b>vote</b> (not a consensus!), return its associated
321 * networkstatus_voter_info_t. */
322 static networkstatus_voter_info_t *
323 get_voter(const networkstatus_t *vote)
325 tor_assert(vote);
326 tor_assert(vote->type == NS_TYPE_VOTE);
327 tor_assert(vote->voters);
328 tor_assert(smartlist_len(vote->voters) == 1);
329 return smartlist_get(vote->voters, 0);
332 /** Return the signature made by <b>voter</b> using the algorithm
333 * <b>alg</b>, or NULL if none is found. */
334 document_signature_t *
335 voter_get_sig_by_algorithm(const networkstatus_voter_info_t *voter,
336 digest_algorithm_t alg)
338 if (!voter->sigs)
339 return NULL;
340 SMARTLIST_FOREACH(voter->sigs, document_signature_t *, sig,
341 if (sig->alg == alg)
342 return sig);
343 return NULL;
346 /** Temporary structure used in constructing a list of dir-source entries
347 * for a consensus. One of these is generated for every vote, and one more
348 * for every legacy key in each vote. */
349 typedef struct dir_src_ent_t {
350 networkstatus_t *v;
351 const char *digest;
352 int is_legacy;
353 } dir_src_ent_t;
355 /** Helper for sorting networkstatus_t votes (not consensuses) by the
356 * hash of their voters' identity digests. */
357 static int
358 compare_votes_by_authority_id_(const void **_a, const void **_b)
360 const networkstatus_t *a = *_a, *b = *_b;
361 return fast_memcmp(get_voter(a)->identity_digest,
362 get_voter(b)->identity_digest, DIGEST_LEN);
365 /** Helper: Compare the dir_src_ent_ts in *<b>_a</b> and *<b>_b</b> by
366 * their identity digests, and return -1, 0, or 1 depending on their
367 * ordering */
368 static int
369 compare_dir_src_ents_by_authority_id_(const void **_a, const void **_b)
371 const dir_src_ent_t *a = *_a, *b = *_b;
372 const networkstatus_voter_info_t *a_v = get_voter(a->v),
373 *b_v = get_voter(b->v);
374 const char *a_id, *b_id;
375 a_id = a->is_legacy ? a_v->legacy_id_digest : a_v->identity_digest;
376 b_id = b->is_legacy ? b_v->legacy_id_digest : b_v->identity_digest;
378 return fast_memcmp(a_id, b_id, DIGEST_LEN);
381 /** Given a sorted list of strings <b>in</b>, add every member to <b>out</b>
382 * that occurs more than <b>min</b> times. */
383 static void
384 get_frequent_members(smartlist_t *out, smartlist_t *in, int min)
386 char *cur = NULL;
387 int count = 0;
388 SMARTLIST_FOREACH_BEGIN(in, char *, cp) {
389 if (cur && !strcmp(cp, cur)) {
390 ++count;
391 } else {
392 if (count > min)
393 smartlist_add(out, cur);
394 cur = cp;
395 count = 1;
397 } SMARTLIST_FOREACH_END(cp);
398 if (count > min)
399 smartlist_add(out, cur);
402 /** Given a sorted list of strings <b>lst</b>, return the member that appears
403 * most. Break ties in favor of later-occurring members. */
404 #define get_most_frequent_member(lst) \
405 smartlist_get_most_frequent_string(lst)
407 /** Return 0 if and only if <b>a</b> and <b>b</b> are routerstatuses
408 * that come from the same routerinfo, with the same derived elements.
410 static int
411 compare_vote_rs(const vote_routerstatus_t *a, const vote_routerstatus_t *b)
413 int r;
414 tor_assert(a);
415 tor_assert(b);
417 if ((r = fast_memcmp(a->status.identity_digest, b->status.identity_digest,
418 DIGEST_LEN)))
419 return r;
420 if ((r = fast_memcmp(a->status.descriptor_digest,
421 b->status.descriptor_digest,
422 DIGEST_LEN)))
423 return r;
424 /* If we actually reached this point, then the identities and
425 * the descriptor digests matched, so somebody is making SHA1 collisions.
427 #define CMP_FIELD(utype, itype, field) do { \
428 utype aval = (utype) (itype) a->status.field; \
429 utype bval = (utype) (itype) b->status.field; \
430 utype u = bval - aval; \
431 itype r2 = (itype) u; \
432 if (r2 < 0) { \
433 return -1; \
434 } else if (r2 > 0) { \
435 return 1; \
437 } while (0)
439 CMP_FIELD(uint64_t, int64_t, published_on);
441 if ((r = strcmp(b->status.nickname, a->status.nickname)))
442 return r;
444 CMP_FIELD(unsigned, int, addr);
445 CMP_FIELD(unsigned, int, or_port);
446 CMP_FIELD(unsigned, int, dir_port);
448 return 0;
451 /** Helper for sorting routerlists based on compare_vote_rs. */
452 static int
453 compare_vote_rs_(const void **_a, const void **_b)
455 const vote_routerstatus_t *a = *_a, *b = *_b;
456 return compare_vote_rs(a,b);
459 /** Helper for sorting OR ports. */
460 static int
461 compare_orports_(const void **_a, const void **_b)
463 const tor_addr_port_t *a = *_a, *b = *_b;
464 int r;
466 if ((r = tor_addr_compare(&a->addr, &b->addr, CMP_EXACT)))
467 return r;
468 if ((r = (((int) b->port) - ((int) a->port))))
469 return r;
471 return 0;
474 /** Given a list of vote_routerstatus_t, all for the same router identity,
475 * return whichever is most frequent, breaking ties in favor of more
476 * recently published vote_routerstatus_t and in case of ties there,
477 * in favor of smaller descriptor digest.
479 static vote_routerstatus_t *
480 compute_routerstatus_consensus(smartlist_t *votes, int consensus_method,
481 char *microdesc_digest256_out,
482 tor_addr_port_t *best_alt_orport_out)
484 vote_routerstatus_t *most = NULL, *cur = NULL;
485 int most_n = 0, cur_n = 0;
486 time_t most_published = 0;
488 /* compare_vote_rs_() sorts the items by identity digest (all the same),
489 * then by SD digest. That way, if we have a tie that the published_on
490 * date cannot tie, we use the descriptor with the smaller digest.
492 smartlist_sort(votes, compare_vote_rs_);
493 SMARTLIST_FOREACH_BEGIN(votes, vote_routerstatus_t *, rs) {
494 if (cur && !compare_vote_rs(cur, rs)) {
495 ++cur_n;
496 } else {
497 if (cur && (cur_n > most_n ||
498 (cur_n == most_n &&
499 cur->status.published_on > most_published))) {
500 most = cur;
501 most_n = cur_n;
502 most_published = cur->status.published_on;
504 cur_n = 1;
505 cur = rs;
507 } SMARTLIST_FOREACH_END(rs);
509 if (cur_n > most_n ||
510 (cur && cur_n == most_n && cur->status.published_on > most_published)) {
511 most = cur;
512 most_n = cur_n;
513 most_published = cur->status.published_on;
516 tor_assert(most);
518 /* If we're producing "a" lines, vote on potential alternative (sets
519 * of) OR port(s) in the winning routerstatuses.
521 * XXX prop186 There's at most one alternative OR port (_the_ IPv6
522 * port) for now. */
523 if (consensus_method >= MIN_METHOD_FOR_A_LINES && best_alt_orport_out) {
524 smartlist_t *alt_orports = smartlist_new();
525 const tor_addr_port_t *most_alt_orport = NULL;
527 SMARTLIST_FOREACH_BEGIN(votes, vote_routerstatus_t *, rs) {
528 tor_assert(rs);
529 if (compare_vote_rs(most, rs) == 0 &&
530 !tor_addr_is_null(&rs->status.ipv6_addr)
531 && rs->status.ipv6_orport) {
532 smartlist_add(alt_orports, tor_addr_port_new(&rs->status.ipv6_addr,
533 rs->status.ipv6_orport));
535 } SMARTLIST_FOREACH_END(rs);
537 smartlist_sort(alt_orports, compare_orports_);
538 most_alt_orport = smartlist_get_most_frequent(alt_orports,
539 compare_orports_);
540 if (most_alt_orport) {
541 memcpy(best_alt_orport_out, most_alt_orport, sizeof(tor_addr_port_t));
542 log_debug(LD_DIR, "\"a\" line winner for %s is %s",
543 most->status.nickname,
544 fmt_addrport(&most_alt_orport->addr, most_alt_orport->port));
547 SMARTLIST_FOREACH(alt_orports, tor_addr_port_t *, ap, tor_free(ap));
548 smartlist_free(alt_orports);
551 if (microdesc_digest256_out) {
552 smartlist_t *digests = smartlist_new();
553 const uint8_t *best_microdesc_digest;
554 SMARTLIST_FOREACH_BEGIN(votes, vote_routerstatus_t *, rs) {
555 char d[DIGEST256_LEN];
556 if (compare_vote_rs(rs, most))
557 continue;
558 if (!vote_routerstatus_find_microdesc_hash(d, rs, consensus_method,
559 DIGEST_SHA256))
560 smartlist_add(digests, tor_memdup(d, sizeof(d)));
561 } SMARTLIST_FOREACH_END(rs);
562 smartlist_sort_digests256(digests);
563 best_microdesc_digest = smartlist_get_most_frequent_digest256(digests);
564 if (best_microdesc_digest)
565 memcpy(microdesc_digest256_out, best_microdesc_digest, DIGEST256_LEN);
566 SMARTLIST_FOREACH(digests, char *, cp, tor_free(cp));
567 smartlist_free(digests);
570 return most;
573 /** Sorting helper: compare two strings based on their values as base-ten
574 * positive integers. (Non-integers are treated as prior to all integers, and
575 * compared lexically.) */
576 static int
577 cmp_int_strings_(const void **_a, const void **_b)
579 const char *a = *_a, *b = *_b;
580 int ai = (int)tor_parse_long(a, 10, 1, INT_MAX, NULL, NULL);
581 int bi = (int)tor_parse_long(b, 10, 1, INT_MAX, NULL, NULL);
582 if (ai<bi) {
583 return -1;
584 } else if (ai==bi) {
585 if (ai == 0) /* Parsing failed. */
586 return strcmp(a, b);
587 return 0;
588 } else {
589 return 1;
593 /** Given a list of networkstatus_t votes, determine and return the number of
594 * the highest consensus method that is supported by 2/3 of the voters. */
595 static int
596 compute_consensus_method(smartlist_t *votes)
598 smartlist_t *all_methods = smartlist_new();
599 smartlist_t *acceptable_methods = smartlist_new();
600 smartlist_t *tmp = smartlist_new();
601 int min = (smartlist_len(votes) * 2) / 3;
602 int n_ok;
603 int result;
604 SMARTLIST_FOREACH(votes, networkstatus_t *, vote,
606 tor_assert(vote->supported_methods);
607 smartlist_add_all(tmp, vote->supported_methods);
608 smartlist_sort(tmp, cmp_int_strings_);
609 smartlist_uniq(tmp, cmp_int_strings_, NULL);
610 smartlist_add_all(all_methods, tmp);
611 smartlist_clear(tmp);
614 smartlist_sort(all_methods, cmp_int_strings_);
615 get_frequent_members(acceptable_methods, all_methods, min);
616 n_ok = smartlist_len(acceptable_methods);
617 if (n_ok) {
618 const char *best = smartlist_get(acceptable_methods, n_ok-1);
619 result = (int)tor_parse_long(best, 10, 1, INT_MAX, NULL, NULL);
620 } else {
621 result = 1;
623 smartlist_free(tmp);
624 smartlist_free(all_methods);
625 smartlist_free(acceptable_methods);
626 return result;
629 /** Return true iff <b>method</b> is a consensus method that we support. */
630 static int
631 consensus_method_is_supported(int method)
633 if (method == MIN_METHOD_FOR_ED25519_ID_IN_MD) {
634 /* This method was broken due to buggy code accidently left in
635 * dircollate.c; do not actually use it.
637 return 0;
640 return (method >= MIN_SUPPORTED_CONSENSUS_METHOD) &&
641 (method <= MAX_SUPPORTED_CONSENSUS_METHOD);
644 /** Return a newly allocated string holding the numbers between low and high
645 * (inclusive) that are supported consensus methods. */
646 STATIC char *
647 make_consensus_method_list(int low, int high, const char *separator)
649 char *list;
651 int i;
652 smartlist_t *lst;
653 lst = smartlist_new();
654 for (i = low; i <= high; ++i) {
655 if (!consensus_method_is_supported(i))
656 continue;
657 smartlist_add_asprintf(lst, "%d", i);
659 list = smartlist_join_strings(lst, separator, 0, NULL);
660 tor_assert(list);
661 SMARTLIST_FOREACH(lst, char *, cp, tor_free(cp));
662 smartlist_free(lst);
663 return list;
666 /** Helper: given <b>lst</b>, a list of version strings such that every
667 * version appears once for every versioning voter who recommends it, return a
668 * newly allocated string holding the resulting client-versions or
669 * server-versions list. May change contents of <b>lst</b> */
670 static char *
671 compute_consensus_versions_list(smartlist_t *lst, int n_versioning)
673 int min = n_versioning / 2;
674 smartlist_t *good = smartlist_new();
675 char *result;
676 sort_version_list(lst, 0);
677 get_frequent_members(good, lst, min);
678 result = smartlist_join_strings(good, ",", 0, NULL);
679 smartlist_free(good);
680 return result;
683 /** Given a list of K=V values, return the int32_t value corresponding to
684 * KEYWORD=, or default_val if no such value exists, or if the value is
685 * corrupt.
687 STATIC int32_t
688 dirvote_get_intermediate_param_value(const smartlist_t *param_list,
689 const char *keyword,
690 int32_t default_val)
692 unsigned int n_found = 0;
693 int32_t value = default_val;
695 SMARTLIST_FOREACH_BEGIN(param_list, const char *, k_v_pair) {
696 if (!strcmpstart(k_v_pair, keyword) && k_v_pair[strlen(keyword)] == '=') {
697 const char *integer_str = &k_v_pair[strlen(keyword)+1];
698 int ok;
699 value = (int32_t)
700 tor_parse_long(integer_str, 10, INT32_MIN, INT32_MAX, &ok, NULL);
701 if (BUG(! ok))
702 return default_val;
703 ++n_found;
705 } SMARTLIST_FOREACH_END(k_v_pair);
707 if (n_found == 1)
708 return value;
709 else if (BUG(n_found > 1))
710 return default_val;
711 else
712 return default_val;
715 /** Minimum number of directory authorities voting for a parameter to
716 * include it in the consensus, if consensus method 12 or later is to be
717 * used. See proposal 178 for details. */
718 #define MIN_VOTES_FOR_PARAM 3
720 /** Helper: given a list of valid networkstatus_t, return a new smartlist
721 * containing the contents of the consensus network parameter set.
723 STATIC smartlist_t *
724 dirvote_compute_params(smartlist_t *votes, int method, int total_authorities)
726 int i;
727 int32_t *vals;
729 int cur_param_len;
730 const char *cur_param;
731 const char *eq;
733 const int n_votes = smartlist_len(votes);
734 smartlist_t *output;
735 smartlist_t *param_list = smartlist_new();
736 (void) method;
738 /* We require that the parameter lists in the votes are well-formed: that
739 is, that their keywords are unique and sorted, and that their values are
740 between INT32_MIN and INT32_MAX inclusive. This should be guaranteed by
741 the parsing code. */
743 vals = tor_calloc(n_votes, sizeof(int));
745 SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
746 if (!v->net_params)
747 continue;
748 smartlist_add_all(param_list, v->net_params);
749 } SMARTLIST_FOREACH_END(v);
751 if (smartlist_len(param_list) == 0) {
752 tor_free(vals);
753 return param_list;
756 smartlist_sort_strings(param_list);
757 i = 0;
758 cur_param = smartlist_get(param_list, 0);
759 eq = strchr(cur_param, '=');
760 tor_assert(eq);
761 cur_param_len = (int)(eq+1 - cur_param);
763 output = smartlist_new();
765 SMARTLIST_FOREACH_BEGIN(param_list, const char *, param) {
766 const char *next_param;
767 int ok=0;
768 eq = strchr(param, '=');
769 tor_assert(i<n_votes); /* Make sure we prevented vote-stuffing. */
770 vals[i++] = (int32_t)
771 tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL);
772 tor_assert(ok); /* Already checked these when parsing. */
774 if (param_sl_idx+1 == smartlist_len(param_list))
775 next_param = NULL;
776 else
777 next_param = smartlist_get(param_list, param_sl_idx+1);
778 /* resolve spurious clang shallow analysis null pointer errors */
779 tor_assert(param);
780 if (!next_param || strncmp(next_param, param, cur_param_len)) {
781 /* We've reached the end of a series. */
782 /* Make sure enough authorities voted on this param, unless the
783 * the consensus method we use is too old for that. */
784 if (i > total_authorities/2 ||
785 i >= MIN_VOTES_FOR_PARAM) {
786 int32_t median = median_int32(vals, i);
787 char *out_string = tor_malloc(64+cur_param_len);
788 memcpy(out_string, param, cur_param_len);
789 tor_snprintf(out_string+cur_param_len,64, "%ld", (long)median);
790 smartlist_add(output, out_string);
793 i = 0;
794 if (next_param) {
795 eq = strchr(next_param, '=');
796 cur_param_len = (int)(eq+1 - next_param);
799 } SMARTLIST_FOREACH_END(param);
801 smartlist_free(param_list);
802 tor_free(vals);
803 return output;
806 #define RANGE_CHECK(a,b,c,d,e,f,g,mx) \
807 ((a) >= 0 && (a) <= (mx) && (b) >= 0 && (b) <= (mx) && \
808 (c) >= 0 && (c) <= (mx) && (d) >= 0 && (d) <= (mx) && \
809 (e) >= 0 && (e) <= (mx) && (f) >= 0 && (f) <= (mx) && \
810 (g) >= 0 && (g) <= (mx))
812 #define CHECK_EQ(a, b, margin) \
813 ((a)-(b) >= 0 ? (a)-(b) <= (margin) : (b)-(a) <= (margin))
815 typedef enum {
816 BW_WEIGHTS_NO_ERROR = 0,
817 BW_WEIGHTS_RANGE_ERROR = 1,
818 BW_WEIGHTS_SUMG_ERROR = 2,
819 BW_WEIGHTS_SUME_ERROR = 3,
820 BW_WEIGHTS_SUMD_ERROR = 4,
821 BW_WEIGHTS_BALANCE_MID_ERROR = 5,
822 BW_WEIGHTS_BALANCE_EG_ERROR = 6
823 } bw_weights_error_t;
826 * Verify that any weightings satisfy the balanced formulas.
828 static bw_weights_error_t
829 networkstatus_check_weights(int64_t Wgg, int64_t Wgd, int64_t Wmg,
830 int64_t Wme, int64_t Wmd, int64_t Wee,
831 int64_t Wed, int64_t scale, int64_t G,
832 int64_t M, int64_t E, int64_t D, int64_t T,
833 int64_t margin, int do_balance) {
834 bw_weights_error_t berr = BW_WEIGHTS_NO_ERROR;
836 // Wed + Wmd + Wgd == 1
837 if (!CHECK_EQ(Wed + Wmd + Wgd, scale, margin)) {
838 berr = BW_WEIGHTS_SUMD_ERROR;
839 goto out;
842 // Wmg + Wgg == 1
843 if (!CHECK_EQ(Wmg + Wgg, scale, margin)) {
844 berr = BW_WEIGHTS_SUMG_ERROR;
845 goto out;
848 // Wme + Wee == 1
849 if (!CHECK_EQ(Wme + Wee, scale, margin)) {
850 berr = BW_WEIGHTS_SUME_ERROR;
851 goto out;
854 // Verify weights within range 0->1
855 if (!RANGE_CHECK(Wgg, Wgd, Wmg, Wme, Wmd, Wed, Wee, scale)) {
856 berr = BW_WEIGHTS_RANGE_ERROR;
857 goto out;
860 if (do_balance) {
861 // Wgg*G + Wgd*D == Wee*E + Wed*D, already scaled
862 if (!CHECK_EQ(Wgg*G + Wgd*D, Wee*E + Wed*D, (margin*T)/3)) {
863 berr = BW_WEIGHTS_BALANCE_EG_ERROR;
864 goto out;
867 // Wgg*G + Wgd*D == M*scale + Wmd*D + Wme*E + Wmg*G, already scaled
868 if (!CHECK_EQ(Wgg*G + Wgd*D, M*scale + Wmd*D + Wme*E + Wmg*G,
869 (margin*T)/3)) {
870 berr = BW_WEIGHTS_BALANCE_MID_ERROR;
871 goto out;
875 out:
876 if (berr) {
877 log_info(LD_DIR,
878 "Bw weight mismatch %d. G="I64_FORMAT" M="I64_FORMAT
879 " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT
880 " Wmd=%d Wme=%d Wmg=%d Wed=%d Wee=%d"
881 " Wgd=%d Wgg=%d Wme=%d Wmg=%d",
882 berr,
883 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
884 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
885 (int)Wmd, (int)Wme, (int)Wmg, (int)Wed, (int)Wee,
886 (int)Wgd, (int)Wgg, (int)Wme, (int)Wmg);
889 return berr;
893 * This function computes the bandwidth weights for consensus method 10.
895 * It returns true if weights could be computed, false otherwise.
897 static int
898 networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
899 int64_t M, int64_t E, int64_t D,
900 int64_t T, int64_t weight_scale)
902 bw_weights_error_t berr = 0;
903 int64_t Wgg = -1, Wgd = -1;
904 int64_t Wmg = -1, Wme = -1, Wmd = -1;
905 int64_t Wed = -1, Wee = -1;
906 const char *casename;
908 if (G <= 0 || M <= 0 || E <= 0 || D <= 0) {
909 log_warn(LD_DIR, "Consensus with empty bandwidth: "
910 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
911 " D="I64_FORMAT" T="I64_FORMAT,
912 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
913 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T));
914 return 0;
918 * Computed from cases in 3.8.3 of dir-spec.txt
920 * 1. Neither are scarce
921 * 2. Both Guard and Exit are scarce
922 * a. R+D <= S
923 * b. R+D > S
924 * 3. One of Guard or Exit is scarce
925 * a. S+D < T/3
926 * b. S+D >= T/3
928 if (3*E >= T && 3*G >= T) { // E >= T/3 && G >= T/3
929 /* Case 1: Neither are scarce. */
930 casename = "Case 1 (Wgd=Wmd=Wed)";
931 Wgd = weight_scale/3;
932 Wed = weight_scale/3;
933 Wmd = weight_scale/3;
934 Wee = (weight_scale*(E+G+M))/(3*E);
935 Wme = weight_scale - Wee;
936 Wmg = (weight_scale*(2*G-E-M))/(3*G);
937 Wgg = weight_scale - Wmg;
939 berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed,
940 weight_scale, G, M, E, D, T, 10, 1);
942 if (berr) {
943 log_warn(LD_DIR,
944 "Bw Weights error %d for %s v10. G="I64_FORMAT" M="I64_FORMAT
945 " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT
946 " Wmd=%d Wme=%d Wmg=%d Wed=%d Wee=%d"
947 " Wgd=%d Wgg=%d Wme=%d Wmg=%d weight_scale=%d",
948 berr, casename,
949 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
950 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
951 (int)Wmd, (int)Wme, (int)Wmg, (int)Wed, (int)Wee,
952 (int)Wgd, (int)Wgg, (int)Wme, (int)Wmg, (int)weight_scale);
953 return 0;
955 } else if (3*E < T && 3*G < T) { // E < T/3 && G < T/3
956 int64_t R = MIN(E, G);
957 int64_t S = MAX(E, G);
959 * Case 2: Both Guards and Exits are scarce
960 * Balance D between E and G, depending upon
961 * D capacity and scarcity.
963 if (R+D < S) { // Subcase a
964 Wgg = weight_scale;
965 Wee = weight_scale;
966 Wmg = 0;
967 Wme = 0;
968 Wmd = 0;
969 if (E < G) {
970 casename = "Case 2a (E scarce)";
971 Wed = weight_scale;
972 Wgd = 0;
973 } else { /* E >= G */
974 casename = "Case 2a (G scarce)";
975 Wed = 0;
976 Wgd = weight_scale;
978 } else { // Subcase b: R+D >= S
979 casename = "Case 2b1 (Wgg=1, Wmd=Wgd)";
980 Wee = (weight_scale*(E - G + M))/E;
981 Wed = (weight_scale*(D - 2*E + 4*G - 2*M))/(3*D);
982 Wme = (weight_scale*(G-M))/E;
983 Wmg = 0;
984 Wgg = weight_scale;
985 Wmd = (weight_scale - Wed)/2;
986 Wgd = (weight_scale - Wed)/2;
988 berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed,
989 weight_scale, G, M, E, D, T, 10, 1);
991 if (berr) {
992 casename = "Case 2b2 (Wgg=1, Wee=1)";
993 Wgg = weight_scale;
994 Wee = weight_scale;
995 Wed = (weight_scale*(D - 2*E + G + M))/(3*D);
996 Wmd = (weight_scale*(D - 2*M + G + E))/(3*D);
997 Wme = 0;
998 Wmg = 0;
1000 if (Wmd < 0) { // Can happen if M > T/3
1001 casename = "Case 2b3 (Wmd=0)";
1002 Wmd = 0;
1003 log_warn(LD_DIR,
1004 "Too much Middle bandwidth on the network to calculate "
1005 "balanced bandwidth-weights. Consider increasing the "
1006 "number of Guard nodes by lowering the requirements.");
1008 Wgd = weight_scale - Wed - Wmd;
1009 berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee,
1010 Wed, weight_scale, G, M, E, D, T, 10, 1);
1012 if (berr != BW_WEIGHTS_NO_ERROR &&
1013 berr != BW_WEIGHTS_BALANCE_MID_ERROR) {
1014 log_warn(LD_DIR,
1015 "Bw Weights error %d for %s v10. G="I64_FORMAT" M="I64_FORMAT
1016 " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT
1017 " Wmd=%d Wme=%d Wmg=%d Wed=%d Wee=%d"
1018 " Wgd=%d Wgg=%d Wme=%d Wmg=%d weight_scale=%d",
1019 berr, casename,
1020 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
1021 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
1022 (int)Wmd, (int)Wme, (int)Wmg, (int)Wed, (int)Wee,
1023 (int)Wgd, (int)Wgg, (int)Wme, (int)Wmg, (int)weight_scale);
1024 return 0;
1027 } else { // if (E < T/3 || G < T/3) {
1028 int64_t S = MIN(E, G);
1029 // Case 3: Exactly one of Guard or Exit is scarce
1030 if (!(3*E < T || 3*G < T) || !(3*G >= T || 3*E >= T)) {
1031 log_warn(LD_BUG,
1032 "Bw-Weights Case 3 v10 but with G="I64_FORMAT" M="
1033 I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT,
1034 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
1035 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T));
1038 if (3*(S+D) < T) { // Subcase a: S+D < T/3
1039 if (G < E) {
1040 casename = "Case 3a (G scarce)";
1041 Wgg = Wgd = weight_scale;
1042 Wmd = Wed = Wmg = 0;
1043 // Minor subcase, if E is more scarce than M,
1044 // keep its bandwidth in place.
1045 if (E < M) Wme = 0;
1046 else Wme = (weight_scale*(E-M))/(2*E);
1047 Wee = weight_scale-Wme;
1048 } else { // G >= E
1049 casename = "Case 3a (E scarce)";
1050 Wee = Wed = weight_scale;
1051 Wmd = Wgd = Wme = 0;
1052 // Minor subcase, if G is more scarce than M,
1053 // keep its bandwidth in place.
1054 if (G < M) Wmg = 0;
1055 else Wmg = (weight_scale*(G-M))/(2*G);
1056 Wgg = weight_scale-Wmg;
1058 } else { // Subcase b: S+D >= T/3
1059 // D != 0 because S+D >= T/3
1060 if (G < E) {
1061 casename = "Case 3bg (G scarce, Wgg=1, Wmd == Wed)";
1062 Wgg = weight_scale;
1063 Wgd = (weight_scale*(D - 2*G + E + M))/(3*D);
1064 Wmg = 0;
1065 Wee = (weight_scale*(E+M))/(2*E);
1066 Wme = weight_scale - Wee;
1067 Wmd = (weight_scale - Wgd)/2;
1068 Wed = (weight_scale - Wgd)/2;
1070 berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee,
1071 Wed, weight_scale, G, M, E, D, T, 10, 1);
1072 } else { // G >= E
1073 casename = "Case 3be (E scarce, Wee=1, Wmd == Wgd)";
1074 Wee = weight_scale;
1075 Wed = (weight_scale*(D - 2*E + G + M))/(3*D);
1076 Wme = 0;
1077 Wgg = (weight_scale*(G+M))/(2*G);
1078 Wmg = weight_scale - Wgg;
1079 Wmd = (weight_scale - Wed)/2;
1080 Wgd = (weight_scale - Wed)/2;
1082 berr = networkstatus_check_weights(Wgg, Wgd, Wmg, Wme, Wmd, Wee,
1083 Wed, weight_scale, G, M, E, D, T, 10, 1);
1085 if (berr) {
1086 log_warn(LD_DIR,
1087 "Bw Weights error %d for %s v10. G="I64_FORMAT" M="I64_FORMAT
1088 " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT
1089 " Wmd=%d Wme=%d Wmg=%d Wed=%d Wee=%d"
1090 " Wgd=%d Wgg=%d Wme=%d Wmg=%d weight_scale=%d",
1091 berr, casename,
1092 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
1093 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
1094 (int)Wmd, (int)Wme, (int)Wmg, (int)Wed, (int)Wee,
1095 (int)Wgd, (int)Wgg, (int)Wme, (int)Wmg, (int)weight_scale);
1096 return 0;
1101 /* We cast down the weights to 32 bit ints on the assumption that
1102 * weight_scale is ~= 10000. We need to ensure a rogue authority
1103 * doesn't break this assumption to rig our weights */
1104 tor_assert(0 < weight_scale && weight_scale <= INT32_MAX);
1107 * Provide Wgm=Wgg, Wmm=1, Wem=Wee, Weg=Wed. May later determine
1108 * that middle nodes need different bandwidth weights for dirport traffic,
1109 * or that weird exit policies need special weight, or that bridges
1110 * need special weight.
1112 * NOTE: This list is sorted.
1114 smartlist_add_asprintf(chunks,
1115 "bandwidth-weights Wbd=%d Wbe=%d Wbg=%d Wbm=%d "
1116 "Wdb=%d "
1117 "Web=%d Wed=%d Wee=%d Weg=%d Wem=%d "
1118 "Wgb=%d Wgd=%d Wgg=%d Wgm=%d "
1119 "Wmb=%d Wmd=%d Wme=%d Wmg=%d Wmm=%d\n",
1120 (int)Wmd, (int)Wme, (int)Wmg, (int)weight_scale,
1121 (int)weight_scale,
1122 (int)weight_scale, (int)Wed, (int)Wee, (int)Wed, (int)Wee,
1123 (int)weight_scale, (int)Wgd, (int)Wgg, (int)Wgg,
1124 (int)weight_scale, (int)Wmd, (int)Wme, (int)Wmg, (int)weight_scale);
1126 log_notice(LD_CIRC, "Computed bandwidth weights for %s with v10: "
1127 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
1128 " T="I64_FORMAT,
1129 casename,
1130 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
1131 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T));
1132 return 1;
1135 /** Update total bandwidth weights (G/M/E/D/T) with the bandwidth of
1136 * the router in <b>rs</b>. */
1137 static void
1138 update_total_bandwidth_weights(const routerstatus_t *rs,
1139 int is_exit, int is_guard,
1140 int64_t *G, int64_t *M, int64_t *E, int64_t *D,
1141 int64_t *T)
1143 int default_bandwidth = rs->bandwidth_kb;
1144 int guardfraction_bandwidth = 0;
1146 if (!rs->has_bandwidth) {
1147 log_info(LD_BUG, "Missing consensus bandwidth for router %s",
1148 rs->nickname);
1149 return;
1152 /* If this routerstatus represents a guard that we have
1153 * guardfraction information on, use it to calculate its actual
1154 * bandwidth. From proposal236:
1156 * Similarly, when calculating the bandwidth-weights line as in
1157 * section 3.8.3 of dir-spec.txt, directory authorities should treat N
1158 * as if fraction F of its bandwidth has the guard flag and (1-F) does
1159 * not. So when computing the totals G,M,E,D, each relay N with guard
1160 * visibility fraction F and bandwidth B should be added as follows:
1162 * G' = G + F*B, if N does not have the exit flag
1163 * M' = M + (1-F)*B, if N does not have the exit flag
1165 * or
1167 * D' = D + F*B, if N has the exit flag
1168 * E' = E + (1-F)*B, if N has the exit flag
1170 * In this block of code, we prepare the bandwidth values by setting
1171 * the default_bandwidth to F*B and guardfraction_bandwidth to (1-F)*B.
1173 if (rs->has_guardfraction) {
1174 guardfraction_bandwidth_t guardfraction_bw;
1176 tor_assert(is_guard);
1178 guard_get_guardfraction_bandwidth(&guardfraction_bw,
1179 rs->bandwidth_kb,
1180 rs->guardfraction_percentage);
1182 default_bandwidth = guardfraction_bw.guard_bw;
1183 guardfraction_bandwidth = guardfraction_bw.non_guard_bw;
1186 /* Now calculate the total bandwidth weights with or without
1187 * guardfraction. Depending on the flags of the relay, add its
1188 * bandwidth to the appropriate weight pool. If it's a guard and
1189 * guardfraction is enabled, add its bandwidth to both pools as
1190 * indicated by the previous comment.
1192 *T += default_bandwidth;
1193 if (is_exit && is_guard) {
1195 *D += default_bandwidth;
1196 if (rs->has_guardfraction) {
1197 *E += guardfraction_bandwidth;
1200 } else if (is_exit) {
1202 *E += default_bandwidth;
1204 } else if (is_guard) {
1206 *G += default_bandwidth;
1207 if (rs->has_guardfraction) {
1208 *M += guardfraction_bandwidth;
1211 } else {
1213 *M += default_bandwidth;
1217 /** Considering the different recommended/required protocols sets as a
1218 * 4-element array, return the element from <b>vote</b> for that protocol
1219 * set.
1221 static const char *
1222 get_nth_protocol_set_vote(int n, const networkstatus_t *vote)
1224 switch (n) {
1225 case 0: return vote->recommended_client_protocols;
1226 case 1: return vote->recommended_relay_protocols;
1227 case 2: return vote->required_client_protocols;
1228 case 3: return vote->required_relay_protocols;
1229 default:
1230 tor_assert_unreached();
1231 return NULL;
1235 /** Considering the different recommended/required protocols sets as a
1236 * 4-element array, return a newly allocated string for the consensus value
1237 * for the n'th set.
1239 static char *
1240 compute_nth_protocol_set(int n, int n_voters, const smartlist_t *votes)
1242 const char *keyword;
1243 smartlist_t *proto_votes = smartlist_new();
1244 int threshold;
1245 switch (n) {
1246 case 0:
1247 keyword = "recommended-client-protocols";
1248 threshold = CEIL_DIV(n_voters, 2);
1249 break;
1250 case 1:
1251 keyword = "recommended-relay-protocols";
1252 threshold = CEIL_DIV(n_voters, 2);
1253 break;
1254 case 2:
1255 keyword = "required-client-protocols";
1256 threshold = CEIL_DIV(n_voters * 2, 3);
1257 break;
1258 case 3:
1259 keyword = "required-relay-protocols";
1260 threshold = CEIL_DIV(n_voters * 2, 3);
1261 break;
1262 default:
1263 tor_assert_unreached();
1264 return NULL;
1267 SMARTLIST_FOREACH_BEGIN(votes, const networkstatus_t *, ns) {
1268 const char *v = get_nth_protocol_set_vote(n, ns);
1269 if (v)
1270 smartlist_add(proto_votes, (void*)v);
1271 } SMARTLIST_FOREACH_END(ns);
1273 char *protocols = protover_compute_vote(proto_votes, threshold);
1274 smartlist_free(proto_votes);
1276 char *result = NULL;
1277 tor_asprintf(&result, "%s %s\n", keyword, protocols);
1278 tor_free(protocols);
1280 return result;
1283 /** Given a list of vote networkstatus_t in <b>votes</b>, our public
1284 * authority <b>identity_key</b>, our private authority <b>signing_key</b>,
1285 * and the number of <b>total_authorities</b> that we believe exist in our
1286 * voting quorum, generate the text of a new v3 consensus vote, and return the
1287 * value in a newly allocated string.
1289 * Note: this function DOES NOT check whether the votes are from
1290 * recognized authorities. (dirvote_add_vote does that.) */
1291 char *
1292 networkstatus_compute_consensus(smartlist_t *votes,
1293 int total_authorities,
1294 crypto_pk_t *identity_key,
1295 crypto_pk_t *signing_key,
1296 const char *legacy_id_key_digest,
1297 crypto_pk_t *legacy_signing_key,
1298 consensus_flavor_t flavor)
1300 smartlist_t *chunks;
1301 char *result = NULL;
1302 int consensus_method;
1303 time_t valid_after, fresh_until, valid_until;
1304 int vote_seconds, dist_seconds;
1305 char *client_versions = NULL, *server_versions = NULL;
1306 smartlist_t *flags;
1307 const char *flavor_name;
1308 uint32_t max_unmeasured_bw_kb = DEFAULT_MAX_UNMEASURED_BW_KB;
1309 int64_t G=0, M=0, E=0, D=0, T=0; /* For bandwidth weights */
1310 const routerstatus_format_type_t rs_format =
1311 flavor == FLAV_NS ? NS_V3_CONSENSUS : NS_V3_CONSENSUS_MICRODESC;
1312 char *params = NULL;
1313 char *packages = NULL;
1314 int added_weights = 0;
1315 dircollator_t *collator = NULL;
1316 smartlist_t *param_list = NULL;
1318 tor_assert(flavor == FLAV_NS || flavor == FLAV_MICRODESC);
1319 tor_assert(total_authorities >= smartlist_len(votes));
1320 tor_assert(total_authorities > 0);
1322 flavor_name = networkstatus_get_flavor_name(flavor);
1324 if (!smartlist_len(votes)) {
1325 log_warn(LD_DIR, "Can't compute a consensus from no votes.");
1326 return NULL;
1328 flags = smartlist_new();
1330 consensus_method = compute_consensus_method(votes);
1331 if (consensus_method_is_supported(consensus_method)) {
1332 log_info(LD_DIR, "Generating consensus using method %d.",
1333 consensus_method);
1334 } else {
1335 log_warn(LD_DIR, "The other authorities will use consensus method %d, "
1336 "which I don't support. Maybe I should upgrade!",
1337 consensus_method);
1338 consensus_method = MAX_SUPPORTED_CONSENSUS_METHOD;
1341 /* Compute medians of time-related things, and figure out how many
1342 * routers we might need to talk about. */
1344 int n_votes = smartlist_len(votes);
1345 time_t *va_times = tor_calloc(n_votes, sizeof(time_t));
1346 time_t *fu_times = tor_calloc(n_votes, sizeof(time_t));
1347 time_t *vu_times = tor_calloc(n_votes, sizeof(time_t));
1348 int *votesec_list = tor_calloc(n_votes, sizeof(int));
1349 int *distsec_list = tor_calloc(n_votes, sizeof(int));
1350 int n_versioning_clients = 0, n_versioning_servers = 0;
1351 smartlist_t *combined_client_versions = smartlist_new();
1352 smartlist_t *combined_server_versions = smartlist_new();
1354 SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
1355 tor_assert(v->type == NS_TYPE_VOTE);
1356 va_times[v_sl_idx] = v->valid_after;
1357 fu_times[v_sl_idx] = v->fresh_until;
1358 vu_times[v_sl_idx] = v->valid_until;
1359 votesec_list[v_sl_idx] = v->vote_seconds;
1360 distsec_list[v_sl_idx] = v->dist_seconds;
1361 if (v->client_versions) {
1362 smartlist_t *cv = smartlist_new();
1363 ++n_versioning_clients;
1364 smartlist_split_string(cv, v->client_versions, ",",
1365 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
1366 sort_version_list(cv, 1);
1367 smartlist_add_all(combined_client_versions, cv);
1368 smartlist_free(cv); /* elements get freed later. */
1370 if (v->server_versions) {
1371 smartlist_t *sv = smartlist_new();
1372 ++n_versioning_servers;
1373 smartlist_split_string(sv, v->server_versions, ",",
1374 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
1375 sort_version_list(sv, 1);
1376 smartlist_add_all(combined_server_versions, sv);
1377 smartlist_free(sv); /* elements get freed later. */
1379 SMARTLIST_FOREACH(v->known_flags, const char *, cp,
1380 smartlist_add(flags, tor_strdup(cp)));
1381 } SMARTLIST_FOREACH_END(v);
1382 valid_after = median_time(va_times, n_votes);
1383 fresh_until = median_time(fu_times, n_votes);
1384 valid_until = median_time(vu_times, n_votes);
1385 vote_seconds = median_int(votesec_list, n_votes);
1386 dist_seconds = median_int(distsec_list, n_votes);
1388 tor_assert(valid_after +
1389 (get_options()->TestingTorNetwork ?
1390 MIN_VOTE_INTERVAL_TESTING : MIN_VOTE_INTERVAL) <= fresh_until);
1391 tor_assert(fresh_until +
1392 (get_options()->TestingTorNetwork ?
1393 MIN_VOTE_INTERVAL_TESTING : MIN_VOTE_INTERVAL) <= valid_until);
1394 tor_assert(vote_seconds >= MIN_VOTE_SECONDS);
1395 tor_assert(dist_seconds >= MIN_DIST_SECONDS);
1397 server_versions = compute_consensus_versions_list(combined_server_versions,
1398 n_versioning_servers);
1399 client_versions = compute_consensus_versions_list(combined_client_versions,
1400 n_versioning_clients);
1401 if (consensus_method >= MIN_METHOD_FOR_PACKAGE_LINES) {
1402 packages = compute_consensus_package_lines(votes);
1403 } else {
1404 packages = tor_strdup("");
1407 SMARTLIST_FOREACH(combined_server_versions, char *, cp, tor_free(cp));
1408 SMARTLIST_FOREACH(combined_client_versions, char *, cp, tor_free(cp));
1409 smartlist_free(combined_server_versions);
1410 smartlist_free(combined_client_versions);
1412 if (consensus_method >= MIN_METHOD_FOR_ED25519_ID_VOTING)
1413 smartlist_add(flags, tor_strdup("NoEdConsensus"));
1415 smartlist_sort_strings(flags);
1416 smartlist_uniq_strings(flags);
1418 tor_free(va_times);
1419 tor_free(fu_times);
1420 tor_free(vu_times);
1421 tor_free(votesec_list);
1422 tor_free(distsec_list);
1425 chunks = smartlist_new();
1428 char va_buf[ISO_TIME_LEN+1], fu_buf[ISO_TIME_LEN+1],
1429 vu_buf[ISO_TIME_LEN+1];
1430 char *flaglist;
1431 format_iso_time(va_buf, valid_after);
1432 format_iso_time(fu_buf, fresh_until);
1433 format_iso_time(vu_buf, valid_until);
1434 flaglist = smartlist_join_strings(flags, " ", 0, NULL);
1436 smartlist_add_asprintf(chunks, "network-status-version 3%s%s\n"
1437 "vote-status consensus\n",
1438 flavor == FLAV_NS ? "" : " ",
1439 flavor == FLAV_NS ? "" : flavor_name);
1441 smartlist_add_asprintf(chunks, "consensus-method %d\n",
1442 consensus_method);
1444 smartlist_add_asprintf(chunks,
1445 "valid-after %s\n"
1446 "fresh-until %s\n"
1447 "valid-until %s\n"
1448 "voting-delay %d %d\n"
1449 "client-versions %s\n"
1450 "server-versions %s\n"
1451 "%s" /* packages */
1452 "known-flags %s\n",
1453 va_buf, fu_buf, vu_buf,
1454 vote_seconds, dist_seconds,
1455 client_versions, server_versions,
1456 packages,
1457 flaglist);
1459 tor_free(flaglist);
1462 if (consensus_method >= MIN_METHOD_FOR_RECOMMENDED_PROTOCOLS) {
1463 int num_dirauth = get_n_authorities(V3_DIRINFO);
1464 int idx;
1465 for (idx = 0; idx < 4; ++idx) {
1466 char *proto_line = compute_nth_protocol_set(idx, num_dirauth, votes);
1467 if (BUG(!proto_line))
1468 continue;
1469 smartlist_add(chunks, proto_line);
1473 param_list = dirvote_compute_params(votes, consensus_method,
1474 total_authorities);
1475 if (smartlist_len(param_list)) {
1476 params = smartlist_join_strings(param_list, " ", 0, NULL);
1477 smartlist_add(chunks, tor_strdup("params "));
1478 smartlist_add(chunks, params);
1479 smartlist_add(chunks, tor_strdup("\n"));
1482 if (consensus_method >= MIN_METHOD_FOR_SHARED_RANDOM) {
1483 int num_dirauth = get_n_authorities(V3_DIRINFO);
1484 /* Default value of this is 2/3 of the total number of authorities. For
1485 * instance, if we have 9 dirauth, the default value is 6. The following
1486 * calculation will round it down. */
1487 int32_t num_srv_agreements =
1488 dirvote_get_intermediate_param_value(param_list,
1489 "AuthDirNumSRVAgreements",
1490 (num_dirauth * 2) / 3);
1491 /* Add the shared random value. */
1492 char *srv_lines = sr_get_string_for_consensus(votes, num_srv_agreements);
1493 if (srv_lines != NULL) {
1494 smartlist_add(chunks, srv_lines);
1498 /* Sort the votes. */
1499 smartlist_sort(votes, compare_votes_by_authority_id_);
1500 /* Add the authority sections. */
1502 smartlist_t *dir_sources = smartlist_new();
1503 SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
1504 dir_src_ent_t *e = tor_malloc_zero(sizeof(dir_src_ent_t));
1505 e->v = v;
1506 e->digest = get_voter(v)->identity_digest;
1507 e->is_legacy = 0;
1508 smartlist_add(dir_sources, e);
1509 if (!tor_digest_is_zero(get_voter(v)->legacy_id_digest)) {
1510 dir_src_ent_t *e_legacy = tor_malloc_zero(sizeof(dir_src_ent_t));
1511 e_legacy->v = v;
1512 e_legacy->digest = get_voter(v)->legacy_id_digest;
1513 e_legacy->is_legacy = 1;
1514 smartlist_add(dir_sources, e_legacy);
1516 } SMARTLIST_FOREACH_END(v);
1517 smartlist_sort(dir_sources, compare_dir_src_ents_by_authority_id_);
1519 SMARTLIST_FOREACH_BEGIN(dir_sources, const dir_src_ent_t *, e) {
1520 char fingerprint[HEX_DIGEST_LEN+1];
1521 char votedigest[HEX_DIGEST_LEN+1];
1522 networkstatus_t *v = e->v;
1523 networkstatus_voter_info_t *voter = get_voter(v);
1525 base16_encode(fingerprint, sizeof(fingerprint), e->digest, DIGEST_LEN);
1526 base16_encode(votedigest, sizeof(votedigest), voter->vote_digest,
1527 DIGEST_LEN);
1529 smartlist_add_asprintf(chunks,
1530 "dir-source %s%s %s %s %s %d %d\n",
1531 voter->nickname, e->is_legacy ? "-legacy" : "",
1532 fingerprint, voter->address, fmt_addr32(voter->addr),
1533 voter->dir_port,
1534 voter->or_port);
1535 if (! e->is_legacy) {
1536 smartlist_add_asprintf(chunks,
1537 "contact %s\n"
1538 "vote-digest %s\n",
1539 voter->contact,
1540 votedigest);
1542 } SMARTLIST_FOREACH_END(e);
1543 SMARTLIST_FOREACH(dir_sources, dir_src_ent_t *, e, tor_free(e));
1544 smartlist_free(dir_sources);
1547 if (consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW) {
1548 char *max_unmeasured_param = NULL;
1549 /* XXXX Extract this code into a common function. Or don't! see #19011 */
1550 if (params) {
1551 if (strcmpstart(params, "maxunmeasuredbw=") == 0)
1552 max_unmeasured_param = params;
1553 else
1554 max_unmeasured_param = strstr(params, " maxunmeasuredbw=");
1556 if (max_unmeasured_param) {
1557 int ok = 0;
1558 char *eq = strchr(max_unmeasured_param, '=');
1559 if (eq) {
1560 max_unmeasured_bw_kb = (uint32_t)
1561 tor_parse_ulong(eq+1, 10, 1, UINT32_MAX, &ok, NULL);
1562 if (!ok) {
1563 log_warn(LD_DIR, "Bad element '%s' in max unmeasured bw param",
1564 escaped(max_unmeasured_param));
1565 max_unmeasured_bw_kb = DEFAULT_MAX_UNMEASURED_BW_KB;
1571 /* Add the actual router entries. */
1573 int *size; /* size[j] is the number of routerstatuses in votes[j]. */
1574 int *flag_counts; /* The number of voters that list flag[j] for the
1575 * currently considered router. */
1576 int i;
1577 smartlist_t *matching_descs = smartlist_new();
1578 smartlist_t *chosen_flags = smartlist_new();
1579 smartlist_t *versions = smartlist_new();
1580 smartlist_t *protocols = smartlist_new();
1581 smartlist_t *exitsummaries = smartlist_new();
1582 uint32_t *bandwidths_kb = tor_calloc(smartlist_len(votes),
1583 sizeof(uint32_t));
1584 uint32_t *measured_bws_kb = tor_calloc(smartlist_len(votes),
1585 sizeof(uint32_t));
1586 uint32_t *measured_guardfraction = tor_calloc(smartlist_len(votes),
1587 sizeof(uint32_t));
1588 int num_bandwidths;
1589 int num_mbws;
1590 int num_guardfraction_inputs;
1592 int *n_voter_flags; /* n_voter_flags[j] is the number of flags that
1593 * votes[j] knows about. */
1594 int *n_flag_voters; /* n_flag_voters[f] is the number of votes that care
1595 * about flags[f]. */
1596 int **flag_map; /* flag_map[j][b] is an index f such that flag_map[f]
1597 * is the same flag as votes[j]->known_flags[b]. */
1598 int *named_flag; /* Index of the flag "Named" for votes[j] */
1599 int *unnamed_flag; /* Index of the flag "Unnamed" for votes[j] */
1600 int n_authorities_measuring_bandwidth;
1602 strmap_t *name_to_id_map = strmap_new();
1603 char conflict[DIGEST_LEN];
1604 char unknown[DIGEST_LEN];
1605 memset(conflict, 0, sizeof(conflict));
1606 memset(unknown, 0xff, sizeof(conflict));
1608 size = tor_calloc(smartlist_len(votes), sizeof(int));
1609 n_voter_flags = tor_calloc(smartlist_len(votes), sizeof(int));
1610 n_flag_voters = tor_calloc(smartlist_len(flags), sizeof(int));
1611 flag_map = tor_calloc(smartlist_len(votes), sizeof(int *));
1612 named_flag = tor_calloc(smartlist_len(votes), sizeof(int));
1613 unnamed_flag = tor_calloc(smartlist_len(votes), sizeof(int));
1614 for (i = 0; i < smartlist_len(votes); ++i)
1615 unnamed_flag[i] = named_flag[i] = -1;
1617 /* Build the flag indexes. Note that no vote can have more than 64 members
1618 * for known_flags, so no value will be greater than 63, so it's safe to
1619 * do U64_LITERAL(1) << index on these values. But note also that
1620 * named_flag and unnamed_flag are initialized to -1, so we need to check
1621 * that they're actually set before doing U64_LITERAL(1) << index with
1622 * them.*/
1623 SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
1624 flag_map[v_sl_idx] = tor_calloc(smartlist_len(v->known_flags),
1625 sizeof(int));
1626 if (smartlist_len(v->known_flags) > MAX_KNOWN_FLAGS_IN_VOTE) {
1627 log_warn(LD_BUG, "Somehow, a vote has %d entries in known_flags",
1628 smartlist_len(v->known_flags));
1630 SMARTLIST_FOREACH_BEGIN(v->known_flags, const char *, fl) {
1631 int p = smartlist_string_pos(flags, fl);
1632 tor_assert(p >= 0);
1633 flag_map[v_sl_idx][fl_sl_idx] = p;
1634 ++n_flag_voters[p];
1635 if (!strcmp(fl, "Named"))
1636 named_flag[v_sl_idx] = fl_sl_idx;
1637 if (!strcmp(fl, "Unnamed"))
1638 unnamed_flag[v_sl_idx] = fl_sl_idx;
1639 } SMARTLIST_FOREACH_END(fl);
1640 n_voter_flags[v_sl_idx] = smartlist_len(v->known_flags);
1641 size[v_sl_idx] = smartlist_len(v->routerstatus_list);
1642 } SMARTLIST_FOREACH_END(v);
1644 /* Named and Unnamed get treated specially */
1646 SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
1647 uint64_t nf;
1648 if (named_flag[v_sl_idx]<0)
1649 continue;
1650 nf = U64_LITERAL(1) << named_flag[v_sl_idx];
1651 SMARTLIST_FOREACH_BEGIN(v->routerstatus_list,
1652 vote_routerstatus_t *, rs) {
1654 if ((rs->flags & nf) != 0) {
1655 const char *d = strmap_get_lc(name_to_id_map, rs->status.nickname);
1656 if (!d) {
1657 /* We have no name officially mapped to this digest. */
1658 strmap_set_lc(name_to_id_map, rs->status.nickname,
1659 rs->status.identity_digest);
1660 } else if (d != conflict &&
1661 fast_memcmp(d, rs->status.identity_digest, DIGEST_LEN)) {
1662 /* Authorities disagree about this nickname. */
1663 strmap_set_lc(name_to_id_map, rs->status.nickname, conflict);
1664 } else {
1665 /* It's already a conflict, or it's already this ID. */
1668 } SMARTLIST_FOREACH_END(rs);
1669 } SMARTLIST_FOREACH_END(v);
1671 SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
1672 uint64_t uf;
1673 if (unnamed_flag[v_sl_idx]<0)
1674 continue;
1675 uf = U64_LITERAL(1) << unnamed_flag[v_sl_idx];
1676 SMARTLIST_FOREACH_BEGIN(v->routerstatus_list,
1677 vote_routerstatus_t *, rs) {
1678 if ((rs->flags & uf) != 0) {
1679 const char *d = strmap_get_lc(name_to_id_map, rs->status.nickname);
1680 if (d == conflict || d == unknown) {
1681 /* Leave it alone; we know what it is. */
1682 } else if (!d) {
1683 /* We have no name officially mapped to this digest. */
1684 strmap_set_lc(name_to_id_map, rs->status.nickname, unknown);
1685 } else if (fast_memeq(d, rs->status.identity_digest, DIGEST_LEN)) {
1686 /* Authorities disagree about this nickname. */
1687 strmap_set_lc(name_to_id_map, rs->status.nickname, conflict);
1688 } else {
1689 /* It's mapped to a different name. */
1692 } SMARTLIST_FOREACH_END(rs);
1693 } SMARTLIST_FOREACH_END(v);
1696 /* We need to know how many votes measure bandwidth. */
1697 n_authorities_measuring_bandwidth = 0;
1698 SMARTLIST_FOREACH(votes, const networkstatus_t *, v,
1699 if (v->has_measured_bws) {
1700 ++n_authorities_measuring_bandwidth;
1704 /* Populate the collator */
1705 collator = dircollator_new(smartlist_len(votes), total_authorities);
1706 SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
1707 dircollator_add_vote(collator, v);
1708 } SMARTLIST_FOREACH_END(v);
1710 dircollator_collate(collator, consensus_method);
1712 /* Now go through all the votes */
1713 flag_counts = tor_calloc(smartlist_len(flags), sizeof(int));
1714 const int num_routers = dircollator_n_routers(collator);
1715 for (i = 0; i < num_routers; ++i) {
1716 vote_routerstatus_t **vrs_lst =
1717 dircollator_get_votes_for_router(collator, i);
1719 vote_routerstatus_t *rs;
1720 routerstatus_t rs_out;
1721 const char *current_rsa_id = NULL;
1722 const char *chosen_version;
1723 const char *chosen_protocol_list;
1724 const char *chosen_name = NULL;
1725 int exitsummary_disagreement = 0;
1726 int is_named = 0, is_unnamed = 0, is_running = 0, is_valid = 0;
1727 int is_guard = 0, is_exit = 0, is_bad_exit = 0;
1728 int naming_conflict = 0;
1729 int n_listing = 0;
1730 char microdesc_digest[DIGEST256_LEN];
1731 tor_addr_port_t alt_orport = {TOR_ADDR_NULL, 0};
1733 memset(flag_counts, 0, sizeof(int)*smartlist_len(flags));
1734 smartlist_clear(matching_descs);
1735 smartlist_clear(chosen_flags);
1736 smartlist_clear(versions);
1737 smartlist_clear(protocols);
1738 num_bandwidths = 0;
1739 num_mbws = 0;
1740 num_guardfraction_inputs = 0;
1741 int ed_consensus = 0;
1742 const uint8_t *ed_consensus_val = NULL;
1744 /* Okay, go through all the entries for this digest. */
1745 for (int voter_idx = 0; voter_idx < smartlist_len(votes); ++voter_idx) {
1746 if (vrs_lst[voter_idx] == NULL)
1747 continue; /* This voter had nothing to say about this entry. */
1748 rs = vrs_lst[voter_idx];
1749 ++n_listing;
1751 current_rsa_id = rs->status.identity_digest;
1753 smartlist_add(matching_descs, rs);
1754 if (rs->version && rs->version[0])
1755 smartlist_add(versions, rs->version);
1757 if (rs->protocols) {
1758 /* We include this one even if it's empty: voting for an
1759 * empty protocol list actually is meaningful. */
1760 smartlist_add(protocols, rs->protocols);
1763 /* Tally up all the flags. */
1764 for (int flag = 0; flag < n_voter_flags[voter_idx]; ++flag) {
1765 if (rs->flags & (U64_LITERAL(1) << flag))
1766 ++flag_counts[flag_map[voter_idx][flag]];
1768 if (named_flag[voter_idx] >= 0 &&
1769 (rs->flags & (U64_LITERAL(1) << named_flag[voter_idx]))) {
1770 if (chosen_name && strcmp(chosen_name, rs->status.nickname)) {
1771 log_notice(LD_DIR, "Conflict on naming for router: %s vs %s",
1772 chosen_name, rs->status.nickname);
1773 naming_conflict = 1;
1775 chosen_name = rs->status.nickname;
1778 /* Count guardfraction votes and note down the values. */
1779 if (rs->status.has_guardfraction) {
1780 measured_guardfraction[num_guardfraction_inputs++] =
1781 rs->status.guardfraction_percentage;
1784 /* count bandwidths */
1785 if (rs->has_measured_bw)
1786 measured_bws_kb[num_mbws++] = rs->measured_bw_kb;
1788 if (rs->status.has_bandwidth)
1789 bandwidths_kb[num_bandwidths++] = rs->status.bandwidth_kb;
1791 /* Count number for which ed25519 is canonical. */
1792 if (rs->ed25519_reflects_consensus) {
1793 ++ed_consensus;
1794 if (ed_consensus_val) {
1795 tor_assert(fast_memeq(ed_consensus_val, rs->ed25519_id,
1796 ED25519_PUBKEY_LEN));
1797 } else {
1798 ed_consensus_val = rs->ed25519_id;
1803 /* We don't include this router at all unless more than half of
1804 * the authorities we believe in list it. */
1805 if (n_listing <= total_authorities/2)
1806 continue;
1808 if (ed_consensus > 0) {
1809 tor_assert(consensus_method >= MIN_METHOD_FOR_ED25519_ID_VOTING);
1810 if (ed_consensus <= total_authorities / 2) {
1811 log_warn(LD_BUG, "Not enough entries had ed_consensus set; how "
1812 "can we have a consensus of %d?", ed_consensus);
1816 /* The clangalyzer can't figure out that this will never be NULL
1817 * if n_listing is at least 1 */
1818 tor_assert(current_rsa_id);
1820 /* Figure out the most popular opinion of what the most recent
1821 * routerinfo and its contents are. */
1822 memset(microdesc_digest, 0, sizeof(microdesc_digest));
1823 rs = compute_routerstatus_consensus(matching_descs, consensus_method,
1824 microdesc_digest, &alt_orport);
1825 /* Copy bits of that into rs_out. */
1826 memset(&rs_out, 0, sizeof(rs_out));
1827 tor_assert(fast_memeq(current_rsa_id,
1828 rs->status.identity_digest,DIGEST_LEN));
1829 memcpy(rs_out.identity_digest, current_rsa_id, DIGEST_LEN);
1830 memcpy(rs_out.descriptor_digest, rs->status.descriptor_digest,
1831 DIGEST_LEN);
1832 rs_out.addr = rs->status.addr;
1833 rs_out.published_on = rs->status.published_on;
1834 rs_out.dir_port = rs->status.dir_port;
1835 rs_out.or_port = rs->status.or_port;
1836 if (consensus_method >= MIN_METHOD_FOR_A_LINES) {
1837 tor_addr_copy(&rs_out.ipv6_addr, &alt_orport.addr);
1838 rs_out.ipv6_orport = alt_orport.port;
1840 rs_out.has_bandwidth = 0;
1841 rs_out.has_exitsummary = 0;
1843 if (chosen_name && !naming_conflict) {
1844 strlcpy(rs_out.nickname, chosen_name, sizeof(rs_out.nickname));
1845 } else {
1846 strlcpy(rs_out.nickname, rs->status.nickname, sizeof(rs_out.nickname));
1850 const char *d = strmap_get_lc(name_to_id_map, rs_out.nickname);
1851 if (!d) {
1852 is_named = is_unnamed = 0;
1853 } else if (fast_memeq(d, current_rsa_id, DIGEST_LEN)) {
1854 is_named = 1; is_unnamed = 0;
1855 } else {
1856 is_named = 0; is_unnamed = 1;
1860 /* Set the flags. */
1861 smartlist_add(chosen_flags, (char*)"s"); /* for the start of the line. */
1862 SMARTLIST_FOREACH_BEGIN(flags, const char *, fl) {
1863 if (!strcmp(fl, "Named")) {
1864 if (is_named)
1865 smartlist_add(chosen_flags, (char*)fl);
1866 } else if (!strcmp(fl, "Unnamed")) {
1867 if (is_unnamed)
1868 smartlist_add(chosen_flags, (char*)fl);
1869 } else if (!strcmp(fl, "NoEdConsensus") &&
1870 consensus_method >= MIN_METHOD_FOR_ED25519_ID_VOTING) {
1871 if (ed_consensus <= total_authorities/2)
1872 smartlist_add(chosen_flags, (char*)fl);
1873 } else {
1874 if (flag_counts[fl_sl_idx] > n_flag_voters[fl_sl_idx]/2) {
1875 smartlist_add(chosen_flags, (char*)fl);
1876 if (!strcmp(fl, "Exit"))
1877 is_exit = 1;
1878 else if (!strcmp(fl, "Guard"))
1879 is_guard = 1;
1880 else if (!strcmp(fl, "Running"))
1881 is_running = 1;
1882 else if (!strcmp(fl, "BadExit"))
1883 is_bad_exit = 1;
1884 else if (!strcmp(fl, "Valid"))
1885 is_valid = 1;
1888 } SMARTLIST_FOREACH_END(fl);
1890 /* Starting with consensus method 4 we do not list servers
1891 * that are not running in a consensus. See Proposal 138 */
1892 if (!is_running)
1893 continue;
1895 /* Starting with consensus method 24, we don't list servers
1896 * that are not valid in a consensus. See Proposal 272 */
1897 if (!is_valid &&
1898 consensus_method >= MIN_METHOD_FOR_EXCLUDING_INVALID_NODES)
1899 continue;
1901 /* Pick the version. */
1902 if (smartlist_len(versions)) {
1903 sort_version_list(versions, 0);
1904 chosen_version = get_most_frequent_member(versions);
1905 } else {
1906 chosen_version = NULL;
1909 /* Pick the protocol list */
1910 if (smartlist_len(protocols)) {
1911 smartlist_sort_strings(protocols);
1912 chosen_protocol_list = get_most_frequent_member(protocols);
1913 } else {
1914 chosen_protocol_list = NULL;
1917 /* If it's a guard and we have enough guardfraction votes,
1918 calculate its consensus guardfraction value. */
1919 if (is_guard && num_guardfraction_inputs > 2 &&
1920 consensus_method >= MIN_METHOD_FOR_GUARDFRACTION) {
1921 rs_out.has_guardfraction = 1;
1922 rs_out.guardfraction_percentage = median_uint32(measured_guardfraction,
1923 num_guardfraction_inputs);
1924 /* final value should be an integer percentage! */
1925 tor_assert(rs_out.guardfraction_percentage <= 100);
1928 /* Pick a bandwidth */
1929 if (num_mbws > 2) {
1930 rs_out.has_bandwidth = 1;
1931 rs_out.bw_is_unmeasured = 0;
1932 rs_out.bandwidth_kb = median_uint32(measured_bws_kb, num_mbws);
1933 } else if (num_bandwidths > 0) {
1934 rs_out.has_bandwidth = 1;
1935 rs_out.bw_is_unmeasured = 1;
1936 rs_out.bandwidth_kb = median_uint32(bandwidths_kb, num_bandwidths);
1937 if (consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW &&
1938 n_authorities_measuring_bandwidth > 2) {
1939 /* Cap non-measured bandwidths. */
1940 if (rs_out.bandwidth_kb > max_unmeasured_bw_kb) {
1941 rs_out.bandwidth_kb = max_unmeasured_bw_kb;
1946 /* Fix bug 2203: Do not count BadExit nodes as Exits for bw weights */
1947 is_exit = is_exit && !is_bad_exit;
1949 /* Update total bandwidth weights with the bandwidths of this router. */
1951 update_total_bandwidth_weights(&rs_out,
1952 is_exit, is_guard,
1953 &G, &M, &E, &D, &T);
1956 /* Ok, we already picked a descriptor digest we want to list
1957 * previously. Now we want to use the exit policy summary from
1958 * that descriptor. If everybody plays nice all the voters who
1959 * listed that descriptor will have the same summary. If not then
1960 * something is fishy and we'll use the most common one (breaking
1961 * ties in favor of lexicographically larger one (only because it
1962 * lets me reuse more existing code)).
1964 * The other case that can happen is that no authority that voted
1965 * for that descriptor has an exit policy summary. That's
1966 * probably quite unlikely but can happen. In that case we use
1967 * the policy that was most often listed in votes, again breaking
1968 * ties like in the previous case.
1971 /* Okay, go through all the votes for this router. We prepared
1972 * that list previously */
1973 const char *chosen_exitsummary = NULL;
1974 smartlist_clear(exitsummaries);
1975 SMARTLIST_FOREACH_BEGIN(matching_descs, vote_routerstatus_t *, vsr) {
1976 /* Check if the vote where this status comes from had the
1977 * proper descriptor */
1978 tor_assert(fast_memeq(rs_out.identity_digest,
1979 vsr->status.identity_digest,
1980 DIGEST_LEN));
1981 if (vsr->status.has_exitsummary &&
1982 fast_memeq(rs_out.descriptor_digest,
1983 vsr->status.descriptor_digest,
1984 DIGEST_LEN)) {
1985 tor_assert(vsr->status.exitsummary);
1986 smartlist_add(exitsummaries, vsr->status.exitsummary);
1987 if (!chosen_exitsummary) {
1988 chosen_exitsummary = vsr->status.exitsummary;
1989 } else if (strcmp(chosen_exitsummary, vsr->status.exitsummary)) {
1990 /* Great. There's disagreement among the voters. That
1991 * really shouldn't be */
1992 exitsummary_disagreement = 1;
1995 } SMARTLIST_FOREACH_END(vsr);
1997 if (exitsummary_disagreement) {
1998 char id[HEX_DIGEST_LEN+1];
1999 char dd[HEX_DIGEST_LEN+1];
2000 base16_encode(id, sizeof(dd), rs_out.identity_digest, DIGEST_LEN);
2001 base16_encode(dd, sizeof(dd), rs_out.descriptor_digest, DIGEST_LEN);
2002 log_warn(LD_DIR, "The voters disagreed on the exit policy summary "
2003 " for router %s with descriptor %s. This really shouldn't"
2004 " have happened.", id, dd);
2006 smartlist_sort_strings(exitsummaries);
2007 chosen_exitsummary = get_most_frequent_member(exitsummaries);
2008 } else if (!chosen_exitsummary) {
2009 char id[HEX_DIGEST_LEN+1];
2010 char dd[HEX_DIGEST_LEN+1];
2011 base16_encode(id, sizeof(dd), rs_out.identity_digest, DIGEST_LEN);
2012 base16_encode(dd, sizeof(dd), rs_out.descriptor_digest, DIGEST_LEN);
2013 log_warn(LD_DIR, "Not one of the voters that made us select"
2014 "descriptor %s for router %s had an exit policy"
2015 "summary", dd, id);
2017 /* Ok, none of those voting for the digest we chose had an
2018 * exit policy for us. Well, that kinda sucks.
2020 smartlist_clear(exitsummaries);
2021 SMARTLIST_FOREACH(matching_descs, vote_routerstatus_t *, vsr, {
2022 if (vsr->status.has_exitsummary)
2023 smartlist_add(exitsummaries, vsr->status.exitsummary);
2025 smartlist_sort_strings(exitsummaries);
2026 chosen_exitsummary = get_most_frequent_member(exitsummaries);
2028 if (!chosen_exitsummary)
2029 log_warn(LD_DIR, "Wow, not one of the voters had an exit "
2030 "policy summary for %s. Wow.", id);
2033 if (chosen_exitsummary) {
2034 rs_out.has_exitsummary = 1;
2035 /* yea, discards the const */
2036 rs_out.exitsummary = (char *)chosen_exitsummary;
2040 if (flavor == FLAV_MICRODESC &&
2041 tor_digest256_is_zero(microdesc_digest)) {
2042 /* With no microdescriptor digest, we omit the entry entirely. */
2043 continue;
2047 char *buf;
2048 /* Okay!! Now we can write the descriptor... */
2049 /* First line goes into "buf". */
2050 buf = routerstatus_format_entry(&rs_out, NULL, NULL, rs_format, NULL);
2051 if (buf)
2052 smartlist_add(chunks, buf);
2054 /* Now an m line, if applicable. */
2055 if (flavor == FLAV_MICRODESC &&
2056 !tor_digest256_is_zero(microdesc_digest)) {
2057 char m[BASE64_DIGEST256_LEN+1];
2058 digest256_to_base64(m, microdesc_digest);
2059 smartlist_add_asprintf(chunks, "m %s\n", m);
2061 /* Next line is all flags. The "\n" is missing. */
2062 smartlist_add(chunks,
2063 smartlist_join_strings(chosen_flags, " ", 0, NULL));
2064 /* Now the version line. */
2065 if (chosen_version) {
2066 smartlist_add(chunks, tor_strdup("\nv "));
2067 smartlist_add(chunks, tor_strdup(chosen_version));
2069 smartlist_add(chunks, tor_strdup("\n"));
2070 if (chosen_protocol_list &&
2071 consensus_method >= MIN_METHOD_FOR_RS_PROTOCOLS) {
2072 smartlist_add_asprintf(chunks, "pr %s\n", chosen_protocol_list);
2074 /* Now the weight line. */
2075 if (rs_out.has_bandwidth) {
2076 char *guardfraction_str = NULL;
2077 int unmeasured = rs_out.bw_is_unmeasured &&
2078 consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW;
2080 /* If we have guardfraction info, include it in the 'w' line. */
2081 if (rs_out.has_guardfraction) {
2082 tor_asprintf(&guardfraction_str,
2083 " GuardFraction=%u", rs_out.guardfraction_percentage);
2085 smartlist_add_asprintf(chunks, "w Bandwidth=%d%s%s\n",
2086 rs_out.bandwidth_kb,
2087 unmeasured?" Unmeasured=1":"",
2088 guardfraction_str ? guardfraction_str : "");
2090 tor_free(guardfraction_str);
2093 /* Now the exitpolicy summary line. */
2094 if (rs_out.has_exitsummary && flavor == FLAV_NS) {
2095 smartlist_add_asprintf(chunks, "p %s\n", rs_out.exitsummary);
2098 /* And the loop is over and we move on to the next router */
2101 tor_free(size);
2102 tor_free(n_voter_flags);
2103 tor_free(n_flag_voters);
2104 for (i = 0; i < smartlist_len(votes); ++i)
2105 tor_free(flag_map[i]);
2106 tor_free(flag_map);
2107 tor_free(flag_counts);
2108 tor_free(named_flag);
2109 tor_free(unnamed_flag);
2110 strmap_free(name_to_id_map, NULL);
2111 smartlist_free(matching_descs);
2112 smartlist_free(chosen_flags);
2113 smartlist_free(versions);
2114 smartlist_free(protocols);
2115 smartlist_free(exitsummaries);
2116 tor_free(bandwidths_kb);
2117 tor_free(measured_bws_kb);
2118 tor_free(measured_guardfraction);
2121 /* Mark the directory footer region */
2122 smartlist_add(chunks, tor_strdup("directory-footer\n"));
2125 int64_t weight_scale = BW_WEIGHT_SCALE;
2126 char *bw_weight_param = NULL;
2128 // Parse params, extract BW_WEIGHT_SCALE if present
2129 // DO NOT use consensus_param_bw_weight_scale() in this code!
2130 // The consensus is not formed yet!
2131 /* XXXX Extract this code into a common function. Or not: #19011. */
2132 if (params) {
2133 if (strcmpstart(params, "bwweightscale=") == 0)
2134 bw_weight_param = params;
2135 else
2136 bw_weight_param = strstr(params, " bwweightscale=");
2139 if (bw_weight_param) {
2140 int ok=0;
2141 char *eq = strchr(bw_weight_param, '=');
2142 if (eq) {
2143 weight_scale = tor_parse_long(eq+1, 10, 1, INT32_MAX, &ok,
2144 NULL);
2145 if (!ok) {
2146 log_warn(LD_DIR, "Bad element '%s' in bw weight param",
2147 escaped(bw_weight_param));
2148 weight_scale = BW_WEIGHT_SCALE;
2150 } else {
2151 log_warn(LD_DIR, "Bad element '%s' in bw weight param",
2152 escaped(bw_weight_param));
2153 weight_scale = BW_WEIGHT_SCALE;
2157 added_weights = networkstatus_compute_bw_weights_v10(chunks, G, M, E, D,
2158 T, weight_scale);
2161 /* Add a signature. */
2163 char digest[DIGEST256_LEN];
2164 char fingerprint[HEX_DIGEST_LEN+1];
2165 char signing_key_fingerprint[HEX_DIGEST_LEN+1];
2166 digest_algorithm_t digest_alg =
2167 flavor == FLAV_NS ? DIGEST_SHA1 : DIGEST_SHA256;
2168 size_t digest_len =
2169 flavor == FLAV_NS ? DIGEST_LEN : DIGEST256_LEN;
2170 const char *algname = crypto_digest_algorithm_get_name(digest_alg);
2171 char *signature;
2173 smartlist_add(chunks, tor_strdup("directory-signature "));
2175 /* Compute the hash of the chunks. */
2176 crypto_digest_smartlist(digest, digest_len, chunks, "", digest_alg);
2178 /* Get the fingerprints */
2179 crypto_pk_get_fingerprint(identity_key, fingerprint, 0);
2180 crypto_pk_get_fingerprint(signing_key, signing_key_fingerprint, 0);
2182 /* add the junk that will go at the end of the line. */
2183 if (flavor == FLAV_NS) {
2184 smartlist_add_asprintf(chunks, "%s %s\n", fingerprint,
2185 signing_key_fingerprint);
2186 } else {
2187 smartlist_add_asprintf(chunks, "%s %s %s\n",
2188 algname, fingerprint,
2189 signing_key_fingerprint);
2191 /* And the signature. */
2192 if (!(signature = router_get_dirobj_signature(digest, digest_len,
2193 signing_key))) {
2194 log_warn(LD_BUG, "Couldn't sign consensus networkstatus.");
2195 goto done;
2197 smartlist_add(chunks, signature);
2199 if (legacy_id_key_digest && legacy_signing_key) {
2200 smartlist_add(chunks, tor_strdup("directory-signature "));
2201 base16_encode(fingerprint, sizeof(fingerprint),
2202 legacy_id_key_digest, DIGEST_LEN);
2203 crypto_pk_get_fingerprint(legacy_signing_key,
2204 signing_key_fingerprint, 0);
2205 if (flavor == FLAV_NS) {
2206 smartlist_add_asprintf(chunks, "%s %s\n", fingerprint,
2207 signing_key_fingerprint);
2208 } else {
2209 smartlist_add_asprintf(chunks, "%s %s %s\n",
2210 algname, fingerprint,
2211 signing_key_fingerprint);
2214 if (!(signature = router_get_dirobj_signature(digest, digest_len,
2215 legacy_signing_key))) {
2216 log_warn(LD_BUG, "Couldn't sign consensus networkstatus.");
2217 goto done;
2219 smartlist_add(chunks, signature);
2223 result = smartlist_join_strings(chunks, "", 0, NULL);
2226 networkstatus_t *c;
2227 if (!(c = networkstatus_parse_vote_from_string(result, NULL,
2228 NS_TYPE_CONSENSUS))) {
2229 log_err(LD_BUG, "Generated a networkstatus consensus we couldn't "
2230 "parse.");
2231 tor_free(result);
2232 goto done;
2234 // Verify balancing parameters
2235 if (added_weights) {
2236 networkstatus_verify_bw_weights(c, consensus_method);
2238 networkstatus_vote_free(c);
2241 done:
2243 dircollator_free(collator);
2244 tor_free(client_versions);
2245 tor_free(server_versions);
2246 tor_free(packages);
2247 SMARTLIST_FOREACH(flags, char *, cp, tor_free(cp));
2248 smartlist_free(flags);
2249 SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
2250 smartlist_free(chunks);
2251 SMARTLIST_FOREACH(param_list, char *, cp, tor_free(cp));
2252 smartlist_free(param_list);
2254 return result;
2257 /** Given a list of networkstatus_t for each vote, return a newly allocated
2258 * string containing the "package" lines for the vote. */
2259 STATIC char *
2260 compute_consensus_package_lines(smartlist_t *votes)
2262 const int n_votes = smartlist_len(votes);
2264 /* This will be a map from "packagename version" strings to arrays
2265 * of const char *, with the i'th member of the array corresponding to the
2266 * package line from the i'th vote.
2268 strmap_t *package_status = strmap_new();
2270 SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
2271 if (! v->package_lines)
2272 continue;
2273 SMARTLIST_FOREACH_BEGIN(v->package_lines, const char *, line) {
2274 if (! validate_recommended_package_line(line))
2275 continue;
2277 /* Skip 'cp' to the second space in the line. */
2278 const char *cp = strchr(line, ' ');
2279 if (!cp) continue;
2280 ++cp;
2281 cp = strchr(cp, ' ');
2282 if (!cp) continue;
2284 char *key = tor_strndup(line, cp - line);
2286 const char **status = strmap_get(package_status, key);
2287 if (!status) {
2288 status = tor_calloc(n_votes, sizeof(const char *));
2289 strmap_set(package_status, key, status);
2291 status[v_sl_idx] = line; /* overwrite old value */
2292 tor_free(key);
2293 } SMARTLIST_FOREACH_END(line);
2294 } SMARTLIST_FOREACH_END(v);
2296 smartlist_t *entries = smartlist_new(); /* temporary */
2297 smartlist_t *result_list = smartlist_new(); /* output */
2298 STRMAP_FOREACH(package_status, key, const char **, values) {
2299 int i, count=-1;
2300 for (i = 0; i < n_votes; ++i) {
2301 if (values[i])
2302 smartlist_add(entries, (void*) values[i]);
2304 smartlist_sort_strings(entries);
2305 int n_voting_for_entry = smartlist_len(entries);
2306 const char *most_frequent =
2307 smartlist_get_most_frequent_string_(entries, &count);
2309 if (n_voting_for_entry >= 3 && count > n_voting_for_entry / 2) {
2310 smartlist_add_asprintf(result_list, "package %s\n", most_frequent);
2313 smartlist_clear(entries);
2315 } STRMAP_FOREACH_END;
2317 smartlist_sort_strings(result_list);
2319 char *result = smartlist_join_strings(result_list, "", 0, NULL);
2321 SMARTLIST_FOREACH(result_list, char *, cp, tor_free(cp));
2322 smartlist_free(result_list);
2323 smartlist_free(entries);
2324 strmap_free(package_status, tor_free_);
2326 return result;
2329 /** Given a consensus vote <b>target</b> and a set of detached signatures in
2330 * <b>sigs</b> that correspond to the same consensus, check whether there are
2331 * any new signatures in <b>src_voter_list</b> that should be added to
2332 * <b>target</b>. (A signature should be added if we have no signature for that
2333 * voter in <b>target</b> yet, or if we have no verifiable signature and the
2334 * new signature is verifiable.) Return the number of signatures added or
2335 * changed, or -1 if the document signed by <b>sigs</b> isn't the same
2336 * document as <b>target</b>. */
2338 networkstatus_add_detached_signatures(networkstatus_t *target,
2339 ns_detached_signatures_t *sigs,
2340 const char *source,
2341 int severity,
2342 const char **msg_out)
2344 int r = 0;
2345 const char *flavor;
2346 smartlist_t *siglist;
2347 tor_assert(sigs);
2348 tor_assert(target);
2349 tor_assert(target->type == NS_TYPE_CONSENSUS);
2351 flavor = networkstatus_get_flavor_name(target->flavor);
2353 /* Do the times seem right? */
2354 if (target->valid_after != sigs->valid_after) {
2355 *msg_out = "Valid-After times do not match "
2356 "when adding detached signatures to consensus";
2357 return -1;
2359 if (target->fresh_until != sigs->fresh_until) {
2360 *msg_out = "Fresh-until times do not match "
2361 "when adding detached signatures to consensus";
2362 return -1;
2364 if (target->valid_until != sigs->valid_until) {
2365 *msg_out = "Valid-until times do not match "
2366 "when adding detached signatures to consensus";
2367 return -1;
2369 siglist = strmap_get(sigs->signatures, flavor);
2370 if (!siglist) {
2371 *msg_out = "No signatures for given consensus flavor";
2372 return -1;
2375 /** Make sure all the digests we know match, and at least one matches. */
2377 common_digests_t *digests = strmap_get(sigs->digests, flavor);
2378 int n_matches = 0;
2379 int alg;
2380 if (!digests) {
2381 *msg_out = "No digests for given consensus flavor";
2382 return -1;
2384 for (alg = DIGEST_SHA1; alg < N_COMMON_DIGEST_ALGORITHMS; ++alg) {
2385 if (!tor_mem_is_zero(digests->d[alg], DIGEST256_LEN)) {
2386 if (fast_memeq(target->digests.d[alg], digests->d[alg],
2387 DIGEST256_LEN)) {
2388 ++n_matches;
2389 } else {
2390 *msg_out = "Mismatched digest.";
2391 return -1;
2395 if (!n_matches) {
2396 *msg_out = "No recognized digests for given consensus flavor";
2400 /* For each voter in src... */
2401 SMARTLIST_FOREACH_BEGIN(siglist, document_signature_t *, sig) {
2402 char voter_identity[HEX_DIGEST_LEN+1];
2403 networkstatus_voter_info_t *target_voter =
2404 networkstatus_get_voter_by_id(target, sig->identity_digest);
2405 authority_cert_t *cert = NULL;
2406 const char *algorithm;
2407 document_signature_t *old_sig = NULL;
2409 algorithm = crypto_digest_algorithm_get_name(sig->alg);
2411 base16_encode(voter_identity, sizeof(voter_identity),
2412 sig->identity_digest, DIGEST_LEN);
2413 log_info(LD_DIR, "Looking at signature from %s using %s", voter_identity,
2414 algorithm);
2415 /* If the target doesn't know about this voter, then forget it. */
2416 if (!target_voter) {
2417 log_info(LD_DIR, "We do not know any voter with ID %s", voter_identity);
2418 continue;
2421 old_sig = voter_get_sig_by_algorithm(target_voter, sig->alg);
2423 /* If the target already has a good signature from this voter, then skip
2424 * this one. */
2425 if (old_sig && old_sig->good_signature) {
2426 log_info(LD_DIR, "We already have a good signature from %s using %s",
2427 voter_identity, algorithm);
2428 continue;
2431 /* Try checking the signature if we haven't already. */
2432 if (!sig->good_signature && !sig->bad_signature) {
2433 cert = authority_cert_get_by_digests(sig->identity_digest,
2434 sig->signing_key_digest);
2435 if (cert) {
2436 /* Not checking the return value here, since we are going to look
2437 * at the status of sig->good_signature in a moment. */
2438 (void) networkstatus_check_document_signature(target, sig, cert);
2442 /* If this signature is good, or we don't have any signature yet,
2443 * then maybe add it. */
2444 if (sig->good_signature || !old_sig || old_sig->bad_signature) {
2445 log_info(LD_DIR, "Adding signature from %s with %s", voter_identity,
2446 algorithm);
2447 tor_log(severity, LD_DIR, "Added a signature for %s from %s.",
2448 target_voter->nickname, source);
2449 ++r;
2450 if (old_sig) {
2451 smartlist_remove(target_voter->sigs, old_sig);
2452 document_signature_free(old_sig);
2454 smartlist_add(target_voter->sigs, document_signature_dup(sig));
2455 } else {
2456 log_info(LD_DIR, "Not adding signature from %s", voter_identity);
2458 } SMARTLIST_FOREACH_END(sig);
2460 return r;
2463 /** Return a newly allocated string containing all the signatures on
2464 * <b>consensus</b> by all voters. If <b>for_detached_signatures</b> is true,
2465 * then the signatures will be put in a detached signatures document, so
2466 * prefix any non-NS-flavored signatures with "additional-signature" rather
2467 * than "directory-signature". */
2468 static char *
2469 networkstatus_format_signatures(networkstatus_t *consensus,
2470 int for_detached_signatures)
2472 smartlist_t *elements;
2473 char buf[4096];
2474 char *result = NULL;
2475 int n_sigs = 0;
2476 const consensus_flavor_t flavor = consensus->flavor;
2477 const char *flavor_name = networkstatus_get_flavor_name(flavor);
2478 const char *keyword;
2480 if (for_detached_signatures && flavor != FLAV_NS)
2481 keyword = "additional-signature";
2482 else
2483 keyword = "directory-signature";
2485 elements = smartlist_new();
2487 SMARTLIST_FOREACH_BEGIN(consensus->voters, networkstatus_voter_info_t *, v) {
2488 SMARTLIST_FOREACH_BEGIN(v->sigs, document_signature_t *, sig) {
2489 char sk[HEX_DIGEST_LEN+1];
2490 char id[HEX_DIGEST_LEN+1];
2491 if (!sig->signature || sig->bad_signature)
2492 continue;
2493 ++n_sigs;
2494 base16_encode(sk, sizeof(sk), sig->signing_key_digest, DIGEST_LEN);
2495 base16_encode(id, sizeof(id), sig->identity_digest, DIGEST_LEN);
2496 if (flavor == FLAV_NS) {
2497 smartlist_add_asprintf(elements,
2498 "%s %s %s\n-----BEGIN SIGNATURE-----\n",
2499 keyword, id, sk);
2500 } else {
2501 const char *digest_name =
2502 crypto_digest_algorithm_get_name(sig->alg);
2503 smartlist_add_asprintf(elements,
2504 "%s%s%s %s %s %s\n-----BEGIN SIGNATURE-----\n",
2505 keyword,
2506 for_detached_signatures ? " " : "",
2507 for_detached_signatures ? flavor_name : "",
2508 digest_name, id, sk);
2510 base64_encode(buf, sizeof(buf), sig->signature, sig->signature_len,
2511 BASE64_ENCODE_MULTILINE);
2512 strlcat(buf, "-----END SIGNATURE-----\n", sizeof(buf));
2513 smartlist_add(elements, tor_strdup(buf));
2514 } SMARTLIST_FOREACH_END(sig);
2515 } SMARTLIST_FOREACH_END(v);
2517 result = smartlist_join_strings(elements, "", 0, NULL);
2518 SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
2519 smartlist_free(elements);
2520 if (!n_sigs)
2521 tor_free(result);
2522 return result;
2525 /** Return a newly allocated string holding the detached-signatures document
2526 * corresponding to the signatures on <b>consensuses</b>, which must contain
2527 * exactly one FLAV_NS consensus, and no more than one consensus for each
2528 * other flavor. */
2529 char *
2530 networkstatus_get_detached_signatures(smartlist_t *consensuses)
2532 smartlist_t *elements;
2533 char *result = NULL, *sigs = NULL;
2534 networkstatus_t *consensus_ns = NULL;
2535 tor_assert(consensuses);
2537 SMARTLIST_FOREACH(consensuses, networkstatus_t *, ns, {
2538 tor_assert(ns);
2539 tor_assert(ns->type == NS_TYPE_CONSENSUS);
2540 if (ns && ns->flavor == FLAV_NS)
2541 consensus_ns = ns;
2543 if (!consensus_ns) {
2544 log_warn(LD_BUG, "No NS consensus given.");
2545 return NULL;
2548 elements = smartlist_new();
2551 char va_buf[ISO_TIME_LEN+1], fu_buf[ISO_TIME_LEN+1],
2552 vu_buf[ISO_TIME_LEN+1];
2553 char d[HEX_DIGEST_LEN+1];
2555 base16_encode(d, sizeof(d),
2556 consensus_ns->digests.d[DIGEST_SHA1], DIGEST_LEN);
2557 format_iso_time(va_buf, consensus_ns->valid_after);
2558 format_iso_time(fu_buf, consensus_ns->fresh_until);
2559 format_iso_time(vu_buf, consensus_ns->valid_until);
2561 smartlist_add_asprintf(elements,
2562 "consensus-digest %s\n"
2563 "valid-after %s\n"
2564 "fresh-until %s\n"
2565 "valid-until %s\n", d, va_buf, fu_buf, vu_buf);
2568 /* Get all the digests for the non-FLAV_NS consensuses */
2569 SMARTLIST_FOREACH_BEGIN(consensuses, networkstatus_t *, ns) {
2570 const char *flavor_name = networkstatus_get_flavor_name(ns->flavor);
2571 int alg;
2572 if (ns->flavor == FLAV_NS)
2573 continue;
2575 /* start with SHA256; we don't include SHA1 for anything but the basic
2576 * consensus. */
2577 for (alg = DIGEST_SHA256; alg < N_COMMON_DIGEST_ALGORITHMS; ++alg) {
2578 char d[HEX_DIGEST256_LEN+1];
2579 const char *alg_name =
2580 crypto_digest_algorithm_get_name(alg);
2581 if (tor_mem_is_zero(ns->digests.d[alg], DIGEST256_LEN))
2582 continue;
2583 base16_encode(d, sizeof(d), ns->digests.d[alg], DIGEST256_LEN);
2584 smartlist_add_asprintf(elements, "additional-digest %s %s %s\n",
2585 flavor_name, alg_name, d);
2587 } SMARTLIST_FOREACH_END(ns);
2589 /* Now get all the sigs for non-FLAV_NS consensuses */
2590 SMARTLIST_FOREACH_BEGIN(consensuses, networkstatus_t *, ns) {
2591 char *sigs_on_this_consensus;
2592 if (ns->flavor == FLAV_NS)
2593 continue;
2594 sigs_on_this_consensus = networkstatus_format_signatures(ns, 1);
2595 if (!sigs_on_this_consensus) {
2596 log_warn(LD_DIR, "Couldn't format signatures");
2597 goto err;
2599 smartlist_add(elements, sigs_on_this_consensus);
2600 } SMARTLIST_FOREACH_END(ns);
2602 /* Now add the FLAV_NS consensus signatrures. */
2603 sigs = networkstatus_format_signatures(consensus_ns, 1);
2604 if (!sigs)
2605 goto err;
2606 smartlist_add(elements, sigs);
2608 result = smartlist_join_strings(elements, "", 0, NULL);
2609 err:
2610 SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
2611 smartlist_free(elements);
2612 return result;
2615 /** Return a newly allocated string holding a detached-signatures document for
2616 * all of the in-progress consensuses in the <b>n_flavors</b>-element array at
2617 * <b>pending</b>. */
2618 static char *
2619 get_detached_signatures_from_pending_consensuses(pending_consensus_t *pending,
2620 int n_flavors)
2622 int flav;
2623 char *signatures;
2624 smartlist_t *c = smartlist_new();
2625 for (flav = 0; flav < n_flavors; ++flav) {
2626 if (pending[flav].consensus)
2627 smartlist_add(c, pending[flav].consensus);
2629 signatures = networkstatus_get_detached_signatures(c);
2630 smartlist_free(c);
2631 return signatures;
2634 /** Release all storage held in <b>s</b>. */
2635 void
2636 ns_detached_signatures_free(ns_detached_signatures_t *s)
2638 if (!s)
2639 return;
2640 if (s->signatures) {
2641 STRMAP_FOREACH(s->signatures, flavor, smartlist_t *, sigs) {
2642 SMARTLIST_FOREACH(sigs, document_signature_t *, sig,
2643 document_signature_free(sig));
2644 smartlist_free(sigs);
2645 } STRMAP_FOREACH_END;
2646 strmap_free(s->signatures, NULL);
2647 strmap_free(s->digests, tor_free_);
2650 tor_free(s);
2653 /* =====
2654 * Certificate functions
2655 * ===== */
2657 /** Allocate and return a new authority_cert_t with the same contents as
2658 * <b>cert</b>. */
2659 authority_cert_t *
2660 authority_cert_dup(authority_cert_t *cert)
2662 authority_cert_t *out = tor_malloc(sizeof(authority_cert_t));
2663 tor_assert(cert);
2665 memcpy(out, cert, sizeof(authority_cert_t));
2666 /* Now copy pointed-to things. */
2667 out->cache_info.signed_descriptor_body =
2668 tor_strndup(cert->cache_info.signed_descriptor_body,
2669 cert->cache_info.signed_descriptor_len);
2670 out->cache_info.saved_location = SAVED_NOWHERE;
2671 out->identity_key = crypto_pk_dup_key(cert->identity_key);
2672 out->signing_key = crypto_pk_dup_key(cert->signing_key);
2674 return out;
2677 /* =====
2678 * Vote scheduling
2679 * ===== */
2681 /** Set *<b>timing_out</b> to the intervals at which we would like to vote.
2682 * Note that these aren't the intervals we'll use to vote; they're the ones
2683 * that we'll vote to use. */
2684 void
2685 dirvote_get_preferred_voting_intervals(vote_timing_t *timing_out)
2687 const or_options_t *options = get_options();
2689 tor_assert(timing_out);
2691 timing_out->vote_interval = options->V3AuthVotingInterval;
2692 timing_out->n_intervals_valid = options->V3AuthNIntervalsValid;
2693 timing_out->vote_delay = options->V3AuthVoteDelay;
2694 timing_out->dist_delay = options->V3AuthDistDelay;
2697 /** Return the start of the next interval of size <b>interval</b> (in
2698 * seconds) after <b>now</b>, plus <b>offset</b>. Midnight always
2699 * starts a fresh interval, and if the last interval of a day would be
2700 * truncated to less than half its size, it is rolled into the
2701 * previous interval. */
2702 time_t
2703 dirvote_get_start_of_next_interval(time_t now, int interval, int offset)
2705 struct tm tm;
2706 time_t midnight_today=0;
2707 time_t midnight_tomorrow;
2708 time_t next;
2710 tor_gmtime_r(&now, &tm);
2711 tm.tm_hour = 0;
2712 tm.tm_min = 0;
2713 tm.tm_sec = 0;
2715 if (tor_timegm(&tm, &midnight_today) < 0) {
2716 log_warn(LD_BUG, "Ran into an invalid time when trying to find midnight.");
2718 midnight_tomorrow = midnight_today + (24*60*60);
2720 next = midnight_today + ((now-midnight_today)/interval + 1)*interval;
2722 /* Intervals never cross midnight. */
2723 if (next > midnight_tomorrow)
2724 next = midnight_tomorrow;
2726 /* If the interval would only last half as long as it's supposed to, then
2727 * skip over to the next day. */
2728 if (next + interval/2 > midnight_tomorrow)
2729 next = midnight_tomorrow;
2731 next += offset;
2732 if (next - interval > now)
2733 next -= interval;
2735 return next;
2738 /* Using the time <b>now</b>, return the next voting valid-after time. */
2739 time_t
2740 get_next_valid_after_time(time_t now)
2742 time_t next_valid_after_time;
2743 const or_options_t *options = get_options();
2744 voting_schedule_t *new_voting_schedule =
2745 get_voting_schedule(options, now, LOG_INFO);
2746 tor_assert(new_voting_schedule);
2748 next_valid_after_time = new_voting_schedule->interval_starts;
2749 voting_schedule_free(new_voting_schedule);
2751 return next_valid_after_time;
2754 static voting_schedule_t voting_schedule;
2756 /** Set voting_schedule to hold the timing for the next vote we should be
2757 * doing. */
2758 void
2759 dirvote_recalculate_timing(const or_options_t *options, time_t now)
2761 voting_schedule_t *new_voting_schedule;
2763 if (!authdir_mode_v3(options)) {
2764 return;
2767 /* get the new voting schedule */
2768 new_voting_schedule = get_voting_schedule(options, now, LOG_NOTICE);
2769 tor_assert(new_voting_schedule);
2771 /* Fill in the global static struct now */
2772 memcpy(&voting_schedule, new_voting_schedule, sizeof(voting_schedule));
2773 voting_schedule_free(new_voting_schedule);
2776 /* Populate and return a new voting_schedule_t that can be used to schedule
2777 * voting. The object is allocated on the heap and it's the responsibility of
2778 * the caller to free it. Can't fail. */
2779 voting_schedule_t *
2780 get_voting_schedule(const or_options_t *options, time_t now, int severity)
2782 int interval, vote_delay, dist_delay;
2783 time_t start;
2784 time_t end;
2785 networkstatus_t *consensus;
2786 voting_schedule_t *new_voting_schedule;
2788 new_voting_schedule = tor_malloc_zero(sizeof(voting_schedule_t));
2790 consensus = networkstatus_get_live_consensus(now);
2792 if (consensus) {
2793 interval = (int)( consensus->fresh_until - consensus->valid_after );
2794 vote_delay = consensus->vote_seconds;
2795 dist_delay = consensus->dist_seconds;
2796 } else {
2797 interval = options->TestingV3AuthInitialVotingInterval;
2798 vote_delay = options->TestingV3AuthInitialVoteDelay;
2799 dist_delay = options->TestingV3AuthInitialDistDelay;
2802 tor_assert(interval > 0);
2804 if (vote_delay + dist_delay > interval/2)
2805 vote_delay = dist_delay = interval / 4;
2807 start = new_voting_schedule->interval_starts =
2808 dirvote_get_start_of_next_interval(now,interval,
2809 options->TestingV3AuthVotingStartOffset);
2810 end = dirvote_get_start_of_next_interval(start+1, interval,
2811 options->TestingV3AuthVotingStartOffset);
2813 tor_assert(end > start);
2815 new_voting_schedule->fetch_missing_signatures = start - (dist_delay/2);
2816 new_voting_schedule->voting_ends = start - dist_delay;
2817 new_voting_schedule->fetch_missing_votes =
2818 start - dist_delay - (vote_delay/2);
2819 new_voting_schedule->voting_starts = start - dist_delay - vote_delay;
2822 char tbuf[ISO_TIME_LEN+1];
2823 format_iso_time(tbuf, new_voting_schedule->interval_starts);
2824 tor_log(severity, LD_DIR,"Choosing expected valid-after time as %s: "
2825 "consensus_set=%d, interval=%d",
2826 tbuf, consensus?1:0, interval);
2829 return new_voting_schedule;
2832 /** Frees a voting_schedule_t. This should be used instead of the generic
2833 * tor_free. */
2834 void
2835 voting_schedule_free(voting_schedule_t *voting_schedule_to_free)
2837 if (!voting_schedule_to_free)
2838 return;
2839 tor_free(voting_schedule_to_free);
2842 /** Entry point: Take whatever voting actions are pending as of <b>now</b>. */
2843 void
2844 dirvote_act(const or_options_t *options, time_t now)
2846 if (!authdir_mode_v3(options))
2847 return;
2848 if (!voting_schedule.voting_starts) {
2849 char *keys = list_v3_auth_ids();
2850 authority_cert_t *c = get_my_v3_authority_cert();
2851 log_notice(LD_DIR, "Scheduling voting. Known authority IDs are %s. "
2852 "Mine is %s.",
2853 keys, hex_str(c->cache_info.identity_digest, DIGEST_LEN));
2854 tor_free(keys);
2855 dirvote_recalculate_timing(options, now);
2857 if (voting_schedule.voting_starts < now && !voting_schedule.have_voted) {
2858 log_notice(LD_DIR, "Time to vote.");
2859 dirvote_perform_vote();
2860 voting_schedule.have_voted = 1;
2862 if (voting_schedule.fetch_missing_votes < now &&
2863 !voting_schedule.have_fetched_missing_votes) {
2864 log_notice(LD_DIR, "Time to fetch any votes that we're missing.");
2865 dirvote_fetch_missing_votes();
2866 voting_schedule.have_fetched_missing_votes = 1;
2868 if (voting_schedule.voting_ends < now &&
2869 !voting_schedule.have_built_consensus) {
2870 log_notice(LD_DIR, "Time to compute a consensus.");
2871 dirvote_compute_consensuses();
2872 /* XXXX We will want to try again later if we haven't got enough
2873 * votes yet. Implement this if it turns out to ever happen. */
2874 voting_schedule.have_built_consensus = 1;
2876 if (voting_schedule.fetch_missing_signatures < now &&
2877 !voting_schedule.have_fetched_missing_signatures) {
2878 log_notice(LD_DIR, "Time to fetch any signatures that we're missing.");
2879 dirvote_fetch_missing_signatures();
2880 voting_schedule.have_fetched_missing_signatures = 1;
2882 if (voting_schedule.interval_starts < now &&
2883 !voting_schedule.have_published_consensus) {
2884 log_notice(LD_DIR, "Time to publish the consensus and discard old votes");
2885 dirvote_publish_consensus();
2886 dirvote_clear_votes(0);
2887 voting_schedule.have_published_consensus = 1;
2888 /* Update our shared random state with the consensus just published. */
2889 sr_act_post_consensus(
2890 networkstatus_get_latest_consensus_by_flavor(FLAV_NS));
2891 /* XXXX We will want to try again later if we haven't got enough
2892 * signatures yet. Implement this if it turns out to ever happen. */
2893 dirvote_recalculate_timing(options, now);
2897 /** A vote networkstatus_t and its unparsed body: held around so we can
2898 * use it to generate a consensus (at voting_ends) and so we can serve it to
2899 * other authorities that might want it. */
2900 typedef struct pending_vote_t {
2901 cached_dir_t *vote_body;
2902 networkstatus_t *vote;
2903 } pending_vote_t;
2905 /** List of pending_vote_t for the current vote. Before we've used them to
2906 * build a consensus, the votes go here. */
2907 static smartlist_t *pending_vote_list = NULL;
2908 /** List of pending_vote_t for the previous vote. After we've used them to
2909 * build a consensus, the votes go here for the next period. */
2910 static smartlist_t *previous_vote_list = NULL;
2912 /* DOCDOC pending_consensuses */
2913 static pending_consensus_t pending_consensuses[N_CONSENSUS_FLAVORS];
2915 /** The detached signatures for the consensus that we're currently
2916 * building. */
2917 static char *pending_consensus_signatures = NULL;
2919 /** List of ns_detached_signatures_t: hold signatures that get posted to us
2920 * before we have generated the consensus on our own. */
2921 static smartlist_t *pending_consensus_signature_list = NULL;
2923 /** Generate a networkstatus vote and post it to all the v3 authorities.
2924 * (V3 Authority only) */
2925 static int
2926 dirvote_perform_vote(void)
2928 crypto_pk_t *key = get_my_v3_authority_signing_key();
2929 authority_cert_t *cert = get_my_v3_authority_cert();
2930 networkstatus_t *ns;
2931 char *contents;
2932 pending_vote_t *pending_vote;
2933 time_t now = time(NULL);
2935 int status;
2936 const char *msg = "";
2938 if (!cert || !key) {
2939 log_warn(LD_NET, "Didn't find key/certificate to generate v3 vote");
2940 return -1;
2941 } else if (cert->expires < now) {
2942 log_warn(LD_NET, "Can't generate v3 vote with expired certificate");
2943 return -1;
2945 if (!(ns = dirserv_generate_networkstatus_vote_obj(key, cert)))
2946 return -1;
2948 contents = format_networkstatus_vote(key, ns);
2949 networkstatus_vote_free(ns);
2950 if (!contents)
2951 return -1;
2953 pending_vote = dirvote_add_vote(contents, &msg, &status);
2954 tor_free(contents);
2955 if (!pending_vote) {
2956 log_warn(LD_DIR, "Couldn't store my own vote! (I told myself, '%s'.)",
2957 msg);
2958 return -1;
2961 directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_VOTE,
2962 ROUTER_PURPOSE_GENERAL,
2963 V3_DIRINFO,
2964 pending_vote->vote_body->dir,
2965 pending_vote->vote_body->dir_len, 0);
2966 log_notice(LD_DIR, "Vote posted.");
2967 return 0;
2970 /** Send an HTTP request to every other v3 authority, for the votes of every
2971 * authority for which we haven't received a vote yet in this period. (V3
2972 * authority only) */
2973 static void
2974 dirvote_fetch_missing_votes(void)
2976 smartlist_t *missing_fps = smartlist_new();
2977 char *resource;
2979 SMARTLIST_FOREACH_BEGIN(router_get_trusted_dir_servers(),
2980 dir_server_t *, ds) {
2981 if (!(ds->type & V3_DIRINFO))
2982 continue;
2983 if (!dirvote_get_vote(ds->v3_identity_digest,
2984 DGV_BY_ID|DGV_INCLUDE_PENDING)) {
2985 char *cp = tor_malloc(HEX_DIGEST_LEN+1);
2986 base16_encode(cp, HEX_DIGEST_LEN+1, ds->v3_identity_digest,
2987 DIGEST_LEN);
2988 smartlist_add(missing_fps, cp);
2990 } SMARTLIST_FOREACH_END(ds);
2992 if (!smartlist_len(missing_fps)) {
2993 smartlist_free(missing_fps);
2994 return;
2997 char *tmp = smartlist_join_strings(missing_fps, " ", 0, NULL);
2998 log_notice(LOG_NOTICE, "We're missing votes from %d authorities (%s). "
2999 "Asking every other authority for a copy.",
3000 smartlist_len(missing_fps), tmp);
3001 tor_free(tmp);
3003 resource = smartlist_join_strings(missing_fps, "+", 0, NULL);
3004 directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE,
3005 0, resource);
3006 tor_free(resource);
3007 SMARTLIST_FOREACH(missing_fps, char *, cp, tor_free(cp));
3008 smartlist_free(missing_fps);
3011 /** Send a request to every other authority for its detached signatures,
3012 * unless we have signatures from all other v3 authorities already. */
3013 static void
3014 dirvote_fetch_missing_signatures(void)
3016 int need_any = 0;
3017 int i;
3018 for (i=0; i < N_CONSENSUS_FLAVORS; ++i) {
3019 networkstatus_t *consensus = pending_consensuses[i].consensus;
3020 if (!consensus ||
3021 networkstatus_check_consensus_signature(consensus, -1) == 1) {
3022 /* We have no consensus, or we have one that's signed by everybody. */
3023 continue;
3025 need_any = 1;
3027 if (!need_any)
3028 return;
3030 directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES,
3031 0, NULL);
3034 /** Release all storage held by pending consensuses (those waiting for
3035 * signatures). */
3036 static void
3037 dirvote_clear_pending_consensuses(void)
3039 int i;
3040 for (i = 0; i < N_CONSENSUS_FLAVORS; ++i) {
3041 pending_consensus_t *pc = &pending_consensuses[i];
3042 tor_free(pc->body);
3044 networkstatus_vote_free(pc->consensus);
3045 pc->consensus = NULL;
3049 /** Drop all currently pending votes, consensus, and detached signatures. */
3050 static void
3051 dirvote_clear_votes(int all_votes)
3053 if (!previous_vote_list)
3054 previous_vote_list = smartlist_new();
3055 if (!pending_vote_list)
3056 pending_vote_list = smartlist_new();
3058 /* All "previous" votes are now junk. */
3059 SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, v, {
3060 cached_dir_decref(v->vote_body);
3061 v->vote_body = NULL;
3062 networkstatus_vote_free(v->vote);
3063 tor_free(v);
3065 smartlist_clear(previous_vote_list);
3067 if (all_votes) {
3068 /* If we're dumping all the votes, we delete the pending ones. */
3069 SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, {
3070 cached_dir_decref(v->vote_body);
3071 v->vote_body = NULL;
3072 networkstatus_vote_free(v->vote);
3073 tor_free(v);
3075 } else {
3076 /* Otherwise, we move them into "previous". */
3077 smartlist_add_all(previous_vote_list, pending_vote_list);
3079 smartlist_clear(pending_vote_list);
3081 if (pending_consensus_signature_list) {
3082 SMARTLIST_FOREACH(pending_consensus_signature_list, char *, cp,
3083 tor_free(cp));
3084 smartlist_clear(pending_consensus_signature_list);
3086 tor_free(pending_consensus_signatures);
3087 dirvote_clear_pending_consensuses();
3090 /** Return a newly allocated string containing the hex-encoded v3 authority
3091 identity digest of every recognized v3 authority. */
3092 static char *
3093 list_v3_auth_ids(void)
3095 smartlist_t *known_v3_keys = smartlist_new();
3096 char *keys;
3097 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
3098 dir_server_t *, ds,
3099 if ((ds->type & V3_DIRINFO) &&
3100 !tor_digest_is_zero(ds->v3_identity_digest))
3101 smartlist_add(known_v3_keys,
3102 tor_strdup(hex_str(ds->v3_identity_digest, DIGEST_LEN))));
3103 keys = smartlist_join_strings(known_v3_keys, ", ", 0, NULL);
3104 SMARTLIST_FOREACH(known_v3_keys, char *, cp, tor_free(cp));
3105 smartlist_free(known_v3_keys);
3106 return keys;
3109 /** Called when we have received a networkstatus vote in <b>vote_body</b>.
3110 * Parse and validate it, and on success store it as a pending vote (which we
3111 * then return). Return NULL on failure. Sets *<b>msg_out</b> and
3112 * *<b>status_out</b> to an HTTP response and status code. (V3 authority
3113 * only) */
3114 pending_vote_t *
3115 dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out)
3117 networkstatus_t *vote;
3118 networkstatus_voter_info_t *vi;
3119 dir_server_t *ds;
3120 pending_vote_t *pending_vote = NULL;
3121 const char *end_of_vote = NULL;
3122 int any_failed = 0;
3123 tor_assert(vote_body);
3124 tor_assert(msg_out);
3125 tor_assert(status_out);
3127 if (!pending_vote_list)
3128 pending_vote_list = smartlist_new();
3129 *status_out = 0;
3130 *msg_out = NULL;
3132 again:
3133 vote = networkstatus_parse_vote_from_string(vote_body, &end_of_vote,
3134 NS_TYPE_VOTE);
3135 if (!end_of_vote)
3136 end_of_vote = vote_body + strlen(vote_body);
3137 if (!vote) {
3138 log_warn(LD_DIR, "Couldn't parse vote: length was %d",
3139 (int)strlen(vote_body));
3140 *msg_out = "Unable to parse vote";
3141 goto err;
3143 tor_assert(smartlist_len(vote->voters) == 1);
3144 vi = get_voter(vote);
3146 int any_sig_good = 0;
3147 SMARTLIST_FOREACH(vi->sigs, document_signature_t *, sig,
3148 if (sig->good_signature)
3149 any_sig_good = 1);
3150 tor_assert(any_sig_good);
3152 ds = trusteddirserver_get_by_v3_auth_digest(vi->identity_digest);
3153 if (!ds) {
3154 char *keys = list_v3_auth_ids();
3155 log_warn(LD_DIR, "Got a vote from an authority (nickname %s, address %s) "
3156 "with authority key ID %s. "
3157 "This key ID is not recognized. Known v3 key IDs are: %s",
3158 vi->nickname, vi->address,
3159 hex_str(vi->identity_digest, DIGEST_LEN), keys);
3160 tor_free(keys);
3161 *msg_out = "Vote not from a recognized v3 authority";
3162 goto err;
3164 tor_assert(vote->cert);
3165 if (!authority_cert_get_by_digests(vote->cert->cache_info.identity_digest,
3166 vote->cert->signing_key_digest)) {
3167 /* Hey, it's a new cert! */
3168 trusted_dirs_load_certs_from_string(
3169 vote->cert->cache_info.signed_descriptor_body,
3170 TRUSTED_DIRS_CERTS_SRC_FROM_VOTE, 1 /*flush*/,
3171 NULL);
3172 if (!authority_cert_get_by_digests(vote->cert->cache_info.identity_digest,
3173 vote->cert->signing_key_digest)) {
3174 log_warn(LD_BUG, "We added a cert, but still couldn't find it.");
3178 /* Is it for the right period? */
3179 if (vote->valid_after != voting_schedule.interval_starts) {
3180 char tbuf1[ISO_TIME_LEN+1], tbuf2[ISO_TIME_LEN+1];
3181 format_iso_time(tbuf1, vote->valid_after);
3182 format_iso_time(tbuf2, voting_schedule.interval_starts);
3183 log_warn(LD_DIR, "Rejecting vote from %s with valid-after time of %s; "
3184 "we were expecting %s", vi->address, tbuf1, tbuf2);
3185 *msg_out = "Bad valid-after time";
3186 goto err;
3189 /* Fetch any new router descriptors we just learned about */
3190 update_consensus_router_descriptor_downloads(time(NULL), 1, vote);
3192 /* Now see whether we already have a vote from this authority. */
3193 SMARTLIST_FOREACH_BEGIN(pending_vote_list, pending_vote_t *, v) {
3194 if (fast_memeq(v->vote->cert->cache_info.identity_digest,
3195 vote->cert->cache_info.identity_digest,
3196 DIGEST_LEN)) {
3197 networkstatus_voter_info_t *vi_old = get_voter(v->vote);
3198 if (fast_memeq(vi_old->vote_digest, vi->vote_digest, DIGEST_LEN)) {
3199 /* Ah, it's the same vote. Not a problem. */
3200 log_info(LD_DIR, "Discarding a vote we already have (from %s).",
3201 vi->address);
3202 if (*status_out < 200)
3203 *status_out = 200;
3204 goto discard;
3205 } else if (v->vote->published < vote->published) {
3206 log_notice(LD_DIR, "Replacing an older pending vote from this "
3207 "directory (%s)", vi->address);
3208 cached_dir_decref(v->vote_body);
3209 networkstatus_vote_free(v->vote);
3210 v->vote_body = new_cached_dir(tor_strndup(vote_body,
3211 end_of_vote-vote_body),
3212 vote->published);
3213 v->vote = vote;
3214 if (end_of_vote &&
3215 !strcmpstart(end_of_vote, "network-status-version"))
3216 goto again;
3218 if (*status_out < 200)
3219 *status_out = 200;
3220 if (!*msg_out)
3221 *msg_out = "OK";
3222 return v;
3223 } else {
3224 *msg_out = "Already have a newer pending vote";
3225 goto err;
3228 } SMARTLIST_FOREACH_END(v);
3230 /* This a valid vote, update our shared random state. */
3231 sr_handle_received_commits(vote->sr_info.commits,
3232 vote->cert->identity_key);
3234 pending_vote = tor_malloc_zero(sizeof(pending_vote_t));
3235 pending_vote->vote_body = new_cached_dir(tor_strndup(vote_body,
3236 end_of_vote-vote_body),
3237 vote->published);
3238 pending_vote->vote = vote;
3239 smartlist_add(pending_vote_list, pending_vote);
3241 if (!strcmpstart(end_of_vote, "network-status-version ")) {
3242 vote_body = end_of_vote;
3243 goto again;
3246 goto done;
3248 err:
3249 any_failed = 1;
3250 if (!*msg_out)
3251 *msg_out = "Error adding vote";
3252 if (*status_out < 400)
3253 *status_out = 400;
3255 discard:
3256 networkstatus_vote_free(vote);
3258 if (end_of_vote && !strcmpstart(end_of_vote, "network-status-version ")) {
3259 vote_body = end_of_vote;
3260 goto again;
3263 done:
3265 if (*status_out < 200)
3266 *status_out = 200;
3267 if (!*msg_out) {
3268 if (!any_failed && !pending_vote) {
3269 *msg_out = "Duplicate discarded";
3270 } else {
3271 *msg_out = "ok";
3275 return any_failed ? NULL : pending_vote;
3278 /* Write the votes in <b>pending_vote_list</b> to disk. */
3279 static void
3280 write_v3_votes_to_disk(const smartlist_t *pending_votes)
3282 smartlist_t *votestrings = smartlist_new();
3283 char *votefile = NULL;
3285 SMARTLIST_FOREACH(pending_votes, pending_vote_t *, v,
3287 sized_chunk_t *c = tor_malloc(sizeof(sized_chunk_t));
3288 c->bytes = v->vote_body->dir;
3289 c->len = v->vote_body->dir_len;
3290 smartlist_add(votestrings, c); /* collect strings to write to disk */
3293 votefile = get_datadir_fname("v3-status-votes");
3294 write_chunks_to_file(votefile, votestrings, 0, 0);
3295 log_debug(LD_DIR, "Wrote votes to disk (%s)!", votefile);
3297 tor_free(votefile);
3298 SMARTLIST_FOREACH(votestrings, sized_chunk_t *, c, tor_free(c));
3299 smartlist_free(votestrings);
3302 /** Try to compute a v3 networkstatus consensus from the currently pending
3303 * votes. Return 0 on success, -1 on failure. Store the consensus in
3304 * pending_consensus: it won't be ready to be published until we have
3305 * everybody else's signatures collected too. (V3 Authority only) */
3306 static int
3307 dirvote_compute_consensuses(void)
3309 /* Have we got enough votes to try? */
3310 int n_votes, n_voters, n_vote_running = 0;
3311 smartlist_t *votes = NULL;
3312 char *consensus_body = NULL, *signatures = NULL;
3313 networkstatus_t *consensus = NULL;
3314 authority_cert_t *my_cert;
3315 pending_consensus_t pending[N_CONSENSUS_FLAVORS];
3316 int flav;
3318 memset(pending, 0, sizeof(pending));
3320 if (!pending_vote_list)
3321 pending_vote_list = smartlist_new();
3323 /* Write votes to disk */
3324 write_v3_votes_to_disk(pending_vote_list);
3326 /* Setup votes smartlist */
3327 votes = smartlist_new();
3328 SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v,
3330 smartlist_add(votes, v->vote); /* collect votes to compute consensus */
3333 /* See if consensus managed to achieve majority */
3334 n_voters = get_n_authorities(V3_DIRINFO);
3335 n_votes = smartlist_len(pending_vote_list);
3336 if (n_votes <= n_voters/2) {
3337 log_warn(LD_DIR, "We don't have enough votes to generate a consensus: "
3338 "%d of %d", n_votes, n_voters/2+1);
3339 goto err;
3341 tor_assert(pending_vote_list);
3342 SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, {
3343 if (smartlist_contains_string(v->vote->known_flags, "Running"))
3344 n_vote_running++;
3346 if (!n_vote_running) {
3347 /* See task 1066. */
3348 log_warn(LD_DIR, "Nobody has voted on the Running flag. Generating "
3349 "and publishing a consensus without Running nodes "
3350 "would make many clients stop working. Not "
3351 "generating a consensus!");
3352 goto err;
3355 if (!(my_cert = get_my_v3_authority_cert())) {
3356 log_warn(LD_DIR, "Can't generate consensus without a certificate.");
3357 goto err;
3361 char legacy_dbuf[DIGEST_LEN];
3362 crypto_pk_t *legacy_sign=NULL;
3363 char *legacy_id_digest = NULL;
3364 int n_generated = 0;
3365 if (get_options()->V3AuthUseLegacyKey) {
3366 authority_cert_t *cert = get_my_v3_legacy_cert();
3367 legacy_sign = get_my_v3_legacy_signing_key();
3368 if (cert) {
3369 if (crypto_pk_get_digest(cert->identity_key, legacy_dbuf)) {
3370 log_warn(LD_BUG,
3371 "Unable to compute digest of legacy v3 identity key");
3372 } else {
3373 legacy_id_digest = legacy_dbuf;
3378 for (flav = 0; flav < N_CONSENSUS_FLAVORS; ++flav) {
3379 const char *flavor_name = networkstatus_get_flavor_name(flav);
3380 consensus_body = networkstatus_compute_consensus(
3381 votes, n_voters,
3382 my_cert->identity_key,
3383 get_my_v3_authority_signing_key(), legacy_id_digest, legacy_sign,
3384 flav);
3386 if (!consensus_body) {
3387 log_warn(LD_DIR, "Couldn't generate a %s consensus at all!",
3388 flavor_name);
3389 continue;
3391 consensus = networkstatus_parse_vote_from_string(consensus_body, NULL,
3392 NS_TYPE_CONSENSUS);
3393 if (!consensus) {
3394 log_warn(LD_DIR, "Couldn't parse %s consensus we generated!",
3395 flavor_name);
3396 tor_free(consensus_body);
3397 continue;
3400 /* 'Check' our own signature, to mark it valid. */
3401 networkstatus_check_consensus_signature(consensus, -1);
3403 pending[flav].body = consensus_body;
3404 pending[flav].consensus = consensus;
3405 n_generated++;
3406 consensus_body = NULL;
3407 consensus = NULL;
3409 if (!n_generated) {
3410 log_warn(LD_DIR, "Couldn't generate any consensus flavors at all.");
3411 goto err;
3415 signatures = get_detached_signatures_from_pending_consensuses(
3416 pending, N_CONSENSUS_FLAVORS);
3418 if (!signatures) {
3419 log_warn(LD_DIR, "Couldn't extract signatures.");
3420 goto err;
3423 dirvote_clear_pending_consensuses();
3424 memcpy(pending_consensuses, pending, sizeof(pending));
3426 tor_free(pending_consensus_signatures);
3427 pending_consensus_signatures = signatures;
3429 if (pending_consensus_signature_list) {
3430 int n_sigs = 0;
3431 /* we may have gotten signatures for this consensus before we built
3432 * it ourself. Add them now. */
3433 SMARTLIST_FOREACH_BEGIN(pending_consensus_signature_list, char *, sig) {
3434 const char *msg = NULL;
3435 int r = dirvote_add_signatures_to_all_pending_consensuses(sig,
3436 "pending", &msg);
3437 if (r >= 0)
3438 n_sigs += r;
3439 else
3440 log_warn(LD_DIR,
3441 "Could not add queued signature to new consensus: %s",
3442 msg);
3443 tor_free(sig);
3444 } SMARTLIST_FOREACH_END(sig);
3445 if (n_sigs)
3446 log_notice(LD_DIR, "Added %d pending signatures while building "
3447 "consensus.", n_sigs);
3448 smartlist_clear(pending_consensus_signature_list);
3451 log_notice(LD_DIR, "Consensus computed; uploading signature(s)");
3453 directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_SIGNATURES,
3454 ROUTER_PURPOSE_GENERAL,
3455 V3_DIRINFO,
3456 pending_consensus_signatures,
3457 strlen(pending_consensus_signatures), 0);
3458 log_notice(LD_DIR, "Signature(s) posted.");
3460 smartlist_free(votes);
3461 return 0;
3462 err:
3463 smartlist_free(votes);
3464 tor_free(consensus_body);
3465 tor_free(signatures);
3466 networkstatus_vote_free(consensus);
3468 return -1;
3471 /** Helper: we just got the <b>detached_signatures_body</b> sent to us as
3472 * signatures on the currently pending consensus. Add them to <b>pc</b>
3473 * as appropriate. Return the number of signatures added. (?) */
3474 static int
3475 dirvote_add_signatures_to_pending_consensus(
3476 pending_consensus_t *pc,
3477 ns_detached_signatures_t *sigs,
3478 const char *source,
3479 int severity,
3480 const char **msg_out)
3482 const char *flavor_name;
3483 int r = -1;
3485 /* Only call if we have a pending consensus right now. */
3486 tor_assert(pc->consensus);
3487 tor_assert(pc->body);
3488 tor_assert(pending_consensus_signatures);
3490 flavor_name = networkstatus_get_flavor_name(pc->consensus->flavor);
3491 *msg_out = NULL;
3494 smartlist_t *sig_list = strmap_get(sigs->signatures, flavor_name);
3495 log_info(LD_DIR, "Have %d signatures for adding to %s consensus.",
3496 sig_list ? smartlist_len(sig_list) : 0, flavor_name);
3498 r = networkstatus_add_detached_signatures(pc->consensus, sigs,
3499 source, severity, msg_out);
3500 log_info(LD_DIR,"Added %d signatures to consensus.", r);
3502 if (r >= 1) {
3503 char *new_signatures =
3504 networkstatus_format_signatures(pc->consensus, 0);
3505 char *dst, *dst_end;
3506 size_t new_consensus_len;
3507 if (!new_signatures) {
3508 *msg_out = "No signatures to add";
3509 goto err;
3511 new_consensus_len =
3512 strlen(pc->body) + strlen(new_signatures) + 1;
3513 pc->body = tor_realloc(pc->body, new_consensus_len);
3514 dst_end = pc->body + new_consensus_len;
3515 dst = strstr(pc->body, "directory-signature ");
3516 tor_assert(dst);
3517 strlcpy(dst, new_signatures, dst_end-dst);
3519 /* We remove this block once it has failed to crash for a while. But
3520 * unless it shows up in profiles, we're probably better leaving it in,
3521 * just in case we break detached signature processing at some point. */
3523 networkstatus_t *v = networkstatus_parse_vote_from_string(
3524 pc->body, NULL,
3525 NS_TYPE_CONSENSUS);
3526 tor_assert(v);
3527 networkstatus_vote_free(v);
3529 *msg_out = "Signatures added";
3530 tor_free(new_signatures);
3531 } else if (r == 0) {
3532 *msg_out = "Signatures ignored";
3533 } else {
3534 goto err;
3537 goto done;
3538 err:
3539 if (!*msg_out)
3540 *msg_out = "Unrecognized error while adding detached signatures.";
3541 done:
3542 return r;
3545 static int
3546 dirvote_add_signatures_to_all_pending_consensuses(
3547 const char *detached_signatures_body,
3548 const char *source,
3549 const char **msg_out)
3551 int r=0, i, n_added = 0, errors = 0;
3552 ns_detached_signatures_t *sigs;
3553 tor_assert(detached_signatures_body);
3554 tor_assert(msg_out);
3555 tor_assert(pending_consensus_signatures);
3557 if (!(sigs = networkstatus_parse_detached_signatures(
3558 detached_signatures_body, NULL))) {
3559 *msg_out = "Couldn't parse detached signatures.";
3560 goto err;
3563 for (i = 0; i < N_CONSENSUS_FLAVORS; ++i) {
3564 int res;
3565 int severity = i == FLAV_NS ? LOG_NOTICE : LOG_INFO;
3566 pending_consensus_t *pc = &pending_consensuses[i];
3567 if (!pc->consensus)
3568 continue;
3569 res = dirvote_add_signatures_to_pending_consensus(pc, sigs, source,
3570 severity, msg_out);
3571 if (res < 0)
3572 errors++;
3573 else
3574 n_added += res;
3577 if (errors && !n_added) {
3578 r = -1;
3579 goto err;
3582 if (n_added && pending_consensuses[FLAV_NS].consensus) {
3583 char *new_detached =
3584 get_detached_signatures_from_pending_consensuses(
3585 pending_consensuses, N_CONSENSUS_FLAVORS);
3586 if (new_detached) {
3587 tor_free(pending_consensus_signatures);
3588 pending_consensus_signatures = new_detached;
3592 r = n_added;
3593 goto done;
3594 err:
3595 if (!*msg_out)
3596 *msg_out = "Unrecognized error while adding detached signatures.";
3597 done:
3598 ns_detached_signatures_free(sigs);
3599 /* XXXX NM Check how return is used. We can now have an error *and*
3600 signatures added. */
3601 return r;
3604 /** Helper: we just got the <b>detached_signatures_body</b> sent to us as
3605 * signatures on the currently pending consensus. Add them to the pending
3606 * consensus (if we have one); otherwise queue them until we have a
3607 * consensus. Return negative on failure, nonnegative on success. */
3609 dirvote_add_signatures(const char *detached_signatures_body,
3610 const char *source,
3611 const char **msg)
3613 if (pending_consensuses[FLAV_NS].consensus) {
3614 log_notice(LD_DIR, "Got a signature from %s. "
3615 "Adding it to the pending consensus.", source);
3616 return dirvote_add_signatures_to_all_pending_consensuses(
3617 detached_signatures_body, source, msg);
3618 } else {
3619 log_notice(LD_DIR, "Got a signature from %s. "
3620 "Queuing it for the next consensus.", source);
3621 if (!pending_consensus_signature_list)
3622 pending_consensus_signature_list = smartlist_new();
3623 smartlist_add(pending_consensus_signature_list,
3624 tor_strdup(detached_signatures_body));
3625 *msg = "Signature queued";
3626 return 0;
3630 /** Replace the consensus that we're currently serving with the one that we've
3631 * been building. (V3 Authority only) */
3632 static int
3633 dirvote_publish_consensus(void)
3635 int i;
3637 /* Now remember all the other consensuses as if we were a directory cache. */
3638 for (i = 0; i < N_CONSENSUS_FLAVORS; ++i) {
3639 pending_consensus_t *pending = &pending_consensuses[i];
3640 const char *name;
3641 name = networkstatus_get_flavor_name(i);
3642 tor_assert(name);
3643 if (!pending->consensus ||
3644 networkstatus_check_consensus_signature(pending->consensus, 1)<0) {
3645 log_warn(LD_DIR, "Not enough info to publish pending %s consensus",name);
3646 continue;
3649 if (networkstatus_set_current_consensus(pending->body, name, 0, NULL))
3650 log_warn(LD_DIR, "Error publishing %s consensus", name);
3651 else
3652 log_notice(LD_DIR, "Published %s consensus", name);
3655 return 0;
3658 /** Release all static storage held in dirvote.c */
3659 void
3660 dirvote_free_all(void)
3662 dirvote_clear_votes(1);
3663 /* now empty as a result of dirvote_clear_votes(). */
3664 smartlist_free(pending_vote_list);
3665 pending_vote_list = NULL;
3666 smartlist_free(previous_vote_list);
3667 previous_vote_list = NULL;
3669 dirvote_clear_pending_consensuses();
3670 tor_free(pending_consensus_signatures);
3671 if (pending_consensus_signature_list) {
3672 /* now empty as a result of dirvote_clear_votes(). */
3673 smartlist_free(pending_consensus_signature_list);
3674 pending_consensus_signature_list = NULL;
3678 /* ====
3679 * Access to pending items.
3680 * ==== */
3682 /** Return the body of the consensus that we're currently trying to build. */
3683 MOCK_IMPL(const char *,
3684 dirvote_get_pending_consensus, (consensus_flavor_t flav))
3686 tor_assert(((int)flav) >= 0 && (int)flav < N_CONSENSUS_FLAVORS);
3687 return pending_consensuses[flav].body;
3690 /** Return the signatures that we know for the consensus that we're currently
3691 * trying to build. */
3692 MOCK_IMPL(const char *,
3693 dirvote_get_pending_detached_signatures, (void))
3695 return pending_consensus_signatures;
3698 /** Return a given vote specified by <b>fp</b>. If <b>by_id</b>, return the
3699 * vote for the authority with the v3 authority identity key digest <b>fp</b>;
3700 * if <b>by_id</b> is false, return the vote whose digest is <b>fp</b>. If
3701 * <b>fp</b> is NULL, return our own vote. If <b>include_previous</b> is
3702 * false, do not consider any votes for a consensus that's already been built.
3703 * If <b>include_pending</b> is false, do not consider any votes for the
3704 * consensus that's in progress. May return NULL if we have no vote for the
3705 * authority in question. */
3706 const cached_dir_t *
3707 dirvote_get_vote(const char *fp, int flags)
3709 int by_id = flags & DGV_BY_ID;
3710 const int include_pending = flags & DGV_INCLUDE_PENDING;
3711 const int include_previous = flags & DGV_INCLUDE_PREVIOUS;
3713 if (!pending_vote_list && !previous_vote_list)
3714 return NULL;
3715 if (fp == NULL) {
3716 authority_cert_t *c = get_my_v3_authority_cert();
3717 if (c) {
3718 fp = c->cache_info.identity_digest;
3719 by_id = 1;
3720 } else
3721 return NULL;
3723 if (by_id) {
3724 if (pending_vote_list && include_pending) {
3725 SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv,
3726 if (fast_memeq(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN))
3727 return pv->vote_body);
3729 if (previous_vote_list && include_previous) {
3730 SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, pv,
3731 if (fast_memeq(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN))
3732 return pv->vote_body);
3734 } else {
3735 if (pending_vote_list && include_pending) {
3736 SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv,
3737 if (fast_memeq(pv->vote->digests.d[DIGEST_SHA1], fp, DIGEST_LEN))
3738 return pv->vote_body);
3740 if (previous_vote_list && include_previous) {
3741 SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, pv,
3742 if (fast_memeq(pv->vote->digests.d[DIGEST_SHA1], fp, DIGEST_LEN))
3743 return pv->vote_body);
3746 return NULL;
3749 /** Construct and return a new microdescriptor from a routerinfo <b>ri</b>
3750 * according to <b>consensus_method</b>.
3752 microdesc_t *
3753 dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method)
3755 microdesc_t *result = NULL;
3756 char *key = NULL, *summary = NULL, *family = NULL;
3757 size_t keylen;
3758 smartlist_t *chunks = smartlist_new();
3759 char *output = NULL;
3761 if (crypto_pk_write_public_key_to_string(ri->onion_pkey, &key, &keylen)<0)
3762 goto done;
3763 summary = policy_summarize(ri->exit_policy, AF_INET);
3764 if (ri->declared_family)
3765 family = smartlist_join_strings(ri->declared_family, " ", 0, NULL);
3767 smartlist_add_asprintf(chunks, "onion-key\n%s", key);
3769 if (consensus_method >= MIN_METHOD_FOR_NTOR_KEY &&
3770 ri->onion_curve25519_pkey) {
3771 char kbuf[128];
3772 base64_encode(kbuf, sizeof(kbuf),
3773 (const char*)ri->onion_curve25519_pkey->public_key,
3774 CURVE25519_PUBKEY_LEN, BASE64_ENCODE_MULTILINE);
3775 smartlist_add_asprintf(chunks, "ntor-onion-key %s", kbuf);
3778 if (consensus_method >= MIN_METHOD_FOR_A_LINES &&
3779 !tor_addr_is_null(&ri->ipv6_addr) && ri->ipv6_orport)
3780 smartlist_add_asprintf(chunks, "a %s\n",
3781 fmt_addrport(&ri->ipv6_addr, ri->ipv6_orport));
3783 if (family)
3784 smartlist_add_asprintf(chunks, "family %s\n", family);
3786 if (summary && strcmp(summary, "reject 1-65535"))
3787 smartlist_add_asprintf(chunks, "p %s\n", summary);
3789 if (consensus_method >= MIN_METHOD_FOR_P6_LINES &&
3790 ri->ipv6_exit_policy) {
3791 /* XXXX+++ This doesn't match proposal 208, which says these should
3792 * be taken unchanged from the routerinfo. That's bogosity, IMO:
3793 * the proposal should have said to do this instead.*/
3794 char *p6 = write_short_policy(ri->ipv6_exit_policy);
3795 if (p6 && strcmp(p6, "reject 1-65535"))
3796 smartlist_add_asprintf(chunks, "p6 %s\n", p6);
3797 tor_free(p6);
3800 if (consensus_method >= MIN_METHOD_FOR_ID_HASH_IN_MD) {
3801 char idbuf[ED25519_BASE64_LEN+1];
3802 const char *keytype;
3803 if (consensus_method >= MIN_METHOD_FOR_ED25519_ID_IN_MD &&
3804 ri->cache_info.signing_key_cert &&
3805 ri->cache_info.signing_key_cert->signing_key_included) {
3806 keytype = "ed25519";
3807 ed25519_public_to_base64(idbuf,
3808 &ri->cache_info.signing_key_cert->signing_key);
3809 } else {
3810 keytype = "rsa1024";
3811 digest_to_base64(idbuf, ri->cache_info.identity_digest);
3813 smartlist_add_asprintf(chunks, "id %s %s\n", keytype, idbuf);
3816 output = smartlist_join_strings(chunks, "", 0, NULL);
3819 smartlist_t *lst = microdescs_parse_from_string(output,
3820 output+strlen(output), 0,
3821 SAVED_NOWHERE, NULL);
3822 if (smartlist_len(lst) != 1) {
3823 log_warn(LD_DIR, "We generated a microdescriptor we couldn't parse.");
3824 SMARTLIST_FOREACH(lst, microdesc_t *, md, microdesc_free(md));
3825 smartlist_free(lst);
3826 goto done;
3828 result = smartlist_get(lst, 0);
3829 smartlist_free(lst);
3832 done:
3833 tor_free(output);
3834 tor_free(key);
3835 tor_free(summary);
3836 tor_free(family);
3837 if (chunks) {
3838 SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
3839 smartlist_free(chunks);
3841 return result;
3844 /** Format the appropriate vote line to describe the microdescriptor <b>md</b>
3845 * in a consensus vote document. Write it into the <b>out_len</b>-byte buffer
3846 * in <b>out</b>. Return -1 on failure and the number of characters written
3847 * on success. */
3848 ssize_t
3849 dirvote_format_microdesc_vote_line(char *out_buf, size_t out_buf_len,
3850 const microdesc_t *md,
3851 int consensus_method_low,
3852 int consensus_method_high)
3854 ssize_t ret = -1;
3855 char d64[BASE64_DIGEST256_LEN+1];
3856 char *microdesc_consensus_methods =
3857 make_consensus_method_list(consensus_method_low,
3858 consensus_method_high,
3859 ",");
3860 tor_assert(microdesc_consensus_methods);
3862 if (digest256_to_base64(d64, md->digest)<0)
3863 goto out;
3865 if (tor_snprintf(out_buf, out_buf_len, "m %s sha256=%s\n",
3866 microdesc_consensus_methods, d64)<0)
3867 goto out;
3869 ret = strlen(out_buf);
3871 out:
3872 tor_free(microdesc_consensus_methods);
3873 return ret;
3876 /** Array of start and end of consensus methods used for supported
3877 microdescriptor formats. */
3878 static const struct consensus_method_range_t {
3879 int low;
3880 int high;
3881 } microdesc_consensus_methods[] = {
3882 {MIN_SUPPORTED_CONSENSUS_METHOD, MIN_METHOD_FOR_A_LINES - 1},
3883 {MIN_METHOD_FOR_A_LINES, MIN_METHOD_FOR_P6_LINES - 1},
3884 {MIN_METHOD_FOR_P6_LINES, MIN_METHOD_FOR_NTOR_KEY - 1},
3885 {MIN_METHOD_FOR_NTOR_KEY, MIN_METHOD_FOR_ID_HASH_IN_MD - 1},
3886 {MIN_METHOD_FOR_ID_HASH_IN_MD, MIN_METHOD_FOR_ED25519_ID_IN_MD - 1},
3887 {MIN_METHOD_FOR_ED25519_ID_IN_MD, MAX_SUPPORTED_CONSENSUS_METHOD},
3888 {-1, -1}
3891 /** Helper type used when generating the microdescriptor lines in a directory
3892 * vote. */
3893 typedef struct microdesc_vote_line_t {
3894 int low;
3895 int high;
3896 microdesc_t *md;
3897 struct microdesc_vote_line_t *next;
3898 } microdesc_vote_line_t;
3900 /** Generate and return a linked list of all the lines that should appear to
3901 * describe a router's microdescriptor versions in a directory vote.
3902 * Add the generated microdescriptors to <b>microdescriptors_out</b>. */
3903 vote_microdesc_hash_t *
3904 dirvote_format_all_microdesc_vote_lines(const routerinfo_t *ri, time_t now,
3905 smartlist_t *microdescriptors_out)
3907 const struct consensus_method_range_t *cmr;
3908 microdesc_vote_line_t *entries = NULL, *ep;
3909 vote_microdesc_hash_t *result = NULL;
3911 /* Generate the microdescriptors. */
3912 for (cmr = microdesc_consensus_methods;
3913 cmr->low != -1 && cmr->high != -1;
3914 cmr++) {
3915 microdesc_t *md = dirvote_create_microdescriptor(ri, cmr->low);
3916 if (md) {
3917 microdesc_vote_line_t *e =
3918 tor_malloc_zero(sizeof(microdesc_vote_line_t));
3919 e->md = md;
3920 e->low = cmr->low;
3921 e->high = cmr->high;
3922 e->next = entries;
3923 entries = e;
3927 /* Compress adjacent identical ones */
3928 for (ep = entries; ep; ep = ep->next) {
3929 while (ep->next &&
3930 fast_memeq(ep->md->digest, ep->next->md->digest, DIGEST256_LEN) &&
3931 ep->low == ep->next->high + 1) {
3932 microdesc_vote_line_t *next = ep->next;
3933 ep->low = next->low;
3934 microdesc_free(next->md);
3935 ep->next = next->next;
3936 tor_free(next);
3940 /* Format them into vote_microdesc_hash_t, and add to microdescriptors_out.*/
3941 while ((ep = entries)) {
3942 char buf[128];
3943 vote_microdesc_hash_t *h;
3944 dirvote_format_microdesc_vote_line(buf, sizeof(buf), ep->md,
3945 ep->low, ep->high);
3946 h = tor_malloc_zero(sizeof(vote_microdesc_hash_t));
3947 h->microdesc_hash_line = tor_strdup(buf);
3948 h->next = result;
3949 result = h;
3950 ep->md->last_listed = now;
3951 smartlist_add(microdescriptors_out, ep->md);
3952 entries = ep->next;
3953 tor_free(ep);
3956 return result;
3959 /** If <b>vrs</b> has a hash made for the consensus method <b>method</b> with
3960 * the digest algorithm <b>alg</b>, decode it and copy it into
3961 * <b>digest256_out</b> and return 0. Otherwise return -1. */
3963 vote_routerstatus_find_microdesc_hash(char *digest256_out,
3964 const vote_routerstatus_t *vrs,
3965 int method,
3966 digest_algorithm_t alg)
3968 /* XXXX only returns the sha256 method. */
3969 const vote_microdesc_hash_t *h;
3970 char mstr[64];
3971 size_t mlen;
3972 char dstr[64];
3974 tor_snprintf(mstr, sizeof(mstr), "%d", method);
3975 mlen = strlen(mstr);
3976 tor_snprintf(dstr, sizeof(dstr), " %s=",
3977 crypto_digest_algorithm_get_name(alg));
3979 for (h = vrs->microdesc; h; h = h->next) {
3980 const char *cp = h->microdesc_hash_line;
3981 size_t num_len;
3982 /* cp looks like \d+(,\d+)* (digesttype=val )+ . Let's hunt for mstr in
3983 * the first part. */
3984 while (1) {
3985 num_len = strspn(cp, "1234567890");
3986 if (num_len == mlen && fast_memeq(mstr, cp, mlen)) {
3987 /* This is the line. */
3988 char buf[BASE64_DIGEST256_LEN+1];
3989 /* XXXX ignores extraneous stuff if the digest is too long. This
3990 * seems harmless enough, right? */
3991 cp = strstr(cp, dstr);
3992 if (!cp)
3993 return -1;
3994 cp += strlen(dstr);
3995 strlcpy(buf, cp, sizeof(buf));
3996 return digest256_from_base64(digest256_out, buf);
3998 if (num_len == 0 || cp[num_len] != ',')
3999 break;
4000 cp += num_len + 1;
4003 return -1;