diff options
Diffstat (limited to 'src/app/config/config.c')
-rw-r--r-- | src/app/config/config.c | 1561 |
1 files changed, 115 insertions, 1446 deletions
diff --git a/src/app/config/config.c b/src/app/config/config.c index 61a4021edc..1b697e73fc 100644 --- a/src/app/config/config.c +++ b/src/app/config/config.c @@ -40,9 +40,11 @@ * running. * <li>options_transition_affects_workers(), in case changes in the option * might require Tor to relaunch or reconfigure its worker threads. + * (This function is now in the relay module.) * <li>options_transition_affects_descriptor(), in case changes in the * option might require a Tor relay to build and publish a new server * descriptor. + * (This function is now in the relay module.) * <li>options_act() and/or options_act_reversible(), in case there's some * action that needs to be taken immediately based on the option's * value. @@ -67,17 +69,14 @@ #include "app/main/main.h" #include "app/main/subsysmgr.h" #include "core/mainloop/connection.h" -#include "core/mainloop/cpuworker.h" #include "core/mainloop/mainloop.h" #include "core/mainloop/netstatus.h" #include "core/or/channel.h" -#include "core/or/circuitbuild.h" #include "core/or/circuitlist.h" #include "core/or/circuitmux.h" #include "core/or/circuitmux_ewma.h" #include "core/or/circuitstats.h" #include "core/or/connection_edge.h" -#include "core/or/connection_or.h" #include "core/or/dos.h" #include "core/or/policies.h" #include "core/or/relay.h" @@ -89,11 +88,7 @@ #include "feature/control/control.h" #include "feature/control/control_auth.h" #include "feature/control/control_events.h" -#include "feature/dirauth/bwauth.h" -#include "feature/dirauth/guardfraction.h" -#include "feature/dircache/consdiffmgr.h" #include "feature/dircache/dirserv.h" -#include "feature/dircommon/voting_schedule.h" #include "feature/hibernate/hibernate.h" #include "feature/hs/hs_config.h" #include "feature/nodelist/dirlist.h" @@ -105,12 +100,12 @@ #include "feature/relay/dns.h" #include "feature/relay/ext_orport.h" #include "feature/relay/routermode.h" +#include "feature/relay/relay_config.h" +#include "feature/relay/transport_config.h" #include "feature/rend/rendclient.h" #include "feature/rend/rendservice.h" #include "lib/geoip/geoip.h" #include "feature/stats/geoip_stats.h" -#include "feature/stats/predict_ports.h" -#include "feature/stats/rephist.h" #include "lib/compress/compress.h" #include "lib/confmgt/structvar.h" #include "lib/crypt_ops/crypto_init.h" @@ -157,10 +152,8 @@ #include "lib/fs/conffile.h" #include "lib/evloop/procmon.h" -#include "feature/dirauth/dirvote.h" -#include "feature/dirauth/dirauth_periodic.h" -#include "feature/dirauth/recommend_pkg.h" #include "feature/dirauth/authmode.h" +#include "feature/dirauth/dirauth_config.h" #include "core/or/connection_st.h" #include "core/or/port_cfg_st.h" @@ -827,23 +820,9 @@ static char *get_windows_conf_root(void); static int options_check_transition_cb(const void *old, const void *new, char **msg); -static int options_transition_affects_workers( - const or_options_t *old_options, const or_options_t *new_options); -static int options_transition_affects_descriptor( - const or_options_t *old_options, const or_options_t *new_options); -static int options_transition_affects_dirauth_timing( - const or_options_t *old_options, const or_options_t *new_options); -static int normalize_nickname_list(config_line_t **normalized_out, - const config_line_t *lst, const char *name, - char **msg); -static char *get_bindaddr_from_transport_listen_line(const char *line, - const char *transport); static int parse_ports(or_options_t *options, int validate_only, char **msg_out, int *n_ports_out, int *world_writable_control_socket); -static int check_server_ports(const smartlist_t *ports, - const or_options_t *options, - int *num_low_ports_out); static int validate_data_directories(or_options_t *options); static int write_configuration_file(const char *fname, const or_options_t *options); @@ -898,8 +877,6 @@ static char *torrc_fname = NULL; static char *torrc_defaults_fname = NULL; /** Result of parsing the command line. */ static parsed_cmdline_t *global_cmdline = NULL; -/** Contents of most recently read DirPortFrontPage file. */ -static char *global_dirfrontpagecontents = NULL; /** List of port_cfg_t for all configured ports. */ static smartlist_t *configured_ports = NULL; /** True iff we're currently validating options, and any calls to @@ -926,13 +903,6 @@ get_options_mgr(void) config_check_toplevel_magic(get_options_mgr(), (opt)); \ STMT_END -/** Return the contents of our frontpage string, or NULL if not configured. */ -MOCK_IMPL(const char*, -get_dirportfrontpage, (void)) -{ - return global_dirfrontpagecontents; -} - /** Returns the currently configured options. */ MOCK_IMPL(or_options_t *, get_options_mutable, (void)) @@ -1087,7 +1057,6 @@ config_free_all(void) tor_free(torrc_fname); tor_free(torrc_defaults_fname); - tor_free(global_dirfrontpagecontents); cleanup_protocol_warning_severity_level(); @@ -1510,6 +1479,7 @@ options_act_reversible,(const or_options_t *old_options, char **msg)) } /* Adjust the port configuration so we can launch listeners. */ + /* 31851: some ports are relay-only */ if (parse_ports(options, 0, msg, &n_ports, NULL)) { if (!*msg) *msg = tor_strdup("Unexpected problem parsing port config"); @@ -1523,6 +1493,7 @@ options_act_reversible,(const or_options_t *old_options, char **msg)) * ports under 1024.) We don't want to rebind if we're hibernating or * shutting down. If networking is disabled, this will close all but the * control listeners, but disable those. */ + /* 31851: some listeners are relay-only */ if (!we_are_hibernating()) { if (retry_all_listeners(new_listeners, options->DisableNetwork) < 0) { *msg = tor_strdup("Failed to bind one of the listener ports."); @@ -1760,32 +1731,6 @@ options_need_geoip_info(const or_options_t *options, const char **reason_out) return bridge_usage || routerset_usage; } -/** Return the bandwidthrate that we are going to report to the authorities - * based on the config options. */ -uint32_t -get_effective_bwrate(const or_options_t *options) -{ - uint64_t bw = options->BandwidthRate; - if (bw > options->MaxAdvertisedBandwidth) - bw = options->MaxAdvertisedBandwidth; - if (options->RelayBandwidthRate > 0 && bw > options->RelayBandwidthRate) - bw = options->RelayBandwidthRate; - /* ensure_bandwidth_cap() makes sure that this cast can't overflow. */ - return (uint32_t)bw; -} - -/** Return the bandwidthburst that we are going to report to the authorities - * based on the config options. */ -uint32_t -get_effective_bwburst(const or_options_t *options) -{ - uint64_t bw = options->BandwidthBurst; - if (options->RelayBandwidthBurst > 0 && bw > options->RelayBandwidthBurst) - bw = options->RelayBandwidthBurst; - /* ensure_bandwidth_cap() makes sure that this cast can't overflow. */ - return (uint32_t)bw; -} - /* Used in the various options_transition_affects* functions. */ #define YES_IF_CHANGED_BOOL(opt) \ if (!CFG_EQ_BOOL(old_options, new_options, opt)) return 1; @@ -1828,32 +1773,6 @@ options_transition_affects_guards(const or_options_t *old_options, return 0; } -/** - * Return true if changing the configuration from <b>old</b> to <b>new</b> - * affects the timing of the voting subsystem - */ -static int -options_transition_affects_dirauth_timing(const or_options_t *old_options, - const or_options_t *new_options) -{ - tor_assert(old_options); - tor_assert(new_options); - - if (authdir_mode_v3(old_options) != authdir_mode_v3(new_options)) - return 1; - if (! authdir_mode_v3(new_options)) - return 0; - YES_IF_CHANGED_INT(V3AuthVotingInterval); - YES_IF_CHANGED_INT(V3AuthVoteDelay); - YES_IF_CHANGED_INT(V3AuthDistDelay); - YES_IF_CHANGED_INT(TestingV3AuthInitialVotingInterval); - YES_IF_CHANGED_INT(TestingV3AuthInitialVoteDelay); - YES_IF_CHANGED_INT(TestingV3AuthInitialDistDelay); - YES_IF_CHANGED_INT(TestingV3AuthVotingStartOffset); - - return 0; -} - /** Fetch the active option list, and take actions based on it. All of the * things we do should survive being done repeatedly. If present, * <b>old_options</b> contains the previous value of the options. @@ -1861,7 +1780,8 @@ options_transition_affects_dirauth_timing(const or_options_t *old_options, * Return 0 if all goes well, return -1 if it's time to die. * * Note: We haven't moved all the "act on new configuration" logic - * here yet. Some is still in do_hup() and other places. + * the options_act* functions yet. Some is still in do_hup() and other + * places. */ MOCK_IMPL(STATIC int, options_act,(const or_options_t *old_options)) @@ -1870,8 +1790,6 @@ options_act,(const or_options_t *old_options)) or_options_t *options = get_options_mutable(); int running_tor = options->command == CMD_RUN_TOR; char *msg=NULL; - const int transition_affects_workers = - old_options && options_transition_affects_workers(old_options, options); const int transition_affects_guards = old_options && options_transition_affects_guards(old_options, options); @@ -1929,19 +1847,6 @@ options_act,(const or_options_t *old_options)) "in a non-anonymous mode. It will provide NO ANONYMITY."); } - /* If we are a bridge with a pluggable transport proxy but no - Extended ORPort, inform the user that they are missing out. */ - if (server_mode(options) && options->ServerTransportPlugin && - !options->ExtORPort_lines) { - log_notice(LD_CONFIG, "We use pluggable transports but the Extended " - "ORPort is disabled. Tor and your pluggable transports proxy " - "communicate with each other via the Extended ORPort so it " - "is suggested you enable it: it will also allow your Bridge " - "to collect statistics about its clients that use pluggable " - "transports. Please enable it using the ExtORPort torrc option " - "(e.g. set 'ExtORPort auto')."); - } - if (options->Bridges) { mark_bridge_list(); for (cl = options->Bridges; cl; cl = cl->next) { @@ -1991,22 +1896,17 @@ options_act,(const or_options_t *old_options)) if (! or_state_loaded() && running_tor) { if (or_state_load()) return -1; - rep_hist_load_mtbf_data(time(NULL)); - } - - /* If we have an ExtORPort, initialize its auth cookie. */ - if (running_tor && - init_ext_or_cookie_authentication(!!options->ExtORPort_lines) < 0) { - log_warn(LD_CONFIG,"Error creating Extended ORPort cookie file."); - return -1; + if (options_act_dirauth_mtbf(options) < 0) + return -1; } + /* 31851: some of the code in these functions is relay-only */ mark_transport_list(); pt_prepare_proxy_list_for_config_read(); if (!options->DisableNetwork) { if (options->ClientTransportPlugin) { for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { - if (parse_transport_line(options, cl->value, 0, 0) < 0) { + if (pt_parse_transport_line(options, cl->value, 0, 0) < 0) { // LCOV_EXCL_START log_warn(LD_BUG, "Previously validated ClientTransportPlugin line " @@ -2016,20 +1916,11 @@ options_act,(const or_options_t *old_options)) } } } - - if (options->ServerTransportPlugin && server_mode(options)) { - for (cl = options->ServerTransportPlugin; cl; cl = cl->next) { - if (parse_transport_line(options, cl->value, 0, 1) < 0) { - // LCOV_EXCL_START - log_warn(LD_BUG, - "Previously validated ServerTransportPlugin line " - "could not be added!"); - return -1; - // LCOV_EXCL_STOP - } - } - } } + + if (options_act_server_transport(old_options) < 0) + return -1; + sweep_transport_list(); sweep_proxy_list(); @@ -2050,16 +1941,8 @@ options_act,(const or_options_t *old_options)) finish_daemon(options->DataDirectory); } - /* We want to reinit keys as needed before we do much of anything else: - keys are important, and other things can depend on them. */ - if (transition_affects_workers || - (options->V3AuthoritativeDir && (!old_options || - !old_options->V3AuthoritativeDir))) { - if (init_keys() < 0) { - log_warn(LD_BUG,"Error initializing keys; exiting"); - return -1; - } - } + if (options_act_relay(old_options) < 0) + return -1; /* Write our PID to the PID file. If we do not have write permissions we * will log a warning and exit. */ @@ -2083,15 +1966,6 @@ options_act,(const or_options_t *old_options)) return -1; } - if (server_mode(options)) { - static int cdm_initialized = 0; - if (cdm_initialized == 0) { - cdm_initialized = 1; - consdiffmgr_configure(NULL); - consdiffmgr_validate(); - } - } - if (init_control_cookie_authentication(options->CookieAuthentication) < 0) { log_warn(LD_CONFIG,"Error creating control cookie authentication file."); return -1; @@ -2109,15 +1983,8 @@ options_act,(const or_options_t *old_options)) * might be a change of scheduler or parameter. */ scheduler_conf_changed(); - /* Set up accounting */ - if (accounting_parse_options(options, 0)<0) { - // LCOV_EXCL_START - log_warn(LD_BUG,"Error in previously validated accounting options"); + if (options_act_relay_accounting(old_options) < 0) return -1; - // LCOV_EXCL_STOP - } - if (accounting_is_enabled(options)) - configure_accounting(time(NULL)); /* Change the cell EWMA settings */ cmux_ewma_set_options(options, networkstatus_get_latest_consensus()); @@ -2141,6 +2008,7 @@ options_act,(const or_options_t *old_options)) tor_free(http_authenticator); } + /* 31851: OutboundBindAddressExit is relay-only */ if (parse_outbound_addresses(options, 0, &msg) < 0) { // LCOV_EXCL_START log_warn(LD_BUG, "Failed parsing previously validated outbound " @@ -2227,65 +2095,17 @@ options_act,(const or_options_t *old_options)) if (revise_automap_entries) addressmap_clear_invalid_automaps(options); -/* How long should we delay counting bridge stats after becoming a bridge? - * We use this so we don't count clients who used our bridge thinking it is - * a relay. If you change this, don't forget to change the log message - * below. It's 4 hours (the time it takes to stop being used by clients) - * plus some extra time for clock skew. */ -#define RELAY_BRIDGE_STATS_DELAY (6 * 60 * 60) - - if (! bool_eq(options->BridgeRelay, old_options->BridgeRelay)) { - int was_relay = 0; - if (options->BridgeRelay) { - time_t int_start = time(NULL); - if (config_lines_eq(old_options->ORPort_lines,options->ORPort_lines)) { - int_start += RELAY_BRIDGE_STATS_DELAY; - was_relay = 1; - } - geoip_bridge_stats_init(int_start); - log_info(LD_CONFIG, "We are acting as a bridge now. Starting new " - "GeoIP stats interval%s.", was_relay ? " in 6 " - "hours from now" : ""); - } else { - geoip_bridge_stats_term(); - log_info(LD_GENERAL, "We are no longer acting as a bridge. " - "Forgetting GeoIP stats."); - } - } - - if (transition_affects_workers) { - log_info(LD_GENERAL, - "Worker-related options changed. Rotating workers."); - const int server_mode_turned_on = - server_mode(options) && !server_mode(old_options); - const int dir_server_mode_turned_on = - dir_server_mode(options) && !dir_server_mode(old_options); - - if (server_mode_turned_on || dir_server_mode_turned_on) { - cpu_init(); - } + if (options_act_bridge_stats(old_options) < 0) + return -1; - if (server_mode_turned_on) { - ip_address_changed(0); - if (have_completed_a_circuit() || !any_predicted_circuits(time(NULL))) - inform_testing_reachability(); - } - cpuworkers_rotate_keyinfo(); - if (dns_reset()) - return -1; - } else { - if (dns_reset()) - return -1; - } + if (dns_reset()) + return -1; - if (options->PerConnBWRate != old_options->PerConnBWRate || - options->PerConnBWBurst != old_options->PerConnBWBurst) - connection_or_update_token_buckets(get_connection_array(), options); + if (options_act_relay_bandwidth(old_options) < 0) + return -1; if (options->BandwidthRate != old_options->BandwidthRate || - options->BandwidthBurst != old_options->BandwidthBurst || - options->RelayBandwidthRate != old_options->RelayBandwidthRate || - options->RelayBandwidthBurst != old_options->RelayBandwidthBurst) + options->BandwidthBurst != old_options->BandwidthBurst) connection_bucket_adjust(options); if (options->MainloopStats != old_options->MainloopStats) { @@ -2293,128 +2113,39 @@ options_act,(const or_options_t *old_options)) } } + /* 31851: These options are relay-only, but we need to disable them if we + * are in client mode. In 29211, we will disable all relay options in + * client mode. */ /* Only collect directory-request statistics on relays and bridges. */ options->DirReqStatistics = options->DirReqStatistics_option && server_mode(options); options->HiddenServiceStatistics = options->HiddenServiceStatistics_option && server_mode(options); - if (options->CellStatistics || options->DirReqStatistics || - options->EntryStatistics || options->ExitPortStatistics || - options->ConnDirectionStatistics || - options->HiddenServiceStatistics || - options->BridgeAuthoritativeDir) { - time_t now = time(NULL); - int print_notice = 0; - - /* Only collect other relay-only statistics on relays. */ - if (!public_server_mode(options)) { - options->CellStatistics = 0; - options->EntryStatistics = 0; - options->ConnDirectionStatistics = 0; - options->ExitPortStatistics = 0; - } - - if ((!old_options || !old_options->CellStatistics) && - options->CellStatistics) { - rep_hist_buffer_stats_init(now); - print_notice = 1; - } - if ((!old_options || !old_options->DirReqStatistics) && - options->DirReqStatistics) { - if (geoip_is_loaded(AF_INET)) { - geoip_dirreq_stats_init(now); - print_notice = 1; - } else { - /* disable statistics collection since we have no geoip file */ - options->DirReqStatistics = 0; - if (options->ORPort_set) - log_notice(LD_CONFIG, "Configured to measure directory request " - "statistics, but no GeoIP database found. " - "Please specify a GeoIP database using the " - "GeoIPFile option."); - } - } - if ((!old_options || !old_options->EntryStatistics) && - options->EntryStatistics && !should_record_bridge_info(options)) { - /* If we get here, we've started recording bridge info when we didn't - * do so before. Note that "should_record_bridge_info()" will - * always be false at this point, because of the earlier block - * that cleared EntryStatistics when public_server_mode() was false. - * We're leaving it in as defensive programming. */ - if (geoip_is_loaded(AF_INET) || geoip_is_loaded(AF_INET6)) { - geoip_entry_stats_init(now); - print_notice = 1; - } else { - options->EntryStatistics = 0; - log_notice(LD_CONFIG, "Configured to measure entry node " - "statistics, but no GeoIP database found. " - "Please specify a GeoIP database using the " - "GeoIPFile option."); - } - } - if ((!old_options || !old_options->ExitPortStatistics) && - options->ExitPortStatistics) { - rep_hist_exit_stats_init(now); - print_notice = 1; - } - if ((!old_options || !old_options->ConnDirectionStatistics) && - options->ConnDirectionStatistics) { - rep_hist_conn_stats_init(now); - } - if ((!old_options || !old_options->HiddenServiceStatistics) && - options->HiddenServiceStatistics) { - log_info(LD_CONFIG, "Configured to measure hidden service statistics."); - rep_hist_hs_stats_init(now); - } - if ((!old_options || !old_options->BridgeAuthoritativeDir) && - options->BridgeAuthoritativeDir) { - rep_hist_desc_stats_init(now); - print_notice = 1; - } - if (print_notice) - log_notice(LD_CONFIG, "Configured to measure statistics. Look for " - "the *-stats files that will first be written to the " - "data directory in 24 hours from now."); - } - - /* If we used to have statistics enabled but we just disabled them, - stop gathering them. */ - if (old_options && old_options->CellStatistics && - !options->CellStatistics) - rep_hist_buffer_stats_term(); - if (old_options && old_options->DirReqStatistics && - !options->DirReqStatistics) - geoip_dirreq_stats_term(); - if (old_options && old_options->EntryStatistics && - !options->EntryStatistics) - geoip_entry_stats_term(); - if (old_options && old_options->HiddenServiceStatistics && - !options->HiddenServiceStatistics) - rep_hist_hs_stats_term(); - if (old_options && old_options->ExitPortStatistics && - !options->ExitPortStatistics) - rep_hist_exit_stats_term(); - if (old_options && old_options->ConnDirectionStatistics && - !options->ConnDirectionStatistics) - rep_hist_conn_stats_term(); - if (old_options && old_options->BridgeAuthoritativeDir && - !options->BridgeAuthoritativeDir) - rep_hist_desc_stats_term(); - - /* Since our options changed, we might need to regenerate and upload our - * server descriptor. - */ - if (!old_options || - options_transition_affects_descriptor(old_options, options)) - mark_my_descriptor_dirty("config change"); + /* Only collect other relay-only statistics on relays. */ + if (!public_server_mode(options)) { + options->CellStatistics = 0; + options->EntryStatistics = 0; + options->ConnDirectionStatistics = 0; + options->ExitPortStatistics = 0; + } + + bool print_notice = 0; + if (options_act_relay_stats(old_options, &print_notice) < 0) + return -1; + if (options_act_dirauth_stats(old_options, &print_notice) < 0) + return -1; + if (print_notice) + options_act_relay_stats_msg(); + + if (options_act_relay_desc(old_options) < 0) + return -1; + + if (options_act_dirauth(old_options) < 0) + return -1; /* We may need to reschedule some directory stuff if our status changed. */ if (old_options) { - if (options_transition_affects_dirauth_timing(old_options, options)) { - voting_schedule_recalculate_timing(options, time(NULL)); - reschedule_dirvote(options); - } if (!bool_eq(directory_fetches_dir_info_early(options), directory_fetches_dir_info_early(old_options)) || !bool_eq(directory_fetches_dir_info_later(options), @@ -2428,29 +2159,10 @@ options_act,(const or_options_t *old_options)) } } - /* DoS mitigation subsystem only applies to public relay. */ - if (public_server_mode(options)) { - /* If we are configured as a relay, initialize the subsystem. Even on HUP, - * this is safe to call as it will load data from the current options - * or/and the consensus. */ - dos_init(); - } else if (old_options && public_server_mode(old_options)) { - /* Going from relay to non relay, clean it up. */ - dos_free_all(); - } - - /* Load the webpage we're going to serve every time someone asks for '/' on - our DirPort. */ - tor_free(global_dirfrontpagecontents); - if (options->DirPortFrontPage) { - global_dirfrontpagecontents = - read_file_to_str(options->DirPortFrontPage, 0, NULL); - if (!global_dirfrontpagecontents) { - log_warn(LD_CONFIG, - "DirPortFrontPage file '%s' not found. Continuing anyway.", - options->DirPortFrontPage); - } - } + if (options_act_relay_dos(old_options) < 0) + return -1; + if (options_act_relay_dir(old_options) < 0) + return -1; return 0; } @@ -3130,8 +2842,8 @@ validate_ports_csv(smartlist_t *sl, const char *name, char **msg) * a complaint into *<b>msg</b> using string <b>desc</b>, and return -1. * Else return 0. */ -static int -ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg) +int +config_ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg) { if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) { /* This handles an understandable special case where somebody says "2gb" @@ -3147,48 +2859,6 @@ ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg) return 0; } -/** Parse an authority type from <b>options</b>-\>PublishServerDescriptor - * and write it to <b>options</b>-\>PublishServerDescriptor_. Treat "1" - * as "v3" unless BridgeRelay is 1, in which case treat it as "bridge". - * Treat "0" as "". - * Return 0 on success or -1 if not a recognized authority type (in which - * case the value of PublishServerDescriptor_ is undefined). */ -static int -compute_publishserverdescriptor(or_options_t *options) -{ - smartlist_t *list = options->PublishServerDescriptor; - dirinfo_type_t *auth = &options->PublishServerDescriptor_; - *auth = NO_DIRINFO; - if (!list) /* empty list, answer is none */ - return 0; - SMARTLIST_FOREACH_BEGIN(list, const char *, string) { - if (!strcasecmp(string, "v1")) - log_warn(LD_CONFIG, "PublishServerDescriptor v1 has no effect, because " - "there are no v1 directory authorities anymore."); - else if (!strcmp(string, "1")) - if (options->BridgeRelay) - *auth |= BRIDGE_DIRINFO; - else - *auth |= V3_DIRINFO; - else if (!strcasecmp(string, "v2")) - log_warn(LD_CONFIG, "PublishServerDescriptor v2 has no effect, because " - "there are no v2 directory authorities anymore."); - else if (!strcasecmp(string, "v3")) - *auth |= V3_DIRINFO; - else if (!strcasecmp(string, "bridge")) - *auth |= BRIDGE_DIRINFO; - else if (!strcasecmp(string, "hidserv")) - log_warn(LD_CONFIG, - "PublishServerDescriptor hidserv is invalid. See " - "PublishHidServDescriptors."); - else if (!strcasecmp(string, "") || !strcmp(string, "0")) - /* no authority */; - else - return -1; - } SMARTLIST_FOREACH_END(string); - return 0; -} - /** Lowest allowable value for RendPostPeriod; if this is too low, hidden * services can overload the directory system. */ #define MIN_REND_POST_PERIOD (10*60) @@ -3281,7 +2951,7 @@ options_validate(const or_options_t *old_options, or_options_t *options, vs = config_validate(get_options_mgr(), old_options, options, msg); return vs < 0 ? -1 : 0; } -#endif +#endif /* defined(TOR_UNIT_TESTS) */ #define REJECT(arg) \ STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END @@ -3480,7 +3150,6 @@ options_validate_cb(const void *old_options_, void *options_, char **msg) or_options_t *options = options_; config_line_t *cl; - const char *uname = get_uname(); int n_ports=0; int world_writable_control_socket=0; @@ -3497,16 +3166,10 @@ options_validate_cb(const void *old_options_, void *options_, char **msg) * Always use the value of UseEntryGuards, not UseEntryGuards_option. */ options->UseEntryGuards = options->UseEntryGuards_option; - if (server_mode(options) && - (!strcmpstart(uname, "Windows 95") || - !strcmpstart(uname, "Windows 98") || - !strcmpstart(uname, "Windows Me"))) { - log_warn(LD_CONFIG, "Tor is running as a server, but you are " - "running %s; this probably won't work. See " - "https://www.torproject.org/docs/faq.html#BestOSForRelay " - "for details.", uname); - } + if (options_validate_relay_os(old_options, options, msg) < 0) + return -1; + /* 31851: OutboundBindAddressExit is unused in client mode */ if (parse_outbound_addresses(options, 1, msg) < 0) return -1; @@ -3521,48 +3184,16 @@ options_validate_cb(const void *old_options_, void *options_, char **msg) "with relative paths."); } - if (options->Nickname == NULL) { - if (server_mode(options)) { - options->Nickname = tor_strdup(UNNAMED_ROUTER_NICKNAME); - } - } else { - if (!is_legal_nickname(options->Nickname)) { - tor_asprintf(msg, - "Nickname '%s', nicknames must be between 1 and 19 characters " - "inclusive, and must contain only the characters [a-zA-Z0-9].", - options->Nickname); - return -1; - } - } - - if (server_mode(options) && !options->ContactInfo) - log_notice(LD_CONFIG, "Your ContactInfo config option is not set. " - "Please consider setting it, so we can contact you if your server is " - "misconfigured or something else goes wrong."); - const char *ContactInfo = options->ContactInfo; - if (ContactInfo && !string_is_utf8(ContactInfo, strlen(ContactInfo))) - REJECT("ContactInfo config option must be UTF-8."); + if (options_validate_relay_info(old_options, options, msg) < 0) + return -1; + /* 31851: this function is currently a no-op in client mode */ check_network_configuration(server_mode(options)); /* Validate the tor_log(s) */ if (options_init_logs(old_options, options, 1)<0) REJECT("Failed to validate Log options. See logs for details."); - if (authdir_mode(options)) { - /* confirm that our address isn't broken, so we can complain now */ - uint32_t tmp; - if (resolve_my_address(LOG_WARN, options, &tmp, NULL, NULL) < 0) - REJECT("Failed to resolve/guess local address. See logs for details."); - } - - if (server_mode(options) && options->RendConfigLines) - log_warn(LD_CONFIG, - "Tor is currently configured as a relay and a hidden service. " - "That's not very secure: you should probably run your hidden service " - "in a separate Tor process, at least -- see " - "https://trac.torproject.org/8742"); - /* XXXX require that the only port not be DirPort? */ /* XXXX require that at least one port be listened-upon. */ if (n_ports == 0 && !options->RendConfigLines) @@ -3641,65 +3272,8 @@ options_validate_cb(const void *old_options_, void *options_, char **msg) "features to be broken in unpredictable ways."); } - if (options->AuthoritativeDir) { - if (!options->ContactInfo && !options->TestingTorNetwork) - REJECT("Authoritative directory servers must set ContactInfo"); - if (!options->RecommendedClientVersions) - options->RecommendedClientVersions = - config_lines_dup(options->RecommendedVersions); - if (!options->RecommendedServerVersions) - options->RecommendedServerVersions = - config_lines_dup(options->RecommendedVersions); - if (options->VersioningAuthoritativeDir && - (!options->RecommendedClientVersions || - !options->RecommendedServerVersions)) - REJECT("Versioning authoritative dir servers must set " - "Recommended*Versions."); - -#ifdef HAVE_MODULE_DIRAUTH - char *t; - /* Call these functions to produce warnings only. */ - t = format_recommended_version_list(options->RecommendedClientVersions, 1); - tor_free(t); - t = format_recommended_version_list(options->RecommendedServerVersions, 1); - tor_free(t); -#endif /* defined(HAVE_MODULE_DIRAUTH) */ - - if (options->UseEntryGuards) { - log_info(LD_CONFIG, "Authoritative directory servers can't set " - "UseEntryGuards. Disabling."); - options->UseEntryGuards = 0; - } - if (!options->DownloadExtraInfo && authdir_mode_v3(options)) { - log_info(LD_CONFIG, "Authoritative directories always try to download " - "extra-info documents. Setting DownloadExtraInfo."); - options->DownloadExtraInfo = 1; - } - if (!(options->BridgeAuthoritativeDir || - options->V3AuthoritativeDir)) - REJECT("AuthoritativeDir is set, but none of " - "(Bridge/V3)AuthoritativeDir is set."); -#ifdef HAVE_MODULE_DIRAUTH - /* If we have a v3bandwidthsfile and it's broken, complain on startup */ - if (options->V3BandwidthsFile && !old_options) { - dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL, NULL, - NULL); - } - /* same for guardfraction file */ - if (options->GuardfractionFile && !old_options) { - dirserv_read_guardfraction_file(options->GuardfractionFile, NULL); - } -#endif /* defined(HAVE_MODULE_DIRAUTH) */ - } - - if (options->AuthoritativeDir && !options->DirPort_set) - REJECT("Running as authoritative directory, but no DirPort set."); - - if (options->AuthoritativeDir && !options->ORPort_set) - REJECT("Running as authoritative directory, but no ORPort set."); - - if (options->AuthoritativeDir && options->ClientOnly) - REJECT("Running as authoritative directory, but ClientOnly also set."); + if (options_validate_dirauth_mode(old_options, options, msg) < 0) + return -1; if (options->FetchDirInfoExtraEarly && !options->FetchDirInfoEarly) REJECT("FetchDirInfoExtraEarly requires that you also set " @@ -3838,57 +3412,11 @@ options_validate_cb(const void *old_options_, void *options_, char **msg) return -1; } - if (compute_publishserverdescriptor(options) < 0) { - tor_asprintf(msg, "Unrecognized value in PublishServerDescriptor"); + if (options_validate_publish_server(old_options, options, msg) < 0) return -1; - } - - if ((options->BridgeRelay - || options->PublishServerDescriptor_ & BRIDGE_DIRINFO) - && (options->PublishServerDescriptor_ & V3_DIRINFO)) { - REJECT("Bridges are not supposed to publish router descriptors to the " - "directory authorities. Please correct your " - "PublishServerDescriptor line."); - } - - if (options->BridgeRelay && options->DirPort_set) { - log_warn(LD_CONFIG, "Can't set a DirPort on a bridge relay; disabling " - "DirPort"); - config_free_lines(options->DirPort_lines); - options->DirPort_lines = NULL; - options->DirPort_set = 0; - } - - if (server_mode(options) && options->ConnectionPadding != -1) { - REJECT("Relays must use 'auto' for the ConnectionPadding setting."); - } - - if (server_mode(options) && options->ReducedConnectionPadding != 0) { - REJECT("Relays cannot set ReducedConnectionPadding. "); - } - - if (server_mode(options) && options->CircuitPadding == 0) { - REJECT("Relays cannot set CircuitPadding to 0. "); - } - - if (server_mode(options) && options->ReducedCircuitPadding == 1) { - REJECT("Relays cannot set ReducedCircuitPadding. "); - } - if (options->BridgeDistribution) { - if (!options->BridgeRelay) { - REJECT("You set BridgeDistribution, but you didn't set BridgeRelay!"); - } - if (check_bridge_distribution_setting(options->BridgeDistribution) < 0) { - REJECT("Invalid BridgeDistribution value."); - } - } - - if (options->MinUptimeHidServDirectoryV2 < 0) { - log_warn(LD_CONFIG, "MinUptimeHidServDirectoryV2 option must be at " - "least 0 seconds. Changing to 0."); - options->MinUptimeHidServDirectoryV2 = 0; - } + if (options_validate_relay_padding(old_options, options, msg) < 0) + return -1; const int min_rendpostperiod = options->TestingTorNetwork ? @@ -4062,134 +3590,26 @@ options_validate_cb(const void *old_options_, void *options_, char **msg) if (options->KeepalivePeriod < 1) REJECT("KeepalivePeriod option must be positive."); - if (ensure_bandwidth_cap(&options->BandwidthRate, + if (config_ensure_bandwidth_cap(&options->BandwidthRate, "BandwidthRate", msg) < 0) return -1; - if (ensure_bandwidth_cap(&options->BandwidthBurst, + if (config_ensure_bandwidth_cap(&options->BandwidthBurst, "BandwidthBurst", msg) < 0) return -1; - if (ensure_bandwidth_cap(&options->MaxAdvertisedBandwidth, - "MaxAdvertisedBandwidth", msg) < 0) - return -1; - if (ensure_bandwidth_cap(&options->RelayBandwidthRate, - "RelayBandwidthRate", msg) < 0) - return -1; - if (ensure_bandwidth_cap(&options->RelayBandwidthBurst, - "RelayBandwidthBurst", msg) < 0) - return -1; - if (ensure_bandwidth_cap(&options->PerConnBWRate, - "PerConnBWRate", msg) < 0) - return -1; - if (ensure_bandwidth_cap(&options->PerConnBWBurst, - "PerConnBWBurst", msg) < 0) - return -1; - if (ensure_bandwidth_cap(&options->AuthDirFastGuarantee, - "AuthDirFastGuarantee", msg) < 0) + + if (options_validate_relay_bandwidth(old_options, options, msg) < 0) return -1; - if (ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee, - "AuthDirGuardBWGuarantee", msg) < 0) + if (options_validate_dirauth_bandwidth(old_options, options, msg) < 0) return -1; - if (options->RelayBandwidthRate && !options->RelayBandwidthBurst) - options->RelayBandwidthBurst = options->RelayBandwidthRate; - if (options->RelayBandwidthBurst && !options->RelayBandwidthRate) - options->RelayBandwidthRate = options->RelayBandwidthBurst; - - if (server_mode(options)) { - const unsigned required_min_bw = - public_server_mode(options) ? - RELAY_REQUIRED_MIN_BANDWIDTH : BRIDGE_REQUIRED_MIN_BANDWIDTH; - const char * const optbridge = - public_server_mode(options) ? "" : "bridge "; - if (options->BandwidthRate < required_min_bw) { - tor_asprintf(msg, - "BandwidthRate is set to %d bytes/second. " - "For %sservers, it must be at least %u.", - (int)options->BandwidthRate, optbridge, - required_min_bw); - return -1; - } else if (options->MaxAdvertisedBandwidth < - required_min_bw/2) { - tor_asprintf(msg, - "MaxAdvertisedBandwidth is set to %d bytes/second. " - "For %sservers, it must be at least %u.", - (int)options->MaxAdvertisedBandwidth, optbridge, - required_min_bw/2); - return -1; - } - if (options->RelayBandwidthRate && - options->RelayBandwidthRate < required_min_bw) { - tor_asprintf(msg, - "RelayBandwidthRate is set to %d bytes/second. " - "For %sservers, it must be at least %u.", - (int)options->RelayBandwidthRate, optbridge, - required_min_bw); - return -1; - } - } - - if (options->RelayBandwidthRate > options->RelayBandwidthBurst) - REJECT("RelayBandwidthBurst must be at least equal " - "to RelayBandwidthRate."); - if (options->BandwidthRate > options->BandwidthBurst) REJECT("BandwidthBurst must be at least equal to BandwidthRate."); - /* if they set relaybandwidth* really high but left bandwidth* - * at the default, raise the defaults. */ - if (options->RelayBandwidthRate > options->BandwidthRate) - options->BandwidthRate = options->RelayBandwidthRate; - if (options->RelayBandwidthBurst > options->BandwidthBurst) - options->BandwidthBurst = options->RelayBandwidthBurst; - - if (accounting_parse_options(options, 1)<0) - REJECT("Failed to parse accounting options. See logs for details."); - - if (options->AccountingMax) { - if (options->RendConfigLines && server_mode(options)) { - log_warn(LD_CONFIG, "Using accounting with a hidden service and an " - "ORPort is risky: your hidden service(s) and your public " - "address will all turn off at the same time, which may alert " - "observers that they are being run by the same party."); - } else if (config_count_key(options->RendConfigLines, - "HiddenServiceDir") > 1) { - log_warn(LD_CONFIG, "Using accounting with multiple hidden services is " - "risky: they will all turn off at the same time, which may " - "alert observers that they are being run by the same party."); - } - } - - options->AccountingRule = ACCT_MAX; - if (options->AccountingRule_option) { - if (!strcmp(options->AccountingRule_option, "sum")) - options->AccountingRule = ACCT_SUM; - else if (!strcmp(options->AccountingRule_option, "max")) - options->AccountingRule = ACCT_MAX; - else if (!strcmp(options->AccountingRule_option, "in")) - options->AccountingRule = ACCT_IN; - else if (!strcmp(options->AccountingRule_option, "out")) - options->AccountingRule = ACCT_OUT; - else - REJECT("AccountingRule must be 'sum', 'max', 'in', or 'out'"); - } - - if (options->DirPort_set && !options->DirCache) { - REJECT("DirPort configured but DirCache disabled. DirPort requires " - "DirCache."); - } - - if (options->BridgeRelay && !options->DirCache) { - REJECT("We're a bridge but DirCache is disabled. BridgeRelay requires " - "DirCache."); - } + if (options_validate_relay_accounting(old_options, options, msg) < 0) + return -1; - if (server_mode(options)) { - char *dircache_msg = NULL; - if (have_enough_mem_for_dircache(options, 0, &dircache_msg)) { - log_warn(LD_CONFIG, "%s", dircache_msg); - tor_free(dircache_msg); - } - } + if (options_validate_relay_mode(old_options, options, msg) < 0) + return -1; if (options->HTTPProxy) { /* parse it now */ if (tor_addr_port_lookup(options->HTTPProxy, @@ -4319,19 +3739,6 @@ options_validate_cb(const void *old_options_, void *options_, char **msg) "have it group-readable."); } - if (options->MyFamily_lines && options->BridgeRelay) { - log_warn(LD_CONFIG, "Listing a family for a bridge relay is not " - "supported: it can reveal bridge fingerprints to censors. " - "You should also make sure you aren't listing this bridge's " - "fingerprint in any other MyFamily."); - } - if (options->MyFamily_lines && !options->ContactInfo) { - log_warn(LD_CONFIG, "MyFamily is set but ContactInfo is not configured. " - "ContactInfo should always be set when MyFamily option is too."); - } - if (normalize_nickname_list(&options->MyFamily, - options->MyFamily_lines, "MyFamily", msg)) - return -1; for (cl = options->NodeFamilies; cl; cl = cl->next) { routerset_t *rs = routerset_new(); if (routerset_parse(rs, cl->value, cl->key)) { @@ -4366,50 +3773,12 @@ options_validate_cb(const void *old_options_, void *options_, char **msg) } for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { - if (parse_transport_line(options, cl->value, 1, 0) < 0) + if (pt_parse_transport_line(options, cl->value, 1, 0) < 0) REJECT("Invalid client transport line. See logs for details."); } - for (cl = options->ServerTransportPlugin; cl; cl = cl->next) { - if (parse_transport_line(options, cl->value, 1, 1) < 0) - REJECT("Invalid server transport line. See logs for details."); - } - - if (options->ServerTransportPlugin && !server_mode(options)) { - log_notice(LD_GENERAL, "Tor is not configured as a relay but you specified" - " a ServerTransportPlugin line (%s). The ServerTransportPlugin " - "line will be ignored.", - escaped(options->ServerTransportPlugin->value)); - } - - for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) { - /** If get_bindaddr_from_transport_listen_line() fails with - 'transport' being NULL, it means that something went wrong - while parsing the ServerTransportListenAddr line. */ - char *bindaddr = get_bindaddr_from_transport_listen_line(cl->value, NULL); - if (!bindaddr) - REJECT("ServerTransportListenAddr did not parse. See logs for details."); - tor_free(bindaddr); - } - - if (options->ServerTransportListenAddr && !options->ServerTransportPlugin) { - log_notice(LD_GENERAL, "You need at least a single managed-proxy to " - "specify a transport listen address. The " - "ServerTransportListenAddr line will be ignored."); - } - - for (cl = options->ServerTransportOptions; cl; cl = cl->next) { - /** If get_options_from_transport_options_line() fails with - 'transport' being NULL, it means that something went wrong - while parsing the ServerTransportOptions line. */ - smartlist_t *options_sl = - get_options_from_transport_options_line(cl->value, NULL); - if (!options_sl) - REJECT("ServerTransportOptions did not parse. See logs for details."); - - SMARTLIST_FOREACH(options_sl, char *, cp, tor_free(cp)); - smartlist_free(options_sl); - } + if (options_validate_server_transport(old_options, options, msg) < 0) + return -1; if (options->ConstrainedSockets) { /* If the user wants to constrain socket buffer use, make sure the desired @@ -4423,85 +3792,10 @@ options_validate_cb(const void *old_options_, void *options_, char **msg) MIN_CONSTRAINED_TCP_BUFFER, MAX_CONSTRAINED_TCP_BUFFER); return -1; } - if (options->DirPort_set) { - /* Providing cached directory entries while system TCP buffers are scarce - * will exacerbate the socket errors. Suggest that this be disabled. */ - COMPLAIN("You have requested constrained socket buffers while also " - "serving directory entries via DirPort. It is strongly " - "suggested that you disable serving directory requests when " - "system TCP buffer resources are scarce."); - } - } - - if (options->V3AuthVoteDelay + options->V3AuthDistDelay >= - options->V3AuthVotingInterval/2) { - /* - This doesn't work, but it seems like it should: - what code is preventing the interval being less than twice the lead-up? - if (options->TestingTorNetwork) { - if (options->V3AuthVoteDelay + options->V3AuthDistDelay >= - options->V3AuthVotingInterval) { - REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than " - "V3AuthVotingInterval"); - } else { - COMPLAIN("V3AuthVoteDelay plus V3AuthDistDelay is more than half " - "V3AuthVotingInterval. This may lead to " - "consensus instability, particularly if clocks drift."); - } - } else { - */ - REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than half " - "V3AuthVotingInterval"); - /* - } - */ } - if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS) { - if (options->TestingTorNetwork) { - if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS_TESTING) { - REJECT("V3AuthVoteDelay is way too low."); - } else { - COMPLAIN("V3AuthVoteDelay is very low. " - "This may lead to failure to vote for a consensus."); - } - } else { - REJECT("V3AuthVoteDelay is way too low."); - } - } - - if (options->V3AuthDistDelay < MIN_DIST_SECONDS) { - if (options->TestingTorNetwork) { - if (options->V3AuthDistDelay < MIN_DIST_SECONDS_TESTING) { - REJECT("V3AuthDistDelay is way too low."); - } else { - COMPLAIN("V3AuthDistDelay is very low. " - "This may lead to missing votes in a consensus."); - } - } else { - REJECT("V3AuthDistDelay is way too low."); - } - } - - if (options->V3AuthNIntervalsValid < 2) - REJECT("V3AuthNIntervalsValid must be at least 2."); - - if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL) { - if (options->TestingTorNetwork) { - if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL_TESTING) { - REJECT("V3AuthVotingInterval is insanely low."); - } else { - COMPLAIN("V3AuthVotingInterval is very low. " - "This may lead to failure to synchronise for a consensus."); - } - } else { - REJECT("V3AuthVotingInterval is insanely low."); - } - } else if (options->V3AuthVotingInterval > 24*60*60) { - REJECT("V3AuthVotingInterval is insanely high."); - } else if (((24*60*60) % options->V3AuthVotingInterval) != 0) { - COMPLAIN("V3AuthVotingInterval does not divide evenly into 24 hours."); - } + if (options_validate_dirauth_schedule(old_options, options, msg) < 0) + return -1; if (hs_config_service_all(options, 1) < 0) REJECT("Failed to configure rendezvous options. See logs for details."); @@ -4542,6 +3836,7 @@ options_validate_cb(const void *old_options_, void *options_, char **msg) if (! options->TestingTorNetwork && !options->UsingTestNetworkDefaults_) { or_options_t *dflt_options = options_new(); options_init(dflt_options); + /* 31851: some of these options are dirauth or relay only */ CHECK_DEFAULT(TestingV3AuthInitialVotingInterval); CHECK_DEFAULT(TestingV3AuthInitialVoteDelay); CHECK_DEFAULT(TestingV3AuthInitialDistDelay); @@ -4569,50 +3864,11 @@ options_validate_cb(const void *old_options_, void *options_, char **msg) !(options->DirAuthorities || (options->AlternateDirAuthority && options->AlternateBridgeAuthority))) REJECT("ClientDNSRejectInternalAddresses used for default network."); - if (options->SigningKeyLifetime < options->TestingSigningKeySlop*2) - REJECT("SigningKeyLifetime is too short."); - if (options->TestingLinkCertLifetime < options->TestingAuthKeySlop*2) - REJECT("LinkCertLifetime is too short."); - if (options->TestingAuthKeyLifetime < options->TestingLinkKeySlop*2) - REJECT("TestingAuthKeyLifetime is too short."); - if (options->TestingV3AuthInitialVotingInterval - < MIN_VOTE_INTERVAL_TESTING_INITIAL) { - REJECT("TestingV3AuthInitialVotingInterval is insanely low."); - } else if (((30*60) % options->TestingV3AuthInitialVotingInterval) != 0) { - REJECT("TestingV3AuthInitialVotingInterval does not divide evenly into " - "30 minutes."); - } - - if (options->TestingV3AuthInitialVoteDelay < MIN_VOTE_SECONDS_TESTING) { - REJECT("TestingV3AuthInitialVoteDelay is way too low."); - } - - if (options->TestingV3AuthInitialDistDelay < MIN_DIST_SECONDS_TESTING) { - REJECT("TestingV3AuthInitialDistDelay is way too low."); - } - - if (options->TestingV3AuthInitialVoteDelay + - options->TestingV3AuthInitialDistDelay >= - options->TestingV3AuthInitialVotingInterval) { - REJECT("TestingV3AuthInitialVoteDelay plus TestingV3AuthInitialDistDelay " - "must be less than TestingV3AuthInitialVotingInterval"); - } - - if (options->TestingV3AuthVotingStartOffset > - MIN(options->TestingV3AuthInitialVotingInterval, - options->V3AuthVotingInterval)) { - REJECT("TestingV3AuthVotingStartOffset is higher than the voting " - "interval."); - } else if (options->TestingV3AuthVotingStartOffset < 0) { - REJECT("TestingV3AuthVotingStartOffset must be non-negative."); - } - - if (options->TestingAuthDirTimeToLearnReachability < 0) { - REJECT("TestingAuthDirTimeToLearnReachability must be non-negative."); - } else if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) { - COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high."); - } + if (options_validate_relay_testing(old_options, options, msg) < 0) + return -1; + if (options_validate_dirauth_testing(old_options, options, msg) < 0) + return -1; if (options->TestingEstimatedDescriptorPropagationTime < 0) { REJECT("TestingEstimatedDescriptorPropagationTime must be non-negative."); @@ -4665,22 +3921,6 @@ options_validate_cb(const void *old_options_, void *options_, char **msg) if (options->AccelDir && !options->AccelName) REJECT("Can't use hardware crypto accelerator dir without engine name."); - if (options->PublishServerDescriptor) - SMARTLIST_FOREACH(options->PublishServerDescriptor, const char *, pubdes, { - if (!strcmp(pubdes, "1") || !strcmp(pubdes, "0")) - if (smartlist_len(options->PublishServerDescriptor) > 1) { - COMPLAIN("You have passed a list of multiple arguments to the " - "PublishServerDescriptor option that includes 0 or 1. " - "0 or 1 should only be used as the sole argument. " - "This configuration will be rejected in a future release."); - break; - } - }); - - if (options->BridgeRelay == 1 && ! options->ORPort_set) - REJECT("BridgeRelay is 1, ORPort is not set. This is an invalid " - "combination."); - if (options_validate_scheduler(options, msg) < 0) { return -1; } @@ -4772,50 +4012,6 @@ compute_real_max_mem_in_queues(const uint64_t val, int log_guess) } } -/* If we have less than 300 MB suggest disabling dircache */ -#define DIRCACHE_MIN_MEM_MB 300 -#define DIRCACHE_MIN_MEM_BYTES (DIRCACHE_MIN_MEM_MB*ONE_MEGABYTE) -#define STRINGIFY(val) #val - -/** Create a warning message for emitting if we are a dircache but may not have - * enough system memory, or if we are not a dircache but probably should be. - * Return -1 when a message is returned in *msg*, else return 0. */ -STATIC int -have_enough_mem_for_dircache(const or_options_t *options, size_t total_mem, - char **msg) -{ - *msg = NULL; - /* XXX We should possibly be looking at MaxMemInQueues here - * unconditionally. Or we should believe total_mem unconditionally. */ - if (total_mem == 0) { - if (get_total_system_memory(&total_mem) < 0) { - total_mem = options->MaxMemInQueues >= SIZE_MAX ? - SIZE_MAX : (size_t)options->MaxMemInQueues; - } - } - if (options->DirCache) { - if (total_mem < DIRCACHE_MIN_MEM_BYTES) { - if (options->BridgeRelay) { - tor_asprintf(msg, "Running a Bridge with less than %d MB of memory " - "is not recommended.", DIRCACHE_MIN_MEM_MB); - } else { - tor_asprintf(msg, "Being a directory cache (default) with less than " - "%d MB of memory is not recommended and may consume " - "most of the available resources. Consider disabling " - "this functionality by setting the DirCache option " - "to 0.", DIRCACHE_MIN_MEM_MB); - } - } - } else { - if (total_mem >= DIRCACHE_MIN_MEM_BYTES) { - *msg = tor_strdup("DirCache is disabled and we are configured as a " - "relay. We will not become a Guard."); - } - } - return *msg == NULL ? 0 : -1; -} -#undef STRINGIFY - /** Helper: return true iff s1 and s2 are both NULL, or both non-NULL * equal strings. */ static int @@ -4911,71 +4107,6 @@ options_check_transition_cb(const void *old_, return 0; } -/** Return 1 if any change from <b>old_options</b> to <b>new_options</b> - * will require us to rotate the CPU and DNS workers; else return 0. */ -static int -options_transition_affects_workers(const or_options_t *old_options, - const or_options_t *new_options) -{ - YES_IF_CHANGED_STRING(DataDirectory); - YES_IF_CHANGED_INT(NumCPUs); - YES_IF_CHANGED_LINELIST(ORPort_lines); - YES_IF_CHANGED_BOOL(ServerDNSSearchDomains); - YES_IF_CHANGED_BOOL(SafeLogging_); - YES_IF_CHANGED_BOOL(ClientOnly); - YES_IF_CHANGED_BOOL(LogMessageDomains); - YES_IF_CHANGED_LINELIST(Logs); - - if (server_mode(old_options) != server_mode(new_options) || - public_server_mode(old_options) != public_server_mode(new_options) || - dir_server_mode(old_options) != dir_server_mode(new_options)) - return 1; - - /* Nothing that changed matters. */ - return 0; -} - -/** Return 1 if any change from <b>old_options</b> to <b>new_options</b> - * will require us to generate a new descriptor; else return 0. */ -static int -options_transition_affects_descriptor(const or_options_t *old_options, - const or_options_t *new_options) -{ - /* XXX We can be smarter here. If your DirPort isn't being - * published and you just turned it off, no need to republish. Etc. */ - - YES_IF_CHANGED_STRING(DataDirectory); - YES_IF_CHANGED_STRING(Nickname); - YES_IF_CHANGED_STRING(Address); - YES_IF_CHANGED_LINELIST(ExitPolicy); - YES_IF_CHANGED_BOOL(ExitRelay); - YES_IF_CHANGED_BOOL(ExitPolicyRejectPrivate); - YES_IF_CHANGED_BOOL(ExitPolicyRejectLocalInterfaces); - YES_IF_CHANGED_BOOL(IPv6Exit); - YES_IF_CHANGED_LINELIST(ORPort_lines); - YES_IF_CHANGED_LINELIST(DirPort_lines); - YES_IF_CHANGED_LINELIST(DirPort_lines); - YES_IF_CHANGED_BOOL(ClientOnly); - YES_IF_CHANGED_BOOL(DisableNetwork); - YES_IF_CHANGED_BOOL(PublishServerDescriptor_); - YES_IF_CHANGED_STRING(ContactInfo); - YES_IF_CHANGED_STRING(BridgeDistribution); - YES_IF_CHANGED_LINELIST(MyFamily); - YES_IF_CHANGED_STRING(AccountingStart); - YES_IF_CHANGED_INT(AccountingMax); - YES_IF_CHANGED_INT(AccountingRule); - YES_IF_CHANGED_BOOL(DirCache); - YES_IF_CHANGED_BOOL(AssumeReachable); - - if (get_effective_bwrate(old_options) != get_effective_bwrate(new_options) || - get_effective_bwburst(old_options) != - get_effective_bwburst(new_options) || - public_server_mode(old_options) != public_server_mode(new_options)) - return 1; - - return 0; -} - #ifdef _WIN32 /** Return the directory on windows where we expect to find our application * data. */ @@ -5060,85 +4191,6 @@ get_default_conf_file(int defaults_file) #endif /* defined(DISABLE_SYSTEM_TORRC) || ... */ } -/** Verify whether lst is a list of strings containing valid-looking - * comma-separated nicknames, or NULL. Will normalise <b>lst</b> to prefix '$' - * to any nickname or fingerprint that needs it. Also splits comma-separated - * list elements into multiple elements. Return 0 on success. - * Warn and return -1 on failure. - */ -static int -normalize_nickname_list(config_line_t **normalized_out, - const config_line_t *lst, const char *name, - char **msg) -{ - if (!lst) - return 0; - - config_line_t *new_nicknames = NULL; - config_line_t **new_nicknames_next = &new_nicknames; - - const config_line_t *cl; - for (cl = lst; cl; cl = cl->next) { - const char *line = cl->value; - if (!line) - continue; - - int valid_line = 1; - smartlist_t *sl = smartlist_new(); - smartlist_split_string(sl, line, ",", - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0); - SMARTLIST_FOREACH_BEGIN(sl, char *, s) - { - char *normalized = NULL; - if (!is_legal_nickname_or_hexdigest(s)) { - // check if first char is dollar - if (s[0] != '$') { - // Try again but with a dollar symbol prepended - char *prepended; - tor_asprintf(&prepended, "$%s", s); - - if (is_legal_nickname_or_hexdigest(prepended)) { - // The nickname is valid when it's prepended, set it as the - // normalized version - normalized = prepended; - } else { - // Still not valid, free and fallback to error message - tor_free(prepended); - } - } - - if (!normalized) { - tor_asprintf(msg, "Invalid nickname '%s' in %s line", s, name); - valid_line = 0; - break; - } - } else { - normalized = tor_strdup(s); - } - - config_line_t *next = tor_malloc_zero(sizeof(*next)); - next->key = tor_strdup(cl->key); - next->value = normalized; - next->next = NULL; - - *new_nicknames_next = next; - new_nicknames_next = &next->next; - } SMARTLIST_FOREACH_END(s); - - SMARTLIST_FOREACH(sl, char *, s, tor_free(s)); - smartlist_free(sl); - - if (!valid_line) { - config_free_lines(new_nicknames); - return -1; - } - } - - *normalized_out = new_nicknames; - - return 0; -} - /** Learn config file name from command line arguments, or use the default. * * If <b>defaults_file</b> is true, we're looking for torrc-defaults; @@ -6067,9 +5119,8 @@ parse_bridge_line(const char *line) * our internal transport list. * - If it's a managed proxy line, launch the managed proxy. */ - -STATIC int -parse_transport_line(const or_options_t *options, +int +pt_parse_transport_line(const or_options_t *options, const char *line, int validate_only, int server) { @@ -6262,157 +5313,6 @@ parse_transport_line(const or_options_t *options, return r; } -/** Given a ServerTransportListenAddr <b>line</b>, return its - * <address:port> string. Return NULL if the line was not - * well-formed. - * - * If <b>transport</b> is set, return NULL if the line is not - * referring to <b>transport</b>. - * - * The returned string is allocated on the heap and it's the - * responsibility of the caller to free it. */ -static char * -get_bindaddr_from_transport_listen_line(const char *line,const char *transport) -{ - smartlist_t *items = NULL; - const char *parsed_transport = NULL; - char *addrport = NULL; - tor_addr_t addr; - uint16_t port = 0; - - items = smartlist_new(); - smartlist_split_string(items, line, NULL, - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); - - if (smartlist_len(items) < 2) { - log_warn(LD_CONFIG,"Too few arguments on ServerTransportListenAddr line."); - goto err; - } - - parsed_transport = smartlist_get(items, 0); - addrport = tor_strdup(smartlist_get(items, 1)); - - /* If 'transport' is given, check if it matches the one on the line */ - if (transport && strcmp(transport, parsed_transport)) - goto err; - - /* Validate addrport */ - if (tor_addr_port_parse(LOG_WARN, addrport, &addr, &port, -1)<0) { - log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr " - "address '%s'", addrport); - goto err; - } - - goto done; - - err: - tor_free(addrport); - addrport = NULL; - - done: - SMARTLIST_FOREACH(items, char*, s, tor_free(s)); - smartlist_free(items); - - return addrport; -} - -/** Given a ServerTransportOptions <b>line</b>, return a smartlist - * with the options. Return NULL if the line was not well-formed. - * - * If <b>transport</b> is set, return NULL if the line is not - * referring to <b>transport</b>. - * - * The returned smartlist and its strings are allocated on the heap - * and it's the responsibility of the caller to free it. */ -smartlist_t * -get_options_from_transport_options_line(const char *line,const char *transport) -{ - smartlist_t *items = smartlist_new(); - smartlist_t *options = smartlist_new(); - const char *parsed_transport = NULL; - - smartlist_split_string(items, line, NULL, - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); - - if (smartlist_len(items) < 2) { - log_warn(LD_CONFIG,"Too few arguments on ServerTransportOptions line."); - goto err; - } - - parsed_transport = smartlist_get(items, 0); - /* If 'transport' is given, check if it matches the one on the line */ - if (transport && strcmp(transport, parsed_transport)) - goto err; - - SMARTLIST_FOREACH_BEGIN(items, const char *, option) { - if (option_sl_idx == 0) /* skip the transport field (first field)*/ - continue; - - /* validate that it's a k=v value */ - if (!string_is_key_value(LOG_WARN, option)) { - log_warn(LD_CONFIG, "%s is not a k=v value.", escaped(option)); - goto err; - } - - /* add it to the options smartlist */ - smartlist_add_strdup(options, option); - log_debug(LD_CONFIG, "Added %s to the list of options", escaped(option)); - } SMARTLIST_FOREACH_END(option); - - goto done; - - err: - SMARTLIST_FOREACH(options, char*, s, tor_free(s)); - smartlist_free(options); - options = NULL; - - done: - SMARTLIST_FOREACH(items, char*, s, tor_free(s)); - smartlist_free(items); - - return options; -} - -/** Given the name of a pluggable transport in <b>transport</b>, check - * the configuration file to see if the user has explicitly asked for - * it to listen on a specific port. Return a <address:port> string if - * so, otherwise NULL. */ -char * -get_transport_bindaddr_from_config(const char *transport) -{ - config_line_t *cl; - const or_options_t *options = get_options(); - - for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) { - char *bindaddr = - get_bindaddr_from_transport_listen_line(cl->value, transport); - if (bindaddr) - return bindaddr; - } - - return NULL; -} - -/** Given the name of a pluggable transport in <b>transport</b>, check - * the configuration file to see if the user has asked us to pass any - * parameters to the pluggable transport. Return a smartlist - * containing the parameters, otherwise NULL. */ -smartlist_t * -get_options_for_server_transport(const char *transport) -{ - config_line_t *cl; - const or_options_t *options = get_options(); - - for (cl = options->ServerTransportOptions; cl; cl = cl->next) { - smartlist_t *options_sl = - get_options_from_transport_options_line(cl->value, transport); - if (options_sl) - return options_sl; - } - - return NULL; -} - /** Read the contents of a DirAuthority line from <b>line</b>. If * <b>validate_only</b> is 0, and the line is well-formed, and it * shares any bits with <b>required_type</b> or <b>required_type</b> @@ -6684,7 +5584,7 @@ parse_dir_fallback_line(const char *line, } /** Allocate and return a new port_cfg_t with reasonable defaults. */ -STATIC port_cfg_t * +port_cfg_t * port_cfg_new(size_t namelen) { tor_assert(namelen <= SIZE_T_CEILING - sizeof(port_cfg_t) - 1); @@ -6698,7 +5598,7 @@ port_cfg_new(size_t namelen) } /** Free all storage held in <b>port</b> */ -STATIC void +void port_cfg_free_(port_cfg_t *port) { tor_free(port); @@ -6732,27 +5632,6 @@ warn_nonlocal_client_ports(const smartlist_t *ports, } SMARTLIST_FOREACH_END(port); } -/** Warn for every Extended ORPort port in <b>ports</b> that is on a - * publicly routable address. */ -static void -warn_nonlocal_ext_orports(const smartlist_t *ports, const char *portname) -{ - SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) { - if (port->type != CONN_TYPE_EXT_OR_LISTENER) - continue; - if (port->is_unix_addr) - continue; - /* XXX maybe warn even if address is RFC1918? */ - if (!tor_addr_is_internal(&port->addr, 1)) { - log_warn(LD_CONFIG, "You specified a public address '%s' for %sPort. " - "This is not advised; this address is supposed to only be " - "exposed on localhost so that your pluggable transport " - "proxies can connect to it.", - fmt_addrport(&port->addr, port->port), portname); - } - } SMARTLIST_FOREACH_END(port); -} - /** Given a list of port_cfg_t in <b>ports</b>, warn if any controller port * there is listening on any non-loopback address. If <b>forbid_nonlocal</b> * is true, then emit a stronger warning and remove the port from the list. @@ -6866,55 +5745,6 @@ warn_client_dns_cache(const char *option, int disabling) } /** - * Validate the configured bridge distribution method from a BridgeDistribution - * config line. - * - * The input <b>bd</b>, is a string taken from the BridgeDistribution config - * line (if present). If the option wasn't set, return 0 immediately. The - * BridgeDistribution option is then validated. Currently valid, recognised - * options are: - * - * - "none" - * - "any" - * - "https" - * - "email" - * - "moat" - * - "hyphae" - * - * If the option string is unrecognised, a warning will be logged and 0 is - * returned. If the option string contains an invalid character, -1 is - * returned. - **/ -STATIC int -check_bridge_distribution_setting(const char *bd) -{ - if (bd == NULL) - return 0; - - const char *RECOGNIZED[] = { - "none", "any", "https", "email", "moat", "hyphae" - }; - unsigned i; - for (i = 0; i < ARRAY_LENGTH(RECOGNIZED); ++i) { - if (!strcmp(bd, RECOGNIZED[i])) - return 0; - } - - const char *cp = bd; - // Method = (KeywordChar | "_") + - while (TOR_ISALNUM(*cp) || *cp == '-' || *cp == '_') - ++cp; - - if (*cp == 0) { - log_warn(LD_CONFIG, "Unrecognized BridgeDistribution value %s. I'll " - "assume you know what you are doing...", escaped(bd)); - return 0; // we reached the end of the string; all is well - } else { - return -1; // we found a bad character in the string. - } -} - -/** * Parse port configuration for a single port type. * * Read entries of the "FooPort" type from the list <b>ports</b>. Syntax is @@ -6944,8 +5774,8 @@ check_bridge_distribution_setting(const char *bd) * <b>out</b> for every port that the client should listen on. Return 0 * on success, -1 on failure. */ -STATIC int -parse_port_config(smartlist_t *out, +int +port_parse_config(smartlist_t *out, const config_line_t *ports, const char *portname, int listener_type, @@ -7378,7 +6208,7 @@ parse_port_config(smartlist_t *out, if (is_control) warn_nonlocal_controller_ports(out, forbid_nonlocal); else if (is_ext_orport) - warn_nonlocal_ext_orports(out, portname); + port_warn_nonlocal_ext_orports(out, portname); else warn_nonlocal_client_ports(out, portname, listener_type); } @@ -7402,8 +6232,8 @@ parse_port_config(smartlist_t *out, /** Return the number of ports which are actually going to listen with type * <b>listenertype</b>. Do not count no_listen ports. Only count unix * sockets if count_sockets is true. */ -static int -count_real_listeners(const smartlist_t *ports, int listenertype, +int +port_count_real_listeners(const smartlist_t *ports, int listenertype, int count_sockets) { int n = 0; @@ -7441,7 +6271,7 @@ parse_ports(or_options_t *options, int validate_only, const unsigned gw_flag = options->UnixSocksGroupWritable ? CL_PORT_DFLT_GROUP_WRITABLE : 0; - if (parse_port_config(ports, + if (port_parse_config(ports, options->SocksPort_lines, "Socks", CONN_TYPE_AP_LISTENER, "127.0.0.1", 9050, @@ -7450,7 +6280,7 @@ parse_ports(or_options_t *options, int validate_only, *msg = tor_strdup("Invalid SocksPort configuration"); goto err; } - if (parse_port_config(ports, + if (port_parse_config(ports, options->DNSPort_lines, "DNS", CONN_TYPE_AP_DNS_LISTENER, "127.0.0.1", 0, @@ -7458,7 +6288,7 @@ parse_ports(or_options_t *options, int validate_only, *msg = tor_strdup("Invalid DNSPort configuration"); goto err; } - if (parse_port_config(ports, + if (port_parse_config(ports, options->TransPort_lines, "Trans", CONN_TYPE_AP_TRANS_LISTENER, "127.0.0.1", 0, @@ -7466,7 +6296,7 @@ parse_ports(or_options_t *options, int validate_only, *msg = tor_strdup("Invalid TransPort configuration"); goto err; } - if (parse_port_config(ports, + if (port_parse_config(ports, options->NATDPort_lines, "NATD", CONN_TYPE_AP_NATD_LISTENER, "127.0.0.1", 0, @@ -7474,7 +6304,7 @@ parse_ports(or_options_t *options, int validate_only, *msg = tor_strdup("Invalid NatdPort configuration"); goto err; } - if (parse_port_config(ports, + if (port_parse_config(ports, options->HTTPTunnelPort_lines, "HTTP Tunnel", CONN_TYPE_AP_HTTP_CONNECT_LISTENER, "127.0.0.1", 0, @@ -7494,7 +6324,7 @@ parse_ports(or_options_t *options, int validate_only, if (options->ControlSocketsGroupWritable) control_port_flags |= CL_PORT_DFLT_GROUP_WRITABLE; - if (parse_port_config(ports, + if (port_parse_config(ports, options->ControlPort_lines, "Control", CONN_TYPE_CONTROL_LISTENER, "127.0.0.1", 0, @@ -7503,7 +6333,7 @@ parse_ports(or_options_t *options, int validate_only, goto err; } - if (parse_port_config(ports, options->ControlSocket, + if (port_parse_config(ports, options->ControlSocket, "ControlSocket", CONN_TYPE_CONTROL_LISTENER, NULL, 0, control_port_flags | CL_PORT_IS_UNIXSOCKET) < 0) { @@ -7511,40 +6341,9 @@ parse_ports(or_options_t *options, int validate_only, goto err; } } - if (! options->ClientOnly) { - if (parse_port_config(ports, - options->ORPort_lines, - "OR", CONN_TYPE_OR_LISTENER, - "0.0.0.0", 0, - CL_PORT_SERVER_OPTIONS) < 0) { - *msg = tor_strdup("Invalid ORPort configuration"); - goto err; - } - if (parse_port_config(ports, - options->ExtORPort_lines, - "ExtOR", CONN_TYPE_EXT_OR_LISTENER, - "127.0.0.1", 0, - CL_PORT_SERVER_OPTIONS|CL_PORT_WARN_NONLOCAL) < 0) { - *msg = tor_strdup("Invalid ExtORPort configuration"); - goto err; - } - if (parse_port_config(ports, - options->DirPort_lines, - "Dir", CONN_TYPE_DIR_LISTENER, - "0.0.0.0", 0, - CL_PORT_SERVER_OPTIONS) < 0) { - *msg = tor_strdup("Invalid DirPort configuration"); - goto err; - } - } - int n_low_ports = 0; - if (check_server_ports(ports, options, &n_low_ports) < 0) { - *msg = tor_strdup("Misconfigured server ports"); + if (port_parse_ports_relay(options, msg, ports, &have_low_ports) < 0) goto err; - } - if (have_low_ports < 0) - have_low_ports = (n_low_ports > 0); *n_ports_out = smartlist_len(ports); @@ -7552,25 +6351,20 @@ parse_ports(or_options_t *options, int validate_only, /* Update the *Port_set options. The !! here is to force a boolean out of an integer. */ - options->ORPort_set = - !! count_real_listeners(ports, CONN_TYPE_OR_LISTENER, 0); + port_update_port_set_relay(options, ports); options->SocksPort_set = - !! count_real_listeners(ports, CONN_TYPE_AP_LISTENER, 1); + !! port_count_real_listeners(ports, CONN_TYPE_AP_LISTENER, 1); options->TransPort_set = - !! count_real_listeners(ports, CONN_TYPE_AP_TRANS_LISTENER, 1); + !! port_count_real_listeners(ports, CONN_TYPE_AP_TRANS_LISTENER, 1); options->NATDPort_set = - !! count_real_listeners(ports, CONN_TYPE_AP_NATD_LISTENER, 1); + !! port_count_real_listeners(ports, CONN_TYPE_AP_NATD_LISTENER, 1); options->HTTPTunnelPort_set = - !! count_real_listeners(ports, CONN_TYPE_AP_HTTP_CONNECT_LISTENER, 1); + !! port_count_real_listeners(ports, CONN_TYPE_AP_HTTP_CONNECT_LISTENER, 1); /* Use options->ControlSocket to test if a control socket is set */ options->ControlPort_set = - !! count_real_listeners(ports, CONN_TYPE_CONTROL_LISTENER, 0); - options->DirPort_set = - !! count_real_listeners(ports, CONN_TYPE_DIR_LISTENER, 0); + !! port_count_real_listeners(ports, CONN_TYPE_CONTROL_LISTENER, 0); options->DNSPort_set = - !! count_real_listeners(ports, CONN_TYPE_AP_DNS_LISTENER, 1); - options->ExtORPort_set = - !! count_real_listeners(ports, CONN_TYPE_EXT_OR_LISTENER, 0); + !! port_count_real_listeners(ports, CONN_TYPE_AP_DNS_LISTENER, 1); if (world_writable_control_socket) { SMARTLIST_FOREACH(ports, port_cfg_t *, p, @@ -7601,7 +6395,7 @@ parse_ports(or_options_t *options, int validate_only, } /* Does port bind to IPv4? */ -static int +int port_binds_ipv4(const port_cfg_t *port) { return tor_addr_family(&port->addr) == AF_INET || @@ -7610,7 +6404,7 @@ port_binds_ipv4(const port_cfg_t *port) } /* Does port bind to IPv6? */ -static int +int port_binds_ipv6(const port_cfg_t *port) { return tor_addr_family(&port->addr) == AF_INET6 || @@ -7618,94 +6412,6 @@ port_binds_ipv6(const port_cfg_t *port) && !port->server_cfg.bind_ipv4_only); } -/** Given a list of <b>port_cfg_t</b> in <b>ports</b>, check them for internal - * consistency and warn as appropriate. Set *<b>n_low_ports_out</b> to the - * number of sub-1024 ports we will be binding. */ -static int -check_server_ports(const smartlist_t *ports, - const or_options_t *options, - int *n_low_ports_out) -{ - int n_orport_advertised = 0; - int n_orport_advertised_ipv4 = 0; - int n_orport_listeners = 0; - int n_dirport_advertised = 0; - int n_dirport_listeners = 0; - int n_low_port = 0; - int r = 0; - - SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) { - if (port->type == CONN_TYPE_DIR_LISTENER) { - if (! port->server_cfg.no_advertise) - ++n_dirport_advertised; - if (! port->server_cfg.no_listen) - ++n_dirport_listeners; - } else if (port->type == CONN_TYPE_OR_LISTENER) { - if (! port->server_cfg.no_advertise) { - ++n_orport_advertised; - if (port_binds_ipv4(port)) - ++n_orport_advertised_ipv4; - } - if (! port->server_cfg.no_listen) - ++n_orport_listeners; - } else { - continue; - } -#ifndef _WIN32 - if (!port->server_cfg.no_listen && port->port < 1024) - ++n_low_port; -#endif - } SMARTLIST_FOREACH_END(port); - - if (n_orport_advertised && !n_orport_listeners) { - log_warn(LD_CONFIG, "We are advertising an ORPort, but not actually " - "listening on one."); - r = -1; - } - if (n_orport_listeners && !n_orport_advertised) { - log_warn(LD_CONFIG, "We are listening on an ORPort, but not advertising " - "any ORPorts. This will keep us from building a %s " - "descriptor, and make us impossible to use.", - options->BridgeRelay ? "bridge" : "router"); - r = -1; - } - if (n_dirport_advertised && !n_dirport_listeners) { - log_warn(LD_CONFIG, "We are advertising a DirPort, but not actually " - "listening on one."); - r = -1; - } - if (n_dirport_advertised > 1) { - log_warn(LD_CONFIG, "Can't advertise more than one DirPort."); - r = -1; - } - if (n_orport_advertised && !n_orport_advertised_ipv4 && - !options->BridgeRelay) { - log_warn(LD_CONFIG, "Configured public relay to listen only on an IPv6 " - "address. Tor needs to listen on an IPv4 address too."); - r = -1; - } - - if (n_low_port && options->AccountingMax && - (!have_capability_support() || options->KeepBindCapabilities == 0)) { - const char *extra = ""; - if (options->KeepBindCapabilities == 0 && have_capability_support()) - extra = ", and you have disabled KeepBindCapabilities."; - log_warn(LD_CONFIG, - "You have set AccountingMax to use hibernation. You have also " - "chosen a low DirPort or OrPort%s." - "This combination can make Tor stop " - "working when it tries to re-attach the port after a period of " - "hibernation. Please choose a different port or turn off " - "hibernation unless you know this combination will work on your " - "platform.", extra); - } - - if (n_low_ports_out) - *n_low_ports_out = n_low_port; - - return r; -} - /** Return a list of port_cfg_t for client ports parsed from the * options. */ MOCK_IMPL(const smartlist_t *, @@ -8184,43 +6890,6 @@ write_to_data_subdir(const char* subdir, const char* fname, return return_val; } -/** Return a smartlist of ports that must be forwarded by - * tor-fw-helper. The smartlist contains the ports in a string format - * that is understandable by tor-fw-helper. */ -smartlist_t * -get_list_of_ports_to_forward(void) -{ - smartlist_t *ports_to_forward = smartlist_new(); - int port = 0; - - /** XXX TODO tor-fw-helper does not support forwarding ports to - other hosts than the local one. If the user is binding to a - different IP address, tor-fw-helper won't work. */ - port = router_get_advertised_or_port(get_options()); /* Get ORPort */ - if (port) - smartlist_add_asprintf(ports_to_forward, "%d:%d", port, port); - - port = router_get_advertised_dir_port(get_options(), 0); /* Get DirPort */ - if (port) - smartlist_add_asprintf(ports_to_forward, "%d:%d", port, port); - - /* Get ports of transport proxies */ - { - smartlist_t *transport_ports = get_transport_proxy_ports(); - if (transport_ports) { - smartlist_add_all(ports_to_forward, transport_ports); - smartlist_free(transport_ports); - } - } - - if (!smartlist_len(ports_to_forward)) { - smartlist_free(ports_to_forward); - ports_to_forward = NULL; - } - - return ports_to_forward; -} - /** Helper to implement GETINFO functions about configuration variables (not * their values). Given a "config/names" question, set *<b>answer</b> to a * new string describing the supported configuration variables and their |