Tor 0.4.9.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
17#include "lib/confmgt/confmgt.h"
18#include "lib/conf/confdecl.h"
20
21/* Required for dirinfo_type_t in or_options_t */
22#include "core/or/or.h"
24#include "core/or/versions.h"
25#include "app/config/config.h"
27
30
38
39/* Copied from config.c, we will refactor later in 29211. */
40#define REJECT(arg) \
41 STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
42#if defined(__GNUC__) && __GNUC__ <= 3
43#define COMPLAIN(args...) \
44 STMT_BEGIN log_warn(LD_CONFIG, args); STMT_END
45#else
46#define COMPLAIN(args, ...) \
47 STMT_BEGIN log_warn(LD_CONFIG, args, ##__VA_ARGS__); STMT_END
48#endif /* defined(__GNUC__) && __GNUC__ <= 3 */
49
50#define YES_IF_CHANGED_INT(opt) \
51 if (!CFG_EQ_INT(old_options, new_options, opt)) return 1;
52
53/** Return true iff we are configured to reject request under load for non
54 * relay connections. */
55bool
57{
58 return !!dirauth_get_options()->AuthDirRejectRequestsUnderLoad;
59}
60
61/**
62 * Legacy validation/normalization function for the dirauth mode options in
63 * options. Uses old_options as the previous options.
64 *
65 * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
66 * on error.
67 */
68int
70 or_options_t *options,
71 char **msg)
72{
73 if (BUG(!options))
74 return -1;
75
76 if (BUG(!msg))
77 return -1;
78
79 if (!authdir_mode(options))
80 return 0;
81
82 /* confirm that our address isn't broken, so we can complain now */
83 tor_addr_t tmp;
84 if (!find_my_address(options, AF_INET, LOG_WARN, &tmp, NULL, NULL))
85 REJECT("Failed to resolve/guess local address. See logs for details.");
86
87 if (!options->ContactInfo && !options->TestingTorNetwork)
88 REJECT("Authoritative directory servers must set ContactInfo");
89
90 if (options->UseEntryGuards) {
91 log_info(LD_CONFIG, "Authoritative directory servers can't set "
92 "UseEntryGuards. Disabling.");
93 options->UseEntryGuards = 0;
94 }
95 if (!options->DownloadExtraInfo && authdir_mode_v3(options)) {
96 log_info(LD_CONFIG, "Authoritative directories always try to download "
97 "extra-info documents. Setting DownloadExtraInfo.");
98 options->DownloadExtraInfo = 1;
99 }
100 if (!(options->BridgeAuthoritativeDir ||
101 options->V3AuthoritativeDir))
102 REJECT("AuthoritativeDir is set, but none of "
103 "(Bridge/V3)AuthoritativeDir is set.");
104
105 /* If we have a v3bandwidthsfile and it's broken, complain on startup */
106 if (options->V3BandwidthsFile && !old_options) {
108 NULL);
109 }
110 /* same for guardfraction file */
111 if (options->GuardfractionFile && !old_options) {
113 }
114
115 if (!options->DirPort_set)
116 REJECT("Running as authoritative directory, but no DirPort set.");
117
118 if (!options->ORPort_set)
119 REJECT("Running as authoritative directory, but no ORPort set.");
120
121 if (options->ClientOnly)
122 REJECT("Running as authoritative directory, but ClientOnly also set.");
123
124 return 0;
125}
126
127/**
128 * Legacy validation/normalization function for the dirauth schedule options
129 * in options. Uses old_options as the previous options.
130 *
131 * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
132 * on error.
133 */
134int
136 or_options_t *options,
137 char **msg)
138{
139 (void)old_options;
140
141 if (BUG(!options))
142 return -1;
143
144 if (BUG(!msg))
145 return -1;
146
147 if (!authdir_mode_v3(options))
148 return 0;
149
150 if (options->V3AuthVoteDelay + options->V3AuthDistDelay >=
151 options->V3AuthVotingInterval/2) {
152 REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than half "
153 "V3AuthVotingInterval");
154 }
155
156 if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS) {
157 if (options->TestingTorNetwork) {
159 REJECT("V3AuthVoteDelay is way too low.");
160 } else {
161 COMPLAIN("V3AuthVoteDelay is very low. "
162 "This may lead to failure to vote for a consensus.");
163 }
164 } else {
165 REJECT("V3AuthVoteDelay is way too low.");
166 }
167 }
168
169 if (options->V3AuthDistDelay < MIN_DIST_SECONDS) {
170 if (options->TestingTorNetwork) {
172 REJECT("V3AuthDistDelay is way too low.");
173 } else {
174 COMPLAIN("V3AuthDistDelay is very low. "
175 "This may lead to missing votes in a consensus.");
176 }
177 } else {
178 REJECT("V3AuthDistDelay is way too low.");
179 }
180 }
181
182 if (options->V3AuthNIntervalsValid < 2)
183 REJECT("V3AuthNIntervalsValid must be at least 2.");
184
186 if (options->TestingTorNetwork) {
188 /* Unreachable, covered by earlier checks */
189 REJECT("V3AuthVotingInterval is insanely low."); /* LCOV_EXCL_LINE */
190 } else {
191 COMPLAIN("V3AuthVotingInterval is very low. "
192 "This may lead to failure to synchronise for a consensus.");
193 }
194 } else {
195 REJECT("V3AuthVotingInterval is insanely low.");
196 }
197 } else if (options->V3AuthVotingInterval > 24*60*60) {
198 REJECT("V3AuthVotingInterval is insanely high.");
199 } else if (((24*60*60) % options->V3AuthVotingInterval) != 0) {
200 COMPLAIN("V3AuthVotingInterval does not divide evenly into 24 hours.");
201 }
202
203 return 0;
204}
205
206/**
207 * Legacy validation/normalization function for the dirauth testing options
208 * in options. Uses old_options as the previous options.
209 *
210 * Returns 0 on success, returns -1 and sets *msg to a newly allocated string
211 * on error.
212 */
213int
215 or_options_t *options,
216 char **msg)
217{
218 (void)old_options;
219
220 if (BUG(!options))
221 return -1;
222
223 if (BUG(!msg))
224 return -1;
225
226 if (!authdir_mode(options))
227 return 0;
228
229 if (!authdir_mode_v3(options))
230 return 0;
231
233 < MIN_VOTE_INTERVAL_TESTING_INITIAL) {
234 REJECT("TestingV3AuthInitialVotingInterval is insanely low.");
235 } else if (((30*60) % options->TestingV3AuthInitialVotingInterval) != 0) {
236 REJECT("TestingV3AuthInitialVotingInterval does not divide evenly into "
237 "30 minutes.");
238 }
239
241 REJECT("TestingV3AuthInitialVoteDelay is way too low.");
242 }
243
245 REJECT("TestingV3AuthInitialDistDelay is way too low.");
246 }
247
248 if (options->TestingV3AuthInitialVoteDelay +
251 REJECT("TestingV3AuthInitialVoteDelay plus TestingV3AuthInitialDistDelay "
252 "must be less than TestingV3AuthInitialVotingInterval");
253 }
254
255 if (options->TestingV3AuthVotingStartOffset >
257 options->V3AuthVotingInterval)) {
258 REJECT("TestingV3AuthVotingStartOffset is higher than the voting "
259 "interval.");
260 } else if (options->TestingV3AuthVotingStartOffset < 0) {
261 REJECT("TestingV3AuthVotingStartOffset must be non-negative.");
262 }
263
264 return 0;
265}
266
267/**
268 * Return true if changing the configuration from <b>old</b> to <b>new</b>
269 * affects the timing of the voting subsystem
270 */
271static int
273 const or_options_t *new_options)
274{
275 tor_assert(old_options);
276 tor_assert(new_options);
277
278 if (authdir_mode_v3(old_options) != authdir_mode_v3(new_options))
279 return 1;
280 if (! authdir_mode_v3(new_options))
281 return 0;
282
283 YES_IF_CHANGED_INT(V3AuthVotingInterval);
284 YES_IF_CHANGED_INT(V3AuthVoteDelay);
285 YES_IF_CHANGED_INT(V3AuthDistDelay);
286 YES_IF_CHANGED_INT(TestingV3AuthInitialVotingInterval);
287 YES_IF_CHANGED_INT(TestingV3AuthInitialVoteDelay);
288 YES_IF_CHANGED_INT(TestingV3AuthInitialDistDelay);
289 YES_IF_CHANGED_INT(TestingV3AuthVotingStartOffset);
290
291 return 0;
292}
293
294/** Fetch the active option list, and take dirauth actions based on it. All of
295 * the things we do should survive being done repeatedly. If present,
296 * <b>old_options</b> contains the previous value of the options.
297 *
298 * Return 0 if all goes well, return -1 if it's time to die.
299 *
300 * Note: We haven't moved all the "act on new configuration" logic
301 * into the options_act* functions yet. Some is still in do_hup() and other
302 * places.
303 */
304int
306{
307 const or_options_t *options = get_options();
308
309 /* We may need to reschedule some dirauth stuff if our status changed. */
310 if (old_options) {
311 if (options_transition_affects_dirauth_timing(old_options, options)) {
312 dirauth_sched_recalculate_timing(options, time(NULL));
313 reschedule_dirvote(options);
314 }
315 }
316
317 return 0;
318}
319
320/** Fetch the active option list, and take dirauth mtbf actions based on it.
321 * All of the things we do should survive being done repeatedly. If present,
322 * <b>old_options</b> contains the previous value of the options.
323 *
324 * Must be called immediately after a successful or_state_load().
325 *
326 * Return 0 if all goes well, return -1 if it's time to die.
327 *
328 * Note: We haven't moved all the "act on new configuration" logic
329 * into the options_act* functions yet. Some is still in do_hup() and other
330 * places.
331 */
332int
334{
335 (void)old_options;
336
337 const or_options_t *options = get_options();
338 int running_tor = options->command == CMD_RUN_TOR;
339
340 if (!authdir_mode(options))
341 return 0;
342
343 /* Load dirauth state */
344 if (running_tor) {
345 rep_hist_load_mtbf_data(time(NULL));
346 }
347
348 return 0;
349}
350
351/** Fetch the active option list, and take dirauth statistics actions based
352 * on it. All of the things we do should survive being done repeatedly. If
353 * present, <b>old_options</b> contains the previous value of the options.
354 *
355 * Sets <b>*print_notice_out</b> if we enabled stats, and need to print
356 * a stats log using options_act_relay_stats_msg().
357 *
358 * Return 0 if all goes well, return -1 if it's time to die.
359 *
360 * Note: We haven't moved all the "act on new configuration" logic
361 * into the options_act* functions yet. Some is still in do_hup() and other
362 * places.
363 */
364int
366 bool *print_notice_out)
367{
368 if (BUG(!print_notice_out))
369 return -1;
370
371 const or_options_t *options = get_options();
372
373 if (authdir_mode_bridge(options)) {
374 time_t now = time(NULL);
375 int print_notice = 0;
376
377 if (!old_options || !authdir_mode_bridge(old_options)) {
379 print_notice = 1;
380 }
381 if (print_notice)
382 *print_notice_out = 1;
383 }
384
385 /* If we used to have statistics enabled but we just disabled them,
386 stop gathering them. */
387 if (old_options && authdir_mode_bridge(old_options) &&
388 !authdir_mode_bridge(options))
390
391 return 0;
392}
393
394/**
395 * Make any necessary modifications to a dirauth_options_t that occur
396 * before validation. On success return 0; on failure return -1 and
397 * set *<b>msg_out</b> to a newly allocated error string.
398 **/
399static int
400dirauth_options_pre_normalize(void *arg, char **msg_out)
401{
402 dirauth_options_t *options = arg;
403 (void)msg_out;
404
405 if (!options->RecommendedClientVersions)
408 if (!options->RecommendedServerVersions)
411
413 "AuthDirFastGuarantee", msg_out) < 0)
414 return -1;
416 "AuthDirGuardBWGuarantee", msg_out) < 0)
417 return -1;
418
419 return 0;
420}
421
422/**
423 * Check whether a dirauth_options_t is correct.
424 *
425 * On success return 0; on failure return -1 and set *<b>msg_out</b> to a
426 * newly allocated error string.
427 **/
428static int
429dirauth_options_validate(const void *arg, char **msg)
430{
431 const dirauth_options_t *options = arg;
432 tor_version_t minimal_accepted_server_version, recommended_version;
433
435 (!options->RecommendedClientVersions ||
436 !options->RecommendedServerVersions)) {
437 REJECT("Versioning authoritative dir servers must set "
438 "Recommended*Versions.");
439 }
440
441 if (options->AuthDirVoteGuardBwThresholdFraction > 1.0 ||
443 REJECT("Guard bandwdith threshold fraction is invalid.");
444 }
445
447 &minimal_accepted_server_version) != 0) {
448 REJECT("Invalid MinimalAcceptedServerVersion");
449 }
450
452 &recommended_version) == 0,
453 "We failed to parse our own version");
454 if (tor_version_compare(&recommended_version,
455 &minimal_accepted_server_version) < 0) {
456 REJECT("MinimalAcceptedServerVersion wants to reject the version "
457 "this node is running");
458 }
459
460 char *recommended_versions;
461 int found_recommended_rejected_version = 0;
462 /* Call these functions to produce warnings only. */
463 recommended_versions = format_recommended_version_list(
464 options->RecommendedClientVersions, 1);
465 tor_free(recommended_versions);
466
467 recommended_versions = format_recommended_version_list(
468 options->RecommendedServerVersions, 1);
469
470 smartlist_t *version_sl = smartlist_new();
471 smartlist_split_string(version_sl, recommended_versions, ",",
472 SPLIT_SKIP_SPACE, 0);
473 SMARTLIST_FOREACH_BEGIN(version_sl, const char *, version) {
474 if (version[0] != '\0' && tor_version_parse(version,
475 &recommended_version) != 0) {
476 COMPLAIN("Found unparseable version in RecommendedServerVersions");
477 continue;
478 }
479
480 if (tor_version_compare(&recommended_version,
481 &minimal_accepted_server_version) < 0) {
482 found_recommended_rejected_version = 1;
483 break;
484 }
485 } SMARTLIST_FOREACH_END(version);
486
487 SMARTLIST_FOREACH(version_sl, char *, version, tor_free(version));
488 smartlist_free(version_sl);
489 tor_free(recommended_versions);
490 if (found_recommended_rejected_version)
491 REJECT("MinimalAcceptedServerVersion wants to reject a recommended "
492 "version");
493
494 if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) {
495 COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high.");
496 }
497
498 return 0;
499}
500
501/* Declare the options field table for dirauth_options */
502#define CONF_CONTEXT TABLE
504#undef CONF_CONTEXT
505
506/** Magic number for dirauth_options_t. */
507#define DIRAUTH_OPTIONS_MAGIC 0x41757448
508
509/**
510 * Declare the configuration options for the dirauth module.
511 **/
513 .size = sizeof(dirauth_options_t),
514 .magic = { "dirauth_options_t",
516 offsetof(dirauth_options_t, magic) },
517 .vars = dirauth_options_t_vars,
518
519 .pre_normalize_fn = dirauth_options_pre_normalize,
520 .validate_fn = dirauth_options_validate
521};
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:2987
const or_options_t * get_options(void)
Definition: config.c:944
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:4445
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:56
Master header file for Tor-specific functionality.
void rep_hist_desc_stats_term(void)
Definition: rephist.c:2117
int rep_hist_load_mtbf_data(time_t now)
Definition: rephist.c:1181
void rep_hist_desc_stats_init(time_t now)
Definition: rephist.c:2094
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.
smartlist_t * smartlist_new(void)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, int flags, int max)
MEMUNIT AuthDirGuardBWGuarantee
DOUBLE AuthDirVoteGuardBwThresholdFraction
STRING MinimalAcceptedServerVersion
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
Parsed Tor version structure.
Header for version.c.
const char * get_short_version(void)
Definition: version.c:56
#define tor_assert(expr)
Definition: util_bug.h:103
int tor_version_compare(tor_version_t *a, tor_version_t *b)
Definition: versions.c:315
int tor_version_parse(const char *s, tor_version_t *out)
Definition: versions.c:206
Header file for versions.c.
void dirauth_sched_recalculate_timing(const or_options_t *options, time_t now)
Header file for voting_schedule.c.