Update copyrights to 2021, using "make update-copyright"
[tor.git] / src / feature / dirauth / dirauth_config.c
blob53c9f9f78186c122e95b092cf51aac0da3dff09f
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 */
7 /**
8 * @file dirauth_config.c
9 * @brief Code to interpret the user's configuration of Tor's directory
10 * authority module.
11 **/
13 #include "orconfig.h"
14 #include "feature/dirauth/dirauth_config.h"
16 #include "lib/encoding/confline.h"
17 #include "lib/confmgt/confmgt.h"
18 #include "lib/conf/confdecl.h"
20 /* Required for dirinfo_type_t in or_options_t */
21 #include "core/or/or.h"
22 #include "app/config/config.h"
23 #include "app/config/resolve_addr.h"
25 #include "feature/dirauth/voting_schedule.h"
26 #include "feature/stats/rephist.h"
28 #include "feature/dirauth/authmode.h"
29 #include "feature/dirauth/bwauth.h"
30 #include "feature/dirauth/dirauth_periodic.h"
31 #include "feature/dirauth/dirauth_sys.h"
32 #include "feature/dirauth/dirvote.h"
33 #include "feature/dirauth/guardfraction.h"
34 #include "feature/dirauth/dirauth_options_st.h"
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 */
47 #define YES_IF_CHANGED_INT(opt) \
48 if (!CFG_EQ_INT(old_options, new_options, opt)) return 1;
50 /** Return true iff we are configured to reject request under load for non
51 * relay connections. */
52 bool
53 dirauth_should_reject_requests_under_load(void)
55 return !!dirauth_get_options()->AuthDirRejectRequestsUnderLoad;
58 /**
59 * Legacy validation/normalization function for the dirauth mode options in
60 * options. Uses old_options as the previous options.
62 * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
63 * on error.
65 int
66 options_validate_dirauth_mode(const or_options_t *old_options,
67 or_options_t *options,
68 char **msg)
70 if (BUG(!options))
71 return -1;
73 if (BUG(!msg))
74 return -1;
76 if (!authdir_mode(options))
77 return 0;
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.");
84 if (!options->ContactInfo && !options->TestingTorNetwork)
85 REJECT("Authoritative directory servers must set ContactInfo");
87 if (options->UseEntryGuards) {
88 log_info(LD_CONFIG, "Authoritative directory servers can't set "
89 "UseEntryGuards. Disabling.");
90 options->UseEntryGuards = 0;
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;
97 if (!(options->BridgeAuthoritativeDir ||
98 options->V3AuthoritativeDir))
99 REJECT("AuthoritativeDir is set, but none of "
100 "(Bridge/V3)AuthoritativeDir is set.");
102 /* If we have a v3bandwidthsfile and it's broken, complain on startup */
103 if (options->V3BandwidthsFile && !old_options) {
104 dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL, NULL,
105 NULL);
107 /* same for guardfraction file */
108 if (options->GuardfractionFile && !old_options) {
109 dirserv_read_guardfraction_file(options->GuardfractionFile, NULL);
112 if (!options->DirPort_set)
113 REJECT("Running as authoritative directory, but no DirPort set.");
115 if (!options->ORPort_set)
116 REJECT("Running as authoritative directory, but no ORPort set.");
118 if (options->ClientOnly)
119 REJECT("Running as authoritative directory, but ClientOnly also set.");
121 return 0;
125 * Legacy validation/normalization function for the dirauth schedule options
126 * in options. Uses old_options as the previous options.
128 * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
129 * on error.
132 options_validate_dirauth_schedule(const or_options_t *old_options,
133 or_options_t *options,
134 char **msg)
136 (void)old_options;
138 if (BUG(!options))
139 return -1;
141 if (BUG(!msg))
142 return -1;
144 if (!authdir_mode_v3(options))
145 return 0;
147 if (options->V3AuthVoteDelay + options->V3AuthDistDelay >=
148 options->V3AuthVotingInterval/2) {
149 REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than half "
150 "V3AuthVotingInterval");
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.");
161 } else {
162 REJECT("V3AuthVoteDelay is way too low.");
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.");
174 } else {
175 REJECT("V3AuthDistDelay is way too low.");
179 if (options->V3AuthNIntervalsValid < 2)
180 REJECT("V3AuthNIntervalsValid must be at least 2.");
182 if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL) {
183 if (options->TestingTorNetwork) {
184 if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL_TESTING) {
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.");
191 } else {
192 REJECT("V3AuthVotingInterval is insanely low.");
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.");
200 return 0;
204 * Legacy validation/normalization function for the dirauth testing options
205 * in options. Uses old_options as the previous options.
207 * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
208 * on error.
211 options_validate_dirauth_testing(const or_options_t *old_options,
212 or_options_t *options,
213 char **msg)
215 (void)old_options;
217 if (BUG(!options))
218 return -1;
220 if (BUG(!msg))
221 return -1;
223 if (!authdir_mode(options))
224 return 0;
226 if (!authdir_mode_v3(options))
227 return 0;
229 if (options->TestingV3AuthInitialVotingInterval
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.");
237 if (options->TestingV3AuthInitialVoteDelay < MIN_VOTE_SECONDS_TESTING) {
238 REJECT("TestingV3AuthInitialVoteDelay is way too low.");
241 if (options->TestingV3AuthInitialDistDelay < MIN_DIST_SECONDS_TESTING) {
242 REJECT("TestingV3AuthInitialDistDelay is way too low.");
245 if (options->TestingV3AuthInitialVoteDelay +
246 options->TestingV3AuthInitialDistDelay >=
247 options->TestingV3AuthInitialVotingInterval) {
248 REJECT("TestingV3AuthInitialVoteDelay plus TestingV3AuthInitialDistDelay "
249 "must be less than TestingV3AuthInitialVotingInterval");
252 if (options->TestingV3AuthVotingStartOffset >
253 MIN(options->TestingV3AuthInitialVotingInterval,
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.");
261 return 0;
265 * Return true if changing the configuration from <b>old</b> to <b>new</b>
266 * affects the timing of the voting subsystem
268 static int
269 options_transition_affects_dirauth_timing(const or_options_t *old_options,
270 const or_options_t *new_options)
272 tor_assert(old_options);
273 tor_assert(new_options);
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;
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);
288 return 0;
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.
295 * Return 0 if all goes well, return -1 if it's time to die.
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.
302 options_act_dirauth(const or_options_t *old_options)
304 const or_options_t *options = get_options();
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);
314 return 0;
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.
321 * Must be called immediately after a successful or_state_load().
323 * Return 0 if all goes well, return -1 if it's time to die.
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.
330 options_act_dirauth_mtbf(const or_options_t *old_options)
332 (void)old_options;
334 const or_options_t *options = get_options();
335 int running_tor = options->command == CMD_RUN_TOR;
337 if (!authdir_mode(options))
338 return 0;
340 /* Load dirauth state */
341 if (running_tor) {
342 rep_hist_load_mtbf_data(time(NULL));
345 return 0;
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.
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().
355 * Return 0 if all goes well, return -1 if it's time to die.
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.
362 options_act_dirauth_stats(const or_options_t *old_options,
363 bool *print_notice_out)
365 if (BUG(!print_notice_out))
366 return -1;
368 const or_options_t *options = get_options();
370 if (authdir_mode_bridge(options)) {
371 time_t now = time(NULL);
372 int print_notice = 0;
374 if (!old_options || !authdir_mode_bridge(old_options)) {
375 rep_hist_desc_stats_init(now);
376 print_notice = 1;
378 if (print_notice)
379 *print_notice_out = 1;
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))
386 rep_hist_desc_stats_term();
388 return 0;
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.
396 static int
397 dirauth_options_pre_normalize(void *arg, char **msg_out)
399 dirauth_options_t *options = arg;
400 (void)msg_out;
402 if (!options->RecommendedClientVersions)
403 options->RecommendedClientVersions =
404 config_lines_dup(options->RecommendedVersions);
405 if (!options->RecommendedServerVersions)
406 options->RecommendedServerVersions =
407 config_lines_dup(options->RecommendedVersions);
409 if (config_ensure_bandwidth_cap(&options->AuthDirFastGuarantee,
410 "AuthDirFastGuarantee", msg_out) < 0)
411 return -1;
412 if (config_ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee,
413 "AuthDirGuardBWGuarantee", msg_out) < 0)
414 return -1;
416 return 0;
420 * Check whether a dirauth_options_t is correct.
422 * On success return 0; on failure return -1 and set *<b>msg_out</b> to a
423 * newly allocated error string.
425 static int
426 dirauth_options_validate(const void *arg, char **msg)
428 const dirauth_options_t *options = arg;
430 if (options->VersioningAuthoritativeDirectory &&
431 (!options->RecommendedClientVersions ||
432 !options->RecommendedServerVersions)) {
433 REJECT("Versioning authoritative dir servers must set "
434 "Recommended*Versions.");
437 char *t;
438 /* Call these functions to produce warnings only. */
439 t = format_recommended_version_list(options->RecommendedClientVersions, 1);
440 tor_free(t);
441 t = format_recommended_version_list(options->RecommendedServerVersions, 1);
442 tor_free(t);
444 if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) {
445 COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high.");
448 return 0;
451 /* Declare the options field table for dirauth_options */
452 #define CONF_CONTEXT TABLE
453 #include "feature/dirauth/dirauth_options.inc"
454 #undef CONF_CONTEXT
456 /** Magic number for dirauth_options_t. */
457 #define DIRAUTH_OPTIONS_MAGIC 0x41757448
460 * Declare the configuration options for the dirauth module.
462 const config_format_t dirauth_options_fmt = {
463 .size = sizeof(dirauth_options_t),
464 .magic = { "dirauth_options_t",
465 DIRAUTH_OPTIONS_MAGIC,
466 offsetof(dirauth_options_t, magic) },
467 .vars = dirauth_options_t_vars,
469 .pre_normalize_fn = dirauth_options_pre_normalize,
470 .validate_fn = dirauth_options_validate