Line data Source code
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"
14 : #include "feature/dirauth/dirauth_config.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 : #include "app/config/resolve_addr.h"
24 :
25 : #include "feature/dirauth/voting_schedule.h"
26 : #include "feature/stats/rephist.h"
27 :
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"
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
53 6 : dirauth_should_reject_requests_under_load(void)
54 : {
55 6 : 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
66 553 : options_validate_dirauth_mode(const or_options_t *old_options,
67 : or_options_t *options,
68 : char **msg)
69 : {
70 553 : if (BUG(!options))
71 0 : return -1;
72 :
73 553 : if (BUG(!msg))
74 0 : return -1;
75 :
76 553 : if (!authdir_mode(options))
77 : return 0;
78 :
79 : /* confirm that our address isn't broken, so we can complain now */
80 71 : tor_addr_t tmp;
81 71 : if (!find_my_address(options, AF_INET, LOG_WARN, &tmp, NULL, NULL))
82 1 : REJECT("Failed to resolve/guess local address. See logs for details.");
83 :
84 70 : if (!options->ContactInfo && !options->TestingTorNetwork)
85 2 : REJECT("Authoritative directory servers must set ContactInfo");
86 :
87 68 : if (options->UseEntryGuards) {
88 66 : log_info(LD_CONFIG, "Authoritative directory servers can't set "
89 : "UseEntryGuards. Disabling.");
90 66 : options->UseEntryGuards = 0;
91 : }
92 68 : if (!options->DownloadExtraInfo && authdir_mode_v3(options)) {
93 46 : log_info(LD_CONFIG, "Authoritative directories always try to download "
94 : "extra-info documents. Setting DownloadExtraInfo.");
95 46 : options->DownloadExtraInfo = 1;
96 : }
97 68 : if (!(options->BridgeAuthoritativeDir ||
98 : options->V3AuthoritativeDir))
99 3 : 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 65 : if (options->V3BandwidthsFile && !old_options) {
104 1 : dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL, NULL,
105 : NULL);
106 : }
107 : /* same for guardfraction file */
108 65 : if (options->GuardfractionFile && !old_options) {
109 1 : dirserv_read_guardfraction_file(options->GuardfractionFile, NULL);
110 : }
111 :
112 65 : if (!options->DirPort_set)
113 2 : REJECT("Running as authoritative directory, but no DirPort set.");
114 :
115 63 : if (!options->ORPort_set)
116 2 : REJECT("Running as authoritative directory, but no ORPort set.");
117 :
118 61 : if (options->ClientOnly)
119 2 : 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
132 440 : options_validate_dirauth_schedule(const or_options_t *old_options,
133 : or_options_t *options,
134 : char **msg)
135 : {
136 440 : (void)old_options;
137 :
138 440 : if (BUG(!options))
139 0 : return -1;
140 :
141 440 : if (BUG(!msg))
142 0 : return -1;
143 :
144 440 : if (!authdir_mode_v3(options))
145 : return 0;
146 :
147 39 : if (options->V3AuthVoteDelay + options->V3AuthDistDelay >=
148 39 : options->V3AuthVotingInterval/2) {
149 2 : REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than half "
150 : "V3AuthVotingInterval");
151 : }
152 :
153 37 : if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS) {
154 3 : if (options->TestingTorNetwork) {
155 2 : if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS_TESTING) {
156 2 : 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 1 : REJECT("V3AuthVoteDelay is way too low.");
163 : }
164 : }
165 :
166 34 : if (options->V3AuthDistDelay < MIN_DIST_SECONDS) {
167 2 : if (options->TestingTorNetwork) {
168 1 : if (options->V3AuthDistDelay < MIN_DIST_SECONDS_TESTING) {
169 1 : 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 1 : REJECT("V3AuthDistDelay is way too low.");
176 : }
177 : }
178 :
179 32 : if (options->V3AuthNIntervalsValid < 2)
180 1 : REJECT("V3AuthNIntervalsValid must be at least 2.");
181 :
182 31 : if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL) {
183 4 : if (options->TestingTorNetwork) {
184 3 : 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 3 : COMPLAIN("V3AuthVotingInterval is very low. "
189 : "This may lead to failure to synchronise for a consensus.");
190 : }
191 : } else {
192 1 : REJECT("V3AuthVotingInterval is insanely low.");
193 : }
194 27 : } else if (options->V3AuthVotingInterval > 24*60*60) {
195 1 : REJECT("V3AuthVotingInterval is insanely high.");
196 26 : } else if (((24*60*60) % options->V3AuthVotingInterval) != 0) {
197 1 : 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
211 401 : options_validate_dirauth_testing(const or_options_t *old_options,
212 : or_options_t *options,
213 : char **msg)
214 : {
215 401 : (void)old_options;
216 :
217 401 : if (BUG(!options))
218 0 : return -1;
219 :
220 401 : if (BUG(!msg))
221 0 : return -1;
222 :
223 401 : if (!authdir_mode(options))
224 : return 0;
225 :
226 36 : if (!authdir_mode_v3(options))
227 : return 0;
228 :
229 29 : if (options->TestingV3AuthInitialVotingInterval
230 : < MIN_VOTE_INTERVAL_TESTING_INITIAL) {
231 1 : REJECT("TestingV3AuthInitialVotingInterval is insanely low.");
232 28 : } else if (((30*60) % options->TestingV3AuthInitialVotingInterval) != 0) {
233 1 : REJECT("TestingV3AuthInitialVotingInterval does not divide evenly into "
234 : "30 minutes.");
235 : }
236 :
237 27 : if (options->TestingV3AuthInitialVoteDelay < MIN_VOTE_SECONDS_TESTING) {
238 1 : REJECT("TestingV3AuthInitialVoteDelay is way too low.");
239 : }
240 :
241 26 : if (options->TestingV3AuthInitialDistDelay < MIN_DIST_SECONDS_TESTING) {
242 1 : REJECT("TestingV3AuthInitialDistDelay is way too low.");
243 : }
244 :
245 25 : if (options->TestingV3AuthInitialVoteDelay +
246 : options->TestingV3AuthInitialDistDelay >=
247 : options->TestingV3AuthInitialVotingInterval) {
248 1 : REJECT("TestingV3AuthInitialVoteDelay plus TestingV3AuthInitialDistDelay "
249 : "must be less than TestingV3AuthInitialVotingInterval");
250 : }
251 :
252 24 : if (options->TestingV3AuthVotingStartOffset >
253 24 : MIN(options->TestingV3AuthInitialVotingInterval,
254 : options->V3AuthVotingInterval)) {
255 1 : REJECT("TestingV3AuthVotingStartOffset is higher than the voting "
256 : "interval.");
257 23 : } else if (options->TestingV3AuthVotingStartOffset < 0) {
258 1 : 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
269 0 : options_transition_affects_dirauth_timing(const or_options_t *old_options,
270 : const or_options_t *new_options)
271 : {
272 0 : tor_assert(old_options);
273 0 : tor_assert(new_options);
274 :
275 0 : if (authdir_mode_v3(old_options) != authdir_mode_v3(new_options))
276 : return 1;
277 0 : if (! authdir_mode_v3(new_options))
278 : return 0;
279 :
280 0 : YES_IF_CHANGED_INT(V3AuthVotingInterval);
281 0 : YES_IF_CHANGED_INT(V3AuthVoteDelay);
282 0 : YES_IF_CHANGED_INT(V3AuthDistDelay);
283 0 : YES_IF_CHANGED_INT(TestingV3AuthInitialVotingInterval);
284 0 : YES_IF_CHANGED_INT(TestingV3AuthInitialVoteDelay);
285 0 : YES_IF_CHANGED_INT(TestingV3AuthInitialDistDelay);
286 0 : 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
302 4 : options_act_dirauth(const or_options_t *old_options)
303 : {
304 4 : const or_options_t *options = get_options();
305 :
306 : /* We may need to reschedule some dirauth stuff if our status changed. */
307 4 : if (old_options) {
308 0 : if (options_transition_affects_dirauth_timing(old_options, options)) {
309 0 : dirauth_sched_recalculate_timing(options, time(NULL));
310 0 : reschedule_dirvote(options);
311 : }
312 : }
313 :
314 4 : 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
330 4 : options_act_dirauth_mtbf(const or_options_t *old_options)
331 : {
332 4 : (void)old_options;
333 :
334 4 : const or_options_t *options = get_options();
335 4 : int running_tor = options->command == CMD_RUN_TOR;
336 :
337 4 : if (!authdir_mode(options))
338 : return 0;
339 :
340 : /* Load dirauth state */
341 0 : if (running_tor) {
342 0 : 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
362 4 : options_act_dirauth_stats(const or_options_t *old_options,
363 : bool *print_notice_out)
364 : {
365 4 : if (BUG(!print_notice_out))
366 0 : return -1;
367 :
368 4 : const or_options_t *options = get_options();
369 :
370 4 : if (authdir_mode_bridge(options)) {
371 0 : time_t now = time(NULL);
372 0 : int print_notice = 0;
373 :
374 0 : if (!old_options || !authdir_mode_bridge(old_options)) {
375 0 : rep_hist_desc_stats_init(now);
376 0 : print_notice = 1;
377 : }
378 0 : if (print_notice)
379 0 : *print_notice_out = 1;
380 : }
381 :
382 : /* If we used to have statistics enabled but we just disabled them,
383 : stop gathering them. */
384 4 : if (old_options && authdir_mode_bridge(old_options) &&
385 0 : !authdir_mode_bridge(options))
386 0 : rep_hist_desc_stats_term();
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 580 : dirauth_options_pre_normalize(void *arg, char **msg_out)
398 : {
399 580 : dirauth_options_t *options = arg;
400 580 : (void)msg_out;
401 :
402 580 : if (!options->RecommendedClientVersions)
403 577 : options->RecommendedClientVersions =
404 577 : config_lines_dup(options->RecommendedVersions);
405 580 : if (!options->RecommendedServerVersions)
406 577 : options->RecommendedServerVersions =
407 577 : config_lines_dup(options->RecommendedVersions);
408 :
409 580 : if (config_ensure_bandwidth_cap(&options->AuthDirFastGuarantee,
410 : "AuthDirFastGuarantee", msg_out) < 0)
411 : return -1;
412 579 : if (config_ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee,
413 : "AuthDirGuardBWGuarantee", msg_out) < 0)
414 1 : 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 578 : dirauth_options_validate(const void *arg, char **msg)
427 : {
428 578 : const dirauth_options_t *options = arg;
429 :
430 578 : if (options->VersioningAuthoritativeDirectory &&
431 3 : (!options->RecommendedClientVersions ||
432 2 : !options->RecommendedServerVersions)) {
433 2 : REJECT("Versioning authoritative dir servers must set "
434 : "Recommended*Versions.");
435 : }
436 :
437 576 : char *t;
438 : /* Call these functions to produce warnings only. */
439 576 : t = format_recommended_version_list(options->RecommendedClientVersions, 1);
440 576 : tor_free(t);
441 576 : t = format_recommended_version_list(options->RecommendedServerVersions, 1);
442 576 : tor_free(t);
443 :
444 576 : if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) {
445 0 : 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
453 : #include "feature/dirauth/dirauth_options.inc"
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 : **/
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,
468 :
469 : .pre_normalize_fn = dirauth_options_pre_normalize,
470 : .validate_fn = dirauth_options_validate
471 : };
|