Tor  0.4.7.0-alpha-dev
dirauth_config.c
Go to the documentation of this file.
1 /* Copyright (c) 2001 Matej Pfajfar.
2  * Copyright (c) 2001-2004, Roger Dingledine.
3  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4  * Copyright (c) 2007-2021, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
6 
7 /**
8  * @file dirauth_config.c
9  * @brief Code to interpret the user's configuration of Tor's directory
10  * authority module.
11  **/
12 
13 #include "orconfig.h"
15 
16 #include "lib/encoding/confline.h"
17 #include "lib/confmgt/confmgt.h"
18 #include "lib/conf/confdecl.h"
19 
20 /* Required for dirinfo_type_t in or_options_t */
21 #include "core/or/or.h"
22 #include "app/config/config.h"
24 
26 #include "feature/stats/rephist.h"
27 
29 #include "feature/dirauth/bwauth.h"
35 
36 /* Copied from config.c, we will refactor later in 29211. */
37 #define REJECT(arg) \
38  STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
39 #if defined(__GNUC__) && __GNUC__ <= 3
40 #define COMPLAIN(args...) \
41  STMT_BEGIN log_warn(LD_CONFIG, args); STMT_END
42 #else
43 #define COMPLAIN(args, ...) \
44  STMT_BEGIN log_warn(LD_CONFIG, args, ##__VA_ARGS__); STMT_END
45 #endif /* defined(__GNUC__) && __GNUC__ <= 3 */
46 
47 #define YES_IF_CHANGED_INT(opt) \
48  if (!CFG_EQ_INT(old_options, new_options, opt)) return 1;
49 
50 /** Return true iff we are configured to reject request under load for non
51  * relay connections. */
52 bool
54 {
55  return !!dirauth_get_options()->AuthDirRejectRequestsUnderLoad;
56 }
57 
58 /**
59  * Legacy validation/normalization function for the dirauth mode options in
60  * options. Uses old_options as the previous options.
61  *
62  * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
63  * on error.
64  */
65 int
67  or_options_t *options,
68  char **msg)
69 {
70  if (BUG(!options))
71  return -1;
72 
73  if (BUG(!msg))
74  return -1;
75 
76  if (!authdir_mode(options))
77  return 0;
78 
79  /* confirm that our address isn't broken, so we can complain now */
80  tor_addr_t tmp;
81  if (!find_my_address(options, AF_INET, LOG_WARN, &tmp, NULL, NULL))
82  REJECT("Failed to resolve/guess local address. See logs for details.");
83 
84  if (!options->ContactInfo && !options->TestingTorNetwork)
85  REJECT("Authoritative directory servers must set ContactInfo");
86 
87  if (options->UseEntryGuards) {
88  log_info(LD_CONFIG, "Authoritative directory servers can't set "
89  "UseEntryGuards. Disabling.");
90  options->UseEntryGuards = 0;
91  }
92  if (!options->DownloadExtraInfo && authdir_mode_v3(options)) {
93  log_info(LD_CONFIG, "Authoritative directories always try to download "
94  "extra-info documents. Setting DownloadExtraInfo.");
95  options->DownloadExtraInfo = 1;
96  }
97  if (!(options->BridgeAuthoritativeDir ||
98  options->V3AuthoritativeDir))
99  REJECT("AuthoritativeDir is set, but none of "
100  "(Bridge/V3)AuthoritativeDir is set.");
101 
102  /* If we have a v3bandwidthsfile and it's broken, complain on startup */
103  if (options->V3BandwidthsFile && !old_options) {
105  NULL);
106  }
107  /* same for guardfraction file */
108  if (options->GuardfractionFile && !old_options) {
110  }
111 
112  if (!options->DirPort_set)
113  REJECT("Running as authoritative directory, but no DirPort set.");
114 
115  if (!options->ORPort_set)
116  REJECT("Running as authoritative directory, but no ORPort set.");
117 
118  if (options->ClientOnly)
119  REJECT("Running as authoritative directory, but ClientOnly also set.");
120 
121  return 0;
122 }
123 
124 /**
125  * Legacy validation/normalization function for the dirauth schedule options
126  * in options. Uses old_options as the previous options.
127  *
128  * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
129  * on error.
130  */
131 int
133  or_options_t *options,
134  char **msg)
135 {
136  (void)old_options;
137 
138  if (BUG(!options))
139  return -1;
140 
141  if (BUG(!msg))
142  return -1;
143 
144  if (!authdir_mode_v3(options))
145  return 0;
146 
147  if (options->V3AuthVoteDelay + options->V3AuthDistDelay >=
148  options->V3AuthVotingInterval/2) {
149  REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than half "
150  "V3AuthVotingInterval");
151  }
152 
153  if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS) {
154  if (options->TestingTorNetwork) {
155  if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS_TESTING) {
156  REJECT("V3AuthVoteDelay is way too low.");
157  } else {
158  COMPLAIN("V3AuthVoteDelay is very low. "
159  "This may lead to failure to vote for a consensus.");
160  }
161  } else {
162  REJECT("V3AuthVoteDelay is way too low.");
163  }
164  }
165 
166  if (options->V3AuthDistDelay < MIN_DIST_SECONDS) {
167  if (options->TestingTorNetwork) {
168  if (options->V3AuthDistDelay < MIN_DIST_SECONDS_TESTING) {
169  REJECT("V3AuthDistDelay is way too low.");
170  } else {
171  COMPLAIN("V3AuthDistDelay is very low. "
172  "This may lead to missing votes in a consensus.");
173  }
174  } else {
175  REJECT("V3AuthDistDelay is way too low.");
176  }
177  }
178 
179  if (options->V3AuthNIntervalsValid < 2)
180  REJECT("V3AuthNIntervalsValid must be at least 2.");
181 
182  if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL) {
183  if (options->TestingTorNetwork) {
185  /* Unreachable, covered by earlier checks */
186  REJECT("V3AuthVotingInterval is insanely low."); /* LCOV_EXCL_LINE */
187  } else {
188  COMPLAIN("V3AuthVotingInterval is very low. "
189  "This may lead to failure to synchronise for a consensus.");
190  }
191  } else {
192  REJECT("V3AuthVotingInterval is insanely low.");
193  }
194  } else if (options->V3AuthVotingInterval > 24*60*60) {
195  REJECT("V3AuthVotingInterval is insanely high.");
196  } else if (((24*60*60) % options->V3AuthVotingInterval) != 0) {
197  COMPLAIN("V3AuthVotingInterval does not divide evenly into 24 hours.");
198  }
199 
200  return 0;
201 }
202 
203 /**
204  * Legacy validation/normalization function for the dirauth testing options
205  * in options. Uses old_options as the previous options.
206  *
207  * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
208  * on error.
209  */
210 int
212  or_options_t *options,
213  char **msg)
214 {
215  (void)old_options;
216 
217  if (BUG(!options))
218  return -1;
219 
220  if (BUG(!msg))
221  return -1;
222 
223  if (!authdir_mode(options))
224  return 0;
225 
226  if (!authdir_mode_v3(options))
227  return 0;
228 
230  < MIN_VOTE_INTERVAL_TESTING_INITIAL) {
231  REJECT("TestingV3AuthInitialVotingInterval is insanely low.");
232  } else if (((30*60) % options->TestingV3AuthInitialVotingInterval) != 0) {
233  REJECT("TestingV3AuthInitialVotingInterval does not divide evenly into "
234  "30 minutes.");
235  }
236 
238  REJECT("TestingV3AuthInitialVoteDelay is way too low.");
239  }
240 
242  REJECT("TestingV3AuthInitialDistDelay is way too low.");
243  }
244 
245  if (options->TestingV3AuthInitialVoteDelay +
248  REJECT("TestingV3AuthInitialVoteDelay plus TestingV3AuthInitialDistDelay "
249  "must be less than TestingV3AuthInitialVotingInterval");
250  }
251 
252  if (options->TestingV3AuthVotingStartOffset >
254  options->V3AuthVotingInterval)) {
255  REJECT("TestingV3AuthVotingStartOffset is higher than the voting "
256  "interval.");
257  } else if (options->TestingV3AuthVotingStartOffset < 0) {
258  REJECT("TestingV3AuthVotingStartOffset must be non-negative.");
259  }
260 
261  return 0;
262 }
263 
264 /**
265  * Return true if changing the configuration from <b>old</b> to <b>new</b>
266  * affects the timing of the voting subsystem
267  */
268 static int
270  const or_options_t *new_options)
271 {
272  tor_assert(old_options);
273  tor_assert(new_options);
274 
275  if (authdir_mode_v3(old_options) != authdir_mode_v3(new_options))
276  return 1;
277  if (! authdir_mode_v3(new_options))
278  return 0;
279 
280  YES_IF_CHANGED_INT(V3AuthVotingInterval);
281  YES_IF_CHANGED_INT(V3AuthVoteDelay);
282  YES_IF_CHANGED_INT(V3AuthDistDelay);
283  YES_IF_CHANGED_INT(TestingV3AuthInitialVotingInterval);
284  YES_IF_CHANGED_INT(TestingV3AuthInitialVoteDelay);
285  YES_IF_CHANGED_INT(TestingV3AuthInitialDistDelay);
286  YES_IF_CHANGED_INT(TestingV3AuthVotingStartOffset);
287 
288  return 0;
289 }
290 
291 /** Fetch the active option list, and take dirauth actions based on it. All of
292  * the things we do should survive being done repeatedly. If present,
293  * <b>old_options</b> contains the previous value of the options.
294  *
295  * Return 0 if all goes well, return -1 if it's time to die.
296  *
297  * Note: We haven't moved all the "act on new configuration" logic
298  * into the options_act* functions yet. Some is still in do_hup() and other
299  * places.
300  */
301 int
303 {
304  const or_options_t *options = get_options();
305 
306  /* We may need to reschedule some dirauth stuff if our status changed. */
307  if (old_options) {
308  if (options_transition_affects_dirauth_timing(old_options, options)) {
309  dirauth_sched_recalculate_timing(options, time(NULL));
310  reschedule_dirvote(options);
311  }
312  }
313 
314  return 0;
315 }
316 
317 /** Fetch the active option list, and take dirauth mtbf actions based on it.
318  * All of the things we do should survive being done repeatedly. If present,
319  * <b>old_options</b> contains the previous value of the options.
320  *
321  * Must be called immediately after a successful or_state_load().
322  *
323  * Return 0 if all goes well, return -1 if it's time to die.
324  *
325  * Note: We haven't moved all the "act on new configuration" logic
326  * into the options_act* functions yet. Some is still in do_hup() and other
327  * places.
328  */
329 int
331 {
332  (void)old_options;
333 
334  const or_options_t *options = get_options();
335  int running_tor = options->command == CMD_RUN_TOR;
336 
337  if (!authdir_mode(options))
338  return 0;
339 
340  /* Load dirauth state */
341  if (running_tor) {
342  rep_hist_load_mtbf_data(time(NULL));
343  }
344 
345  return 0;
346 }
347 
348 /** Fetch the active option list, and take dirauth statistics actions based
349  * on it. All of the things we do should survive being done repeatedly. If
350  * present, <b>old_options</b> contains the previous value of the options.
351  *
352  * Sets <b>*print_notice_out</b> if we enabled stats, and need to print
353  * a stats log using options_act_relay_stats_msg().
354  *
355  * Return 0 if all goes well, return -1 if it's time to die.
356  *
357  * Note: We haven't moved all the "act on new configuration" logic
358  * into the options_act* functions yet. Some is still in do_hup() and other
359  * places.
360  */
361 int
363  bool *print_notice_out)
364 {
365  if (BUG(!print_notice_out))
366  return -1;
367 
368  const or_options_t *options = get_options();
369 
370  if (authdir_mode_bridge(options)) {
371  time_t now = time(NULL);
372  int print_notice = 0;
373 
374  if (!old_options || !authdir_mode_bridge(old_options)) {
376  print_notice = 1;
377  }
378  if (print_notice)
379  *print_notice_out = 1;
380  }
381 
382  /* If we used to have statistics enabled but we just disabled them,
383  stop gathering them. */
384  if (old_options && authdir_mode_bridge(old_options) &&
385  !authdir_mode_bridge(options))
387 
388  return 0;
389 }
390 
391 /**
392  * Make any necessary modifications to a dirauth_options_t that occur
393  * before validation. On success return 0; on failure return -1 and
394  * set *<b>msg_out</b> to a newly allocated error string.
395  **/
396 static int
397 dirauth_options_pre_normalize(void *arg, char **msg_out)
398 {
399  dirauth_options_t *options = arg;
400  (void)msg_out;
401 
402  if (!options->RecommendedClientVersions)
403  options->RecommendedClientVersions =
405  if (!options->RecommendedServerVersions)
406  options->RecommendedServerVersions =
408 
410  "AuthDirFastGuarantee", msg_out) < 0)
411  return -1;
413  "AuthDirGuardBWGuarantee", msg_out) < 0)
414  return -1;
415 
416  return 0;
417 }
418 
419 /**
420  * Check whether a dirauth_options_t is correct.
421  *
422  * On success return 0; on failure return -1 and set *<b>msg_out</b> to a
423  * newly allocated error string.
424  **/
425 static int
426 dirauth_options_validate(const void *arg, char **msg)
427 {
428  const dirauth_options_t *options = arg;
429 
430  if (options->VersioningAuthoritativeDirectory &&
431  (!options->RecommendedClientVersions ||
432  !options->RecommendedServerVersions)) {
433  REJECT("Versioning authoritative dir servers must set "
434  "Recommended*Versions.");
435  }
436 
437  char *t;
438  /* Call these functions to produce warnings only. */
440  tor_free(t);
442  tor_free(t);
443 
444  if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) {
445  COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high.");
446  }
447 
448  return 0;
449 }
450 
451 /* Declare the options field table for dirauth_options */
452 #define CONF_CONTEXT TABLE
454 #undef CONF_CONTEXT
455 
456 /** Magic number for dirauth_options_t. */
457 #define DIRAUTH_OPTIONS_MAGIC 0x41757448
458 
459 /**
460  * Declare the configuration options for the dirauth module.
461  **/
463  .size = sizeof(dirauth_options_t),
464  .magic = { "dirauth_options_t",
466  offsetof(dirauth_options_t, magic) },
467  .vars = dirauth_options_t_vars,
468 
469  .pre_normalize_fn = dirauth_options_pre_normalize,
470  .validate_fn = dirauth_options_validate
471 };
int authdir_mode(const or_options_t *options)
Definition: authmode.c:25
int authdir_mode_bridge(const or_options_t *options)
Definition: authmode.c:76
Header file for directory authority mode.
int dirserv_read_measured_bandwidths(const char *from_file, smartlist_t *routerstatuses, smartlist_t *bw_file_headers, uint8_t *digest_out)
Definition: bwauth.c:232
Header file for bwauth.c.
Macros for generating a configuration struct from a list of its individual fields.
int config_ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg)
Definition: config.c:2951
const or_options_t * get_options(void)
Definition: config.c:919
Header file for config.c.
config_line_t * config_lines_dup(const config_line_t *inp)
Definition: confline.c:226
Header for confline.c.
Header for confmgt.c.
int options_act_dirauth_mtbf(const or_options_t *old_options)
static int dirauth_options_validate(const void *arg, char **msg)
const config_format_t dirauth_options_fmt
bool dirauth_should_reject_requests_under_load(void)
int options_act_dirauth_stats(const or_options_t *old_options, bool *print_notice_out)
int options_validate_dirauth_mode(const or_options_t *old_options, or_options_t *options, char **msg)
static int options_transition_affects_dirauth_timing(const or_options_t *old_options, const or_options_t *new_options)
static int dirauth_options_pre_normalize(void *arg, char **msg_out)
int options_act_dirauth(const or_options_t *old_options)
#define DIRAUTH_OPTIONS_MAGIC
int options_validate_dirauth_testing(const or_options_t *old_options, or_options_t *options, char **msg)
int options_validate_dirauth_schedule(const or_options_t *old_options, or_options_t *options, char **msg)
Header for feature/dirauth/dirauth_config.c.
Declare configuration options for the crypto_ops module.
Structure dirauth_options_t to hold directory authority options.
void reschedule_dirvote(const or_options_t *options)
Header for dirauth_periodic.c.
Header for dirauth_sys.c.
char * format_recommended_version_list(const config_line_t *ln, int warn)
Definition: dirvote.c:4454
Header file for dirvote.c.
#define MIN_DIST_SECONDS_TESTING
Definition: dirvote.h:34
#define MIN_VOTE_INTERVAL_TESTING
Definition: dirvote.h:46
#define MIN_VOTE_INTERVAL
Definition: dirvote.h:37
#define MIN_DIST_SECONDS
Definition: dirvote.h:32
#define MIN_VOTE_SECONDS_TESTING
Definition: dirvote.h:29
#define MIN_VOTE_SECONDS
Definition: dirvote.h:27
Header file for guardfraction.c.
int dirserv_read_guardfraction_file(const char *fname, smartlist_t *vote_routerstatuses)
#define LD_CONFIG
Definition: log.h:68
#define LOG_WARN
Definition: log.h:53
#define tor_free(p)
Definition: malloc.h:52
Master header file for Tor-specific functionality.
void rep_hist_desc_stats_term(void)
Definition: rephist.c:1884
int rep_hist_load_mtbf_data(time_t now)
Definition: rephist.c:1125
void rep_hist_desc_stats_init(time_t now)
Definition: rephist.c:1861
Header file for rephist.c.
bool find_my_address(const or_options_t *options, int family, int warn_severity, tor_addr_t *addr_out, resolved_addr_method_t *method_out, char **hostname_out)
Attempt to find our IP address that can be used as our external reachable address.
Definition: resolve_addr.c:727
Header file for resolve_addr.c.
MEMUNIT AuthDirGuardBWGuarantee
INTERVAL TestingAuthDirTimeToLearnReachability
LINELIST RecommendedServerVersions
LINELIST RecommendedClientVersions
LINELIST RecommendedVersions
int TestingV3AuthInitialDistDelay
char * ContactInfo
int V3AuthNIntervalsValid
char * GuardfractionFile
char * V3BandwidthsFile
int TestingV3AuthInitialVotingInterval
int V3AuthoritativeDir
int TestingV3AuthInitialVoteDelay
tor_cmdline_mode_t command
Definition: or_options_st.h:68
int V3AuthVotingInterval
int BridgeAuthoritativeDir
int TestingV3AuthVotingStartOffset
@ CMD_RUN_TOR
#define tor_assert(expr)
Definition: util_bug.h:102
void dirauth_sched_recalculate_timing(const or_options_t *options, time_t now)
Header file for voting_schedule.c.