diff --git a/Makefile.am b/Makefile.am index 9866f87f8c..8b2772577f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -488,19 +488,19 @@ version: .PHONY: autostyle-ifdefs autostyle-ifdefs: - $(PYTHON) scripts/maint/annotate_ifdef_directives.py $(OWNED_TOR_C_FILES) + $(PYTHON) $(top_srcdir)/scripts/maint/annotate_ifdef_directives.py $(OWNED_TOR_C_FILES) .PHONY: autostyle-ifdefs autostyle-operators: - $(PERL) scripts/coccinelle/test-operator-cleanup $(OWNED_TOR_C_FILES) + $(PERL) $(top_srcdir)/scripts/coccinelle/test-operator-cleanup $(OWNED_TOR_C_FILES) .PHONY: rectify-includes rectify-includes: - $(PYTHON) scripts/maint/rectify_include_paths.py + $(PYTHON) $(top_srcdir)/scripts/maint/rectify_include_paths.py .PHONY: update-copyright update-copyright: - $(PERL) scripts/maint/updateCopyright.pl $(OWNED_TOR_C_FILES) + $(PERL) $(top_srcdir)/scripts/maint/updateCopyright.pl $(OWNED_TOR_C_FILES) .PHONY: autostyle autostyle: update-versions rustfmt autostyle-ifdefs rectify-includes diff --git a/changes/bug32213 b/changes/bug32213 new file mode 100644 index 0000000000..9083f4286c --- /dev/null +++ b/changes/bug32213 @@ -0,0 +1,20 @@ + o Minor bugfixes (dirauth module): + - When the dirauth module is disabled, reject attempts to set the + AuthoritativeDir option, rather than ignoring the value of the + option. Fixes bug 32213; bugfix on 0.3.4.1-alpha. + - Split the dirauth config code into a separate file in the dirauth + module. Disable this code when the dirauth module is disabled. + Closes ticket 32213. + o Minor features (relay module): + - When the relay module is disabled, reject attempts to set the + ORPort, DirPort, DirCache, BridgeRelay, ExtORPort, or + ServerTransport* options, rather than ignoring the values of these + options. Closes ticket 32213. + - Split the relay and server pluggable transport config code into + separate files in the relay module. Disable this code when the relay + module is disabled. Closes ticket 32213. + o Code simplification and refactoring: + - Simplify some relay and dirauth config code. Closes ticket 32213. + o Testing: + - Improve test coverage for relay and dirauth config code, focusing on + option validation and normalization. Closes ticket 32213. diff --git a/changes/bug32352 b/changes/bug32352 new file mode 100644 index 0000000000..ca93e4efdf --- /dev/null +++ b/changes/bug32352 @@ -0,0 +1,6 @@ + o Minor bugfixes (config): + - When dumping the config, stop adding a trailing space after the option + name, when there is no option value. This issue only affects options + that accept an empty value or list. (Most options reject empty values, + or delete the entire line from the dumped options.) + Fixes bug 32352; bugfix on 0.0.9pre6. diff --git a/changes/bug32368 b/changes/bug32368 new file mode 100644 index 0000000000..378f74fa54 --- /dev/null +++ b/changes/bug32368 @@ -0,0 +1,4 @@ + o Minor bugfixes (test): + - Use the same code to find the tor binary in all of our test scripts. + This change makes sure we are always using the coverage binary, when + coverage is enabled. Fixes bug 32368; bugfix on 0.2.7.3-rc. diff --git a/changes/bug32370 b/changes/bug32370 new file mode 100644 index 0000000000..9e450d9612 --- /dev/null +++ b/changes/bug32370 @@ -0,0 +1,3 @@ + o Minor bugfixes (build): + - Fix "make autostyle" for out-of-tree builds. + Fixes bug 32370; bugfix on 0.4.1.2-alpha. diff --git a/changes/bug32371 b/changes/bug32371 new file mode 100644 index 0000000000..1fed15c2d7 --- /dev/null +++ b/changes/bug32371 @@ -0,0 +1,3 @@ + o Minor bugfixes (scripts): + - Fix update_versions.py for out-of-tree builds. + Fixes bug 32371; bugfix on 0.4.0.1-alpha. diff --git a/changes/ticket32213_parseconf b/changes/ticket32213_parseconf new file mode 100644 index 0000000000..a334bec5c6 --- /dev/null +++ b/changes/ticket32213_parseconf @@ -0,0 +1,3 @@ + o Testing: + - Improve the consistency of test_parseconf.sh output, and run all the + tests, even if one fails. Closes ticket 32213. diff --git a/scripts/maint/practracker/exceptions.txt b/scripts/maint/practracker/exceptions.txt index f7bd8287e8..761299993e 100644 --- a/scripts/maint/practracker/exceptions.txt +++ b/scripts/maint/practracker/exceptions.txt @@ -33,25 +33,25 @@ # # Remember: It is better to fix the problem than to add a new exception! -problem file-size /src/app/config/config.c 8459 -problem include-count /src/app/config/config.c 89 +problem file-size /src/app/config/config.c 7223 +problem include-count /src/app/config/config.c 80 problem function-size /src/app/config/config.c:options_act_reversible() 296 -problem function-size /src/app/config/config.c:options_act() 589 +problem function-size /src/app/config/config.c:options_act() 381 problem function-size /src/app/config/config.c:resolve_my_address() 190 -problem function-size /src/app/config/config.c:options_validate_cb() 1209 -problem function-size /src/app/config/config.c:options_init_from_torrc() 207 -problem function-size /src/app/config/config.c:options_init_from_string() 113 -problem function-size /src/app/config/config.c:options_init_logs() 145 +problem function-size /src/app/config/config.c:options_validate_cb() 785 +problem function-size /src/app/config/config.c:options_init_from_torrc() 188 +problem function-size /src/app/config/config.c:options_init_from_string() 103 +problem function-size /src/app/config/config.c:options_init_logs() 125 problem function-size /src/app/config/config.c:parse_bridge_line() 104 -problem function-size /src/app/config/config.c:parse_transport_line() 189 +problem function-size /src/app/config/config.c:pt_parse_transport_line() 189 problem function-size /src/app/config/config.c:parse_dir_authority_line() 150 problem function-size /src/app/config/config.c:parse_dir_fallback_line() 101 -problem function-size /src/app/config/config.c:parse_port_config() 446 -problem function-size /src/app/config/config.c:parse_ports() 168 -problem file-size /src/app/config/or_options_st.h 1121 +problem function-size /src/app/config/config.c:port_parse_config() 446 +problem function-size /src/app/config/config.c:parse_ports() 132 +problem file-size /src/app/config/or_options_st.h 1117 problem include-count /src/app/main/main.c 68 problem function-size /src/app/main/main.c:dumpstats() 102 -problem function-size /src/app/main/main.c:tor_init() 137 +problem function-size /src/app/main/main.c:tor_init() 111 problem function-size /src/app/main/main.c:sandbox_init_filter() 291 problem function-size /src/app/main/main.c:run_tor_main_loop() 105 problem function-size /src/app/main/ntmain.c:nt_service_install() 126 @@ -204,7 +204,7 @@ problem function-size /src/feature/control/control_cmd.c:add_onion_helper_keyarg problem function-size /src/feature/control/control_events.c:control_event_stream_status() 118 problem include-count /src/feature/control/control_getinfo.c 54 problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_misc() 108 -problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_dir() 302 +problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_dir() 297 problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_events() 234 problem function-size /src/feature/dirauth/bwauth.c:dirserv_read_measured_bandwidths() 121 problem file-size /src/feature/dirauth/dirvote.c 4700 @@ -257,7 +257,7 @@ problem function-size /src/feature/hs/hs_descriptor.c:decrypt_desc_layer() 111 problem function-size /src/feature/hs/hs_descriptor.c:decode_introduction_point() 122 problem function-size /src/feature/hs/hs_descriptor.c:desc_decode_superencrypted_v3() 107 problem function-size /src/feature/hs/hs_descriptor.c:desc_decode_encrypted_v3() 107 -problem file-size /src/feature/hs/hs_service.c 4182 +problem file-size /src/feature/hs/hs_service.c 4172 problem function-size /src/feature/keymgt/loadkey.c:ed_key_init_from_file() 326 problem function-size /src/feature/nodelist/authcert.c:trusted_dirs_load_certs_from_string() 123 problem function-size /src/feature/nodelist/authcert.c:authority_certs_fetch_missing() 295 @@ -320,7 +320,7 @@ problem function-size /src/lib/net/address.c:tor_addr_compare_masked() 110 problem function-size /src/lib/net/inaddr.c:tor_inet_pton() 107 problem function-size /src/lib/net/socketpair.c:tor_ersatz_socketpair() 102 problem function-size /src/lib/osinfo/uname.c:get_uname() 116 -problem function-size /src/lib/process/process_unix.c:process_unix_exec() 220 +problem function-size /src/lib/process/process_unix.c:process_unix_exec() 213 problem function-size /src/lib/process/process_win32.c:process_win32_exec() 151 problem function-size /src/lib/process/process_win32.c:process_win32_create_pipe() 109 problem function-size /src/lib/process/restrict.c:set_max_file_descriptors() 102 diff --git a/scripts/maint/update_versions.py b/scripts/maint/update_versions.py index 8067f2c6c8..706a93b6a2 100755 --- a/scripts/maint/update_versions.py +++ b/scripts/maint/update_versions.py @@ -95,7 +95,7 @@ def update_file(fname, replace_on_change(fname, have_changed) # Find out our version -with open("configure.ac") as f: +with open(P("configure.ac")) as f: version = find_version(f) # If we have no version, we can't proceed. 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. *
  • 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.) *
  • 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.) *
  • 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 old to new - * 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, * old_options 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 (options_act_bridge_stats(old_options) < 0) + return -1; - 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 (dns_reset()) + return -1; - 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 (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 (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."); + /* 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 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(); + 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(); - /* 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"); + 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 *msg using string desc, 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 options-\>PublishServerDescriptor - * and write it to options-\>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) - return -1; - if (ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee, - "AuthDirGuardBWGuarantee", 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_validate_relay_bandwidth(old_options, options, msg) < 0) + return -1; + if (options_validate_dirauth_bandwidth(old_options, options, msg) < 0) + return -1; 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 (options_validate_relay_accounting(old_options, options, msg) < 0) + return -1; - 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 (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 old_options to new_options - * 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 old_options to new_options - * 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 lst 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 defaults_file 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 line, return its - * string. Return NULL if the line was not - * well-formed. - * - * If transport is set, return NULL if the line is not - * referring to transport. - * - * 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 line, return a smartlist - * with the options. Return NULL if the line was not well-formed. - * - * If transport is set, return NULL if the line is not - * referring to transport. - * - * 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 transport, check - * the configuration file to see if the user has explicitly asked for - * it to listen on a specific port. Return a 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 transport, 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 line. If * validate_only is 0, and the line is well-formed, and it * shares any bits with required_type or required_type @@ -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 port */ -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 ports 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 ports, warn if any controller port * there is listening on any non-loopback address. If forbid_nonlocal * is true, then emit a stronger warning and remove the port from the list. @@ -6865,55 +5744,6 @@ warn_client_dns_cache(const char *option, int disabling) "to your destination."); } -/** - * Validate the configured bridge distribution method from a BridgeDistribution - * config line. - * - * The input bd, 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. * @@ -6944,8 +5774,8 @@ check_bridge_distribution_setting(const char *bd) * out 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 * listenertype. 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 port_cfg_t in ports, check them for internal - * consistency and warn as appropriate. Set *n_low_ports_out 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 *answer to a * new string describing the supported configuration variables and their diff --git a/src/app/config/config.h b/src/app/config/config.h index 9cc77e2c69..eeba9e64d0 100644 --- a/src/app/config/config.h +++ b/src/app/config/config.h @@ -31,7 +31,6 @@ #define MAX_DEFAULT_MEMORY_QUEUE_SIZE (UINT64_C(2) << 30) #endif -MOCK_DECL(const char*, get_dirportfrontpage, (void)); MOCK_DECL(const or_options_t *, get_options, (void)); MOCK_DECL(or_options_t *, get_options_mutable, (void)); int set_options(or_options_t *new_val, char **msg); @@ -163,6 +162,8 @@ int write_to_data_subdir(const char* subdir, const char* fname, int get_num_cpus(const or_options_t *options); MOCK_DECL(const smartlist_t *,get_configured_ports,(void)); +int port_binds_ipv4(const port_cfg_t *port); +int port_binds_ipv6(const port_cfg_t *port); int get_first_advertised_port_by_type_af(int listener_type, int address_family); #define get_primary_or_port() \ @@ -181,17 +182,10 @@ char *get_first_listener_addrport_string(int listener_type); int options_need_geoip_info(const or_options_t *options, const char **reason_out); -smartlist_t *get_list_of_ports_to_forward(void); - int getinfo_helper_config(control_connection_t *conn, const char *question, char **answer, const char **errmsg); -uint32_t get_effective_bwrate(const or_options_t *options); -uint32_t get_effective_bwburst(const or_options_t *options); - -char *get_transport_bindaddr_from_config(const char *transport); - int init_cookie_authentication(const char *fname, const char *header, int cookie_len, int group_readable, uint8_t **cookie_out, int *cookie_is_set_out); @@ -246,14 +240,16 @@ void bridge_line_free_(bridge_line_t *bridge_line); #define bridge_line_free(line) \ FREE_AND_NULL(bridge_line_t, bridge_line_free_, (line)) bridge_line_t *parse_bridge_line(const char *line); -smartlist_t *get_options_from_transport_options_line(const char *line, - const char *transport); -smartlist_t *get_options_for_server_transport(const char *transport); /* Port helper functions. */ int options_any_client_port_set(const or_options_t *options); - -#ifdef CONFIG_PRIVATE +int port_parse_config(smartlist_t *out, + const struct config_line_t *ports, + const char *portname, + int listener_type, + const char *defaultaddr, + int defaultport, + const unsigned flags); #define CL_PORT_NO_STREAM_OPTIONS (1u<<0) #define CL_PORT_WARN_NONLOCAL (1u<<1) @@ -264,24 +260,32 @@ int options_any_client_port_set(const or_options_t *options); #define CL_PORT_IS_UNIXSOCKET (1u<<6) #define CL_PORT_DFLT_GROUP_WRITABLE (1u<<7) +port_cfg_t *port_cfg_new(size_t namelen); +#define port_cfg_free(port) \ + FREE_AND_NULL(port_cfg_t, port_cfg_free_, (port)) +void port_cfg_free_(port_cfg_t *port); + +int port_count_real_listeners(const smartlist_t *ports, + int listenertype, + int count_sockets); +int pt_parse_transport_line(const or_options_t *options, + const char *line, int validate_only, + int server); +int config_ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg); + +#ifdef CONFIG_PRIVATE + MOCK_DECL(STATIC int, options_act,(const or_options_t *old_options)); MOCK_DECL(STATIC int, options_act_reversible,(const or_options_t *old_options, char **msg)); struct config_mgr_t; STATIC const struct config_mgr_t *get_options_mgr(void); -STATIC port_cfg_t *port_cfg_new(size_t namelen); -#define port_cfg_free(port) \ - FREE_AND_NULL(port_cfg_t, port_cfg_free_, (port)) -STATIC void port_cfg_free_(port_cfg_t *port); #define or_options_free(opt) \ FREE_AND_NULL(or_options_t, or_options_free_, (opt)) STATIC void or_options_free_(or_options_t *options); STATIC int options_validate_single_onion(or_options_t *options, char **msg); -STATIC int parse_transport_line(const or_options_t *options, - const char *line, int validate_only, - int server); STATIC int consider_adding_dir_servers(const or_options_t *options, const or_options_t *old_options); STATIC void add_default_trusted_dir_authorities(dirinfo_type_t type); @@ -290,17 +294,6 @@ STATIC int parse_dir_authority_line(const char *line, dirinfo_type_t required_type, int validate_only); STATIC int parse_dir_fallback_line(const char *line, int validate_only); -STATIC int have_enough_mem_for_dircache(const or_options_t *options, - size_t total_mem, char **msg); -STATIC int parse_port_config(smartlist_t *out, - const struct config_line_t *ports, - const char *portname, - int listener_type, - const char *defaultaddr, - int defaultport, - const unsigned flags); - -STATIC int check_bridge_distribution_setting(const char *bd); STATIC uint64_t compute_real_max_mem_in_queues(const uint64_t val, int log_guess); diff --git a/src/app/config/statefile.c b/src/app/config/statefile.c index 1d6f63cdeb..db4d780a78 100644 --- a/src/app/config/statefile.c +++ b/src/app/config/statefile.c @@ -32,6 +32,7 @@ #include "core/or/or.h" #include "core/or/circuitstats.h" #include "app/config/config.h" +#include "feature/relay/transport_config.h" #include "lib/confmgt/confmgt.h" #include "core/mainloop/mainloop.h" #include "core/mainloop/netstatus.h" @@ -638,7 +639,7 @@ get_stored_bindaddr_for_server_transport(const char *transport) { /* See if the user explicitly asked for a specific listening address for this transport. */ - char *conf_bindaddr = get_transport_bindaddr_from_config(transport); + char *conf_bindaddr = pt_get_bindaddr_from_config(transport); if (conf_bindaddr) return conf_bindaddr; } diff --git a/src/app/main/shutdown.c b/src/app/main/shutdown.c index 93d6351d1b..cc07b921c3 100644 --- a/src/app/main/shutdown.c +++ b/src/app/main/shutdown.c @@ -45,6 +45,7 @@ #include "feature/nodelist/routerlist.h" #include "feature/nodelist/routerlist.h" #include "feature/relay/ext_orport.h" +#include "feature/relay/relay_config.h" #include "feature/rend/rendcache.h" #include "feature/rend/rendclient.h" #include "feature/stats/geoip_stats.h" @@ -143,6 +144,7 @@ tor_free_all(int postfork) if (!postfork) { config_free_all(); + relay_config_free_all(); or_state_free_all(); } if (!postfork) { diff --git a/src/core/include.am b/src/core/include.am index 565668abe3..a69914619e 100644 --- a/src/core/include.am +++ b/src/core/include.am @@ -171,14 +171,17 @@ endif LIBTOR_APP_TESTING_A_SOURCES = $(LIBTOR_APP_A_SOURCES) # The Relay module. -MODULE_RELAY_SOURCES = \ - src/feature/relay/routermode.c +MODULE_RELAY_SOURCES = \ + src/feature/relay/routermode.c \ + src/feature/relay/relay_config.c \ + src/feature/relay/transport_config.c # The Directory Authority module. -MODULE_DIRAUTH_SOURCES = \ +MODULE_DIRAUTH_SOURCES = \ src/feature/dirauth/authmode.c \ src/feature/dirauth/bridgeauth.c \ src/feature/dirauth/bwauth.c \ + src/feature/dirauth/dirauth_config.c \ src/feature/dirauth/dirauth_periodic.c \ src/feature/dirauth/dirauth_sys.c \ src/feature/dirauth/dircollate.c \ @@ -336,6 +339,7 @@ noinst_HEADERS += \ src/feature/dirauth/authmode.h \ src/feature/dirauth/bridgeauth.h \ src/feature/dirauth/bwauth.h \ + src/feature/dirauth/dirauth_config.h \ src/feature/dirauth/dirauth_periodic.h \ src/feature/dirauth/dirauth_sys.h \ src/feature/dirauth/dircollate.h \ @@ -428,12 +432,14 @@ noinst_HEADERS += \ src/feature/relay/dns_structs.h \ src/feature/relay/ext_orport.h \ src/feature/relay/onion_queue.h \ + src/feature/relay/relay_config.h \ src/feature/relay/relay_periodic.h \ src/feature/relay/relay_sys.h \ src/feature/relay/router.h \ src/feature/relay/routerkeys.h \ src/feature/relay/routermode.h \ src/feature/relay/selftest.h \ + src/feature/relay/transport_config.h \ src/feature/rend/rend_authorized_client_st.h \ src/feature/rend/rend_encoded_v2_service_descriptor_st.h \ src/feature/rend/rend_intro_point_st.h \ diff --git a/src/feature/client/transports.c b/src/feature/client/transports.c index 3f731ac7d4..6537a4b2da 100644 --- a/src/feature/client/transports.c +++ b/src/feature/client/transports.c @@ -97,6 +97,8 @@ #include "core/or/circuitbuild.h" #include "feature/client/transports.h" #include "feature/relay/router.h" +/* 31851: split the server transport code out of the client module */ +#include "feature/relay/transport_config.h" #include "app/config/statefile.h" #include "core/or/connection_or.h" #include "feature/relay/ext_orport.h" @@ -1279,7 +1281,7 @@ get_transport_options_for_server_proxy(const managed_proxy_t *mp) string. */ SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, const char *, transport) { smartlist_t *options_tmp_sl = NULL; - options_tmp_sl = get_options_for_server_transport(transport); + options_tmp_sl = pt_get_options_for_server_transport(transport); if (!options_tmp_sl) continue; diff --git a/src/feature/dirauth/dirauth_config.c b/src/feature/dirauth/dirauth_config.c new file mode 100644 index 0000000000..552f851461 --- /dev/null +++ b/src/feature/dirauth/dirauth_config.c @@ -0,0 +1,440 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file dirauth_config.c + * @brief Code to interpret the user's configuration of Tor's directory + * authority module. + **/ + +#include "orconfig.h" +#include "feature/dirauth/dirauth_config.h" + +#include "lib/encoding/confline.h" +#include "lib/confmgt/confmgt.h" + +/* Required for dirinfo_type_t in or_options_t */ +#include "core/or/or.h" +#include "app/config/config.h" + +#include "feature/dircommon/voting_schedule.h" +#include "feature/stats/rephist.h" + +#include "feature/dirauth/authmode.h" +#include "feature/dirauth/bwauth.h" +#include "feature/dirauth/dirauth_periodic.h" +#include "feature/dirauth/dirvote.h" +#include "feature/dirauth/guardfraction.h" + +/* Copied from config.c, we will refactor later in 29211. */ +#define REJECT(arg) \ + STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END +#if defined(__GNUC__) && __GNUC__ <= 3 +#define COMPLAIN(args...) \ + STMT_BEGIN log_warn(LD_CONFIG, args); STMT_END +#else +#define COMPLAIN(args, ...) \ + STMT_BEGIN log_warn(LD_CONFIG, args, ##__VA_ARGS__); STMT_END +#endif /* defined(__GNUC__) && __GNUC__ <= 3 */ + +#define YES_IF_CHANGED_INT(opt) \ + if (!CFG_EQ_INT(old_options, new_options, opt)) return 1; + +/** + * Legacy validation/normalization function for the dirauth mode options in + * options. Uses old_options as the previous options. + * + * Returns 0 on success, returns -1 and sets *msg to a newly allocated string + * on error. + */ +int +options_validate_dirauth_mode(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + if (BUG(!options)) + return -1; + + if (BUG(!msg)) + return -1; + + if (!authdir_mode(options)) + return 0; + + /* 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 (!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."); + + 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); + + 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."); + + /* 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); + } + + if (!options->DirPort_set) + REJECT("Running as authoritative directory, but no DirPort set."); + + if (!options->ORPort_set) + REJECT("Running as authoritative directory, but no ORPort set."); + + if (options->ClientOnly) + REJECT("Running as authoritative directory, but ClientOnly also set."); + + if (options->MinUptimeHidServDirectoryV2 < 0) { + log_warn(LD_CONFIG, "MinUptimeHidServDirectoryV2 option must be at " + "least 0 seconds. Changing to 0."); + options->MinUptimeHidServDirectoryV2 = 0; + } + + return 0; +} + +/** + * Legacy validation/normalization function for the dirauth bandwidth options + * in options. Uses old_options as the previous options. + * + * Returns 0 on success, returns -1 and sets *msg to a newly allocated string + * on error. + */ +int +options_validate_dirauth_bandwidth(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + if (BUG(!options)) + return -1; + + if (BUG(!msg)) + return -1; + + if (!authdir_mode(options)) + return 0; + + if (config_ensure_bandwidth_cap(&options->AuthDirFastGuarantee, + "AuthDirFastGuarantee", msg) < 0) + return -1; + if (config_ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee, + "AuthDirGuardBWGuarantee", msg) < 0) + return -1; + + return 0; +} + +/** + * Legacy validation/normalization function for the dirauth schedule options + * in options. Uses old_options as the previous options. + * + * Returns 0 on success, returns -1 and sets *msg to a newly allocated string + * on error. + */ +int +options_validate_dirauth_schedule(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + if (BUG(!options)) + return -1; + + if (BUG(!msg)) + return -1; + + if (!authdir_mode_v3(options)) + return 0; + + if (options->V3AuthVoteDelay + options->V3AuthDistDelay >= + options->V3AuthVotingInterval/2) { + 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) { + /* Unreachable, covered by earlier checks */ + REJECT("V3AuthVotingInterval is insanely low."); /* LCOV_EXCL_LINE */ + } 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."); + } + + return 0; +} + +/** + * Legacy validation/normalization function for the dirauth testing options + * in options. Uses old_options as the previous options. + * + * Returns 0 on success, returns -1 and sets *msg to a newly allocated string + * on error. + */ +int +options_validate_dirauth_testing(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + if (BUG(!options)) + return -1; + + if (BUG(!msg)) + return -1; + + if (!authdir_mode(options)) + return 0; + + if (options->TestingAuthDirTimeToLearnReachability < 0) { + REJECT("TestingAuthDirTimeToLearnReachability must be non-negative."); + } else if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) { + COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high."); + } + + if (!authdir_mode_v3(options)) + return 0; + + 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."); + } + + return 0; +} + +/** + * Return true if changing the configuration from old to new + * 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 dirauth actions based on it. All of + * the things we do should survive being done repeatedly. If present, + * old_options contains the previous value of the 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 + * into the options_act* functions yet. Some is still in do_hup() and other + * places. + */ +int +options_act_dirauth(const or_options_t *old_options) +{ + const or_options_t *options = get_options(); + + /* We may need to reschedule some dirauth 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); + } + } + + return 0; +} + +/** Fetch the active option list, and take dirauth mtbf actions based on it. + * All of the things we do should survive being done repeatedly. If present, + * old_options contains the previous value of the options. + * + * Must be called immediately after a successful or_state_load(). + * + * 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 + * into the options_act* functions yet. Some is still in do_hup() and other + * places. + */ +int +options_act_dirauth_mtbf(const or_options_t *old_options) +{ + (void)old_options; + + const or_options_t *options = get_options(); + int running_tor = options->command == CMD_RUN_TOR; + + if (!authdir_mode(options)) + return 0; + + /* Load dirauth state */ + if (running_tor) { + rep_hist_load_mtbf_data(time(NULL)); + } + + return 0; +} + +/** Fetch the active option list, and take dirauth statistics actions based + * on it. All of the things we do should survive being done repeatedly. If + * present, old_options contains the previous value of the options. + * + * Sets *print_notice_out if we enabled stats, and need to print + * a stats log using options_act_relay_stats_msg(). + * + * 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 + * into the options_act* functions yet. Some is still in do_hup() and other + * places. + */ +int +options_act_dirauth_stats(const or_options_t *old_options, + bool *print_notice_out) +{ + if (BUG(!print_notice_out)) + return -1; + + const or_options_t *options = get_options(); + + if (authdir_mode_bridge(options)) { + time_t now = time(NULL); + int print_notice = 0; + + if (!old_options || !authdir_mode_bridge(old_options)) { + rep_hist_desc_stats_init(now); + print_notice = 1; + } + if (print_notice) + *print_notice_out = 1; + } + + /* If we used to have statistics enabled but we just disabled them, + stop gathering them. */ + if (old_options && authdir_mode_bridge(old_options) && + !authdir_mode_bridge(options)) + rep_hist_desc_stats_term(); + + return 0; +} diff --git a/src/feature/dirauth/dirauth_config.h b/src/feature/dirauth/dirauth_config.h new file mode 100644 index 0000000000..655ab0a7fa --- /dev/null +++ b/src/feature/dirauth/dirauth_config.h @@ -0,0 +1,87 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file dirauth_config.h + * @brief Header for feature/dirauth/dirauth_config.c + **/ + +#ifndef TOR_FEATURE_DIRAUTH_DIRAUTH_CONFIG_H +#define TOR_FEATURE_DIRAUTH_DIRAUTH_CONFIG_H + +typedef struct or_options_t or_options_t; + +#ifdef HAVE_MODULE_DIRAUTH + +#include "lib/cc/torint.h" + +int options_validate_dirauth_mode(const or_options_t *old_options, + or_options_t *options, + char **msg); + +int options_validate_dirauth_bandwidth(const or_options_t *old_options, + or_options_t *options, + char **msg); + +int options_validate_dirauth_schedule(const or_options_t *old_options, + or_options_t *options, + char **msg); + +int options_validate_dirauth_testing(const or_options_t *old_options, + or_options_t *options, + char **msg); + +int options_act_dirauth(const or_options_t *old_options); +int options_act_dirauth_mtbf(const or_options_t *old_options); +int options_act_dirauth_stats(const or_options_t *old_options, + bool *print_notice_out); + +#else /* !defined(HAVE_MODULE_DIRAUTH) */ + +/** When tor is compiled with the dirauth module disabled, it can't be + * configured as a directory authority. + * + * Returns -1 and sets msg to a newly allocated string, if AuthoritativeDir + * is set in options. Otherwise returns 0. */ +static inline int +options_validate_dirauth_mode(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + /* Only check the primary option for now, #29211 will disable more + * options. */ + if (options->AuthoritativeDir) { + /* REJECT() this configuration */ + *msg = tor_strdup("This tor was built with dirauth mode disabled. " + "It can not be configured with AuthoritativeDir 1."); + return -1; + } + + return 0; +} + +#define options_validate_dirauth_bandwidth(old_options, options, msg) \ + (((void)(old_options)),((void)(options)),((void)(msg)),0) +#define options_validate_dirauth_schedule(old_options, options, msg) \ + (((void)(old_options)),((void)(options)),((void)(msg)),0) +#define options_validate_dirauth_testing(old_options, options, msg) \ + (((void)(old_options)),((void)(options)),((void)(msg)),0) +#define options_validate_dirauth_testing(old_options, options, msg) \ + (((void)(old_options)),((void)(options)),((void)(msg)),0) + +#define options_act_dirauth(old_options) \ + (((void)(old_options)),0) +#define options_act_dirauth_mtbf(old_options) \ + (((void)(old_options)),0) + +#define options_act_dirauth_stats(old_options, print_notice_out) \ + (((void)(old_options)),((void)(print_notice_out)),0) + +#endif /* defined(HAVE_MODULE_DIRAUTH) */ + +#endif /* !defined(TOR_FEATURE_DIRAUTH_DIRAUTH_CONFIG_H) */ diff --git a/src/feature/dircache/dircache.c b/src/feature/dircache/dircache.c index 795f1b8ed7..9938f9426c 100644 --- a/src/feature/dircache/dircache.c +++ b/src/feature/dircache/dircache.c @@ -28,6 +28,7 @@ #include "feature/nodelist/authcert.h" #include "feature/nodelist/networkstatus.h" #include "feature/nodelist/routerlist.h" +#include "feature/relay/relay_config.h" #include "feature/relay/routermode.h" #include "feature/rend/rendcache.h" #include "feature/stats/geoip_stats.h" @@ -478,7 +479,7 @@ static int handle_get_frontpage(dir_connection_t *conn, const get_handler_args_t *args) { (void) args; /* unused */ - const char *frontpage = get_dirportfrontpage(); + const char *frontpage = relay_get_dirportfrontpage(); if (frontpage) { size_t dlen; diff --git a/src/feature/relay/relay_config.c b/src/feature/relay/relay_config.c new file mode 100644 index 0000000000..275e0e6a68 --- /dev/null +++ b/src/feature/relay/relay_config.c @@ -0,0 +1,1440 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file relay_config.c + * @brief Code to interpret the user's configuration of Tor's relay module. + **/ + +#include "orconfig.h" +#define RELAY_CONFIG_PRIVATE +#include "feature/relay/relay_config.h" + +#include "lib/encoding/confline.h" +#include "lib/confmgt/confmgt.h" + +#include "lib/container/smartlist.h" +#include "lib/geoip/geoip.h" +#include "lib/meminfo/meminfo.h" +#include "lib/osinfo/uname.h" +#include "lib/process/setuid.h" + +/* Required for dirinfo_type_t in or_options_t */ +#include "core/or/or.h" +#include "app/config/config.h" + +#include "core/mainloop/connection.h" +#include "core/mainloop/cpuworker.h" +#include "core/mainloop/mainloop.h" +#include "core/or/circuitbuild.h" +#include "core/or/connection_or.h" +#include "core/or/port_cfg_st.h" + +#include "feature/hibernate/hibernate.h" +#include "feature/nodelist/nickname.h" +#include "feature/stats/geoip_stats.h" +#include "feature/stats/predict_ports.h" +#include "feature/stats/rephist.h" + +#include "feature/dirauth/authmode.h" + +#include "feature/dircache/consdiffmgr.h" +#include "feature/relay/dns.h" +#include "feature/relay/routermode.h" + +/** Contents of most recently read DirPortFrontPage file. */ +static char *global_dirfrontpagecontents = NULL; + +/* Copied from config.c, we will refactor later in 29211. */ +#define REJECT(arg) \ + STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END +#if defined(__GNUC__) && __GNUC__ <= 3 +#define COMPLAIN(args...) \ + STMT_BEGIN log_warn(LD_CONFIG, args); STMT_END +#else +#define COMPLAIN(args, ...) \ + STMT_BEGIN log_warn(LD_CONFIG, args, ##__VA_ARGS__); STMT_END +#endif /* defined(__GNUC__) && __GNUC__ <= 3 */ + +/* 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; +#define YES_IF_CHANGED_INT(opt) \ + if (!CFG_EQ_INT(old_options, new_options, opt)) return 1; +#define YES_IF_CHANGED_STRING(opt) \ + if (!CFG_EQ_STRING(old_options, new_options, opt)) return 1; +#define YES_IF_CHANGED_LINELIST(opt) \ + if (!CFG_EQ_LINELIST(old_options, new_options, opt)) return 1; + +/** Return the contents of our frontpage string, or NULL if not configured. */ +MOCK_IMPL(const char*, +relay_get_dirportfrontpage, (void)) +{ + return global_dirfrontpagecontents; +} + +/** Release all memory and resources held by global relay configuration + * structures. + */ +void +relay_config_free_all(void) +{ + tor_free(global_dirfrontpagecontents); +} + +/** Return the bandwidthrate that we are going to report to the authorities + * based on the config options. */ +uint32_t +relay_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; + /* config_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 +relay_get_effective_bwburst(const or_options_t *options) +{ + uint64_t bw = options->BandwidthBurst; + if (options->RelayBandwidthBurst > 0 && bw > options->RelayBandwidthBurst) + bw = options->RelayBandwidthBurst; + /* config_ensure_bandwidth_cap() makes sure that this cast can't overflow. */ + return (uint32_t)bw; +} + +/** Warn for every Extended ORPort port in ports that is on a + * publicly routable address. */ +void +port_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 ports, check them for internal + * consistency and warn as appropriate. On Unix-based OSes, set + * *n_low_ports_out to the number of sub-1024 ports we will be + * binding, and warn if we may be unable to re-bind after hibernation. */ +static int +check_server_ports(const smartlist_t *ports, + const or_options_t *options, + int *n_low_ports_out) +{ + if (BUG(!ports)) + return -1; + + if (BUG(!options)) + return -1; + + if (BUG(!n_low_ports_out)) + return -1; + + 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; +} + +/** Parse all relay ports from options. On success, add parsed ports to + * ports, and return 0. On failure, set *msg to a description + * of the problem and return -1. + **/ +int +port_parse_ports_relay(or_options_t *options, + char **msg, + smartlist_t *ports_out, + int *have_low_ports_out) +{ + int retval = -1; + smartlist_t *ports = smartlist_new(); + int n_low_ports = 0; + + if (BUG(!options)) + goto err; + + if (BUG(!msg)) + goto err; + + if (BUG(!ports_out)) + goto err; + + if (BUG(!have_low_ports_out)) + goto err; + + if (options->ClientOnly) { + retval = 0; + goto err; + } + + if (port_parse_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 (port_parse_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 (port_parse_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; + } + + if (check_server_ports(ports, options, &n_low_ports) < 0) { + *msg = tor_strdup("Misconfigured server ports"); + goto err; + } + + smartlist_add_all(ports_out, ports); + smartlist_free(ports); + ports = NULL; + retval = 0; + + err: + if (*have_low_ports_out < 0) + *have_low_ports_out = (n_low_ports > 0); + if (ports) { + SMARTLIST_FOREACH(ports, port_cfg_t *, p, port_cfg_free(p)); + smartlist_free(ports); + } + return retval; +} + +/** Update the relay *Port_set values in options from ports. */ +void +port_update_port_set_relay(or_options_t *options, + const smartlist_t *ports) +{ + if (BUG(!options)) + return; + + if (BUG(!ports)) + return; + + if (options->ClientOnly) + return; + + /* Update the relay *Port_set options. The !! here is to force a boolean + * out of an integer. */ + options->ORPort_set = + !! port_count_real_listeners(ports, CONN_TYPE_OR_LISTENER, 0); + options->DirPort_set = + !! port_count_real_listeners(ports, CONN_TYPE_DIR_LISTENER, 0); + options->ExtORPort_set = + !! port_count_real_listeners(ports, CONN_TYPE_EXT_OR_LISTENER, 0); +} + +/** + * Legacy validation function, which checks that the current OS is usable in + * relay mode, if options is set to a relay mode. + * + * Warns about OSes with potential issues. Always returns 0. + */ +int +options_validate_relay_os(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + if (BUG(!options)) + return -1; + + if (BUG(!msg)) + return -1; + + if (!server_mode(options)) + return 0; + + const char *uname = get_uname(); + + if (!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); + } + + return 0; +} + +/** + * Legacy validation/normalization function for the relay info options. + * Uses old_options as the previous options. + * + * Returns 0 on success, returns -1 and sets *msg to a newly allocated string + * on error. + */ +int +options_validate_relay_info(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + if (BUG(!options)) + return -1; + + if (BUG(!msg)) + return -1; + + 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."); + + return 0; +} + +/** Parse an authority type from options-\>PublishServerDescriptor + * and write it to options-\>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; +} + +/** + * Validate the configured bridge distribution method from a BridgeDistribution + * config line. + * + * The input bd, 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. + } +} + +/** + * Legacy validation/normalization function for the bridge relay options. + * Uses old_options as the previous options. + * + * Returns 0 on success, returns -1 and sets *msg to a newly allocated string + * on error. + */ +int +options_validate_publish_server(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + if (BUG(!options)) + return -1; + + if (BUG(!msg)) + return -1; + + if (compute_publishserverdescriptor(options) < 0) { + tor_asprintf(msg, "Unrecognized value in PublishServerDescriptor"); + 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->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->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; + } + }); + + return 0; +} + +/** + * Legacy validation/normalization function for the relay padding options. + * Uses old_options as the previous options. + * + * Returns 0 on success, returns -1 and sets *msg to a newly allocated string + * on error. + */ +int +options_validate_relay_padding(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + if (BUG(!options)) + return -1; + + if (BUG(!msg)) + return -1; + + if (!server_mode(options)) + return 0; + + if (options->ConnectionPadding != -1) { + REJECT("Relays must use 'auto' for the ConnectionPadding setting."); + } + + if (options->ReducedConnectionPadding != 0) { + REJECT("Relays cannot set ReducedConnectionPadding. "); + } + + if (options->CircuitPadding == 0) { + REJECT("Relays cannot set CircuitPadding to 0. "); + } + + if (options->ReducedCircuitPadding == 1) { + REJECT("Relays cannot set ReducedCircuitPadding. "); + } + + return 0; +} + +/** + * Legacy validation/normalization function for the relay bandwidth options. + * Uses old_options as the previous options. + * + * Returns 0 on success, returns -1 and sets *msg to a newly allocated string + * on error. + */ +int +options_validate_relay_bandwidth(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + if (BUG(!options)) + return -1; + + if (BUG(!msg)) + return -1; + + /* 31851: the tests expect us to validate bandwidths, even when we are not + * in relay mode. */ + if (config_ensure_bandwidth_cap(&options->MaxAdvertisedBandwidth, + "MaxAdvertisedBandwidth", msg) < 0) + return -1; + if (config_ensure_bandwidth_cap(&options->RelayBandwidthRate, + "RelayBandwidthRate", msg) < 0) + return -1; + if (config_ensure_bandwidth_cap(&options->RelayBandwidthBurst, + "RelayBandwidthBurst", msg) < 0) + return -1; + if (config_ensure_bandwidth_cap(&options->PerConnBWRate, + "PerConnBWRate", msg) < 0) + return -1; + if (config_ensure_bandwidth_cap(&options->PerConnBWBurst, + "PerConnBWBurst", 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; + } + } + + /* 31851: the tests expect us to validate bandwidths, even when we are not + * in relay mode. */ + if (options->RelayBandwidthRate > options->RelayBandwidthBurst) + REJECT("RelayBandwidthBurst must be at least equal " + "to RelayBandwidthRate."); + + /* 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; + + return 0; +} + +/** + * Legacy validation/normalization function for the relay bandwidth accounting + * options. Uses old_options as the previous options. + * + * Returns 0 on success, returns -1 and sets *msg to a newly allocated string + * on error. + */ +int +options_validate_relay_accounting(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + if (BUG(!options)) + return -1; + + if (BUG(!msg)) + return -1; + + /* 31851: the tests expect us to validate accounting, even when we are not + * in relay mode. */ + 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'"); + } + + return 0; +} + +/** Verify whether lst is a list of strings containing valid-looking + * comma-separated nicknames, or NULL. Will normalise lst 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; +} + +#define ONE_MEGABYTE (UINT64_C(1) << 20) + +/* 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 + +/** + * Legacy validation/normalization function for the relay mode options. + * Uses old_options as the previous options. + * + * Returns 0 on success, returns -1 and sets *msg to a newly allocated string + * on error. + */ +int +options_validate_relay_mode(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + if (BUG(!options)) + return -1; + + if (BUG(!msg)) + return -1; + + 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"); + + 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 (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->BridgeRelay == 1 && ! options->ORPort_set) + REJECT("BridgeRelay is 1, ORPort is not set. This is an invalid " + "combination."); + + 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->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; + + if (options->ConstrainedSockets) { + 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."); + } + } + + return 0; +} + +/** + * Legacy validation/normalization function for the relay testing options + * in options. Uses old_options as the previous options. + * + * Returns 0 on success, returns -1 and sets *msg to a newly allocated string + * on error. + */ +int +options_validate_relay_testing(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + if (BUG(!options)) + return -1; + + if (BUG(!msg)) + return -1; + + 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."); + + return 0; +} + +/** Return 1 if any change from old_options to new_options + * 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 old_options to new_options + * 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 (relay_get_effective_bwrate(old_options) != + relay_get_effective_bwrate(new_options) || + relay_get_effective_bwburst(old_options) != + relay_get_effective_bwburst(new_options) || + public_server_mode(old_options) != public_server_mode(new_options)) + return 1; + + return 0; +} + +/** Fetch the active option list, and take relay actions based on it. All of + * the things we do should survive being done repeatedly. If present, + * old_options contains the previous value of the 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 + * into the options_act* functions yet. Some is still in do_hup() and other + * places. + */ +int +options_act_relay(const or_options_t *old_options) +{ + const or_options_t *options = get_options(); + + const int transition_affects_workers = + old_options && options_transition_affects_workers(old_options, options); + + /* 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 || + (authdir_mode_v3(options) && (!old_options || + !authdir_mode_v3(old_options)))) { + if (init_keys() < 0) { + log_warn(LD_BUG,"Error initializing keys; exiting"); + return -1; + } + } + + if (server_mode(options)) { + static int cdm_initialized = 0; + if (cdm_initialized == 0) { + cdm_initialized = 1; + consdiffmgr_configure(NULL); + consdiffmgr_validate(); + } + } + + /* Check for transitions that need action. */ + if (old_options) { + 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 (server_mode_turned_on) { + ip_address_changed(0); + if (have_completed_a_circuit() || !any_predicted_circuits(time(NULL))) + inform_testing_reachability(); + } + cpuworkers_rotate_keyinfo(); + } + } + + return 0; +} + +/** Fetch the active option list, and take relay accounting actions based on + * it. All of the things we do should survive being done repeatedly. If + * present, old_options contains the previous value of the 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 + * into the options_act* functions yet. Some is still in do_hup() and other + * places. + */ +int +options_act_relay_accounting(const or_options_t *old_options) +{ + (void)old_options; + + const or_options_t *options = get_options(); + + /* Set up accounting */ + if (accounting_parse_options(options, 0)<0) { + // LCOV_EXCL_START + log_warn(LD_BUG,"Error in previously validated accounting options"); + return -1; + // LCOV_EXCL_STOP + } + if (accounting_is_enabled(options)) + configure_accounting(time(NULL)); + + return 0; +} + +/** Fetch the active option list, and take relay bandwidth actions based on + * it. All of the things we do should survive being done repeatedly. If + * present, old_options contains the previous value of the 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 + * into the options_act* functions yet. Some is still in do_hup() and other + * places. + */ +int +options_act_relay_bandwidth(const or_options_t *old_options) +{ + const or_options_t *options = get_options(); + + /* Check for transitions that need action. */ + if (old_options) { + if (options->PerConnBWRate != old_options->PerConnBWRate || + options->PerConnBWBurst != old_options->PerConnBWBurst) + connection_or_update_token_buckets(get_connection_array(), options); + + if (options->RelayBandwidthRate != old_options->RelayBandwidthRate || + options->RelayBandwidthBurst != old_options->RelayBandwidthBurst) + connection_bucket_adjust(options); + } + + return 0; +} + +/** Fetch the active option list, and take bridge statistics actions based on + * it. All of the things we do should survive being done repeatedly. If + * present, old_options contains the previous value of the 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 + * into the options_act* functions yet. Some is still in do_hup() and other + * places. + */ +int +options_act_bridge_stats(const or_options_t *old_options) +{ + const or_options_t *options = get_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) + + /* Check for transitions that need action. */ + if (old_options) { + 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."); + } + } + } + + return 0; +} + +/** Fetch the active option list, and take relay statistics actions based on + * it. All of the things we do should survive being done repeatedly. If + * present, old_options contains the previous value of the options. + * + * Sets *print_notice_out if we enabled stats, and need to print + * a stats log using options_act_relay_stats_msg(). + * + * If loading the GeoIP file failed, sets DirReqStatistics and + * EntryStatistics to 0. This breaks the normalization/act ordering + * introduced in 29211. + * + * 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 + * into the options_act* functions yet. Some is still in do_hup() and other + * places. + */ +int +options_act_relay_stats(const or_options_t *old_options, + bool *print_notice_out) +{ + if (BUG(!print_notice_out)) + return -1; + + or_options_t *options = get_options_mutable(); + + if (options->CellStatistics || options->DirReqStatistics || + options->EntryStatistics || options->ExitPortStatistics || + options->ConnDirectionStatistics || + options->HiddenServiceStatistics) { + time_t now = time(NULL); + int print_notice = 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 */ + /* 29211: refactor to avoid the normalisation/act inversion */ + 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 (print_notice) + *print_notice_out = 1; + } + + /* 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(); + + return 0; +} + +/** Print a notice about relay/dirauth stats being enabled. */ +void +options_act_relay_stats_msg(void) +{ + 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."); +} + +/** Fetch the active option list, and take relay descriptor actions based on + * it. All of the things we do should survive being done repeatedly. If + * present, old_options contains the previous value of the 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 + * into the options_act* functions yet. Some is still in do_hup() and other + * places. + */ +int +options_act_relay_desc(const or_options_t *old_options) +{ + const or_options_t *options = get_options(); + + /* 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"); + + return 0; +} + +/** Fetch the active option list, and take relay DoS actions based on + * it. All of the things we do should survive being done repeatedly. If + * present, old_options contains the previous value of the 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 + * into the options_act* functions yet. Some is still in do_hup() and other + * places. + */ +int +options_act_relay_dos(const or_options_t *old_options) +{ + const or_options_t *options = get_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(); + } + + return 0; +} + +/** Fetch the active option list, and take dirport actions based on + * it. All of the things we do should survive being done repeatedly. If + * present, old_options contains the previous value of the 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 + * into the options_act* functions yet. Some is still in do_hup() and other + * places. + */ +int +options_act_relay_dir(const or_options_t *old_options) +{ + (void)old_options; + + const or_options_t *options = get_options(); + + if (!public_server_mode(options)) + return 0; + + /* 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); + } + } + + return 0; +} diff --git a/src/feature/relay/relay_config.h b/src/feature/relay/relay_config.h new file mode 100644 index 0000000000..214f07efc2 --- /dev/null +++ b/src/feature/relay/relay_config.h @@ -0,0 +1,188 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file relay_config.h + * @brief Header for feature/relay/relay_config.c + **/ + +#ifndef TOR_FEATURE_RELAY_RELAY_CONFIG_H +#define TOR_FEATURE_RELAY_RELAY_CONFIG_H + +typedef struct or_options_t or_options_t; + +#ifdef HAVE_MODULE_RELAY + +#include "lib/cc/torint.h" +#include "lib/testsupport/testsupport.h" + +typedef struct smartlist_t smartlist_t; + +int options_validate_relay_mode(const or_options_t *old_options, + or_options_t *options, + char **msg); + +MOCK_DECL(const char*, relay_get_dirportfrontpage, (void)); +void relay_config_free_all(void); + +uint32_t relay_get_effective_bwrate(const or_options_t *options); +uint32_t relay_get_effective_bwburst(const or_options_t *options); + +void port_warn_nonlocal_ext_orports(const smartlist_t *ports, + const char *portname); + +int port_parse_ports_relay(or_options_t *options, + char **msg, + smartlist_t *ports_out, + int *have_low_ports_out); +void port_update_port_set_relay(or_options_t *options, + const smartlist_t *ports); + +int options_validate_relay_os(const or_options_t *old_options, + or_options_t *options, + char **msg); + +int options_validate_relay_info(const or_options_t *old_options, + or_options_t *options, + char **msg); + +int options_validate_publish_server(const or_options_t *old_options, + or_options_t *options, + char **msg); + +int options_validate_relay_padding(const or_options_t *old_options, + or_options_t *options, + char **msg); + +int options_validate_relay_bandwidth(const or_options_t *old_options, + or_options_t *options, + char **msg); + +int options_validate_relay_accounting(const or_options_t *old_options, + or_options_t *options, + char **msg); + +int options_validate_relay_testing(const or_options_t *old_options, + or_options_t *options, + char **msg); + +int options_act_relay(const or_options_t *old_options); +int options_act_relay_accounting(const or_options_t *old_options); +int options_act_relay_bandwidth(const or_options_t *old_options); +int options_act_bridge_stats(const or_options_t *old_options); + +int options_act_relay_stats(const or_options_t *old_options, + bool *print_notice_out); +void options_act_relay_stats_msg(void); + +int options_act_relay_desc(const or_options_t *old_options); +int options_act_relay_dos(const or_options_t *old_options); +int options_act_relay_dir(const or_options_t *old_options); + +#ifdef RELAY_CONFIG_PRIVATE + +STATIC int check_bridge_distribution_setting(const char *bd); +STATIC int have_enough_mem_for_dircache(const or_options_t *options, + size_t total_mem, char **msg); + +#endif /* defined(RELAY_CONFIG_PRIVATE) */ + +#else /* !defined(HAVE_MODULE_RELAY) */ + +#include "lib/cc/compat_compiler.h" + +/** When tor is compiled with the relay module disabled, it can't be + * configured as a relay or bridge. + * + * Always sets ClientOnly to 1. + * + * Returns -1 and sets msg to a newly allocated string, if ORPort, DirPort, + * DirCache, or BridgeRelay are set in options. Otherwise returns 0. */ +static inline int +options_validate_relay_mode(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + /* Only check the primary options for now, #29211 will disable more + * options. These ORPort and DirPort checks are too strict, and will + * reject valid configs that disable ports, like "ORPort 0". */ + if (options->DirCache || + options->BridgeRelay || + options->ORPort_lines || + options->DirPort_lines) { + /* REJECT() this configuration */ + *msg = tor_strdup("This tor was built with relay mode disabled. " + "It can not be configured with an ORPort, a DirPort, " + "DirCache 1, or BridgeRelay 1."); + return -1; + } + + /* 31851 / 29211: Set this option the correct way */ + options->ClientOnly = 1; + + return 0; +} + +#define relay_get_dirportfrontpage() \ + (NULL) +#define relay_config_free_all() \ + STMT_BEGIN STMT_END + +#define relay_get_effective_bwrate(options) \ + (((void)(options)),0) +#define relay_get_effective_bwburst(options) \ + (((void)(options)),0) + +#define port_warn_nonlocal_ext_orports(ports, portname) \ + (((void)(ports)),((void)(portname))) + +#define port_parse_ports_relay(options, msg, ports_out, have_low_ports_out) \ + (((void)(options)),((void)(msg)),((void)(ports_out)), \ + ((void)(have_low_ports_out)),0) +#define port_update_port_set_relay(options, ports) \ + (((void)(options)),((void)(ports))) + +#define options_validate_relay_os(old_options, options, msg) \ + (((void)(old_options)),((void)(options)),((void)(msg)),0) +#define options_validate_relay_info(old_options, options, msg) \ + (((void)(old_options)),((void)(options)),((void)(msg)),0) +#define options_validate_publish_server(old_options, options, msg) \ + (((void)(old_options)),((void)(options)),((void)(msg)),0) +#define options_validate_relay_padding(old_options, options, msg) \ + (((void)(old_options)),((void)(options)),((void)(msg)),0) +#define options_validate_relay_bandwidth(old_options, options, msg) \ + (((void)(old_options)),((void)(options)),((void)(msg)),0) +#define options_validate_relay_accounting(old_options, options, msg) \ + (((void)(old_options)),((void)(options)),((void)(msg)),0) +#define options_validate_relay_testing(old_options, options, msg) \ + (((void)(old_options)),((void)(options)),((void)(msg)),0) + +#define options_act_relay(old_options) \ + (((void)(old_options)),0) +#define options_act_relay_accounting(old_options) \ + (((void)(old_options)),0) +#define options_act_relay_bandwidth(old_options) \ + (((void)(old_options)),0) +#define options_act_bridge_stats(old_options) \ + (((void)(old_options)),0) + +#define options_act_relay_stats(old_options, print_notice_out) \ + (((void)(old_options)),((void)(print_notice_out)),0) +#define options_act_relay_stats_msg() \ + STMT_BEGIN STMT_END + +#define options_act_relay_desc(old_options) \ + (((void)(old_options)),0) +#define options_act_relay_dos(old_options) \ + (((void)(old_options)),0) +#define options_act_relay_dir(old_options) \ + (((void)(old_options)),0) + +#endif /* defined(HAVE_MODULE_RELAY) */ + +#endif /* !defined(TOR_FEATURE_RELAY_RELAY_CONFIG_H) */ diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c index 5c79010934..7f80b288de 100644 --- a/src/feature/relay/router.c +++ b/src/feature/relay/router.c @@ -35,6 +35,7 @@ #include "feature/nodelist/routerlist.h" #include "feature/nodelist/torcert.h" #include "feature/relay/dns.h" +#include "feature/relay/relay_config.h" #include "feature/relay/router.h" #include "feature/relay/routerkeys.h" #include "feature/relay/routermode.h" @@ -1222,7 +1223,7 @@ router_should_be_dirserver(const or_options_t *options, int dir_port) * much larger effect on output than input so there is no reason to turn it * off if using AccountingRule in. */ int interval_length = accounting_get_interval_length(); - uint32_t effective_bw = get_effective_bwrate(options); + uint32_t effective_bw = relay_get_effective_bwrate(options); uint64_t acc_bytes; if (!interval_length) { log_warn(LD_BUG, "An accounting interval is not allowed to be zero " @@ -2041,10 +2042,10 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out)) ri->protocol_list = tor_strdup(protover_get_supported_protocols()); /* compute ri->bandwidthrate as the min of various options */ - ri->bandwidthrate = get_effective_bwrate(options); + ri->bandwidthrate = relay_get_effective_bwrate(options); /* and compute ri->bandwidthburst similarly */ - ri->bandwidthburst = get_effective_bwburst(options); + ri->bandwidthburst = relay_get_effective_bwburst(options); /* Report bandwidth, unless we're hibernating or shutting down */ ri->bandwidthcapacity = hibernating ? 0 : rep_hist_bandwidth_assess(); diff --git a/src/feature/relay/transport_config.c b/src/feature/relay/transport_config.c new file mode 100644 index 0000000000..9d6be4bafd --- /dev/null +++ b/src/feature/relay/transport_config.c @@ -0,0 +1,307 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file transport_config.c + * @brief Code to interpret the user's configuration of Tor's server + * pluggable transports. + **/ + +#include "orconfig.h" +#define RELAY_TRANSPORT_CONFIG_PRIVATE +#include "feature/relay/transport_config.h" + +#include "lib/encoding/confline.h" +#include "lib/encoding/keyval.h" + +#include "lib/container/smartlist.h" + +/* Required for dirinfo_type_t in or_options_t */ +#include "core/or/or.h" +#include "app/config/config.h" + +#include "feature/relay/ext_orport.h" +#include "feature/relay/routermode.h" + +/* Copied from config.c, we will refactor later in 29211. */ +#define REJECT(arg) \ + STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END + +/** Given a ServerTransportListenAddr line, return its + * string. Return NULL if the line was not + * well-formed. + * + * If transport is set, return NULL if the line is not + * referring to transport. + * + * 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 the name of a pluggable transport in transport, check + * the configuration file to see if the user has explicitly asked for + * it to listen on a specific port. Return a string if + * so, otherwise NULL. */ +char * +pt_get_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 a ServerTransportOptions line, return a smartlist + * with the options. Return NULL if the line was not well-formed. + * + * If transport is set, return NULL if the line is not + * referring to transport. + * + * The returned smartlist and its strings are allocated on the heap + * and it's the responsibility of the caller to free it. */ +STATIC smartlist_t * +get_options_from_transport_options_line(const char *line, + const char *transport) +{ + smartlist_t *items = smartlist_new(); + smartlist_t *pt_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(pt_options, option); + log_debug(LD_CONFIG, "Added %s to the list of options", escaped(option)); + } SMARTLIST_FOREACH_END(option); + + goto done; + + err: + SMARTLIST_FOREACH(pt_options, char*, s, tor_free(s)); + smartlist_free(pt_options); + pt_options = NULL; + + done: + SMARTLIST_FOREACH(items, char*, s, tor_free(s)); + smartlist_free(items); + + return pt_options; +} + +/** Given the name of a pluggable transport in transport, 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 * +pt_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; +} + +/** + * Legacy validation/normalization function for the server transport options. + * Uses old_options as the previous options. + * + * Returns 0 on success, returns -1 and sets *msg to a newly allocated string + * on error. + */ +int +options_validate_server_transport(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + if (BUG(!options)) + return -1; + + if (BUG(!msg)) + return -1; + + config_line_t *cl; + + 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)); + } + + 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->ServerTransportPlugin; cl; cl = cl->next) { + if (pt_parse_transport_line(options, cl->value, 1, 1) < 0) + REJECT("Invalid server transport line. See logs for details."); + } + + 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); + } + + 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); + } + + return 0; +} + +/** Fetch the active option list, and take server pluggable transport actions + * based on it. All of the things we do should survive being done repeatedly. + * If present, old_options contains the previous value of the 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 + * into the options_act* functions yet. Some is still in do_hup() and other + * places. + */ +int +options_act_server_transport(const or_options_t *old_options) +{ + (void)old_options; + + config_line_t *cl; + const or_options_t *options = get_options(); + int running_tor = options->command == CMD_RUN_TOR; + + /* If we are a bridge with a pluggable transport proxy but no + Extended ORPort, inform the user that they are missing out. */ + if (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 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->DisableNetwork) { + if (options->ServerTransportPlugin) { + for (cl = options->ServerTransportPlugin; cl; cl = cl->next) { + if (pt_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 + } + } + } + } + + return 0; +} diff --git a/src/feature/relay/transport_config.h b/src/feature/relay/transport_config.h new file mode 100644 index 0000000000..d3cceb3698 --- /dev/null +++ b/src/feature/relay/transport_config.h @@ -0,0 +1,85 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * @file transport_config.h + * @brief Header for feature/relay/transport_config.c + **/ + +#ifndef TOR_FEATURE_RELAY_TRANSPORT_CONFIG_H +#define TOR_FEATURE_RELAY_TRANSPORT_CONFIG_H + +#ifdef HAVE_MODULE_RELAY + +#include "lib/testsupport/testsupport.h" + +typedef struct or_options_t or_options_t; +typedef struct smartlist_t smartlist_t; + +int options_validate_server_transport(const or_options_t *old_options, + or_options_t *options, + char **msg); + +char *pt_get_bindaddr_from_config(const char *transport); +smartlist_t *pt_get_options_for_server_transport(const char *transport); + +int options_act_server_transport(const or_options_t *old_options); + +#ifdef RELAY_TRANSPORT_CONFIG_PRIVATE + +STATIC smartlist_t *get_options_from_transport_options_line( + const char *line, + const char *transport); + +#endif /* defined(RELAY_TRANSPORT_CONFIG_PRIVATE) */ + +#else /* !defined(HAVE_MODULE_RELAY) */ + +/** When tor is compiled with the relay module disabled, it can't be + * configured with server pluggable transports. + * + * Returns -1 and sets msg to a newly allocated string, if ExtORPort, + * ServerTransportPlugin, ServerTransportListenAddr, or + * ServerTransportOptions are set in options. Otherwise returns 0. */ +static inline int +options_validate_server_transport(const or_options_t *old_options, + or_options_t *options, + char **msg) +{ + (void)old_options; + + /* These ExtORPort checks are too strict, and will reject valid configs + * that disable ports, like "ExtORPort 0". */ + if (options->ServerTransportPlugin || + options->ServerTransportListenAddr || + options->ServerTransportOptions || + options->ExtORPort_lines) { + /* REJECT() this configuration */ + *msg = tor_strdup("This tor was built with relay mode disabled. " + "It can not be configured with an ExtORPort, " + "a ServerTransportPlugin, a ServerTransportListenAddr, " + "or ServerTransportOptions."); + return -1; + } + + return 0; +} + +#define pt_get_bindaddr_from_config(transport) \ + (((void)(transport)),NULL) + +/* 31851: called from client/transports.c, but only from server code */ +#define pt_get_options_for_server_transport(transport) \ + (((void)(transport)),NULL) + +#define options_validate_server_transport(old_options, options, msg) \ + (((void)(old_options)),((void)(options)),((void)(msg)),0) +#define options_act_server_transport(old_options) \ + (((void)(old_options)),0) + +#endif /* defined(HAVE_MODULE_RELAY) */ + +#endif /* !defined(TOR_FEATURE_RELAY_TRANSPORT_CONFIG_H) */ diff --git a/src/lib/confmgt/confmgt.c b/src/lib/confmgt/confmgt.c index 1218a63ae3..3fdb630e8a 100644 --- a/src/lib/confmgt/confmgt.c +++ b/src/lib/confmgt/confmgt.c @@ -1307,9 +1307,10 @@ config_dump(const config_mgr_t *mgr, const void *default_options, */ continue; } - smartlist_add_asprintf(elements, "%s%s %s\n", + int value_exists = line->value && *(line->value); + smartlist_add_asprintf(elements, "%s%s%s%s\n", comment_option ? "# " : "", - line->key, line->value); + line->key, value_exists ? " " : "", line->value); } config_free_lines(assigned); } SMARTLIST_FOREACH_END(mv); @@ -1317,7 +1318,9 @@ config_dump(const config_mgr_t *mgr, const void *default_options, if (fmt->extra) { line = *(config_line_t**)STRUCT_VAR_P(options, fmt->extra->offset); for (; line; line = line->next) { - smartlist_add_asprintf(elements, "%s %s\n", line->key, line->value); + int value_exists = line->value && *(line->value); + smartlist_add_asprintf(elements, "%s%s%s\n", + line->key, value_exists ? " " : "", line->value); } } diff --git a/src/test/conf_examples/badnick_1/error_no_dirauth_relay b/src/test/conf_examples/badnick_1/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/badnick_1/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/badnick_2/error_no_dirauth_relay b/src/test/conf_examples/badnick_2/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/badnick_2/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/bridgeauth_1/error_no_dirauth b/src/test/conf_examples/bridgeauth_1/error_no_dirauth new file mode 100644 index 0000000000..e6bd5db69c --- /dev/null +++ b/src/test/conf_examples/bridgeauth_1/error_no_dirauth @@ -0,0 +1 @@ +This tor was built with dirauth mode disabled. diff --git a/src/test/conf_examples/bridgeauth_1/error_no_dirauth_relay b/src/test/conf_examples/bridgeauth_1/error_no_dirauth_relay new file mode 100644 index 0000000000..e6bd5db69c --- /dev/null +++ b/src/test/conf_examples/bridgeauth_1/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with dirauth mode disabled. diff --git a/src/test/conf_examples/bridgeauth_1/expected_no_dirauth b/src/test/conf_examples/bridgeauth_1/expected_no_dirauth deleted file mode 100644 index d43aaf2c8b..0000000000 --- a/src/test/conf_examples/bridgeauth_1/expected_no_dirauth +++ /dev/null @@ -1,7 +0,0 @@ -Address 198.51.100.123 -AuthoritativeDirectory 1 -BridgeAuthoritativeDir 1 -ContactInfo tor_parse_test@example.com -DirPort 80 -Nickname Unnamed -ORPort 443 diff --git a/src/test/conf_examples/bridgeauth_1/expected_no_dirauth_relay b/src/test/conf_examples/bridgeauth_1/expected_no_dirauth_relay deleted file mode 100644 index e059d79971..0000000000 --- a/src/test/conf_examples/bridgeauth_1/expected_no_dirauth_relay +++ /dev/null @@ -1,6 +0,0 @@ -Address 198.51.100.123 -AuthoritativeDirectory 1 -BridgeAuthoritativeDir 1 -ContactInfo tor_parse_test@example.com -DirPort 80 -ORPort 443 diff --git a/src/test/conf_examples/contactinfo_notutf8/error_no_dirauth_relay b/src/test/conf_examples/contactinfo_notutf8/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/contactinfo_notutf8/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/dirauth_1/error_no_dirauth b/src/test/conf_examples/dirauth_1/error_no_dirauth new file mode 100644 index 0000000000..e6bd5db69c --- /dev/null +++ b/src/test/conf_examples/dirauth_1/error_no_dirauth @@ -0,0 +1 @@ +This tor was built with dirauth mode disabled. diff --git a/src/test/conf_examples/dirauth_1/error_no_dirauth_relay b/src/test/conf_examples/dirauth_1/error_no_dirauth_relay new file mode 100644 index 0000000000..e6bd5db69c --- /dev/null +++ b/src/test/conf_examples/dirauth_1/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with dirauth mode disabled. diff --git a/src/test/conf_examples/dirauth_1/expected_no_dirauth b/src/test/conf_examples/dirauth_1/expected_no_dirauth deleted file mode 100644 index f006c6f8f2..0000000000 --- a/src/test/conf_examples/dirauth_1/expected_no_dirauth +++ /dev/null @@ -1,7 +0,0 @@ -Address 192.0.2.1 -AuthoritativeDirectory 1 -ContactInfo tor_parse_test@example.net -DirPort 9030 -Nickname Unnamed -ORPort 9001 -V3AuthoritativeDirectory 1 diff --git a/src/test/conf_examples/dirauth_1/expected_no_dirauth_relay b/src/test/conf_examples/dirauth_1/expected_no_dirauth_relay deleted file mode 100644 index 4b9ad49bb2..0000000000 --- a/src/test/conf_examples/dirauth_1/expected_no_dirauth_relay +++ /dev/null @@ -1,6 +0,0 @@ -Address 192.0.2.1 -AuthoritativeDirectory 1 -ContactInfo tor_parse_test@example.net -DirPort 9030 -ORPort 9001 -V3AuthoritativeDirectory 1 diff --git a/src/test/conf_examples/example_1/error_no_dirauth_relay b/src/test/conf_examples/example_1/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/example_1/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/example_3/error_no_dirauth_relay b/src/test/conf_examples/example_3/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/example_3/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/include_1/error_no_dirauth_relay b/src/test/conf_examples/include_1/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/include_1/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/include_bug_31408/error_no_dirauth_relay b/src/test/conf_examples/include_bug_31408/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/include_bug_31408/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/large_1/error_no_dirauth_relay b/src/test/conf_examples/large_1/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/large_1/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/ops_1/error_no_dirauth_relay b/src/test/conf_examples/ops_1/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/ops_1/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/ops_1/expected_no_dirauth_relay b/src/test/conf_examples/ops_1/expected_no_dirauth_relay deleted file mode 100644 index 2bb9bfa132..0000000000 --- a/src/test/conf_examples/ops_1/expected_no_dirauth_relay +++ /dev/null @@ -1 +0,0 @@ -ORPort 1000 diff --git a/src/test/conf_examples/ops_3/error_no_dirauth_relay b/src/test/conf_examples/ops_3/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/ops_3/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/ops_3/expected_no_dirauth_relay b/src/test/conf_examples/ops_3/expected_no_dirauth_relay deleted file mode 100644 index 93dea50eeb..0000000000 --- a/src/test/conf_examples/ops_3/expected_no_dirauth_relay +++ /dev/null @@ -1,2 +0,0 @@ -ORPort 9999 -ORPort 1000 diff --git a/src/test/conf_examples/ops_4/error_no_dirauth_relay b/src/test/conf_examples/ops_4/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/ops_4/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/ops_4/expected_no_dirauth_relay b/src/test/conf_examples/ops_4/expected_no_dirauth_relay deleted file mode 100644 index 56b3a5b71f..0000000000 --- a/src/test/conf_examples/ops_4/expected_no_dirauth_relay +++ /dev/null @@ -1 +0,0 @@ -ORPort 9099 diff --git a/src/test/conf_examples/ops_5/error_no_dirauth_relay b/src/test/conf_examples/ops_5/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/ops_5/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/ops_5/expected_no_dirauth_relay b/src/test/conf_examples/ops_5/expected_no_dirauth_relay deleted file mode 100644 index 834a785090..0000000000 --- a/src/test/conf_examples/ops_5/expected_no_dirauth_relay +++ /dev/null @@ -1,2 +0,0 @@ -ORPort 9000 -ORPort 9099 diff --git a/src/test/conf_examples/pt_01/error_no_dirauth_relay b/src/test/conf_examples/pt_01/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/pt_01/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/pt_01/expected b/src/test/conf_examples/pt_01/expected new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/test/conf_examples/pt_01/torrc b/src/test/conf_examples/pt_01/torrc new file mode 100644 index 0000000000..574bb32a0d --- /dev/null +++ b/src/test/conf_examples/pt_01/torrc @@ -0,0 +1,7 @@ +# Relay PT tests +# Options from relay/transport_config.c +# Empty linelist values are ignored with a warning +ExtORPort +ServerTransportPlugin +ServerTransportListenAddr +ServerTransportOptions diff --git a/src/test/conf_examples/pt_02/error_no_dirauth_relay b/src/test/conf_examples/pt_02/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/pt_02/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/pt_02/expected b/src/test/conf_examples/pt_02/expected new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/test/conf_examples/pt_02/torrc b/src/test/conf_examples/pt_02/torrc new file mode 100644 index 0000000000..d047d615f7 --- /dev/null +++ b/src/test/conf_examples/pt_02/torrc @@ -0,0 +1,11 @@ +# Relay PT tests +# Options from relay/transport_config.c +# Bad options are also ignored +ExtORPort illegal_hostname_chars$()^*%(%#%)#(%* +ServerTransportPlugin bad +ServerTransportPlugin bad2 exec +ServerTransportPlugin bad3 exec / +ServerTransportListenAddr bad +ServerTransportListenAddr bad2 illegal_hostname_chars$()^*%(%#%)#(%* +ServerTransportOptions bad +ServerTransportOptions bad2 not_kv diff --git a/src/test/conf_examples/pt_03/error_no_dirauth_relay b/src/test/conf_examples/pt_03/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/pt_03/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/pt_03/expected b/src/test/conf_examples/pt_03/expected new file mode 100644 index 0000000000..f849f2a78f --- /dev/null +++ b/src/test/conf_examples/pt_03/expected @@ -0,0 +1 @@ +ServerTransportPlugin bad3 exec / diff --git a/src/test/conf_examples/pt_03/torrc b/src/test/conf_examples/pt_03/torrc new file mode 100644 index 0000000000..9868c39b26 --- /dev/null +++ b/src/test/conf_examples/pt_03/torrc @@ -0,0 +1,4 @@ +# Relay PT tests +# Options from relay/transport_config.c +# Plugin, but no ExtORPort +ServerTransportPlugin bad3 exec / diff --git a/src/test/conf_examples/pt_04/error_no_dirauth_relay b/src/test/conf_examples/pt_04/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/pt_04/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/pt_04/expected b/src/test/conf_examples/pt_04/expected new file mode 100644 index 0000000000..9087f600e0 --- /dev/null +++ b/src/test/conf_examples/pt_04/expected @@ -0,0 +1,3 @@ +ExtORPortCookieAuthFile / +ExtORPort 1 +ServerTransportPlugin bad3 exec / diff --git a/src/test/conf_examples/pt_04/torrc b/src/test/conf_examples/pt_04/torrc new file mode 100644 index 0000000000..18bb28f9cf --- /dev/null +++ b/src/test/conf_examples/pt_04/torrc @@ -0,0 +1,6 @@ +# Relay PT tests +# Options from relay/transport_config.c +# Try a bad cookie auth file +ExtORPort 1 +ExtORPortCookieAuthFile / +ServerTransportPlugin bad3 exec / diff --git a/src/test/conf_examples/pt_05/error_no_dirauth_relay b/src/test/conf_examples/pt_05/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/pt_05/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/pt_05/expected b/src/test/conf_examples/pt_05/expected new file mode 100644 index 0000000000..61568bb9ac --- /dev/null +++ b/src/test/conf_examples/pt_05/expected @@ -0,0 +1,4 @@ +ExtORPort 1 +Nickname Unnamed +ORPort 2 +ServerTransportPlugin bad3 exec / diff --git a/src/test/conf_examples/pt_05/torrc b/src/test/conf_examples/pt_05/torrc new file mode 100644 index 0000000000..55c569bb1b --- /dev/null +++ b/src/test/conf_examples/pt_05/torrc @@ -0,0 +1,6 @@ +# Relay PT tests +# Options from relay/transport_config.c +# Try a valid minimal config +ORPort 2 +ExtORPort 1 +ServerTransportPlugin bad3 exec / diff --git a/src/test/conf_examples/pt_06/error_no_dirauth_relay b/src/test/conf_examples/pt_06/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/pt_06/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/pt_06/expected b/src/test/conf_examples/pt_06/expected new file mode 100644 index 0000000000..d5788b92c9 --- /dev/null +++ b/src/test/conf_examples/pt_06/expected @@ -0,0 +1,6 @@ +ExtORPortCookieAuthFile / +ExtORPortCookieAuthFileGroupReadable 1 +ExtORPort 1 +ServerTransportListenAddr bad3 127.0.0.1:2 +ServerTransportOptions bad3 a=b +ServerTransportPlugin bad3 exec / diff --git a/src/test/conf_examples/pt_06/torrc b/src/test/conf_examples/pt_06/torrc new file mode 100644 index 0000000000..20cfc329a7 --- /dev/null +++ b/src/test/conf_examples/pt_06/torrc @@ -0,0 +1,9 @@ +# Relay PT tests +# Options from relay/transport_config.c +# Try a config with all the options +ExtORPort 1 +ExtORPortCookieAuthFile / +ExtORPortCookieAuthFileGroupReadable 1 +ServerTransportPlugin bad3 exec / +ServerTransportListenAddr bad3 127.0.0.1:2 +ServerTransportOptions bad3 a=b diff --git a/src/test/conf_examples/pt_07/error_no_dirauth_relay b/src/test/conf_examples/pt_07/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/pt_07/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/pt_07/expected b/src/test/conf_examples/pt_07/expected new file mode 100644 index 0000000000..c3a75dc407 --- /dev/null +++ b/src/test/conf_examples/pt_07/expected @@ -0,0 +1,4 @@ +ExtORPort 2.2.2.2:1 +Nickname Unnamed +ORPort 2 +ServerTransportPlugin bad3 exec / diff --git a/src/test/conf_examples/pt_07/torrc b/src/test/conf_examples/pt_07/torrc new file mode 100644 index 0000000000..40eaf50e64 --- /dev/null +++ b/src/test/conf_examples/pt_07/torrc @@ -0,0 +1,6 @@ +# Relay PT tests +# Options from relay/transport_config.c +# Try a valid config with a risky ExtORPort address +ORPort 2 +ExtORPort 2.2.2.2:1 +ServerTransportPlugin bad3 exec / diff --git a/src/test/conf_examples/pt_08/error b/src/test/conf_examples/pt_08/error new file mode 100644 index 0000000000..7931bbb4b9 --- /dev/null +++ b/src/test/conf_examples/pt_08/error @@ -0,0 +1 @@ +ExtORPort does not support unix sockets \ No newline at end of file diff --git a/src/test/conf_examples/pt_08/error_no_dirauth_relay b/src/test/conf_examples/pt_08/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/pt_08/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/pt_08/torrc b/src/test/conf_examples/pt_08/torrc new file mode 100644 index 0000000000..bf36a185a4 --- /dev/null +++ b/src/test/conf_examples/pt_08/torrc @@ -0,0 +1,5 @@ +# Relay PT tests +# Options from relay/transport_config.c +# Try an invalid config with a unix socket for ExtORPort +ExtORPort unix:/ +ServerTransportPlugin bad3 exec / diff --git a/src/test/conf_examples/pt_09/error_no_dirauth_relay b/src/test/conf_examples/pt_09/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/pt_09/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/pt_09/expected b/src/test/conf_examples/pt_09/expected new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/test/conf_examples/pt_09/torrc b/src/test/conf_examples/pt_09/torrc new file mode 100644 index 0000000000..50a8e95b95 --- /dev/null +++ b/src/test/conf_examples/pt_09/torrc @@ -0,0 +1,7 @@ +# Relay PT tests +# Options from relay/transport_config.c +# Try a valid minimal config, with a bad ServerTransportListenAddr +ORPort 2 +ExtORPort 1 +ServerTransportPlugin bad3 exec / +ServerTransportListenAddr bad3 [aaaa::bbbb:ccccc] diff --git a/src/test/conf_examples/relay_01/error_no_dirauth_relay b/src/test/conf_examples/relay_01/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_01/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_01/expected b/src/test/conf_examples/relay_01/expected new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/test/conf_examples/relay_01/torrc b/src/test/conf_examples/relay_01/torrc new file mode 100644 index 0000000000..da3e85b427 --- /dev/null +++ b/src/test/conf_examples/relay_01/torrc @@ -0,0 +1,5 @@ +# Relay tests +# Options from relay/relay_config.c +# Empty linelist values are ignored with a warning +ORPort +DirPort diff --git a/src/test/conf_examples/relay_02/error_no_dirauth_relay b/src/test/conf_examples/relay_02/error_no_dirauth_relay new file mode 100644 index 0000000000..dd87d9f7e2 --- /dev/null +++ b/src/test/conf_examples/relay_02/error_no_dirauth_relay @@ -0,0 +1 @@ +Unrecognized value bad diff --git a/src/test/conf_examples/relay_02/expected b/src/test/conf_examples/relay_02/expected new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/test/conf_examples/relay_02/torrc b/src/test/conf_examples/relay_02/torrc new file mode 100644 index 0000000000..3eaa4403a9 --- /dev/null +++ b/src/test/conf_examples/relay_02/torrc @@ -0,0 +1,7 @@ +# Relay tests +# Options from relay/relay_config.c +# Bad options are also ignored +ORPort illegal_hostname_chars$()^*%(%#%)#(%* +DirPort illegal_hostname_chars$()^*%(%#%)#(%* +DirCache bad +BridgeRelay bad diff --git a/src/test/conf_examples/relay_03/error_no_dirauth_relay b/src/test/conf_examples/relay_03/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_03/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_03/expected b/src/test/conf_examples/relay_03/expected new file mode 100644 index 0000000000..15056a8d1f --- /dev/null +++ b/src/test/conf_examples/relay_03/expected @@ -0,0 +1,2 @@ +DirPort 1 +ORPort 0 diff --git a/src/test/conf_examples/relay_03/torrc b/src/test/conf_examples/relay_03/torrc new file mode 100644 index 0000000000..fd7da7bb95 --- /dev/null +++ b/src/test/conf_examples/relay_03/torrc @@ -0,0 +1,5 @@ +# Relay tests +# Options from relay/relay_config.c +# DirPort, but no ORPort +ORPort 0 +DirPort 1 diff --git a/src/test/conf_examples/relay_04/error_no_dirauth_relay b/src/test/conf_examples/relay_04/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_04/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_04/expected b/src/test/conf_examples/relay_04/expected new file mode 100644 index 0000000000..1d25374ed1 --- /dev/null +++ b/src/test/conf_examples/relay_04/expected @@ -0,0 +1,2 @@ +Nickname Unnamed +ORPort 1 diff --git a/src/test/conf_examples/relay_04/torrc b/src/test/conf_examples/relay_04/torrc new file mode 100644 index 0000000000..ff08b2376b --- /dev/null +++ b/src/test/conf_examples/relay_04/torrc @@ -0,0 +1,4 @@ +# Relay tests +# Options from relay/relay_config.c +# Try a valid minimal config +ORPort 1 diff --git a/src/test/conf_examples/relay_05/error_no_dirauth_relay b/src/test/conf_examples/relay_05/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_05/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_05/expected b/src/test/conf_examples/relay_05/expected new file mode 100644 index 0000000000..ae58cee1af --- /dev/null +++ b/src/test/conf_examples/relay_05/expected @@ -0,0 +1,3 @@ +DirPort 2 +Nickname Unnamed +ORPort 1 diff --git a/src/test/conf_examples/relay_05/torrc b/src/test/conf_examples/relay_05/torrc new file mode 100644 index 0000000000..faeaad32a0 --- /dev/null +++ b/src/test/conf_examples/relay_05/torrc @@ -0,0 +1,5 @@ +# Relay tests +# Options from relay/relay_config.c +# Try a valid minimal directory mirror config +ORPort 1 +DirPort 2 diff --git a/src/test/conf_examples/relay_06/error_no_dirauth_relay b/src/test/conf_examples/relay_06/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_06/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_06/expected b/src/test/conf_examples/relay_06/expected new file mode 100644 index 0000000000..904c7339e0 --- /dev/null +++ b/src/test/conf_examples/relay_06/expected @@ -0,0 +1,3 @@ +BridgeRelay 1 +Nickname Unnamed +ORPort 1 diff --git a/src/test/conf_examples/relay_06/torrc b/src/test/conf_examples/relay_06/torrc new file mode 100644 index 0000000000..baeae8df5d --- /dev/null +++ b/src/test/conf_examples/relay_06/torrc @@ -0,0 +1,5 @@ +# Relay tests +# Options from relay/relay_config.c +# Try a valid minimal bridge config +ORPort 1 +BridgeRelay 1 diff --git a/src/test/conf_examples/relay_07/error_no_dirauth_relay b/src/test/conf_examples/relay_07/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_07/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_07/expected b/src/test/conf_examples/relay_07/expected new file mode 100644 index 0000000000..79fa3e5a47 --- /dev/null +++ b/src/test/conf_examples/relay_07/expected @@ -0,0 +1,3 @@ +DirCache 0 +Nickname Unnamed +ORPort 1 diff --git a/src/test/conf_examples/relay_07/torrc b/src/test/conf_examples/relay_07/torrc new file mode 100644 index 0000000000..01ac138597 --- /dev/null +++ b/src/test/conf_examples/relay_07/torrc @@ -0,0 +1,5 @@ +# Relay tests +# Options from relay/relay_config.c +# Try a valid minimal non-directory cache config +ORPort 1 +DirCache 0 diff --git a/src/test/conf_examples/relay_08/error_no_dirauth_relay b/src/test/conf_examples/relay_08/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_08/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_08/expected b/src/test/conf_examples/relay_08/expected new file mode 100644 index 0000000000..904c7339e0 --- /dev/null +++ b/src/test/conf_examples/relay_08/expected @@ -0,0 +1,3 @@ +BridgeRelay 1 +Nickname Unnamed +ORPort 1 diff --git a/src/test/conf_examples/relay_08/torrc b/src/test/conf_examples/relay_08/torrc new file mode 100644 index 0000000000..9e2ff9465c --- /dev/null +++ b/src/test/conf_examples/relay_08/torrc @@ -0,0 +1,6 @@ +# Relay tests +# Options from relay/relay_config.c +# Try a valid config with all the bridge options +ORPort 1 +BridgeRelay 1 +DirCache 1 diff --git a/src/test/conf_examples/relay_09/error_no_dirauth_relay b/src/test/conf_examples/relay_09/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_09/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_09/expected b/src/test/conf_examples/relay_09/expected new file mode 100644 index 0000000000..ae58cee1af --- /dev/null +++ b/src/test/conf_examples/relay_09/expected @@ -0,0 +1,3 @@ +DirPort 2 +Nickname Unnamed +ORPort 1 diff --git a/src/test/conf_examples/relay_09/torrc b/src/test/conf_examples/relay_09/torrc new file mode 100644 index 0000000000..014eeca34b --- /dev/null +++ b/src/test/conf_examples/relay_09/torrc @@ -0,0 +1,6 @@ +# Relay tests +# Options from relay/relay_config.c +# Try a valid config with all the non-bridge options +ORPort 1 +DirPort 2 +DirCache 1 diff --git a/src/test/conf_examples/relay_10/error_no_dirauth_relay b/src/test/conf_examples/relay_10/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_10/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_10/expected b/src/test/conf_examples/relay_10/expected new file mode 100644 index 0000000000..904c7339e0 --- /dev/null +++ b/src/test/conf_examples/relay_10/expected @@ -0,0 +1,3 @@ +BridgeRelay 1 +Nickname Unnamed +ORPort 1 diff --git a/src/test/conf_examples/relay_10/torrc b/src/test/conf_examples/relay_10/torrc new file mode 100644 index 0000000000..4318ebb45b --- /dev/null +++ b/src/test/conf_examples/relay_10/torrc @@ -0,0 +1,7 @@ +# Relay tests +# Options from relay/relay_config.c +# Try a valid config, that has a warning: Bridge, warn and disable DirPort +ORPort 1 +DirPort 2 +DirCache 1 +BridgeRelay 1 diff --git a/src/test/conf_examples/relay_11/error b/src/test/conf_examples/relay_11/error new file mode 100644 index 0000000000..8ed5c31bc7 --- /dev/null +++ b/src/test/conf_examples/relay_11/error @@ -0,0 +1 @@ +We are advertising an ORPort, but not actually listening on one diff --git a/src/test/conf_examples/relay_11/error_no_dirauth_relay b/src/test/conf_examples/relay_11/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_11/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_11/torrc b/src/test/conf_examples/relay_11/torrc new file mode 100644 index 0000000000..a1e13eb3ce --- /dev/null +++ b/src/test/conf_examples/relay_11/torrc @@ -0,0 +1,4 @@ +# Relay tests +# Options from relay/relay_config.c +# Advertising but not listening: ORPort +ORPort 1 NoListen diff --git a/src/test/conf_examples/relay_12/error b/src/test/conf_examples/relay_12/error new file mode 100644 index 0000000000..57706d6a7a --- /dev/null +++ b/src/test/conf_examples/relay_12/error @@ -0,0 +1 @@ +We are advertising a DirPort, but not actually listening on one diff --git a/src/test/conf_examples/relay_12/error_no_dirauth_relay b/src/test/conf_examples/relay_12/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_12/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_12/torrc b/src/test/conf_examples/relay_12/torrc new file mode 100644 index 0000000000..4a7d398112 --- /dev/null +++ b/src/test/conf_examples/relay_12/torrc @@ -0,0 +1,4 @@ +# Relay tests +# Options from relay/relay_config.c +# Advertising but not listening: DirPort +DirPort 1 NoListen diff --git a/src/test/conf_examples/relay_13/error b/src/test/conf_examples/relay_13/error new file mode 100644 index 0000000000..cd74247ea8 --- /dev/null +++ b/src/test/conf_examples/relay_13/error @@ -0,0 +1 @@ +We are listening on an ORPort, but not advertising any ORPorts diff --git a/src/test/conf_examples/relay_13/error_no_dirauth_relay b/src/test/conf_examples/relay_13/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_13/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_13/torrc b/src/test/conf_examples/relay_13/torrc new file mode 100644 index 0000000000..b76b72c0cc --- /dev/null +++ b/src/test/conf_examples/relay_13/torrc @@ -0,0 +1,4 @@ +# Relay tests +# Options from relay/relay_config.c +# Listening but not advertising: ORPort +ORPort 1 NoAdvertise diff --git a/src/test/conf_examples/relay_14/error_no_dirauth_relay b/src/test/conf_examples/relay_14/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_14/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_14/expected b/src/test/conf_examples/relay_14/expected new file mode 100644 index 0000000000..31bb1c2507 --- /dev/null +++ b/src/test/conf_examples/relay_14/expected @@ -0,0 +1 @@ +DirPort 1 NoAdvertise diff --git a/src/test/conf_examples/relay_14/torrc b/src/test/conf_examples/relay_14/torrc new file mode 100644 index 0000000000..15c6496c7e --- /dev/null +++ b/src/test/conf_examples/relay_14/torrc @@ -0,0 +1,4 @@ +# Relay tests +# Options from relay/relay_config.c +# Listening but not advertising: DirPort +DirPort 1 NoAdvertise diff --git a/src/test/conf_examples/relay_15/error b/src/test/conf_examples/relay_15/error new file mode 100644 index 0000000000..da30f0cd14 --- /dev/null +++ b/src/test/conf_examples/relay_15/error @@ -0,0 +1 @@ +Can't advertise more than one DirPort diff --git a/src/test/conf_examples/relay_15/error_no_dirauth_relay b/src/test/conf_examples/relay_15/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_15/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_15/torrc b/src/test/conf_examples/relay_15/torrc new file mode 100644 index 0000000000..e1f78ee6a0 --- /dev/null +++ b/src/test/conf_examples/relay_15/torrc @@ -0,0 +1,5 @@ +# Relay tests +# Options from relay/relay_config.c +# Advertising more than one DirPort +DirPort 1 +DirPort 2 diff --git a/src/test/conf_examples/relay_16/error b/src/test/conf_examples/relay_16/error new file mode 100644 index 0000000000..37b89ee572 --- /dev/null +++ b/src/test/conf_examples/relay_16/error @@ -0,0 +1 @@ +Configured public relay to listen only on an IPv6 address. Tor needs to listen on an IPv4 address diff --git a/src/test/conf_examples/relay_16/error_no_dirauth_relay b/src/test/conf_examples/relay_16/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_16/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_16/torrc b/src/test/conf_examples/relay_16/torrc new file mode 100644 index 0000000000..e544cd87a4 --- /dev/null +++ b/src/test/conf_examples/relay_16/torrc @@ -0,0 +1,4 @@ +# Relay tests +# Options from relay/relay_config.c +# IPv6 ORPort only +ORPort [::1]:2 diff --git a/src/test/conf_examples/relay_17/error_no_dirauth_relay b/src/test/conf_examples/relay_17/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_17/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_17/expected b/src/test/conf_examples/relay_17/expected new file mode 100644 index 0000000000..3fb0c9db92 --- /dev/null +++ b/src/test/conf_examples/relay_17/expected @@ -0,0 +1,4 @@ +AccountingMax 1 +KeepBindCapabilities 0 +Nickname Unnamed +ORPort 1 diff --git a/src/test/conf_examples/relay_17/torrc b/src/test/conf_examples/relay_17/torrc new file mode 100644 index 0000000000..f63f36815e --- /dev/null +++ b/src/test/conf_examples/relay_17/torrc @@ -0,0 +1,6 @@ +# Relay tests +# Options from relay/relay_config.c +# Rebind warning +ORPort 1 +AccountingMax 1 +KeepBindCapabilities 0 diff --git a/src/test/conf_examples/relay_18/error b/src/test/conf_examples/relay_18/error new file mode 100644 index 0000000000..5b28d311b0 --- /dev/null +++ b/src/test/conf_examples/relay_18/error @@ -0,0 +1 @@ +Invalid DirPort configuration diff --git a/src/test/conf_examples/relay_18/error_no_dirauth_relay b/src/test/conf_examples/relay_18/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_18/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_18/torrc b/src/test/conf_examples/relay_18/torrc new file mode 100644 index 0000000000..67a0fd0dfb --- /dev/null +++ b/src/test/conf_examples/relay_18/torrc @@ -0,0 +1,4 @@ +# Relay tests +# Options from relay/relay_config.c +# Bad DirPort +DirPort illegal_hostname_chars$()^*%(%#%)#(%* diff --git a/src/test/conf_examples/relay_19/error_no_dirauth_relay b/src/test/conf_examples/relay_19/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_19/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_19/expected b/src/test/conf_examples/relay_19/expected new file mode 100644 index 0000000000..f077169c88 --- /dev/null +++ b/src/test/conf_examples/relay_19/expected @@ -0,0 +1,3 @@ +Nickname Unnamed +ORPort 1 +PublishServerDescriptor diff --git a/src/test/conf_examples/relay_19/torrc b/src/test/conf_examples/relay_19/torrc new file mode 100644 index 0000000000..fd2cd91fa5 --- /dev/null +++ b/src/test/conf_examples/relay_19/torrc @@ -0,0 +1,5 @@ +# Relay tests +# Options from relay/relay_config.c +# Minimal PublishServerDescriptor +ORPort 1 +PublishServerDescriptor diff --git a/src/test/conf_examples/relay_20/error b/src/test/conf_examples/relay_20/error new file mode 100644 index 0000000000..e5a81637f8 --- /dev/null +++ b/src/test/conf_examples/relay_20/error @@ -0,0 +1 @@ +Unrecognized value in PublishServerDescriptor diff --git a/src/test/conf_examples/relay_20/error_no_dirauth_relay b/src/test/conf_examples/relay_20/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_20/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_20/torrc b/src/test/conf_examples/relay_20/torrc new file mode 100644 index 0000000000..87dd74fdc1 --- /dev/null +++ b/src/test/conf_examples/relay_20/torrc @@ -0,0 +1,5 @@ +# Relay tests +# Options from relay/relay_config.c +# Invalid PublishServerDescriptor +ORPort 1 +PublishServerDescriptor bad diff --git a/src/test/conf_examples/relay_21/error_no_dirauth_relay b/src/test/conf_examples/relay_21/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_21/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_21/expected b/src/test/conf_examples/relay_21/expected new file mode 100644 index 0000000000..9bcead1402 --- /dev/null +++ b/src/test/conf_examples/relay_21/expected @@ -0,0 +1,3 @@ +Nickname Unnamed +ORPort 1 +PublishServerDescriptor v1,v2,hidserv diff --git a/src/test/conf_examples/relay_21/torrc b/src/test/conf_examples/relay_21/torrc new file mode 100644 index 0000000000..97f032f626 --- /dev/null +++ b/src/test/conf_examples/relay_21/torrc @@ -0,0 +1,5 @@ +# Relay tests +# Options from relay/relay_config.c +# Ignored PublishServerDescriptor values +ORPort 1 +PublishServerDescriptor v1,v2,hidserv diff --git a/src/test/conf_examples/relay_22/error b/src/test/conf_examples/relay_22/error new file mode 100644 index 0000000000..c47dd8c4c6 --- /dev/null +++ b/src/test/conf_examples/relay_22/error @@ -0,0 +1 @@ +Invalid BridgeDistribution value diff --git a/src/test/conf_examples/relay_22/error_no_dirauth_relay b/src/test/conf_examples/relay_22/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_22/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_22/torrc b/src/test/conf_examples/relay_22/torrc new file mode 100644 index 0000000000..e83c83260e --- /dev/null +++ b/src/test/conf_examples/relay_22/torrc @@ -0,0 +1,6 @@ +# Relay tests +# Options from relay/relay_config.c +# Bad BridgeDistribution characters +ORPort 1 +BridgeRelay 1 +BridgeDistribution *$%()@! diff --git a/src/test/conf_examples/relay_23/error b/src/test/conf_examples/relay_23/error new file mode 100644 index 0000000000..f76bbe77c4 --- /dev/null +++ b/src/test/conf_examples/relay_23/error @@ -0,0 +1 @@ +Relays must use 'auto' for the ConnectionPadding setting diff --git a/src/test/conf_examples/relay_23/error_no_dirauth_relay b/src/test/conf_examples/relay_23/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_23/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_23/torrc b/src/test/conf_examples/relay_23/torrc new file mode 100644 index 0000000000..3d28a1e27c --- /dev/null +++ b/src/test/conf_examples/relay_23/torrc @@ -0,0 +1,5 @@ +# Relay tests +# Options from relay/relay_config.c +# Relays can't set ConnectionPadding +ORPort 1 +ConnectionPadding 1 diff --git a/src/test/conf_examples/relay_24/error b/src/test/conf_examples/relay_24/error new file mode 100644 index 0000000000..f76bbe77c4 --- /dev/null +++ b/src/test/conf_examples/relay_24/error @@ -0,0 +1 @@ +Relays must use 'auto' for the ConnectionPadding setting diff --git a/src/test/conf_examples/relay_24/error_no_dirauth_relay b/src/test/conf_examples/relay_24/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_24/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_24/torrc b/src/test/conf_examples/relay_24/torrc new file mode 100644 index 0000000000..1206e59e09 --- /dev/null +++ b/src/test/conf_examples/relay_24/torrc @@ -0,0 +1,5 @@ +# Relay tests +# Options from relay/relay_config.c +# Relays can't set ConnectionPadding +ORPort 1 +ConnectionPadding 0 diff --git a/src/test/conf_examples/relay_25/error b/src/test/conf_examples/relay_25/error new file mode 100644 index 0000000000..bac681e6cc --- /dev/null +++ b/src/test/conf_examples/relay_25/error @@ -0,0 +1 @@ +Relays cannot set ReducedConnectionPadding diff --git a/src/test/conf_examples/relay_25/error_no_dirauth_relay b/src/test/conf_examples/relay_25/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_25/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_25/torrc b/src/test/conf_examples/relay_25/torrc new file mode 100644 index 0000000000..ab862a16f3 --- /dev/null +++ b/src/test/conf_examples/relay_25/torrc @@ -0,0 +1,5 @@ +# Relay tests +# Options from relay/relay_config.c +# Relays can't set ReducedConnectionPadding 1 +ORPort 1 +ReducedConnectionPadding 1 diff --git a/src/test/conf_examples/relay_26/error b/src/test/conf_examples/relay_26/error new file mode 100644 index 0000000000..94334935e3 --- /dev/null +++ b/src/test/conf_examples/relay_26/error @@ -0,0 +1 @@ +Relays cannot set CircuitPadding to 0 diff --git a/src/test/conf_examples/relay_26/error_no_dirauth_relay b/src/test/conf_examples/relay_26/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_26/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_26/torrc b/src/test/conf_examples/relay_26/torrc new file mode 100644 index 0000000000..5dd6d68dc4 --- /dev/null +++ b/src/test/conf_examples/relay_26/torrc @@ -0,0 +1,5 @@ +# Relay tests +# Options from relay/relay_config.c +# Relays can't set CircuitPadding to 0 +ORPort 1 +CircuitPadding 0 diff --git a/src/test/conf_examples/relay_27/error b/src/test/conf_examples/relay_27/error new file mode 100644 index 0000000000..e26ce46914 --- /dev/null +++ b/src/test/conf_examples/relay_27/error @@ -0,0 +1 @@ +Relays cannot set ReducedCircuitPadding diff --git a/src/test/conf_examples/relay_27/error_no_dirauth_relay b/src/test/conf_examples/relay_27/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_27/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_27/torrc b/src/test/conf_examples/relay_27/torrc new file mode 100644 index 0000000000..8556b2f351 --- /dev/null +++ b/src/test/conf_examples/relay_27/torrc @@ -0,0 +1,5 @@ +# Relay tests +# Options from relay/relay_config.c +# Relays can't set ReducedCircuitPadding 1 +ORPort 1 +ReducedCircuitPadding 1 diff --git a/src/test/conf_examples/relay_28/error b/src/test/conf_examples/relay_28/error new file mode 100644 index 0000000000..3f14df975b --- /dev/null +++ b/src/test/conf_examples/relay_28/error @@ -0,0 +1 @@ +SigningKeyLifetime is too short diff --git a/src/test/conf_examples/relay_28/error_no_dirauth_relay b/src/test/conf_examples/relay_28/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_28/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_28/torrc b/src/test/conf_examples/relay_28/torrc new file mode 100644 index 0000000000..3e2c895bb7 --- /dev/null +++ b/src/test/conf_examples/relay_28/torrc @@ -0,0 +1,5 @@ +# Relay tests +# Options from relay/relay_config.c +# Short key lifetimes +ORPort 1 +SigningKeyLifetime 1 diff --git a/src/test/conf_examples/relay_29/error_no_dirauth_relay b/src/test/conf_examples/relay_29/error_no_dirauth_relay new file mode 100644 index 0000000000..9f9c0fd8f3 --- /dev/null +++ b/src/test/conf_examples/relay_29/error_no_dirauth_relay @@ -0,0 +1 @@ +This tor was built with relay mode disabled. diff --git a/src/test/conf_examples/relay_29/expected b/src/test/conf_examples/relay_29/expected new file mode 100644 index 0000000000..1d25374ed1 --- /dev/null +++ b/src/test/conf_examples/relay_29/expected @@ -0,0 +1,2 @@ +Nickname Unnamed +ORPort 1 diff --git a/src/test/conf_examples/relay_29/torrc b/src/test/conf_examples/relay_29/torrc new file mode 100644 index 0000000000..4181d5acc2 --- /dev/null +++ b/src/test/conf_examples/relay_29/torrc @@ -0,0 +1,5 @@ +# Relay tests +# Options from relay/relay_config.c +# MyFamily normalisation: empty MyFamily +ORPort 1 +MyFamily diff --git a/src/test/include.am b/src/test/include.am index 667bbf5368..bd7ab71a20 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -203,6 +203,7 @@ src_test_test_SOURCES += \ src/test/test_sendme.c \ src/test/test_shared_random.c \ src/test/test_socks.c \ + src/test/test_stats.c \ src/test/test_status.c \ src/test/test_storagedir.c \ src/test/test_threads.c \ diff --git a/src/test/test.c b/src/test/test.c index c4227dca50..90c0058be8 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -55,7 +55,6 @@ #include "core/crypto/onion_fast.h" #include "core/crypto/onion_tap.h" #include "core/or/policies.h" -#include "feature/stats/rephist.h" #include "app/config/statefile.h" #include "lib/crypt_ops/crypto_curve25519.h" @@ -639,166 +638,6 @@ test_rend_fns(void *arg) tor_free(intro_points_encrypted); } -/** Run unit tests for stats code. */ -static void -test_stats(void *arg) -{ - time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */ - char *s = NULL; - int i; - - /* Start with testing exit port statistics; we shouldn't collect exit - * stats without initializing them. */ - (void)arg; - rep_hist_note_exit_stream_opened(80); - rep_hist_note_exit_bytes(80, 100, 10000); - s = rep_hist_format_exit_stats(now + 86400); - tt_ptr_op(s, OP_EQ, NULL); - - /* Initialize stats, note some streams and bytes, and generate history - * string. */ - rep_hist_exit_stats_init(now); - rep_hist_note_exit_stream_opened(80); - rep_hist_note_exit_bytes(80, 100, 10000); - rep_hist_note_exit_stream_opened(443); - rep_hist_note_exit_bytes(443, 100, 10000); - rep_hist_note_exit_bytes(443, 100, 10000); - s = rep_hist_format_exit_stats(now + 86400); - tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n" - "exit-kibibytes-written 80=1,443=1,other=0\n" - "exit-kibibytes-read 80=10,443=20,other=0\n" - "exit-streams-opened 80=4,443=4,other=0\n",OP_EQ, s); - tor_free(s); - - /* Add a few bytes on 10 more ports and ensure that only the top 10 - * ports are contained in the history string. */ - for (i = 50; i < 60; i++) { - rep_hist_note_exit_bytes(i, i, i); - rep_hist_note_exit_stream_opened(i); - } - s = rep_hist_format_exit_stats(now + 86400); - tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n" - "exit-kibibytes-written 52=1,53=1,54=1,55=1,56=1,57=1,58=1," - "59=1,80=1,443=1,other=1\n" - "exit-kibibytes-read 52=1,53=1,54=1,55=1,56=1,57=1,58=1," - "59=1,80=10,443=20,other=1\n" - "exit-streams-opened 52=4,53=4,54=4,55=4,56=4,57=4,58=4," - "59=4,80=4,443=4,other=4\n",OP_EQ, s); - tor_free(s); - - /* Stop collecting stats, add some bytes, and ensure we don't generate - * a history string. */ - rep_hist_exit_stats_term(); - rep_hist_note_exit_bytes(80, 100, 10000); - s = rep_hist_format_exit_stats(now + 86400); - tt_ptr_op(s, OP_EQ, NULL); - - /* Re-start stats, add some bytes, reset stats, and see what history we - * get when observing no streams or bytes at all. */ - rep_hist_exit_stats_init(now); - rep_hist_note_exit_stream_opened(80); - rep_hist_note_exit_bytes(80, 100, 10000); - rep_hist_reset_exit_stats(now); - s = rep_hist_format_exit_stats(now + 86400); - tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n" - "exit-kibibytes-written other=0\n" - "exit-kibibytes-read other=0\n" - "exit-streams-opened other=0\n",OP_EQ, s); - tor_free(s); - - /* Continue with testing connection statistics; we shouldn't collect - * conn stats without initializing them. */ - rep_hist_note_or_conn_bytes(1, 20, 400, now); - s = rep_hist_format_conn_stats(now + 86400); - tt_ptr_op(s, OP_EQ, NULL); - - /* Initialize stats, note bytes, and generate history string. */ - rep_hist_conn_stats_init(now); - rep_hist_note_or_conn_bytes(1, 30000, 400000, now); - rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5); - rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10); - rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15); - s = rep_hist_format_conn_stats(now + 86400); - tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n",OP_EQ, s); - tor_free(s); - - /* Stop collecting stats, add some bytes, and ensure we don't generate - * a history string. */ - rep_hist_conn_stats_term(); - rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15); - s = rep_hist_format_conn_stats(now + 86400); - tt_ptr_op(s, OP_EQ, NULL); - - /* Re-start stats, add some bytes, reset stats, and see what history we - * get when observing no bytes at all. */ - rep_hist_conn_stats_init(now); - rep_hist_note_or_conn_bytes(1, 30000, 400000, now); - rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5); - rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10); - rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15); - rep_hist_reset_conn_stats(now); - s = rep_hist_format_conn_stats(now + 86400); - tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n",OP_EQ, s); - tor_free(s); - - /* Continue with testing buffer statistics; we shouldn't collect buffer - * stats without initializing them. */ - rep_hist_add_buffer_stats(2.0, 2.0, 20); - s = rep_hist_format_buffer_stats(now + 86400); - tt_ptr_op(s, OP_EQ, NULL); - - /* Initialize stats, add statistics for a single circuit, and generate - * the history string. */ - rep_hist_buffer_stats_init(now); - rep_hist_add_buffer_stats(2.0, 2.0, 20); - s = rep_hist_format_buffer_stats(now + 86400); - tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n" - "cell-processed-cells 20,0,0,0,0,0,0,0,0,0\n" - "cell-queued-cells 2.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00," - "0.00,0.00\n" - "cell-time-in-queue 2,0,0,0,0,0,0,0,0,0\n" - "cell-circuits-per-decile 1\n",OP_EQ, s); - tor_free(s); - - /* Add nineteen more circuit statistics to the one that's already in the - * history to see that the math works correctly. */ - for (i = 21; i < 30; i++) - rep_hist_add_buffer_stats(2.0, 2.0, i); - for (i = 20; i < 30; i++) - rep_hist_add_buffer_stats(3.5, 3.5, i); - s = rep_hist_format_buffer_stats(now + 86400); - tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n" - "cell-processed-cells 29,28,27,26,25,24,23,22,21,20\n" - "cell-queued-cells 2.75,2.75,2.75,2.75,2.75,2.75,2.75,2.75," - "2.75,2.75\n" - "cell-time-in-queue 3,3,3,3,3,3,3,3,3,3\n" - "cell-circuits-per-decile 2\n",OP_EQ, s); - tor_free(s); - - /* Stop collecting stats, add statistics for one circuit, and ensure we - * don't generate a history string. */ - rep_hist_buffer_stats_term(); - rep_hist_add_buffer_stats(2.0, 2.0, 20); - s = rep_hist_format_buffer_stats(now + 86400); - tt_ptr_op(s, OP_EQ, NULL); - - /* Re-start stats, add statistics for one circuit, reset stats, and make - * sure that the history has all zeros. */ - rep_hist_buffer_stats_init(now); - rep_hist_add_buffer_stats(2.0, 2.0, 20); - rep_hist_reset_buffer_stats(now); - s = rep_hist_format_buffer_stats(now + 86400); - tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n" - "cell-processed-cells 0,0,0,0,0,0,0,0,0,0\n" - "cell-queued-cells 0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00," - "0.00,0.00\n" - "cell-time-in-queue 0,0,0,0,0,0,0,0,0,0\n" - "cell-circuits-per-decile 0\n",OP_EQ, s); - - done: - tor_free(s); -} - #define ENT(name) \ { #name, test_ ## name , 0, NULL, NULL } #define FORK(name) \ @@ -812,7 +651,6 @@ static struct testcase_t test_array[] = { { "fast_handshake", test_fast_handshake, 0, NULL, NULL }, FORK(circuit_timeout), FORK(rend_fns), - FORK(stats), END_OF_TESTCASES }; @@ -919,6 +757,7 @@ struct testgroup_t testgroups[] = { { "sendme/", sendme_tests }, { "shared-random/", sr_tests }, { "socks/", socks_tests }, + { "stats/", stats_tests }, { "status/" , status_tests }, { "storagedir/", storagedir_tests }, { "token_bucket/", token_bucket_tests }, diff --git a/src/test/test.h b/src/test/test.h index b2dc552c82..967562890f 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -280,6 +280,7 @@ extern struct testcase_t scheduler_tests[]; extern struct testcase_t sendme_tests[]; extern struct testcase_t socks_tests[]; extern struct testcase_t sr_tests[]; +extern struct testcase_t stats_tests[]; extern struct testcase_t status_tests[]; extern struct testcase_t storagedir_tests[]; extern struct testcase_t thread_tests[]; diff --git a/src/test/test_cmdline.sh b/src/test/test_cmdline.sh index cf758c3851..ded58af63d 100755 --- a/src/test/test_cmdline.sh +++ b/src/test/test_cmdline.sh @@ -3,6 +3,21 @@ umask 077 set -e +# emulate realpath(), in case coreutils or equivalent is not installed. +abspath() { + f="$*" + if [ -d "$f" ]; then + dir="$f" + base="" + else + dir="$(dirname "$f")" + base="/$(basename "$f")" + fi + dir="$(cd "$dir" && pwd)" + echo "$dir$base" +} + +# find the tor binary if [ $# -ge 1 ]; then TOR_BINARY="${1}" shift @@ -10,6 +25,8 @@ else TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}" fi +TOR_BINARY="$(abspath "$TOR_BINARY")" + echo "TOR BINARY IS ${TOR_BINARY}" die() { echo "$1" >&2 ; exit 5; } diff --git a/src/test/test_config.c b/src/test/test_config.c index 83f3c50ca9..a75a862739 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -6,6 +6,8 @@ #include "orconfig.h" #define CONFIG_PRIVATE +#define RELAY_CONFIG_PRIVATE +#define RELAY_TRANSPORT_CONFIG_PRIVATE #define PT_PRIVATE #define ROUTERSET_PRIVATE #include "core/or/or.h" @@ -16,6 +18,8 @@ #include "core/or/circuitmux_ewma.h" #include "core/or/circuitbuild.h" #include "app/config/config.h" +#include "feature/relay/relay_config.h" +#include "feature/relay/transport_config.h" #include "lib/confmgt/confmgt.h" #include "core/mainloop/connection.h" #include "core/or/connection_edge.h" @@ -689,84 +693,84 @@ test_config_parse_transport_plugin_line(void *arg) int old_transport_is_needed_mock_call_count; /* Bad transport lines - too short */ - r = parse_transport_line(options, "bad", 1, 0); + r = pt_parse_transport_line(options, "bad", 1, 0); tt_int_op(r, OP_LT, 0); - r = parse_transport_line(options, "bad", 1, 1); + r = pt_parse_transport_line(options, "bad", 1, 1); tt_int_op(r, OP_LT, 0); - r = parse_transport_line(options, "bad bad", 1, 0); + r = pt_parse_transport_line(options, "bad bad", 1, 0); tt_int_op(r, OP_LT, 0); - r = parse_transport_line(options, "bad bad", 1, 1); + r = pt_parse_transport_line(options, "bad bad", 1, 1); tt_int_op(r, OP_LT, 0); /* Test transport list parsing */ - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 exec /usr/bin/fake-transport", 1, 0); tt_int_op(r, OP_EQ, 0); - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 exec /usr/bin/fake-transport", 1, 1); tt_int_op(r, OP_EQ, 0); - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1,transport_2 exec /usr/bin/fake-transport", 1, 0); tt_int_op(r, OP_EQ, 0); - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1,transport_2 exec /usr/bin/fake-transport", 1, 1); tt_int_op(r, OP_EQ, 0); /* Bad transport identifiers */ - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_* exec /usr/bin/fake-transport", 1, 0); tt_int_op(r, OP_LT, 0); - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_* exec /usr/bin/fake-transport", 1, 1); tt_int_op(r, OP_LT, 0); /* Check SOCKS cases for client transport */ - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 socks4 1.2.3.4:567", 1, 0); tt_int_op(r, OP_EQ, 0); - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 socks5 1.2.3.4:567", 1, 0); tt_int_op(r, OP_EQ, 0); /* Proxy case for server transport */ - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 proxy 1.2.3.4:567", 1, 1); tt_int_op(r, OP_EQ, 0); /* Multiple-transport error exit */ - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1,transport_2 socks5 1.2.3.4:567", 1, 0); tt_int_op(r, OP_LT, 0); - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1,transport_2 proxy 1.2.3.4:567", 1, 1); tt_int_op(r, OP_LT, 0); /* No port error exit */ - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 socks5 1.2.3.4", 1, 0); tt_int_op(r, OP_LT, 0); - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 proxy 1.2.3.4", 1, 1); tt_int_op(r, OP_LT, 0); /* Unparsable address error exit */ - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 socks5 1.2.3:6x7", 1, 0); tt_int_op(r, OP_LT, 0); - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 proxy 1.2.3:6x7", 1, 1); tt_int_op(r, OP_LT, 0); /* "Strange {Client|Server}TransportPlugin field" error exit */ - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 foo bar", 1, 0); tt_int_op(r, OP_LT, 0); - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 foo bar", 1, 1); tt_int_op(r, OP_LT, 0); /* No sandbox mode error exit */ tmp = options->Sandbox; options->Sandbox = 1; - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 exec /usr/bin/fake-transport", 1, 0); tt_int_op(r, OP_LT, 0); - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 exec /usr/bin/fake-transport", 1, 1); tt_int_op(r, OP_LT, 0); options->Sandbox = tmp; @@ -778,7 +782,7 @@ test_config_parse_transport_plugin_line(void *arg) MOCK(pt_kickstart_proxy, pt_kickstart_proxy_mock); old_pt_kickstart_proxy_mock_call_count = pt_kickstart_proxy_mock_call_count; - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 exec /usr/bin/fake-transport", 0, 1); tt_int_op(r, OP_EQ, 0); tt_assert(pt_kickstart_proxy_mock_call_count == @@ -786,7 +790,7 @@ test_config_parse_transport_plugin_line(void *arg) UNMOCK(pt_kickstart_proxy); /* This one hits a log line in the !validate_only case only */ - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 proxy 1.2.3.4:567", 0, 1); tt_int_op(r, OP_EQ, 0); @@ -803,7 +807,7 @@ test_config_parse_transport_plugin_line(void *arg) transport_add_from_config_mock_call_count; old_transport_is_needed_mock_call_count = transport_is_needed_mock_call_count; - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 exec /usr/bin/fake-transport", 0, 0); /* Should have succeeded */ tt_int_op(r, OP_EQ, 0); @@ -827,7 +831,7 @@ test_config_parse_transport_plugin_line(void *arg) transport_add_from_config_mock_call_count; old_transport_is_needed_mock_call_count = transport_is_needed_mock_call_count; - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 exec /usr/bin/fake-transport", 0, 0); /* Should have succeeded */ tt_int_op(r, OP_EQ, 0); @@ -851,7 +855,7 @@ test_config_parse_transport_plugin_line(void *arg) transport_add_from_config_mock_call_count; old_transport_is_needed_mock_call_count = transport_is_needed_mock_call_count; - r = parse_transport_line(options, + r = pt_parse_transport_line(options, "transport_1 socks5 1.2.3.4:567", 0, 0); /* Should have succeeded */ tt_int_op(r, OP_EQ, 0); @@ -3997,40 +4001,40 @@ test_config_parse_port_config__ports__no_ports_given(void *data) slout = smartlist_new(); // Test no defaultport, no defaultaddress and no out - ret = parse_port_config(NULL, NULL, "DNS", 0, NULL, 0, 0); + ret = port_parse_config(NULL, NULL, "DNS", 0, NULL, 0, 0); tt_int_op(ret, OP_EQ, 0); // Test with defaultport, no defaultaddress and no out - ret = parse_port_config(NULL, NULL, "DNS", 0, NULL, 42, 0); + ret = port_parse_config(NULL, NULL, "DNS", 0, NULL, 42, 0); tt_int_op(ret, OP_EQ, 0); // Test no defaultport, with defaultaddress and no out - ret = parse_port_config(NULL, NULL, "DNS", 0, "127.0.0.2", 0, 0); + ret = port_parse_config(NULL, NULL, "DNS", 0, "127.0.0.2", 0, 0); tt_int_op(ret, OP_EQ, 0); // Test with defaultport, with defaultaddress and no out - ret = parse_port_config(NULL, NULL, "DNS", 0, "127.0.0.2", 42, 0); + ret = port_parse_config(NULL, NULL, "DNS", 0, "127.0.0.2", 42, 0); tt_int_op(ret, OP_EQ, 0); // Test no defaultport, no defaultaddress and with out - ret = parse_port_config(slout, NULL, "DNS", 0, NULL, 0, 0); + ret = port_parse_config(slout, NULL, "DNS", 0, NULL, 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 0); // Test with defaultport, no defaultaddress and with out - ret = parse_port_config(slout, NULL, "DNS", 0, NULL, 42, 0); + ret = port_parse_config(slout, NULL, "DNS", 0, NULL, 42, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 0); // Test no defaultport, with defaultaddress and with out - ret = parse_port_config(slout, NULL, "DNS", 0, "127.0.0.2", 0, 0); + ret = port_parse_config(slout, NULL, "DNS", 0, "127.0.0.2", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 0); // Test with defaultport, with defaultaddress and out, adds a new port cfg SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); - ret = parse_port_config(slout, NULL, "DNS", 0, "127.0.0.2", 42, 0); + ret = port_parse_config(slout, NULL, "DNS", 0, "127.0.0.2", 42, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); port_cfg = (port_cfg_t *)smartlist_get(slout, 0); @@ -4041,7 +4045,7 @@ test_config_parse_port_config__ports__no_ports_given(void *data) // for a unix address SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); - ret = parse_port_config(slout, NULL, "DNS", 0, "/foo/bar/unixdomain", + ret = port_parse_config(slout, NULL, "DNS", 0, "/foo/bar/unixdomain", 42, CL_PORT_IS_UNIXSOCKET); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4072,28 +4076,28 @@ test_config_parse_port_config__ports__ports_given(void *data) // Test error when encounters an invalid Port specification config_port_invalid = mock_config_line("DNSPort", ""); - ret = parse_port_config(NULL, config_port_invalid, "DNS", 0, NULL, + ret = port_parse_config(NULL, config_port_invalid, "DNS", 0, NULL, 0, 0); tt_int_op(ret, OP_EQ, -1); // Test error when encounters an empty unix domain specification config_free_lines(config_port_invalid); config_port_invalid = NULL; config_port_invalid = mock_config_line("DNSPort", "unix:"); - ret = parse_port_config(NULL, config_port_invalid, "DNS", 0, NULL, + ret = port_parse_config(NULL, config_port_invalid, "DNS", 0, NULL, 0, 0); tt_int_op(ret, OP_EQ, -1); // Test error when encounters a unix domain specification but the listener // doesn't support domain sockets config_port_valid = mock_config_line("DNSPort", "unix:/tmp/foo/bar"); - ret = parse_port_config(NULL, config_port_valid, "DNS", + ret = port_parse_config(NULL, config_port_valid, "DNS", CONN_TYPE_AP_DNS_LISTENER, NULL, 0, 0); tt_int_op(ret, OP_EQ, -1); // Test valid unix domain SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); - ret = parse_port_config(slout, config_port_valid, "SOCKS", + ret = port_parse_config(slout, config_port_valid, "SOCKS", CONN_TYPE_AP_LISTENER, NULL, 0, 0); #ifdef _WIN32 tt_int_op(ret, OP_EQ, -1); @@ -4104,7 +4108,7 @@ test_config_parse_port_config__ports__ports_given(void *data) tt_int_op(port_cfg->port, OP_EQ, 0); tt_int_op(port_cfg->is_unix_addr, OP_EQ, 1); tt_str_op(port_cfg->unix_addr, OP_EQ, "/tmp/foo/bar"); - /* Test entry port defaults as initialised in parse_port_config */ + /* Test entry port defaults as initialised in port_parse_config */ tt_int_op(port_cfg->entry_cfg.dns_request, OP_EQ, 1); tt_int_op(port_cfg->entry_cfg.ipv4_traffic, OP_EQ, 1); tt_int_op(port_cfg->entry_cfg.onion_traffic, OP_EQ, 1); @@ -4118,7 +4122,7 @@ test_config_parse_port_config__ports__ports_given(void *data) "unix:/tmp/foo/bar NoIPv4Traffic " "NoIPv6Traffic " "NoOnionTraffic"); - ret = parse_port_config(NULL, config_port_invalid, "SOCKS", + ret = port_parse_config(NULL, config_port_invalid, "SOCKS", CONN_TYPE_AP_LISTENER, NULL, 0, CL_PORT_TAKES_HOSTNAMES); tt_int_op(ret, OP_EQ, -1); @@ -4127,7 +4131,7 @@ test_config_parse_port_config__ports__ports_given(void *data) config_free_lines(config_port_invalid); config_port_invalid = NULL; config_port_invalid = mock_config_line("DNSPort", "127.0.0.1:80 NoDNSRequest"); - ret = parse_port_config(NULL, config_port_invalid, "DNS", + ret = port_parse_config(NULL, config_port_invalid, "DNS", CONN_TYPE_AP_DNS_LISTENER, NULL, 0, CL_PORT_TAKES_HOSTNAMES); tt_int_op(ret, OP_EQ, -1); @@ -4140,7 +4144,7 @@ test_config_parse_port_config__ports__ports_given(void *data) config_port_valid = mock_config_line("DNSPort", "127.0.0.1:80 " "NoIPv6Traffic " "NoIPv4Traffic NoOnionTraffic"); - ret = parse_port_config(slout, config_port_valid, "DNS", + ret = port_parse_config(slout, config_port_valid, "DNS", CONN_TYPE_AP_DNS_LISTENER, NULL, 0, CL_PORT_TAKES_HOSTNAMES); tt_int_op(ret, OP_EQ, 0); @@ -4156,7 +4160,7 @@ test_config_parse_port_config__ports__ports_given(void *data) config_port_invalid = mock_config_line("SOCKSPort", "NoIPv6Traffic " "unix:/tmp/foo/bar NoIPv4Traffic"); - ret = parse_port_config(NULL, config_port_invalid, "SOCKS", + ret = port_parse_config(NULL, config_port_invalid, "SOCKS", CONN_TYPE_AP_LISTENER, NULL, 0, CL_PORT_TAKES_HOSTNAMES); tt_int_op(ret, OP_EQ, -1); @@ -4169,7 +4173,7 @@ test_config_parse_port_config__ports__ports_given(void *data) config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/foo/bar " "NoIPv6Traffic " "NoDNSRequest NoIPv4Traffic"); - ret = parse_port_config(slout, config_port_valid, "SOCKS", + ret = port_parse_config(slout, config_port_valid, "SOCKS", CONN_TYPE_AP_LISTENER, NULL, 0, CL_PORT_TAKES_HOSTNAMES); #ifdef _WIN32 @@ -4191,7 +4195,7 @@ test_config_parse_port_config__ports__ports_given(void *data) config_port_valid = mock_config_line("SOCKSPort", "unix:\"/tmp/foo/ bar\" " "NoIPv6Traffic " "NoDNSRequest NoIPv4Traffic"); - ret = parse_port_config(slout, config_port_valid, "SOCKS", + ret = port_parse_config(slout, config_port_valid, "SOCKS", CONN_TYPE_AP_LISTENER, NULL, 0, CL_PORT_TAKES_HOSTNAMES); #ifdef _WIN32 @@ -4213,7 +4217,7 @@ test_config_parse_port_config__ports__ports_given(void *data) config_port_valid = mock_config_line("SOCKSPort", "unix:\"/tmp/foo/ bar " "NoIPv6Traffic " "NoDNSRequest NoIPv4Traffic"); - ret = parse_port_config(slout, config_port_valid, "SOCKS", + ret = port_parse_config(slout, config_port_valid, "SOCKS", CONN_TYPE_AP_LISTENER, NULL, 0, CL_PORT_TAKES_HOSTNAMES); tt_int_op(ret, OP_EQ, -1); @@ -4225,7 +4229,7 @@ test_config_parse_port_config__ports__ports_given(void *data) config_port_valid = mock_config_line("SOCKSPort", "unix:\"\" " "NoIPv6Traffic " "NoDNSRequest NoIPv4Traffic"); - ret = parse_port_config(slout, config_port_valid, "SOCKS", + ret = port_parse_config(slout, config_port_valid, "SOCKS", CONN_TYPE_AP_LISTENER, NULL, 0, CL_PORT_TAKES_HOSTNAMES); tt_int_op(ret, OP_EQ, -1); @@ -4236,7 +4240,7 @@ test_config_parse_port_config__ports__ports_given(void *data) smartlist_clear(slout); config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/foo/bar " "OnionTrafficOnly"); - ret = parse_port_config(slout, config_port_valid, "SOCKS", + ret = port_parse_config(slout, config_port_valid, "SOCKS", CONN_TYPE_AP_LISTENER, NULL, 0, CL_PORT_TAKES_HOSTNAMES); #ifdef _WIN32 @@ -4257,7 +4261,7 @@ test_config_parse_port_config__ports__ports_given(void *data) smartlist_clear(slout); config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/foo/bar " "NoIPv4Traffic IPv6Traffic"); - ret = parse_port_config(slout, config_port_valid, "SOCKS", + ret = port_parse_config(slout, config_port_valid, "SOCKS", CONN_TYPE_AP_LISTENER, NULL, 0, CL_PORT_TAKES_HOSTNAMES); #ifdef _WIN32 @@ -4276,7 +4280,7 @@ test_config_parse_port_config__ports__ports_given(void *data) smartlist_clear(slout); config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/foo/bar " "IPv4Traffic IPv6Traffic"); - ret = parse_port_config(slout, config_port_valid, "SOCKS", + ret = port_parse_config(slout, config_port_valid, "SOCKS", CONN_TYPE_AP_LISTENER, NULL, 0, CL_PORT_TAKES_HOSTNAMES); #ifdef _WIN32 @@ -4292,28 +4296,28 @@ test_config_parse_port_config__ports__ports_given(void *data) // Test failure if we specify world writable for an IP Port config_free_lines(config_port_invalid); config_port_invalid = NULL; config_port_invalid = mock_config_line("DNSPort", "42 WorldWritable"); - ret = parse_port_config(NULL, config_port_invalid, "DNS", 0, + ret = port_parse_config(NULL, config_port_invalid, "DNS", 0, "127.0.0.3", 0, 0); tt_int_op(ret, OP_EQ, -1); // Test failure if we specify group writable for an IP Port config_free_lines(config_port_invalid); config_port_invalid = NULL; config_port_invalid = mock_config_line("DNSPort", "42 GroupWritable"); - ret = parse_port_config(NULL, config_port_invalid, "DNS", 0, + ret = port_parse_config(NULL, config_port_invalid, "DNS", 0, "127.0.0.3", 0, 0); tt_int_op(ret, OP_EQ, -1); // Test failure if we specify group writable for an IP Port config_free_lines(config_port_invalid); config_port_invalid = NULL; config_port_invalid = mock_config_line("DNSPort", "42 RelaxDirModeCheck"); - ret = parse_port_config(NULL, config_port_invalid, "DNS", 0, + ret = port_parse_config(NULL, config_port_invalid, "DNS", 0, "127.0.0.3", 0, 0); tt_int_op(ret, OP_EQ, -1); // Test success with only a port (this will fail without a default address) config_free_lines(config_port_valid); config_port_valid = NULL; config_port_valid = mock_config_line("DNSPort", "42"); - ret = parse_port_config(NULL, config_port_valid, "DNS", 0, + ret = port_parse_config(NULL, config_port_valid, "DNS", 0, "127.0.0.3", 0, 0); tt_int_op(ret, OP_EQ, 0); @@ -4322,7 +4326,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 IsolateDestPort"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.3", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4335,7 +4339,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 NoIsolateDestPorts"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.3", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4348,7 +4352,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 IsolateDestAddr"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.3", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4361,7 +4365,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 IsolateSOCKSAuth"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.3", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4374,7 +4378,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 IsolateClientProtocol"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.3", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4387,7 +4391,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 IsolateClientAddr"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.3", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4398,7 +4402,7 @@ test_config_parse_port_config__ports__ports_given(void *data) // Test success with ignored unknown options config_free_lines(config_port_valid); config_port_valid = NULL; config_port_valid = mock_config_line("DNSPort", "42 ThisOptionDoesntExist"); - ret = parse_port_config(NULL, config_port_valid, "DNS", 0, + ret = port_parse_config(NULL, config_port_valid, "DNS", 0, "127.0.0.3", 0, 0); tt_int_op(ret, OP_EQ, 0); @@ -4407,7 +4411,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 NoIsolateSOCKSAuth"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.3", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4420,7 +4424,7 @@ test_config_parse_port_config__ports__ports_given(void *data) smartlist_clear(slout); config_port_valid = mock_config_line("SOCKSPort", "42 IPv6Traffic PreferIPv6"); - ret = parse_port_config(slout, config_port_valid, "SOCKS", + ret = port_parse_config(slout, config_port_valid, "SOCKS", CONN_TYPE_AP_LISTENER, "127.0.0.42", 0, CL_PORT_TAKES_HOSTNAMES); tt_int_op(ret, OP_EQ, 0); @@ -4433,7 +4437,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 CacheIPv4DNS"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.42", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4446,7 +4450,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 CacheIPv6DNS"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.42", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4459,7 +4463,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 NoCacheIPv4DNS"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.42", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4472,7 +4476,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 CacheDNS"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.42", 0, CL_PORT_TAKES_HOSTNAMES); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4485,7 +4489,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 UseIPv4Cache"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.42", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4498,7 +4502,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 UseIPv6Cache"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.42", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4511,7 +4515,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 UseDNSCache"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.42", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4524,7 +4528,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 NoPreferIPv6Automap"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.42", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4536,7 +4540,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 PreferSOCKSNoAuth"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.42", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4551,14 +4555,14 @@ test_config_parse_port_config__ports__ports_given(void *data) config_port_invalid = mock_config_line("DNSPort", "0"); config_port_valid = mock_config_line("DNSPort", "42"); config_port_invalid->next = config_port_valid; - ret = parse_port_config(slout, config_port_invalid, "DNS", 0, + ret = port_parse_config(slout, config_port_invalid, "DNS", 0, "127.0.0.42", 0, 0); tt_int_op(ret, OP_EQ, -1); // Test success with warn non-local control SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); - ret = parse_port_config(slout, config_port_valid, "Control", + ret = port_parse_config(slout, config_port_valid, "Control", CONN_TYPE_CONTROL_LISTENER, "127.0.0.42", 0, CL_PORT_WARN_NONLOCAL); tt_int_op(ret, OP_EQ, 0); @@ -4566,7 +4570,7 @@ test_config_parse_port_config__ports__ports_given(void *data) // Test success with warn non-local listener SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); - ret = parse_port_config(slout, config_port_valid, "ExtOR", + ret = port_parse_config(slout, config_port_valid, "ExtOR", CONN_TYPE_EXT_OR_LISTENER, "127.0.0.42", 0, CL_PORT_WARN_NONLOCAL); tt_int_op(ret, OP_EQ, 0); @@ -4574,12 +4578,12 @@ test_config_parse_port_config__ports__ports_given(void *data) // Test success with warn non-local other SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.42", 0, CL_PORT_WARN_NONLOCAL); tt_int_op(ret, OP_EQ, 0); // Test success with warn non-local other without out - ret = parse_port_config(NULL, config_port_valid, "DNS", 0, + ret = port_parse_config(NULL, config_port_valid, "DNS", 0, "127.0.0.42", 0, CL_PORT_WARN_NONLOCAL); tt_int_op(ret, OP_EQ, 0); @@ -4590,7 +4594,7 @@ test_config_parse_port_config__ports__ports_given(void *data) smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 IPv4Traffic " "IPv6Traffic"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.44", 0, CL_PORT_TAKES_HOSTNAMES | CL_PORT_NO_STREAM_OPTIONS); @@ -4605,7 +4609,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_invalid = mock_config_line("DNSPort", "42 SessionGroup=invalid"); - ret = parse_port_config(slout, config_port_invalid, "DNS", 0, + ret = port_parse_config(slout, config_port_invalid, "DNS", 0, "127.0.0.44", 0, CL_PORT_NO_STREAM_OPTIONS); tt_int_op(ret, OP_EQ, -1); @@ -4615,7 +4619,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_invalid = mock_config_line("DNSPort", "42 SessionGroup=123"); - ret = parse_port_config(slout, config_port_invalid, "DNS", 0, + ret = port_parse_config(slout, config_port_invalid, "DNS", 0, "127.0.0.44", 0, CL_PORT_NO_STREAM_OPTIONS); tt_int_op(ret, OP_EQ, -1); @@ -4625,7 +4629,7 @@ test_config_parse_port_config__ports__ports_given(void *data) smartlist_clear(slout); config_port_invalid = mock_config_line("DNSPort", "42 SessionGroup=123 " "SessionGroup=321"); - ret = parse_port_config(slout, config_port_invalid, "DNS", 0, + ret = port_parse_config(slout, config_port_invalid, "DNS", 0, "127.0.0.44", 0, 0); tt_int_op(ret, OP_EQ, -1); @@ -4634,7 +4638,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "42 SessionGroup=1111122"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.44", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4646,7 +4650,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "0"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.45", 0, CL_PORT_IS_UNIXSOCKET); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 0); @@ -4656,7 +4660,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "something"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.45", 0, CL_PORT_IS_UNIXSOCKET); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4669,7 +4673,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "auto"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.46", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4683,7 +4687,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "AuTo"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.46", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4697,7 +4701,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "127.0.0.122:auto"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.46", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4710,7 +4714,7 @@ test_config_parse_port_config__ports__ports_given(void *data) config_free_lines(config_port_invalid); config_port_invalid = NULL; config_port_invalid = mock_config_line("DNSPort", "invalidstuff!!:auto"); MOCK(tor_addr_lookup, mock_tor_addr_lookup__fail_on_bad_addrs); - ret = parse_port_config(NULL, config_port_invalid, "DNS", 0, + ret = port_parse_config(NULL, config_port_invalid, "DNS", 0, "127.0.0.46", 0, 0); UNMOCK(tor_addr_lookup); tt_int_op(ret, OP_EQ, -1); @@ -4720,7 +4724,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "127.0.0.123:656"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, "127.0.0.46", 0, 0); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4734,7 +4738,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_invalid = mock_config_line("DNSPort", "something wrong"); - ret = parse_port_config(slout, config_port_invalid, "DNS", 0, + ret = port_parse_config(slout, config_port_invalid, "DNS", 0, "127.0.0.46", 0, 0); tt_int_op(ret, OP_EQ, -1); @@ -4743,7 +4747,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_invalid = mock_config_line("DNSPort", "127.0.1.0:123:auto"); - ret = parse_port_config(slout, config_port_invalid, "DNS", 0, + ret = port_parse_config(slout, config_port_invalid, "DNS", 0, "127.0.0.46", 0, 0); tt_int_op(ret, OP_EQ, -1); @@ -4753,7 +4757,7 @@ test_config_parse_port_config__ports__ports_given(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("SOCKSPort", "unix:/tmp/somewhere"); - ret = parse_port_config(slout, config_port_valid, "SOCKS", + ret = port_parse_config(slout, config_port_valid, "SOCKS", CONN_TYPE_AP_LISTENER, "127.0.0.46", 0, CL_PORT_DFLT_GROUP_WRITABLE); #ifdef _WIN32 @@ -4789,7 +4793,7 @@ test_config_parse_port_config__ports__server_options(void *data) config_free_lines(config_port_valid); config_port_valid = NULL; config_port_valid = mock_config_line("DNSPort", "127.0.0.124:656 NoAdvertise"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, NULL, 0, CL_PORT_SERVER_OPTIONS); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4802,7 +4806,7 @@ test_config_parse_port_config__ports__server_options(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "127.0.0.124:656 NoListen"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, NULL, 0, CL_PORT_SERVER_OPTIONS); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4816,7 +4820,7 @@ test_config_parse_port_config__ports__server_options(void *data) smartlist_clear(slout); config_port_invalid = mock_config_line("DNSPort", "127.0.0.124:656 NoListen " "NoAdvertise"); - ret = parse_port_config(slout, config_port_invalid, "DNS", 0, NULL, + ret = port_parse_config(slout, config_port_invalid, "DNS", 0, NULL, 0, CL_PORT_SERVER_OPTIONS); tt_int_op(ret, OP_EQ, -1); @@ -4825,7 +4829,7 @@ test_config_parse_port_config__ports__server_options(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "127.0.0.124:656 IPv4Only"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, NULL, 0, CL_PORT_SERVER_OPTIONS); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4838,7 +4842,7 @@ test_config_parse_port_config__ports__server_options(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "[::1]:656 IPv6Only"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, NULL, 0, CL_PORT_SERVER_OPTIONS); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4852,7 +4856,7 @@ test_config_parse_port_config__ports__server_options(void *data) smartlist_clear(slout); config_port_invalid = mock_config_line("DNSPort", "127.0.0.124:656 IPv6Only " "IPv4Only"); - ret = parse_port_config(slout, config_port_invalid, "DNS", 0, NULL, + ret = port_parse_config(slout, config_port_invalid, "DNS", 0, NULL, 0, CL_PORT_SERVER_OPTIONS); tt_int_op(ret, OP_EQ, -1); @@ -4861,7 +4865,7 @@ test_config_parse_port_config__ports__server_options(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_valid = mock_config_line("DNSPort", "127.0.0.124:656 unknown"); - ret = parse_port_config(slout, config_port_valid, "DNS", 0, NULL, 0, + ret = port_parse_config(slout, config_port_valid, "DNS", 0, NULL, 0, CL_PORT_SERVER_OPTIONS); tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(slout), OP_EQ, 1); @@ -4872,7 +4876,7 @@ test_config_parse_port_config__ports__server_options(void *data) smartlist_clear(slout); config_port_invalid = mock_config_line("DNSPort", "127.0.0.124:656 IPv6Only"); - ret = parse_port_config(slout, config_port_invalid, "DNS", 0, NULL, + ret = port_parse_config(slout, config_port_invalid, "DNS", 0, NULL, 0, CL_PORT_SERVER_OPTIONS); tt_int_op(ret, OP_EQ, -1); @@ -4881,7 +4885,7 @@ test_config_parse_port_config__ports__server_options(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_invalid = mock_config_line("DNSPort", "[::1]:656 IPv4Only"); - ret = parse_port_config(slout, config_port_invalid, "DNS", 0, NULL, + ret = port_parse_config(slout, config_port_invalid, "DNS", 0, NULL, 0, CL_PORT_SERVER_OPTIONS); tt_int_op(ret, OP_EQ, -1); @@ -4890,7 +4894,7 @@ test_config_parse_port_config__ports__server_options(void *data) SMARTLIST_FOREACH(slout,port_cfg_t *,pf,port_cfg_free(pf)); smartlist_clear(slout); config_port_invalid = mock_config_line("ORPort", "unix:\"\""); - ret = parse_port_config(slout, config_port_invalid, "ORPort", 0, NULL, + ret = port_parse_config(slout, config_port_invalid, "ORPort", 0, NULL, 0, CL_PORT_SERVER_OPTIONS); tt_int_op(ret, OP_EQ, -1); diff --git a/src/test/test_dir_handle_get.c b/src/test/test_dir_handle_get.c index edfd0c74e1..ae968eb7e2 100644 --- a/src/test/test_dir_handle_get.c +++ b/src/test/test_dir_handle_get.c @@ -20,6 +20,7 @@ #include "lib/compress/compress.h" #include "feature/rend/rendcommon.h" #include "feature/rend/rendcache.h" +#include "feature/relay/relay_config.h" #include "feature/relay/router.h" #include "feature/nodelist/authcert.h" #include "feature/nodelist/dirlist.h" @@ -118,7 +119,7 @@ test_dir_handle_get_v1_command_not_found(void *data) conn = new_dir_conn(); // no frontpage configured - tt_ptr_op(get_dirportfrontpage(), OP_EQ, NULL); + tt_ptr_op(relay_get_dirportfrontpage(), OP_EQ, NULL); /* V1 path */ tt_int_op(directory_handle_command_get(conn, GET("/tor/"), NULL, 0), @@ -152,9 +153,9 @@ test_dir_handle_get_v1_command(void *data) (void) data; MOCK(connection_write_to_buf_impl_, connection_write_to_buf_mock); - MOCK(get_dirportfrontpage, mock_get_dirportfrontpage); + MOCK(relay_get_dirportfrontpage, mock_get_dirportfrontpage); - exp_body = get_dirportfrontpage(); + exp_body = relay_get_dirportfrontpage(); body_len = strlen(exp_body); conn = new_dir_conn(); @@ -177,7 +178,7 @@ test_dir_handle_get_v1_command(void *data) done: UNMOCK(connection_write_to_buf_impl_); - UNMOCK(get_dirportfrontpage); + UNMOCK(relay_get_dirportfrontpage); connection_free_minimal(TO_CONN(conn)); tor_free(header); tor_free(body); diff --git a/src/test/test_key_expiration.sh b/src/test/test_key_expiration.sh index 9d42c1cc4c..2238f7aa78 100755 --- a/src/test/test_key_expiration.sh +++ b/src/test/test_key_expiration.sh @@ -6,6 +6,20 @@ umask 077 set -e +# emulate realpath(), in case coreutils or equivalent is not installed. +abspath() { + f="$*" + if [ -d "$f" ]; then + dir="$f" + base="" + else + dir="$(dirname "$f")" + base="/$(basename "$f")" + fi + dir="$(cd "$dir" && pwd)" + echo "$dir$base" +} + if [ $# -eq 0 ] || [ ! -f "${1}" ] || [ ! -x "${1}" ]; then if [ "$TESTING_TOR_BINARY" = "" ] ; then echo "Usage: ${0} PATH_TO_TOR [case-number]" @@ -21,13 +35,18 @@ if test "$UNAME_OS" = 'CYGWIN' || \ exit 77 fi +# find the tor binary if [ $# -ge 1 ]; then TOR_BINARY="${1}" shift else - TOR_BINARY="${TESTING_TOR_BINARY}" + TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}" fi +TOR_BINARY="$(abspath "$TOR_BINARY")" + +echo "TOR BINARY IS ${TOR_BINARY}" + if "$TOR_BINARY" --list-modules | grep -q "relay: no"; then echo "This test requires the relay module. Skipping." >&2 exit 77 diff --git a/src/test/test_keygen.sh b/src/test/test_keygen.sh index 57df888274..6812f8883d 100755 --- a/src/test/test_keygen.sh +++ b/src/test/test_keygen.sh @@ -6,6 +6,20 @@ umask 077 set -e +# emulate realpath(), in case coreutils or equivalent is not installed. +abspath() { + f="$*" + if [ -d "$f" ]; then + dir="$f" + base="" + else + dir="$(dirname "$f")" + base="/$(basename "$f")" + fi + dir="$(cd "$dir" && pwd)" + echo "$dir$base" +} + if [ $# -eq 0 ] || [ ! -f "${1}" ] || [ ! -x "${1}" ]; then if [ "$TESTING_TOR_BINARY" = "" ] ; then echo "Usage: ${0} PATH_TO_TOR [case-number]" @@ -21,13 +35,18 @@ if test "$UNAME_OS" = 'CYGWIN' || \ exit 77 fi +# find the tor binary if [ $# -ge 1 ]; then TOR_BINARY="${1}" shift else - TOR_BINARY="${TESTING_TOR_BINARY}" + TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}" fi +TOR_BINARY="$(abspath "$TOR_BINARY")" + +echo "TOR BINARY IS ${TOR_BINARY}" + if "$TOR_BINARY" --list-modules | grep -q "relay: no"; then echo "This test requires the relay module. Skipping." >&2 exit 77 diff --git a/src/test/test_options.c b/src/test/test_options.c index ae26cf31b9..c06fb998fb 100644 --- a/src/test/test_options.c +++ b/src/test/test_options.c @@ -4,10 +4,13 @@ /* See LICENSE for licensing information */ #define CONFIG_PRIVATE +#define RELAY_CONFIG_PRIVATE #define LOG_PRIVATE #include "core/or/or.h" #include "lib/confmgt/confmgt.h" #include "app/config/config.h" +#include "feature/dirauth/dirauth_config.h" +#include "feature/relay/relay_config.h" #include "test/test.h" #include "lib/geoip/geoip.h" @@ -99,6 +102,50 @@ clear_log_messages(void) options_init(opt); \ } while (0) +#ifdef COCCI + +#define ENABLE_AUTHORITY_MIN "" +#define ENABLE_AUTHORITY_V3_MIN "" +#define ENABLE_AUTHORITY_BRIDGE_MIN "" +#define AUTHORITY_OPT_REQ_ "" +#define ENABLE_AUTHORITY "" +#define ENABLE_AUTHORITY_V3 "" +#define ENABLE_AUTHORITY_BRIDGE "" + +#else /* !defined(COCCI) */ + +#define ENABLE_AUTHORITY_MIN \ + "AuthoritativeDirectory 1\n" + +#define ENABLE_AUTHORITY_V3_MIN \ + ENABLE_AUTHORITY_MIN \ + "V3AuthoritativeDir 1\n" + +#define ENABLE_AUTHORITY_BRIDGE_MIN \ + ENABLE_AUTHORITY_MIN \ + "BridgeAuthoritativeDir 1\n" + +#define AUTHORITY_OPT_REQ_ \ + "Address 192.0.2.111\n" \ + "ContactInfo a@example.org\n" \ + "DirPort 1025\n" \ + "ORPort 1026\n" + +/* Not actually valid: requires v3 / bridge */ +#define ENABLE_AUTHORITY \ + ENABLE_AUTHORITY_MIN \ + AUTHORITY_OPT_REQ_ + +#define ENABLE_AUTHORITY_V3 \ + ENABLE_AUTHORITY_V3_MIN \ + AUTHORITY_OPT_REQ_ + +#define ENABLE_AUTHORITY_BRIDGE \ + ENABLE_AUTHORITY_BRIDGE_MIN \ + AUTHORITY_OPT_REQ_ + +#endif /* defined(COCCI) */ + #define VALID_DIR_AUTH "DirAuthority dizum orport=443 v3ident=E8A9C45" \ "EDE6D711294FADF8E7951F4DE6CA56B58 194.109.206.212:80 7EA6 EAD6 FD83" \ " 083C 538F 4403 8BBF A077 587D D755\n" @@ -710,7 +757,7 @@ test_options_validate__authdir(void *ignored) char *msg; setup_capture_of_logs(LOG_INFO); options_test_data_t *tdata = get_options_test_data( - "AuthoritativeDirectory 1\n" + ENABLE_AUTHORITY_V3_MIN "Address this.should.not!exist!.example.org"); sandbox_disable_getaddrinfo_cache(); @@ -726,7 +773,7 @@ test_options_validate__authdir(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3_MIN "Address 100.200.10.1"); mock_clean_saved_logs(); ret = options_validate(NULL, tdata->opt, &msg); @@ -736,7 +783,7 @@ test_options_validate__authdir(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3_MIN "Address 100.200.10.1\n"); mock_clean_saved_logs(); ret = options_validate(NULL, tdata->opt, &msg); @@ -746,7 +793,7 @@ test_options_validate__authdir(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_MIN "Address 100.200.10.1\n" "TestingTorNetwork 1\n"); mock_clean_saved_logs(); @@ -757,9 +804,7 @@ test_options_validate__authdir(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" - "Address 100.200.10.1\n" - "ContactInfo hello@hello.com\n"); + tdata = get_options_test_data(ENABLE_AUTHORITY); mock_clean_saved_logs(); ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); @@ -768,10 +813,8 @@ test_options_validate__authdir(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" - "Address 100.200.10.1\n" - "RecommendedVersions 1.2, 3.14\n" - "ContactInfo hello@hello.com\n"); + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "RecommendedVersions 1.2, 3.14\n"); mock_clean_saved_logs(); options_validate(NULL, tdata->opt, &msg); tt_str_op(tdata->opt->RecommendedClientVersions->value, OP_EQ, "1.2, 3.14"); @@ -779,12 +822,10 @@ test_options_validate__authdir(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" - "Address 100.200.10.1\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 "RecommendedVersions 1.2, 3.14\n" "RecommendedClientVersions 25\n" - "RecommendedServerVersions 4.18\n" - "ContactInfo hello@hello.com\n"); + "RecommendedServerVersions 4.18\n"); mock_clean_saved_logs(); options_validate(NULL, tdata->opt, &msg); tt_str_op(tdata->opt->RecommendedClientVersions->value, OP_EQ, "25"); @@ -792,13 +833,11 @@ test_options_validate__authdir(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" - "Address 100.200.10.1\n" + tdata = get_options_test_data(ENABLE_AUTHORITY "VersioningAuthoritativeDirectory 1\n" "RecommendedVersions 1.2, 3.14\n" "RecommendedClientVersions 25\n" - "RecommendedServerVersions 4.18\n" - "ContactInfo hello@hello.com\n"); + "RecommendedServerVersions 4.18\n"); mock_clean_saved_logs(); options_validate(NULL, tdata->opt, &msg); tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)" @@ -806,11 +845,9 @@ test_options_validate__authdir(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" - "Address 100.200.10.1\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 "VersioningAuthoritativeDirectory 1\n" - "RecommendedServerVersions 4.18\n" - "ContactInfo hello@hello.com\n"); + "RecommendedServerVersions 4.18\n"); mock_clean_saved_logs(); options_validate(NULL, tdata->opt, &msg); tt_str_op(msg, OP_EQ, "Versioning authoritative dir servers must set " @@ -818,11 +855,9 @@ test_options_validate__authdir(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" - "Address 100.200.10.1\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 "VersioningAuthoritativeDirectory 1\n" - "RecommendedClientVersions 4.18\n" - "ContactInfo hello@hello.com\n"); + "RecommendedClientVersions 4.18\n"); mock_clean_saved_logs(); options_validate(NULL, tdata->opt, &msg); tt_str_op(msg, OP_EQ, "Versioning authoritative dir servers must set " @@ -830,10 +865,8 @@ test_options_validate__authdir(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" - "Address 100.200.10.1\n" - "UseEntryGuards 1\n" - "ContactInfo hello@hello.com\n"); + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "UseEntryGuards 1\n"); mock_clean_saved_logs(); options_validate(NULL, tdata->opt, &msg); expect_log_msg("Authoritative directory servers " @@ -842,10 +875,8 @@ test_options_validate__authdir(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" - "Address 100.200.10.1\n" - "V3AuthoritativeDir 1\n" - "ContactInfo hello@hello.com\n"); + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "DownloadExtraInfo 0\n"); mock_clean_saved_logs(); options_validate(NULL, tdata->opt, &msg); expect_log_msg("Authoritative directories always try" @@ -854,80 +885,27 @@ test_options_validate__authdir(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" - "Address 100.200.10.1\n" - "DownloadExtraInfo 1\n" - "V3AuthoritativeDir 1\n" - "ContactInfo hello@hello.com\n"); - mock_clean_saved_logs(); - options_validate(NULL, tdata->opt, &msg); - expect_no_log_msg("Authoritative directories always try" - " to download extra-info documents. Setting DownloadExtraInfo.\n"); - tt_int_op(tdata->opt->DownloadExtraInfo, OP_EQ, 1); - tor_free(msg); - - free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" - "Address 100.200.10.1\n" - "ContactInfo hello@hello.com\n"); - mock_clean_saved_logs(); - options_validate(NULL, tdata->opt, &msg); - tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)" - "AuthoritativeDir is set."); - tor_free(msg); - - free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" - "Address 100.200.10.1\n" - "BridgeAuthoritativeDir 1\n" - "ContactInfo hello@hello.com\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 "V3BandwidthsFile non-existent-file\n"); mock_clean_saved_logs(); options_validate(NULL, tdata->opt, &msg); - tt_str_op(msg, OP_EQ, - "Running as authoritative directory, but no DirPort set."); + expect_log_msg("Can't open bandwidth file at configured location: " + "non-existent-file\n"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" - "Address 100.200.10.1\n" - "BridgeAuthoritativeDir 1\n" - "ContactInfo hello@hello.com\n" - "V3BandwidthsFile non-existent-file\n"); - mock_clean_saved_logs(); - options_validate(NULL, tdata->opt, &msg); - tt_str_op(msg, OP_EQ, - "Running as authoritative directory, but no DirPort set."); - tor_free(msg); - - free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" - "Address 100.200.10.1\n" - "BridgeAuthoritativeDir 1\n" - "ContactInfo hello@hello.com\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 "GuardfractionFile non-existent-file\n"); mock_clean_saved_logs(); options_validate(NULL, tdata->opt, &msg); - tt_str_op(msg, OP_EQ, - "Running as authoritative directory, but no DirPort set."); + expect_log_msg("Cannot open guardfraction file 'non-existent-file'. " + "Failing.\n"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3_MIN "Address 100.200.10.1\n" - "BridgeAuthoritativeDir 1\n" - "ContactInfo hello@hello.com\n" - "GuardfractionFile non-existent-file\n"); - mock_clean_saved_logs(); - options_validate(NULL, tdata->opt, &msg); - tt_str_op(msg, OP_EQ, - "Running as authoritative directory, but no DirPort set."); - tor_free(msg); - - free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" - "Address 100.200.10.1\n" - "BridgeAuthoritativeDir 1\n" + "ORPort 2000\n" "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); ret = options_validate(NULL, tdata->opt, &msg); @@ -937,10 +915,21 @@ test_options_validate__authdir(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("AuthoritativeDirectory 1\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_BRIDGE_MIN + "Address 100.200.10.1\n" + "ORPort 2000\n" + "ContactInfo hello@hello.com\n"); + mock_clean_saved_logs(); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, -1); + tt_str_op(msg, OP_EQ, + "Running as authoritative directory, but no DirPort set."); + tor_free(msg); + + free_options_test_data(tdata); + tdata = get_options_test_data(ENABLE_AUTHORITY_V3_MIN "Address 100.200.10.1\n" "DirPort 999\n" - "BridgeAuthoritativeDir 1\n" "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); ret = options_validate(NULL, tdata->opt, &msg); @@ -949,22 +938,57 @@ test_options_validate__authdir(void *ignored) "Running as authoritative directory, but no ORPort set."); tor_free(msg); - // TODO: This case can't be reached, since clientonly is used to - // check when parsing port lines as well. - /* free_options_test_data(tdata); */ - /* tdata = get_options_test_data("AuthoritativeDirectory 1\n" */ - /* "Address 100.200.10.1\n" */ - /* "DirPort 999\n" */ - /* "ORPort 888\n" */ - /* "ClientOnly 1\n" */ - /* "BridgeAuthoritativeDir 1\n" */ - /* "ContactInfo hello@hello.com\n" ); */ - /* mock_clean_saved_logs(); */ - /* ret = options_validate(NULL, tdata->opt, */ - /* tdata->def_opt, 0, &msg); */ - /* tt_int_op(ret, OP_EQ, -1); */ - /* tt_str_op(msg, OP_EQ, "Running as authoritative directory, " */ - /* "but ClientOnly also set."); */ + free_options_test_data(tdata); + tdata = get_options_test_data(ENABLE_AUTHORITY_BRIDGE_MIN + "Address 100.200.10.1\n" + "DirPort 999\n" + "ContactInfo hello@hello.com\n"); + mock_clean_saved_logs(); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, -1); + tt_str_op(msg, OP_EQ, + "Running as authoritative directory, but no ORPort set."); + tor_free(msg); + + free_options_test_data(tdata); + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "ClientOnly 1\n"); + /* We have to call the dirauth-specific function, and fake port parsing, + * to hit this case */ + tdata->opt->DirPort_set = 1; + tdata->opt->ORPort_set = 1; + mock_clean_saved_logs(); + ret = options_validate_dirauth_mode(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, -1); + tt_str_op(msg, OP_EQ, "Running as authoritative directory, " + "but ClientOnly also set."); + tor_free(msg); + + free_options_test_data(tdata); + tdata = get_options_test_data(ENABLE_AUTHORITY_BRIDGE + "ClientOnly 1\n"); + /* We have to call the dirauth-specific function, and fake port parsing, + * to hit this case */ + tdata->opt->DirPort_set = 1; + tdata->opt->ORPort_set = 1; + mock_clean_saved_logs(); + ret = options_validate_dirauth_mode(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, -1); + tt_str_op(msg, OP_EQ, "Running as authoritative directory, " + "but ClientOnly also set."); + tor_free(msg); + + free_options_test_data(tdata); + tdata = get_options_test_data(ENABLE_AUTHORITY_V3); + /* We have to set this value manually, because it won't parse */ + tdata->opt->MinUptimeHidServDirectoryV2 = -1; + mock_clean_saved_logs(); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); + expect_log_msg("MinUptimeHidServDirectoryV2 " + "option must be at least 0 seconds. Changing to 0.\n"); + tt_int_op(tdata->opt->MinUptimeHidServDirectoryV2, OP_EQ, 0); + tor_free(msg); done: teardown_capture_of_logs(); @@ -978,6 +1002,7 @@ test_options_validate__relay_with_hidden_services(void *ignored) { (void)ignored; char *msg; + int ret; setup_capture_of_logs(LOG_DEBUG); options_test_data_t *tdata = get_options_test_data( "ORPort 127.0.0.1:5555\n" @@ -986,7 +1011,8 @@ test_options_validate__relay_with_hidden_services(void *ignored) "HiddenServicePort 80 127.0.0.1:8080\n" ); - options_validate(NULL, tdata->opt, &msg); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); expect_log_msg( "Tor is currently configured as a relay and a hidden service. " "That's not very secure: you should probably run your hidden servi" @@ -999,27 +1025,25 @@ test_options_validate__relay_with_hidden_services(void *ignored) tor_free(msg); } -// TODO: it doesn't seem possible to hit the case of having no port lines at -// all, since there will be a default created for SocksPort -/* static void */ -/* test_options_validate__ports(void *ignored) */ -/* { */ -/* (void)ignored; */ -/* int ret; */ -/* char *msg; */ -/* setup_capture_of_logs(LOG_WARN); */ -/* options_test_data_t *tdata = get_options_test_data(""); */ -/* ret = options_validate(NULL, tdata->opt, */ -/* tdata->def_opt, 0, &msg); */ -/* expect_log_msg("SocksPort, TransPort, NATDPort, DNSPort, and ORPort " */ -/* "are all undefined, and there aren't any hidden services " */ -/* "configured. " */ -/* " Tor will still run, but probably won't do anything.\n"); */ -/* done: */ -/* teardown_capture_of_logs(); */ -/* free_options_test_data(tdata); */ -/* tor_free(msg); */ -/* } */ +static void +test_options_validate__listen_ports(void *ignored) +{ + (void)ignored; + int ret; + char *msg; + setup_capture_of_logs(LOG_WARN); + options_test_data_t *tdata = get_options_test_data("SOCKSPort 0"); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); + expect_log_msg("SocksPort, TransPort, NATDPort, DNSPort, and ORPort " + "are all undefined, and there aren't any hidden services " + "configured. " + " Tor will still run, but probably won't do anything.\n"); + done: + teardown_capture_of_logs(); + free_options_test_data(tdata); + tor_free(msg); +} static void test_options_validate__transproxy(void *ignored) @@ -2004,15 +2028,7 @@ test_options_validate__hidserv(void *ignored) char *msg; setup_capture_of_logs(LOG_WARN); - options_test_data_t *tdata = get_options_test_data(""); - - tdata->opt->MinUptimeHidServDirectoryV2 = -1; - ret = options_validate(NULL, tdata->opt, &msg); - tt_int_op(ret, OP_EQ, 0); - expect_log_msg("MinUptimeHidServDirectoryV2 " - "option must be at least 0 seconds. Changing to 0.\n"); - tt_int_op(tdata->opt->MinUptimeHidServDirectoryV2, OP_EQ, 0); - tor_free(msg); + options_test_data_t *tdata = NULL; free_options_test_data(tdata); tdata = get_options_test_data("RendPostPeriod 1\n" ); @@ -2101,25 +2117,46 @@ test_options_validate__bandwidth(void *ignored) char *msg; options_test_data_t *tdata = NULL; -#define ENSURE_BANDWIDTH_PARAM(p) \ - STMT_BEGIN \ +#define ENSURE_BANDWIDTH_PARAM(p, EXTRA_OPT_STR) \ + STMT_BEGIN \ free_options_test_data(tdata); \ - tdata = get_options_test_data(#p " 3Gb\n"); \ - ret = options_validate(NULL, tdata->opt, &msg); \ + tdata = get_options_test_data(EXTRA_OPT_STR \ + #p " 3Gb\n"); \ + ret = options_validate(NULL, tdata->opt, &msg); \ tt_int_op(ret, OP_EQ, -1); \ tt_mem_op(msg, OP_EQ, #p " (3221225471) must be at most 2147483647", 40); \ tor_free(msg); \ STMT_END - ENSURE_BANDWIDTH_PARAM(BandwidthRate); - ENSURE_BANDWIDTH_PARAM(BandwidthBurst); - ENSURE_BANDWIDTH_PARAM(MaxAdvertisedBandwidth); - ENSURE_BANDWIDTH_PARAM(RelayBandwidthRate); - ENSURE_BANDWIDTH_PARAM(RelayBandwidthBurst); - ENSURE_BANDWIDTH_PARAM(PerConnBWRate); - ENSURE_BANDWIDTH_PARAM(PerConnBWBurst); - ENSURE_BANDWIDTH_PARAM(AuthDirFastGuarantee); - ENSURE_BANDWIDTH_PARAM(AuthDirGuardBWGuarantee); + ENSURE_BANDWIDTH_PARAM(BandwidthRate, ""); + ENSURE_BANDWIDTH_PARAM(BandwidthBurst, ""); + + ENSURE_BANDWIDTH_PARAM(BandwidthRate, ENABLE_AUTHORITY_V3); + ENSURE_BANDWIDTH_PARAM(BandwidthBurst, ENABLE_AUTHORITY_V3); + + ENSURE_BANDWIDTH_PARAM(BandwidthRate, ENABLE_AUTHORITY_BRIDGE); + ENSURE_BANDWIDTH_PARAM(BandwidthBurst, ENABLE_AUTHORITY_BRIDGE); + + ENSURE_BANDWIDTH_PARAM(MaxAdvertisedBandwidth, ""); + ENSURE_BANDWIDTH_PARAM(RelayBandwidthRate, ""); + ENSURE_BANDWIDTH_PARAM(RelayBandwidthBurst, ""); + ENSURE_BANDWIDTH_PARAM(PerConnBWRate, ""); + ENSURE_BANDWIDTH_PARAM(PerConnBWBurst, ""); + + ENSURE_BANDWIDTH_PARAM(MaxAdvertisedBandwidth, ENABLE_AUTHORITY_V3); + ENSURE_BANDWIDTH_PARAM(RelayBandwidthRate, ENABLE_AUTHORITY_V3); + ENSURE_BANDWIDTH_PARAM(RelayBandwidthBurst, ENABLE_AUTHORITY_V3); + ENSURE_BANDWIDTH_PARAM(PerConnBWRate, ENABLE_AUTHORITY_V3); + ENSURE_BANDWIDTH_PARAM(PerConnBWBurst, ENABLE_AUTHORITY_V3); + + ENSURE_BANDWIDTH_PARAM(MaxAdvertisedBandwidth, ENABLE_AUTHORITY_BRIDGE); + ENSURE_BANDWIDTH_PARAM(RelayBandwidthRate, ENABLE_AUTHORITY_BRIDGE); + ENSURE_BANDWIDTH_PARAM(RelayBandwidthBurst, ENABLE_AUTHORITY_BRIDGE); + ENSURE_BANDWIDTH_PARAM(PerConnBWRate, ENABLE_AUTHORITY_BRIDGE); + ENSURE_BANDWIDTH_PARAM(PerConnBWBurst, ENABLE_AUTHORITY_BRIDGE); + + ENSURE_BANDWIDTH_PARAM(AuthDirFastGuarantee, ENABLE_AUTHORITY_V3); + ENSURE_BANDWIDTH_PARAM(AuthDirGuardBWGuarantee, ENABLE_AUTHORITY_V3); free_options_test_data(tdata); tdata = get_options_test_data("RelayBandwidthRate 1000\n"); @@ -2524,6 +2561,20 @@ test_options_validate__accounting(void *ignored) tt_int_op(tdata->opt->AccountingRule, OP_EQ, ACCT_MAX); tor_free(msg); + free_options_test_data(tdata); + tdata = get_options_test_data("AccountingRule in\n"); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); + tt_int_op(tdata->opt->AccountingRule, OP_EQ, ACCT_IN); + tor_free(msg); + + free_options_test_data(tdata); + tdata = get_options_test_data("AccountingRule out\n"); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); + tt_int_op(tdata->opt->AccountingRule, OP_EQ, ACCT_OUT); + tor_free(msg); + free_options_test_data(tdata); tdata = get_options_test_data("AccountingStart fail\n"); ret = options_validate(NULL, tdata->opt, &msg); @@ -3459,7 +3510,8 @@ test_options_validate__v3_auth(void *ignored) setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); - tdata = get_options_test_data("V3AuthVoteDelay 1000\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "V3AuthVoteDelay 1000\n" "V3AuthDistDelay 1000\n" "V3AuthVotingInterval 1000\n" ); @@ -3471,14 +3523,16 @@ test_options_validate__v3_auth(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("V3AuthVoteDelay 1\n"); + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "V3AuthVoteDelay 1\n"); ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "V3AuthVoteDelay is way too low."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("V3AuthVoteDelay 1\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "V3AuthVoteDelay 1\n" "TestingTorNetwork 1\n"); ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); @@ -3490,14 +3544,16 @@ test_options_validate__v3_auth(void *ignored) // since they are the same free_options_test_data(tdata); - tdata = get_options_test_data("V3AuthDistDelay 1\n"); + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "V3AuthDistDelay 1\n"); ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "V3AuthDistDelay is way too low."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("V3AuthDistDelay 1\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "V3AuthDistDelay 1\n" "TestingTorNetwork 1\n" ); ret = options_validate(NULL, tdata->opt, &msg); @@ -3505,12 +3561,13 @@ test_options_validate__v3_auth(void *ignored) tt_str_op(msg, OP_EQ, "V3AuthDistDelay is way too low."); tor_free(msg); - // TODO: we can't reach the case of v3authdistdelay lower than + // We can't reach the case of v3authdistdelay lower than // MIN_DIST_SECONDS but not lower than MIN_DIST_SECONDS_TESTING, // since they are the same free_options_test_data(tdata); - tdata = get_options_test_data("V3AuthNIntervalsValid 1\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "V3AuthNIntervalsValid 1\n" ); ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); @@ -3518,7 +3575,8 @@ test_options_validate__v3_auth(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("V3AuthVoteDelay 49\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "V3AuthVoteDelay 49\n" "V3AuthDistDelay 49\n" "V3AuthVotingInterval 200\n" ); @@ -3528,7 +3586,49 @@ test_options_validate__v3_auth(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("V3AuthVoteDelay 49\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + VALID_DIR_AUTH + "TestingTorNetwork 1\n" + "V3AuthVoteDelay 49\n" + "V3AuthDistDelay 49\n" + "V3AuthVotingInterval 200\n" + ); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); + tt_ptr_op(msg, OP_EQ, NULL); + tor_free(msg); + + free_options_test_data(tdata); + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + VALID_DIR_AUTH + "TestingTorNetwork 1\n" + "V3AuthVoteDelay 2\n" + "V3AuthDistDelay 2\n" + "V3AuthVotingInterval 9\n" + ); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, -1); + tt_str_op(msg, OP_EQ, + "V3AuthVoteDelay plus V3AuthDistDelay must be less than half " + "V3AuthVotingInterval"); + tor_free(msg); + + free_options_test_data(tdata); + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + VALID_DIR_AUTH + "TestingTorNetwork 1\n" + "V3AuthVoteDelay 2\n" + "V3AuthDistDelay 2\n" + "V3AuthVotingInterval 10\n" + ); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); + tt_ptr_op(msg, OP_EQ, NULL); + tor_free(msg); + + free_options_test_data(tdata); + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "V3AuthVoteDelay 49\n" "V3AuthDistDelay 49\n" "V3AuthVotingInterval 200000\n" ); @@ -3538,7 +3638,8 @@ test_options_validate__v3_auth(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("V3AuthVoteDelay 49\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "V3AuthVoteDelay 49\n" "V3AuthDistDelay 49\n" "V3AuthVotingInterval 1441\n" ); @@ -3550,7 +3651,8 @@ test_options_validate__v3_auth(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("V3AuthVoteDelay 49\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "V3AuthVoteDelay 49\n" "V3AuthDistDelay 49\n" "V3AuthVotingInterval 1440\n" ); @@ -3562,7 +3664,8 @@ test_options_validate__v3_auth(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("V3AuthVoteDelay 49\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "V3AuthVoteDelay 49\n" "V3AuthDistDelay 49\n" "V3AuthVotingInterval 299\n" VALID_DIR_AUTH @@ -3575,23 +3678,23 @@ test_options_validate__v3_auth(void *ignored) "This may lead to failure to synchronise for a consensus.\n"); tor_free(msg); - // TODO: It is impossible to reach the case of testingtor network, with - // v3authvotinginterval too low - /* free_options_test_data(tdata); */ - /* tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES */ - /* "V3AuthVoteDelay 1\n" */ - /* "V3AuthDistDelay 1\n" */ - /* "V3AuthVotingInterval 9\n" */ - /* VALID_DIR_AUTH */ - /* "TestingTorNetwork 1\n" */ - /* ); */ - /* ret = options_validate(NULL, tdata->opt, */ - /* tdata->def_opt, 0, &msg); */ - /* tt_int_op(ret, OP_EQ, -1); */ - /* tt_str_op(msg, OP_EQ, "V3AuthVotingInterval is insanely low."); */ + free_options_test_data(tdata); + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "V3AuthVoteDelay 1\n" + "V3AuthDistDelay 1\n" + "V3AuthVotingInterval 9\n" + VALID_DIR_AUTH + "TestingTorNetwork 1\n" + ); + /* We have to call the dirauth-specific function to reach this case */ + ret = options_validate_dirauth_schedule(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, -1); + tt_str_op(msg, OP_EQ, "V3AuthVoteDelay is way too low."); + tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("TestingV3AuthInitialVoteDelay 1\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "TestingV3AuthInitialVoteDelay 1\n" VALID_DIR_AUTH "TestingTorNetwork 1\n" ); @@ -3601,7 +3704,8 @@ test_options_validate__v3_auth(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("TestingV3AuthInitialDistDelay 1\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "TestingV3AuthInitialDistDelay 1\n" VALID_DIR_AUTH "TestingTorNetwork 1\n" ); @@ -3611,7 +3715,8 @@ test_options_validate__v3_auth(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(VALID_DIR_AUTH + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + VALID_DIR_AUTH "TestingTorNetwork 1\n" ); tdata->opt->TestingV3AuthVotingStartOffset = 100000; @@ -3622,7 +3727,8 @@ test_options_validate__v3_auth(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(VALID_DIR_AUTH + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + VALID_DIR_AUTH "TestingTorNetwork 1\n" ); tdata->opt->TestingV3AuthVotingStartOffset = -1; @@ -3633,7 +3739,8 @@ test_options_validate__v3_auth(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(VALID_DIR_AUTH + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + VALID_DIR_AUTH "TestingTorNetwork 1\n" "TestingV3AuthInitialVotingInterval 4\n" ); @@ -3642,6 +3749,48 @@ test_options_validate__v3_auth(void *ignored) tt_str_op(msg, OP_EQ, "TestingV3AuthInitialVotingInterval is insanely low."); tor_free(msg); + free_options_test_data(tdata); + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + VALID_DIR_AUTH + "TestingTorNetwork 1\n" + "TestingV3AuthInitialVoteDelay 2\n" + "TestingV3AuthInitialDistDelay 2\n" + "TestingV3AuthInitialVotingInterval 5\n" + ); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); + tt_ptr_op(msg, OP_EQ, NULL); + tor_free(msg); + + free_options_test_data(tdata); + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + VALID_DIR_AUTH + "TestingTorNetwork 1\n" + "TestingV3AuthInitialVotingInterval 7\n" + ); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, -1); + tt_str_op(msg, OP_EQ, + "TestingV3AuthInitialVotingInterval does not divide evenly into " + "30 minutes."); + tor_free(msg); + + free_options_test_data(tdata); + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + VALID_DIR_AUTH + "TestingTorNetwork 1\n" + "TestingV3AuthInitialVoteDelay 3\n" + "TestingV3AuthInitialDistDelay 3\n" + "TestingV3AuthInitialVotingInterval 5\n" + ); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, -1); + tt_str_op(msg, OP_EQ, + "TestingV3AuthInitialVoteDelay plus " + "TestingV3AuthInitialDistDelay must be less than " + "TestingV3AuthInitialVotingInterval"); + tor_free(msg); + done: policies_free_all(); teardown_capture_of_logs(); @@ -3688,10 +3837,11 @@ test_options_validate__testing_options(void *ignored) options_test_data_t *tdata = NULL; setup_capture_of_logs(LOG_WARN); -#define TEST_TESTING_OPTION(name, low_val, high_val, err_low) \ +#define TEST_TESTING_OPTION(name, low_val, high_val, err_low, EXTRA_OPT_STR) \ STMT_BEGIN \ free_options_test_data(tdata); \ - tdata = get_options_test_data(VALID_DIR_AUTH \ + tdata = get_options_test_data(EXTRA_OPT_STR \ + VALID_DIR_AUTH \ "TestingTorNetwork 1\n" \ ); \ tdata->opt-> name = low_val; \ @@ -3701,25 +3851,44 @@ test_options_validate__testing_options(void *ignored) tor_free(msg); \ \ free_options_test_data(tdata); \ - tdata = get_options_test_data(VALID_DIR_AUTH \ + tdata = get_options_test_data(EXTRA_OPT_STR \ + VALID_DIR_AUTH \ "TestingTorNetwork 1\n" \ ); \ tdata->opt-> name = high_val; \ mock_clean_saved_logs(); \ ret = options_validate(NULL, tdata->opt, &msg); \ tt_int_op(ret, OP_EQ, 0); \ + tt_ptr_op(msg, OP_EQ, NULL); \ expect_log_msg( #name " is insanely high.\n"); \ tor_free(msg); \ STMT_END TEST_TESTING_OPTION(TestingAuthDirTimeToLearnReachability, -1, 8000, - "must be non-negative."); + "must be non-negative.", ENABLE_AUTHORITY_V3); + TEST_TESTING_OPTION(TestingAuthDirTimeToLearnReachability, -1, 8000, + "must be non-negative.", ENABLE_AUTHORITY_BRIDGE); + TEST_TESTING_OPTION(TestingEstimatedDescriptorPropagationTime, -1, 3601, - "must be non-negative."); + "must be non-negative.", ""); TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, -1, 3601, - "is way too low."); + "is way too low.", ""); TEST_TESTING_OPTION(TestingDirConnectionMaxStall, 1, 3601, - "is way too low."); + "is way too low.", ""); + + TEST_TESTING_OPTION(TestingEstimatedDescriptorPropagationTime, -1, 3601, + "must be non-negative.", ENABLE_AUTHORITY_V3); + TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, -1, 3601, + "is way too low.", ENABLE_AUTHORITY_V3); + TEST_TESTING_OPTION(TestingDirConnectionMaxStall, 1, 3601, + "is way too low.", ENABLE_AUTHORITY_V3); + + TEST_TESTING_OPTION(TestingEstimatedDescriptorPropagationTime, -1, 3601, + "must be non-negative.", ENABLE_AUTHORITY_BRIDGE); + TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, -1, 3601, + "is way too low.", ENABLE_AUTHORITY_BRIDGE); + TEST_TESTING_OPTION(TestingDirConnectionMaxStall, 1, 3601, + "is way too low.", ENABLE_AUTHORITY_BRIDGE); free_options_test_data(tdata); tdata = get_options_test_data("TestingEnableConnBwEvent 1\n"); @@ -4144,6 +4313,7 @@ struct testcase_t options_tests[] = { LOCAL_VALIDATE_TEST(logs), LOCAL_VALIDATE_TEST(authdir), LOCAL_VALIDATE_TEST(relay_with_hidden_services), + LOCAL_VALIDATE_TEST(listen_ports), LOCAL_VALIDATE_TEST(transproxy), LOCAL_VALIDATE_TEST(exclude_nodes), LOCAL_VALIDATE_TEST(node_families), diff --git a/src/test/test_parseconf.sh b/src/test/test_parseconf.sh index 3edb5032e2..86a00f7a02 100755 --- a/src/test/test_parseconf.sh +++ b/src/test/test_parseconf.sh @@ -85,6 +85,8 @@ fi TOR_BINARY="$(abspath "$TOR_BINARY")" +echo "TOR BINARY IS ${TOR_BINARY}" + TOR_MODULES_DISABLED="$("$TOR_BINARY" --list-modules | grep ": no" \ | cut -d ":" -f1 | sort | tr "\n" "_")" # Remove the last underscore, if there is one @@ -116,7 +118,9 @@ else EXITCODE=1 fi -die() { echo "$1" >&2 ; exit "$EXITCODE"; } +FINAL_EXIT=0 + +die() { echo "$1" >&2 ; FINAL_EXIT=$EXITCODE; } if test "$WINDOWS" = 1; then FILTER="dos2unix" @@ -161,10 +165,10 @@ for dir in "${EXAMPLEDIR}"/*; do # Check for broken configs if test -f "./error${suffix}"; then - echo "FAIL: Found both ${dir}/expected${suffix}" - echo "and ${dir}/error${suffix}." - echo "(Only one of these files should exist.)" - exit $EXITCODE + echo "FAIL: Found both ${dir}/expected${suffix}" >&2 + echo "and ${dir}/error${suffix}." >&2 + echo "(Only one of these files should exist.)" >&2 + FINAL_EXIT=$EXITCODE fi EXPECTED="./expected${suffix}" @@ -185,7 +189,7 @@ for dir in "${EXAMPLEDIR}"/*; do --dump-config short \ ${CMDLINE} \ | "${FILTER}" > "${DATA_DIR}/output.${testname}" \ - || die "Failure: Tor exited." + || die "FAIL: $EXPECTED: Tor reported an error." if cmp "$EXPECTED" "${DATA_DIR}/output.${testname}">/dev/null ; then # Check round-trip. @@ -194,17 +198,18 @@ for dir in "${EXAMPLEDIR}"/*; do --dump-config short \ | "${FILTER}" \ > "${DATA_DIR}/output_2.${testname}" \ - || die "Failure: Tor exited on round-trip." + || die \ + "FAIL: $EXPECTED: Tor reported an error on round-trip." if ! cmp "${DATA_DIR}/output.${testname}" \ "${DATA_DIR}/output_2.${testname}"; then - echo "Failure: did not match on round-trip." - exit $EXITCODE + echo "FAIL: $EXPECTED did not match on round-trip." >&2 + FINAL_EXIT=$EXITCODE fi echo "OK" else - echo "FAIL" + echo "FAIL" >&2 if test "$(wc -c < "${DATA_DIR}/output.${testname}")" = 0; then # There was no output -- probably we failed. "${TOR_BINARY}" -f "./torrc" \ @@ -212,39 +217,49 @@ for dir in "${EXAMPLEDIR}"/*; do --verify-config \ ${CMDLINE} || true fi - diff -u "$EXPECTED" "${DATA_DIR}/output.${testname}" || /bin/true - exit $EXITCODE + echo "FAIL: $EXPECTED did not match." >&2 + diff -u "$EXPECTED" "${DATA_DIR}/output.${testname}" >&2 \ + || true + FINAL_EXIT=$EXITCODE fi elif test -f "$ERROR"; then # This case should fail: run verify-config and see if it does. + if ! test -s "$ERROR"; then + echo "FAIL: error file '$ERROR' is empty." >&2 + echo "Empty error files match any output." >&2 + FINAL_EXIT=$EXITCODE + fi + "${TOR_BINARY}" --verify-config \ -f ./torrc \ --defaults-torrc "${DEFAULTS}" \ ${CMDLINE} \ > "${DATA_DIR}/output.${testname}" \ - && die "Failure: Tor did not report an error." + && die "FAIL: $ERROR: Tor did not report an error." expect_err="$(cat $ERROR)" if grep "${expect_err}" "${DATA_DIR}/output.${testname}" >/dev/null; then echo "OK" else - echo "FAIL" - echo "Expected error: ${expect_err}" - echo "Tor said:" - cat "${DATA_DIR}/output.${testname}" - exit $EXITCODE + echo "FAIL" >&2 + echo "Expected $ERROR: ${expect_err}" >&2 + echo "Tor said:" >&2 + cat "${DATA_DIR}/output.${testname}" >&2 + FINAL_EXIT=$EXITCODE fi else # This case is not actually configured with a success or a failure. # call that an error. - echo "FAIL: Did not find ${dir}/*expected or ${dir}/*error." - exit $EXITCODE + echo "FAIL: Did not find ${dir}/*expected or ${dir}/*error." >&2 + FINAL_EXIT=$EXITCODE fi cd "${PREV_DIR}" done + +exit $FINAL_EXIT diff --git a/src/test/test_rebind.sh b/src/test/test_rebind.sh index d6d9d86668..879008c1c1 100755 --- a/src/test/test_rebind.sh +++ b/src/test/test_rebind.sh @@ -1,7 +1,23 @@ #!/bin/sh +umask 077 +set -e set -x +# emulate realpath(), in case coreutils or equivalent is not installed. +abspath() { + f="$*" + if [ -d "$f" ]; then + dir="$f" + base="" + else + dir="$(dirname "$f")" + base="/$(basename "$f")" + fi + dir="$(cd "$dir" && pwd)" + echo "$dir$base" +} + UNAME_OS=$(uname -s | cut -d_ -f1) if test "$UNAME_OS" = 'CYGWIN' || \ test "$UNAME_OS" = 'MSYS' || \ @@ -12,6 +28,23 @@ if test "$UNAME_OS" = 'CYGWIN' || \ fi fi +# find the tor binary +if [ $# -ge 1 ]; then + TOR_BINARY="${1}" + shift +else + TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}" +fi + +TOR_BINARY="$(abspath "$TOR_BINARY")" + +echo "TOR BINARY IS ${TOR_BINARY}" + +if "${TOR_BINARY}" --list-modules | grep -q "relay: no"; then + echo "This test requires the relay module. Skipping." >&2 + exit 77 +fi + tmpdir= clean () { if [ -n "$tmpdir" ] && [ -d "$tmpdir" ]; then @@ -30,6 +63,6 @@ elif [ ! -d "$tmpdir" ]; then exit 3 fi -"${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/test_rebind.py" "${TESTING_TOR_BINARY}" "$tmpdir" +"${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/test_rebind.py" "${TOR_BINARY}" "$tmpdir" exit $? diff --git a/src/test/test_stats.c b/src/test/test_stats.c new file mode 100644 index 0000000000..64e723c706 --- /dev/null +++ b/src/test/test_stats.c @@ -0,0 +1,258 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file test_stats.c + * \brief Unit tests for the statistics (reputation history) module. + **/ + +#include "orconfig.h" +#include "lib/crypt_ops/crypto_rand.h" +#include "app/config/or_state_st.h" +#include "test/rng_test_helpers.h" + +#include + +#ifdef _WIN32 +/* For mkdir() */ +#include +#else +#include +#endif /* defined(_WIN32) */ + +#include + +/* These macros pull in declarations for some functions and structures that + * are typically file-private. */ +#define CIRCUITSTATS_PRIVATE +#define CIRCUITLIST_PRIVATE +#define MAINLOOP_PRIVATE +#define STATEFILE_PRIVATE + +#include "core/or/or.h" +#include "lib/err/backtrace.h" +#include "lib/buf/buffers.h" +#include "core/or/circuitstats.h" +#include "app/config/config.h" +#include "test/test.h" +#include "core/mainloop/mainloop.h" +#include "lib/memarea/memarea.h" +#include "feature/stats/rephist.h" +#include "app/config/statefile.h" + +/** Run unit tests for some stats code. */ +static void +test_stats(void *arg) +{ + time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */ + char *s = NULL; + int i; + + /* Start with testing exit port statistics; we shouldn't collect exit + * stats without initializing them. */ + (void)arg; + rep_hist_note_exit_stream_opened(80); + rep_hist_note_exit_bytes(80, 100, 10000); + s = rep_hist_format_exit_stats(now + 86400); + tt_ptr_op(s, OP_EQ, NULL); + + /* Initialize stats, note some streams and bytes, and generate history + * string. */ + rep_hist_exit_stats_init(now); + rep_hist_note_exit_stream_opened(80); + rep_hist_note_exit_bytes(80, 100, 10000); + rep_hist_note_exit_stream_opened(443); + rep_hist_note_exit_bytes(443, 100, 10000); + rep_hist_note_exit_bytes(443, 100, 10000); + s = rep_hist_format_exit_stats(now + 86400); + tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "exit-kibibytes-written 80=1,443=1,other=0\n" + "exit-kibibytes-read 80=10,443=20,other=0\n" + "exit-streams-opened 80=4,443=4,other=0\n",OP_EQ, s); + tor_free(s); + + /* Add a few bytes on 10 more ports and ensure that only the top 10 + * ports are contained in the history string. */ + for (i = 50; i < 60; i++) { + rep_hist_note_exit_bytes(i, i, i); + rep_hist_note_exit_stream_opened(i); + } + s = rep_hist_format_exit_stats(now + 86400); + tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "exit-kibibytes-written 52=1,53=1,54=1,55=1,56=1,57=1,58=1," + "59=1,80=1,443=1,other=1\n" + "exit-kibibytes-read 52=1,53=1,54=1,55=1,56=1,57=1,58=1," + "59=1,80=10,443=20,other=1\n" + "exit-streams-opened 52=4,53=4,54=4,55=4,56=4,57=4,58=4," + "59=4,80=4,443=4,other=4\n",OP_EQ, s); + tor_free(s); + + /* Stop collecting stats, add some bytes, and ensure we don't generate + * a history string. */ + rep_hist_exit_stats_term(); + rep_hist_note_exit_bytes(80, 100, 10000); + s = rep_hist_format_exit_stats(now + 86400); + tt_ptr_op(s, OP_EQ, NULL); + + /* Re-start stats, add some bytes, reset stats, and see what history we + * get when observing no streams or bytes at all. */ + rep_hist_exit_stats_init(now); + rep_hist_note_exit_stream_opened(80); + rep_hist_note_exit_bytes(80, 100, 10000); + rep_hist_reset_exit_stats(now); + s = rep_hist_format_exit_stats(now + 86400); + tt_str_op("exit-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "exit-kibibytes-written other=0\n" + "exit-kibibytes-read other=0\n" + "exit-streams-opened other=0\n",OP_EQ, s); + tor_free(s); + + /* Continue with testing connection statistics; we shouldn't collect + * conn stats without initializing them. */ + rep_hist_note_or_conn_bytes(1, 20, 400, now); + s = rep_hist_format_conn_stats(now + 86400); + tt_ptr_op(s, OP_EQ, NULL); + + /* Initialize stats, note bytes, and generate history string. */ + rep_hist_conn_stats_init(now); + rep_hist_note_or_conn_bytes(1, 30000, 400000, now); + rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5); + rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10); + rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15); + s = rep_hist_format_conn_stats(now + 86400); + tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n",OP_EQ, s); + tor_free(s); + + /* Stop collecting stats, add some bytes, and ensure we don't generate + * a history string. */ + rep_hist_conn_stats_term(); + rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15); + s = rep_hist_format_conn_stats(now + 86400); + tt_ptr_op(s, OP_EQ, NULL); + + /* Re-start stats, add some bytes, reset stats, and see what history we + * get when observing no bytes at all. */ + rep_hist_conn_stats_init(now); + rep_hist_note_or_conn_bytes(1, 30000, 400000, now); + rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5); + rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10); + rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15); + rep_hist_reset_conn_stats(now); + s = rep_hist_format_conn_stats(now + 86400); + tt_str_op("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n",OP_EQ, s); + tor_free(s); + + /* Continue with testing buffer statistics; we shouldn't collect buffer + * stats without initializing them. */ + rep_hist_add_buffer_stats(2.0, 2.0, 20); + s = rep_hist_format_buffer_stats(now + 86400); + tt_ptr_op(s, OP_EQ, NULL); + + /* Initialize stats, add statistics for a single circuit, and generate + * the history string. */ + rep_hist_buffer_stats_init(now); + rep_hist_add_buffer_stats(2.0, 2.0, 20); + s = rep_hist_format_buffer_stats(now + 86400); + tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "cell-processed-cells 20,0,0,0,0,0,0,0,0,0\n" + "cell-queued-cells 2.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00," + "0.00,0.00\n" + "cell-time-in-queue 2,0,0,0,0,0,0,0,0,0\n" + "cell-circuits-per-decile 1\n",OP_EQ, s); + tor_free(s); + + /* Add nineteen more circuit statistics to the one that's already in the + * history to see that the math works correctly. */ + for (i = 21; i < 30; i++) + rep_hist_add_buffer_stats(2.0, 2.0, i); + for (i = 20; i < 30; i++) + rep_hist_add_buffer_stats(3.5, 3.5, i); + s = rep_hist_format_buffer_stats(now + 86400); + tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "cell-processed-cells 29,28,27,26,25,24,23,22,21,20\n" + "cell-queued-cells 2.75,2.75,2.75,2.75,2.75,2.75,2.75,2.75," + "2.75,2.75\n" + "cell-time-in-queue 3,3,3,3,3,3,3,3,3,3\n" + "cell-circuits-per-decile 2\n",OP_EQ, s); + tor_free(s); + + /* Stop collecting stats, add statistics for one circuit, and ensure we + * don't generate a history string. */ + rep_hist_buffer_stats_term(); + rep_hist_add_buffer_stats(2.0, 2.0, 20); + s = rep_hist_format_buffer_stats(now + 86400); + tt_ptr_op(s, OP_EQ, NULL); + + /* Re-start stats, add statistics for one circuit, reset stats, and make + * sure that the history has all zeros. */ + rep_hist_buffer_stats_init(now); + rep_hist_add_buffer_stats(2.0, 2.0, 20); + rep_hist_reset_buffer_stats(now); + s = rep_hist_format_buffer_stats(now + 86400); + tt_str_op("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "cell-processed-cells 0,0,0,0,0,0,0,0,0,0\n" + "cell-queued-cells 0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00," + "0.00,0.00\n" + "cell-time-in-queue 0,0,0,0,0,0,0,0,0,0\n" + "cell-circuits-per-decile 0\n",OP_EQ, s); + + done: + tor_free(s); +} + +/** Run unit tests the mtbf stats code. */ +static void +test_rephist_mtbf(void *arg) +{ + (void)arg; + + time_t now = 1572500000; /* 2010-10-31 05:33:20 UTC */ + time_t far_future = MAX(now, time(NULL)) + 365*24*60*60; + int r; + + /* Make a temporary datadir for these tests */ + char *ddir_fname = tor_strdup(get_fname_rnd("datadir_mtbf")); + tor_free(get_options_mutable()->DataDirectory); + get_options_mutable()->DataDirectory = tor_strdup(ddir_fname); + check_private_dir(ddir_fname, CPD_CREATE, NULL); + + rep_history_clean(far_future); + + /* No data */ + + r = rep_hist_load_mtbf_data(now); + tt_int_op(r, OP_EQ, -1); + rep_history_clean(far_future); + + /* Blank data */ + + r = rep_hist_record_mtbf_data(now, 0); + tt_int_op(r, OP_EQ, 0); + r = rep_hist_load_mtbf_data(now); + tt_int_op(r, OP_EQ, 0); + rep_history_clean(far_future); + + r = rep_hist_record_mtbf_data(now, 1); + tt_int_op(r, OP_EQ, 0); + r = rep_hist_load_mtbf_data(now); + tt_int_op(r, OP_EQ, 0); + rep_history_clean(far_future); + + done: + rep_history_clean(far_future); + tor_free(ddir_fname); +} + +#define ENT(name) \ + { #name, test_ ## name , 0, NULL, NULL } +#define FORK(name) \ + { #name, test_ ## name , TT_FORK, NULL, NULL } + +struct testcase_t stats_tests[] = { + FORK(stats), + ENT(rephist_mtbf), + + END_OF_TESTCASES +}; diff --git a/src/test/test_zero_length_keys.sh b/src/test/test_zero_length_keys.sh index eeabab352d..b944d9bf3f 100755 --- a/src/test/test_zero_length_keys.sh +++ b/src/test/test_zero_length_keys.sh @@ -1,15 +1,44 @@ #!/bin/sh # Check that tor regenerates keys when key files are zero-length -if "${builddir:-.}/src/app/tor" --list-modules | grep -q "relay: no"; then +umask 077 +set -e + +# emulate realpath(), in case coreutils or equivalent is not installed. +abspath() { + f="$*" + if [ -d "$f" ]; then + dir="$f" + base="" + else + dir="$(dirname "$f")" + base="/$(basename "$f")" + fi + dir="$(cd "$dir" && pwd)" + echo "$dir$base" +} + +# find the tor binary +if [ $# -ge 1 ]; then + TOR_BINARY="${1}" + shift +else + TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}" +fi + +TOR_BINARY="$(abspath "$TOR_BINARY")" + +echo "TOR BINARY IS ${TOR_BINARY}" + +if "$TOR_BINARY" --list-modules | grep -q "relay: no"; then echo "This test requires the relay module. Skipping." >&2 exit 77 fi exitcode=0 -"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/app/tor" -z || exitcode=1 -"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/app/tor" -d || exitcode=1 -"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "${builddir:-.}/src/app/tor" -e || exitcode=1 +"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "$TOR_BINARY" -z || exitcode=1 +"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "$TOR_BINARY" -d || exitcode=1 +"${SHELL:-sh}" "${abs_top_srcdir:-.}/src/test/zero_length_keys.sh" "$TOR_BINARY" -e || exitcode=1 exit ${exitcode}