diff options
Diffstat (limited to 'src/feature/dirauth')
42 files changed, 1437 insertions, 469 deletions
diff --git a/src/feature/dirauth/.may_include b/src/feature/dirauth/.may_include new file mode 100644 index 0000000000..a9bb274699 --- /dev/null +++ b/src/feature/dirauth/.may_include @@ -0,0 +1,2 @@ +*.h +feature/dirauth/*.inc diff --git a/src/feature/dirauth/authmode.c b/src/feature/dirauth/authmode.c index 29fcc6d1a9..0fde7bc679 100644 --- a/src/feature/dirauth/authmode.c +++ b/src/feature/dirauth/authmode.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -26,6 +26,15 @@ authdir_mode(const or_options_t *options) { return options->AuthoritativeDir != 0; } + +/* Return true iff we believe ourselves to be a v3 authoritative directory + * server. */ +int +authdir_mode_v3(const or_options_t *options) +{ + return authdir_mode(options) && options->V3AuthoritativeDir != 0; +} + /** Return true iff we are an authoritative directory server that is * authoritative about receiving and serving descriptors of type * <b>purpose</b> on its dirport. diff --git a/src/feature/dirauth/authmode.h b/src/feature/dirauth/authmode.h index bfd5f4dc04..6e6ba7f8ae 100644 --- a/src/feature/dirauth/authmode.h +++ b/src/feature/dirauth/authmode.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2018-2019, The Tor Project, Inc. */ +/* Copyright (c) 2018-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -14,19 +14,13 @@ #ifdef HAVE_MODULE_DIRAUTH int authdir_mode(const or_options_t *options); +int authdir_mode_v3(const or_options_t *options); int authdir_mode_handles_descs(const or_options_t *options, int purpose); int authdir_mode_publishes_statuses(const or_options_t *options); int authdir_mode_tests_reachability(const or_options_t *options); int authdir_mode_bridge(const or_options_t *options); -/* Return true iff we believe ourselves to be a v3 authoritative directory - * server. */ -static inline int -authdir_mode_v3(const or_options_t *options) -{ - return authdir_mode(options) && options->V3AuthoritativeDir != 0; -} - +/* Is the dirauth module enabled? */ #define have_module_dirauth() (1) #else /* !defined(HAVE_MODULE_DIRAUTH) */ diff --git a/src/feature/dirauth/bridgeauth.c b/src/feature/dirauth/bridgeauth.c index 4aaefc7a6d..b7bf3e4e04 100644 --- a/src/feature/dirauth/bridgeauth.c +++ b/src/feature/dirauth/bridgeauth.c @@ -1,9 +1,14 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file bridgeauth.c + * @brief Bridge authority code + **/ + #include "core/or/or.h" #include "feature/dirauth/bridgeauth.h" #include "feature/dirauth/voteflags.h" diff --git a/src/feature/dirauth/bridgeauth.h b/src/feature/dirauth/bridgeauth.h index 4905e9c3ee..382d1cfcb8 100644 --- a/src/feature/dirauth/bridgeauth.h +++ b/src/feature/dirauth/bridgeauth.h @@ -1,9 +1,14 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file bridgeauth.h + * @brief Header for bridgeauth.c + **/ + #ifndef TOR_DIRAUTH_BRIDGEAUTH_H #define TOR_DIRAUTH_BRIDGEAUTH_H diff --git a/src/feature/dirauth/bwauth.c b/src/feature/dirauth/bwauth.c index e60c8b86bd..ff0c78f018 100644 --- a/src/feature/dirauth/bwauth.c +++ b/src/feature/dirauth/bwauth.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -13,10 +13,12 @@ #include "feature/dirauth/bwauth.h" #include "app/config/config.h" +#include "feature/dirauth/dirauth_sys.h" #include "feature/nodelist/networkstatus.h" #include "feature/nodelist/routerlist.h" #include "feature/dirparse/ns_parse.h" +#include "feature/dirauth/dirauth_options_st.h" #include "feature/nodelist/routerinfo_st.h" #include "feature/nodelist/vote_routerstatus_st.h" @@ -56,7 +58,7 @@ dirserv_get_last_n_measured_bws(void) } /** Measured bandwidth cache entry */ -typedef struct mbw_cache_entry_s { +typedef struct mbw_cache_entry_t { long mbw_kb; time_t as_of; } mbw_cache_entry_t; @@ -182,7 +184,7 @@ dirserv_get_credible_bandwidth_kb(const routerinfo_t *ri) /* Check if we have a measured bandwidth, and check the threshold if not */ if (!(dirserv_query_measured_bw_cache_kb(ri->cache_info.identity_digest, &mbw_kb, NULL))) { - threshold = get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised; + threshold = dirauth_get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised; if (routers_with_measured_bw > threshold) { /* Return zero for unmeasured bandwidth if we are above threshold */ bw_kb = 0; diff --git a/src/feature/dirauth/bwauth.h b/src/feature/dirauth/bwauth.h index 81c8affbd7..849c58e2fc 100644 --- a/src/feature/dirauth/bwauth.h +++ b/src/feature/dirauth/bwauth.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** diff --git a/src/feature/dirauth/dirauth_config.c b/src/feature/dirauth/dirauth_config.c new file mode 100644 index 0000000000..ca16dc8424 --- /dev/null +++ b/src/feature/dirauth/dirauth_config.c @@ -0,0 +1,470 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2020, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file dirauth_config.c + * @brief Code to interpret the user's configuration of Tor's directory + * authority module. + **/ + +#include "orconfig.h" +#include "feature/dirauth/dirauth_config.h" + +#include "lib/encoding/confline.h" +#include "lib/confmgt/confmgt.h" +#include "lib/conf/confdecl.h" + +/* Required for dirinfo_type_t in or_options_t */ +#include "core/or/or.h" +#include "app/config/config.h" + +#include "feature/dircommon/voting_schedule.h" +#include "feature/stats/rephist.h" + +#include "feature/dirauth/authmode.h" +#include "feature/dirauth/bwauth.h" +#include "feature/dirauth/dirauth_periodic.h" +#include "feature/dirauth/dirauth_sys.h" +#include "feature/dirauth/dirvote.h" +#include "feature/dirauth/guardfraction.h" +#include "feature/dirauth/dirauth_options_st.h" + +/* Copied from config.c, we will refactor later in 29211. */ +#define REJECT(arg) \ + STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END +#if defined(__GNUC__) && __GNUC__ <= 3 +#define COMPLAIN(args...) \ + STMT_BEGIN log_warn(LD_CONFIG, args); STMT_END +#else +#define COMPLAIN(args, ...) \ + STMT_BEGIN log_warn(LD_CONFIG, args, ##__VA_ARGS__); STMT_END +#endif /* defined(__GNUC__) && __GNUC__ <= 3 */ + +#define YES_IF_CHANGED_INT(opt) \ + if (!CFG_EQ_INT(old_options, new_options, opt)) return 1; + +/** Return true iff we are configured to reject request under load for non + * relay connections. */ +bool +dirauth_should_reject_requests_under_load(void) +{ + return !!dirauth_get_options()->AuthDirRejectRequestsUnderLoad; +} + +/** + * Legacy validation/normalization function for the dirauth mode options in + * options. Uses old_options as the previous options. + * + * Returns 0 on success, returns -1 and sets *msg to a newly allocated string + * on error. + */ +int +options_validate_dirauth_mode(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + if (BUG(!options)) + return -1; + + if (BUG(!msg)) + return -1; + + if (!authdir_mode(options)) + return 0; + + /* confirm that our address isn't broken, so we can complain now */ + uint32_t tmp; + if (resolve_my_address(LOG_WARN, options, &tmp, NULL, NULL) < 0) + REJECT("Failed to resolve/guess local address. See logs for details."); + + if (!options->ContactInfo && !options->TestingTorNetwork) + REJECT("Authoritative directory servers must set ContactInfo"); + + if (options->UseEntryGuards) { + log_info(LD_CONFIG, "Authoritative directory servers can't set " + "UseEntryGuards. Disabling."); + options->UseEntryGuards = 0; + } + if (!options->DownloadExtraInfo && authdir_mode_v3(options)) { + log_info(LD_CONFIG, "Authoritative directories always try to download " + "extra-info documents. Setting DownloadExtraInfo."); + options->DownloadExtraInfo = 1; + } + if (!(options->BridgeAuthoritativeDir || + options->V3AuthoritativeDir)) + REJECT("AuthoritativeDir is set, but none of " + "(Bridge/V3)AuthoritativeDir is set."); + + /* If we have a v3bandwidthsfile and it's broken, complain on startup */ + if (options->V3BandwidthsFile && !old_options) { + dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL, NULL, + NULL); + } + /* same for guardfraction file */ + if (options->GuardfractionFile && !old_options) { + dirserv_read_guardfraction_file(options->GuardfractionFile, NULL); + } + + if (!options->DirPort_set) + REJECT("Running as authoritative directory, but no DirPort set."); + + if (!options->ORPort_set) + REJECT("Running as authoritative directory, but no ORPort set."); + + if (options->ClientOnly) + REJECT("Running as authoritative directory, but ClientOnly also set."); + + return 0; +} + +/** + * Legacy validation/normalization function for the dirauth schedule options + * in options. Uses old_options as the previous options. + * + * Returns 0 on success, returns -1 and sets *msg to a newly allocated string + * on error. + */ +int +options_validate_dirauth_schedule(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + if (BUG(!options)) + return -1; + + if (BUG(!msg)) + return -1; + + if (!authdir_mode_v3(options)) + return 0; + + if (options->V3AuthVoteDelay + options->V3AuthDistDelay >= + options->V3AuthVotingInterval/2) { + REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than half " + "V3AuthVotingInterval"); + } + + if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS) { + if (options->TestingTorNetwork) { + if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS_TESTING) { + REJECT("V3AuthVoteDelay is way too low."); + } else { + COMPLAIN("V3AuthVoteDelay is very low. " + "This may lead to failure to vote for a consensus."); + } + } else { + REJECT("V3AuthVoteDelay is way too low."); + } + } + + if (options->V3AuthDistDelay < MIN_DIST_SECONDS) { + if (options->TestingTorNetwork) { + if (options->V3AuthDistDelay < MIN_DIST_SECONDS_TESTING) { + REJECT("V3AuthDistDelay is way too low."); + } else { + COMPLAIN("V3AuthDistDelay is very low. " + "This may lead to missing votes in a consensus."); + } + } else { + REJECT("V3AuthDistDelay is way too low."); + } + } + + if (options->V3AuthNIntervalsValid < 2) + REJECT("V3AuthNIntervalsValid must be at least 2."); + + if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL) { + if (options->TestingTorNetwork) { + if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL_TESTING) { + /* Unreachable, covered by earlier checks */ + REJECT("V3AuthVotingInterval is insanely low."); /* LCOV_EXCL_LINE */ + } else { + COMPLAIN("V3AuthVotingInterval is very low. " + "This may lead to failure to synchronise for a consensus."); + } + } else { + REJECT("V3AuthVotingInterval is insanely low."); + } + } else if (options->V3AuthVotingInterval > 24*60*60) { + REJECT("V3AuthVotingInterval is insanely high."); + } else if (((24*60*60) % options->V3AuthVotingInterval) != 0) { + COMPLAIN("V3AuthVotingInterval does not divide evenly into 24 hours."); + } + + return 0; +} + +/** + * Legacy validation/normalization function for the dirauth testing options + * in options. Uses old_options as the previous options. + * + * Returns 0 on success, returns -1 and sets *msg to a newly allocated string + * on error. + */ +int +options_validate_dirauth_testing(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + if (BUG(!options)) + return -1; + + if (BUG(!msg)) + return -1; + + if (!authdir_mode(options)) + return 0; + + if (!authdir_mode_v3(options)) + return 0; + + if (options->TestingV3AuthInitialVotingInterval + < MIN_VOTE_INTERVAL_TESTING_INITIAL) { + REJECT("TestingV3AuthInitialVotingInterval is insanely low."); + } else if (((30*60) % options->TestingV3AuthInitialVotingInterval) != 0) { + REJECT("TestingV3AuthInitialVotingInterval does not divide evenly into " + "30 minutes."); + } + + if (options->TestingV3AuthInitialVoteDelay < MIN_VOTE_SECONDS_TESTING) { + REJECT("TestingV3AuthInitialVoteDelay is way too low."); + } + + if (options->TestingV3AuthInitialDistDelay < MIN_DIST_SECONDS_TESTING) { + REJECT("TestingV3AuthInitialDistDelay is way too low."); + } + + if (options->TestingV3AuthInitialVoteDelay + + options->TestingV3AuthInitialDistDelay >= + options->TestingV3AuthInitialVotingInterval) { + REJECT("TestingV3AuthInitialVoteDelay plus TestingV3AuthInitialDistDelay " + "must be less than TestingV3AuthInitialVotingInterval"); + } + + if (options->TestingV3AuthVotingStartOffset > + MIN(options->TestingV3AuthInitialVotingInterval, + options->V3AuthVotingInterval)) { + REJECT("TestingV3AuthVotingStartOffset is higher than the voting " + "interval."); + } else if (options->TestingV3AuthVotingStartOffset < 0) { + REJECT("TestingV3AuthVotingStartOffset must be non-negative."); + } + + return 0; +} + +/** + * Return true if changing the configuration from <b>old</b> to <b>new</b> + * affects the timing of the voting subsystem + */ +static int +options_transition_affects_dirauth_timing(const or_options_t *old_options, + const or_options_t *new_options) +{ + tor_assert(old_options); + tor_assert(new_options); + + if (authdir_mode_v3(old_options) != authdir_mode_v3(new_options)) + return 1; + if (! authdir_mode_v3(new_options)) + return 0; + + YES_IF_CHANGED_INT(V3AuthVotingInterval); + YES_IF_CHANGED_INT(V3AuthVoteDelay); + YES_IF_CHANGED_INT(V3AuthDistDelay); + YES_IF_CHANGED_INT(TestingV3AuthInitialVotingInterval); + YES_IF_CHANGED_INT(TestingV3AuthInitialVoteDelay); + YES_IF_CHANGED_INT(TestingV3AuthInitialDistDelay); + YES_IF_CHANGED_INT(TestingV3AuthVotingStartOffset); + + return 0; +} + +/** Fetch the active option list, and take dirauth actions based on it. All of + * the things we do should survive being done repeatedly. If present, + * <b>old_options</b> contains the previous value of the options. + * + * Return 0 if all goes well, return -1 if it's time to die. + * + * Note: We haven't moved all the "act on new configuration" logic + * into the options_act* functions yet. Some is still in do_hup() and other + * places. + */ +int +options_act_dirauth(const or_options_t *old_options) +{ + const or_options_t *options = get_options(); + + /* We may need to reschedule some dirauth stuff if our status changed. */ + if (old_options) { + if (options_transition_affects_dirauth_timing(old_options, options)) { + voting_schedule_recalculate_timing(options, time(NULL)); + reschedule_dirvote(options); + } + } + + return 0; +} + +/** Fetch the active option list, and take dirauth mtbf actions based on it. + * All of the things we do should survive being done repeatedly. If present, + * <b>old_options</b> contains the previous value of the options. + * + * Must be called immediately after a successful or_state_load(). + * + * Return 0 if all goes well, return -1 if it's time to die. + * + * Note: We haven't moved all the "act on new configuration" logic + * into the options_act* functions yet. Some is still in do_hup() and other + * places. + */ +int +options_act_dirauth_mtbf(const or_options_t *old_options) +{ + (void)old_options; + + const or_options_t *options = get_options(); + int running_tor = options->command == CMD_RUN_TOR; + + if (!authdir_mode(options)) + return 0; + + /* Load dirauth state */ + if (running_tor) { + rep_hist_load_mtbf_data(time(NULL)); + } + + return 0; +} + +/** Fetch the active option list, and take dirauth statistics actions based + * on it. All of the things we do should survive being done repeatedly. If + * present, <b>old_options</b> contains the previous value of the options. + * + * Sets <b>*print_notice_out</b> if we enabled stats, and need to print + * a stats log using options_act_relay_stats_msg(). + * + * Return 0 if all goes well, return -1 if it's time to die. + * + * Note: We haven't moved all the "act on new configuration" logic + * into the options_act* functions yet. Some is still in do_hup() and other + * places. + */ +int +options_act_dirauth_stats(const or_options_t *old_options, + bool *print_notice_out) +{ + if (BUG(!print_notice_out)) + return -1; + + const or_options_t *options = get_options(); + + if (authdir_mode_bridge(options)) { + time_t now = time(NULL); + int print_notice = 0; + + if (!old_options || !authdir_mode_bridge(old_options)) { + rep_hist_desc_stats_init(now); + print_notice = 1; + } + if (print_notice) + *print_notice_out = 1; + } + + /* If we used to have statistics enabled but we just disabled them, + stop gathering them. */ + if (old_options && authdir_mode_bridge(old_options) && + !authdir_mode_bridge(options)) + rep_hist_desc_stats_term(); + + return 0; +} + +/** + * Make any necessary modifications to a dirauth_options_t that occur + * before validation. On success return 0; on failure return -1 and + * set *<b>msg_out</b> to a newly allocated error string. + **/ +static int +dirauth_options_pre_normalize(void *arg, char **msg_out) +{ + dirauth_options_t *options = arg; + (void)msg_out; + + if (!options->RecommendedClientVersions) + options->RecommendedClientVersions = + config_lines_dup(options->RecommendedVersions); + if (!options->RecommendedServerVersions) + options->RecommendedServerVersions = + config_lines_dup(options->RecommendedVersions); + + if (config_ensure_bandwidth_cap(&options->AuthDirFastGuarantee, + "AuthDirFastGuarantee", msg_out) < 0) + return -1; + if (config_ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee, + "AuthDirGuardBWGuarantee", msg_out) < 0) + return -1; + + return 0; +} + +/** + * Check whether a dirauth_options_t is correct. + * + * On success return 0; on failure return -1 and set *<b>msg_out</b> to a + * newly allocated error string. + **/ +static int +dirauth_options_validate(const void *arg, char **msg) +{ + const dirauth_options_t *options = arg; + + if (options->VersioningAuthoritativeDirectory && + (!options->RecommendedClientVersions || + !options->RecommendedServerVersions)) { + REJECT("Versioning authoritative dir servers must set " + "Recommended*Versions."); + } + + char *t; + /* Call these functions to produce warnings only. */ + t = format_recommended_version_list(options->RecommendedClientVersions, 1); + tor_free(t); + t = format_recommended_version_list(options->RecommendedServerVersions, 1); + tor_free(t); + + if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) { + COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high."); + } + + return 0; +} + +/* Declare the options field table for dirauth_options */ +#define CONF_CONTEXT TABLE +#include "feature/dirauth/dirauth_options.inc" +#undef CONF_CONTEXT + +/** Magic number for dirauth_options_t. */ +#define DIRAUTH_OPTIONS_MAGIC 0x41757448 + +/** + * Declare the configuration options for the dirauth module. + **/ +const config_format_t dirauth_options_fmt = { + .size = sizeof(dirauth_options_t), + .magic = { "dirauth_options_t", + DIRAUTH_OPTIONS_MAGIC, + offsetof(dirauth_options_t, magic) }, + .vars = dirauth_options_t_vars, + + .pre_normalize_fn = dirauth_options_pre_normalize, + .validate_fn = dirauth_options_validate +}; diff --git a/src/feature/dirauth/dirauth_config.h b/src/feature/dirauth/dirauth_config.h new file mode 100644 index 0000000000..9042ff8779 --- /dev/null +++ b/src/feature/dirauth/dirauth_config.h @@ -0,0 +1,91 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2020, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file dirauth_config.h + * @brief Header for feature/dirauth/dirauth_config.c + **/ + +#ifndef TOR_FEATURE_DIRAUTH_DIRAUTH_CONFIG_H +#define TOR_FEATURE_DIRAUTH_DIRAUTH_CONFIG_H + +struct or_options_t; + +#ifdef HAVE_MODULE_DIRAUTH + +#include "lib/cc/torint.h" + +int options_validate_dirauth_mode(const struct or_options_t *old_options, + struct or_options_t *options, + char **msg); + +int options_validate_dirauth_schedule(const struct or_options_t *old_options, + struct or_options_t *options, + char **msg); + +int options_validate_dirauth_testing(const struct or_options_t *old_options, + struct or_options_t *options, + char **msg); + +int options_act_dirauth(const struct or_options_t *old_options); +int options_act_dirauth_mtbf(const struct or_options_t *old_options); +int options_act_dirauth_stats(const struct or_options_t *old_options, + bool *print_notice_out); + +bool dirauth_should_reject_requests_under_load(void); + +extern const struct config_format_t dirauth_options_fmt; + +#else /* !defined(HAVE_MODULE_DIRAUTH) */ + +/** When tor is compiled with the dirauth module disabled, it can't be + * configured as a directory authority. + * + * Returns -1 and sets msg to a newly allocated string, if AuthoritativeDir + * is set in options. Otherwise returns 0. */ +static inline int +options_validate_dirauth_mode(const struct or_options_t *old_options, + struct or_options_t *options, + char **msg) +{ + (void)old_options; + + /* Only check the primary option for now, #29211 will disable more + * options. */ + if (options->AuthoritativeDir) { + /* REJECT() this configuration */ + *msg = tor_strdup("This tor was built with dirauth mode disabled. " + "It can not be configured with AuthoritativeDir 1."); + return -1; + } + + return 0; +} + +#define options_validate_dirauth_schedule(old_options, options, msg) \ + (((void)(old_options)),((void)(options)),((void)(msg)),0) +#define options_validate_dirauth_testing(old_options, options, msg) \ + (((void)(old_options)),((void)(options)),((void)(msg)),0) + +#define options_act_dirauth(old_options) \ + (((void)(old_options)),0) +#define options_act_dirauth_mtbf(old_options) \ + (((void)(old_options)),0) + +static inline int +options_act_dirauth_stats(const struct or_options_t *old_options, + bool *print_notice_out) +{ + (void)old_options; + *print_notice_out = 0; + return 0; +} + +#define dirauth_should_reject_requests_under_load() (false) + +#endif /* defined(HAVE_MODULE_DIRAUTH) */ + +#endif /* !defined(TOR_FEATURE_DIRAUTH_DIRAUTH_CONFIG_H) */ diff --git a/src/feature/dirauth/dirauth_options.inc b/src/feature/dirauth/dirauth_options.inc new file mode 100644 index 0000000000..21f4996c39 --- /dev/null +++ b/src/feature/dirauth/dirauth_options.inc @@ -0,0 +1,105 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file dirauth_options.inc + * @brief Declare configuration options for the crypto_ops module. + **/ + +/** Holds configuration about our directory authority options. */ +BEGIN_CONF_STRUCT(dirauth_options_t) + +/** If non-zero, always vote the Fast flag for any relay advertising + * this amount of capacity or more. */ +CONF_VAR(AuthDirFastGuarantee, MEMUNIT, 0, "100 KB") + +/** If non-zero, this advertised capacity or more is always sufficient + * to satisfy the bandwidth requirement for the Guard flag. */ +CONF_VAR(AuthDirGuardBWGuarantee, MEMUNIT, 0, "2 MB") + +/** Boolean: are we on IPv6? */ +CONF_VAR(AuthDirHasIPv6Connectivity, BOOL, 0, "0") + +/** True iff we should list bad exits, and vote for all other exits as + * good. */ +CONF_VAR(AuthDirListBadExits, BOOL, 0, "0") + +/** Do not permit more than this number of servers per IP address. */ +CONF_VAR(AuthDirMaxServersPerAddr, POSINT, 0, "2") + +/** Boolean: Do we enforce key-pinning? */ +CONF_VAR(AuthDirPinKeys, BOOL, 0, "1") + +/** Bool (default: 1): Switch for the shared random protocol. Only + * relevant to a directory authority. If off, the authority won't + * participate in the protocol. If on (default), a flag is added to the + * vote indicating participation. */ +CONF_VAR(AuthDirSharedRandomness, BOOL, 0, "1") + +/** Bool (default: 1): When testing routerinfos as a directory authority, + * do we enforce Ed25519 identity match? */ +/* NOTE: remove this option someday. */ +CONF_VAR(AuthDirTestEd25519LinkKeys, BOOL, 0, "1") + +/** Authority only: key=value pairs that we add to our networkstatus + * consensus vote on the 'params' line. */ +CONF_VAR(ConsensusParams, STRING, 0, NULL) + +/** Authority only: minimum number of measured bandwidths we must see + * before we only believe measured bandwidths to assign flags. */ +CONF_VAR(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, 0, "500") + +/** As directory authority, accept hidden service directories after what + * time? */ +CONF_VAR(MinUptimeHidServDirectoryV2, INTERVAL, 0, "96 hours") + +/** Which versions of tor should we tell users to run? */ +CONF_VAR(RecommendedVersions, LINELIST, 0, NULL) + +/** Which versions of tor should we tell users to run on clients? */ +CONF_VAR(RecommendedClientVersions, LINELIST, 0, NULL) + +/** Which versions of tor should we tell users to run on relays? */ +CONF_VAR(RecommendedServerVersions, LINELIST, 0, NULL) + +/** If an authority has been around for less than this amount of time, it + * does not believe its reachability information is accurate. Only + * altered on testing networks. */ +CONF_VAR(TestingAuthDirTimeToLearnReachability, INTERVAL, 0, "30 minutes") + + /** Relays in a testing network which should be voted Exit + * regardless of exit policy. */ +CONF_VAR(TestingDirAuthVoteExit, ROUTERSET, 0, NULL) +CONF_VAR(TestingDirAuthVoteExitIsStrict, BOOL, 0, "0") + +/** Relays in a testing network which should be voted Guard + * regardless of uptime and bandwidth. */ +CONF_VAR(TestingDirAuthVoteGuard, ROUTERSET, 0, NULL) +CONF_VAR(TestingDirAuthVoteGuardIsStrict, BOOL, 0, "0") + +/** Relays in a testing network which should be voted HSDir + * regardless of uptime and DirPort. */ +CONF_VAR(TestingDirAuthVoteHSDir, ROUTERSET, 0, NULL) +CONF_VAR(TestingDirAuthVoteHSDirIsStrict, BOOL, 0, "0") + +/** Minimum value for the Exit flag threshold on testing networks. */ +CONF_VAR(TestingMinExitFlagThreshold, MEMUNIT, 0, "0") + +/** Minimum value for the Fast flag threshold on testing networks. */ +CONF_VAR(TestingMinFastFlagThreshold, MEMUNIT, 0, "0") + +/** Boolean: is this an authoritative directory that's willing to recommend + * versions? */ +CONF_VAR(VersioningAuthoritativeDirectory, BOOL, 0, "0") + +/** Boolean: Under bandwidth pressure, if set to 1, the authority will always + * answer directory requests from relays but will start sending 503 error code + * for the other connections. If set to 0, all connections are considered the + * same and the authority will try to answer them all regardless of bandwidth + * pressure or not. */ +CONF_VAR(AuthDirRejectRequestsUnderLoad, BOOL, 0, "1") + +END_CONF_STRUCT(dirauth_options_t) diff --git a/src/feature/dirauth/dirauth_options_st.h b/src/feature/dirauth/dirauth_options_st.h new file mode 100644 index 0000000000..02a498c054 --- /dev/null +++ b/src/feature/dirauth/dirauth_options_st.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2020, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file dirauth_options_st.h + * @brief Structure dirauth_options_t to hold directory authority options. + **/ + +#ifndef TOR_FEATURE_DIRAUTH_DIRAUTH_OPTIONS_ST_H +#define TOR_FEATURE_DIRAUTH_DIRAUTH_OPTIONS_ST_H + +#include "lib/conf/confdecl.h" +#include "feature/nodelist/routerset.h" + +#define CONF_CONTEXT STRUCT +#include "feature/dirauth/dirauth_options.inc" +#undef CONF_CONTEXT + +typedef struct dirauth_options_t dirauth_options_t; + +#endif /* !defined(TOR_FEATURE_DIRAUTH_DIRAUTH_OPTIONS_ST_H) */ diff --git a/src/feature/dirauth/dirauth_periodic.c b/src/feature/dirauth/dirauth_periodic.c index 02727d61b4..19e51c5a05 100644 --- a/src/feature/dirauth/dirauth_periodic.c +++ b/src/feature/dirauth/dirauth_periodic.c @@ -1,9 +1,14 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file dirauth_periodic.c + * @brief Peridoic events for directory authorities. + **/ + #include "core/or/or.h" #include "app/config/or_options_st.h" @@ -18,11 +23,13 @@ #include "core/mainloop/periodic.h" +#ifndef COCCI #define DECLARE_EVENT(name, roles, flags) \ static periodic_event_item_t name ## _event = \ PERIODIC_EVENT(name, \ PERIODIC_EVENT_ROLE_##roles, \ flags) +#endif /* !defined(COCCI) */ #define FL(name) (PERIODIC_EVENT_FLAG_##name) diff --git a/src/feature/dirauth/dirauth_periodic.h b/src/feature/dirauth/dirauth_periodic.h index 866fbd35de..ccdda92a77 100644 --- a/src/feature/dirauth/dirauth_periodic.h +++ b/src/feature/dirauth/dirauth_periodic.h @@ -1,9 +1,14 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file dirauth_periodic.h + * @brief Header for dirauth_periodic.c + **/ + #ifndef DIRVOTE_PERIODIC_H #define DIRVOTE_PERIODIC_H diff --git a/src/feature/dirauth/dirauth_stub.c b/src/feature/dirauth/dirauth_stub.c new file mode 100644 index 0000000000..15a195b0fb --- /dev/null +++ b/src/feature/dirauth/dirauth_stub.c @@ -0,0 +1,33 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2020, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file dirauth_stub.c + * @brief Stub declarations for use when dirauth module is disabled. + **/ + +#include "orconfig.h" +#include "feature/dirauth/dirauth_sys.h" +#include "lib/conf/conftypes.h" +#include "lib/conf/confdecl.h" +#include "lib/subsys/subsys.h" + +/* Declare the options field table for dirauth_options */ +#define CONF_CONTEXT STUB_TABLE +#include "feature/dirauth/dirauth_options.inc" +#undef CONF_CONTEXT + +static const config_format_t dirauth_options_stub_fmt = { + .vars = dirauth_options_t_vars, +}; + +const struct subsys_fns_t sys_dirauth = { + .name = "dirauth", + .supported = false, + .level = DIRAUTH_SUBSYS_LEVEL, + + .options_format = &dirauth_options_stub_fmt +}; diff --git a/src/feature/dirauth/dirauth_sys.c b/src/feature/dirauth/dirauth_sys.c index e38d391300..56ac501e16 100644 --- a/src/feature/dirauth/dirauth_sys.c +++ b/src/feature/dirauth/dirauth_sys.c @@ -1,20 +1,31 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file dirauth_sys.c + * @brief Directory authority subsystem declarations + **/ + #include "core/or/or.h" +#define DIRAUTH_SYS_PRIVATE #include "feature/dirauth/bwauth.h" #include "feature/dirauth/dirauth_sys.h" #include "feature/dirauth/dirvote.h" #include "feature/dirauth/dirauth_periodic.h" #include "feature/dirauth/keypin.h" #include "feature/dirauth/process_descs.h" +#include "feature/dirauth/dirauth_config.h" + +#include "feature/dirauth/dirauth_options_st.h" #include "lib/subsys/subsys.h" +static const dirauth_options_t *global_dirauth_options; + static int subsys_dirauth_initialize(void) { @@ -29,12 +40,31 @@ subsys_dirauth_shutdown(void) dirvote_free_all(); dirserv_clear_measured_bw_cache(); keypin_close_journal(); + global_dirauth_options = NULL; +} + +const dirauth_options_t * +dirauth_get_options(void) +{ + tor_assert(global_dirauth_options); + return global_dirauth_options; +} + +STATIC int +dirauth_set_options(void *arg) +{ + dirauth_options_t *opts = arg; + global_dirauth_options = opts; + return 0; } const struct subsys_fns_t sys_dirauth = { .name = "dirauth", .supported = true, - .level = 70, + .level = DIRAUTH_SUBSYS_LEVEL, .initialize = subsys_dirauth_initialize, .shutdown = subsys_dirauth_shutdown, + + .options_format = &dirauth_options_fmt, + .set_options = dirauth_set_options, }; diff --git a/src/feature/dirauth/dirauth_sys.h b/src/feature/dirauth/dirauth_sys.h index 4e9b6a2ab4..c512b91b33 100644 --- a/src/feature/dirauth/dirauth_sys.h +++ b/src/feature/dirauth/dirauth_sys.h @@ -1,12 +1,32 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file dirauth_sys.h + * @brief Header for dirauth_sys.c + **/ + #ifndef DIRAUTH_SYS_H #define DIRAUTH_SYS_H +struct dirauth_options_t; +const struct dirauth_options_t *dirauth_get_options(void); + extern const struct subsys_fns_t sys_dirauth; +/** + * Subsystem level for the directory-authority system. + * + * Defined here so that it can be shared between the real and stub + * definitions. + **/ +#define DIRAUTH_SUBSYS_LEVEL 70 + +#ifdef DIRAUTH_SYS_PRIVATE +STATIC int dirauth_set_options(void *arg); +#endif + #endif /* !defined(DIRAUTH_SYS_H) */ diff --git a/src/feature/dirauth/dircollate.c b/src/feature/dirauth/dircollate.c index 7992e3a85f..b35cb021ff 100644 --- a/src/feature/dirauth/dircollate.c +++ b/src/feature/dirauth/dircollate.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -32,8 +32,8 @@ static void dircollator_collate_by_ed25519(dircollator_t *dc); /** Hashtable entry mapping a pair of digests (actually an ed25519 key and an * RSA SHA1 digest) to an array of vote_routerstatus_t. */ -typedef struct ddmap_entry_s { - HT_ENTRY(ddmap_entry_s) node; +typedef struct ddmap_entry_t { + HT_ENTRY(ddmap_entry_t) node; /** A SHA1-RSA1024 identity digest and Ed25519 identity key, * concatenated. (If there is no ed25519 identity key, there is no * entry in this table.) */ @@ -89,9 +89,9 @@ ddmap_entry_set_digests(ddmap_entry_t *ent, memcpy(ent->d + DIGEST_LEN, ed25519, DIGEST256_LEN); } -HT_PROTOTYPE(double_digest_map, ddmap_entry_s, node, ddmap_entry_hash, +HT_PROTOTYPE(double_digest_map, ddmap_entry_t, node, ddmap_entry_hash, ddmap_entry_eq) -HT_GENERATE2(double_digest_map, ddmap_entry_s, node, ddmap_entry_hash, +HT_GENERATE2(double_digest_map, ddmap_entry_t, node, ddmap_entry_hash, ddmap_entry_eq, 0.6, tor_reallocarray, tor_free_) /** Helper: add a single vote_routerstatus_t <b>vrs</b> to the collator diff --git a/src/feature/dirauth/dircollate.h b/src/feature/dirauth/dircollate.h index 754a094817..90c6bddad5 100644 --- a/src/feature/dirauth/dircollate.h +++ b/src/feature/dirauth/dircollate.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -15,7 +15,7 @@ #include "lib/testsupport/testsupport.h" #include "core/or/or.h" -typedef struct dircollator_s dircollator_t; +typedef struct dircollator_t dircollator_t; dircollator_t *dircollator_new(int n_votes, int n_authorities); void dircollator_free_(dircollator_t *obj); @@ -30,11 +30,11 @@ vote_routerstatus_t **dircollator_get_votes_for_router(dircollator_t *dc, int idx); #ifdef DIRCOLLATE_PRIVATE -struct ddmap_entry_s; -typedef HT_HEAD(double_digest_map, ddmap_entry_s) double_digest_map_t; +struct ddmap_entry_t; +typedef HT_HEAD(double_digest_map, ddmap_entry_t) double_digest_map_t; /** A dircollator keeps track of all the routerstatus entries in a * set of networkstatus votes, and matches them by an appropriate rule. */ -struct dircollator_s { +struct dircollator_t { /** True iff we have run the collation algorithm. */ int is_collated; /** The total number of votes that we received. */ diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c index 043bbfc227..e230815ca3 100644 --- a/src/feature/dirauth/dirvote.c +++ b/src/feature/dirauth/dirvote.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define DIRVOTE_PRIVATE @@ -41,10 +41,12 @@ #include "feature/dirauth/dirvote.h" #include "feature/dirauth/authmode.h" #include "feature/dirauth/shared_random_state.h" +#include "feature/dirauth/dirauth_sys.h" #include "feature/nodelist/authority_cert_st.h" #include "feature/dircache/cached_dir_st.h" #include "feature/dirclient/dir_server_st.h" +#include "feature/dirauth/dirauth_options_st.h" #include "feature/nodelist/document_signature_st.h" #include "feature/nodelist/microdesc_st.h" #include "feature/nodelist/networkstatus_st.h" @@ -382,7 +384,6 @@ format_networkstatus_vote(crypto_pk_t *private_signing_key, rsf = routerstatus_format_entry(&vrs->status, vrs->version, vrs->protocols, NS_V3_VOTE, - ROUTERSTATUS_FORMAT_NO_CONSENSUS_METHOD, vrs); if (rsf) smartlist_add(chunks, rsf); @@ -1538,14 +1539,11 @@ networkstatus_compute_consensus(smartlist_t *votes, consensus_method = MAX_SUPPORTED_CONSENSUS_METHOD; } - if (consensus_method >= MIN_METHOD_FOR_INIT_BW_WEIGHTS_ONE) { + { /* It's smarter to initialize these weights to 1, so that later on, * we can't accidentally divide by zero. */ G = M = E = D = 1; T = 4; - } else { - /* ...but originally, they were set to zero. */ - G = M = E = D = T = 0; } /* Compute medians of time-related things, and figure out how many @@ -2246,7 +2244,7 @@ networkstatus_compute_consensus(smartlist_t *votes, /* Okay!! Now we can write the descriptor... */ /* First line goes into "buf". */ buf = routerstatus_format_entry(&rs_out, NULL, NULL, - rs_format, consensus_method, NULL); + rs_format, NULL); if (buf) smartlist_add(chunks, buf); } @@ -2266,8 +2264,7 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_add_strdup(chunks, chosen_version); } smartlist_add_strdup(chunks, "\n"); - if (chosen_protocol_list && - consensus_method >= MIN_METHOD_FOR_RS_PROTOCOLS) { + if (chosen_protocol_list) { smartlist_add_asprintf(chunks, "pr %s\n", chosen_protocol_list); } /* Now the weight line. */ @@ -2530,9 +2527,12 @@ compute_consensus_package_lines(smartlist_t *votes) * any new signatures in <b>src_voter_list</b> that should be added to * <b>target</b>. (A signature should be added if we have no signature for that * voter in <b>target</b> 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 <b>sigs</b> isn't the same - * document as <b>target</b>. */ + * new signature is verifiable.) + * + * Return the number of signatures added or changed, or -1 if the document + * signatures are invalid. Sets *<b>msg_out</b> to a string constant + * describing the signature status. + */ STATIC int networkstatus_add_detached_signatures(networkstatus_t *target, ns_detached_signatures_t *sigs, @@ -3567,6 +3567,14 @@ dirvote_add_signatures_to_pending_consensus( return r; } +/** Helper: we just got the <b>detached_signatures_body</b> sent to us as + * signatures on the currently pending consensus. Add them to the pending + * consensus (if we have one). + * + * Set *<b>msg</b> to a string constant describing the status, regardless of + * success or failure. + * + * Return negative on failure, nonnegative on success. */ static int dirvote_add_signatures_to_all_pending_consensuses( const char *detached_signatures_body, @@ -3629,7 +3637,12 @@ dirvote_add_signatures_to_all_pending_consensuses( /** Helper: we just got the <b>detached_signatures_body</b> 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. */ + * consensus. + * + * Set *<b>msg</b> to a string constant describing the status, regardless of + * success or failure. + * + * Return negative on failure, nonnegative on success. */ int dirvote_add_signatures(const char *detached_signatures_body, const char *source, @@ -3803,13 +3816,6 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method) smartlist_add_asprintf(chunks, "ntor-onion-key %s", kbuf); } - /* We originally put a lines in the micrdescriptors, but then we worked out - * that we needed them in the microdesc consensus. See #20916. */ - if (consensus_method < MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC && - !tor_addr_is_null(&ri->ipv6_addr) && ri->ipv6_orport) - smartlist_add_asprintf(chunks, "a %s\n", - fmt_addrport(&ri->ipv6_addr, ri->ipv6_orport)); - if (family) { if (consensus_method < MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS) { smartlist_add_asprintf(chunks, "family %s\n", family); @@ -3915,8 +3921,7 @@ static const struct consensus_method_range_t { int low; int high; } microdesc_consensus_methods[] = { - {MIN_SUPPORTED_CONSENSUS_METHOD, MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC - 1}, - {MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC, + {MIN_SUPPORTED_CONSENSUS_METHOD, MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS - 1}, {MIN_METHOD_FOR_CANONICAL_FAMILIES_IN_MICRODESCS, MAX_SUPPORTED_CONSENSUS_METHOD}, @@ -4228,7 +4233,7 @@ compare_routerinfo_by_ip_and_bw_(const void **a, const void **b) static digestmap_t * get_possible_sybil_list(const smartlist_t *routers) { - const or_options_t *options = get_options(); + const dirauth_options_t *options = dirauth_get_options(); digestmap_t *omit_as_sybil; smartlist_t *routers_by_ip = smartlist_new(); uint32_t last_addr; @@ -4417,6 +4422,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, authority_cert_t *cert) { const or_options_t *options = get_options(); + const dirauth_options_t *d_options = dirauth_get_options(); networkstatus_t *v3_out = NULL; uint32_t addr; char *hostname = NULL, *client_versions = NULL, *server_versions = NULL; @@ -4424,7 +4430,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, smartlist_t *routers, *routerstatuses; char identity_digest[DIGEST_LEN]; char signing_key_digest[DIGEST_LEN]; - int listbadexits = options->AuthDirListBadExits; + const int listbadexits = d_options->AuthDirListBadExits; routerlist_t *rl = router_get_routerlist(); time_t now = time(NULL); time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH; @@ -4456,11 +4462,11 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, hostname = tor_dup_ip(addr); } - if (options->VersioningAuthoritativeDir) { + if (d_options->VersioningAuthoritativeDirectory) { client_versions = - format_recommended_version_list(options->RecommendedClientVersions, 0); + format_recommended_version_list(d_options->RecommendedClientVersions, 0); server_versions = - format_recommended_version_list(options->RecommendedServerVersions, 0); + format_recommended_version_list(d_options->RecommendedServerVersions, 0); } contact = get_options()->ContactInfo; @@ -4661,10 +4667,10 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, smartlist_add_strdup(v3_out->known_flags, "BadExit"); smartlist_sort_strings(v3_out->known_flags); - if (options->ConsensusParams) { + if (d_options->ConsensusParams) { v3_out->net_params = smartlist_new(); smartlist_split_string(v3_out->net_params, - options->ConsensusParams, NULL, 0, 0); + d_options->ConsensusParams, NULL, 0, 0); smartlist_sort_strings(v3_out->net_params); } v3_out->bw_file_headers = bw_file_headers; diff --git a/src/feature/dirauth/dirvote.h b/src/feature/dirauth/dirvote.h index b7df33a3a9..675f4ee148 100644 --- a/src/feature/dirauth/dirvote.h +++ b/src/feature/dirauth/dirvote.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -49,36 +49,12 @@ #define MIN_VOTE_INTERVAL_TESTING_INITIAL \ ((MIN_VOTE_SECONDS_TESTING)+(MIN_DIST_SECONDS_TESTING)+1) -/* A placeholder for routerstatus_format_entry() when the consensus method - * argument is not applicable. */ -#define ROUTERSTATUS_FORMAT_NO_CONSENSUS_METHOD 0 - /** The lowest consensus method that we currently support. */ -#define MIN_SUPPORTED_CONSENSUS_METHOD 25 +#define MIN_SUPPORTED_CONSENSUS_METHOD 28 /** The highest consensus method that we currently support. */ #define MAX_SUPPORTED_CONSENSUS_METHOD 29 -/** Lowest consensus method where authorities vote on required/recommended - * protocols. */ -#define MIN_METHOD_FOR_RECOMMENDED_PROTOCOLS 25 - -/** Lowest consensus method where authorities add protocols to routerstatus - * entries. */ -#define MIN_METHOD_FOR_RS_PROTOCOLS 25 - -/** Lowest consensus method where authorities initialize bandwidth weights to 1 - * instead of 0. See #14881 */ -#define MIN_METHOD_FOR_INIT_BW_WEIGHTS_ONE 26 - -/** Lowest consensus method where the microdesc consensus contains relay IPv6 - * addresses. See #23826 and #20916. */ -#define MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS 27 - -/** Lowest consensus method where microdescriptors do not contain relay IPv6 - * addresses. See #23828 and #20916. */ -#define MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC 28 - /** * Lowest consensus method where microdescriptor lines are put in canonical * form for improved compressibility and ease of storage. See proposal 298. @@ -186,7 +162,7 @@ dirvote_add_signatures(const char *detached_signatures_body, { (void) detached_signatures_body; (void) source; - (void) msg_out; + *msg_out = "No directory authority support"; /* If the dirauth module is disabled, this should NEVER be called else we * failed to safeguard the dirauth module. */ tor_assert_nonfatal_unreached(); diff --git a/src/feature/dirauth/dsigs_parse.c b/src/feature/dirauth/dsigs_parse.c index c5c8e18866..d0bb931814 100644 --- a/src/feature/dirauth/dsigs_parse.c +++ b/src/feature/dirauth/dsigs_parse.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** diff --git a/src/feature/dirauth/dsigs_parse.h b/src/feature/dirauth/dsigs_parse.h index 0cc53072f8..b25e3e0b28 100644 --- a/src/feature/dirauth/dsigs_parse.h +++ b/src/feature/dirauth/dsigs_parse.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** diff --git a/src/feature/dirauth/feature_dirauth.md b/src/feature/dirauth/feature_dirauth.md new file mode 100644 index 0000000000..b152b94894 --- /dev/null +++ b/src/feature/dirauth/feature_dirauth.md @@ -0,0 +1,9 @@ +@dir /feature/dirauth +@brief feature/dirauth: Directory authority implementation. + +This module handles running Tor as a directory authority. + +The directory protocol is specified in +[dir-spec.txt](https://gitweb.torproject.org/torspec.git/tree/dir-spec.txt). + + diff --git a/src/feature/dirauth/guardfraction.c b/src/feature/dirauth/guardfraction.c index d1a7f194d4..40189ce494 100644 --- a/src/feature/dirauth/guardfraction.c +++ b/src/feature/dirauth/guardfraction.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** diff --git a/src/feature/dirauth/guardfraction.h b/src/feature/dirauth/guardfraction.h index 9f01ded838..c10fd9b7bb 100644 --- a/src/feature/dirauth/guardfraction.h +++ b/src/feature/dirauth/guardfraction.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -16,7 +16,7 @@ STATIC int dirserv_read_guardfraction_file_from_str(const char *guardfraction_file_str, smartlist_t *vote_routerstatuses); -#endif /* defined(DIRSERV_PRIVATE) */ +#endif int dirserv_read_guardfraction_file(const char *fname, smartlist_t *vote_routerstatuses); diff --git a/src/feature/dirauth/include.am b/src/feature/dirauth/include.am new file mode 100644 index 0000000000..2ef629ae35 --- /dev/null +++ b/src/feature/dirauth/include.am @@ -0,0 +1,52 @@ + +# The Directory Authority module. + +# ADD_C_FILE: INSERT SOURCES HERE. +MODULE_DIRAUTH_SOURCES = \ + src/feature/dirauth/authmode.c \ + src/feature/dirauth/bridgeauth.c \ + src/feature/dirauth/bwauth.c \ + src/feature/dirauth/dirauth_config.c \ + src/feature/dirauth/dirauth_periodic.c \ + src/feature/dirauth/dirauth_sys.c \ + src/feature/dirauth/dircollate.c \ + src/feature/dirauth/dirvote.c \ + src/feature/dirauth/dsigs_parse.c \ + src/feature/dirauth/guardfraction.c \ + src/feature/dirauth/keypin.c \ + src/feature/dirauth/process_descs.c \ + src/feature/dirauth/reachability.c \ + src/feature/dirauth/recommend_pkg.c \ + src/feature/dirauth/shared_random.c \ + src/feature/dirauth/shared_random_state.c \ + src/feature/dirauth/voteflags.c + +# ADD_C_FILE: INSERT HEADERS HERE. +noinst_HEADERS += \ + src/feature/dirauth/authmode.h \ + src/feature/dirauth/bridgeauth.h \ + src/feature/dirauth/bwauth.h \ + src/feature/dirauth/dirauth_config.h \ + src/feature/dirauth/dirauth_options.inc \ + src/feature/dirauth/dirauth_options_st.h \ + src/feature/dirauth/dirauth_periodic.h \ + src/feature/dirauth/dirauth_sys.h \ + src/feature/dirauth/dircollate.h \ + src/feature/dirauth/dirvote.h \ + src/feature/dirauth/dsigs_parse.h \ + src/feature/dirauth/guardfraction.h \ + src/feature/dirauth/keypin.h \ + src/feature/dirauth/ns_detached_signatures_st.h \ + src/feature/dirauth/reachability.h \ + src/feature/dirauth/recommend_pkg.h \ + src/feature/dirauth/process_descs.h \ + src/feature/dirauth/shared_random.h \ + src/feature/dirauth/shared_random_state.h \ + src/feature/dirauth/vote_microdesc_hash_st.h \ + src/feature/dirauth/voteflags.h + +if BUILD_MODULE_DIRAUTH +LIBTOR_APP_A_SOURCES += $(MODULE_DIRAUTH_SOURCES) +else +LIBTOR_APP_A_STUB_SOURCES += src/feature/dirauth/dirauth_stub.c +endif diff --git a/src/feature/dirauth/keypin.c b/src/feature/dirauth/keypin.c index 316b7d6c2f..edf5ba5833 100644 --- a/src/feature/dirauth/keypin.c +++ b/src/feature/dirauth/keypin.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2019, The Tor Project, Inc. */ +/* Copyright (c) 2014-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -15,8 +15,6 @@ #include "lib/cc/torint.h" #include "lib/crypt_ops/crypto_digest.h" #include "lib/crypt_ops/crypto_format.h" -#include "lib/crypt_ops/crypto_format.h" -#include "lib/ctime/di_ops.h" #include "lib/ctime/di_ops.h" #include "lib/encoding/binascii.h" #include "lib/encoding/time_fmt.h" diff --git a/src/feature/dirauth/keypin.h b/src/feature/dirauth/keypin.h index 1de84f6d4a..881f010f0e 100644 --- a/src/feature/dirauth/keypin.h +++ b/src/feature/dirauth/keypin.h @@ -1,6 +1,11 @@ -/* Copyright (c) 2014-2019, The Tor Project, Inc. */ +/* Copyright (c) 2014-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file keypin.h + * @brief Header for keypin.c + **/ + #ifndef TOR_KEYPIN_H #define TOR_KEYPIN_H @@ -40,6 +45,8 @@ int keypin_check_lone_rsa(const uint8_t *rsa_id_digest); #ifdef KEYPIN_PRIVATE +#include "ext/ht.h" + /** * In-memory representation of a key-pinning table entry. */ diff --git a/src/feature/dirauth/ns_detached_signatures_st.h b/src/feature/dirauth/ns_detached_signatures_st.h index 61d20b7525..f409431ec1 100644 --- a/src/feature/dirauth/ns_detached_signatures_st.h +++ b/src/feature/dirauth/ns_detached_signatures_st.h @@ -1,9 +1,14 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file ns_detached_signatures_st.h + * @brief Detached consensus signatures structure. + **/ + #ifndef NS_DETACHED_SIGNATURES_ST_H #define NS_DETACHED_SIGNATURES_ST_H @@ -19,4 +24,3 @@ struct ns_detached_signatures_t { }; #endif /* !defined(NS_DETACHED_SIGNATURES_ST_H) */ - diff --git a/src/feature/dirauth/process_descs.c b/src/feature/dirauth/process_descs.c index 71e3195c01..5025d0ae39 100644 --- a/src/feature/dirauth/process_descs.c +++ b/src/feature/dirauth/process_descs.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -12,17 +12,21 @@ * them make those decisions. **/ +#define PROCESS_DESCS_PRIVATE + #include "core/or/or.h" #include "feature/dirauth/process_descs.h" #include "app/config/config.h" #include "core/or/policies.h" #include "core/or/versions.h" +#include "feature/dirauth/dirauth_sys.h" #include "feature/dirauth/keypin.h" #include "feature/dirauth/reachability.h" #include "feature/dirclient/dlstatus.h" #include "feature/dircommon/directory.h" #include "feature/nodelist/describe.h" +#include "feature/nodelist/microdesc.h" #include "feature/nodelist/networkstatus.h" #include "feature/nodelist/nodelist.h" #include "feature/nodelist/routerinfo.h" @@ -32,46 +36,28 @@ #include "feature/relay/router.h" #include "core/or/tor_version_st.h" +#include "feature/dirauth/dirauth_options_st.h" #include "feature/nodelist/extrainfo_st.h" #include "feature/nodelist/node_st.h" +#include "feature/nodelist/microdesc_st.h" #include "feature/nodelist/routerinfo_st.h" #include "feature/nodelist/routerstatus_st.h" +#include "feature/nodelist/vote_routerstatus_st.h" #include "lib/encoding/confline.h" +#include "lib/crypt_ops/crypto_format.h" /** How far in the future do we allow a router to get? (seconds) */ #define ROUTER_ALLOW_SKEW (60*60*12) static void directory_remove_invalid(void); -struct authdir_config_t; static was_router_added_t dirserv_add_extrainfo(extrainfo_t *ei, const char **msg); static uint32_t -dirserv_get_status_impl(const char *fp, const char *nickname, - uint32_t addr, uint16_t or_port, - const char *platform, const char **msg, - int severity); - -/* 1 Historically used to indicate Named */ -#define FP_INVALID 2 /**< Believed invalid. */ -#define FP_REJECT 4 /**< We will not publish this router. */ -/* 8 Historically used to avoid using this as a dir. */ -#define FP_BADEXIT 16 /**< We'll tell clients not to use this as an exit. */ -/* 32 Historically used to indicade Unnamed */ - -/** Target of status_by_digest map. */ -typedef uint32_t router_status_t; - -static void add_fingerprint_to_dir(const char *fp, - struct authdir_config_t *list, - router_status_t add_status); - -/** List of nickname-\>identity fingerprint mappings for all the routers - * that we name. Used to prevent router impersonation. */ -typedef struct authdir_config_t { - strmap_t *fp_by_name; /**< Map from lc nickname to fingerprint. */ - digestmap_t *status_by_digest; /**< Map from digest to router_status_t. */ -} authdir_config_t; +dirserv_get_status_impl(const char *id_digest, + const ed25519_public_key_t *ed25519_public_key, + const char *nickname, uint32_t addr, uint16_t or_port, + const char *platform, const char **msg, int severity); /** Should be static; exposed for testing. */ static authdir_config_t *fingerprint_list = NULL; @@ -83,20 +69,39 @@ authdir_config_new(void) authdir_config_t *list = tor_malloc_zero(sizeof(authdir_config_t)); list->fp_by_name = strmap_new(); list->status_by_digest = digestmap_new(); + list->status_by_digest256 = digest256map_new(); return list; } +#ifdef TOR_UNIT_TESTS + +/** Initialize fingerprint_list to a new authdir_config_t. Used for tests. */ +void +authdir_init_fingerprint_list(void) +{ + fingerprint_list = authdir_config_new(); +} + +/* Return the current fingerprint_list. Used for tests. */ +authdir_config_t * +authdir_return_fingerprint_list(void) +{ + return fingerprint_list; +} + +#endif /* defined(TOR_UNIT_TESTS) */ + /** Add the fingerprint <b>fp</b> to the smartlist of fingerprint_entry_t's * <b>list</b>, or-ing the currently set status flags with * <b>add_status</b>. */ -/* static */ void -add_fingerprint_to_dir(const char *fp, authdir_config_t *list, - router_status_t add_status) +int +add_rsa_fingerprint_to_dir(const char *fp, authdir_config_t *list, + rtr_flags_t add_status) { char *fingerprint; char d[DIGEST_LEN]; - router_status_t *status; + rtr_flags_t *status; tor_assert(fp); tor_assert(list); @@ -107,24 +112,52 @@ add_fingerprint_to_dir(const char *fp, authdir_config_t *list, log_warn(LD_DIRSERV, "Couldn't decode fingerprint \"%s\"", escaped(fp)); tor_free(fingerprint); - return; + return -1; } status = digestmap_get(list->status_by_digest, d); if (!status) { - status = tor_malloc_zero(sizeof(router_status_t)); + status = tor_malloc_zero(sizeof(rtr_flags_t)); digestmap_set(list->status_by_digest, d, status); } tor_free(fingerprint); *status |= add_status; - return; + return 0; +} + +/** Add the ed25519 key <b>edkey</b> to the smartlist of fingerprint_entry_t's + * <b>list</b>, or-ing the currently set status flags with <b>add_status</b>. + * Return -1 if we were unable to decode the key, else return 0. + */ +int +add_ed25519_to_dir(const ed25519_public_key_t *edkey, authdir_config_t *list, + rtr_flags_t add_status) +{ + rtr_flags_t *status; + + tor_assert(edkey); + tor_assert(list); + + if (ed25519_validate_pubkey(edkey) < 0) { + log_warn(LD_DIRSERV, "Invalid ed25519 key \"%s\"", ed25519_fmt(edkey)); + return -1; + } + + status = digest256map_get(list->status_by_digest256, edkey->pubkey); + if (!status) { + status = tor_malloc_zero(sizeof(rtr_flags_t)); + digest256map_set(list->status_by_digest256, edkey->pubkey, status); + } + + *status |= add_status; + return 0; } /** Add the fingerprint for this OR to the global list of recognized * identity key fingerprints. */ int -dirserv_add_own_fingerprint(crypto_pk_t *pk) +dirserv_add_own_fingerprint(crypto_pk_t *pk, const ed25519_public_key_t *edkey) { char fp[FINGERPRINT_LEN+1]; if (crypto_pk_get_fingerprint(pk, fp, 0)<0) { @@ -133,7 +166,14 @@ dirserv_add_own_fingerprint(crypto_pk_t *pk) } if (!fingerprint_list) fingerprint_list = authdir_config_new(); - add_fingerprint_to_dir(fp, fingerprint_list, 0); + if (add_rsa_fingerprint_to_dir(fp, fingerprint_list, 0) < 0) { + log_err(LD_BUG, "Error adding RSA fingerprint"); + return -1; + } + if (add_ed25519_to_dir(edkey, fingerprint_list, 0) < 0) { + log_err(LD_BUG, "Error adding ed25519 key"); + return -1; + } return 0; } @@ -174,27 +214,46 @@ dirserv_load_fingerprint_file(void) fingerprint_list_new = authdir_config_new(); for (list=front; list; list=list->next) { - char digest_tmp[DIGEST_LEN]; - router_status_t add_status = 0; + rtr_flags_t add_status = 0; nickname = list->key; fingerprint = list->value; tor_strstrip(fingerprint, " "); /* remove spaces */ - if (strlen(fingerprint) != HEX_DIGEST_LEN || - base16_decode(digest_tmp, sizeof(digest_tmp), - fingerprint, HEX_DIGEST_LEN) != sizeof(digest_tmp)) { - log_notice(LD_CONFIG, - "Invalid fingerprint (nickname '%s', " - "fingerprint %s). Skipping.", - nickname, fingerprint); - continue; - } + + /* Determine what we should do with the relay with the nickname field. */ if (!strcasecmp(nickname, "!reject")) { - add_status = FP_REJECT; + add_status = RTR_REJECT; } else if (!strcasecmp(nickname, "!badexit")) { - add_status = FP_BADEXIT; + add_status = RTR_BADEXIT; } else if (!strcasecmp(nickname, "!invalid")) { - add_status = FP_INVALID; + add_status = RTR_INVALID; + } + + /* Check if fingerprint is RSA or ed25519 by verifying it. */ + int ed25519_not_ok = -1, rsa_not_ok = -1; + + /* Attempt to add the RSA key. */ + if (strlen(fingerprint) == HEX_DIGEST_LEN) { + rsa_not_ok = add_rsa_fingerprint_to_dir(fingerprint, + fingerprint_list_new, + add_status); + } + + /* Check ed25519 key. We check the size to prevent buffer overflows. + * If valid, attempt to add it, */ + ed25519_public_key_t ed25519_pubkey_tmp; + if (strlen(fingerprint) == BASE64_DIGEST256_LEN) { + if (!digest256_from_base64((char *) ed25519_pubkey_tmp.pubkey, + fingerprint)) { + ed25519_not_ok = add_ed25519_to_dir(&ed25519_pubkey_tmp, + fingerprint_list_new, add_status); + } + } + + /* If both keys are invalid (or missing), log and skip. */ + if (ed25519_not_ok && rsa_not_ok) { + log_warn(LD_CONFIG, "Invalid fingerprint (nickname '%s', " + "fingerprint %s). Skipping.", nickname, fingerprint); + continue; } - add_fingerprint_to_dir(fingerprint, fingerprint_list_new, add_status); } config_free_lines(front); @@ -225,26 +284,33 @@ dirserv_load_fingerprint_file(void) * * Return the appropriate router status. * - * If the status is 'FP_REJECT' and <b>msg</b> is provided, set - * *<b>msg</b> to an explanation of why. */ + * If the status is 'RTR_REJECT' and <b>msg</b> is provided, set + * *<b>msg</b> to a string constant explaining why. */ uint32_t dirserv_router_get_status(const routerinfo_t *router, const char **msg, int severity) { char d[DIGEST_LEN]; - const int key_pinning = get_options()->AuthDirPinKeys; + const int key_pinning = dirauth_get_options()->AuthDirPinKeys; + uint32_t r; + ed25519_public_key_t *signing_key = NULL; if (crypto_pk_get_digest(router->identity_pkey, d)) { log_warn(LD_BUG,"Error computing fingerprint"); if (msg) *msg = "Bug: Error computing fingerprint"; - return FP_REJECT; + return RTR_REJECT; } - /* Check for the more common reasons to reject a router first. */ - const uint32_t r = dirserv_get_status_impl(d, router->nickname, - router->addr, router->or_port, - router->platform, msg, severity); + /* First, check for the more common reasons to reject a router. */ + if (router->cache_info.signing_key_cert) { + /* This has an ed25519 identity key. */ + signing_key = &router->cache_info.signing_key_cert->signing_key; + } + r = dirserv_get_status_impl(d, signing_key, router->nickname, router->addr, + router->or_port, router->platform, msg, + severity); + if (r) return r; @@ -259,7 +325,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg, "key.", router_describe(router)); if (msg) *msg = "Missing ntor curve25519 onion key. Please upgrade!"; - return FP_REJECT; + return RTR_REJECT; } if (router->cache_info.signing_key_cert) { @@ -275,7 +341,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg, if (msg) { *msg = "Ed25519 identity key or RSA identity key has changed."; } - return FP_REJECT; + return RTR_REJECT; } } } else { @@ -292,7 +358,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg, if (msg) { *msg = "Ed25519 identity key has disappeared."; } - return FP_REJECT; + return RTR_REJECT; } #endif /* defined(DISABLE_DISABLING_ED25519) */ } @@ -304,15 +370,17 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg, /** Return true if there is no point in downloading the router described by * <b>rs</b> because this directory would reject it. */ int -dirserv_would_reject_router(const routerstatus_t *rs) +dirserv_would_reject_router(const routerstatus_t *rs, + const vote_routerstatus_t *vrs) { uint32_t res; + struct ed25519_public_key_t pk; + memcpy(&pk.pubkey, vrs->ed25519_id, ED25519_PUBKEY_LEN); - res = dirserv_get_status_impl(rs->identity_digest, rs->nickname, - rs->addr, rs->or_port, - NULL, NULL, LOG_DEBUG); + res = dirserv_get_status_impl(rs->identity_digest, &pk, rs->nickname, + rs->addr, rs->or_port, NULL, NULL, LOG_DEBUG); - return (res & FP_REJECT) != 0; + return (res & RTR_REJECT) != 0; } /** @@ -331,22 +399,21 @@ dirserv_rejects_tor_version(const char *platform, static const char please_upgrade_string[] = "Tor version is insecure or unsupported. Please upgrade!"; - /* Versions before Tor 0.2.9 are unsupported. Versions between 0.2.9.0 and - * 0.2.9.4 suffer from bug #20499, where relays don't keep their consensus - * up to date */ - if (!tor_version_as_new_as(platform,"0.2.9.5-alpha")) { + /* Versions before Tor 0.3.5 are unsupported. + * + * Also, reject unstable versions of 0.3.5, since (as of this writing) + * they are almost none of the network. */ + if (!tor_version_as_new_as(platform,"0.3.5.7")) { if (msg) *msg = please_upgrade_string; return true; } - /* Series between Tor 0.3.0 and 0.3.4 inclusive are unsupported, and some - * have bug #27841, which makes them broken as intro points. Reject them. - * - * Also reject unstable versions of 0.3.5, since (as of this writing) - * they are almost none of the network. */ - if (tor_version_as_new_as(platform,"0.3.0.0-alpha-dev") && - !tor_version_as_new_as(platform,"0.3.5.7")) { + /* Series between Tor 0.3.6 and 0.4.1.4-rc inclusive are unsupported. + * Reject them. 0.3.6.0-alpha-dev only existed for a short time, before + * it was renamed to 0.4.0.0-alpha-dev. */ + if (tor_version_as_new_as(platform,"0.3.6.0-alpha-dev") && + !tor_version_as_new_as(platform,"0.4.1.5")) { if (msg) { *msg = please_upgrade_string; } @@ -357,19 +424,20 @@ dirserv_rejects_tor_version(const char *platform, } /** Helper: As dirserv_router_get_status, but takes the router fingerprint - * (hex, no spaces), nickname, address (used for logging only), IP address, OR - * port and platform (logging only) as arguments. + * (hex, no spaces), ed25519 key, nickname, address (used for logging only), + * IP address, OR port and platform (logging only) as arguments. * * Log messages at 'severity'. (There's not much point in * logging that we're rejecting servers we'll not download.) */ static uint32_t -dirserv_get_status_impl(const char *id_digest, const char *nickname, - uint32_t addr, uint16_t or_port, +dirserv_get_status_impl(const char *id_digest, + const ed25519_public_key_t *ed25519_public_key, + const char *nickname, uint32_t addr, uint16_t or_port, const char *platform, const char **msg, int severity) { uint32_t result = 0; - router_status_t *status_by_digest; + rtr_flags_t *status_by_digest; if (!fingerprint_list) fingerprint_list = authdir_config_new(); @@ -384,13 +452,13 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname, if (msg) { *msg = "Malformed platform string."; } - return FP_REJECT; + return RTR_REJECT; } } /* Check whether the version is obsolete, broken, insecure, etc... */ if (platform && dirserv_rejects_tor_version(platform, msg)) { - return FP_REJECT; + return RTR_REJECT; } status_by_digest = digestmap_get(fingerprint_list->status_by_digest, @@ -398,23 +466,30 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname, if (status_by_digest) result |= *status_by_digest; - if (result & FP_REJECT) { + if (ed25519_public_key) { + status_by_digest = digest256map_get(fingerprint_list->status_by_digest256, + ed25519_public_key->pubkey); + if (status_by_digest) + result |= *status_by_digest; + } + + if (result & RTR_REJECT) { if (msg) - *msg = "Fingerprint is marked rejected -- if you think this is a " - "mistake please set a valid email address in ContactInfo and " - "send an email to bad-relays@lists.torproject.org mentioning " - "your fingerprint(s)?"; - return FP_REJECT; - } else if (result & FP_INVALID) { + *msg = "Fingerprint and/or ed25519 identity is marked rejected -- if " + "you think this is a mistake please set a valid email address " + "in ContactInfo and send an email to " + "bad-relays@lists.torproject.org mentioning your fingerprint(s)?"; + return RTR_REJECT; + } else if (result & RTR_INVALID) { if (msg) - *msg = "Fingerprint is marked invalid"; + *msg = "Fingerprint and/or ed25519 identity is marked invalid"; } if (authdir_policy_badexit_address(addr, or_port)) { log_fn(severity, LD_DIRSERV, "Marking '%s' as bad exit because of address '%s'", nickname, fmt_addr32(addr)); - result |= FP_BADEXIT; + result |= RTR_BADEXIT; } if (!authdir_policy_permits_address(addr, or_port)) { @@ -425,13 +500,13 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname, "mistake please set a valid email address in ContactInfo and " "send an email to bad-relays@lists.torproject.org mentioning " "your address(es) and fingerprint(s)?"; - return FP_REJECT; + return RTR_REJECT; } if (!authdir_policy_valid_address(addr, or_port)) { log_fn(severity, LD_DIRSERV, "Not marking '%s' valid because of address '%s'", nickname, fmt_addr32(addr)); - result |= FP_INVALID; + result |= RTR_INVALID; } return result; @@ -446,6 +521,7 @@ dirserv_free_fingerprint_list(void) strmap_free(fingerprint_list->fp_by_name, tor_free_); digestmap_free(fingerprint_list->status_by_digest, tor_free_); + digest256map_free(fingerprint_list->status_by_digest256, tor_free_); tor_free(fingerprint_list); } @@ -487,7 +563,8 @@ dirserv_router_has_valid_address(routerinfo_t *ri) /** Check whether we, as a directory server, want to accept <b>ri</b>. If so, * set its is_valid,running fields and return 0. Otherwise, return -1. * - * If the router is rejected, set *<b>msg</b> to an explanation of why. + * If the router is rejected, set *<b>msg</b> to a string constant explining + * why. * * If <b>complain</b> then explain at log-level 'notice' why we refused * a descriptor; else explain at log-level 'info'. @@ -501,7 +578,7 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, int severity = (complain && ri->contact_info) ? LOG_NOTICE : LOG_INFO; uint32_t status = dirserv_router_get_status(ri, msg, severity); tor_assert(msg); - if (status & FP_REJECT) + if (status & RTR_REJECT) return -1; /* msg is already set. */ /* Is there too much clock skew? */ @@ -537,7 +614,7 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, return -1; } - *valid_out = ! (status & FP_INVALID); + *valid_out = ! (status & RTR_INVALID); return 0; } @@ -549,8 +626,8 @@ void dirserv_set_node_flags_from_authoritative_status(node_t *node, uint32_t authstatus) { - node->is_valid = (authstatus & FP_INVALID) ? 0 : 1; - node->is_bad_exit = (authstatus & FP_BADEXIT) ? 1 : 0; + node->is_valid = (authstatus & RTR_INVALID) ? 0 : 1; + node->is_bad_exit = (authstatus & RTR_BADEXIT) ? 1 : 0; } /** True iff <b>a</b> is more severe than <b>b</b>. */ @@ -653,7 +730,8 @@ dirserv_add_multiple_descriptors(const char *desc, size_t desclen, * That means the caller must not access <b>ri</b> after this function * returns, since it might have been freed. * - * Return the status of the operation. + * Return the status of the operation, and set *<b>msg</b> to a string + * constant describing the status. * * This function is only called when fresh descriptors are posted, not when * we re-load the cache. @@ -666,7 +744,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source) char *desc, *nickname; const size_t desclen = ri->cache_info.signed_descriptor_len + ri->cache_info.annotations_len; - const int key_pinning = get_options()->AuthDirPinKeys; + const int key_pinning = dirauth_get_options()->AuthDirPinKeys; *msg = NULL; /* If it's too big, refuse it now. Otherwise we'll cache it all over the @@ -864,21 +942,21 @@ directory_remove_invalid(void) continue; r = dirserv_router_get_status(ent, &msg, LOG_INFO); description = router_describe(ent); - if (r & FP_REJECT) { + if (r & RTR_REJECT) { log_info(LD_DIRSERV, "Router %s is now rejected: %s", description, msg?msg:""); routerlist_remove(rl, ent, 0, time(NULL)); continue; } - if (bool_neq((r & FP_INVALID), !node->is_valid)) { + if (bool_neq((r & RTR_INVALID), !node->is_valid)) { log_info(LD_DIRSERV, "Router '%s' is now %svalid.", description, - (r&FP_INVALID) ? "in" : ""); - node->is_valid = (r&FP_INVALID)?0:1; + (r&RTR_INVALID) ? "in" : ""); + node->is_valid = (r&RTR_INVALID)?0:1; } - if (bool_neq((r & FP_BADEXIT), node->is_bad_exit)) { + if (bool_neq((r & RTR_BADEXIT), node->is_bad_exit)) { log_info(LD_DIRSERV, "Router '%s' is now a %s exit", description, - (r & FP_BADEXIT) ? "bad" : "good"); - node->is_bad_exit = (r&FP_BADEXIT) ? 1: 0; + (r & RTR_BADEXIT) ? "bad" : "good"); + node->is_bad_exit = (r&RTR_BADEXIT) ? 1: 0; } } SMARTLIST_FOREACH_END(node); diff --git a/src/feature/dirauth/process_descs.h b/src/feature/dirauth/process_descs.h index e504daa7b7..1461ab697d 100644 --- a/src/feature/dirauth/process_descs.h +++ b/src/feature/dirauth/process_descs.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -15,6 +15,48 @@ // for was_router_added_t. #include "feature/nodelist/routerlist.h" +#include "lib/crypt_ops/crypto_ed25519.h" + +struct authdir_config_t; + +/** Target of status_by_digest map. */ +typedef uint32_t rtr_flags_t; + +int add_rsa_fingerprint_to_dir(const char *fp, struct authdir_config_t *list, + rtr_flags_t add_status); + +int add_ed25519_to_dir(const ed25519_public_key_t *edkey, + struct authdir_config_t *list, + rtr_flags_t add_status); + +/** List of nickname-\>identity fingerprint mappings for all the routers + * that we name. Used to prevent router impersonation. */ +typedef struct authdir_config_t { + strmap_t *fp_by_name; /**< Map from lc nickname to fingerprint. */ + digestmap_t *status_by_digest; /**< Map from digest to router_status_t. */ + digest256map_t *status_by_digest256; /**< Map from digest256 to + * router_status_t. */ +} authdir_config_t; + +#if defined(PROCESS_DESCS_PRIVATE) || defined(TOR_UNIT_TESTS) + +/* 1 Historically used to indicate Named */ +#define RTR_INVALID 2 /**< Believed invalid. */ +#define RTR_REJECT 4 /**< We will not publish this router. */ +/* 8 Historically used to avoid using this as a dir. */ +#define RTR_BADEXIT 16 /**< We'll tell clients not to use this as an exit. */ +/* 32 Historically used to indicade Unnamed */ + +#endif /* defined(PROCESS_DESCS_PRIVATE) || defined(TOR_UNIT_TESTS) */ + +#ifdef TOR_UNIT_TESTS + +void authdir_init_fingerprint_list(void); + +authdir_config_t *authdir_return_fingerprint_list(void); + +#endif /* defined(TOR_UNIT_TESTS) */ + void dirserv_free_fingerprint_list(void); #ifdef HAVE_MODULE_DIRAUTH @@ -28,11 +70,13 @@ enum was_router_added_t dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source); -int dirserv_would_reject_router(const routerstatus_t *rs); +int dirserv_would_reject_router(const routerstatus_t *rs, + const vote_routerstatus_t *vrs); int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, int complain, int *valid_out); -int dirserv_add_own_fingerprint(crypto_pk_t *pk); +int dirserv_add_own_fingerprint(crypto_pk_t *pk, + const ed25519_public_key_t *edkey); uint32_t dirserv_router_get_status(const routerinfo_t *router, const char **msg, int severity); @@ -54,7 +98,7 @@ dirserv_add_multiple_descriptors(const char *desc, size_t desclen, (void)desclen; (void)purpose; (void)source; - (void)msg; + *msg = "No directory authority support"; return (enum was_router_added_t)0; } static inline enum was_router_added_t @@ -63,14 +107,16 @@ dirserv_add_descriptor(routerinfo_t *ri, const char *source) { (void)ri; - (void)msg; (void)source; + *msg = "No directory authority support"; return (enum was_router_added_t)0; } static inline int -dirserv_would_reject_router(const routerstatus_t *rs) +dirserv_would_reject_router(const routerstatus_t *rs, + const vote_routerstatus_t *vrs) { (void)rs; + (void)vrs; return 0; } static inline int @@ -79,15 +125,16 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, int *valid_out) { (void)ri; - (void)msg; (void)complain; - (void)valid_out; + *msg = "No directory authority support"; + *valid_out = 0; return 0; } static inline int -dirserv_add_own_fingerprint(crypto_pk_t *pk) +dirserv_add_own_fingerprint(crypto_pk_t *pk, const ed25519_public_key_t *edkey) { (void)pk; + (void)edkey; return 0; } static inline uint32_t @@ -96,8 +143,9 @@ dirserv_router_get_status(const routerinfo_t *router, int severity) { (void)router; - (void)msg; (void)severity; + if (msg) + *msg = "No directory authority support"; return 0; } static inline void diff --git a/src/feature/dirauth/reachability.c b/src/feature/dirauth/reachability.c index 883b692cbb..65fa27ed80 100644 --- a/src/feature/dirauth/reachability.c +++ b/src/feature/dirauth/reachability.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -17,6 +17,7 @@ #include "core/or/channeltls.h" #include "core/or/command.h" #include "feature/dirauth/authmode.h" +#include "feature/dirauth/dirauth_sys.h" #include "feature/nodelist/describe.h" #include "feature/nodelist/nodelist.h" #include "feature/nodelist/routerinfo.h" @@ -24,6 +25,7 @@ #include "feature/nodelist/torcert.h" #include "feature/stats/rephist.h" +#include "feature/dirauth/dirauth_options_st.h" #include "feature/nodelist/node_st.h" #include "feature/nodelist/routerinfo_st.h" #include "feature/nodelist/routerlist_st.h" @@ -53,7 +55,7 @@ dirserv_orconn_tls_done(const tor_addr_t *addr, ri = node->ri; - if (get_options()->AuthDirTestEd25519LinkKeys && + if (dirauth_get_options()->AuthDirTestEd25519LinkKeys && node_supports_ed25519_link_authentication(node, 1) && ri->cache_info.signing_key_cert) { /* We allow the node to have an ed25519 key if we haven't been told one in @@ -125,7 +127,7 @@ dirserv_should_launch_reachability_test(const routerinfo_t *ri, void dirserv_single_reachability_test(time_t now, routerinfo_t *router) { - const or_options_t *options = get_options(); + const dirauth_options_t *dirauth_options = dirauth_get_options(); channel_t *chan = NULL; const node_t *node = NULL; tor_addr_t router_addr; @@ -136,7 +138,7 @@ dirserv_single_reachability_test(time_t now, routerinfo_t *router) node = node_get_by_id(router->cache_info.identity_digest); tor_assert(node); - if (options->AuthDirTestEd25519LinkKeys && + if (dirauth_options->AuthDirTestEd25519LinkKeys && node_supports_ed25519_link_authentication(node, 1) && router->cache_info.signing_key_cert) { ed_id_key = &router->cache_info.signing_key_cert->signing_key; @@ -154,7 +156,7 @@ dirserv_single_reachability_test(time_t now, routerinfo_t *router) if (chan) command_setup_channel(chan); /* Possible IPv6. */ - if (get_options()->AuthDirHasIPv6Connectivity == 1 && + if (dirauth_get_options()->AuthDirHasIPv6Connectivity == 1 && !tor_addr_is_null(&router->ipv6_addr)) { char addrstr[TOR_ADDR_BUF_LEN]; log_debug(LD_OR, "Testing reachability of %s at %s:%u.", diff --git a/src/feature/dirauth/reachability.h b/src/feature/dirauth/reachability.h index 46d0e7ee2e..19448a67f3 100644 --- a/src/feature/dirauth/reachability.h +++ b/src/feature/dirauth/reachability.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -24,10 +24,10 @@ #define REACHABILITY_TEST_CYCLE_PERIOD \ (REACHABILITY_TEST_INTERVAL*REACHABILITY_MODULO_PER_TEST) +#ifdef HAVE_MODULE_DIRAUTH void dirserv_single_reachability_test(time_t now, routerinfo_t *router); void dirserv_test_reachability(time_t now); -#ifdef HAVE_MODULE_DIRAUTH int dirserv_should_launch_reachability_test(const routerinfo_t *ri, const routerinfo_t *ri_old); void dirserv_orconn_tls_done(const tor_addr_t *addr, @@ -35,25 +35,16 @@ void dirserv_orconn_tls_done(const tor_addr_t *addr, const char *digest_rcvd, const struct ed25519_public_key_t *ed_id_rcvd); #else /* !defined(HAVE_MODULE_DIRAUTH) */ -static inline int -dirserv_should_launch_reachability_test(const routerinfo_t *ri, - const routerinfo_t *ri_old) -{ - (void)ri; - (void)ri_old; - return 0; -} -static inline void -dirserv_orconn_tls_done(const tor_addr_t *addr, - uint16_t or_port, - const char *digest_rcvd, - const struct ed25519_public_key_t *ed_id_rcvd) -{ - (void)addr; - (void)or_port; - (void)digest_rcvd; - (void)ed_id_rcvd; -} +#define dirserv_single_reachability_test(now, router) \ + (((void)(now)),((void)(router))) +#define dirserv_test_reachability(now) \ + (((void)(now))) + +#define dirserv_should_launch_reachability_test(ri, ri_old) \ + (((void)(ri)),((void)(ri_old)),0) +#define dirserv_orconn_tls_done(addr, or_port, digest_rcvd, ed_id_rcvd) \ + (((void)(addr)),((void)(or_port)),((void)(digest_rcvd)), \ + ((void)(ed_id_rcvd))) #endif /* defined(HAVE_MODULE_DIRAUTH) */ #endif /* !defined(TOR_REACHABILITY_H) */ diff --git a/src/feature/dirauth/recommend_pkg.c b/src/feature/dirauth/recommend_pkg.c index 0456ff8463..84254566c6 100644 --- a/src/feature/dirauth/recommend_pkg.c +++ b/src/feature/dirauth/recommend_pkg.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** diff --git a/src/feature/dirauth/recommend_pkg.h b/src/feature/dirauth/recommend_pkg.h index af17e945e8..dcd9f8be8a 100644 --- a/src/feature/dirauth/recommend_pkg.h +++ b/src/feature/dirauth/recommend_pkg.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** diff --git a/src/feature/dirauth/shared_random.c b/src/feature/dirauth/shared_random.c index a45f0a29c3..48e2147ea6 100644 --- a/src/feature/dirauth/shared_random.c +++ b/src/feature/dirauth/shared_random.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2019, The Tor Project, Inc. */ +/* Copyright (c) 2016-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -90,7 +90,7 @@ #include "core/or/or.h" #include "feature/dirauth/shared_random.h" #include "app/config/config.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "lib/crypt_ops/crypto_rand.h" #include "lib/crypt_ops/crypto_util.h" #include "feature/nodelist/networkstatus.h" @@ -103,23 +103,25 @@ #include "feature/dirauth/dirvote.h" #include "feature/dirauth/authmode.h" +#include "feature/dirauth/dirauth_sys.h" +#include "feature/dirauth/dirauth_options_st.h" #include "feature/nodelist/authority_cert_st.h" #include "feature/nodelist/networkstatus_st.h" -/* String prefix of shared random values in votes/consensuses. */ +/** String prefix of shared random values in votes/consensuses. */ static const char previous_srv_str[] = "shared-rand-previous-value"; static const char current_srv_str[] = "shared-rand-current-value"; static const char commit_ns_str[] = "shared-rand-commit"; static const char sr_flag_ns_str[] = "shared-rand-participate"; -/* The value of the consensus param AuthDirNumSRVAgreements found in the +/** The value of the consensus param AuthDirNumSRVAgreements found in the * vote. This is set once the consensus creation subsystem requests the * SRV(s) that should be put in the consensus. We use this value to decide * if we keep or not an SRV. */ static int32_t num_srv_agreements_from_vote; -/* Return a heap allocated copy of the SRV <b>orig</b>. */ +/** Return a heap allocated copy of the SRV <b>orig</b>. */ sr_srv_t * sr_srv_dup(const sr_srv_t *orig) { @@ -135,7 +137,7 @@ sr_srv_dup(const sr_srv_t *orig) return duplicate; } -/* Allocate a new commit object and initializing it with <b>rsa_identity</b> +/** Allocate a new commit object and initializing it with <b>rsa_identity</b> * that MUST be provided. The digest algorithm is set to the default one * that is supported. The rest is uninitialized. This never returns NULL. */ static sr_commit_t * @@ -153,7 +155,7 @@ commit_new(const char *rsa_identity) return commit; } -/* Issue a log message describing <b>commit</b>. */ +/** Issue a log message describing <b>commit</b>. */ static void commit_log(const sr_commit_t *commit) { @@ -166,7 +168,7 @@ commit_log(const sr_commit_t *commit) commit->reveal_ts, safe_str(commit->encoded_reveal)); } -/* Make sure that the commitment and reveal information in <b>commit</b> +/** Make sure that the commitment and reveal information in <b>commit</b> * match. If they match return 0, return -1 otherwise. This function MUST be * used everytime we receive a new reveal value. Furthermore, the commit * object MUST have a reveal value and the hash of the reveal value. */ @@ -220,7 +222,7 @@ verify_commit_and_reveal(const sr_commit_t *commit) return -1; } -/* Return true iff the commit contains an encoded reveal value. */ +/** Return true iff the commit contains an encoded reveal value. */ STATIC int commit_has_reveal_value(const sr_commit_t *commit) { @@ -228,7 +230,7 @@ commit_has_reveal_value(const sr_commit_t *commit) sizeof(commit->encoded_reveal)); } -/* Parse the encoded commit. The format is: +/** Parse the encoded commit. The format is: * base64-encode( TIMESTAMP || H(REVEAL) ) * * If successfully decoded and parsed, commit is updated and 0 is returned. @@ -283,7 +285,7 @@ commit_decode(const char *encoded, sr_commit_t *commit) return -1; } -/* Parse the b64 blob at <b>encoded</b> containing reveal information and +/** Parse the b64 blob at <b>encoded</b> containing reveal information and * store the information in-place in <b>commit</b>. Return 0 on success else * a negative value. */ STATIC int @@ -333,7 +335,7 @@ reveal_decode(const char *encoded, sr_commit_t *commit) return -1; } -/* Encode a reveal element using a given commit object to dst which is a +/** Encode a reveal element using a given commit object to dst which is a * buffer large enough to put the base64-encoded reveal construction. The * format is as follow: * REVEAL = base64-encode( TIMESTAMP || H(RN) ) @@ -362,7 +364,7 @@ reveal_encode(const sr_commit_t *commit, char *dst, size_t len) return ret; } -/* Encode the given commit object to dst which is a buffer large enough to +/** Encode the given commit object to dst which is a buffer large enough to * put the base64-encoded commit. The format is as follow: * COMMIT = base64-encode( TIMESTAMP || H(H(RN)) ) * Return base64 encoded length on success else a negative value. @@ -388,14 +390,14 @@ commit_encode(const sr_commit_t *commit, char *dst, size_t len) return base64_encode(dst, len, buf, sizeof(buf), 0); } -/* Cleanup both our global state and disk state. */ +/** Cleanup both our global state and disk state. */ static void sr_cleanup(void) { sr_state_free_all(); } -/* Using <b>commit</b>, return a newly allocated string containing the commit +/** Using <b>commit</b>, return a newly allocated string containing the commit * information that should be used during SRV calculation. It's the caller * responsibility to free the memory. Return NULL if this is not a commit to be * used for SRV calculation. */ @@ -414,7 +416,7 @@ get_srv_element_from_commit(const sr_commit_t *commit) return element; } -/* Return a srv object that is built with the construction: +/** Return a srv object that is built with the construction: * SRV = SHA3-256("shared-random" | INT_8(reveal_num) | * INT_4(version) | HASHED_REVEALS | previous_SRV) * This function cannot fail. */ @@ -456,7 +458,7 @@ generate_srv(const char *hashed_reveals, uint64_t reveal_num, return srv; } -/* Compare reveal values and return the result. This should exclusively be +/** Compare reveal values and return the result. This should exclusively be * used by smartlist_sort(). */ static int compare_reveal_(const void **_a, const void **_b) @@ -466,7 +468,7 @@ compare_reveal_(const void **_a, const void **_b) sizeof(a->hashed_reveal)); } -/* Given <b>commit</b> give the line that we should place in our votes. +/** Given <b>commit</b> give the line that we should place in our votes. * It's the responsibility of the caller to free the string. */ static char * get_vote_line_from_commit(const sr_commit_t *commit, sr_phase_t phase) @@ -506,7 +508,7 @@ get_vote_line_from_commit(const sr_commit_t *commit, sr_phase_t phase) return vote_line; } -/* Return a heap allocated string that contains the given <b>srv</b> string +/** Return a heap allocated string that contains the given <b>srv</b> string * representation formatted for a networkstatus document using the * <b>key</b> as the start of the line. This doesn't return NULL. */ static char * @@ -524,7 +526,7 @@ srv_to_ns_string(const sr_srv_t *srv, const char *key) return srv_str; } -/* Given the previous SRV and the current SRV, return a heap allocated +/** Given the previous SRV and the current SRV, return a heap allocated * string with their data that could be put in a vote or a consensus. Caller * must free the returned string. Return NULL if no SRVs were provided. */ static char * @@ -557,7 +559,7 @@ get_ns_str_from_sr_values(const sr_srv_t *prev_srv, const sr_srv_t *cur_srv) return srv_str; } -/* Return 1 iff the two commits have the same commitment values. This +/** Return 1 iff the two commits have the same commitment values. This * function does not care about reveal values. */ STATIC int commitments_are_the_same(const sr_commit_t *commit_one, @@ -572,7 +574,7 @@ commitments_are_the_same(const sr_commit_t *commit_one, return 1; } -/* We just received a commit from the vote of authority with +/** We just received a commit from the vote of authority with * <b>identity_digest</b>. Return 1 if this commit is authorititative that * is, it belongs to the authority that voted it. Else return 0 if not. */ STATIC int @@ -586,7 +588,7 @@ commit_is_authoritative(const sr_commit_t *commit, sizeof(commit->rsa_identity)); } -/* Decide if the newly received <b>commit</b> should be kept depending on +/** Decide if the newly received <b>commit</b> should be kept depending on * the current phase and state of the protocol. The <b>voter_key</b> is the * RSA identity key fingerprint of the authority's vote from which the * commit comes from. The <b>phase</b> is the phase we should be validating @@ -705,7 +707,7 @@ should_keep_commit(const sr_commit_t *commit, const char *voter_key, return 0; } -/* We are in reveal phase and we found a valid and verified <b>commit</b> in +/** We are in reveal phase and we found a valid and verified <b>commit</b> in * a vote that contains reveal values that we could use. Update the commit * we have in our state. Never call this with an unverified commit. */ STATIC void @@ -726,7 +728,7 @@ save_commit_during_reveal_phase(const sr_commit_t *commit) sr_state_copy_reveal_info(saved_commit, commit); } -/* Save <b>commit</b> to our persistent state. Depending on the current +/** Save <b>commit</b> to our persistent state. Depending on the current * phase, different actions are taken. Steals reference of <b>commit</b>. * The commit object MUST be valid and verified before adding it to the * state. */ @@ -751,7 +753,7 @@ save_commit_to_state(sr_commit_t *commit) } } -/* Return 1 if we should we keep an SRV voted by <b>n_agreements</b> auths. +/** Return 1 if we should we keep an SRV voted by <b>n_agreements</b> auths. * Return 0 if we should ignore it. */ static int should_keep_srv(int n_agreements) @@ -781,7 +783,7 @@ should_keep_srv(int n_agreements) return 1; } -/* Helper: compare two DIGEST256_LEN digests. */ +/** Helper: compare two DIGEST256_LEN digests. */ static int compare_srvs_(const void **_a, const void **_b) { @@ -789,7 +791,7 @@ compare_srvs_(const void **_a, const void **_b) return tor_memcmp(a->value, b->value, sizeof(a->value)); } -/* Return the most frequent member of the sorted list of DIGEST256_LEN +/** Return the most frequent member of the sorted list of DIGEST256_LEN * digests in <b>sl</b> with the count of that most frequent element. */ static sr_srv_t * smartlist_get_most_frequent_srv(const smartlist_t *sl, int *count_out) @@ -806,7 +808,7 @@ compare_srv_(const void **_a, const void **_b) sizeof(a->value)); } -/* Using a list of <b>votes</b>, return the SRV object from them that has +/** Using a list of <b>votes</b>, return the SRV object from them that has * been voted by the majority of dirauths. If <b>current</b> is set, we look * for the current SRV value else the previous one. The returned pointer is * an object located inside a vote. NULL is returned if no appropriate value @@ -868,7 +870,7 @@ get_majority_srv_from_votes(const smartlist_t *votes, int current) return the_srv; } -/* Free a commit object. */ +/** Free a commit object. */ void sr_commit_free_(sr_commit_t *commit) { @@ -880,7 +882,7 @@ sr_commit_free_(sr_commit_t *commit) tor_free(commit); } -/* Generate the commitment/reveal value for the protocol run starting at +/** Generate the commitment/reveal value for the protocol run starting at * <b>timestamp</b>. <b>my_rsa_cert</b> is our authority RSA certificate. */ sr_commit_t * sr_generate_our_commit(time_t timestamp, const authority_cert_t *my_rsa_cert) @@ -937,7 +939,8 @@ sr_generate_our_commit(time_t timestamp, const authority_cert_t *my_rsa_cert) return NULL; } -/* Compute the shared random value based on the active commits in our state. */ +/** Compute the shared random value based on the active commits in our + * state. */ void sr_compute_srv(void) { @@ -1010,7 +1013,7 @@ sr_compute_srv(void) tor_free(reveals); } -/* Parse a commit from a vote or from our disk state and return a newly +/** Parse a commit from a vote or from our disk state and return a newly * allocated commit object. NULL is returned on error. * * The commit's data is in <b>args</b> and the order matters very much: @@ -1082,7 +1085,7 @@ sr_parse_commit(const smartlist_t *args) return NULL; } -/* Called when we are done parsing a vote by <b>voter_key</b> that might +/** Called when we are done parsing a vote by <b>voter_key</b> that might * contain some useful <b>commits</b>. Find if any of them should be kept * and update our state accordingly. Once done, the list of commitments will * be empty. */ @@ -1120,7 +1123,7 @@ sr_handle_received_commits(smartlist_t *commits, crypto_pk_t *voter_key) } SMARTLIST_FOREACH_END(commit); } -/* Return a heap-allocated string containing commits that should be put in +/** Return a heap-allocated string containing commits that should be put in * the votes. It's the responsibility of the caller to free the string. * This always return a valid string, either empty or with line(s). */ char * @@ -1129,7 +1132,7 @@ sr_get_string_for_vote(void) char *vote_str = NULL; digestmap_t *state_commits; smartlist_t *chunks = smartlist_new(); - const or_options_t *options = get_options(); + const dirauth_options_t *options = dirauth_get_options(); /* Are we participating in the protocol? */ if (!options->AuthDirSharedRandomness) { @@ -1178,7 +1181,7 @@ sr_get_string_for_vote(void) return vote_str; } -/* Return a heap-allocated string that should be put in the consensus and +/** Return a heap-allocated string that should be put in the consensus and * contains the shared randomness values. It's the responsibility of the * caller to free the string. NULL is returned if no SRV(s) available. * @@ -1194,7 +1197,7 @@ sr_get_string_for_consensus(const smartlist_t *votes, int32_t num_srv_agreements) { char *srv_str; - const or_options_t *options = get_options(); + const dirauth_options_t *options = dirauth_get_options(); tor_assert(votes); @@ -1222,7 +1225,7 @@ sr_get_string_for_consensus(const smartlist_t *votes, return NULL; } -/* We just computed a new <b>consensus</b>. Update our state with the SRVs +/** We just computed a new <b>consensus</b>. Update our state with the SRVs * from the consensus (might be NULL as well). Register the SRVs in our SR * state and prepare for the upcoming protocol round. */ void @@ -1261,7 +1264,7 @@ sr_act_post_consensus(const networkstatus_t *consensus) sr_state_update(voting_schedule_get_next_valid_after_time()); } -/* Initialize shared random subsystem. This MUST be called early in the boot +/** Initialize shared random subsystem. This MUST be called early in the boot * process of tor. Return 0 on success else -1 on error. */ int sr_init(int save_to_disk) @@ -1269,7 +1272,7 @@ sr_init(int save_to_disk) return sr_state_init(save_to_disk, 1); } -/* Save our state to disk and cleanup everything. */ +/** Save our state to disk and cleanup everything. */ void sr_save_and_cleanup(void) { @@ -1279,7 +1282,7 @@ sr_save_and_cleanup(void) #ifdef TOR_UNIT_TESTS -/* Set the global value of number of SRV agreements so the test can play +/** Set the global value of number of SRV agreements so the test can play * along by calling specific functions that don't parse the votes prior for * the AuthDirNumSRVAgreements value. */ void diff --git a/src/feature/dirauth/shared_random.h b/src/feature/dirauth/shared_random.h index 7ff9f15512..c4e259dcdb 100644 --- a/src/feature/dirauth/shared_random.h +++ b/src/feature/dirauth/shared_random.h @@ -1,86 +1,88 @@ -/* Copyright (c) 2016-2019, The Tor Project, Inc. */ +/* Copyright (c) 2016-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #ifndef TOR_SHARED_RANDOM_H #define TOR_SHARED_RANDOM_H -/* - * This file contains ABI/API of the shared random protocol defined in +/** + * \file shared_random.h + * + * \brief This file contains ABI/API of the shared random protocol defined in * proposal #250. Every public functions and data structure are namespaced * with "sr_" which stands for shared random. */ #include "core/or/or.h" -/* Protocol version */ +/** Protocol version */ #define SR_PROTO_VERSION 1 -/* Default digest algorithm. */ +/** Default digest algorithm. */ #define SR_DIGEST_ALG DIGEST_SHA3_256 -/* Invariant token in the SRV calculation. */ +/** Invariant token in the SRV calculation. */ #define SR_SRV_TOKEN "shared-random" -/* Don't count the NUL terminated byte even though the TOKEN has it. */ +/** Don't count the NUL terminated byte even though the TOKEN has it. */ #define SR_SRV_TOKEN_LEN (sizeof(SR_SRV_TOKEN) - 1) -/* Length of the random number (in bytes). */ +/** Length of the random number (in bytes). */ #define SR_RANDOM_NUMBER_LEN 32 -/* Size of a decoded commit value in a vote or state. It's a hash and a +/** Size of a decoded commit value in a vote or state. It's a hash and a * timestamp. It adds up to 40 bytes. */ #define SR_COMMIT_LEN (sizeof(uint64_t) + DIGEST256_LEN) -/* Size of a decoded reveal value from a vote or state. It's a 64 bit +/** Size of a decoded reveal value from a vote or state. It's a 64 bit * timestamp and the hashed random number. This adds up to 40 bytes. */ #define SR_REVEAL_LEN (sizeof(uint64_t) + DIGEST256_LEN) -/* Size of SRV message length. The construction is has follow: +/** Size of SRV message length. The construction is has follow: * "shared-random" | INT_8(reveal_num) | INT_4(version) | PREV_SRV */ #define SR_SRV_MSG_LEN \ (SR_SRV_TOKEN_LEN + sizeof(uint64_t) + sizeof(uint32_t) + DIGEST256_LEN) -/* Length of base64 encoded commit NOT including the NUL terminated byte. +/** Length of base64 encoded commit NOT including the NUL terminated byte. * Formula is taken from base64_encode_size. This adds up to 56 bytes. */ #define SR_COMMIT_BASE64_LEN (BASE64_LEN(SR_COMMIT_LEN)) -/* Length of base64 encoded reveal NOT including the NUL terminated byte. +/** Length of base64 encoded reveal NOT including the NUL terminated byte. * Formula is taken from base64_encode_size. This adds up to 56 bytes. */ #define SR_REVEAL_BASE64_LEN (BASE64_LEN(SR_REVEAL_LEN)) -/* Length of base64 encoded shared random value. It's 32 bytes long so 44 +/** Length of base64 encoded shared random value. It's 32 bytes long so 44 * bytes from the base64_encode_size formula. That includes the '=' * character at the end. */ #define SR_SRV_VALUE_BASE64_LEN (BASE64_LEN(DIGEST256_LEN)) -/* Assert if commit valid flag is not set. */ +/** Assert if commit valid flag is not set. */ #define ASSERT_COMMIT_VALID(c) tor_assert((c)->valid) -/* Protocol phase. */ +/** Protocol phase. */ typedef enum { - /* Commitment phase */ + /** Commitment phase */ SR_PHASE_COMMIT = 1, - /* Reveal phase */ + /** Reveal phase */ SR_PHASE_REVEAL = 2, } sr_phase_t; -/* A shared random value (SRV). */ +/** A shared random value (SRV). */ typedef struct sr_srv_t { - /* The number of reveal values used to derive this SRV. */ + /** The number of reveal values used to derive this SRV. */ uint64_t num_reveals; - /* The actual value. This is the stored result of SHA3-256. */ + /** The actual value. This is the stored result of SHA3-256. */ uint8_t value[DIGEST256_LEN]; } sr_srv_t; -/* A commit (either ours or from another authority). */ +/** A commit (either ours or from another authority). */ typedef struct sr_commit_t { - /* Hashing algorithm used. */ + /** Hashing algorithm used. */ digest_algorithm_t alg; - /* Indicate if this commit has been verified thus valid. */ + /** Indicate if this commit has been verified thus valid. */ unsigned int valid:1; /* Commit owner info */ - /* The RSA identity key of the authority and its base16 representation, + /** The RSA identity key of the authority and its base16 representation, * which includes the NUL terminated byte. */ char rsa_identity[DIGEST_LEN]; char rsa_identity_hex[HEX_DIGEST_LEN + 1]; /* Commitment information */ - /* Timestamp of reveal. Correspond to TIMESTAMP. */ + /** Timestamp of reveal. Correspond to TIMESTAMP. */ uint64_t reveal_ts; /* H(REVEAL) as found in COMMIT message. */ char hashed_reveal[DIGEST256_LEN]; @@ -89,13 +91,13 @@ typedef struct sr_commit_t { /* Reveal information */ - /* H(RN) which is what we used as the random value for this commit. We + /** H(RN) which is what we used as the random value for this commit. We * don't use the raw bytes since those are sent on the network thus * avoiding possible information leaks of our PRNG. */ uint8_t random_number[SR_RANDOM_NUMBER_LEN]; - /* Timestamp of commit. Correspond to TIMESTAMP. */ + /** Timestamp of commit. Correspond to TIMESTAMP. */ uint64_t commit_ts; - /* This is the whole reveal message. We use it during verification */ + /** This is the whole reveal message. We use it during verification */ char encoded_reveal[SR_REVEAL_BASE64_LEN + 1]; } sr_commit_t; @@ -191,4 +193,3 @@ void set_num_srv_agreements(int32_t value); #endif /* TOR_UNIT_TESTS */ #endif /* !defined(TOR_SHARED_RANDOM_H) */ - diff --git a/src/feature/dirauth/shared_random_state.c b/src/feature/dirauth/shared_random_state.c index 4078d6a24a..cfbfa4ec5b 100644 --- a/src/feature/dirauth/shared_random_state.c +++ b/src/feature/dirauth/shared_random_state.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2019, The Tor Project, Inc. */ +/* Copyright (c) 2016-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -12,7 +12,7 @@ #include "core/or/or.h" #include "app/config/config.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "lib/crypt_ops/crypto_util.h" #include "feature/dirauth/dirvote.h" #include "feature/nodelist/networkstatus.h" @@ -26,18 +26,18 @@ #include "app/config/or_state_st.h" -/* Default filename of the shared random state on disk. */ +/** Default filename of the shared random state on disk. */ static const char default_fname[] = "sr-state"; -/* String representation of a protocol phase. */ +/** String representation of a protocol phase. */ static const char *phase_str[] = { "unknown", "commit", "reveal" }; -/* Our shared random protocol state. There is only one possible state per +/** Our shared random protocol state. There is only one possible state per * protocol run so this is the global state which is reset at every run once * the shared random value has been computed. */ static sr_state_t *sr_state = NULL; -/* Representation of our persistent state on disk. The sr_state above +/** Representation of our persistent state on disk. The sr_state above * contains the data parsed from this state. When we save to disk, we * translate the sr_state to this sr_disk_state. */ static sr_disk_state_t *sr_disk_state = NULL; @@ -56,14 +56,10 @@ DUMMY_TYPECHECK_INSTANCE(sr_disk_state_t); #define V(member,conftype,initvalue) \ VAR(#member, conftype, member, initvalue) -/* Our persistent state magic number. */ +/** Our persistent state magic number. */ #define SR_DISK_STATE_MAGIC 0x98AB1254 -static int -disk_state_validate_cb(void *old_state, void *state, void *default_state, - int from_setconf, char **msg); - -/* Array of variables that are saved to disk as a persistent state. */ +/** Array of variables that are saved to disk as a persistent state. */ static const config_var_t state_vars[] = { V(Version, POSINT, "0"), V(TorVersion, STRING, NULL), @@ -78,7 +74,7 @@ static const config_var_t state_vars[] = { END_OF_CONFIG_VARS }; -/* "Extra" variable in the state that receives lines we can't parse. This +/** "Extra" variable in the state that receives lines we can't parse. This * lets us preserve options from versions of Tor newer than us. */ static const struct_member_t state_extra_var = { .name = "__extra", @@ -86,24 +82,19 @@ static const struct_member_t state_extra_var = { .offset = offsetof(sr_disk_state_t, ExtraLines), }; -/* Configuration format of sr_disk_state_t. */ +/** Configuration format of sr_disk_state_t. */ static const config_format_t state_format = { - sizeof(sr_disk_state_t), - { + .size = sizeof(sr_disk_state_t), + .magic = { "sr_disk_state_t", SR_DISK_STATE_MAGIC, offsetof(sr_disk_state_t, magic_), }, - NULL, - NULL, - state_vars, - disk_state_validate_cb, - NULL, - &state_extra_var, - -1, + .vars = state_vars, + .extra = &state_extra_var, }; -/* Global configuration manager for the shared-random state file */ +/** Global configuration manager for the shared-random state file */ static config_mgr_t *shared_random_state_mgr = NULL; /** Return the configuration manager for the shared-random state file. */ @@ -119,7 +110,7 @@ get_srs_mgr(void) static void state_query_del_(sr_state_object_t obj_type, void *data); -/* Return a string representation of a protocol phase. */ +/** Return a string representation of a protocol phase. */ STATIC const char * get_phase_str(sr_phase_t phase) { @@ -137,7 +128,7 @@ get_phase_str(sr_phase_t phase) return the_string; } -/* Return the time we should expire the state file created at <b>now</b>. +/** Return the time we should expire the state file created at <b>now</b>. * We expire the state file in the beginning of the next protocol run. */ STATIC time_t get_state_valid_until_time(time_t now) @@ -168,7 +159,7 @@ get_state_valid_until_time(time_t now) return valid_until; } -/* Given the consensus 'valid-after' time, return the protocol phase we should +/** Given the consensus 'valid-after' time, return the protocol phase we should * be in. */ STATIC sr_phase_t get_sr_protocol_phase(time_t valid_after) @@ -188,7 +179,7 @@ get_sr_protocol_phase(time_t valid_after) } } -/* Add the given <b>commit</b> to <b>state</b>. It MUST be a valid commit +/** Add the given <b>commit</b> to <b>state</b>. It MUST be a valid commit * and there shouldn't be a commit from the same authority in the state * already else verification hasn't been done prior. This takes ownership of * the commit once in our state. */ @@ -213,7 +204,7 @@ commit_add_to_state(sr_commit_t *commit, sr_state_t *state) } } -/* Helper: deallocate a commit object. (Used with digestmap_free(), which +/** Helper: deallocate a commit object. (Used with digestmap_free(), which * requires a function pointer whose argument is void *). */ static void commit_free_(void *p) @@ -224,7 +215,7 @@ commit_free_(void *p) #define state_free(val) \ FREE_AND_NULL(sr_state_t, state_free_, (val)) -/* Free a state that was allocated with state_new(). */ +/** Free a state that was allocated with state_new(). */ static void state_free_(sr_state_t *state) { @@ -238,7 +229,7 @@ state_free_(sr_state_t *state) tor_free(state); } -/* Allocate an sr_state_t object and returns it. If no <b>fname</b>, the +/** Allocate an sr_state_t object and returns it. If no <b>fname</b>, the * default file name is used. This function does NOT initialize the state * timestamp, phase or shared random value. NULL is never returned. */ static sr_state_t * @@ -257,7 +248,7 @@ state_new(const char *fname, time_t now) return new_state; } -/* Set our global state pointer with the one given. */ +/** Set our global state pointer with the one given. */ static void state_set(sr_state_t *state) { @@ -271,7 +262,7 @@ state_set(sr_state_t *state) #define disk_state_free(val) \ FREE_AND_NULL(sr_disk_state_t, disk_state_free_, (val)) -/* Free an allocated disk state. */ +/** Free an allocated disk state. */ static void disk_state_free_(sr_disk_state_t *state) { @@ -281,7 +272,7 @@ disk_state_free_(sr_disk_state_t *state) config_free(get_srs_mgr(), state); } -/* Allocate a new disk state, initialize it and return it. */ +/** Allocate a new disk state, initialize it and return it. */ static sr_disk_state_t * disk_state_new(time_t now) { @@ -297,7 +288,7 @@ disk_state_new(time_t now) return new_state; } -/* Set our global disk state with the given state. */ +/** Set our global disk state with the given state. */ static void disk_state_set(sr_disk_state_t *state) { @@ -308,7 +299,7 @@ disk_state_set(sr_disk_state_t *state) sr_disk_state = state; } -/* Return -1 if the disk state is invalid (something in there that we can't or +/** Return -1 if the disk state is invalid (something in there that we can't or * shouldn't use). Return 0 if everything checks out. */ static int disk_state_validate(const sr_disk_state_t *state) @@ -343,25 +334,7 @@ disk_state_validate(const sr_disk_state_t *state) return -1; } -/* Validate the disk state (NOP for now). */ -static int -disk_state_validate_cb(void *old_state, void *state, void *default_state, - int from_setconf, char **msg) -{ - /* We don't use these; only options do. */ - (void) from_setconf; - (void) default_state; - (void) old_state; - - /* This is called by config_dump which is just before we are about to - * write it to disk. At that point, our global memory state has been - * copied to the disk state so it's fair to assume it's trustable. */ - (void) state; - (void) msg; - return 0; -} - -/* Parse the Commit line(s) in the disk state and translate them to the +/** Parse the Commit line(s) in the disk state and translate them to the * the memory state. Return 0 on success else -1 on error. */ static int disk_state_parse_commits(sr_state_t *state, @@ -416,7 +389,7 @@ disk_state_parse_commits(sr_state_t *state, return -1; } -/* Parse a share random value line from the disk state and save it to dst +/** Parse a share random value line from the disk state and save it to dst * which is an allocated srv object. Return 0 on success else -1. */ static int disk_state_parse_srv(const char *value, sr_srv_t *dst) @@ -451,7 +424,7 @@ disk_state_parse_srv(const char *value, sr_srv_t *dst) return ret; } -/* Parse both SharedRandCurrentValue and SharedRandPreviousValue line from +/** Parse both SharedRandCurrentValue and SharedRandPreviousValue line from * the state. Return 0 on success else -1. */ static int disk_state_parse_sr_values(sr_state_t *state, @@ -502,7 +475,7 @@ disk_state_parse_sr_values(sr_state_t *state, return -1; } -/* Parse the given disk state and set a newly allocated state. On success, +/** Parse the given disk state and set a newly allocated state. On success, * return that state else NULL. */ static sr_state_t * disk_state_parse(const sr_disk_state_t *new_disk_state) @@ -536,7 +509,7 @@ disk_state_parse(const sr_disk_state_t *new_disk_state) return NULL; } -/* From a valid commit object and an allocated config line, set the line's +/** From a valid commit object and an allocated config line, set the line's * value to the state string representation of a commit. */ static void disk_state_put_commit_line(const sr_commit_t *commit, config_line_t *line) @@ -563,7 +536,7 @@ disk_state_put_commit_line(const sr_commit_t *commit, config_line_t *line) } } -/* From a valid srv object and an allocated config line, set the line's +/** From a valid srv object and an allocated config line, set the line's * value to the state string representation of a shared random value. */ static void disk_state_put_srv_line(const sr_srv_t *srv, config_line_t *line) @@ -581,7 +554,7 @@ disk_state_put_srv_line(const sr_srv_t *srv, config_line_t *line) tor_asprintf(&line->value, "%" PRIu64 " %s", srv->num_reveals, encoded); } -/* Reset disk state that is free allocated memory and zeroed the object. */ +/** Reset disk state that is free allocated memory and zeroed the object. */ static void disk_state_reset(void) { @@ -600,7 +573,7 @@ disk_state_reset(void) sr_disk_state->TorVersion = tor_strdup(get_version()); } -/* Update our disk state based on our global SR state. */ +/** Update our disk state based on our global SR state. */ static void disk_state_update(void) { @@ -644,7 +617,7 @@ disk_state_update(void) } DIGESTMAP_FOREACH_END; } -/* Load state from disk and put it into our disk state. If the state passes +/** Load state from disk and put it into our disk state. If the state passes * validation, our global state will be updated with it. Return 0 on * success. On error, -EINVAL is returned if the state on disk did contained * something malformed or is unreadable. -ENOENT is returned indicating that @@ -662,7 +635,7 @@ disk_state_load_from_disk(void) return ret; } -/* Helper for disk_state_load_from_disk(). */ +/** Helper for disk_state_load_from_disk(). */ STATIC int disk_state_load_from_disk_impl(const char *fname) { @@ -724,7 +697,7 @@ disk_state_load_from_disk_impl(const char *fname) return ret; } -/* Save the disk state to disk but before that update it from the current +/** Save the disk state to disk but before that update it from the current * state so we always have the latest. Return 0 on success else -1. */ static int disk_state_save_to_disk(void) @@ -768,7 +741,7 @@ disk_state_save_to_disk(void) return ret; } -/* Reset our state to prepare for a new protocol run. Once this returns, all +/** Reset our state to prepare for a new protocol run. Once this returns, all * commits in the state will be removed and freed. */ STATIC void reset_state_for_new_protocol_run(time_t valid_after) @@ -789,7 +762,7 @@ reset_state_for_new_protocol_run(time_t valid_after) sr_state_delete_commits(); } -/* This is the first round of the new protocol run starting at +/** This is the first round of the new protocol run starting at * <b>valid_after</b>. Do the necessary housekeeping. */ STATIC void new_protocol_run(time_t valid_after) @@ -823,7 +796,7 @@ new_protocol_run(time_t valid_after) } } -/* Return 1 iff the <b>next_phase</b> is a phase transition from the current +/** Return 1 iff the <b>next_phase</b> is a phase transition from the current * phase that is it's different. */ STATIC int is_phase_transition(sr_phase_t next_phase) @@ -831,7 +804,7 @@ is_phase_transition(sr_phase_t next_phase) return sr_state->phase != next_phase; } -/* Helper function: return a commit using the RSA fingerprint of the +/** Helper function: return a commit using the RSA fingerprint of the * authority or NULL if no such commit is known. */ static sr_commit_t * state_query_get_commit(const char *rsa_fpr) @@ -840,7 +813,7 @@ state_query_get_commit(const char *rsa_fpr) return digestmap_get(sr_state->commits, rsa_fpr); } -/* Helper function: This handles the GET state action using an +/** Helper function: This handles the GET state action using an * <b>obj_type</b> and <b>data</b> needed for the action. */ static void * state_query_get_(sr_state_object_t obj_type, const void *data) @@ -875,7 +848,7 @@ state_query_get_(sr_state_object_t obj_type, const void *data) return obj; } -/* Helper function: This handles the PUT state action using an +/** Helper function: This handles the PUT state action using an * <b>obj_type</b> and <b>data</b> needed for the action. * PUT frees the previous data before replacing it, if needed. */ static void @@ -928,7 +901,7 @@ state_query_put_(sr_state_object_t obj_type, void *data) } } -/* Helper function: This handles the DEL_ALL state action using an +/** Helper function: This handles the DEL_ALL state action using an * <b>obj_type</b> and <b>data</b> needed for the action. */ static void state_query_del_all_(sr_state_object_t obj_type) @@ -957,7 +930,7 @@ state_query_del_all_(sr_state_object_t obj_type) } } -/* Helper function: This handles the DEL state action using an +/** Helper function: This handles the DEL state action using an * <b>obj_type</b> and <b>data</b> needed for the action. */ static void state_query_del_(sr_state_object_t obj_type, void *data) @@ -983,7 +956,7 @@ state_query_del_(sr_state_object_t obj_type, void *data) } } -/* Query state using an <b>action</b> for an object type <b>obj_type</b>. +/** Query state using an <b>action</b> for an object type <b>obj_type</b>. * The <b>data</b> pointer needs to point to an object that the action needs * to use and if anything is required to be returned, it is stored in * <b>out</b>. @@ -1025,7 +998,7 @@ state_query(sr_state_action_t action, sr_state_object_t obj_type, } } -/* Delete the current SRV value from the state freeing it and the value is set +/** Delete the current SRV value from the state freeing it and the value is set * to NULL meaning empty. */ STATIC void state_del_current_srv(void) @@ -1033,7 +1006,7 @@ state_del_current_srv(void) state_query(SR_STATE_ACTION_DEL, SR_STATE_OBJ_CURSRV, NULL, NULL); } -/* Delete the previous SRV value from the state freeing it and the value is +/** Delete the previous SRV value from the state freeing it and the value is * set to NULL meaning empty. */ STATIC void state_del_previous_srv(void) @@ -1041,7 +1014,7 @@ state_del_previous_srv(void) state_query(SR_STATE_ACTION_DEL, SR_STATE_OBJ_PREVSRV, NULL, NULL); } -/* Rotate SRV value by setting the previous SRV to the current SRV, and +/** Rotate SRV value by setting the previous SRV to the current SRV, and * clearing the current SRV. */ STATIC void state_rotate_srv(void) @@ -1054,7 +1027,7 @@ state_rotate_srv(void) sr_state_set_current_srv(NULL); } -/* Set valid after time in the our state. */ +/** Set valid after time in the our state. */ void sr_state_set_valid_after(time_t valid_after) { @@ -1062,7 +1035,7 @@ sr_state_set_valid_after(time_t valid_after) (void *) &valid_after, NULL); } -/* Return the phase we are currently in according to our state. */ +/** Return the phase we are currently in according to our state. */ sr_phase_t sr_state_get_phase(void) { @@ -1072,7 +1045,7 @@ sr_state_get_phase(void) return *(sr_phase_t *) ptr; } -/* Return the previous SRV value from our state. Value CAN be NULL. +/** Return the previous SRV value from our state. Value CAN be NULL. * The state object owns the SRV, so the calling code should not free the SRV. * Use sr_srv_dup() if you want to keep a copy of the SRV. */ const sr_srv_t * @@ -1084,7 +1057,7 @@ sr_state_get_previous_srv(void) return srv; } -/* Set the current SRV value from our state. Value CAN be NULL. The srv +/** Set the current SRV value from our state. Value CAN be NULL. The srv * object ownership is transferred to the state object. */ void sr_state_set_previous_srv(const sr_srv_t *srv) @@ -1093,7 +1066,7 @@ sr_state_set_previous_srv(const sr_srv_t *srv) NULL); } -/* Return the current SRV value from our state. Value CAN be NULL. +/** Return the current SRV value from our state. Value CAN be NULL. * The state object owns the SRV, so the calling code should not free the SRV. * Use sr_srv_dup() if you want to keep a copy of the SRV. */ const sr_srv_t * @@ -1105,7 +1078,7 @@ sr_state_get_current_srv(void) return srv; } -/* Set the current SRV value from our state. Value CAN be NULL. The srv +/** Set the current SRV value from our state. Value CAN be NULL. The srv * object ownership is transferred to the state object. */ void sr_state_set_current_srv(const sr_srv_t *srv) @@ -1114,7 +1087,7 @@ sr_state_set_current_srv(const sr_srv_t *srv) NULL); } -/* Clean all the SRVs in our state. */ +/** Clean all the SRVs in our state. */ void sr_state_clean_srvs(void) { @@ -1123,7 +1096,7 @@ sr_state_clean_srvs(void) state_del_current_srv(); } -/* Return a pointer to the commits map from our state. CANNOT be NULL. */ +/** Return a pointer to the commits map from our state. CANNOT be NULL. */ digestmap_t * sr_state_get_commits(void) { @@ -1134,7 +1107,7 @@ sr_state_get_commits(void) return commits; } -/* Update the current SR state as needed for the upcoming voting round at +/** Update the current SR state as needed for the upcoming voting round at * <b>valid_after</b>. */ void sr_state_update(time_t valid_after) @@ -1198,7 +1171,7 @@ sr_state_update(time_t valid_after) } } -/* Return commit object from the given authority digest <b>rsa_identity</b>. +/** Return commit object from the given authority digest <b>rsa_identity</b>. * Return NULL if not found. */ sr_commit_t * sr_state_get_commit(const char *rsa_identity) @@ -1212,7 +1185,7 @@ sr_state_get_commit(const char *rsa_identity) return commit; } -/* Add <b>commit</b> to the permanent state. The commit object ownership is +/** Add <b>commit</b> to the permanent state. The commit object ownership is * transferred to the state so the caller MUST not free it. */ void sr_state_add_commit(sr_commit_t *commit) @@ -1227,14 +1200,14 @@ sr_state_add_commit(sr_commit_t *commit) sr_commit_get_rsa_fpr(commit)); } -/* Remove all commits from our state. */ +/** Remove all commits from our state. */ void sr_state_delete_commits(void) { state_query(SR_STATE_ACTION_DEL_ALL, SR_STATE_OBJ_COMMIT, NULL, NULL); } -/* Copy the reveal information from <b>commit</b> into <b>saved_commit</b>. +/** Copy the reveal information from <b>commit</b> into <b>saved_commit</b>. * This <b>saved_commit</b> MUST come from our current SR state. Once modified, * the disk state is updated. */ void @@ -1255,7 +1228,7 @@ sr_state_copy_reveal_info(sr_commit_t *saved_commit, const sr_commit_t *commit) sr_commit_get_rsa_fpr(saved_commit)); } -/* Set the fresh SRV flag from our state. This doesn't need to trigger a +/** Set the fresh SRV flag from our state. This doesn't need to trigger a * disk state synchronization so we directly change the state. */ void sr_state_set_fresh_srv(void) @@ -1263,7 +1236,7 @@ sr_state_set_fresh_srv(void) sr_state->is_srv_fresh = 1; } -/* Unset the fresh SRV flag from our state. This doesn't need to trigger a +/** Unset the fresh SRV flag from our state. This doesn't need to trigger a * disk state synchronization so we directly change the state. */ void sr_state_unset_fresh_srv(void) @@ -1271,14 +1244,14 @@ sr_state_unset_fresh_srv(void) sr_state->is_srv_fresh = 0; } -/* Return the value of the fresh SRV flag. */ +/** Return the value of the fresh SRV flag. */ unsigned int sr_state_srv_is_fresh(void) { return sr_state->is_srv_fresh; } -/* Cleanup and free our disk and memory state. */ +/** Cleanup and free our disk and memory state. */ void sr_state_free_all(void) { @@ -1290,7 +1263,7 @@ sr_state_free_all(void) config_mgr_free(shared_random_state_mgr); } -/* Save our current state in memory to disk. */ +/** Save our current state in memory to disk. */ void sr_state_save(void) { @@ -1298,7 +1271,7 @@ sr_state_save(void) state_query(SR_STATE_ACTION_SAVE, 0, NULL, NULL); } -/* Return 1 iff the state has been initialized that is it exists in memory. +/** Return 1 iff the state has been initialized that is it exists in memory. * Return 0 otherwise. */ int sr_state_is_initialized(void) @@ -1306,7 +1279,7 @@ sr_state_is_initialized(void) return sr_state == NULL ? 0 : 1; } -/* Initialize the disk and memory state. +/** Initialize the disk and memory state. * * If save_to_disk is set to 1, the state is immediately saved to disk after * creation else it's not thus only kept in memory. @@ -1369,7 +1342,7 @@ sr_state_init(int save_to_disk, int read_from_disk) #ifdef TOR_UNIT_TESTS -/* Set the current phase of the protocol. Used only by unit tests. */ +/** Set the current phase of the protocol. Used only by unit tests. */ void set_sr_phase(sr_phase_t phase) { @@ -1378,7 +1351,7 @@ set_sr_phase(sr_phase_t phase) sr_state->phase = phase; } -/* Get the SR state. Used only by unit tests */ +/** Get the SR state. Used only by unit tests */ sr_state_t * get_sr_state(void) { diff --git a/src/feature/dirauth/shared_random_state.h b/src/feature/dirauth/shared_random_state.h index 08f999f9d4..3a34bcc3e7 100644 --- a/src/feature/dirauth/shared_random_state.h +++ b/src/feature/dirauth/shared_random_state.h @@ -1,12 +1,17 @@ -/* Copyright (c) 2016-2019, The Tor Project, Inc. */ +/* Copyright (c) 2016-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file shared_random_state.h + * @brief Header for shared_random_state.c + **/ + #ifndef TOR_SHARED_RANDOM_STATE_H #define TOR_SHARED_RANDOM_STATE_H #include "feature/dirauth/shared_random.h" -/* Action that can be performed on the state for any objects. */ +/** Action that can be performed on the state for any objects. */ typedef enum { SR_STATE_ACTION_GET = 1, SR_STATE_ACTION_PUT = 2, @@ -15,52 +20,53 @@ typedef enum { SR_STATE_ACTION_SAVE = 5, } sr_state_action_t; -/* Object in the state that can be queried through the state API. */ +/** Object in the state that can be queried through the state API. */ typedef enum { - /* Will return a single commit using an authority identity key. */ + /** Will return a single commit using an authority identity key. */ SR_STATE_OBJ_COMMIT, - /* Returns the entire list of commits from the state. */ + /** Returns the entire list of commits from the state. */ SR_STATE_OBJ_COMMITS, - /* Return the current SRV object pointer. */ + /** Return the current SRV object pointer. */ SR_STATE_OBJ_CURSRV, - /* Return the previous SRV object pointer. */ + /** Return the previous SRV object pointer. */ SR_STATE_OBJ_PREVSRV, - /* Return the phase. */ + /** Return the phase. */ SR_STATE_OBJ_PHASE, - /* Get or Put the valid after time. */ + /** Get or Put the valid after time. */ SR_STATE_OBJ_VALID_AFTER, } sr_state_object_t; -/* State of the protocol. It's also saved on disk in fname. This data +/** State of the protocol. It's also saved on disk in fname. This data * structure MUST be synchronized at all time with the one on disk. */ typedef struct sr_state_t { - /* Filename of the state file on disk. */ + /** Filename of the state file on disk. */ char *fname; - /* Version of the protocol. */ + /** Version of the protocol. */ uint32_t version; - /* The valid-after of the voting period we have prepared the state for. */ + /** The valid-after of the voting period we have prepared the state for. */ time_t valid_after; - /* Until when is this state valid? */ + /** Until when is this state valid? */ time_t valid_until; - /* Protocol phase. */ + /** Protocol phase. */ sr_phase_t phase; - /* Number of runs completed. */ + /** Number of runs completed. */ uint64_t n_protocol_runs; - /* The number of commitment rounds we've performed in this protocol run. */ + /** The number of commitment rounds we've performed in this protocol run. */ unsigned int n_commit_rounds; - /* The number of reveal rounds we've performed in this protocol run. */ + /** The number of reveal rounds we've performed in this protocol run. */ unsigned int n_reveal_rounds; - /* A map of all the received commitments for this protocol run. This is + /** A map of all the received commitments for this protocol run. This is * indexed by authority RSA identity digest. */ digestmap_t *commits; - /* Current and previous shared random value. */ + /** Current shared random value. */ sr_srv_t *previous_srv; + /** Previous shared random value. */ sr_srv_t *current_srv; - /* Indicate if the state contains an SRV that was _just_ generated. This is + /** Indicate if the state contains an SRV that was _just_ generated. This is * used during voting so that we know whether to use the super majority rule * or not when deciding on keeping it for the consensus. It is _always_ set * to 0 post consensus. @@ -73,22 +79,22 @@ typedef struct sr_state_t { unsigned int is_srv_fresh:1; } sr_state_t; -/* Persistent state of the protocol, as saved to disk. */ +/** Persistent state of the protocol, as saved to disk. */ typedef struct sr_disk_state_t { uint32_t magic_; - /* Version of the protocol. */ + /** Version of the protocol. */ int Version; - /* Version of our running tor. */ + /** Version of our running tor. */ char *TorVersion; - /* Creation time of this state */ + /** Creation time of this state */ time_t ValidAfter; - /* State valid until? */ + /** State valid until? */ time_t ValidUntil; - /* All commits seen that are valid. */ + /** All commits seen that are valid. */ struct config_line_t *Commit; - /* Previous and current shared random value. */ + /** Previous and current shared random value. */ struct config_line_t *SharedRandValues; - /* Extra Lines for configuration we might not know. */ + /** Extra Lines for configuration we might not know. */ struct config_line_t *ExtraLines; } sr_disk_state_t; diff --git a/src/feature/dirauth/vote_microdesc_hash_st.h b/src/feature/dirauth/vote_microdesc_hash_st.h index 7869f92b4f..7f8ebf7fd7 100644 --- a/src/feature/dirauth/vote_microdesc_hash_st.h +++ b/src/feature/dirauth/vote_microdesc_hash_st.h @@ -1,9 +1,14 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file vote_microdesc_hash_st.h + * @brief Microdescriptor-hash voting strcture. + **/ + #ifndef VOTE_MICRODESC_HASH_ST_H #define VOTE_MICRODESC_HASH_ST_H @@ -19,4 +24,3 @@ struct vote_microdesc_hash_t { }; #endif /* !defined(VOTE_MICRODESC_HASH_ST_H) */ - diff --git a/src/feature/dirauth/voteflags.c b/src/feature/dirauth/voteflags.c index f552af98c4..477eb6f0b7 100644 --- a/src/feature/dirauth/voteflags.c +++ b/src/feature/dirauth/voteflags.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -18,6 +18,7 @@ #include "core/or/policies.h" #include "feature/dirauth/bwauth.h" #include "feature/dirauth/reachability.h" +#include "feature/dirauth/dirauth_sys.h" #include "feature/hibernate/hibernate.h" #include "feature/nodelist/dirlist.h" #include "feature/nodelist/networkstatus.h" @@ -27,6 +28,7 @@ #include "feature/relay/router.h" #include "feature/stats/rephist.h" +#include "feature/dirauth/dirauth_options_st.h" #include "feature/nodelist/node_st.h" #include "feature/nodelist/routerinfo_st.h" #include "feature/nodelist/routerlist_st.h" @@ -145,7 +147,7 @@ router_is_active(const routerinfo_t *ri, const node_t *node, time_t now) * if TestingTorNetwork, and TestingMinExitFlagThreshold is non-zero */ if (!ri->bandwidthcapacity) { if (get_options()->TestingTorNetwork) { - if (get_options()->TestingMinExitFlagThreshold > 0) { + if (dirauth_get_options()->TestingMinExitFlagThreshold > 0) { /* If we're in a TestingTorNetwork, and TestingMinExitFlagThreshold is, * then require bandwidthcapacity */ return 0; @@ -175,14 +177,14 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router, long uptime; /* If we haven't been running for at least - * get_options()->MinUptimeHidServDirectoryV2 seconds, we can't + * MinUptimeHidServDirectoryV2 seconds, we can't * have accurate data telling us a relay has been up for at least * that long. We also want to allow a bit of slack: Reachability * tests aren't instant. If we haven't been running long enough, * trust the relay. */ if (get_uptime() > - get_options()->MinUptimeHidServDirectoryV2 * 1.1) + dirauth_get_options()->MinUptimeHidServDirectoryV2 * 1.1) uptime = MIN(rep_hist_get_uptime(router->cache_info.identity_digest, now), real_uptime(router, now)); else @@ -191,7 +193,7 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router, return (router->wants_to_be_hs_dir && router->supports_tunnelled_dir_requests && node->is_stable && node->is_fast && - uptime >= get_options()->MinUptimeHidServDirectoryV2 && + uptime >= dirauth_get_options()->MinUptimeHidServDirectoryV2 && router_is_active(router, node, now)); } @@ -214,9 +216,10 @@ router_counts_toward_thresholds(const node_t *node, time_t now, dirserv_has_measured_bw(node->identity); uint64_t min_bw_kb = ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER_KB; const or_options_t *options = get_options(); + const dirauth_options_t *dirauth_options = dirauth_get_options(); if (options->TestingTorNetwork) { - min_bw_kb = (int64_t)options->TestingMinExitFlagThreshold / 1000; + min_bw_kb = (int64_t)dirauth_options->TestingMinExitFlagThreshold / 1000; } return node->ri && router_is_active(node->ri, node, now) && @@ -242,11 +245,12 @@ dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil) const smartlist_t *nodelist; time_t now = time(NULL); const or_options_t *options = get_options(); + const dirauth_options_t *dirauth_options = dirauth_get_options(); /* Require mbw? */ int require_mbw = (dirserv_get_last_n_measured_bws() > - options->MinMeasuredBWsForAuthToIgnoreAdvertised) ? 1 : 0; + dirauth_options->MinMeasuredBWsForAuthToIgnoreAdvertised) ? 1 : 0; /* initialize these all here, in case there are no routers */ stable_uptime = 0; @@ -338,7 +342,7 @@ dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil) ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG, INT32_MAX); if (options->TestingTorNetwork) { - min_fast = (int32_t)options->TestingMinFastFlagThreshold; + min_fast = (int32_t)dirauth_options->TestingMinFastFlagThreshold; } max_fast = networkstatus_get_param(NULL, "FastFlagMaxThreshold", INT32_MAX, min_fast, INT32_MAX); @@ -352,9 +356,11 @@ dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil) } /* Protect sufficiently fast nodes from being pushed out of the set * of Fast nodes. */ - if (options->AuthDirFastGuarantee && - fast_bandwidth_kb > options->AuthDirFastGuarantee/1000) - fast_bandwidth_kb = (uint32_t)options->AuthDirFastGuarantee/1000; + { + const uint64_t fast_opt = dirauth_get_options()->AuthDirFastGuarantee; + if (fast_opt && fast_bandwidth_kb > fast_opt / 1000) + fast_bandwidth_kb = (uint32_t)(fast_opt / 1000); + } /* Now that we have a time-known that 7/8 routers are known longer than, * fill wfus with the wfu of every such "familiar" router. */ @@ -428,7 +434,7 @@ dirserv_get_flag_thresholds_line(void) { char *result=NULL; const int measured_threshold = - get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised; + dirauth_get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised; const int enough_measured_bw = dirserv_get_last_n_measured_bws() > measured_threshold; @@ -455,8 +461,9 @@ dirserv_get_flag_thresholds_line(void) int running_long_enough_to_decide_unreachable(void) { - return time_of_process_start - + get_options()->TestingAuthDirTimeToLearnReachability < approx_time(); + const dirauth_options_t *opts = dirauth_get_options(); + return time_of_process_start + + opts->TestingAuthDirTimeToLearnReachability < approx_time(); } /** Each server needs to have passed a reachability test no more @@ -481,6 +488,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now) */ int answer; const or_options_t *options = get_options(); + const dirauth_options_t *dirauth_options = dirauth_get_options(); node_t *node = node_get_mutable_by_id(router->cache_info.identity_digest); tor_assert(node); @@ -507,7 +515,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now) IPv6 OR port since that'd kill all dual stack relays until a majority of the dir auths have IPv6 connectivity. */ answer = (now < node->last_reachable + REACHABLE_TIMEOUT && - (options->AuthDirHasIPv6Connectivity != 1 || + (dirauth_options->AuthDirHasIPv6Connectivity != 1 || tor_addr_is_null(&router->ipv6_addr) || now < node->last_reachable6 + REACHABLE_TIMEOUT)); } @@ -538,7 +546,7 @@ static int should_publish_node_ipv6(const node_t *node, const routerinfo_t *ri, time_t now) { - const or_options_t *options = get_options(); + const dirauth_options_t *options = dirauth_get_options(); return options->AuthDirHasIPv6Connectivity == 1 && !tor_addr_is_null(&ri->ipv6_addr) && @@ -571,10 +579,10 @@ dirauth_set_routerstatus_from_routerinfo(routerstatus_t *rs, set_routerstatus_from_routerinfo(rs, node, ri); /* Override rs->is_possible_guard. */ + const uint64_t bw_opt = dirauth_get_options()->AuthDirGuardBWGuarantee; if (node->is_fast && node->is_stable && ri->supports_tunnelled_dir_requests && - ((options->AuthDirGuardBWGuarantee && - routerbw_kb >= options->AuthDirGuardBWGuarantee/1000) || + ((bw_opt && routerbw_kb >= bw_opt / 1000) || routerbw_kb >= MIN(guard_bandwidth_including_exits_kb, guard_bandwidth_excluding_exits_kb))) { long tk = rep_hist_get_weighted_time_known( @@ -612,9 +620,9 @@ dirauth_set_routerstatus_from_routerinfo(routerstatus_t *rs, STATIC void dirserv_set_routerstatus_testing(routerstatus_t *rs) { - const or_options_t *options = get_options(); + const dirauth_options_t *options = dirauth_get_options(); - tor_assert(options->TestingTorNetwork); + tor_assert(get_options()->TestingTorNetwork); if (routerset_contains_routerstatus(options->TestingDirAuthVoteExit, rs, 0)) { diff --git a/src/feature/dirauth/voteflags.h b/src/feature/dirauth/voteflags.h index c4f36e7817..91f3854573 100644 --- a/src/feature/dirauth/voteflags.h +++ b/src/feature/dirauth/voteflags.h @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2019, The Tor Project, Inc. */ + * Copyright (c) 2007-2020, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** |