tor
master
|
Functions to compute directory consensus, and schedule voting. More...
#include "or.h"
#include "config.h"
#include "dircollate.h"
#include "directory.h"
#include "dirserv.h"
#include "microdesc.h"
#include "networkstatus.h"
#include "nodelist.h"
#include "parsecommon.h"
#include "policies.h"
#include "protover.h"
#include "rephist.h"
#include "router.h"
#include "routerkeys.h"
#include "routerlist.h"
#include "routerparse.h"
#include "entrynodes.h"
#include "torcert.h"
#include "voting_schedule.h"
#include "dirauth/dirvote.h"
#include "dirauth/mode.h"
#include "dirauth/shared_random_state.h"
Data Structures | |
struct | pending_consensus_t |
struct | dir_src_ent_t |
struct | pending_vote_t |
struct | consensus_method_range_t |
struct | microdesc_vote_line_t |
Macros | |
#define | DIRVOTE_PRIVATE |
#define | get_most_frequent_member(lst) smartlist_get_most_frequent_string(lst) |
#define | CMP_FIELD(utype, itype, field) |
#define | MIN_VOTES_FOR_PARAM 3 |
#define | RANGE_CHECK(a, b, c, d, e, f, g, mx) |
#define | CHECK_EQ(a, b, margin) ((a)-(b) >= 0 ? (a)-(b) <= (margin) : (b)-(a) <= (margin)) |
#define | IF_TIME_FOR_NEXT_ACTION(when_field, done_field) |
#define | ENDIF |
Typedefs | |
typedef struct pending_consensus_t | pending_consensus_t |
typedef struct dir_src_ent_t | dir_src_ent_t |
typedef struct pending_vote_t | pending_vote_t |
typedef struct microdesc_vote_line_t | microdesc_vote_line_t |
Functions | |
STATIC authority_cert_t * | authority_cert_dup (authority_cert_t *cert) |
STATIC char * | format_networkstatus_vote (crypto_pk_t *private_signing_key, networkstatus_t *v3_ns) |
STATIC char * | make_consensus_method_list (int low, int high, const char *separator) |
STATIC int32_t | dirvote_get_intermediate_param_value (const smartlist_t *param_list, const char *keyword, int32_t default_val) |
STATIC smartlist_t * | dirvote_compute_params (smartlist_t *votes, int method, int total_authorities) |
int | networkstatus_compute_bw_weights_v10 (smartlist_t *chunks, int64_t G, int64_t M, int64_t E, int64_t D, int64_t T, int64_t weight_scale) |
STATIC char * | networkstatus_compute_consensus (smartlist_t *votes, int total_authorities, crypto_pk_t *identity_key, crypto_pk_t *signing_key, const char *legacy_id_key_digest, crypto_pk_t *legacy_signing_key, consensus_flavor_t flavor) |
STATIC char * | compute_consensus_package_lines (smartlist_t *votes) |
STATIC int | networkstatus_add_detached_signatures (networkstatus_t *target, ns_detached_signatures_t *sigs, const char *source, int severity, const char **msg_out) |
STATIC char * | networkstatus_get_detached_signatures (smartlist_t *consensuses) |
time_t | dirvote_act (const or_options_t *options, time_t now) |
pending_vote_t * | dirvote_add_vote (const char *vote_body, const char **msg_out, int *status_out) |
int | dirvote_add_signatures (const char *detached_signatures_body, const char *source, const char **msg) |
void | dirvote_free_all (void) |
MOCK_IMPL (const char *, dirvote_get_pending_consensus,(consensus_flavor_t flav)) | |
MOCK_IMPL (const char *, dirvote_get_pending_detached_signatures,(void)) | |
const cached_dir_t * | dirvote_get_vote (const char *fp, int flags) |
STATIC microdesc_t * | dirvote_create_microdescriptor (const routerinfo_t *ri, int consensus_method) |
vote_microdesc_hash_t * | dirvote_format_all_microdesc_vote_lines (const routerinfo_t *ri, time_t now, smartlist_t *microdescriptors_out) |
void | dirvote_parse_sr_commits (networkstatus_t *ns, const smartlist_t *tokens) |
void | dirvote_clear_commits (networkstatus_t *ns) |
void | dirvote_dirreq_get_status_vote (const char *url, smartlist_t *items, smartlist_t *dir_items) |
networkstatus_t * | dirserv_generate_networkstatus_vote_obj (crypto_pk_t *private_key, authority_cert_t *cert) |
Functions to compute directory consensus, and schedule voting.
This module is the center of the consensus-voting based directory authority system. With this system, a set of authorities first publish vote based on their opinions of the network, and then compute a consensus from those votes. Each authority signs the consensus, and clients trust the consensus if enough known authorities have signed it.
The code in this module is only invoked on directory authorities. It's responsible for:
The main entry points are in dirvote_act(), which handles scheduled actions; and dirvote_add_vote() and dirvote_add_signatures(), which handle uploaded and downloaded votes and signatures.
(See dir-spec.txt from torspec.git for a complete specification of the directory protocol and voting algorithms.)
#define CMP_FIELD | ( | utype, | |
itype, | |||
field | |||
) |
#define ENDIF |
#define get_most_frequent_member | ( | lst | ) | smartlist_get_most_frequent_string(lst) |
Given a sorted list of strings lst, return the member that appears most. Break ties in favor of later-occurring members.
#define IF_TIME_FOR_NEXT_ACTION | ( | when_field, | |
done_field | |||
) |
#define MIN_VOTES_FOR_PARAM 3 |
Minimum number of directory authorities voting for a parameter to include it in the consensus, if consensus method 12 or later is to be used. See proposal 178 for details.
#define RANGE_CHECK | ( | a, | |
b, | |||
c, | |||
d, | |||
e, | |||
f, | |||
g, | |||
mx | |||
) |
typedef struct dir_src_ent_t dir_src_ent_t |
Temporary structure used in constructing a list of dir-source entries for a consensus. One of these is generated for every vote, and one more for every legacy key in each vote.
typedef struct microdesc_vote_line_t microdesc_vote_line_t |
Helper type used when generating the microdescriptor lines in a directory vote.
typedef struct pending_consensus_t pending_consensus_t |
A consensus that we have built and are appending signatures to. Once it's time to publish it, it will become an active consensus if it accumulates enough signatures.
typedef struct pending_vote_t pending_vote_t |
A vote networkstatus_t and its unparsed body: held around so we can use it to generate a consensus (at voting_ends) and so we can serve it to other authorities that might want it.
STATIC authority_cert_t* authority_cert_dup | ( | authority_cert_t * | cert | ) |
Allocate and return a new authority_cert_t with the same contents as cert.
STATIC char* compute_consensus_package_lines | ( | smartlist_t * | votes | ) |
Given a list of networkstatus_t for each vote, return a newly allocated string containing the "package" lines for the vote.
networkstatus_t* dirserv_generate_networkstatus_vote_obj | ( | crypto_pk_t * | private_key, |
authority_cert_t * | cert | ||
) |
Return a new networkstatus_t* containing our current opinion. (For v3 authorities)
time_t dirvote_act | ( | const or_options_t * | options, |
time_t | now | ||
) |
Entry point: Take whatever voting actions are pending as of now.
Return the time at which the next action should be taken.
int dirvote_add_signatures | ( | const char * | detached_signatures_body, |
const char * | source, | ||
const char ** | msg | ||
) |
Helper: we just got the detached_signatures_body sent to us as signatures on the currently pending consensus. Add them to the pending consensus (if we have one); otherwise queue them until we have a consensus. Return negative on failure, nonnegative on success.
pending_vote_t* dirvote_add_vote | ( | const char * | vote_body, |
const char ** | msg_out, | ||
int * | status_out | ||
) |
Called when we have received a networkstatus vote in vote_body. Parse and validate it, and on success store it as a pending vote (which we then return). Return NULL on failure. Sets *msg_out and *status_out to an HTTP response and status code. (V3 authority only)
STATIC smartlist_t* dirvote_compute_params | ( | smartlist_t * | votes, |
int | method, | ||
int | total_authorities | ||
) |
Helper: given a list of valid networkstatus_t, return a new smartlist containing the contents of the consensus network parameter set.
STATIC microdesc_t* dirvote_create_microdescriptor | ( | const routerinfo_t * | ri, |
int | consensus_method | ||
) |
Construct and return a new microdescriptor from a routerinfo ri according to consensus_method.
vote_microdesc_hash_t* dirvote_format_all_microdesc_vote_lines | ( | const routerinfo_t * | ri, |
time_t | now, | ||
smartlist_t * | microdescriptors_out | ||
) |
Generate and return a linked list of all the lines that should appear to describe a router's microdescriptor versions in a directory vote. Add the generated microdescriptors to microdescriptors_out.
void dirvote_free_all | ( | void | ) |
Release all static storage held in dirvote.c
STATIC int32_t dirvote_get_intermediate_param_value | ( | const smartlist_t * | param_list, |
const char * | keyword, | ||
int32_t | default_val | ||
) |
Given a list of K=V values, return the int32_t value corresponding to KEYWORD=, or default_val if no such value exists, or if the value is corrupt.
const cached_dir_t* dirvote_get_vote | ( | const char * | fp, |
int | flags | ||
) |
Return a given vote specified by fp. If by_id, return the vote for the authority with the v3 authority identity key digest fp; if by_id is false, return the vote whose digest is fp. If fp is NULL, return our own vote. If include_previous is false, do not consider any votes for a consensus that's already been built. If include_pending is false, do not consider any votes for the consensus that's in progress. May return NULL if we have no vote for the authority in question.
STATIC char* format_networkstatus_vote | ( | crypto_pk_t * | private_signing_key, |
networkstatus_t * | v3_ns | ||
) |
Return a new string containing the string representation of the vote in v3_ns, signed with our v3 signing key private_signing_key. For v3 authorities.
STATIC char* make_consensus_method_list | ( | int | low, |
int | high, | ||
const char * | separator | ||
) |
Return a newly allocated string holding the numbers between low and high (inclusive) that are supported consensus methods.
MOCK_IMPL | ( | const char * | , |
dirvote_get_pending_consensus | , | ||
(consensus_flavor_t flav) | |||
) |
Return the body of the consensus that we're currently trying to build.
MOCK_IMPL | ( | const char * | , |
dirvote_get_pending_detached_signatures | , | ||
(void) | |||
) |
Return the signatures that we know for the consensus that we're currently trying to build.
STATIC int networkstatus_add_detached_signatures | ( | networkstatus_t * | target, |
ns_detached_signatures_t * | sigs, | ||
const char * | source, | ||
int | severity, | ||
const char ** | msg_out | ||
) |
Given a consensus vote target and a set of detached signatures in sigs that correspond to the same consensus, check whether there are any new signatures in src_voter_list that should be added to target. (A signature should be added if we have no signature for that voter in target yet, or if we have no verifiable signature and the new signature is verifiable.) Return the number of signatures added or changed, or -1 if the document signed by sigs isn't the same document as target.
Make sure all the digests we know match, and at least one matches.
int networkstatus_compute_bw_weights_v10 | ( | smartlist_t * | chunks, |
int64_t | G, | ||
int64_t | M, | ||
int64_t | E, | ||
int64_t | D, | ||
int64_t | T, | ||
int64_t | weight_scale | ||
) |
This function computes the bandwidth weights for consensus method 10.
It returns true if weights could be computed, false otherwise.
STATIC char* networkstatus_compute_consensus | ( | smartlist_t * | votes, |
int | total_authorities, | ||
crypto_pk_t * | identity_key, | ||
crypto_pk_t * | signing_key, | ||
const char * | legacy_id_key_digest, | ||
crypto_pk_t * | legacy_signing_key, | ||
consensus_flavor_t | flavor | ||
) |
Given a list of vote networkstatus_t in votes, our public authority identity_key, our private authority signing_key, and the number of total_authorities that we believe exist in our voting quorum, generate the text of a new v3 consensus or microdescriptor consensus (depending on flavor), and return the value in a newly allocated string.
Note: this function DOES NOT check whether the votes are from recognized authorities. (dirvote_add_vote does that.)
WATCH OUT: You need to think before you change the behavior of this function, or of the functions it calls! If some authorities compute the consensus with a different algorithm than others, they will not reach the same result, and they will not all sign the same thing! If you really need to change the algorithm here, you should allocate a new "consensus_method" for the new behavior, and make the new behavior conditional on a new-enough consensus_method.
STATIC char* networkstatus_get_detached_signatures | ( | smartlist_t * | consensuses | ) |
Return a newly allocated string holding the detached-signatures document corresponding to the signatures on consensuses, which must contain exactly one FLAV_NS consensus, and no more than one consensus for each other flavor.