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