dirauth_config.c (16687B)
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 #include "lib/version/torversion.h" 20 21 /* Required for dirinfo_type_t in or_options_t */ 22 #include "core/or/or.h" 23 #include "core/or/tor_version_st.h" 24 #include "core/or/versions.h" 25 #include "app/config/config.h" 26 #include "app/config/resolve_addr.h" 27 28 #include "feature/dirauth/voting_schedule.h" 29 #include "feature/stats/rephist.h" 30 31 #include "feature/dirauth/authmode.h" 32 #include "feature/dirauth/bwauth.h" 33 #include "feature/dirauth/dirauth_periodic.h" 34 #include "feature/dirauth/dirauth_sys.h" 35 #include "feature/dirauth/dirvote.h" 36 #include "feature/dirauth/guardfraction.h" 37 #include "feature/dirauth/dirauth_options_st.h" 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. */ 55 bool 56 dirauth_should_reject_requests_under_load(void) 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 */ 68 int 69 options_validate_dirauth_mode(const or_options_t *old_options, 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) { 107 dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL, NULL, 108 NULL); 109 } 110 /* same for guardfraction file */ 111 if (options->GuardfractionFile && !old_options) { 112 dirserv_read_guardfraction_file(options->GuardfractionFile, NULL); 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 */ 134 int 135 options_validate_dirauth_schedule(const or_options_t *old_options, 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) { 158 if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS_TESTING) { 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) { 171 if (options->V3AuthDistDelay < MIN_DIST_SECONDS_TESTING) { 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 185 if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL) { 186 if (options->TestingTorNetwork) { 187 if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL_TESTING) { 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 */ 213 int 214 options_validate_dirauth_testing(const or_options_t *old_options, 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 232 if (options->TestingV3AuthInitialVotingInterval 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 240 if (options->TestingV3AuthInitialVoteDelay < MIN_VOTE_SECONDS_TESTING) { 241 REJECT("TestingV3AuthInitialVoteDelay is way too low."); 242 } 243 244 if (options->TestingV3AuthInitialDistDelay < MIN_DIST_SECONDS_TESTING) { 245 REJECT("TestingV3AuthInitialDistDelay is way too low."); 246 } 247 248 if (options->TestingV3AuthInitialVoteDelay + 249 options->TestingV3AuthInitialDistDelay >= 250 options->TestingV3AuthInitialVotingInterval) { 251 REJECT("TestingV3AuthInitialVoteDelay plus TestingV3AuthInitialDistDelay " 252 "must be less than TestingV3AuthInitialVotingInterval"); 253 } 254 255 if (options->TestingV3AuthVotingStartOffset > 256 MIN(options->TestingV3AuthInitialVotingInterval, 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 */ 271 static int 272 options_transition_affects_dirauth_timing(const or_options_t *old_options, 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 */ 304 int 305 options_act_dirauth(const or_options_t *old_options) 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 */ 332 int 333 options_act_dirauth_mtbf(const or_options_t *old_options) 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 */ 364 int 365 options_act_dirauth_stats(const or_options_t *old_options, 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)) { 378 rep_hist_desc_stats_init(now); 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)) 389 rep_hist_desc_stats_term(); 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 **/ 399 static int 400 dirauth_options_pre_normalize(void *arg, char **msg_out) 401 { 402 dirauth_options_t *options = arg; 403 (void)msg_out; 404 405 if (!options->RecommendedClientVersions) 406 options->RecommendedClientVersions = 407 config_lines_dup(options->RecommendedVersions); 408 if (!options->RecommendedServerVersions) 409 options->RecommendedServerVersions = 410 config_lines_dup(options->RecommendedVersions); 411 412 if (config_ensure_bandwidth_cap(&options->AuthDirFastGuarantee, 413 "AuthDirFastGuarantee", msg_out) < 0) 414 return -1; 415 if (config_ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee, 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 **/ 428 static int 429 dirauth_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 434 if (options->VersioningAuthoritativeDirectory && 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 || 442 options->AuthDirVoteGuardBwThresholdFraction < 0.0) { 443 REJECT("Guard bandwdith threshold fraction is invalid."); 444 } 445 446 if (tor_version_parse(options->MinimalAcceptedServerVersion, 447 &minimal_accepted_server_version) != 0) { 448 REJECT("Invalid MinimalAcceptedServerVersion"); 449 } 450 451 tor_assertf(tor_version_parse(get_short_version(), 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 503 #include "feature/dirauth/dirauth_options.inc" 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 **/ 512 const config_format_t dirauth_options_fmt = { 513 .size = sizeof(dirauth_options_t), 514 .magic = { "dirauth_options_t", 515 DIRAUTH_OPTIONS_MAGIC, 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 };