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
9 #include "dircollate.h"
10 #include "directory.h"
13 #include "microdesc.h"
14 #include "networkstatus.h"
19 #include "routerkeys.h"
20 #include "routerlist.h"
21 #include "routerparse.h"
22 #include "entrynodes.h" /* needed for guardfraction methods */
24 #include "shared_random_state.h"
28 * \brief Functions to compute directory consensus, and schedule voting.
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 */
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
,
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
,
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);
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. */
68 format_line_if_present(const char *keyword
, const char *opt_value
)
72 tor_asprintf(&result
, "%s %s\n", keyword
, opt_value
);
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. */
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
);
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
);
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. */
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
];
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
;
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);
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
));
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();
176 authority_cert_t
*cert
= v3_ns
->cert
;
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
);
188 params
= tor_strdup("");
191 smartlist_add_asprintf(chunks
,
192 "network-status-version 3\n"
194 "consensus-methods %s\n"
199 "voting-delay %d %d\n"
200 "%s%s" /* versions */
204 "flag-thresholds %s\n"
206 "dir-source %s %s %s %s %d %d\n"
208 "%s", /* shared randomness information */
209 v3_ns
->type
== NS_TYPE_VOTE
? "vote" : "opinion",
211 published
, va
, fu
, vu
,
212 v3_ns
->vote_seconds
, v3_ns
->dist_seconds
,
213 client_versions_line
,
214 server_versions_line
,
220 voter
->nickname
, fingerprint
, voter
->address
,
221 fmt_addr32(addr
), voter
->dir_port
, voter
->or_port
,
223 shared_random_vote_str
?
224 shared_random_vote_str
: "");
228 tor_free(flag_thresholds
);
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
*,
245 vote_microdesc_hash_t
*h
;
246 rsf
= routerstatus_format_entry(&vrs
->status
,
247 vrs
->version
, vrs
->protocols
,
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");
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
);
281 log_warn(LD_BUG
, "Unable to sign networkstatus vote.");
284 smartlist_add(chunks
, sig
);
287 status
= smartlist_join_strings(chunks
, "", 0, NULL
);
291 if (!(v
= networkstatus_parse_vote_from_string(status
, NULL
,
293 log_err(LD_BUG
,"Generated a networkstatus %s we couldn't parse: "
295 v3_ns
->type
== NS_TYPE_VOTE
? "vote" : "opinion", status
);
298 networkstatus_vote_free(v
);
306 tor_free(client_versions_line
);
307 tor_free(server_versions_line
);
308 tor_free(protocols_lines
);
311 SMARTLIST_FOREACH(chunks
, char *, cp
, tor_free(cp
));
312 smartlist_free(chunks
);
317 * Consensus generation
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
)
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
)
340 SMARTLIST_FOREACH(voter
->sigs
, document_signature_t
*, sig
,
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
{
355 /** Helper for sorting networkstatus_t votes (not consensuses) by the
356 * hash of their voters' identity digests. */
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
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. */
384 get_frequent_members(smartlist_t
*out
, smartlist_t
*in
, int min
)
388 SMARTLIST_FOREACH_BEGIN(in
, char *, cp
) {
389 if (cur
&& !strcmp(cp
, cur
)) {
393 smartlist_add(out
, cur
);
397 } SMARTLIST_FOREACH_END(cp
);
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.
411 compare_vote_rs(const vote_routerstatus_t
*a
, const vote_routerstatus_t
*b
)
417 if ((r
= fast_memcmp(a
->status
.identity_digest
, b
->status
.identity_digest
,
420 if ((r
= fast_memcmp(a
->status
.descriptor_digest
,
421 b
->status
.descriptor_digest
,
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; \
434 } else if (r2 > 0) { \
439 CMP_FIELD(uint64_t, int64_t, published_on
);
441 if ((r
= strcmp(b
->status
.nickname
, a
->status
.nickname
)))
444 CMP_FIELD(unsigned, int, addr
);
445 CMP_FIELD(unsigned, int, or_port
);
446 CMP_FIELD(unsigned, int, dir_port
);
451 /** Helper for sorting routerlists based on compare_vote_rs. */
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. */
461 compare_orports_(const void **_a
, const void **_b
)
463 const tor_addr_port_t
*a
= *_a
, *b
= *_b
;
466 if ((r
= tor_addr_compare(&a
->addr
, &b
->addr
, CMP_EXACT
)))
468 if ((r
= (((int) b
->port
) - ((int) a
->port
))))
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
)) {
497 if (cur
&& (cur_n
> most_n
||
499 cur
->status
.published_on
> most_published
))) {
502 most_published
= cur
->status
.published_on
;
507 } SMARTLIST_FOREACH_END(rs
);
509 if (cur_n
> most_n
||
510 (cur
&& cur_n
== most_n
&& cur
->status
.published_on
> most_published
)) {
513 most_published
= cur
->status
.published_on
;
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
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
) {
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
,
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
))
558 if (!vote_routerstatus_find_microdesc_hash(d
, rs
, consensus_method
,
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
);
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.) */
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
);
585 if (ai
== 0) /* Parsing failed. */
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. */
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;
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
);
618 const char *best
= smartlist_get(acceptable_methods
, n_ok
-1);
619 result
= (int)tor_parse_long(best
, 10, 1, INT_MAX
, NULL
, NULL
);
624 smartlist_free(all_methods
);
625 smartlist_free(acceptable_methods
);
629 /** Return true iff <b>method</b> is a consensus method that we support. */
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.
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. */
647 make_consensus_method_list(int low
, int high
, const char *separator
)
653 lst
= smartlist_new();
654 for (i
= low
; i
<= high
; ++i
) {
655 if (!consensus_method_is_supported(i
))
657 smartlist_add_asprintf(lst
, "%d", i
);
659 list
= smartlist_join_strings(lst
, separator
, 0, NULL
);
661 SMARTLIST_FOREACH(lst
, char *, cp
, tor_free(cp
));
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> */
671 compute_consensus_versions_list(smartlist_t
*lst
, int n_versioning
)
673 int min
= n_versioning
/ 2;
674 smartlist_t
*good
= smartlist_new();
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
);
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
688 dirvote_get_intermediate_param_value(const smartlist_t
*param_list
,
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];
700 tor_parse_long(integer_str
, 10, INT32_MIN
, INT32_MAX
, &ok
, NULL
);
705 } SMARTLIST_FOREACH_END(k_v_pair
);
709 else if (BUG(n_found
> 1))
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.
724 dirvote_compute_params(smartlist_t
*votes
, int method
, int total_authorities
)
730 const char *cur_param
;
733 const int n_votes
= smartlist_len(votes
);
735 smartlist_t
*param_list
= smartlist_new();
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
743 vals
= tor_calloc(n_votes
, sizeof(int));
745 SMARTLIST_FOREACH_BEGIN(votes
, networkstatus_t
*, v
) {
748 smartlist_add_all(param_list
, v
->net_params
);
749 } SMARTLIST_FOREACH_END(v
);
751 if (smartlist_len(param_list
) == 0) {
756 smartlist_sort_strings(param_list
);
758 cur_param
= smartlist_get(param_list
, 0);
759 eq
= strchr(cur_param
, '=');
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
;
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
))
777 next_param
= smartlist_get(param_list
, param_sl_idx
+1);
778 /* resolve spurious clang shallow analysis null pointer errors */
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
);
795 eq
= strchr(next_param
, '=');
796 cur_param_len
= (int)(eq
+1 - next_param
);
799 } SMARTLIST_FOREACH_END(param
);
801 smartlist_free(param_list
);
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))
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
;
843 if (!CHECK_EQ(Wmg
+ Wgg
, scale
, margin
)) {
844 berr
= BW_WEIGHTS_SUMG_ERROR
;
849 if (!CHECK_EQ(Wme
+ Wee
, scale
, margin
)) {
850 berr
= BW_WEIGHTS_SUME_ERROR
;
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
;
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
;
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
,
870 berr
= BW_WEIGHTS_BALANCE_MID_ERROR
;
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",
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
);
893 * This function computes the bandwidth weights for consensus method 10.
895 * It returns true if weights could be computed, false otherwise.
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
));
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
924 * 3. One of Guard or Exit is scarce
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);
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",
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
);
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
970 casename
= "Case 2a (E scarce)";
973 } else { /* E >= G */
974 casename
= "Case 2a (G scarce)";
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
;
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);
992 casename
= "Case 2b2 (Wgg=1, Wee=1)";
995 Wed
= (weight_scale
*(D
- 2*E
+ G
+ M
))/(3*D
);
996 Wmd
= (weight_scale
*(D
- 2*M
+ G
+ E
))/(3*D
);
1000 if (Wmd
< 0) { // Can happen if M > T/3
1001 casename
= "Case 2b3 (Wmd=0)";
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
) {
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",
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
);
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
)) {
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
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.
1046 else Wme
= (weight_scale
*(E
-M
))/(2*E
);
1047 Wee
= weight_scale
-Wme
;
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.
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
1061 casename
= "Case 3bg (G scarce, Wgg=1, Wmd == Wed)";
1063 Wgd
= (weight_scale
*(D
- 2*G
+ E
+ M
))/(3*D
);
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);
1073 casename
= "Case 3be (E scarce, Wee=1, Wmd == Wgd)";
1075 Wed
= (weight_scale
*(D
- 2*E
+ G
+ M
))/(3*D
);
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);
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",
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
);
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 "
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
,
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
1130 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
1131 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
));
1135 /** Update total bandwidth weights (G/M/E/D/T) with the bandwidth of
1136 * the router in <b>rs</b>. */
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
,
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",
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
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
,
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
;
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
1222 get_nth_protocol_set_vote(int n
, const networkstatus_t
*vote
)
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
;
1230 tor_assert_unreached();
1235 /** Considering the different recommended/required protocols sets as a
1236 * 4-element array, return a newly allocated string for the consensus value
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();
1247 keyword
= "recommended-client-protocols";
1248 threshold
= CEIL_DIV(n_voters
, 2);
1251 keyword
= "recommended-relay-protocols";
1252 threshold
= CEIL_DIV(n_voters
, 2);
1255 keyword
= "required-client-protocols";
1256 threshold
= CEIL_DIV(n_voters
* 2, 3);
1259 keyword
= "required-relay-protocols";
1260 threshold
= CEIL_DIV(n_voters
* 2, 3);
1263 tor_assert_unreached();
1267 SMARTLIST_FOREACH_BEGIN(votes
, const networkstatus_t
*, ns
) {
1268 const char *v
= get_nth_protocol_set_vote(n
, ns
);
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
);
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.) */
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
;
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.");
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.",
1335 log_warn(LD_DIR
, "The other authorities will use consensus method %d, "
1336 "which I don't support. Maybe I should upgrade!",
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
);
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
);
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];
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",
1444 smartlist_add_asprintf(chunks
,
1448 "voting-delay %d %d\n"
1449 "client-versions %s\n"
1450 "server-versions %s\n"
1453 va_buf
, fu_buf
, vu_buf
,
1454 vote_seconds
, dist_seconds
,
1455 client_versions
, server_versions
,
1462 if (consensus_method
>= MIN_METHOD_FOR_RECOMMENDED_PROTOCOLS
) {
1463 int num_dirauth
= get_n_authorities(V3_DIRINFO
);
1465 for (idx
= 0; idx
< 4; ++idx
) {
1466 char *proto_line
= compute_nth_protocol_set(idx
, num_dirauth
, votes
);
1467 if (BUG(!proto_line
))
1469 smartlist_add(chunks
, proto_line
);
1473 param_list
= dirvote_compute_params(votes
, consensus_method
,
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
));
1506 e
->digest
= get_voter(v
)->identity_digest
;
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
));
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
,
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
),
1535 if (! e
->is_legacy
) {
1536 smartlist_add_asprintf(chunks
,
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 */
1551 if (strcmpstart(params
, "maxunmeasuredbw=") == 0)
1552 max_unmeasured_param
= params
;
1554 max_unmeasured_param
= strstr(params
, " maxunmeasuredbw=");
1556 if (max_unmeasured_param
) {
1558 char *eq
= strchr(max_unmeasured_param
, '=');
1560 max_unmeasured_bw_kb
= (uint32_t)
1561 tor_parse_ulong(eq
+1, 10, 1, UINT32_MAX
, &ok
, NULL
);
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. */
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
),
1584 uint32_t *measured_bws_kb
= tor_calloc(smartlist_len(votes
),
1586 uint32_t *measured_guardfraction
= tor_calloc(smartlist_len(votes
),
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
1623 SMARTLIST_FOREACH_BEGIN(votes
, networkstatus_t
*, v
) {
1624 flag_map
[v_sl_idx
] = tor_calloc(smartlist_len(v
->known_flags
),
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
);
1633 flag_map
[v_sl_idx
][fl_sl_idx
] = 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
) {
1648 if (named_flag
[v_sl_idx
]<0)
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
);
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
);
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
) {
1673 if (unnamed_flag
[v_sl_idx
]<0)
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. */
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
);
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;
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
);
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
];
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
) {
1794 if (ed_consensus_val
) {
1795 tor_assert(fast_memeq(ed_consensus_val
, rs
->ed25519_id
,
1796 ED25519_PUBKEY_LEN
));
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)
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
,
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
));
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
);
1852 is_named
= is_unnamed
= 0;
1853 } else if (fast_memeq(d
, current_rsa_id
, DIGEST_LEN
)) {
1854 is_named
= 1; is_unnamed
= 0;
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")) {
1865 smartlist_add(chosen_flags
, (char*)fl
);
1866 } else if (!strcmp(fl
, "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
);
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"))
1878 else if (!strcmp(fl
, "Guard"))
1880 else if (!strcmp(fl
, "Running"))
1882 else if (!strcmp(fl
, "BadExit"))
1884 else if (!strcmp(fl
, "Valid"))
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 */
1895 /* Starting with consensus method 24, we don't list servers
1896 * that are not valid in a consensus. See Proposal 272 */
1898 consensus_method
>= MIN_METHOD_FOR_EXCLUDING_INVALID_NODES
)
1901 /* Pick the version. */
1902 if (smartlist_len(versions
)) {
1903 sort_version_list(versions
, 0);
1904 chosen_version
= get_most_frequent_member(versions
);
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
);
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 */
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
,
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
,
1981 if (vsr
->status
.has_exitsummary
&&
1982 fast_memeq(rs_out
.descriptor_digest
,
1983 vsr
->status
.descriptor_digest
,
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"
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. */
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
);
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 */
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
]);
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. */
2133 if (strcmpstart(params
, "bwweightscale=") == 0)
2134 bw_weight_param
= params
;
2136 bw_weight_param
= strstr(params
, " bwweightscale=");
2139 if (bw_weight_param
) {
2141 char *eq
= strchr(bw_weight_param
, '=');
2143 weight_scale
= tor_parse_long(eq
+1, 10, 1, INT32_MAX
, &ok
,
2146 log_warn(LD_DIR
, "Bad element '%s' in bw weight param",
2147 escaped(bw_weight_param
));
2148 weight_scale
= BW_WEIGHT_SCALE
;
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
,
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
;
2169 flavor
== FLAV_NS
? DIGEST_LEN
: DIGEST256_LEN
;
2170 const char *algname
= crypto_digest_algorithm_get_name(digest_alg
);
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
);
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
,
2194 log_warn(LD_BUG
, "Couldn't sign consensus networkstatus.");
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
);
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.");
2219 smartlist_add(chunks
, signature
);
2223 result
= smartlist_join_strings(chunks
, "", 0, NULL
);
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 "
2234 // Verify balancing parameters
2235 if (added_weights
) {
2236 networkstatus_verify_bw_weights(c
, consensus_method
);
2238 networkstatus_vote_free(c
);
2243 dircollator_free(collator
);
2244 tor_free(client_versions
);
2245 tor_free(server_versions
);
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
);
2257 /** Given a list of networkstatus_t for each vote, return a newly allocated
2258 * string containing the "package" lines for the vote. */
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
)
2273 SMARTLIST_FOREACH_BEGIN(v
->package_lines
, const char *, line
) {
2274 if (! validate_recommended_package_line(line
))
2277 /* Skip 'cp' to the second space in the line. */
2278 const char *cp
= strchr(line
, ' ');
2281 cp
= strchr(cp
, ' ');
2284 char *key
= tor_strndup(line
, cp
- line
);
2286 const char **status
= strmap_get(package_status
, key
);
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 */
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
) {
2300 for (i
= 0; i
< n_votes
; ++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_
);
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
,
2342 const char **msg_out
)
2346 smartlist_t
*siglist
;
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";
2359 if (target
->fresh_until
!= sigs
->fresh_until
) {
2360 *msg_out
= "Fresh-until times do not match "
2361 "when adding detached signatures to consensus";
2364 if (target
->valid_until
!= sigs
->valid_until
) {
2365 *msg_out
= "Valid-until times do not match "
2366 "when adding detached signatures to consensus";
2369 siglist
= strmap_get(sigs
->signatures
, flavor
);
2371 *msg_out
= "No signatures for given consensus flavor";
2375 /** Make sure all the digests we know match, and at least one matches. */
2377 common_digests_t
*digests
= strmap_get(sigs
->digests
, flavor
);
2381 *msg_out
= "No digests for given consensus flavor";
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
],
2390 *msg_out
= "Mismatched digest.";
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
,
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
);
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
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
);
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
);
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
,
2447 tor_log(severity
, LD_DIR
, "Added a signature for %s from %s.",
2448 target_voter
->nickname
, source
);
2451 smartlist_remove(target_voter
->sigs
, old_sig
);
2452 document_signature_free(old_sig
);
2454 smartlist_add(target_voter
->sigs
, document_signature_dup(sig
));
2456 log_info(LD_DIR
, "Not adding signature from %s", voter_identity
);
2458 } SMARTLIST_FOREACH_END(sig
);
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". */
2469 networkstatus_format_signatures(networkstatus_t
*consensus
,
2470 int for_detached_signatures
)
2472 smartlist_t
*elements
;
2474 char *result
= NULL
;
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";
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
)
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",
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",
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
);
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
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
, {
2539 tor_assert(ns
->type
== NS_TYPE_CONSENSUS
);
2540 if (ns
&& ns
->flavor
== FLAV_NS
)
2543 if (!consensus_ns
) {
2544 log_warn(LD_BUG
, "No NS consensus given.");
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"
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
);
2572 if (ns
->flavor
== FLAV_NS
)
2575 /* start with SHA256; we don't include SHA1 for anything but the basic
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
))
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
)
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");
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);
2606 smartlist_add(elements
, sigs
);
2608 result
= smartlist_join_strings(elements
, "", 0, NULL
);
2610 SMARTLIST_FOREACH(elements
, char *, cp
, tor_free(cp
));
2611 smartlist_free(elements
);
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>. */
2619 get_detached_signatures_from_pending_consensuses(pending_consensus_t
*pending
,
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
);
2634 /** Release all storage held in <b>s</b>. */
2636 ns_detached_signatures_free(ns_detached_signatures_t
*s
)
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_
);
2654 * Certificate functions
2657 /** Allocate and return a new authority_cert_t with the same contents as
2660 authority_cert_dup(authority_cert_t
*cert
)
2662 authority_cert_t
*out
= tor_malloc(sizeof(authority_cert_t
));
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
);
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. */
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. */
2703 dirvote_get_start_of_next_interval(time_t now
, int interval
, int offset
)
2706 time_t midnight_today
=0;
2707 time_t midnight_tomorrow
;
2710 tor_gmtime_r(&now
, &tm
);
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
;
2732 if (next
- interval
> now
)
2738 /* Using the time <b>now</b>, return the next voting valid-after time. */
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
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
)) {
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. */
2780 get_voting_schedule(const or_options_t
*options
, time_t now
, int severity
)
2782 int interval
, vote_delay
, dist_delay
;
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
);
2793 interval
= (int)( consensus
->fresh_until
- consensus
->valid_after
);
2794 vote_delay
= consensus
->vote_seconds
;
2795 dist_delay
= consensus
->dist_seconds
;
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
2835 voting_schedule_free(voting_schedule_t
*voting_schedule_to_free
)
2837 if (!voting_schedule_to_free
)
2839 tor_free(voting_schedule_to_free
);
2842 /** Entry point: Take whatever voting actions are pending as of <b>now</b>. */
2844 dirvote_act(const or_options_t
*options
, time_t now
)
2846 if (!authdir_mode_v3(options
))
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. "
2853 keys
, hex_str(c
->cache_info
.identity_digest
, DIGEST_LEN
));
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
;
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
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) */
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
;
2932 pending_vote_t
*pending_vote
;
2933 time_t now
= time(NULL
);
2936 const char *msg
= "";
2938 if (!cert
|| !key
) {
2939 log_warn(LD_NET
, "Didn't find key/certificate to generate v3 vote");
2941 } else if (cert
->expires
< now
) {
2942 log_warn(LD_NET
, "Can't generate v3 vote with expired certificate");
2945 if (!(ns
= dirserv_generate_networkstatus_vote_obj(key
, cert
)))
2948 contents
= format_networkstatus_vote(key
, ns
);
2949 networkstatus_vote_free(ns
);
2953 pending_vote
= dirvote_add_vote(contents
, &msg
, &status
);
2955 if (!pending_vote
) {
2956 log_warn(LD_DIR
, "Couldn't store my own vote! (I told myself, '%s'.)",
2961 directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_VOTE
,
2962 ROUTER_PURPOSE_GENERAL
,
2964 pending_vote
->vote_body
->dir
,
2965 pending_vote
->vote_body
->dir_len
, 0);
2966 log_notice(LD_DIR
, "Vote posted.");
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) */
2974 dirvote_fetch_missing_votes(void)
2976 smartlist_t
*missing_fps
= smartlist_new();
2979 SMARTLIST_FOREACH_BEGIN(router_get_trusted_dir_servers(),
2980 dir_server_t
*, ds
) {
2981 if (!(ds
->type
& V3_DIRINFO
))
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
,
2988 smartlist_add(missing_fps
, cp
);
2990 } SMARTLIST_FOREACH_END(ds
);
2992 if (!smartlist_len(missing_fps
)) {
2993 smartlist_free(missing_fps
);
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
);
3003 resource
= smartlist_join_strings(missing_fps
, "+", 0, NULL
);
3004 directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE
,
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. */
3014 dirvote_fetch_missing_signatures(void)
3018 for (i
=0; i
< N_CONSENSUS_FLAVORS
; ++i
) {
3019 networkstatus_t
*consensus
= pending_consensuses
[i
].consensus
;
3021 networkstatus_check_consensus_signature(consensus
, -1) == 1) {
3022 /* We have no consensus, or we have one that's signed by everybody. */
3030 directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES
,
3034 /** Release all storage held by pending consensuses (those waiting for
3037 dirvote_clear_pending_consensuses(void)
3040 for (i
= 0; i
< N_CONSENSUS_FLAVORS
; ++i
) {
3041 pending_consensus_t
*pc
= &pending_consensuses
[i
];
3044 networkstatus_vote_free(pc
->consensus
);
3045 pc
->consensus
= NULL
;
3049 /** Drop all currently pending votes, consensus, and detached signatures. */
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
);
3065 smartlist_clear(previous_vote_list
);
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
);
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
,
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. */
3093 list_v3_auth_ids(void)
3095 smartlist_t
*known_v3_keys
= smartlist_new();
3097 SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
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
);
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
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
;
3120 pending_vote_t
*pending_vote
= NULL
;
3121 const char *end_of_vote
= NULL
;
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();
3133 vote
= networkstatus_parse_vote_from_string(vote_body
, &end_of_vote
,
3136 end_of_vote
= vote_body
+ strlen(vote_body
);
3138 log_warn(LD_DIR
, "Couldn't parse vote: length was %d",
3139 (int)strlen(vote_body
));
3140 *msg_out
= "Unable to parse vote";
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
)
3150 tor_assert(any_sig_good
);
3152 ds
= trusteddirserver_get_by_v3_auth_digest(vi
->identity_digest
);
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
);
3161 *msg_out
= "Vote not from a recognized v3 authority";
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*/,
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";
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
,
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).",
3202 if (*status_out
< 200)
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
),
3215 !strcmpstart(end_of_vote
, "network-status-version"))
3218 if (*status_out
< 200)
3224 *msg_out
= "Already have a newer pending vote";
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
),
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
;
3251 *msg_out
= "Error adding vote";
3252 if (*status_out
< 400)
3256 networkstatus_vote_free(vote
);
3258 if (end_of_vote
&& !strcmpstart(end_of_vote
, "network-status-version ")) {
3259 vote_body
= end_of_vote
;
3265 if (*status_out
< 200)
3268 if (!any_failed
&& !pending_vote
) {
3269 *msg_out
= "Duplicate discarded";
3275 return any_failed
? NULL
: pending_vote
;
3278 /* Write the votes in <b>pending_vote_list</b> to disk. */
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
);
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) */
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
];
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);
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"))
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!");
3355 if (!(my_cert
= get_my_v3_authority_cert())) {
3356 log_warn(LD_DIR
, "Can't generate consensus without a certificate.");
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();
3369 if (crypto_pk_get_digest(cert
->identity_key
, legacy_dbuf
)) {
3371 "Unable to compute digest of legacy v3 identity key");
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(
3382 my_cert
->identity_key
,
3383 get_my_v3_authority_signing_key(), legacy_id_digest
, legacy_sign
,
3386 if (!consensus_body
) {
3387 log_warn(LD_DIR
, "Couldn't generate a %s consensus at all!",
3391 consensus
= networkstatus_parse_vote_from_string(consensus_body
, NULL
,
3394 log_warn(LD_DIR
, "Couldn't parse %s consensus we generated!",
3396 tor_free(consensus_body
);
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
;
3406 consensus_body
= NULL
;
3410 log_warn(LD_DIR
, "Couldn't generate any consensus flavors at all.");
3415 signatures
= get_detached_signatures_from_pending_consensuses(
3416 pending
, N_CONSENSUS_FLAVORS
);
3419 log_warn(LD_DIR
, "Couldn't extract signatures.");
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
) {
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
,
3441 "Could not add queued signature to new consensus: %s",
3444 } SMARTLIST_FOREACH_END(sig
);
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
,
3456 pending_consensus_signatures
,
3457 strlen(pending_consensus_signatures
), 0);
3458 log_notice(LD_DIR
, "Signature(s) posted.");
3460 smartlist_free(votes
);
3463 smartlist_free(votes
);
3464 tor_free(consensus_body
);
3465 tor_free(signatures
);
3466 networkstatus_vote_free(consensus
);
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. (?) */
3475 dirvote_add_signatures_to_pending_consensus(
3476 pending_consensus_t
*pc
,
3477 ns_detached_signatures_t
*sigs
,
3480 const char **msg_out
)
3482 const char *flavor_name
;
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
);
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
);
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";
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 ");
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(
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";
3540 *msg_out
= "Unrecognized error while adding detached signatures.";
3546 dirvote_add_signatures_to_all_pending_consensuses(
3547 const char *detached_signatures_body
,
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.";
3563 for (i
= 0; i
< N_CONSENSUS_FLAVORS
; ++i
) {
3565 int severity
= i
== FLAV_NS
? LOG_NOTICE
: LOG_INFO
;
3566 pending_consensus_t
*pc
= &pending_consensuses
[i
];
3569 res
= dirvote_add_signatures_to_pending_consensus(pc
, sigs
, source
,
3577 if (errors
&& !n_added
) {
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
);
3587 tor_free(pending_consensus_signatures
);
3588 pending_consensus_signatures
= new_detached
;
3596 *msg_out
= "Unrecognized error while adding detached signatures.";
3598 ns_detached_signatures_free(sigs
);
3599 /* XXXX NM Check how return is used. We can now have an error *and*
3600 signatures added. */
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
,
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
);
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";
3630 /** Replace the consensus that we're currently serving with the one that we've
3631 * been building. (V3 Authority only) */
3633 dirvote_publish_consensus(void)
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
];
3641 name
= networkstatus_get_flavor_name(i
);
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
);
3649 if (networkstatus_set_current_consensus(pending
->body
, name
, 0, NULL
))
3650 log_warn(LD_DIR
, "Error publishing %s consensus", name
);
3652 log_notice(LD_DIR
, "Published %s consensus", name
);
3658 /** Release all static storage held in dirvote.c */
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
;
3679 * Access to pending items.
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
)
3716 authority_cert_t
*c
= get_my_v3_authority_cert();
3718 fp
= c
->cache_info
.identity_digest
;
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
);
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
);
3749 /** Construct and return a new microdescriptor from a routerinfo <b>ri</b>
3750 * according to <b>consensus_method</b>.
3753 dirvote_create_microdescriptor(const routerinfo_t
*ri
, int consensus_method
)
3755 microdesc_t
*result
= NULL
;
3756 char *key
= NULL
, *summary
= NULL
, *family
= NULL
;
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)
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
) {
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
));
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
);
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
);
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
);
3828 result
= smartlist_get(lst
, 0);
3829 smartlist_free(lst
);
3838 SMARTLIST_FOREACH(chunks
, char *, cp
, tor_free(cp
));
3839 smartlist_free(chunks
);
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
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
)
3855 char d64
[BASE64_DIGEST256_LEN
+1];
3856 char *microdesc_consensus_methods
=
3857 make_consensus_method_list(consensus_method_low
,
3858 consensus_method_high
,
3860 tor_assert(microdesc_consensus_methods
);
3862 if (digest256_to_base64(d64
, md
->digest
)<0)
3865 if (tor_snprintf(out_buf
, out_buf_len
, "m %s sha256=%s\n",
3866 microdesc_consensus_methods
, d64
)<0)
3869 ret
= strlen(out_buf
);
3872 tor_free(microdesc_consensus_methods
);
3876 /** Array of start and end of consensus methods used for supported
3877 microdescriptor formats. */
3878 static const struct consensus_method_range_t
{
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
},
3891 /** Helper type used when generating the microdescriptor lines in a directory
3893 typedef struct microdesc_vote_line_t
{
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;
3915 microdesc_t
*md
= dirvote_create_microdescriptor(ri
, cmr
->low
);
3917 microdesc_vote_line_t
*e
=
3918 tor_malloc_zero(sizeof(microdesc_vote_line_t
));
3921 e
->high
= cmr
->high
;
3927 /* Compress adjacent identical ones */
3928 for (ep
= entries
; ep
; ep
= 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
;
3940 /* Format them into vote_microdesc_hash_t, and add to microdescriptors_out.*/
3941 while ((ep
= entries
)) {
3943 vote_microdesc_hash_t
*h
;
3944 dirvote_format_microdesc_vote_line(buf
, sizeof(buf
), ep
->md
,
3946 h
= tor_malloc_zero(sizeof(vote_microdesc_hash_t
));
3947 h
->microdesc_hash_line
= tor_strdup(buf
);
3950 ep
->md
->last_listed
= now
;
3951 smartlist_add(microdescriptors_out
, ep
->md
);
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
,
3966 digest_algorithm_t alg
)
3968 /* XXXX only returns the sha256 method. */
3969 const vote_microdesc_hash_t
*h
;
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
;
3982 /* cp looks like \d+(,\d+)* (digesttype=val )+ . Let's hunt for mstr in
3983 * the first part. */
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
);
3995 strlcpy(buf
, cp
, sizeof(buf
));
3996 return digest256_from_base64(digest256_out
, buf
);
3998 if (num_len
== 0 || cp
[num_len
] != ',')