diff options
Diffstat (limited to 'src')
508 files changed, 10204 insertions, 4709 deletions
diff --git a/src/app/app.dox b/src/app/app.dox new file mode 100644 index 0000000000..21d5791cde --- /dev/null +++ b/src/app/app.dox @@ -0,0 +1,8 @@ +/** +@dir /app +@brief app: top-level entry point for Tor + +The "app" directory has Tor's main entry point and configuration logic, +and is responsible for initializing and managing the other modules in +Tor. +**/ diff --git a/src/app/config/app_config.dox b/src/app/config/app_config.dox new file mode 100644 index 0000000000..ef4a878277 --- /dev/null +++ b/src/app/config/app_config.dox @@ -0,0 +1,8 @@ +/** +@dir /app/config +@brief app/config: Top-level configuration code + +Refactoring this module is a work in progress, see +[ticket 29211](https://trac.torproject.org/projects/tor/ticket/29211). + +**/ diff --git a/src/app/config/config.c b/src/app/config/config.c index deda2448b6..4a308a808f 100644 --- a/src/app/config/config.c +++ b/src/app/config/config.c @@ -22,7 +22,8 @@ * * To add new items to the torrc, there are a minimum of three places to edit: * <ul> - * <li>The or_options_t structure in or.h, where the options are stored. + * <li>The or_options_t structure in or_options_st.h, where the options are + * stored. * <li>The option_vars_ array below in this module, which configures * the names of the torrc options, their types, their multiplicities, * and their mappings to fields in or_options_t. @@ -32,16 +33,18 @@ * * Additionally, you might need to edit these places too: * <ul> - * <li>options_validate() below, in case you want to reject some possible + * <li>options_validate_cb() below, in case you want to reject some possible * values of the new configuration option. * <li>options_transition_allowed() below, in case you need to * forbid some or all changes in the option while Tor is * running. * <li>options_transition_affects_workers(), in case changes in the option * might require Tor to relaunch or reconfigure its worker threads. + * (This function is now in the relay module.) * <li>options_transition_affects_descriptor(), in case changes in the * option might require a Tor relay to build and publish a new server * descriptor. + * (This function is now in the relay module.) * <li>options_act() and/or options_act_reversible(), in case there's some * action that needs to be taken immediately based on the option's * value. @@ -61,22 +64,19 @@ #define CONFIG_PRIVATE #include "core/or/or.h" #include "app/config/config.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "app/config/statefile.h" #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" @@ -88,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" @@ -104,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" @@ -156,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" @@ -186,8 +180,12 @@ static const char unix_q_socket_prefix[] = "unix:\""; /** macro to help with the bulk rename of *DownloadSchedule to * *DowloadInitialDelay . */ +#ifndef COCCI #define DOWNLOAD_SCHEDULE(name) \ { #name "DownloadSchedule", #name "DownloadInitialDelay", 0, 1 } +#else +#define DOWNLOAD_SCHEDULE(name) { NULL, NULL, 0, 1 } +#endif /* !defined(COCCI) */ /** A list of abbreviations and aliases to map command-line options, obsolete * option names, or alternative option names, to their current values. */ @@ -268,6 +266,9 @@ DUMMY_TYPECHECK_INSTANCE(or_options_t); #define VAR_NODUMP(varname,conftype,member,initvalue) \ CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \ CFLG_NODUMP, initvalue) +#define VAR_NODUMP_IMMUTABLE(varname,conftype,member,initvalue) \ + CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \ + CFLG_NODUMP | CFLG_IMMUTABLE, initvalue) #define VAR_INVIS(varname,conftype,member,initvalue) \ CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \ CFLG_NODUMP | CFLG_NOSET | CFLG_NOLIST, initvalue) @@ -275,6 +276,13 @@ DUMMY_TYPECHECK_INSTANCE(or_options_t); #define V(member,conftype,initvalue) \ VAR(#member, conftype, member, initvalue) +#define VAR_IMMUTABLE(varname, conftype, member, initvalue) \ + CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \ + CFLG_IMMUTABLE, initvalue) + +#define V_IMMUTABLE(member,conftype,initvalue) \ + VAR_IMMUTABLE(#member, conftype, member, initvalue) + /** As V, but uses a type definition instead of a type enum */ #define V_D(member,type,initvalue) \ VAR_D(#member, type, member, initvalue) @@ -344,7 +352,7 @@ static const config_var_t option_vars_[] = { V(BridgeRecordUsageByCountry, BOOL, "1"), V(BridgeRelay, BOOL, "0"), V(BridgeDistribution, STRING, NULL), - VAR("CacheDirectory", FILENAME, CacheDirectory_option, NULL), + VAR_IMMUTABLE("CacheDirectory",FILENAME, CacheDirectory_option, NULL), V(CacheDirectoryGroupReadable, AUTOBOOL, "auto"), V(CellStatistics, BOOL, "0"), V(PaddingStatistics, BOOL, "1"), @@ -378,9 +386,9 @@ static const config_var_t option_vars_[] = { V(UnixSocksGroupWritable, BOOL, "0"), V(CookieAuthentication, BOOL, "0"), V(CookieAuthFileGroupReadable, BOOL, "0"), - V(CookieAuthFile, STRING, NULL), + V(CookieAuthFile, FILENAME, NULL), V(CountPrivateBandwidth, BOOL, "0"), - VAR("DataDirectory", FILENAME, DataDirectory_option, NULL), + VAR_IMMUTABLE("DataDirectory", FILENAME, DataDirectory_option, NULL), V(DataDirectoryGroupReadable, BOOL, "0"), V(DisableOOSCheck, BOOL, "1"), V(DisableNetwork, BOOL, "0"), @@ -401,8 +409,8 @@ static const config_var_t option_vars_[] = { * an order of magnitude, so there isn't too much load shifting to * authorities when fallbacks go down. */ V(DirAuthorityFallbackRate, DOUBLE, "0.1"), - V(DisableAllSwap, BOOL, "0"), - V(DisableDebuggerAttachment, BOOL, "1"), + V_IMMUTABLE(DisableAllSwap, BOOL, "0"), + V_IMMUTABLE(DisableDebuggerAttachment, BOOL, "1"), OBSOLETE("DisableIOCP"), OBSOLETE("DisableV2DirectoryInfo_"), OBSOLETE("DynamicDHGroups"), @@ -448,7 +456,7 @@ static const config_var_t option_vars_[] = { V(ExtendAllowPrivateAddresses, BOOL, "0"), V(ExitRelay, AUTOBOOL, "auto"), VPORT(ExtORPort), - V(ExtORPortCookieAuthFile, STRING, NULL), + V(ExtORPortCookieAuthFile, FILENAME, NULL), V(ExtORPortCookieAuthFileGroupReadable, BOOL, "0"), V(ExtraInfoStatistics, BOOL, "1"), V(ExtendByEd25519ID, AUTOBOOL, "auto"), @@ -478,11 +486,11 @@ static const config_var_t option_vars_[] = { #endif /* defined(_WIN32) */ OBSOLETE("Group"), V(GuardLifetime, INTERVAL, "0 minutes"), - V(HardwareAccel, BOOL, "0"), + V_IMMUTABLE(HardwareAccel, BOOL, "0"), V(HeartbeatPeriod, INTERVAL, "6 hours"), V(MainloopStats, BOOL, "0"), - V(AccelName, STRING, NULL), - V(AccelDir, FILENAME, NULL), + V_IMMUTABLE(AccelName, STRING, NULL), + V_IMMUTABLE(AccelDir, FILENAME, NULL), V(HashedControlPassword, LINELIST, NULL), OBSOLETE("HidServDirectoryV2"), VAR("HiddenServiceDir", LINELIST_S, RendConfigLines, NULL), @@ -506,8 +514,8 @@ static const config_var_t option_vars_[] = { V(ClientOnionAuthDir, FILENAME, NULL), OBSOLETE("CloseHSClientCircuitsImmediatelyOnTimeout"), OBSOLETE("CloseHSServiceRendCircuitsImmediatelyOnTimeout"), - V(HiddenServiceSingleHopMode, BOOL, "0"), - V(HiddenServiceNonAnonymousMode,BOOL, "0"), + V_IMMUTABLE(HiddenServiceSingleHopMode, BOOL, "0"), + V_IMMUTABLE(HiddenServiceNonAnonymousMode,BOOL, "0"), V(HTTPProxy, STRING, NULL), V(HTTPProxyAuthenticator, STRING, NULL), V(HTTPSProxy, STRING, NULL), @@ -522,18 +530,18 @@ static const config_var_t option_vars_[] = { V(Socks5Proxy, STRING, NULL), V(Socks5ProxyUsername, STRING, NULL), V(Socks5ProxyPassword, STRING, NULL), - VAR("KeyDirectory", FILENAME, KeyDirectory_option, NULL), + VAR_IMMUTABLE("KeyDirectory", FILENAME, KeyDirectory_option, NULL), V(KeyDirectoryGroupReadable, BOOL, "0"), VAR_D("HSLayer2Nodes", ROUTERSET, HSLayer2Nodes, NULL), VAR_D("HSLayer3Nodes", ROUTERSET, HSLayer3Nodes, NULL), V(KeepalivePeriod, INTERVAL, "5 minutes"), - V(KeepBindCapabilities, AUTOBOOL, "auto"), + V_IMMUTABLE(KeepBindCapabilities, AUTOBOOL, "auto"), VAR("Log", LINELIST, Logs, NULL), V(LogMessageDomains, BOOL, "0"), V(LogTimeGranularity, MSEC_INTERVAL, "1 second"), V(TruncateLogFile, BOOL, "0"), - V(SyslogIdentityTag, STRING, NULL), - V(AndroidIdentityTag, STRING, NULL), + V_IMMUTABLE(SyslogIdentityTag, STRING, NULL), + V_IMMUTABLE(AndroidIdentityTag,STRING, NULL), V(LongLivedPorts, CSV, "21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"), VAR("MapAddress", LINELIST, AddressMap, NULL), @@ -555,7 +563,7 @@ static const config_var_t option_vars_[] = { OBSOLETE("PredictedPortsRelevanceTime"), OBSOLETE("WarnUnsafeSocks"), VAR("NodeFamily", LINELIST, NodeFamilies, NULL), - V(NoExec, BOOL, "0"), + V_IMMUTABLE(NoExec, BOOL, "0"), V(NumCPUs, POSINT, "0"), V(NumDirectoryGuards, POSINT, "0"), V(NumEntryGuards, POSINT, "0"), @@ -586,8 +594,8 @@ static const config_var_t option_vars_[] = { V(PathsNeededToBuildCircuits, DOUBLE, "-1"), V(PerConnBWBurst, MEMUNIT, "0"), V(PerConnBWRate, MEMUNIT, "0"), - V(PidFile, STRING, NULL), - V(TestingTorNetwork, BOOL, "0"), + V_IMMUTABLE(PidFile, FILENAME, NULL), + V_IMMUTABLE(TestingTorNetwork, BOOL, "0"), V(TestingMinExitFlagThreshold, MEMUNIT, "0"), V(TestingMinFastFlagThreshold, MEMUNIT, "0"), @@ -621,17 +629,17 @@ static const config_var_t option_vars_[] = { V(RelayBandwidthRate, MEMUNIT, "0"), V(RendPostPeriod, INTERVAL, "1 hour"), V(RephistTrackTime, INTERVAL, "24 hours"), - V(RunAsDaemon, BOOL, "0"), + V_IMMUTABLE(RunAsDaemon, BOOL, "0"), V(ReducedExitPolicy, BOOL, "0"), OBSOLETE("RunTesting"), // currently unused - V(Sandbox, BOOL, "0"), + V_IMMUTABLE(Sandbox, BOOL, "0"), V(SafeLogging, STRING, "1"), V(SafeSocks, BOOL, "0"), V(ServerDNSAllowBrokenConfig, BOOL, "1"), V(ServerDNSAllowNonRFC953Hostnames, BOOL,"0"), V(ServerDNSDetectHijacking, BOOL, "1"), V(ServerDNSRandomizeCase, BOOL, "1"), - V(ServerDNSResolvConfFile, STRING, NULL), + V(ServerDNSResolvConfFile, FILENAME, NULL), V(ServerDNSSearchDomains, BOOL, "0"), V(ServerDNSTestAddresses, CSV, "www.google.com,www.mit.edu,www.yahoo.com,www.slashdot.org"), @@ -652,7 +660,7 @@ static const config_var_t option_vars_[] = { V(StrictNodes, BOOL, "0"), OBSOLETE("Support022HiddenServices"), V(TestSocks, BOOL, "0"), - V(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"), + V_IMMUTABLE(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"), OBSOLETE("Tor2webMode"), OBSOLETE("Tor2webRendezvousPoints"), OBSOLETE("TLSECGroup"), @@ -669,7 +677,7 @@ static const config_var_t option_vars_[] = { V(UseGuardFraction, AUTOBOOL, "auto"), V(UseMicrodescriptors, AUTOBOOL, "auto"), OBSOLETE("UseNTorHandshake"), - V(User, STRING, NULL), + V_IMMUTABLE(User, STRING, NULL), OBSOLETE("UserspaceIOCPBuffers"), V(AuthDirSharedRandomness, BOOL, "1"), V(AuthDirTestEd25519LinkKeys, BOOL, "1"), @@ -697,12 +705,14 @@ static const config_var_t option_vars_[] = { VAR_NODUMP("__ReloadTorrcOnSIGHUP", BOOL, ReloadTorrcOnSIGHUP, "1"), VAR_NODUMP("__AllDirActionsPrivate", BOOL, AllDirActionsPrivate, "0"), VAR_NODUMP("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"), - VAR_NODUMP("__DisableSignalHandlers", BOOL, DisableSignalHandlers, "0"), + VAR_NODUMP_IMMUTABLE("__DisableSignalHandlers", BOOL, + DisableSignalHandlers, "0"), VAR_NODUMP("__LeaveStreamsUnattached",BOOL, LeaveStreamsUnattached, "0"), VAR_NODUMP("__HashedControlSessionPassword", LINELIST, HashedControlSessionPassword, NULL), - VAR_NODUMP("__OwningControllerProcess",STRING,OwningControllerProcess, NULL), + VAR_NODUMP_IMMUTABLE("__OwningControllerProcess",STRING, + OwningControllerProcess, NULL), VAR_NODUMP("__OwningControllerFD", UINT64, OwningControllerFD, UINT64_MAX_STRING), V(MinUptimeHidServDirectoryV2, INTERVAL, "96 hours"), @@ -765,7 +775,9 @@ static const config_var_t option_vars_[] = { /** List of default directory authorities */ static const char *default_authorities[] = { +#ifndef COCCI #include "auth_dirs.inc" +#endif NULL }; @@ -773,7 +785,9 @@ static const char *default_authorities[] = { * relays that meet certain stability criteria. */ static const char *default_fallbacks[] = { +#ifndef COCCI #include "fallback_dirs.inc" +#endif NULL }; @@ -783,7 +797,9 @@ static const struct { const char *k; const char *v; } testing_tor_network_defaults[] = { +#ifndef COCCI #include "testnet.inc" +#endif { NULL, NULL } }; @@ -812,32 +828,16 @@ static const config_deprecation_t option_deprecation_notes_[] = { #ifdef _WIN32 static char *get_windows_conf_root(void); #endif -static int options_act_reversible(const or_options_t *old_options, char **msg); -static int options_transition_allowed(const or_options_t *old, - const or_options_t *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 options_check_transition_cb(const void *old, + const void *new, + char **msg); 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); -static int options_init_logs(const or_options_t *old_options, - or_options_t *options, int validate_only); static void init_libevent(const or_options_t *options); static int opt_streq(const char *s1, const char *s2); @@ -845,31 +845,33 @@ static int parse_outbound_addresses(or_options_t *options, int validate_only, char **msg); static void config_maybe_load_geoip_files_(const or_options_t *options, const or_options_t *old_options); -static int options_validate_cb(void *old_options, void *options, - void *default_options, - int from_setconf, char **msg); +static int options_validate_cb(const void *old_options, void *options, + char **msg); static void cleanup_protocol_warning_severity_level(void); static void set_protocol_warning_severity_level(int warning_severity); static void options_clear_cb(const config_mgr_t *mgr, void *opts); +static setopt_err_t options_validate_and_set(const or_options_t *old_options, + or_options_t *new_options, + char **msg_out); /** Magic value for or_options_t. */ #define OR_OPTIONS_MAGIC 9090909 /** Configuration format for or_options_t. */ static const config_format_t options_format = { - sizeof(or_options_t), - { + .size = sizeof(or_options_t), + .magic = { "or_options_t", OR_OPTIONS_MAGIC, offsetof(or_options_t, magic_), }, - option_abbrevs_, - option_deprecation_notes_, - option_vars_, - options_validate_cb, - options_clear_cb, - NULL, - offsetof(or_options_t, subconfigs_), + .abbrevs = option_abbrevs_, + .deprecations = option_deprecation_notes_, + .vars = option_vars_, + .legacy_validate_fn = options_validate_cb, + .check_transition_fn = options_check_transition_cb, + .clear_fn = options_clear_cb, + .config_suite_offset = offsetof(or_options_t, subconfigs_), }; /* @@ -885,14 +887,8 @@ static or_options_t *global_default_options = NULL; static char *torrc_fname = NULL; /** Name of the most recently read torrc-defaults file.*/ static char *torrc_defaults_fname = NULL; -/** Configuration options set by command line. */ -static config_line_t *global_cmdline_options = NULL; -/** Non-configuration options set by the command line */ -static config_line_t *global_cmdline_only_options = NULL; -/** Boolean: Have we parsed the command line? */ -static int have_parsed_cmdline = 0; -/** Contents of most recently read DirPortFrontPage file. */ -static char *global_dirfrontpagecontents = NULL; +/** Result of parsing the command line. */ +static parsed_cmdline_t *global_cmdline = 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 @@ -915,12 +911,9 @@ get_options_mgr(void) return options_mgr; } -/** Return the contents of our frontpage string, or NULL if not configured. */ -MOCK_IMPL(const char*, -get_dirportfrontpage, (void)) -{ - return global_dirfrontpagecontents; -} +#define CHECK_OPTIONS_MAGIC(opt) STMT_BEGIN \ + config_check_toplevel_magic(get_options_mgr(), (opt)); \ + STMT_END /** Returns the currently configured options. */ MOCK_IMPL(or_options_t *, @@ -1021,6 +1014,7 @@ static void options_clear_cb(const config_mgr_t *mgr, void *opts) { (void)mgr; + CHECK_OPTIONS_MAGIC(opts); or_options_t *options = opts; routerset_free(options->ExcludeExitNodesUnion_); @@ -1064,11 +1058,7 @@ config_free_all(void) or_options_free(global_default_options); global_default_options = NULL; - config_free_lines(global_cmdline_options); - global_cmdline_options = NULL; - - config_free_lines(global_cmdline_only_options); - global_cmdline_only_options = NULL; + parsed_cmdline_free(global_cmdline); if (configured_ports) { SMARTLIST_FOREACH(configured_ports, @@ -1079,11 +1069,9 @@ config_free_all(void) tor_free(torrc_fname); tor_free(torrc_defaults_fname); - tor_free(global_dirfrontpagecontents); cleanup_protocol_warning_severity_level(); - have_parsed_cmdline = 0; libevent_initialized = 0; config_mgr_free(options_mgr); @@ -1239,7 +1227,8 @@ add_default_fallback_dir_servers,(void)) * user if we changed any dangerous ones. */ static int -validate_dir_servers(or_options_t *options, or_options_t *old_options) +validate_dir_servers(const or_options_t *options, + const or_options_t *old_options) { config_line_t *cl; @@ -1426,8 +1415,8 @@ static int have_low_ports = -1; * * Return 0 if all goes well, return -1 if things went badly. */ -static int -options_act_reversible(const or_options_t *old_options, char **msg) +MOCK_IMPL(STATIC int, +options_act_reversible,(const or_options_t *old_options, char **msg)) { smartlist_t *new_listeners = smartlist_new(); or_options_t *options = get_options_mutable(); @@ -1502,6 +1491,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"); @@ -1515,6 +1505,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."); @@ -1752,32 +1743,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; @@ -1820,32 +1785,6 @@ options_transition_affects_guards(const or_options_t *old_options, return 0; } -/** - * Return true if changing the configuration from <b>old</b> to <b>new</b> - * affects the timing of the voting subsystem - */ -static int -options_transition_affects_dirauth_timing(const or_options_t *old_options, - const or_options_t *new_options) -{ - tor_assert(old_options); - tor_assert(new_options); - - if (authdir_mode_v3(old_options) != authdir_mode_v3(new_options)) - return 1; - if (! authdir_mode_v3(new_options)) - return 0; - YES_IF_CHANGED_INT(V3AuthVotingInterval); - YES_IF_CHANGED_INT(V3AuthVoteDelay); - YES_IF_CHANGED_INT(V3AuthDistDelay); - YES_IF_CHANGED_INT(TestingV3AuthInitialVotingInterval); - YES_IF_CHANGED_INT(TestingV3AuthInitialVoteDelay); - YES_IF_CHANGED_INT(TestingV3AuthInitialDistDelay); - YES_IF_CHANGED_INT(TestingV3AuthVotingStartOffset); - - return 0; -} - /** Fetch the active option list, and take actions based on it. All of the * things we do should survive being done repeatedly. If present, * <b>old_options</b> contains the previous value of the options. @@ -1853,17 +1792,16 @@ 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. */ -STATIC int -options_act(const or_options_t *old_options) +MOCK_IMPL(STATIC int, +options_act,(const or_options_t *old_options)) { config_line_t *cl; 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); @@ -1921,19 +1859,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) { @@ -1983,22 +1908,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 " @@ -2008,20 +1928,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(); @@ -2042,16 +1953,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. */ @@ -2075,15 +1978,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; @@ -2101,15 +1995,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()); @@ -2133,6 +2020,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 " @@ -2219,65 +2107,17 @@ options_act(const or_options_t *old_options) if (revise_automap_entries) addressmap_clear_invalid_automaps(options); -/* How long should we delay counting bridge stats after becoming a bridge? - * We use this so we don't count clients who used our bridge thinking it is - * a relay. If you change this, don't forget to change the log message - * below. It's 4 hours (the time it takes to stop being used by clients) - * plus some extra time for clock skew. */ -#define RELAY_BRIDGE_STATS_DELAY (6 * 60 * 60) - - if (! bool_eq(options->BridgeRelay, old_options->BridgeRelay)) { - int was_relay = 0; - if (options->BridgeRelay) { - time_t int_start = time(NULL); - if (config_lines_eq(old_options->ORPort_lines,options->ORPort_lines)) { - int_start += RELAY_BRIDGE_STATS_DELAY; - was_relay = 1; - } - geoip_bridge_stats_init(int_start); - log_info(LD_CONFIG, "We are acting as a bridge now. Starting new " - "GeoIP stats interval%s.", was_relay ? " in 6 " - "hours from now" : ""); - } else { - geoip_bridge_stats_term(); - log_info(LD_GENERAL, "We are no longer acting as a bridge. " - "Forgetting GeoIP stats."); - } - } - - if (transition_affects_workers) { - log_info(LD_GENERAL, - "Worker-related options changed. Rotating workers."); - const int server_mode_turned_on = - server_mode(options) && !server_mode(old_options); - const int dir_server_mode_turned_on = - dir_server_mode(options) && !dir_server_mode(old_options); - - if (server_mode_turned_on || dir_server_mode_turned_on) { - cpu_init(); - } + if (options_act_bridge_stats(old_options) < 0) + return -1; - if (server_mode_turned_on) { - ip_address_changed(0); - if (have_completed_a_circuit() || !any_predicted_circuits(time(NULL))) - inform_testing_reachability(); - } - cpuworkers_rotate_keyinfo(); - if (dns_reset()) - return -1; - } else { - if (dns_reset()) - return -1; - } + if (dns_reset()) + return -1; - if (options->PerConnBWRate != old_options->PerConnBWRate || - options->PerConnBWBurst != old_options->PerConnBWBurst) - connection_or_update_token_buckets(get_connection_array(), options); + if (options_act_relay_bandwidth(old_options) < 0) + return -1; if (options->BandwidthRate != old_options->BandwidthRate || - options->BandwidthBurst != old_options->BandwidthBurst || - options->RelayBandwidthRate != old_options->RelayBandwidthRate || - options->RelayBandwidthBurst != old_options->RelayBandwidthBurst) + options->BandwidthBurst != old_options->BandwidthBurst) connection_bucket_adjust(options); if (options->MainloopStats != old_options->MainloopStats) { @@ -2285,128 +2125,39 @@ options_act(const or_options_t *old_options) } } + /* 31851: These options are relay-only, but we need to disable them if we + * are in client mode. In 29211, we will disable all relay options in + * client mode. */ /* Only collect directory-request statistics on relays and bridges. */ options->DirReqStatistics = options->DirReqStatistics_option && server_mode(options); options->HiddenServiceStatistics = options->HiddenServiceStatistics_option && server_mode(options); - if (options->CellStatistics || options->DirReqStatistics || - options->EntryStatistics || options->ExitPortStatistics || - options->ConnDirectionStatistics || - options->HiddenServiceStatistics || - options->BridgeAuthoritativeDir) { - time_t now = time(NULL); - int print_notice = 0; - - /* Only collect other relay-only statistics on relays. */ - if (!public_server_mode(options)) { - options->CellStatistics = 0; - options->EntryStatistics = 0; - options->ConnDirectionStatistics = 0; - options->ExitPortStatistics = 0; - } - - if ((!old_options || !old_options->CellStatistics) && - options->CellStatistics) { - rep_hist_buffer_stats_init(now); - print_notice = 1; - } - if ((!old_options || !old_options->DirReqStatistics) && - options->DirReqStatistics) { - if (geoip_is_loaded(AF_INET)) { - geoip_dirreq_stats_init(now); - print_notice = 1; - } else { - /* disable statistics collection since we have no geoip file */ - options->DirReqStatistics = 0; - if (options->ORPort_set) - log_notice(LD_CONFIG, "Configured to measure directory request " - "statistics, but no GeoIP database found. " - "Please specify a GeoIP database using the " - "GeoIPFile option."); - } - } - if ((!old_options || !old_options->EntryStatistics) && - options->EntryStatistics && !should_record_bridge_info(options)) { - /* If we get here, we've started recording bridge info when we didn't - * do so before. Note that "should_record_bridge_info()" will - * always be false at this point, because of the earlier block - * that cleared EntryStatistics when public_server_mode() was false. - * We're leaving it in as defensive programming. */ - if (geoip_is_loaded(AF_INET) || geoip_is_loaded(AF_INET6)) { - geoip_entry_stats_init(now); - print_notice = 1; - } else { - options->EntryStatistics = 0; - log_notice(LD_CONFIG, "Configured to measure entry node " - "statistics, but no GeoIP database found. " - "Please specify a GeoIP database using the " - "GeoIPFile option."); - } - } - if ((!old_options || !old_options->ExitPortStatistics) && - options->ExitPortStatistics) { - rep_hist_exit_stats_init(now); - print_notice = 1; - } - if ((!old_options || !old_options->ConnDirectionStatistics) && - options->ConnDirectionStatistics) { - rep_hist_conn_stats_init(now); - } - if ((!old_options || !old_options->HiddenServiceStatistics) && - options->HiddenServiceStatistics) { - log_info(LD_CONFIG, "Configured to measure hidden service statistics."); - rep_hist_hs_stats_init(now); - } - if ((!old_options || !old_options->BridgeAuthoritativeDir) && - options->BridgeAuthoritativeDir) { - rep_hist_desc_stats_init(now); - print_notice = 1; - } - if (print_notice) - log_notice(LD_CONFIG, "Configured to measure statistics. Look for " - "the *-stats files that will first be written to the " - "data directory in 24 hours from now."); - } - - /* If we used to have statistics enabled but we just disabled them, - stop gathering them. */ - if (old_options && old_options->CellStatistics && - !options->CellStatistics) - rep_hist_buffer_stats_term(); - if (old_options && old_options->DirReqStatistics && - !options->DirReqStatistics) - geoip_dirreq_stats_term(); - if (old_options && old_options->EntryStatistics && - !options->EntryStatistics) - geoip_entry_stats_term(); - if (old_options && old_options->HiddenServiceStatistics && - !options->HiddenServiceStatistics) - rep_hist_hs_stats_term(); - if (old_options && old_options->ExitPortStatistics && - !options->ExitPortStatistics) - rep_hist_exit_stats_term(); - if (old_options && old_options->ConnDirectionStatistics && - !options->ConnDirectionStatistics) - rep_hist_conn_stats_term(); - if (old_options && old_options->BridgeAuthoritativeDir && - !options->BridgeAuthoritativeDir) - rep_hist_desc_stats_term(); - - /* Since our options changed, we might need to regenerate and upload our - * server descriptor. - */ - if (!old_options || - options_transition_affects_descriptor(old_options, options)) - mark_my_descriptor_dirty("config change"); + /* Only collect other relay-only statistics on relays. */ + if (!public_server_mode(options)) { + options->CellStatistics = 0; + options->EntryStatistics = 0; + options->ConnDirectionStatistics = 0; + options->ExitPortStatistics = 0; + } + + bool print_notice = 0; + if (options_act_relay_stats(old_options, &print_notice) < 0) + return -1; + if (options_act_dirauth_stats(old_options, &print_notice) < 0) + return -1; + if (print_notice) + options_act_relay_stats_msg(); + + if (options_act_relay_desc(old_options) < 0) + return -1; + + if (options_act_dirauth(old_options) < 0) + return -1; /* We may need to reschedule some directory stuff if our status changed. */ if (old_options) { - if (options_transition_affects_dirauth_timing(old_options, options)) { - voting_schedule_recalculate_timing(options, time(NULL)); - reschedule_dirvote(options); - } if (!bool_eq(directory_fetches_dir_info_early(options), directory_fetches_dir_info_early(old_options)) || !bool_eq(directory_fetches_dir_info_later(options), @@ -2420,87 +2171,110 @@ 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; } +/** + * Enumeration to describe the syntax for a command-line option. + **/ typedef enum { - TAKES_NO_ARGUMENT = 0, + /** Describe an option that does not take an argument. */ + ARGUMENT_NONE = 0, + /** Describes an option that takes a single argument. */ ARGUMENT_NECESSARY = 1, + /** Describes an option that takes a single optional argument. */ ARGUMENT_OPTIONAL = 2 } takes_argument_t; +/** Table describing arguments that Tor accepts on the command line, + * other than those that are the same as in torrc. */ static const struct { + /** The string that the user has to provide. */ const char *name; + /** Does this option accept an argument? */ takes_argument_t takes_argument; + /** If not CMD_RUN_TOR, what should Tor do when it starts? */ + tor_cmdline_mode_t command; + /** If nonzero, set the quiet level to this. 1 is "hush", 2 is "quiet" */ + int quiet; } CMDLINE_ONLY_OPTIONS[] = { - { "-f", ARGUMENT_NECESSARY }, - { "--allow-missing-torrc", TAKES_NO_ARGUMENT }, - { "--defaults-torrc", ARGUMENT_NECESSARY }, - { "--hash-password", ARGUMENT_NECESSARY }, - { "--dump-config", ARGUMENT_OPTIONAL }, - { "--list-fingerprint", TAKES_NO_ARGUMENT }, - { "--keygen", TAKES_NO_ARGUMENT }, - { "--key-expiration", ARGUMENT_OPTIONAL }, - { "--newpass", TAKES_NO_ARGUMENT }, - { "--no-passphrase", TAKES_NO_ARGUMENT }, - { "--passphrase-fd", ARGUMENT_NECESSARY }, - { "--verify-config", TAKES_NO_ARGUMENT }, - { "--ignore-missing-torrc", TAKES_NO_ARGUMENT }, - { "--quiet", TAKES_NO_ARGUMENT }, - { "--hush", TAKES_NO_ARGUMENT }, - { "--version", TAKES_NO_ARGUMENT }, - { "--list-modules", TAKES_NO_ARGUMENT }, - { "--library-versions", TAKES_NO_ARGUMENT }, - { "-h", TAKES_NO_ARGUMENT }, - { "--help", TAKES_NO_ARGUMENT }, - { "--list-torrc-options", TAKES_NO_ARGUMENT }, - { "--list-deprecated-options",TAKES_NO_ARGUMENT }, - { "--nt-service", TAKES_NO_ARGUMENT }, - { "-nt-service", TAKES_NO_ARGUMENT }, - { NULL, 0 }, + { .name="-f", + .takes_argument=ARGUMENT_NECESSARY }, + { .name="--allow-missing-torrc" }, + { .name="--defaults-torrc", + .takes_argument=ARGUMENT_NECESSARY }, + { .name="--hash-password", + .takes_argument=ARGUMENT_NECESSARY, + .command=CMD_HASH_PASSWORD, + .quiet=QUIET_HUSH }, + { .name="--dump-config", + .takes_argument=ARGUMENT_OPTIONAL, + .command=CMD_DUMP_CONFIG, + .quiet=QUIET_SILENT }, + { .name="--list-fingerprint", + .command=CMD_LIST_FINGERPRINT }, + { .name="--keygen", + .command=CMD_KEYGEN }, + { .name="--key-expiration", + .takes_argument=ARGUMENT_OPTIONAL, + .command=CMD_KEY_EXPIRATION }, + { .name="--newpass" }, + { .name="--no-passphrase" }, + { .name="--passphrase-fd", + .takes_argument=ARGUMENT_NECESSARY }, + { .name="--verify-config", + .command=CMD_VERIFY_CONFIG }, + { .name="--ignore-missing-torrc" }, + { .name="--quiet", + .quiet=QUIET_SILENT }, + { .name="--hush", + .quiet=QUIET_HUSH }, + { .name="--version", + .command=CMD_IMMEDIATE, + .quiet=QUIET_HUSH }, + { .name="--list-modules", + .command=CMD_IMMEDIATE, + .quiet=QUIET_HUSH }, + { .name="--library-versions", + .command=CMD_IMMEDIATE, + .quiet=QUIET_HUSH }, + { .name="-h", + .command=CMD_IMMEDIATE, + .quiet=QUIET_HUSH }, + { .name="--help", + .command=CMD_IMMEDIATE, + .quiet=QUIET_HUSH }, + { .name="--list-torrc-options", + .command=CMD_IMMEDIATE, + .quiet=QUIET_HUSH }, + { .name="--list-deprecated-options", + .command=CMD_IMMEDIATE }, + { .name="--nt-service" }, + { .name="-nt-service" }, + { .name=NULL }, }; /** Helper: Read a list of configuration options from the command line. If - * successful, or if ignore_errors is set, put them in *<b>result</b>, put the - * commandline-only options in *<b>cmdline_result</b>, and return 0; - * otherwise, return -1 and leave *<b>result</b> and <b>cmdline_result</b> - * alone. */ -int -config_parse_commandline(int argc, char **argv, int ignore_errors, - config_line_t **result, - config_line_t **cmdline_result) + * successful, return a newly allocated parsed_cmdline_t; otherwise return + * NULL. + * + * If <b>ignore_errors</b> is set, try to recover from all recoverable + * errors and return the best command line we can. + */ +parsed_cmdline_t * +config_parse_commandline(int argc, char **argv, int ignore_errors) { + parsed_cmdline_t *result = tor_malloc_zero(sizeof(parsed_cmdline_t)); + result->command = CMD_RUN_TOR; config_line_t *param = NULL; - config_line_t *front = NULL; - config_line_t **new = &front; - - config_line_t *front_cmdline = NULL; - config_line_t **new_cmdline = &front_cmdline; + config_line_t **new_cmdline = &result->cmdline_opts; + config_line_t **new = &result->other_opts; char *s, *arg; int i = 1; @@ -2510,11 +2284,19 @@ config_parse_commandline(int argc, char **argv, int ignore_errors, takes_argument_t want_arg = ARGUMENT_NECESSARY; int is_cmdline = 0; int j; + bool is_a_command = false; for (j = 0; CMDLINE_ONLY_OPTIONS[j].name != NULL; ++j) { if (!strcmp(argv[i], CMDLINE_ONLY_OPTIONS[j].name)) { is_cmdline = 1; want_arg = CMDLINE_ONLY_OPTIONS[j].takes_argument; + if (CMDLINE_ONLY_OPTIONS[j].command != CMD_RUN_TOR) { + is_a_command = true; + result->command = CMDLINE_ONLY_OPTIONS[j].command; + } + quiet_level_t quiet = CMDLINE_ONLY_OPTIONS[j].quiet; + if (quiet > result->quiet_level) + result->quiet_level = quiet; break; } } @@ -2545,14 +2327,13 @@ config_parse_commandline(int argc, char **argv, int ignore_errors, } else { log_warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.", argv[i]); - config_free_lines(front); - config_free_lines(front_cmdline); - return -1; + parsed_cmdline_free(result); + return NULL; } } else if (want_arg == ARGUMENT_OPTIONAL && is_last) { arg = tor_strdup(""); } else { - arg = (want_arg != TAKES_NO_ARGUMENT) ? tor_strdup(argv[i+1]) : + arg = (want_arg != ARGUMENT_NONE) ? tor_strdup(argv[i+1]) : tor_strdup(""); } @@ -2565,6 +2346,10 @@ config_parse_commandline(int argc, char **argv, int ignore_errors, log_debug(LD_CONFIG, "command line: parsed keyword '%s', value '%s'", param->key, param->value); + if (is_a_command) { + result->command_arg = param->value; + } + if (is_cmdline) { *new_cmdline = param; new_cmdline = &((*new_cmdline)->next); @@ -2575,9 +2360,19 @@ config_parse_commandline(int argc, char **argv, int ignore_errors, i += want_arg ? 2 : 1; } - *cmdline_result = front_cmdline; - *result = front; - return 0; + + return result; +} + +/** Release all storage held by <b>cmdline</b>. */ +void +parsed_cmdline_free_(parsed_cmdline_t *cmdline) +{ + if (!cmdline) + return; + config_free_lines(cmdline->cmdline_opts); + config_free_lines(cmdline->other_opts); + tor_free(cmdline); } /** Return true iff key is a valid configuration option. */ @@ -2623,37 +2418,9 @@ options_trial_assign(config_line_t *list, unsigned flags, char **msg) or_options_free(trial_options); return r; } + const or_options_t *cur_options = get_options(); - setopt_err_t rv; - or_options_t *cur_options = get_options_mutable(); - - in_option_validation = 1; - - if (options_validate(cur_options, trial_options, - global_default_options, 1, msg) < 0) { - or_options_free(trial_options); - rv = SETOPT_ERR_PARSE; /*XXX make this a separate return value. */ - goto done; - } - - if (options_transition_allowed(cur_options, trial_options, msg) < 0) { - or_options_free(trial_options); - rv = SETOPT_ERR_TRANSITION; - goto done; - } - in_option_validation = 0; - - if (set_options(trial_options, msg)<0) { - or_options_free(trial_options); - rv = SETOPT_ERR_SETTING; - goto done; - } - - /* we liked it. put it in place. */ - rv = SETOPT_OK; - done: - in_option_validation = 0; - return rv; + return options_validate_and_set(cur_options, trial_options, msg); } /** Print a usage message for tor. */ @@ -2703,6 +2470,7 @@ list_deprecated_options(void) static void list_enabled_modules(void) { + printf("%s: %s\n", "relay", have_module_relay() ? "yes" : "no"); printf("%s: %s\n", "dirauth", have_module_dirauth() ? "yes" : "no"); } @@ -3006,7 +2774,9 @@ is_local_addr, (const tor_addr_t *addr)) or_options_t * options_new(void) { - return config_new(get_options_mgr()); + or_options_t *options = config_new(get_options_mgr()); + options->command = CMD_RUN_TOR; + return options; } /** Set <b>options</b> to hold reasonable defaults for most options. @@ -3084,8 +2854,8 @@ validate_ports_csv(smartlist_t *sl, const char *name, char **msg) * a complaint into *<b>msg</b> using string <b>desc</b>, and return -1. * Else return 0. */ -static int -ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg) +int +config_ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg) { if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) { /* This handles an understandable special case where somebody says "2gb" @@ -3101,48 +2871,6 @@ ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg) return 0; } -/** Parse an authority type from <b>options</b>-\>PublishServerDescriptor - * and write it to <b>options</b>-\>PublishServerDescriptor_. Treat "1" - * as "v3" unless BridgeRelay is 1, in which case treat it as "bridge". - * Treat "0" as "". - * Return 0 on success or -1 if not a recognized authority type (in which - * case the value of PublishServerDescriptor_ is undefined). */ -static int -compute_publishserverdescriptor(or_options_t *options) -{ - smartlist_t *list = options->PublishServerDescriptor; - dirinfo_type_t *auth = &options->PublishServerDescriptor_; - *auth = NO_DIRINFO; - if (!list) /* empty list, answer is none */ - return 0; - SMARTLIST_FOREACH_BEGIN(list, const char *, string) { - if (!strcasecmp(string, "v1")) - log_warn(LD_CONFIG, "PublishServerDescriptor v1 has no effect, because " - "there are no v1 directory authorities anymore."); - else if (!strcmp(string, "1")) - if (options->BridgeRelay) - *auth |= BRIDGE_DIRINFO; - else - *auth |= V3_DIRINFO; - else if (!strcasecmp(string, "v2")) - log_warn(LD_CONFIG, "PublishServerDescriptor v2 has no effect, because " - "there are no v2 directory authorities anymore."); - else if (!strcasecmp(string, "v3")) - *auth |= V3_DIRINFO; - else if (!strcasecmp(string, "bridge")) - *auth |= BRIDGE_DIRINFO; - else if (!strcasecmp(string, "hidserv")) - log_warn(LD_CONFIG, - "PublishServerDescriptor hidserv is invalid. See " - "PublishHidServDescriptors."); - else if (!strcasecmp(string, "") || !strcmp(string, "0")) - /* no authority */; - else - return -1; - } SMARTLIST_FOREACH_END(string); - return 0; -} - /** Lowest allowable value for RendPostPeriod; if this is too low, hidden * services can overload the directory system. */ #define MIN_REND_POST_PERIOD (10*60) @@ -3175,17 +2903,68 @@ compute_publishserverdescriptor(or_options_t *options) * */ #define RECOMMENDED_MIN_CIRCUIT_BUILD_TIMEOUT (10) -static int -options_validate_cb(void *old_options, void *options, void *default_options, - int from_setconf, char **msg) +/** + * Validate <b>new_options</b>. If it is valid, and it is a reasonable + * replacement for <b>old_options</b>, replace the previous value of the + * global options, and return return SETOPT_OK. + * + * If it is not valid, then free <b>new_options</b>, set *<b>msg_out</b> to a + * newly allocated error message, and return an error code. + */ +static setopt_err_t +options_validate_and_set(const or_options_t *old_options, + or_options_t *new_options, + char **msg_out) { + setopt_err_t rv; + validation_status_t vs; + in_option_validation = 1; - int rv = options_validate(old_options, options, default_options, - from_setconf, msg); + vs = config_validate(get_options_mgr(), old_options, new_options, msg_out); + + if (vs == VSTAT_TRANSITION_ERR) { + rv = SETOPT_ERR_TRANSITION; + goto err; + } else if (vs < 0) { + rv = SETOPT_ERR_PARSE; + goto err; + } + in_option_validation = 0; + + if (set_options(new_options, msg_out)) { + rv = SETOPT_ERR_SETTING; + goto err; + } + + rv = SETOPT_OK; + new_options = NULL; /* prevent free */ + err: in_option_validation = 0; + tor_assert(new_options == NULL || rv != SETOPT_OK); + or_options_free(new_options); return rv; } +#ifdef TOR_UNIT_TESTS +/** + * Return 0 if every setting in <b>options</b> is reasonable, is a + * permissible transition from <b>old_options</b>, and none of the + * testing-only settings differ from <b>default_options</b> unless in + * testing mode. Else return -1. Should have no side effects, except for + * normalizing the contents of <b>options</b>. + * + * On error, tor_strdup an error explanation into *<b>msg</b>. + */ +int +options_validate(const or_options_t *old_options, or_options_t *options, + char **msg) +{ + validation_status_t vs; + vs = config_validate(get_options_mgr(), old_options, options, msg); + return vs < 0 ? -1 : 0; +} +#endif /* defined(TOR_UNIT_TESTS) */ + #define REJECT(arg) \ STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END #if defined(__GNUC__) && __GNUC__ <= 3 @@ -3206,7 +2985,7 @@ options_validate_cb(void *old_options, void *options, void *default_options, */ static int warn_if_option_path_is_relative(const char *option, - char *filepath) + const char *filepath) { if (filepath && path_is_relative(filepath)) { char *abs_path = make_path_absolute(filepath); @@ -3219,34 +2998,29 @@ warn_if_option_path_is_relative(const char *option, } /** Scan <b>options</b> for occurrences of relative file/directory - * path and log a warning whenever it is found. + * paths and log a warning whenever one is found. * * Return 1 if there were relative paths; 0 otherwise. */ static int -warn_about_relative_paths(or_options_t *options) +warn_about_relative_paths(const or_options_t *options) { tor_assert(options); int n = 0; + const config_mgr_t *mgr = get_options_mgr(); - n += warn_if_option_path_is_relative("CookieAuthFile", - options->CookieAuthFile); - n += warn_if_option_path_is_relative("ExtORPortCookieAuthFile", - options->ExtORPortCookieAuthFile); - n += warn_if_option_path_is_relative("DirPortFrontPage", - options->DirPortFrontPage); - n += warn_if_option_path_is_relative("V3BandwidthsFile", - options->V3BandwidthsFile); - n += warn_if_option_path_is_relative("ControlPortWriteToFile", - options->ControlPortWriteToFile); - n += warn_if_option_path_is_relative("GeoIPFile",options->GeoIPFile); - n += warn_if_option_path_is_relative("GeoIPv6File",options->GeoIPv6File); - n += warn_if_option_path_is_relative("Log",options->DebugLogFile); - n += warn_if_option_path_is_relative("AccelDir",options->AccelDir); - n += warn_if_option_path_is_relative("DataDirectory",options->DataDirectory); - n += warn_if_option_path_is_relative("PidFile",options->PidFile); - n += warn_if_option_path_is_relative("ClientOnionAuthDir", - options->ClientOnionAuthDir); + smartlist_t *vars = config_mgr_list_vars(mgr); + SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, cv) { + config_line_t *line; + if (cv->member.type != CONFIG_TYPE_FILENAME) + continue; + const char *name = cv->member.name; + line = config_get_assigned_option(mgr, options, name, 0); + if (line) + n += warn_if_option_path_is_relative(name, line->value); + config_free_lines(line); + } SMARTLIST_FOREACH_END(cv); + smartlist_free(vars); for (config_line_t *hs_line = options->RendConfigLines; hs_line; hs_line = hs_line->next) { @@ -3273,6 +3047,10 @@ options_validate_scheduler(or_options_t *options, char **msg) "can be used or set at least one value."); } /* Ok, we do have scheduler types, validate them. */ + if (options->SchedulerTypes_) { + SMARTLIST_FOREACH(options->SchedulerTypes_, int *, iptr, tor_free(iptr)); + smartlist_free(options->SchedulerTypes_); + } options->SchedulerTypes_ = smartlist_new(); SMARTLIST_FOREACH_BEGIN(options->Schedulers, const char *, type) { int *sched_type; @@ -3365,25 +3143,20 @@ options_validate_single_onion(or_options_t *options, char **msg) return 0; } -/** Return 0 if every setting in <b>options</b> is reasonable, is a - * permissible transition from <b>old_options</b>, and none of the - * testing-only settings differ from <b>default_options</b> unless in - * testing mode. Else return -1. Should have no side effects, except for - * normalizing the contents of <b>options</b>. - * - * On error, tor_strdup an error explanation into *<b>msg</b>. - * - * XXX - * If <b>from_setconf</b>, we were called by the controller, and our - * Log line should stay empty. If it's 0, then give us a default log - * if there are no logs defined. +/** + * Legacy validation/normalization callback for or_options_t. See + * legacy_validate_fn_t for more information. */ -STATIC int -options_validate(or_options_t *old_options, or_options_t *options, - or_options_t *default_options, int from_setconf, char **msg) +static int +options_validate_cb(const void *old_options_, void *options_, char **msg) { + if (old_options_) + CHECK_OPTIONS_MAGIC(old_options_); + CHECK_OPTIONS_MAGIC(options_); + const or_options_t *old_options = old_options_; + or_options_t *options = options_; + config_line_t *cl; - const char *uname = get_uname(); int n_ports=0; int world_writable_control_socket=0; @@ -3400,16 +3173,10 @@ options_validate(or_options_t *old_options, or_options_t *options, * 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; @@ -3424,56 +3191,16 @@ options_validate(or_options_t *old_options, or_options_t *options, "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)); - /* Special case on first boot if no Log options are given. */ - if (!options->Logs && !options->RunAsDaemon && !from_setconf) { - if (quiet_level == 0) - config_line_append(&options->Logs, "Log", "notice stdout"); - else if (quiet_level == 1) - config_line_append(&options->Logs, "Log", "warn stdout"); - } - /* 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) @@ -3552,65 +3279,8 @@ options_validate(or_options_t *old_options, or_options_t *options, "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 " @@ -3749,57 +3419,11 @@ options_validate(or_options_t *old_options, or_options_t *options, 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 ? @@ -3973,134 +3597,26 @@ options_validate(or_options_t *old_options, or_options_t *options, if (options->KeepalivePeriod < 1) REJECT("KeepalivePeriod option must be positive."); - if (ensure_bandwidth_cap(&options->BandwidthRate, + if (config_ensure_bandwidth_cap(&options->BandwidthRate, "BandwidthRate", msg) < 0) return -1; - if (ensure_bandwidth_cap(&options->BandwidthBurst, + if (config_ensure_bandwidth_cap(&options->BandwidthBurst, "BandwidthBurst", msg) < 0) return -1; - if (ensure_bandwidth_cap(&options->MaxAdvertisedBandwidth, - "MaxAdvertisedBandwidth", msg) < 0) - return -1; - if (ensure_bandwidth_cap(&options->RelayBandwidthRate, - "RelayBandwidthRate", msg) < 0) - return -1; - if (ensure_bandwidth_cap(&options->RelayBandwidthBurst, - "RelayBandwidthBurst", msg) < 0) - return -1; - if (ensure_bandwidth_cap(&options->PerConnBWRate, - "PerConnBWRate", msg) < 0) - return -1; - if (ensure_bandwidth_cap(&options->PerConnBWBurst, - "PerConnBWBurst", msg) < 0) - return -1; - if (ensure_bandwidth_cap(&options->AuthDirFastGuarantee, - "AuthDirFastGuarantee", msg) < 0) + + if (options_validate_relay_bandwidth(old_options, options, msg) < 0) return -1; - if (ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee, - "AuthDirGuardBWGuarantee", msg) < 0) + if (options_validate_dirauth_bandwidth(old_options, options, msg) < 0) return -1; - if (options->RelayBandwidthRate && !options->RelayBandwidthBurst) - options->RelayBandwidthBurst = options->RelayBandwidthRate; - if (options->RelayBandwidthBurst && !options->RelayBandwidthRate) - options->RelayBandwidthRate = options->RelayBandwidthBurst; - - if (server_mode(options)) { - const unsigned required_min_bw = - public_server_mode(options) ? - RELAY_REQUIRED_MIN_BANDWIDTH : BRIDGE_REQUIRED_MIN_BANDWIDTH; - const char * const optbridge = - public_server_mode(options) ? "" : "bridge "; - if (options->BandwidthRate < required_min_bw) { - tor_asprintf(msg, - "BandwidthRate is set to %d bytes/second. " - "For %sservers, it must be at least %u.", - (int)options->BandwidthRate, optbridge, - required_min_bw); - return -1; - } else if (options->MaxAdvertisedBandwidth < - required_min_bw/2) { - tor_asprintf(msg, - "MaxAdvertisedBandwidth is set to %d bytes/second. " - "For %sservers, it must be at least %u.", - (int)options->MaxAdvertisedBandwidth, optbridge, - required_min_bw/2); - return -1; - } - if (options->RelayBandwidthRate && - options->RelayBandwidthRate < required_min_bw) { - tor_asprintf(msg, - "RelayBandwidthRate is set to %d bytes/second. " - "For %sservers, it must be at least %u.", - (int)options->RelayBandwidthRate, optbridge, - required_min_bw); - return -1; - } - } - - if (options->RelayBandwidthRate > options->RelayBandwidthBurst) - REJECT("RelayBandwidthBurst must be at least equal " - "to RelayBandwidthRate."); - if (options->BandwidthRate > options->BandwidthBurst) REJECT("BandwidthBurst must be at least equal to BandwidthRate."); - /* if they set relaybandwidth* really high but left bandwidth* - * at the default, raise the defaults. */ - if (options->RelayBandwidthRate > options->BandwidthRate) - options->BandwidthRate = options->RelayBandwidthRate; - if (options->RelayBandwidthBurst > options->BandwidthBurst) - options->BandwidthBurst = options->RelayBandwidthBurst; - - if (accounting_parse_options(options, 1)<0) - REJECT("Failed to parse accounting options. See logs for details."); - - if (options->AccountingMax) { - if (options->RendConfigLines && server_mode(options)) { - log_warn(LD_CONFIG, "Using accounting with a hidden service and an " - "ORPort is risky: your hidden service(s) and your public " - "address will all turn off at the same time, which may alert " - "observers that they are being run by the same party."); - } else if (config_count_key(options->RendConfigLines, - "HiddenServiceDir") > 1) { - log_warn(LD_CONFIG, "Using accounting with multiple hidden services is " - "risky: they will all turn off at the same time, which may " - "alert observers that they are being run by the same party."); - } - } - - options->AccountingRule = ACCT_MAX; - if (options->AccountingRule_option) { - if (!strcmp(options->AccountingRule_option, "sum")) - options->AccountingRule = ACCT_SUM; - else if (!strcmp(options->AccountingRule_option, "max")) - options->AccountingRule = ACCT_MAX; - else if (!strcmp(options->AccountingRule_option, "in")) - options->AccountingRule = ACCT_IN; - else if (!strcmp(options->AccountingRule_option, "out")) - options->AccountingRule = ACCT_OUT; - else - REJECT("AccountingRule must be 'sum', 'max', 'in', or 'out'"); - } - - if (options->DirPort_set && !options->DirCache) { - REJECT("DirPort configured but DirCache disabled. DirPort requires " - "DirCache."); - } - - if (options->BridgeRelay && !options->DirCache) { - REJECT("We're a bridge but DirCache is disabled. BridgeRelay requires " - "DirCache."); - } + if (options_validate_relay_accounting(old_options, options, msg) < 0) + return -1; - if (server_mode(options)) { - char *dircache_msg = NULL; - if (have_enough_mem_for_dircache(options, 0, &dircache_msg)) { - log_warn(LD_CONFIG, "%s", dircache_msg); - tor_free(dircache_msg); - } - } + if (options_validate_relay_mode(old_options, options, msg) < 0) + return -1; if (options->HTTPProxy) { /* parse it now */ if (tor_addr_port_lookup(options->HTTPProxy, @@ -4230,19 +3746,6 @@ options_validate(or_options_t *old_options, or_options_t *options, "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)) { @@ -4277,50 +3780,12 @@ options_validate(or_options_t *old_options, or_options_t *options, } 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 @@ -4334,85 +3799,10 @@ options_validate(or_options_t *old_options, or_options_t *options, 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."); @@ -4440,82 +3830,52 @@ options_validate(or_options_t *old_options, or_options_t *options, #define CHECK_DEFAULT(arg) \ STMT_BEGIN \ - if (!options->TestingTorNetwork && \ - !options->UsingTestNetworkDefaults_ && \ - !config_is_same(get_options_mgr(),options, \ - default_options,#arg)) { \ + if (!config_is_same(get_options_mgr(),options, \ + dflt_options,#arg)) { \ + or_options_free(dflt_options); \ REJECT(#arg " may only be changed in testing Tor " \ "networks!"); \ - } STMT_END - CHECK_DEFAULT(TestingV3AuthInitialVotingInterval); - CHECK_DEFAULT(TestingV3AuthInitialVoteDelay); - CHECK_DEFAULT(TestingV3AuthInitialDistDelay); - CHECK_DEFAULT(TestingV3AuthVotingStartOffset); - CHECK_DEFAULT(TestingAuthDirTimeToLearnReachability); - CHECK_DEFAULT(TestingEstimatedDescriptorPropagationTime); - CHECK_DEFAULT(TestingServerDownloadInitialDelay); - CHECK_DEFAULT(TestingClientDownloadInitialDelay); - CHECK_DEFAULT(TestingServerConsensusDownloadInitialDelay); - CHECK_DEFAULT(TestingClientConsensusDownloadInitialDelay); - CHECK_DEFAULT(TestingBridgeDownloadInitialDelay); - CHECK_DEFAULT(TestingBridgeBootstrapDownloadInitialDelay); - CHECK_DEFAULT(TestingClientMaxIntervalWithoutRequest); - CHECK_DEFAULT(TestingDirConnectionMaxStall); - CHECK_DEFAULT(TestingAuthKeyLifetime); - CHECK_DEFAULT(TestingLinkCertLifetime); - CHECK_DEFAULT(TestingSigningKeySlop); - CHECK_DEFAULT(TestingAuthKeySlop); - CHECK_DEFAULT(TestingLinkKeySlop); + } \ + STMT_END + + /* Check for options that can only be changed from the defaults in testing + networks. */ + 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); + CHECK_DEFAULT(TestingV3AuthVotingStartOffset); + CHECK_DEFAULT(TestingAuthDirTimeToLearnReachability); + CHECK_DEFAULT(TestingEstimatedDescriptorPropagationTime); + CHECK_DEFAULT(TestingServerDownloadInitialDelay); + CHECK_DEFAULT(TestingClientDownloadInitialDelay); + CHECK_DEFAULT(TestingServerConsensusDownloadInitialDelay); + CHECK_DEFAULT(TestingClientConsensusDownloadInitialDelay); + CHECK_DEFAULT(TestingBridgeDownloadInitialDelay); + CHECK_DEFAULT(TestingBridgeBootstrapDownloadInitialDelay); + CHECK_DEFAULT(TestingClientMaxIntervalWithoutRequest); + CHECK_DEFAULT(TestingDirConnectionMaxStall); + CHECK_DEFAULT(TestingAuthKeyLifetime); + CHECK_DEFAULT(TestingLinkCertLifetime); + CHECK_DEFAULT(TestingSigningKeySlop); + CHECK_DEFAULT(TestingAuthKeySlop); + CHECK_DEFAULT(TestingLinkKeySlop); + or_options_free(dflt_options); + } #undef CHECK_DEFAULT if (!options->ClientDNSRejectInternalAddresses && !(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."); @@ -4568,22 +3928,6 @@ options_validate(or_options_t *old_options, or_options_t *options, 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; } @@ -4675,50 +4019,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 @@ -4727,13 +4027,19 @@ opt_streq(const char *s1, const char *s2) return 0 == strcmp_opt(s1, s2); } -/** Check if any of the previous options have changed but aren't allowed to. */ +/** Check if any config options have changed but aren't allowed to. */ static int -options_transition_allowed(const or_options_t *old, - const or_options_t *new_val, - char **msg) +options_check_transition_cb(const void *old_, + const void *new_val_, + char **msg) { - if (!old) + CHECK_OPTIONS_MAGIC(old_); + CHECK_OPTIONS_MAGIC(new_val_); + + const or_options_t *old = old_; + const or_options_t *new_val = new_val_; + + if (BUG(!old)) return 0; #define BAD_CHANGE_TO(opt, how) do { \ @@ -4742,36 +4048,6 @@ options_transition_allowed(const or_options_t *old, return -1; \ } while (0) -#define NO_CHANGE_BOOL(opt) \ - if (! CFG_EQ_BOOL(old, new_val, opt)) BAD_CHANGE_TO(opt,"") -#define NO_CHANGE_INT(opt) \ - if (! CFG_EQ_INT(old, new_val, opt)) BAD_CHANGE_TO(opt,"") -#define NO_CHANGE_STRING(opt) \ - if (! CFG_EQ_STRING(old, new_val, opt)) BAD_CHANGE_TO(opt,"") - - NO_CHANGE_STRING(PidFile); - NO_CHANGE_BOOL(RunAsDaemon); - NO_CHANGE_BOOL(Sandbox); - NO_CHANGE_STRING(DataDirectory); - NO_CHANGE_STRING(KeyDirectory); - NO_CHANGE_STRING(CacheDirectory); - NO_CHANGE_STRING(User); - NO_CHANGE_BOOL(KeepBindCapabilities); - NO_CHANGE_STRING(SyslogIdentityTag); - NO_CHANGE_STRING(AndroidIdentityTag); - NO_CHANGE_BOOL(HardwareAccel); - NO_CHANGE_STRING(AccelName); - NO_CHANGE_STRING(AccelDir); - NO_CHANGE_BOOL(TestingTorNetwork); - NO_CHANGE_BOOL(DisableAllSwap); - NO_CHANGE_INT(TokenBucketRefillInterval); - NO_CHANGE_BOOL(HiddenServiceSingleHopMode); - NO_CHANGE_BOOL(HiddenServiceNonAnonymousMode); - NO_CHANGE_BOOL(DisableDebuggerAttachment); - NO_CHANGE_BOOL(NoExec); - NO_CHANGE_INT(OwningControllerFD); - NO_CHANGE_BOOL(DisableSignalHandlers); - if (sandbox_is_active()) { #define SB_NOCHANGE_STR(opt) \ if (! CFG_EQ_STRING(old, new_val, opt)) \ @@ -4808,71 +4084,6 @@ options_transition_allowed(const or_options_t *old, return 0; } -/** Return 1 if any change from <b>old_options</b> to <b>new_options</b> - * will require us to rotate the CPU and DNS workers; else return 0. */ -static int -options_transition_affects_workers(const or_options_t *old_options, - const or_options_t *new_options) -{ - YES_IF_CHANGED_STRING(DataDirectory); - YES_IF_CHANGED_INT(NumCPUs); - YES_IF_CHANGED_LINELIST(ORPort_lines); - YES_IF_CHANGED_BOOL(ServerDNSSearchDomains); - YES_IF_CHANGED_BOOL(SafeLogging_); - YES_IF_CHANGED_BOOL(ClientOnly); - YES_IF_CHANGED_BOOL(LogMessageDomains); - YES_IF_CHANGED_LINELIST(Logs); - - if (server_mode(old_options) != server_mode(new_options) || - public_server_mode(old_options) != public_server_mode(new_options) || - dir_server_mode(old_options) != dir_server_mode(new_options)) - return 1; - - /* Nothing that changed matters. */ - return 0; -} - -/** Return 1 if any change from <b>old_options</b> to <b>new_options</b> - * will require us to generate a new descriptor; else return 0. */ -static int -options_transition_affects_descriptor(const or_options_t *old_options, - const or_options_t *new_options) -{ - /* XXX We can be smarter here. If your DirPort isn't being - * published and you just turned it off, no need to republish. Etc. */ - - YES_IF_CHANGED_STRING(DataDirectory); - YES_IF_CHANGED_STRING(Nickname); - YES_IF_CHANGED_STRING(Address); - YES_IF_CHANGED_LINELIST(ExitPolicy); - YES_IF_CHANGED_BOOL(ExitRelay); - YES_IF_CHANGED_BOOL(ExitPolicyRejectPrivate); - YES_IF_CHANGED_BOOL(ExitPolicyRejectLocalInterfaces); - YES_IF_CHANGED_BOOL(IPv6Exit); - YES_IF_CHANGED_LINELIST(ORPort_lines); - YES_IF_CHANGED_LINELIST(DirPort_lines); - YES_IF_CHANGED_LINELIST(DirPort_lines); - YES_IF_CHANGED_BOOL(ClientOnly); - YES_IF_CHANGED_BOOL(DisableNetwork); - YES_IF_CHANGED_BOOL(PublishServerDescriptor_); - YES_IF_CHANGED_STRING(ContactInfo); - YES_IF_CHANGED_STRING(BridgeDistribution); - YES_IF_CHANGED_LINELIST(MyFamily); - YES_IF_CHANGED_STRING(AccountingStart); - YES_IF_CHANGED_INT(AccountingMax); - YES_IF_CHANGED_INT(AccountingRule); - YES_IF_CHANGED_BOOL(DirCache); - YES_IF_CHANGED_BOOL(AssumeReachable); - - if (get_effective_bwrate(old_options) != get_effective_bwrate(new_options) || - get_effective_bwburst(old_options) != - get_effective_bwburst(new_options) || - public_server_mode(old_options) != public_server_mode(new_options)) - return 1; - - return 0; -} - #ifdef _WIN32 /** Return the directory on windows where we expect to find our application * data. */ @@ -4957,85 +4168,6 @@ get_default_conf_file(int defaults_file) #endif /* defined(DISABLE_SYSTEM_TORRC) || ... */ } -/** Verify whether lst is a list of strings containing valid-looking - * comma-separated nicknames, or NULL. Will normalise <b>lst</b> to prefix '$' - * to any nickname or fingerprint that needs it. Also splits comma-separated - * list elements into multiple elements. Return 0 on success. - * Warn and return -1 on failure. - */ -static int -normalize_nickname_list(config_line_t **normalized_out, - const config_line_t *lst, const char *name, - char **msg) -{ - if (!lst) - return 0; - - config_line_t *new_nicknames = NULL; - config_line_t **new_nicknames_next = &new_nicknames; - - const config_line_t *cl; - for (cl = lst; cl; cl = cl->next) { - const char *line = cl->value; - if (!line) - continue; - - int valid_line = 1; - smartlist_t *sl = smartlist_new(); - smartlist_split_string(sl, line, ",", - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0); - SMARTLIST_FOREACH_BEGIN(sl, char *, s) - { - char *normalized = NULL; - if (!is_legal_nickname_or_hexdigest(s)) { - // check if first char is dollar - if (s[0] != '$') { - // Try again but with a dollar symbol prepended - char *prepended; - tor_asprintf(&prepended, "$%s", s); - - if (is_legal_nickname_or_hexdigest(prepended)) { - // The nickname is valid when it's prepended, set it as the - // normalized version - normalized = prepended; - } else { - // Still not valid, free and fallback to error message - tor_free(prepended); - } - } - - if (!normalized) { - tor_asprintf(msg, "Invalid nickname '%s' in %s line", s, name); - valid_line = 0; - break; - } - } else { - normalized = tor_strdup(s); - } - - config_line_t *next = tor_malloc_zero(sizeof(*next)); - next->key = tor_strdup(cl->key); - next->value = normalized; - next->next = NULL; - - *new_nicknames_next = next; - new_nicknames_next = &next->next; - } SMARTLIST_FOREACH_END(s); - - SMARTLIST_FOREACH(sl, char *, s, tor_free(s)); - smartlist_free(sl); - - if (!valid_line) { - config_free_lines(new_nicknames); - return -1; - } - } - - *normalized_out = new_nicknames; - - return 0; -} - /** Learn config file name from command line arguments, or use the default. * * If <b>defaults_file</b> is true, we're looking for torrc-defaults; @@ -5048,12 +4180,12 @@ normalize_nickname_list(config_line_t **normalized_out, * filename if it doesn't exist. */ static char * -find_torrc_filename(config_line_t *cmd_arg, +find_torrc_filename(const config_line_t *cmd_arg, int defaults_file, int *using_default_fname, int *ignore_missing_torrc) { char *fname=NULL; - config_line_t *p_index; + const config_line_t *p_index; const char *fname_opt = defaults_file ? "--defaults-torrc" : "-f"; const char *ignore_opt = defaults_file ? NULL : "--ignore-missing-torrc"; @@ -5132,7 +4264,7 @@ load_torrc_from_stdin(void) * Return the contents of the file on success, and NULL on failure. */ static char * -load_torrc_from_disk(config_line_t *cmd_arg, int defaults_file) +load_torrc_from_disk(const config_line_t *cmd_arg, int defaults_file) { char *fname=NULL; char *cf = NULL; @@ -5187,24 +4319,20 @@ int options_init_from_torrc(int argc, char **argv) { char *cf=NULL, *cf_defaults=NULL; - int command; int retval = -1; - char *command_arg = NULL; char *errmsg=NULL; - config_line_t *p_index = NULL; - config_line_t *cmdline_only_options = NULL; + const config_line_t *cmdline_only_options; /* Go through command-line variables */ - if (! have_parsed_cmdline) { + if (global_cmdline == NULL) { /* Or we could redo the list every time we pass this place. * It does not really matter */ - if (config_parse_commandline(argc, argv, 0, &global_cmdline_options, - &global_cmdline_only_options) < 0) { + global_cmdline = config_parse_commandline(argc, argv, 0); + if (global_cmdline == NULL) { goto err; } - have_parsed_cmdline = 1; } - cmdline_only_options = global_cmdline_only_options; + cmdline_only_options = global_cmdline->cmdline_opts; if (config_line_find(cmdline_only_options, "-h") || config_line_find(cmdline_only_options, "--help")) { @@ -5267,25 +4395,10 @@ options_init_from_torrc(int argc, char **argv) return 1; } - command = CMD_RUN_TOR; - for (p_index = cmdline_only_options; p_index; p_index = p_index->next) { - if (!strcmp(p_index->key,"--keygen")) { - command = CMD_KEYGEN; - } else if (!strcmp(p_index->key, "--key-expiration")) { - command = CMD_KEY_EXPIRATION; - command_arg = p_index->value; - } else if (!strcmp(p_index->key,"--list-fingerprint")) { - command = CMD_LIST_FINGERPRINT; - } else if (!strcmp(p_index->key, "--hash-password")) { - command = CMD_HASH_PASSWORD; - command_arg = p_index->value; - } else if (!strcmp(p_index->key, "--dump-config")) { - command = CMD_DUMP_CONFIG; - command_arg = p_index->value; - } else if (!strcmp(p_index->key, "--verify-config")) { - command = CMD_VERIFY_CONFIG; - } - } + int command = global_cmdline->command; + const char *command_arg = global_cmdline->command_arg; + /* "immediate" has already been handled by this point. */ + tor_assert(command != CMD_IMMEDIATE); if (command == CMD_HASH_PASSWORD) { cf_defaults = tor_strdup(""); @@ -5453,8 +4566,15 @@ options_init_from_string(const char *cf_defaults, const char *cf, } /* Go through command-line variables too */ - retval = config_assign(get_options_mgr(), newoptions, - global_cmdline_options, CAL_WARN_DEPRECATIONS, msg); + { + config_line_t *other_opts = NULL; + if (global_cmdline) { + other_opts = global_cmdline->other_opts; + } + retval = config_assign(get_options_mgr(), newoptions, + other_opts, + CAL_WARN_DEPRECATIONS, msg); + } if (retval < 0) { err = SETOPT_ERR_PARSE; goto err; @@ -5473,26 +4593,12 @@ options_init_from_string(const char *cf_defaults, const char *cf, } newoptions->IncludeUsed = cf_has_include; - in_option_validation = 1; newoptions->FilesOpenedByIncludes = opened_files; + opened_files = NULL; // prevent double-free. - /* Validate newoptions */ - if (options_validate(oldoptions, newoptions, newdefaultoptions, - 0, msg) < 0) { - err = SETOPT_ERR_PARSE; /*XXX make this a separate return value.*/ + err = options_validate_and_set(oldoptions, newoptions, msg); + if (err < 0) goto err; - } - - if (options_transition_allowed(oldoptions, newoptions, msg) < 0) { - err = SETOPT_ERR_TRANSITION; - goto err; - } - in_option_validation = 0; - - if (set_options(newoptions, msg)) { - err = SETOPT_ERR_SETTING; - goto err; /* frees and replaces old options */ - } or_options_free(global_default_options); global_default_options = newdefaultoptions; @@ -5505,9 +4611,6 @@ options_init_from_string(const char *cf_defaults, const char *cf, SMARTLIST_FOREACH(opened_files, char *, f, tor_free(f)); smartlist_free(opened_files); } - // may have been set to opened_files, avoid double free - newoptions->FilesOpenedByIncludes = NULL; - or_options_free(newoptions); or_options_free(newdefaultoptions); if (*msg) { char *old_msg = *msg; @@ -5641,22 +4744,14 @@ open_and_add_file_log(const log_severity_list_t *severity, } /** - * Initialize the logs based on the configuration file. - */ + * Try to set our global log granularity from `options->LogGranularity`, + * adjusting it as needed so that we are an even divisor of a second, or an + * even multiple of seconds. Return 0 on success, -1 on failure. + **/ static int -options_init_logs(const or_options_t *old_options, or_options_t *options, - int validate_only) +options_init_log_granularity(const or_options_t *options, + int validate_only) { - config_line_t *opt; - int ok; - smartlist_t *elts; - int run_as_daemon = -#ifdef _WIN32 - 0; -#else - options->RunAsDaemon; -#endif - if (options->LogTimeGranularity <= 0) { log_warn(LD_CONFIG, "Log time granularity '%d' has to be positive.", options->LogTimeGranularity); @@ -5686,9 +4781,38 @@ options_init_logs(const or_options_t *old_options, or_options_t *options, set_log_time_granularity(options->LogTimeGranularity); } + return 0; +} + +/** + * Initialize the logs based on the configuration file. + */ +STATIC int +options_init_logs(const or_options_t *old_options, or_options_t *options, + int validate_only) +{ + config_line_t *opt; + int ok; + smartlist_t *elts; + int run_as_daemon = +#ifdef _WIN32 + 0; +#else + options->RunAsDaemon; +#endif + + if (options_init_log_granularity(options, validate_only) < 0) + return -1; + ok = 1; elts = smartlist_new(); + if (options->Logs == NULL && !run_as_daemon && !validate_only) { + /* When no logs are given, the default behavior is to log nothing (if + RunAsDaemon is set) or to log based on the quiet level otherwise. */ + add_default_log_for_quiet_level(quiet_level); + } + for (opt = options->Logs; opt; opt = opt->next) { log_severity_list_t *severity; const char *cfg = opt->value; @@ -5972,9 +5096,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) { @@ -6167,157 +5290,6 @@ parse_transport_line(const or_options_t *options, return r; } -/** Given a ServerTransportListenAddr <b>line</b>, return its - * <address:port> string. Return NULL if the line was not - * well-formed. - * - * If <b>transport</b> is set, return NULL if the line is not - * referring to <b>transport</b>. - * - * The returned string is allocated on the heap and it's the - * responsibility of the caller to free it. */ -static char * -get_bindaddr_from_transport_listen_line(const char *line,const char *transport) -{ - smartlist_t *items = NULL; - const char *parsed_transport = NULL; - char *addrport = NULL; - tor_addr_t addr; - uint16_t port = 0; - - items = smartlist_new(); - smartlist_split_string(items, line, NULL, - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); - - if (smartlist_len(items) < 2) { - log_warn(LD_CONFIG,"Too few arguments on ServerTransportListenAddr line."); - goto err; - } - - parsed_transport = smartlist_get(items, 0); - addrport = tor_strdup(smartlist_get(items, 1)); - - /* If 'transport' is given, check if it matches the one on the line */ - if (transport && strcmp(transport, parsed_transport)) - goto err; - - /* Validate addrport */ - if (tor_addr_port_parse(LOG_WARN, addrport, &addr, &port, -1)<0) { - log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr " - "address '%s'", addrport); - goto err; - } - - goto done; - - err: - tor_free(addrport); - addrport = NULL; - - done: - SMARTLIST_FOREACH(items, char*, s, tor_free(s)); - smartlist_free(items); - - return addrport; -} - -/** Given a ServerTransportOptions <b>line</b>, return a smartlist - * with the options. Return NULL if the line was not well-formed. - * - * If <b>transport</b> is set, return NULL if the line is not - * referring to <b>transport</b>. - * - * The returned smartlist and its strings are allocated on the heap - * and it's the responsibility of the caller to free it. */ -smartlist_t * -get_options_from_transport_options_line(const char *line,const char *transport) -{ - smartlist_t *items = smartlist_new(); - smartlist_t *options = smartlist_new(); - const char *parsed_transport = NULL; - - smartlist_split_string(items, line, NULL, - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); - - if (smartlist_len(items) < 2) { - log_warn(LD_CONFIG,"Too few arguments on ServerTransportOptions line."); - goto err; - } - - parsed_transport = smartlist_get(items, 0); - /* If 'transport' is given, check if it matches the one on the line */ - if (transport && strcmp(transport, parsed_transport)) - goto err; - - SMARTLIST_FOREACH_BEGIN(items, const char *, option) { - if (option_sl_idx == 0) /* skip the transport field (first field)*/ - continue; - - /* validate that it's a k=v value */ - if (!string_is_key_value(LOG_WARN, option)) { - log_warn(LD_CONFIG, "%s is not a k=v value.", escaped(option)); - goto err; - } - - /* add it to the options smartlist */ - smartlist_add_strdup(options, option); - log_debug(LD_CONFIG, "Added %s to the list of options", escaped(option)); - } SMARTLIST_FOREACH_END(option); - - goto done; - - err: - SMARTLIST_FOREACH(options, char*, s, tor_free(s)); - smartlist_free(options); - options = NULL; - - done: - SMARTLIST_FOREACH(items, char*, s, tor_free(s)); - smartlist_free(items); - - return options; -} - -/** Given the name of a pluggable transport in <b>transport</b>, check - * the configuration file to see if the user has explicitly asked for - * it to listen on a specific port. Return a <address:port> string if - * so, otherwise NULL. */ -char * -get_transport_bindaddr_from_config(const char *transport) -{ - config_line_t *cl; - const or_options_t *options = get_options(); - - for (cl = options->ServerTransportListenAddr; cl; cl = cl->next) { - char *bindaddr = - get_bindaddr_from_transport_listen_line(cl->value, transport); - if (bindaddr) - return bindaddr; - } - - return NULL; -} - -/** Given the name of a pluggable transport in <b>transport</b>, check - * the configuration file to see if the user has asked us to pass any - * parameters to the pluggable transport. Return a smartlist - * containing the parameters, otherwise NULL. */ -smartlist_t * -get_options_for_server_transport(const char *transport) -{ - config_line_t *cl; - const or_options_t *options = get_options(); - - for (cl = options->ServerTransportOptions; cl; cl = cl->next) { - smartlist_t *options_sl = - get_options_from_transport_options_line(cl->value, transport); - if (options_sl) - return options_sl; - } - - return NULL; -} - /** Read the contents of a DirAuthority line from <b>line</b>. If * <b>validate_only</b> is 0, and the line is well-formed, and it * shares any bits with <b>required_type</b> or <b>required_type</b> @@ -6589,7 +5561,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); @@ -6603,7 +5575,7 @@ port_cfg_new(size_t namelen) } /** Free all storage held in <b>port</b> */ -STATIC void +void port_cfg_free_(port_cfg_t *port) { tor_free(port); @@ -6637,27 +5609,6 @@ warn_nonlocal_client_ports(const smartlist_t *ports, } SMARTLIST_FOREACH_END(port); } -/** Warn for every Extended ORPort port in <b>ports</b> that is on a - * publicly routable address. */ -static void -warn_nonlocal_ext_orports(const smartlist_t *ports, const char *portname) -{ - SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) { - if (port->type != CONN_TYPE_EXT_OR_LISTENER) - continue; - if (port->is_unix_addr) - continue; - /* XXX maybe warn even if address is RFC1918? */ - if (!tor_addr_is_internal(&port->addr, 1)) { - log_warn(LD_CONFIG, "You specified a public address '%s' for %sPort. " - "This is not advised; this address is supposed to only be " - "exposed on localhost so that your pluggable transport " - "proxies can connect to it.", - fmt_addrport(&port->addr, port->port), portname); - } - } SMARTLIST_FOREACH_END(port); -} - /** Given a list of port_cfg_t in <b>ports</b>, warn if any controller port * there is listening on any non-loopback address. If <b>forbid_nonlocal</b> * is true, then emit a stronger warning and remove the port from the list. @@ -6771,55 +5722,6 @@ warn_client_dns_cache(const char *option, int disabling) } /** - * Validate the configured bridge distribution method from a BridgeDistribution - * config line. - * - * The input <b>bd</b>, is a string taken from the BridgeDistribution config - * line (if present). If the option wasn't set, return 0 immediately. The - * BridgeDistribution option is then validated. Currently valid, recognised - * options are: - * - * - "none" - * - "any" - * - "https" - * - "email" - * - "moat" - * - "hyphae" - * - * If the option string is unrecognised, a warning will be logged and 0 is - * returned. If the option string contains an invalid character, -1 is - * returned. - **/ -STATIC int -check_bridge_distribution_setting(const char *bd) -{ - if (bd == NULL) - return 0; - - const char *RECOGNIZED[] = { - "none", "any", "https", "email", "moat", "hyphae" - }; - unsigned i; - for (i = 0; i < ARRAY_LENGTH(RECOGNIZED); ++i) { - if (!strcmp(bd, RECOGNIZED[i])) - return 0; - } - - const char *cp = bd; - // Method = (KeywordChar | "_") + - while (TOR_ISALNUM(*cp) || *cp == '-' || *cp == '_') - ++cp; - - if (*cp == 0) { - log_warn(LD_CONFIG, "Unrecognized BridgeDistribution value %s. I'll " - "assume you know what you are doing...", escaped(bd)); - return 0; // we reached the end of the string; all is well - } else { - return -1; // we found a bad character in the string. - } -} - -/** * Parse port configuration for a single port type. * * Read entries of the "FooPort" type from the list <b>ports</b>. Syntax is @@ -6849,8 +5751,8 @@ check_bridge_distribution_setting(const char *bd) * <b>out</b> for every port that the client should listen on. Return 0 * on success, -1 on failure. */ -STATIC int -parse_port_config(smartlist_t *out, +int +port_parse_config(smartlist_t *out, const config_line_t *ports, const char *portname, int listener_type, @@ -7283,7 +6185,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); } @@ -7307,8 +6209,8 @@ parse_port_config(smartlist_t *out, /** Return the number of ports which are actually going to listen with type * <b>listenertype</b>. Do not count no_listen ports. Only count unix * sockets if count_sockets is true. */ -static int -count_real_listeners(const smartlist_t *ports, int listenertype, +int +port_count_real_listeners(const smartlist_t *ports, int listenertype, int count_sockets) { int n = 0; @@ -7346,7 +6248,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, @@ -7355,7 +6257,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, @@ -7363,7 +6265,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, @@ -7371,7 +6273,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, @@ -7379,7 +6281,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, @@ -7399,7 +6301,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, @@ -7408,7 +6310,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) { @@ -7416,40 +6318,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); @@ -7457,25 +6328,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, @@ -7506,7 +6372,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 || @@ -7515,7 +6381,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 || @@ -7523,94 +6389,6 @@ port_binds_ipv6(const port_cfg_t *port) && !port->server_cfg.bind_ipv4_only); } -/** Given a list of <b>port_cfg_t</b> in <b>ports</b>, check them for internal - * consistency and warn as appropriate. Set *<b>n_low_ports_out</b> to the - * number of sub-1024 ports we will be binding. */ -static int -check_server_ports(const smartlist_t *ports, - const or_options_t *options, - int *n_low_ports_out) -{ - int n_orport_advertised = 0; - int n_orport_advertised_ipv4 = 0; - int n_orport_listeners = 0; - int n_dirport_advertised = 0; - int n_dirport_listeners = 0; - int n_low_port = 0; - int r = 0; - - SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) { - if (port->type == CONN_TYPE_DIR_LISTENER) { - if (! port->server_cfg.no_advertise) - ++n_dirport_advertised; - if (! port->server_cfg.no_listen) - ++n_dirport_listeners; - } else if (port->type == CONN_TYPE_OR_LISTENER) { - if (! port->server_cfg.no_advertise) { - ++n_orport_advertised; - if (port_binds_ipv4(port)) - ++n_orport_advertised_ipv4; - } - if (! port->server_cfg.no_listen) - ++n_orport_listeners; - } else { - continue; - } -#ifndef _WIN32 - if (!port->server_cfg.no_listen && port->port < 1024) - ++n_low_port; -#endif - } SMARTLIST_FOREACH_END(port); - - if (n_orport_advertised && !n_orport_listeners) { - log_warn(LD_CONFIG, "We are advertising an ORPort, but not actually " - "listening on one."); - r = -1; - } - if (n_orport_listeners && !n_orport_advertised) { - log_warn(LD_CONFIG, "We are listening on an ORPort, but not advertising " - "any ORPorts. This will keep us from building a %s " - "descriptor, and make us impossible to use.", - options->BridgeRelay ? "bridge" : "router"); - r = -1; - } - if (n_dirport_advertised && !n_dirport_listeners) { - log_warn(LD_CONFIG, "We are advertising a DirPort, but not actually " - "listening on one."); - r = -1; - } - if (n_dirport_advertised > 1) { - log_warn(LD_CONFIG, "Can't advertise more than one DirPort."); - r = -1; - } - if (n_orport_advertised && !n_orport_advertised_ipv4 && - !options->BridgeRelay) { - log_warn(LD_CONFIG, "Configured public relay to listen only on an IPv6 " - "address. Tor needs to listen on an IPv4 address too."); - r = -1; - } - - if (n_low_port && options->AccountingMax && - (!have_capability_support() || options->KeepBindCapabilities == 0)) { - const char *extra = ""; - if (options->KeepBindCapabilities == 0 && have_capability_support()) - extra = ", and you have disabled KeepBindCapabilities."; - log_warn(LD_CONFIG, - "You have set AccountingMax to use hibernation. You have also " - "chosen a low DirPort or OrPort%s." - "This combination can make Tor stop " - "working when it tries to re-attach the port after a period of " - "hibernation. Please choose a different port or turn off " - "hibernation unless you know this combination will work on your " - "platform.", extra); - } - - if (n_low_ports_out) - *n_low_ports_out = n_low_port; - - return r; -} - /** Return a list of port_cfg_t for client ports parsed from the * options. */ MOCK_IMPL(const smartlist_t *, @@ -8089,43 +6867,6 @@ write_to_data_subdir(const char* subdir, const char* fname, return return_val; } -/** Return a smartlist of ports that must be forwarded by - * tor-fw-helper. The smartlist contains the ports in a string format - * that is understandable by tor-fw-helper. */ -smartlist_t * -get_list_of_ports_to_forward(void) -{ - smartlist_t *ports_to_forward = smartlist_new(); - int port = 0; - - /** XXX TODO tor-fw-helper does not support forwarding ports to - other hosts than the local one. If the user is binding to a - different IP address, tor-fw-helper won't work. */ - port = router_get_advertised_or_port(get_options()); /* Get ORPort */ - if (port) - smartlist_add_asprintf(ports_to_forward, "%d:%d", port, port); - - port = router_get_advertised_dir_port(get_options(), 0); /* Get DirPort */ - if (port) - smartlist_add_asprintf(ports_to_forward, "%d:%d", port, port); - - /* Get ports of transport proxies */ - { - smartlist_t *transport_ports = get_transport_proxy_ports(); - if (transport_ports) { - smartlist_add_all(ports_to_forward, transport_ports); - smartlist_free(transport_ports); - } - } - - if (!smartlist_len(ports_to_forward)) { - smartlist_free(ports_to_forward); - ports_to_forward = NULL; - } - - return ports_to_forward; -} - /** Helper to implement GETINFO functions about configuration variables (not * their values). Given a "config/names" question, set *<b>answer</b> to a * new string describing the supported configuration variables and their diff --git a/src/app/config/config.h b/src/app/config/config.h index 44f09e5ee9..eeba9e64d0 100644 --- a/src/app/config/config.h +++ b/src/app/config/config.h @@ -14,6 +14,7 @@ #include "app/config/or_options_st.h" #include "lib/testsupport/testsupport.h" +#include "app/config/quiet_level.h" #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(DARWIN) #define KERNEL_MAY_SUPPORT_IPFW @@ -30,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); @@ -162,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() \ @@ -180,26 +182,36 @@ 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); or_options_t *options_new(void); -int config_parse_commandline(int argc, char **argv, int ignore_errors, - struct config_line_t **result, - struct config_line_t **cmdline_result); +/** Options settings parsed from the command-line. */ +typedef struct { + /** List of options that can only be set from the command-line */ + struct config_line_t *cmdline_opts; + /** List of other options, to be handled by the general Tor configuration + system. */ + struct config_line_t *other_opts; + /** Subcommand that Tor has been told to run */ + tor_cmdline_mode_t command; + /** Argument for the command mode, if any. */ + const char *command_arg; + /** How quiet have we been told to be? */ + quiet_level_t quiet_level; +} parsed_cmdline_t; + +parsed_cmdline_t *config_parse_commandline(int argc, char **argv, + int ignore_errors); +void parsed_cmdline_free_(parsed_cmdline_t *cmdline); +#define parsed_cmdline_free(c) \ + FREE_AND_NULL(parsed_cmdline_t, parsed_cmdline_free_, (c)) void config_register_addressmaps(const or_options_t *options); /* XXXX move to connection_edge.h */ @@ -228,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) @@ -246,26 +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) -STATIC int options_act(const or_options_t *old_options); +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 options_validate(or_options_t *old_options, - or_options_t *options, - or_options_t *default_options, - int from_setconf, 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); @@ -274,23 +294,20 @@ 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); STATIC int open_and_add_file_log(const log_severity_list_t *severity, const char *fname, int truncate_log); +STATIC int options_init_logs(const or_options_t *old_options, + or_options_t *options, int validate_only); + +#ifdef TOR_UNIT_TESTS +int options_validate(const or_options_t *old_options, + or_options_t *options, + char **msg); +#endif #endif /* defined(CONFIG_PRIVATE) */ diff --git a/src/app/config/or_options_st.h b/src/app/config/or_options_st.h index 32dcd9fb18..1bbb2b97ec 100644 --- a/src/app/config/or_options_st.h +++ b/src/app/config/or_options_st.h @@ -15,6 +15,7 @@ #include "lib/cc/torint.h" #include "lib/net/address.h" +#include "app/config/tor_cmdline_mode.h" struct smartlist_t; struct config_line_t; @@ -31,12 +32,7 @@ struct or_options_t { uint32_t magic_; /** What should the tor process actually do? */ - enum { - CMD_RUN_TOR=0, CMD_LIST_FINGERPRINT, CMD_HASH_PASSWORD, - CMD_VERIFY_CONFIG, CMD_RUN_UNITTESTS, CMD_DUMP_CONFIG, - CMD_KEYGEN, - CMD_KEY_EXPIRATION, - } command; + tor_cmdline_mode_t command; char *command_arg; /**< Argument for command-line option. */ struct config_line_t *Logs; /**< New-style list of configuration lines @@ -854,7 +850,7 @@ struct or_options_t { * to make this false. */ int ReloadTorrcOnSIGHUP; - /* The main parameter for picking circuits within a connection. + /** The main parameter for picking circuits within a connection. * * If this value is positive, when picking a cell to relay on a connection, * we always relay from the circuit whose weighted cell count is lowest. @@ -1050,7 +1046,7 @@ struct or_options_t { /** The list of scheduler type string ordered by priority that is first one * has to be tried first. Default: KIST,KISTLite,Vanilla */ struct smartlist_t *Schedulers; - /* An ordered list of scheduler_types mapped from Schedulers. */ + /** An ordered list of scheduler_types mapped from Schedulers. */ struct smartlist_t *SchedulerTypes_; /** List of files that were opened by %include in torrc and torrc-defaults */ diff --git a/src/app/config/or_state_st.h b/src/app/config/or_state_st.h index 225003bb7e..27cc936c7d 100644 --- a/src/app/config/or_state_st.h +++ b/src/app/config/or_state_st.h @@ -5,7 +5,7 @@ /* See LICENSE for licensing information */ /** - * \file or_state_t + * \file or_state_st.h * * \brief The or_state_t structure, which represents Tor's state file. */ diff --git a/src/app/config/quiet_level.c b/src/app/config/quiet_level.c new file mode 100644 index 0000000000..84bc0149b8 --- /dev/null +++ b/src/app/config/quiet_level.c @@ -0,0 +1,38 @@ +/* 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 quiet_level.c + * @brief Code to handle default logging level (quiet/hush/normal). + **/ + +#include "orconfig.h" +#include "lib/log/log.h" +#include "app/config/quiet_level.h" + +/** Decides our behavior when no logs are configured/before any logs have been + * configured. For QUIET_NONE, we log notice to stdout as normal. For + * QUIET_HUSH, we log warnings only. For QUIET_SILENT, we log nothing. + */ +quiet_level_t quiet_level = 0; + +/** Add a default log (or not), depending on the value of <b>quiet</b>. */ +void +add_default_log_for_quiet_level(quiet_level_t quiet) +{ + switch (quiet) { + case QUIET_SILENT: + /* --quiet: no initial logging */ + return; + case QUIET_HUSH: + /* --hush: log at warning or higher. */ + add_default_log(LOG_WARN); + break; + case QUIET_NONE: /* fall through */ + default: + add_default_log(LOG_NOTICE); + } +} diff --git a/src/app/config/quiet_level.h b/src/app/config/quiet_level.h new file mode 100644 index 0000000000..03e3f58fb0 --- /dev/null +++ b/src/app/config/quiet_level.h @@ -0,0 +1,30 @@ +/* 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 quiet_level.h + * \brief Declare the quiet_level enumeration and global. + **/ + +#ifndef QUIET_LEVEL_H +#define QUIET_LEVEL_H + +/** Enumeration to define how quietly Tor should log at startup. */ +typedef enum { + /** Default quiet level: we log everything of level NOTICE or higher. */ + QUIET_NONE = 0, + /** "--hush" quiet level: we log everything of level WARNING or higher. */ + QUIET_HUSH = 1 , + /** "--quiet" quiet level: we log nothing at all. */ + QUIET_SILENT = 2 +} quiet_level_t; + +/** How quietly should Tor log at startup? */ +extern quiet_level_t quiet_level; + +void add_default_log_for_quiet_level(quiet_level_t quiet); + +#endif /* !defined(QUIET_LEVEL_H) */ diff --git a/src/app/config/statefile.c b/src/app/config/statefile.c index 552bd2c443..db4d780a78 100644 --- a/src/app/config/statefile.c +++ b/src/app/config/statefile.c @@ -12,7 +12,7 @@ * * This 'state' file is a typed key-value store that allows multiple * entries for the same key. It follows the same metaformat as described - * in confparse.c, and uses the same code to read and write itself. + * in confmgt.c, and uses the same code to read and write itself. * * The state file is most suitable for small values that don't change too * frequently. For values that become very large, we typically use a separate @@ -32,7 +32,8 @@ #include "core/or/or.h" #include "core/or/circuitstats.h" #include "app/config/config.h" -#include "lib/confmgt/confparse.h" +#include "feature/relay/transport_config.h" +#include "lib/confmgt/confmgt.h" #include "core/mainloop/mainloop.h" #include "core/mainloop/netstatus.h" #include "core/mainloop/connection.h" @@ -141,9 +142,8 @@ static const config_var_t state_vars_[] = { static int or_state_validate(or_state_t *state, char **msg); -static int or_state_validate_cb(void *old_options, void *options, - void *default_options, - int from_setconf, char **msg); +static int or_state_validate_cb(const void *old_options, + void *options, char **msg); /** Magic value for or_state_t. */ #define OR_STATE_MAGIC 0x57A73f57 @@ -158,19 +158,17 @@ static struct_member_t state_extra_var = { /** Configuration format for or_state_t. */ static const config_format_t state_format = { - sizeof(or_state_t), - { + .size = sizeof(or_state_t), + .magic = { "or_state_t", OR_STATE_MAGIC, offsetof(or_state_t, magic_), }, - state_abbrevs_, - NULL, - state_vars_, - or_state_validate_cb, - NULL, - &state_extra_var, - offsetof(or_state_t, substates_), + .abbrevs = state_abbrevs_, + .vars = state_vars_, + .legacy_validate_fn = or_state_validate_cb, + .extra = &state_extra_var, + .config_suite_offset = offsetof(or_state_t, substates_), }; /* A global configuration manager for state-file objects */ @@ -187,6 +185,10 @@ get_state_mgr(void) return state_mgr; } +#define CHECK_STATE_MAGIC(s) STMT_BEGIN \ + config_check_toplevel_magic(get_state_mgr(), (s)); \ + STMT_END + /** Persistent serialized state. */ static or_state_t *global_state = NULL; @@ -268,19 +270,6 @@ validate_transports_in_state(or_state_t *state) return 0; } -static int -or_state_validate_cb(void *old_state, void *state, void *default_state, - int from_setconf, char **msg) -{ - /* We don't use these; only options do. Still, we need to match that - * signature. */ - (void) from_setconf; - (void) default_state; - (void) old_state; - - return or_state_validate(state, msg); -} - /** Return 0 if every setting in <b>state</b> is reasonable, and a * permissible transition from <b>old_state</b>. Else warn and return -1. * Should have no side effects, except for normalizing the contents of @@ -289,6 +278,23 @@ or_state_validate_cb(void *old_state, void *state, void *default_state, static int or_state_validate(or_state_t *state, char **msg) { + return config_validate(get_state_mgr(), NULL, state, msg); +} + +/** + * Legacy validation/normalization callback for or_state_t. See + * legacy_validate_fn_t for more information. + */ +static int +or_state_validate_cb(const void *old_state, void *state_, char **msg) +{ + /* There is not a meaningful concept of a state-to-state transition, + * since we do not reload the state after we start. */ + (void) old_state; + CHECK_STATE_MAGIC(state_); + + or_state_t *state = state_; + if (entry_guards_parse_state(state, 0, msg)<0) return -1; @@ -633,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/config/tor_cmdline_mode.h b/src/app/config/tor_cmdline_mode.h new file mode 100644 index 0000000000..b2c43bbb87 --- /dev/null +++ b/src/app/config/tor_cmdline_mode.h @@ -0,0 +1,34 @@ +/* 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 tor_cmdline_mode.h + * \brief Declare the tor_cmdline_mode_t enumeration + **/ + +#ifndef TOR_CMDLINE_MODE_H +#define TOR_CMDLINE_MODE_H + +/** + * Enumeration to describe which command Tor is running. These commands + * are controlled by command-line options. + **/ +typedef enum { + CMD_RUN_TOR=0, /**< The default: run Tor as a daemon. */ + CMD_LIST_FINGERPRINT, /**< Running --list-fingerprint. */ + CMD_HASH_PASSWORD, /**< Running --hash-password. */ + CMD_VERIFY_CONFIG, /**< Running --verify-config. */ + CMD_DUMP_CONFIG, /**< Running --dump-config. */ + CMD_KEYGEN, /**< Running --keygen */ + CMD_KEY_EXPIRATION, /**< Running --key-expiration */ + CMD_IMMEDIATE, /**< Special value: indicates a command that is handled + * immediately during configuration processing. */ + CMD_RUN_UNITTESTS, /**< Special value: indicates that we have entered + * the Tor code from the unit tests, not from the + * regular Tor binary at all. */ +} tor_cmdline_mode_t; + +#endif /* !defined(TOR_CMDLINE_MODE_H) */ diff --git a/src/app/main/app_main.dox b/src/app/main/app_main.dox new file mode 100644 index 0000000000..c714ad1396 --- /dev/null +++ b/src/app/main/app_main.dox @@ -0,0 +1,4 @@ +/** +@dir /app/main +@brief app/main: Entry point for tor. +**/ diff --git a/src/app/main/main.c b/src/app/main/main.c index 3bdf8f146b..fad2e0b62f 100644 --- a/src/app/main/main.c +++ b/src/app/main/main.c @@ -13,6 +13,7 @@ #include "app/config/config.h" #include "app/config/statefile.h" +#include "app/config/quiet_level.h" #include "app/main/main.h" #include "app/main/ntmain.h" #include "app/main/shutdown.h" @@ -108,16 +109,6 @@ static void dumpmemusage(int severity); static void dumpstats(int severity); /* log stats */ static void process_signal(int sig); -/********* START VARIABLES **********/ - -/** Decides our behavior when no logs are configured/before any - * logs have been configured. For 0, we log notice to stdout as normal. - * For 1, we log warnings only. For 2, we log nothing. - */ -int quiet_level = 0; - -/********* END VARIABLES ************/ - /** Called when we get a SIGHUP: reload configuration files and keys, * retry all connections, and so on. */ static int @@ -528,7 +519,7 @@ int tor_init(int argc, char *argv[]) { char progname[256]; - int quiet = 0; + quiet_level_t quiet = QUIET_NONE; time_of_process_start = time(NULL); tor_init_connection_lists(); @@ -547,43 +538,17 @@ tor_init(int argc, char *argv[]) hs_init(); { - /* We search for the "quiet" option first, since it decides whether we - * will log anything at all to the command line. */ - config_line_t *opts = NULL, *cmdline_opts = NULL; - const config_line_t *cl; - (void) config_parse_commandline(argc, argv, 1, &opts, &cmdline_opts); - for (cl = cmdline_opts; cl; cl = cl->next) { - if (!strcmp(cl->key, "--hush")) - quiet = 1; - if (!strcmp(cl->key, "--quiet") || - !strcmp(cl->key, "--dump-config")) - quiet = 2; - /* The following options imply --hush */ - if (!strcmp(cl->key, "--version") || !strcmp(cl->key, "--digests") || - !strcmp(cl->key, "--list-torrc-options") || - !strcmp(cl->key, "--library-versions") || - !strcmp(cl->key, "--list-modules") || - !strcmp(cl->key, "--hash-password") || - !strcmp(cl->key, "-h") || !strcmp(cl->key, "--help")) { - if (quiet < 1) - quiet = 1; - } - } - config_free_lines(opts); - config_free_lines(cmdline_opts); + /* We check for the "quiet"/"hush" settings first, since they decide + whether we log anything at all to stdout. */ + parsed_cmdline_t *cmdline; + cmdline = config_parse_commandline(argc, argv, 1); + if (cmdline) + quiet = cmdline->quiet_level; + parsed_cmdline_free(cmdline); } /* give it somewhere to log to initially */ - switch (quiet) { - case 2: - /* no initial logging */ - break; - case 1: - add_temp_log(LOG_WARN); - break; - default: - add_temp_log(LOG_NOTICE); - } + add_default_log_for_quiet_level(quiet); quiet_level = quiet; { @@ -1347,7 +1312,7 @@ tor_run_main(const tor_main_configuration_t *tor_cfg) result = 0; break; case CMD_VERIFY_CONFIG: - if (quiet_level == 0) + if (quiet_level == QUIET_NONE) printf("Configuration was valid\n"); result = 0; break; @@ -1355,6 +1320,7 @@ tor_run_main(const tor_main_configuration_t *tor_cfg) result = do_dump_config(); break; case CMD_RUN_UNITTESTS: /* only set by test.c */ + case CMD_IMMEDIATE: /* Handled in config.c */ default: log_warn(LD_BUG,"Illegal command number %d: internal error.", get_options()->command); diff --git a/src/app/main/ntmain.c b/src/app/main/ntmain.c index a2de5bb87e..9351d96870 100644 --- a/src/app/main/ntmain.c +++ b/src/app/main/ntmain.c @@ -340,6 +340,7 @@ nt_service_main(void) "or --key-expiration) in NT service."); break; case CMD_RUN_UNITTESTS: + case CMD_IMMEDIATE: default: log_err(LD_CONFIG, "Illegal command number %d: internal error.", get_options()->command); 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/app/main/subsysmgr.c b/src/app/main/subsysmgr.c index 5aa4fd76c9..1f4bc840f2 100644 --- a/src/app/main/subsysmgr.c +++ b/src/app/main/subsysmgr.c @@ -3,6 +3,14 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file subsysmgr.c + * @brief Manager for Tor's subsystems. + * + * This code is responsible for initializing, configuring, and shutting + * down all of Tor's individual subsystems. + **/ + #include "orconfig.h" #include "app/main/subsysmgr.h" diff --git a/src/app/main/subsysmgr.h b/src/app/main/subsysmgr.h index d4426614e3..f8bc83e0ad 100644 --- a/src/app/main/subsysmgr.h +++ b/src/app/main/subsysmgr.h @@ -3,6 +3,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file subsysmgr.h + * @brief Header for subsysmgr.c + **/ + #ifndef TOR_SUBSYSMGR_T #define TOR_SUBSYSMGR_T diff --git a/src/app/main/subsystem_list.c b/src/app/main/subsystem_list.c index 1af9340c1a..4a40702e70 100644 --- a/src/app/main/subsystem_list.c +++ b/src/app/main/subsystem_list.c @@ -3,6 +3,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file subsystem_list.c + * @brief List of Tor's subsystems. + **/ + #include "orconfig.h" #include "app/main/subsysmgr.h" #include "lib/cc/compat_compiler.h" diff --git a/src/core/core.dox b/src/core/core.dox new file mode 100644 index 0000000000..11bf55cb78 --- /dev/null +++ b/src/core/core.dox @@ -0,0 +1,20 @@ +/** +@dir /core +@brief core: main loop and onion routing functionality + +The "core" directory has the central protocols for Tor, which every +client and relay must implement in order to perform onion routing. + +It is divided into three lower-level pieces: + + - \refdir{core/crypto} -- Tor-specific cryptography. + + - \refdir{core/proto} -- Protocol encoding/decoding. + + - \refdir{core/mainloop} -- A connection-oriented asynchronous mainloop. + +and one high-level piece: + + - \refdir{core/or} -- Implements onion routing itself. + +**/ diff --git a/src/core/crypto/core_crypto.dox b/src/core/crypto/core_crypto.dox new file mode 100644 index 0000000000..28ece92bb8 --- /dev/null +++ b/src/core/crypto/core_crypto.dox @@ -0,0 +1,8 @@ +/** +@dir /core/crypto +@brief core/crypto: Tor-specific cryptography + +This module implements Tor's circuit-construction crypto and Tor's +relay crypto. + +**/ diff --git a/src/core/crypto/hs_ntor.h b/src/core/crypto/hs_ntor.h index e5a5171915..5a70974a0c 100644 --- a/src/core/crypto/hs_ntor.h +++ b/src/core/crypto/hs_ntor.h @@ -1,6 +1,11 @@ /* Copyright (c) 2017-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file hs_ntor.h + * @brief Header for hs_ntor.c + **/ + #ifndef TOR_HS_NTOR_H #define TOR_HS_NTOR_H diff --git a/src/core/crypto/onion_ntor.h b/src/core/crypto/onion_ntor.h index 51e72b4083..ea504c1050 100644 --- a/src/core/crypto/onion_ntor.h +++ b/src/core/crypto/onion_ntor.h @@ -1,6 +1,11 @@ /* Copyright (c) 2012-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file onion_ntor.h + * @brief Header for onion_ntor.c + **/ + #ifndef TOR_ONION_NTOR_H #define TOR_ONION_NTOR_H diff --git a/src/core/crypto/relay_crypto.c b/src/core/crypto/relay_crypto.c index 8a285131a8..3213e6a476 100644 --- a/src/core/crypto/relay_crypto.c +++ b/src/core/crypto/relay_crypto.c @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file relay_crypto.h + * @brief Header for relay_crypto.c + **/ + #include "core/or/or.h" #include "core/or/circuitlist.h" #include "core/or/crypt_path.h" diff --git a/src/core/include.am b/src/core/include.am index 9b4b251c81..a69914619e 100644 --- a/src/core/include.am +++ b/src/core/include.am @@ -9,6 +9,7 @@ endif # ADD_C_FILE: INSERT SOURCES HERE. LIBTOR_APP_A_SOURCES = \ src/app/config/config.c \ + src/app/config/quiet_level.c \ src/app/config/statefile.c \ src/app/main/main.c \ src/app/main/shutdown.c \ @@ -71,6 +72,7 @@ LIBTOR_APP_A_SOURCES = \ src/feature/client/circpathbias.c \ src/feature/client/dnsserv.c \ src/feature/client/entrynodes.c \ + src/feature/client/proxymode.c \ src/feature/client/transports.c \ src/feature/control/btrack.c \ src/feature/control/btrack_circuit.c \ @@ -145,7 +147,6 @@ LIBTOR_APP_A_SOURCES = \ src/feature/relay/relay_sys.c \ src/feature/relay/router.c \ src/feature/relay/routerkeys.c \ - src/feature/relay/routermode.c \ src/feature/relay/selftest.c \ src/feature/rend/rendcache.c \ src/feature/rend/rendclient.c \ @@ -169,11 +170,18 @@ endif # LIBTOR_APP_TESTING_A_SOURCES = $(LIBTOR_APP_A_SOURCES) +# The Relay module. +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 \ @@ -188,6 +196,10 @@ MODULE_DIRAUTH_SOURCES = \ src/feature/dirauth/shared_random_state.c \ src/feature/dirauth/voteflags.c +if BUILD_MODULE_RELAY +LIBTOR_APP_A_SOURCES += $(MODULE_RELAY_SOURCES) +endif + if BUILD_MODULE_DIRAUTH LIBTOR_APP_A_SOURCES += $(MODULE_DIRAUTH_SOURCES) endif @@ -196,6 +208,7 @@ src_core_libtor_app_a_SOURCES = $(LIBTOR_APP_A_SOURCES) if UNITTESTS_ENABLED # Add the sources of the modules that are needed for tests to work here. +LIBTOR_APP_TESTING_A_SOURCES += $(MODULE_RELAY_SOURCES) LIBTOR_APP_TESTING_A_SOURCES += $(MODULE_DIRAUTH_SOURCES) src_core_libtor_app_testing_a_SOURCES = $(LIBTOR_APP_TESTING_A_SOURCES) @@ -215,7 +228,9 @@ noinst_HEADERS += \ src/app/config/config.h \ src/app/config/or_options_st.h \ src/app/config/or_state_st.h \ + src/app/config/quiet_level.h \ src/app/config/statefile.h \ + src/app/config/tor_cmdline_mode.h \ src/app/main/main.h \ src/app/main/ntmain.h \ src/app/main/shutdown.h \ @@ -303,6 +318,7 @@ noinst_HEADERS += \ src/feature/client/circpathbias.h \ src/feature/client/dnsserv.h \ src/feature/client/entrynodes.h \ + src/feature/client/proxymode.h \ src/feature/client/transports.h \ src/feature/control/btrack_circuit.h \ src/feature/control/btrack_orconn.h \ @@ -321,8 +337,9 @@ noinst_HEADERS += \ src/feature/control/fmt_serverstatus.h \ src/feature/control/getinfo_geoip.h \ src/feature/dirauth/authmode.h \ - src/feature/dirauth/bridgeauth.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 \ @@ -353,7 +370,7 @@ noinst_HEADERS += \ src/feature/dircommon/fp_pair.h \ src/feature/dircommon/vote_timing_st.h \ src/feature/dircommon/voting_schedule.h \ - src/feature/dirparse/authcert_members.i \ + src/feature/dirparse/authcert_members.h \ src/feature/dirparse/authcert_parse.h \ src/feature/dirparse/microdesc_parse.h \ src/feature/dirparse/ns_parse.h \ @@ -415,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/core/mainloop/core_mainloop.dox b/src/core/mainloop/core_mainloop.dox new file mode 100644 index 0000000000..28cd42bf60 --- /dev/null +++ b/src/core/mainloop/core_mainloop.dox @@ -0,0 +1,12 @@ +/** +@dir /core/mainloop +@brief core/mainloop: Non-onion-routing mainloop functionality + +This module uses the event-loop code of \refdir{lib/evloop} to implement an +asynchronous connection-oriented protocol handler. + +The layering here is imperfect: the code here was split from \refdir{core/or} +without refactoring how the two modules call one another. Probably many +functions should be moved and refactored. + +**/ diff --git a/src/core/mainloop/mainloop.c b/src/core/mainloop/mainloop.c index 6f29a6981a..55b7271605 100644 --- a/src/core/mainloop/mainloop.c +++ b/src/core/mainloop/mainloop.c @@ -71,6 +71,7 @@ #include "feature/client/bridges.h" #include "feature/client/dnsserv.h" #include "feature/client/entrynodes.h" +#include "feature/client/proxymode.h" #include "feature/client/transports.h" #include "feature/control/control.h" #include "feature/control/control_events.h" @@ -1348,9 +1349,11 @@ get_signewnym_epoch(void) static int periodic_events_initialized = 0; /* Declare all the timer callback functions... */ +#ifndef COCCI #undef CALLBACK #define CALLBACK(name) \ static int name ## _callback(time_t, const or_options_t *) + CALLBACK(add_entropy); CALLBACK(check_expired_networkstatus); CALLBACK(clean_caches); @@ -1373,9 +1376,10 @@ CALLBACK(second_elapsed); #undef CALLBACK /* Now we declare an array of periodic_event_item_t for each periodic event */ -#define CALLBACK(name, r, f) \ +#define CALLBACK(name, r, f) \ PERIODIC_EVENT(name, PERIODIC_EVENT_ROLE_ ## r, f) #define FL(name) (PERIODIC_EVENT_FLAG_ ## name) +#endif /* !defined(COCCI) */ STATIC periodic_event_item_t mainloop_periodic_events[] = { @@ -1426,8 +1430,10 @@ STATIC periodic_event_item_t mainloop_periodic_events[] = { END_OF_PERIODIC_EVENTS }; +#ifndef COCCI #undef CALLBACK #undef FL +#endif /* These are pointers to members of periodic_events[] that are used to * implement particular callbacks. We keep them separate here so that we @@ -1526,8 +1532,10 @@ initialize_periodic_events(void) /* Set up all periodic events. We'll launch them by roles. */ +#ifndef COCCI #define NAMED_CALLBACK(name) \ STMT_BEGIN name ## _event = periodic_events_find( #name ); STMT_END +#endif NAMED_CALLBACK(prune_old_routers); NAMED_CALLBACK(fetch_networkstatus); diff --git a/src/core/mainloop/mainloop.h b/src/core/mainloop/mainloop.h index caef736c15..fe181c1920 100644 --- a/src/core/mainloop/mainloop.h +++ b/src/core/mainloop/mainloop.h @@ -94,7 +94,6 @@ void tor_mainloop_free_all(void); struct token_bucket_rw_t; extern time_t time_of_process_start; -extern int quiet_level; extern struct token_bucket_rw_t global_bucket; extern struct token_bucket_rw_t global_relayed_bucket; diff --git a/src/core/mainloop/mainloop_pubsub.c b/src/core/mainloop/mainloop_pubsub.c index 53275d8119..764a1b0cc9 100644 --- a/src/core/mainloop/mainloop_pubsub.c +++ b/src/core/mainloop/mainloop_pubsub.c @@ -4,6 +4,15 @@ * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file mainloop_pubsub.c + * @brief Connect the publish-subscribe code to the main-loop. + * + * This module is responsible for instantiating all the channels used by the + * publish-subscribe code, and making sure that each one's messages are + * processed when appropriate. + **/ + #include "orconfig.h" #include "core/or/or.h" diff --git a/src/core/mainloop/mainloop_pubsub.h b/src/core/mainloop/mainloop_pubsub.h index 365a3dd565..bd57c0c174 100644 --- a/src/core/mainloop/mainloop_pubsub.h +++ b/src/core/mainloop/mainloop_pubsub.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file mainloop_pubsub.h + * @brief Header for mainloop_pubsub.c + **/ + #ifndef TOR_MAINLOOP_PUBSUB_H #define TOR_MAINLOOP_PUBSUB_H diff --git a/src/core/mainloop/mainloop_sys.c b/src/core/mainloop/mainloop_sys.c index fbd5a40327..f14ecb261b 100644 --- a/src/core/mainloop/mainloop_sys.c +++ b/src/core/mainloop/mainloop_sys.c @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file mainloop_sys.c + * @brief Declare the "mainloop" subsystem. + **/ + #include "core/or/or.h" #include "core/mainloop/mainloop_sys.h" #include "core/mainloop/mainloop.h" diff --git a/src/core/mainloop/mainloop_sys.h b/src/core/mainloop/mainloop_sys.h index fa74fe5d4b..434a25a44b 100644 --- a/src/core/mainloop/mainloop_sys.h +++ b/src/core/mainloop/mainloop_sys.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file mainloop_sys.h + * @brief Header for mainloop_sys.c + **/ + #ifndef MAINLOOP_SYS_H #define MAINLOOP_SYS_H diff --git a/src/core/mainloop/netstatus.c b/src/core/mainloop/netstatus.c index 4924888598..c34e613d1f 100644 --- a/src/core/mainloop/netstatus.c +++ b/src/core/mainloop/netstatus.c @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file netstatus.c + * @brief Track whether the network is disabled, dormant, etc. + **/ + #include "core/or/or.h" #include "core/mainloop/netstatus.h" #include "core/mainloop/mainloop.h" diff --git a/src/core/mainloop/netstatus.h b/src/core/mainloop/netstatus.h index e8469ff558..ce3d2e23f9 100644 --- a/src/core/mainloop/netstatus.h +++ b/src/core/mainloop/netstatus.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file netstatus.h + * @brief Header for netstatus.c + **/ + #ifndef TOR_NETSTATUS_H #define TOR_NETSTATUS_H diff --git a/src/core/mainloop/periodic.c b/src/core/mainloop/periodic.c index 5c2f6f2b36..efc6a63165 100644 --- a/src/core/mainloop/periodic.c +++ b/src/core/mainloop/periodic.c @@ -39,7 +39,7 @@ static const int MAX_INTERVAL = 10 * 365 * 86400; /** * Global list of periodic events that have been registered with - * <b>periodic_event_register</a>. + * <b>periodic_event_register</b>. **/ static smartlist_t *the_periodic_events = NULL; diff --git a/src/core/mainloop/periodic.h b/src/core/mainloop/periodic.h index a9aa461969..34fb9cc5ae 100644 --- a/src/core/mainloop/periodic.h +++ b/src/core/mainloop/periodic.h @@ -1,6 +1,11 @@ /* Copyright (c) 2015-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file periodic.h + * @brief Header for periodic.c + **/ + #ifndef TOR_PERIODIC_H #define TOR_PERIODIC_H @@ -71,8 +76,10 @@ typedef struct periodic_event_item_t { } periodic_event_item_t; /** events will get their interval from first execution */ +#ifndef COCCI #define PERIODIC_EVENT(fn, r, f) { fn##_callback, 0, NULL, #fn, r, f, 0 } #define END_OF_PERIODIC_EVENTS { NULL, 0, NULL, NULL, 0, 0, 0 } +#endif /* Return true iff the given event was setup before thus is enabled to be * scheduled. */ diff --git a/src/core/or/addr_policy_st.h b/src/core/or/addr_policy_st.h index 11442d29b4..41c4ac47eb 100644 --- a/src/core/or/addr_policy_st.h +++ b/src/core/or/addr_policy_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file addr_policy_st.h + * @brief Address policy structures. + **/ + #ifndef TOR_ADDR_POLICY_ST_H #define TOR_ADDR_POLICY_ST_H diff --git a/src/core/or/address_set.c b/src/core/or/address_set.c index 758fba4aac..c74ddbf708 100644 --- a/src/core/or/address_set.c +++ b/src/core/or/address_set.c @@ -17,7 +17,7 @@ #include "lib/crypt_ops/crypto_rand.h" #include "siphash.h" -/* Wrap our hash function to have the signature that the bloom filter +/** Wrap our hash function to have the signature that the bloom filter * needs. */ static uint64_t bloomfilt_addr_hash(const struct sipkey *key, diff --git a/src/core/or/cell_queue_st.h b/src/core/or/cell_queue_st.h index 7ba339b965..763bc5bc1e 100644 --- a/src/core/or/cell_queue_st.h +++ b/src/core/or/cell_queue_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file cell_queue_st.h + * @brief Cell queue structures + **/ + #ifndef PACKED_CELL_ST_H #define PACKED_CELL_ST_H diff --git a/src/core/or/cell_st.h b/src/core/or/cell_st.h index c4eec4f4b5..5c1667d321 100644 --- a/src/core/or/cell_st.h +++ b/src/core/or/cell_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file cell_st.h + * @brief Fixed-size cell structure. + **/ + #ifndef CELL_ST_H #define CELL_ST_H @@ -17,4 +22,3 @@ struct cell_t { }; #endif /* !defined(CELL_ST_H) */ - diff --git a/src/core/or/channel.h b/src/core/or/channel.h index 97aa000337..3533e6176e 100644 --- a/src/core/or/channel.h +++ b/src/core/or/channel.h @@ -48,7 +48,7 @@ typedef enum { /* channel states for channel_t */ typedef enum { - /* + /** * Closed state - channel is inactive * * Permitted transitions from: @@ -57,7 +57,7 @@ typedef enum { * - CHANNEL_STATE_OPENING */ CHANNEL_STATE_CLOSED = 0, - /* + /** * Opening state - channel is trying to connect * * Permitted transitions from: @@ -68,7 +68,7 @@ typedef enum { * - CHANNEL_STATE_OPEN */ CHANNEL_STATE_OPENING, - /* + /** * Open state - channel is active and ready for use * * Permitted transitions from: @@ -80,7 +80,7 @@ typedef enum { * - CHANNEL_STATE_MAINT */ CHANNEL_STATE_OPEN, - /* + /** * Maintenance state - channel is temporarily offline for subclass specific * maintenance activities such as TLS renegotiation. * @@ -92,7 +92,7 @@ typedef enum { * - CHANNEL_STATE_OPEN */ CHANNEL_STATE_MAINT, - /* + /** * Closing state - channel is shutting down * * Permitted transitions from: @@ -103,7 +103,7 @@ typedef enum { * - CHANNEL_STATE_ERROR */ CHANNEL_STATE_CLOSING, - /* + /** * Error state - channel has experienced a permanent error * * Permitted transitions from: @@ -115,7 +115,7 @@ typedef enum { * - None */ CHANNEL_STATE_ERROR, - /* + /** * Placeholder for maximum state value */ CHANNEL_STATE_LAST @@ -124,7 +124,7 @@ typedef enum { /* channel listener states for channel_listener_t */ typedef enum { - /* + /** * Closed state - channel listener is inactive * * Permitted transitions from: @@ -133,7 +133,7 @@ typedef enum { * - CHANNEL_LISTENER_STATE_LISTENING */ CHANNEL_LISTENER_STATE_CLOSED = 0, - /* + /** * Listening state - channel listener is listening for incoming * connections * @@ -144,7 +144,7 @@ typedef enum { * - CHANNEL_LISTENER_STATE_ERROR */ CHANNEL_LISTENER_STATE_LISTENING, - /* + /** * Closing state - channel listener is shutting down * * Permitted transitions from: @@ -154,7 +154,7 @@ typedef enum { * - CHANNEL_LISTENER_STATE_ERROR */ CHANNEL_LISTENER_STATE_CLOSING, - /* + /** * Error state - channel listener has experienced a permanent error * * Permitted transitions from: @@ -164,7 +164,7 @@ typedef enum { * - None */ CHANNEL_LISTENER_STATE_ERROR, - /* + /** * Placeholder for maximum state value */ CHANNEL_LISTENER_STATE_LAST @@ -267,21 +267,21 @@ struct channel_s { /** State variable for use by the scheduler */ enum { - /* + /** * The channel is not open, or it has a full output buffer but no queued * cells. */ SCHED_CHAN_IDLE = 0, - /* + /** * The channel has space on its output buffer to write, but no queued * cells. */ SCHED_CHAN_WAITING_FOR_CELLS, - /* + /** * The scheduler has queued cells but no output buffer space to write. */ SCHED_CHAN_WAITING_TO_WRITE, - /* + /** * The scheduler has both queued cells and output buffer space, and is * eligible for the scheduler loop. */ @@ -444,9 +444,9 @@ struct channel_s { ratelim_t last_warned_circ_ids_exhausted; /** Channel timestamps for cell channels */ - time_t timestamp_client; /* Client used this, according to relay.c */ - time_t timestamp_recv; /* Cell received from lower layer */ - time_t timestamp_xmit; /* Cell sent to lower layer */ + time_t timestamp_client; /*(< Client used this, according to relay.c */ + time_t timestamp_recv; /**< Cell received from lower layer */ + time_t timestamp_xmit; /**< Cell sent to lower layer */ /** Timestamp for run_connection_housekeeping(). We update this once a * second when we run housekeeping and find a circuit on this channel, and @@ -458,16 +458,17 @@ struct channel_s { * distinct namespace. */ uint64_t dirreq_id; - /** Channel counters for cell channels */ + /** Channel counters for cells and bytes we have received. */ uint64_t n_cells_recved, n_bytes_recved; + /** Channel counters for cells and bytes we have sent. */ uint64_t n_cells_xmitted, n_bytes_xmitted; }; struct channel_listener_s { - /* Current channel listener state */ + /** Current channel listener state */ channel_listener_state_t state; - /* Globally unique ID number for a channel over the lifetime of a Tor + /** Globally unique ID number for a channel over the lifetime of a Tor * process. */ uint64_t global_identifier; diff --git a/src/core/or/channelpadding.c b/src/core/or/channelpadding.c index 4a0f0e00da..2b8314db89 100644 --- a/src/core/or/channelpadding.c +++ b/src/core/or/channelpadding.c @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file channelpadding.c + * @brief Link-level padding code. + **/ + /* TOR_CHANNEL_INTERNAL_ define needed for an O(1) implementation of * channelpadding_channel_to_channelinfo() */ #define TOR_CHANNEL_INTERNAL_ diff --git a/src/core/or/circuit_st.h b/src/core/or/circuit_st.h index eae3c908d5..929f3840ef 100644 --- a/src/core/or/circuit_st.h +++ b/src/core/or/circuit_st.h @@ -4,11 +4,18 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file circuit_st.h + * @brief Base circuit structure. + **/ + #ifndef CIRCUIT_ST_H #define CIRCUIT_ST_H #include "core/or/or.h" +#include "lib/container/handles.h" + #include "core/or/cell_queue_st.h" struct hs_token_t; @@ -54,6 +61,9 @@ struct circuit_t { uint32_t magic; /**< For memory and type debugging: must equal * ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */ + /** Handle entry for handle-based lookup */ + HANDLE_ENTRY(circuit, circuit_t); + /** The channel that is next in this circuit. */ channel_t *n_chan; diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c index 1daf468715..57d929292d 100644 --- a/src/core/or/circuitbuild.c +++ b/src/core/or/circuitbuild.c @@ -30,7 +30,7 @@ #include "core/or/or.h" #include "app/config/config.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "core/crypto/hs_ntor.h" #include "core/crypto/onion_crypto.h" #include "core/crypto/onion_fast.h" diff --git a/src/core/or/circuitlist.c b/src/core/or/circuitlist.c index 9ee9f93c99..9a0b9241da 100644 --- a/src/core/or/circuitlist.c +++ b/src/core/or/circuitlist.c @@ -147,6 +147,9 @@ static int any_opened_circs_cached_val = 0; /********* END VARIABLES ************/ +/* Implement circuit handle helpers. */ +HANDLE_IMPL(circuit, circuit_t,) + or_circuit_t * TO_OR_CIRCUIT(circuit_t *x) { @@ -1247,6 +1250,9 @@ circuit_free_(circuit_t *circ) /* Free any circuit padding structures */ circpad_circuit_free_all_machineinfos(circ); + /* Clear all dangling handle references. */ + circuit_handles_clear(circ); + if (should_free) { memwipe(mem, 0xAA, memlen); /* poison memory */ tor_free(mem); diff --git a/src/core/or/circuitlist.h b/src/core/or/circuitlist.h index 80c1f7ac4e..afbf1ad98f 100644 --- a/src/core/or/circuitlist.h +++ b/src/core/or/circuitlist.h @@ -12,6 +12,7 @@ #ifndef TOR_CIRCUITLIST_H #define TOR_CIRCUITLIST_H +#include "lib/container/handles.h" #include "lib/testsupport/testsupport.h" #include "feature/hs/hs_ident.h" #include "core/or/ocirc_event.h" @@ -242,6 +243,11 @@ MOCK_DECL(void, channel_note_destroy_not_pending, smartlist_t *circuit_find_circuits_to_upgrade_from_guard_wait(void); +/* Declare the handle helpers */ +HANDLE_DECL(circuit, circuit_t, ) +#define circuit_handle_free(h) \ + FREE_AND_NULL(circuit_handle_t, circuit_handle_free_, (h)) + #ifdef CIRCUITLIST_PRIVATE STATIC void circuit_free_(circuit_t *circ); #define circuit_free(circ) FREE_AND_NULL(circuit_t, circuit_free_, (circ)) diff --git a/src/core/or/circuitmux.c b/src/core/or/circuitmux.c index b2628bec3f..f92a53eb27 100644 --- a/src/core/or/circuitmux.c +++ b/src/core/or/circuitmux.c @@ -69,14 +69,14 @@ * made to attach all existing circuits to the new policy. **/ +#define CIRCUITMUX_PRIVATE + #include "core/or/or.h" #include "core/or/channel.h" #include "core/or/circuitlist.h" #include "core/or/circuitmux.h" #include "core/or/relay.h" -#include "core/or/cell_queue_st.h" -#include "core/or/destroy_cell_queue_st.h" #include "core/or/or_circuit_st.h" /* @@ -84,12 +84,6 @@ */ /* - * Map of muxinfos for circuitmux_t to use; struct is defined below (name - * of struct must match HT_HEAD line). - */ -typedef struct chanid_circid_muxinfo_map chanid_circid_muxinfo_map_t; - -/* * Hash table entry (yeah, calling it chanid_circid_muxinfo_s seems to * break the hash table code). */ @@ -103,49 +97,6 @@ typedef struct chanid_circid_muxinfo_t chanid_circid_muxinfo_t; typedef struct circuit_muxinfo_s circuit_muxinfo_t; /* - * Structures for circuitmux.c - */ - -struct circuitmux_s { - /* Keep count of attached, active circuits */ - unsigned int n_circuits, n_active_circuits; - - /* Total number of queued cells on all circuits */ - unsigned int n_cells; - - /* - * Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t - */ - chanid_circid_muxinfo_map_t *chanid_circid_map; - - /** List of queued destroy cells */ - destroy_cell_queue_t destroy_cell_queue; - /** Boolean: True iff the last cell to circuitmux_get_first_active_circuit - * returned the destroy queue. Used to force alternation between - * destroy/non-destroy cells. - * - * XXXX There is no reason to think that alternating is a particularly good - * approach -- it's just designed to prevent destroys from starving other - * cells completely. - */ - unsigned int last_cell_was_destroy : 1; - /** Destroy counter: increment this when a destroy gets queued, decrement - * when we unqueue it, so we can test to make sure they don't starve. - */ - int64_t destroy_ctr; - - /* - * Circuitmux policy; if this is non-NULL, it can override the built- - * in round-robin active circuits behavior. This is how EWMA works in - * the new circuitmux_t world. - */ - const circuitmux_policy_t *policy; - - /* Policy-specific data */ - circuitmux_policy_data_t *policy_data; -}; - -/* * This struct holds whatever we want to store per attached circuit on a * circuitmux_t; right now, just the count of queued cells and the direction. */ @@ -221,9 +172,6 @@ chanid_circid_entry_hash(chanid_circid_muxinfo_t *a) ((unsigned int)(a->chan_id & 0xffffffff))); } -/* Declare the struct chanid_circid_muxinfo_map type */ -HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t); - /* Emit a bunch of hash table stuff */ HT_PROTOTYPE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node, chanid_circid_entry_hash, chanid_circid_entries_eq) diff --git a/src/core/or/circuitmux.h b/src/core/or/circuitmux.h index 67cd9bcdd8..c68c31b29a 100644 --- a/src/core/or/circuitmux.h +++ b/src/core/or/circuitmux.h @@ -158,5 +158,61 @@ void circuitmux_mark_destroyed_circids_usable(circuitmux_t *cmux, MOCK_DECL(int, circuitmux_compare_muxes, (circuitmux_t *cmux_1, circuitmux_t *cmux_2)); +#ifdef CIRCUITMUX_PRIVATE + +#include "core/or/destroy_cell_queue_st.h" + +/* + * Map of muxinfos for circuitmux_t to use; struct is defined below (name + * of struct must match HT_HEAD line). + */ +typedef HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t) + chanid_circid_muxinfo_map_t; + +/* + * Structures for circuitmux.c + */ + +struct circuitmux_s { + /* Keep count of attached, active circuits */ + unsigned int n_circuits, n_active_circuits; + + /* Total number of queued cells on all circuits */ + unsigned int n_cells; + + /* + * Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t + */ + chanid_circid_muxinfo_map_t *chanid_circid_map; + + /** List of queued destroy cells */ + destroy_cell_queue_t destroy_cell_queue; + /** Boolean: True iff the last cell to circuitmux_get_first_active_circuit + * returned the destroy queue. Used to force alternation between + * destroy/non-destroy cells. + * + * XXXX There is no reason to think that alternating is a particularly good + * approach -- it's just designed to prevent destroys from starving other + * cells completely. + */ + unsigned int last_cell_was_destroy : 1; + /** Destroy counter: increment this when a destroy gets queued, decrement + * when we unqueue it, so we can test to make sure they don't starve. + */ + int64_t destroy_ctr; + + /* + * Circuitmux policy; if this is non-NULL, it can override the built- + * in round-robin active circuits behavior. This is how EWMA works in + * the new circuitmux_t world. + */ + const circuitmux_policy_t *policy; + + /* Policy-specific data */ + circuitmux_policy_data_t *policy_data; +}; + +#endif /* CIRCUITMUX_PRIVATE */ + #endif /* !defined(TOR_CIRCUITMUX_H) */ diff --git a/src/core/or/circuitmux_ewma.c b/src/core/or/circuitmux_ewma.c index 3f83c3fd5a..5c9eac1c3f 100644 --- a/src/core/or/circuitmux_ewma.c +++ b/src/core/or/circuitmux_ewma.c @@ -58,115 +58,6 @@ /** The natural logarithm of 0.5. */ #define LOG_ONEHALF -0.69314718055994529 -/*** EWMA structures ***/ - -typedef struct cell_ewma_s cell_ewma_t; -typedef struct ewma_policy_data_s ewma_policy_data_t; -typedef struct ewma_policy_circ_data_s ewma_policy_circ_data_t; - -/** - * The cell_ewma_t structure keeps track of how many cells a circuit has - * transferred recently. It keeps an EWMA (exponentially weighted moving - * average) of the number of cells flushed from the circuit queue onto a - * connection in channel_flush_from_first_active_circuit(). - */ - -struct cell_ewma_s { - /** The last 'tick' at which we recalibrated cell_count. - * - * A cell sent at exactly the start of this tick has weight 1.0. Cells sent - * since the start of this tick have weight greater than 1.0; ones sent - * earlier have less weight. */ - unsigned int last_adjusted_tick; - /** The EWMA of the cell count. */ - double cell_count; - /** True iff this is the cell count for a circuit's previous - * channel. */ - unsigned int is_for_p_chan : 1; - /** The position of the circuit within the OR connection's priority - * queue. */ - int heap_index; -}; - -struct ewma_policy_data_s { - circuitmux_policy_data_t base_; - - /** - * Priority queue of cell_ewma_t for circuits with queued cells waiting - * for room to free up on the channel that owns this circuitmux. Kept - * in heap order according to EWMA. This was formerly in channel_t, and - * in or_connection_t before that. - */ - smartlist_t *active_circuit_pqueue; - - /** - * The tick on which the cell_ewma_ts in active_circuit_pqueue last had - * their ewma values rescaled. This was formerly in channel_t, and in - * or_connection_t before that. - */ - unsigned int active_circuit_pqueue_last_recalibrated; -}; - -struct ewma_policy_circ_data_s { - circuitmux_policy_circ_data_t base_; - - /** - * The EWMA count for the number of cells flushed from this circuit - * onto this circuitmux. Used to determine which circuit to flush - * from next. This was formerly in circuit_t and or_circuit_t. - */ - cell_ewma_t cell_ewma; - - /** - * Pointer back to the circuit_t this is for; since we're separating - * out circuit selection policy like this, we can't attach cell_ewma_t - * to the circuit_t any more, so we can't use SUBTYPE_P directly to a - * circuit_t like before; instead get it here. - */ - circuit_t *circ; -}; - -#define EWMA_POL_DATA_MAGIC 0x2fd8b16aU -#define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U - -/*** Downcasts for the above types ***/ - -static ewma_policy_data_t * -TO_EWMA_POL_DATA(circuitmux_policy_data_t *); - -static ewma_policy_circ_data_t * -TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *); - -/** - * Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert - * if the cast is impossible. - */ - -static inline ewma_policy_data_t * -TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol) -{ - if (!pol) return NULL; - else { - tor_assert(pol->magic == EWMA_POL_DATA_MAGIC); - return DOWNCAST(ewma_policy_data_t, pol); - } -} - -/** - * Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t - * and assert if the cast is impossible. - */ - -static inline ewma_policy_circ_data_t * -TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol) -{ - if (!pol) return NULL; - else { - tor_assert(pol->magic == EWMA_POL_CIRC_DATA_MAGIC); - return DOWNCAST(ewma_policy_circ_data_t, pol); - } -} - /*** Static declarations for circuitmux_ewma.c ***/ static void add_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma); diff --git a/src/core/or/circuitmux_ewma.h b/src/core/or/circuitmux_ewma.h index b45ce1f916..dcfbc17a82 100644 --- a/src/core/or/circuitmux_ewma.h +++ b/src/core/or/circuitmux_ewma.h @@ -22,9 +22,114 @@ void cmux_ewma_set_options(const or_options_t *options, void circuitmux_ewma_free_all(void); #ifdef CIRCUITMUX_EWMA_PRIVATE + +/*** EWMA structures ***/ + +typedef struct cell_ewma_s cell_ewma_t; +typedef struct ewma_policy_data_s ewma_policy_data_t; +typedef struct ewma_policy_circ_data_s ewma_policy_circ_data_t; + +/** + * The cell_ewma_t structure keeps track of how many cells a circuit has + * transferred recently. It keeps an EWMA (exponentially weighted moving + * average) of the number of cells flushed from the circuit queue onto a + * connection in channel_flush_from_first_active_circuit(). + */ + +struct cell_ewma_s { + /** The last 'tick' at which we recalibrated cell_count. + * + * A cell sent at exactly the start of this tick has weight 1.0. Cells sent + * since the start of this tick have weight greater than 1.0; ones sent + * earlier have less weight. */ + unsigned int last_adjusted_tick; + /** The EWMA of the cell count. */ + double cell_count; + /** True iff this is the cell count for a circuit's previous + * channel. */ + unsigned int is_for_p_chan : 1; + /** The position of the circuit within the OR connection's priority + * queue. */ + int heap_index; +}; + +struct ewma_policy_data_s { + circuitmux_policy_data_t base_; + + /** + * Priority queue of cell_ewma_t for circuits with queued cells waiting + * for room to free up on the channel that owns this circuitmux. Kept + * in heap order according to EWMA. This was formerly in channel_t, and + * in or_connection_t before that. + */ + smartlist_t *active_circuit_pqueue; + + /** + * The tick on which the cell_ewma_ts in active_circuit_pqueue last had + * their ewma values rescaled. This was formerly in channel_t, and in + * or_connection_t before that. + */ + unsigned int active_circuit_pqueue_last_recalibrated; +}; + +struct ewma_policy_circ_data_s { + circuitmux_policy_circ_data_t base_; + + /** + * The EWMA count for the number of cells flushed from this circuit + * onto this circuitmux. Used to determine which circuit to flush + * from next. This was formerly in circuit_t and or_circuit_t. + */ + cell_ewma_t cell_ewma; + + /** + * Pointer back to the circuit_t this is for; since we're separating + * out circuit selection policy like this, we can't attach cell_ewma_t + * to the circuit_t any more, so we can't use SUBTYPE_P directly to a + * circuit_t like before; instead get it here. + */ + circuit_t *circ; +}; + +#define EWMA_POL_DATA_MAGIC 0x2fd8b16aU +#define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U + +/*** Downcasts for the above types ***/ + +/** + * Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert + * if the cast is impossible. + */ + +static inline ewma_policy_data_t * +TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol) +{ + if (!pol) return NULL; + else { + tor_assert(pol->magic == EWMA_POL_DATA_MAGIC); + return DOWNCAST(ewma_policy_data_t, pol); + } +} + +/** + * Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t + * and assert if the cast is impossible. + */ + +static inline ewma_policy_circ_data_t * +TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol) +{ + if (!pol) return NULL; + else { + tor_assert(pol->magic == EWMA_POL_CIRC_DATA_MAGIC); + return DOWNCAST(ewma_policy_circ_data_t, pol); + } +} + STATIC unsigned cell_ewma_get_current_tick_and_fraction(double *remainder_out); STATIC void cell_ewma_initialize_ticks(void); -#endif + +#endif /* CIRCUITMUX_EWMA_PRIVATE */ #endif /* !defined(TOR_CIRCUITMUX_EWMA_H) */ diff --git a/src/core/or/circuitpadding.c b/src/core/or/circuitpadding.c index 99c68d5f6b..e9b14144cc 100644 --- a/src/core/or/circuitpadding.c +++ b/src/core/or/circuitpadding.c @@ -116,6 +116,7 @@ STATIC smartlist_t *origin_padding_machines = NULL; * runtime and as long as circuits are alive. */ STATIC smartlist_t *relay_padding_machines = NULL; +#ifndef COCCI /** Loop over the current padding state machines using <b>loop_var</b> as the * loop variable. */ #define FOR_EACH_CIRCUIT_MACHINE_BEGIN(loop_var) \ @@ -130,6 +131,7 @@ STATIC smartlist_t *relay_padding_machines = NULL; if (!(circ)->padding_info[loop_var]) \ continue; #define FOR_EACH_ACTIVE_CIRCUIT_MACHINE_END } STMT_END ; +#endif /* !defined(COCCI) */ /** * Free the machineinfo at an index @@ -2179,8 +2181,8 @@ circpad_add_matching_machines(origin_circuit_t *on_circ, circ->padding_machine[i] = NULL; on_circ->padding_negotiation_failed = 1; } else { - /* Success. Don't try any more machines */ - return; + /* Success. Don't try any more machines on this index */ + break; } } } SMARTLIST_FOREACH_END(machine); diff --git a/src/core/or/circuitpadding.h b/src/core/or/circuitpadding.h index e9eb32c618..a5c46b4390 100644 --- a/src/core/or/circuitpadding.h +++ b/src/core/or/circuitpadding.h @@ -301,7 +301,7 @@ typedef struct circpad_state_t { * | | | | | | | * | | | | | | | * 0 +----+----+-----+-----+---------+---------------+ - * 0 100 200 350 500 1000 ∞ microseconds + * 0 100 200 350 500 1000 inf microseconds * * would be specified the following way: * histogram_len = 6; @@ -388,7 +388,7 @@ typedef struct circpad_state_t { * * States are allowed to transition to themselves, which means re-schedule * a new padding timer. They are also allowed to temporarily "transition" - * to the "IGNORE" and "CANCEL" pseudo-states. See #defines below + * to the "IGNORE" and "CANCEL" pseudo-states. See defines below * for details on state behavior and meaning. */ circpad_statenum_t next_state[CIRCPAD_NUM_EVENTS]; diff --git a/src/core/or/circuitpadding_machines.c b/src/core/or/circuitpadding_machines.c index 7220d657fc..98767f9e8f 100644 --- a/src/core/or/circuitpadding_machines.c +++ b/src/core/or/circuitpadding_machines.c @@ -5,8 +5,6 @@ * \file circuitpadding_machines.c * \brief Circuit padding state machines * - * \detail - * * Introduce circuit padding machines that will be used by Tor circuits, as * specified by proposal 302 "Hiding onion service clients using padding". * diff --git a/src/core/or/circuitstats.c b/src/core/or/circuitstats.c index 7a7f3ca600..7df2154116 100644 --- a/src/core/or/circuitstats.c +++ b/src/core/or/circuitstats.c @@ -29,7 +29,7 @@ #include "core/or/circuitbuild.h" #include "core/or/circuitstats.h" #include "app/config/config.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "feature/control/control_events.h" #include "lib/crypt_ops/crypto_rand.h" #include "core/mainloop/mainloop.h" diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c index 606c5e2dd2..a74ecbfd54 100644 --- a/src/core/or/circuituse.c +++ b/src/core/or/circuituse.c @@ -42,6 +42,7 @@ #include "feature/client/bridges.h" #include "feature/client/circpathbias.h" #include "feature/client/entrynodes.h" +#include "feature/client/proxymode.h" #include "feature/control/control_events.h" #include "feature/dircommon/directory.h" #include "feature/hs/hs_circuit.h" diff --git a/src/core/or/connection_st.h b/src/core/or/connection_st.h index 1c42a56d6b..08558d79ff 100644 --- a/src/core/or/connection_st.h +++ b/src/core/or/connection_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file connection_st.h + * @brief Base connection structure. + **/ + #ifndef CONNECTION_ST_H #define CONNECTION_ST_H diff --git a/src/core/or/core_or.dox b/src/core/or/core_or.dox new file mode 100644 index 0000000000..705e9b5436 --- /dev/null +++ b/src/core/or/core_or.dox @@ -0,0 +1,62 @@ +/** +@dir /core/or +@brief core/or: *Onion routing happens here*. + +This is the central part of Tor that handles the core tasks of onion routing: +building circuit, handling circuits, attaching circuit to streams, moving +data around, and so forth. + +Some aspects of this module should probably be refactored into others. + +Notable files here include: + +`channel.c` +: Generic channel implementation. Channels handle sending and receiving cells +among tor nodes. + +`channeltls.c` +: Channel implementation for TLS-based OR connections. Uses `connection_or.c`. + +`circuitbuild.c` +: Code for constructing circuits and choosing their paths. (*Note*: +this module could plausibly be split into handling the client side, +the server side, and the path generation aspects of circuit building.) + +`circuitlist.c` +: Code for maintaining and navigating the global list of circuits. + +`circuitmux.c` +: Generic circuitmux implementation. A circuitmux handles deciding, for a +particular channel, which circuit should write next. + +`circuitmux_ewma.c` +: A circuitmux implementation based on the EWMA (exponentially +weighted moving average) algorithm. + +`circuituse.c` +: Code to actually send and receive data on circuits. + +`command.c` +: Handles incoming cells on channels. + +`connection.c` +: Generic and common connection tools, and implementation for the simpler +connection types. + +`connection_edge.c` +: Implementation for entry and exit connections. + +`connection_or.c` +: Implementation for OR connections (the ones that send cells over TLS). + +`onion.c` +: Generic code for generating and responding to CREATE and CREATED +cells, and performing the appropriate onion handshakes. Also contains +code to manage the server-side onion queue. + +`relay.c` +: Handles particular types of relay cells, and provides code to receive, +encrypt, route, and interpret relay cells. + +`scheduler.c` +: Decides which channel/circuit pair is ready to receive the next cell. diff --git a/src/core/or/cpath_build_state_st.h b/src/core/or/cpath_build_state_st.h index 4572a10430..240badde40 100644 --- a/src/core/or/cpath_build_state_st.h +++ b/src/core/or/cpath_build_state_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file cpath_build_state_st.h + * @brief Circuit-build-stse structure + **/ + #ifndef CIRCUIT_BUILD_STATE_ST_ST_H #define CIRCUIT_BUILD_STATE_ST_ST_H @@ -35,4 +40,3 @@ struct cpath_build_state_t { }; #endif /* !defined(CIRCUIT_BUILD_STATE_ST_ST_H) */ - diff --git a/src/core/or/crypt_path_reference_st.h b/src/core/or/crypt_path_reference_st.h index 1827022b4e..fb20a3fc5a 100644 --- a/src/core/or/crypt_path_reference_st.h +++ b/src/core/or/crypt_path_reference_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file crypt_path_reference_st.h + * @brief reference-counting structure for crypt_path_t + **/ + #ifndef CRYPT_PATH_REFERENCE_ST_H #define CRYPT_PATH_REFERENCE_ST_H @@ -20,4 +25,3 @@ struct crypt_path_reference_t { }; #endif /* !defined(CRYPT_PATH_REFERENCE_ST_H) */ - diff --git a/src/core/or/crypt_path_st.h b/src/core/or/crypt_path_st.h index 249ac6aaa3..945961d5d1 100644 --- a/src/core/or/crypt_path_st.h +++ b/src/core/or/crypt_path_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file crypt_path_st.h + * @brief Path structures for origin circuits. + **/ + #ifndef CRYPT_PATH_ST_H #define CRYPT_PATH_ST_H diff --git a/src/core/or/destroy_cell_queue_st.h b/src/core/or/destroy_cell_queue_st.h index e917afc700..3c4df050c2 100644 --- a/src/core/or/destroy_cell_queue_st.h +++ b/src/core/or/destroy_cell_queue_st.h @@ -4,9 +4,16 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file destroy_cell_queue_st.h + * @brief Destroy-cell queue structures + **/ + #ifndef DESTROY_CELL_QUEUE_ST_H #define DESTROY_CELL_QUEUE_ST_H +#include "core/or/cell_queue_st.h" + /** A single queued destroy cell. */ struct destroy_cell_t { TOR_SIMPLEQ_ENTRY(destroy_cell_t) next; @@ -24,4 +31,3 @@ struct destroy_cell_queue_t { }; #endif /* !defined(DESTROY_CELL_QUEUE_ST_H) */ - diff --git a/src/core/or/edge_connection_st.h b/src/core/or/edge_connection_st.h index 8922a3a9cf..d043d1ffb4 100644 --- a/src/core/or/edge_connection_st.h +++ b/src/core/or/edge_connection_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file edge_connection_st.h + * @brief Edge-connection structure. + **/ + #ifndef EDGE_CONNECTION_ST_H #define EDGE_CONNECTION_ST_H @@ -74,4 +79,3 @@ struct edge_connection_t { }; #endif /* !defined(EDGE_CONNECTION_ST_H) */ - diff --git a/src/core/or/entry_connection_st.h b/src/core/or/entry_connection_st.h index e65c545d17..b866e78493 100644 --- a/src/core/or/entry_connection_st.h +++ b/src/core/or/entry_connection_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file entry_connection_st.h + * @brief Entry connection structure. + **/ + #ifndef ENTRY_CONNECTION_ST_H #define ENTRY_CONNECTION_ST_H @@ -97,4 +102,3 @@ struct entry_connection_t { #define ENTRY_TO_EDGE_CONN(c) (&(((c))->edge_)) #endif /* !defined(ENTRY_CONNECTION_ST_H) */ - diff --git a/src/core/or/entry_port_cfg_st.h b/src/core/or/entry_port_cfg_st.h index b84838d44f..f52f47d1c9 100644 --- a/src/core/or/entry_port_cfg_st.h +++ b/src/core/or/entry_port_cfg_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file entry_port_cfg_st.h + * @brief Configuration structure for client ports. + **/ + #ifndef ENTRY_PORT_CFG_ST_H #define ENTRY_PORT_CFG_ST_H @@ -51,4 +56,3 @@ struct entry_port_cfg_t { }; #endif /* !defined(ENTRY_PORT_CFG_ST_H) */ - diff --git a/src/core/or/extend_info_st.h b/src/core/or/extend_info_st.h index 7704ff16b5..babf15c59a 100644 --- a/src/core/or/extend_info_st.h +++ b/src/core/or/extend_info_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file extend_info_st.h + * @brief Extend-info structure. + **/ + #ifndef EXTEND_INFO_ST_H #define EXTEND_INFO_ST_H diff --git a/src/core/or/half_edge_st.h b/src/core/or/half_edge_st.h index 1fe47ad3f1..cb2044654f 100644 --- a/src/core/or/half_edge_st.h +++ b/src/core/or/half_edge_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file half_edge_st.h + * @brief Half-open connection structure. + **/ + #ifndef HALF_EDGE_ST_H #define HALF_EDGE_ST_H @@ -31,4 +36,3 @@ typedef struct half_edge_t { } half_edge_t; #endif /* !defined(HALF_EDGE_ST_H) */ - diff --git a/src/core/or/listener_connection_st.h b/src/core/or/listener_connection_st.h index 1250d9c9b4..fafc8444f9 100644 --- a/src/core/or/listener_connection_st.h +++ b/src/core/or/listener_connection_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file listener_connection_st.h + * @brief Listener connection structure. + **/ + #ifndef LISTENER_CONNECTION_ST_H #define LISTENER_CONNECTION_ST_H @@ -22,4 +27,3 @@ struct listener_connection_t { }; #endif /* !defined(LISTENER_CONNECTION_ST_H) */ - diff --git a/src/core/or/or_connection_st.h b/src/core/or/or_connection_st.h index 051fcd00d3..c364117a35 100644 --- a/src/core/or/or_connection_st.h +++ b/src/core/or/or_connection_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file or_connection_st.h + * @brief OR connection structure. + **/ + #ifndef OR_CONNECTION_ST_H #define OR_CONNECTION_ST_H diff --git a/src/core/or/or_handshake_certs_st.h b/src/core/or/or_handshake_certs_st.h index 9deb6d6d59..209fee551d 100644 --- a/src/core/or/or_handshake_certs_st.h +++ b/src/core/or/or_handshake_certs_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file or_handshake_certs_st.h + * @brief OR handshake certs structure + **/ + #ifndef OR_HANDSHAKE_CERTS_ST #define OR_HANDSHAKE_CERTS_ST diff --git a/src/core/or/or_handshake_state_st.h b/src/core/or/or_handshake_state_st.h index 472ce8a302..43f88e7565 100644 --- a/src/core/or/or_handshake_state_st.h +++ b/src/core/or/or_handshake_state_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file or_handshake_state_st.h + * @brief OR handshake state structure + **/ + #ifndef OR_HANDSHAKE_STATE_ST #define OR_HANDSHAKE_STATE_ST @@ -75,4 +80,3 @@ struct or_handshake_state_t { }; #endif /* !defined(OR_HANDSHAKE_STATE_ST) */ - diff --git a/src/core/or/or_periodic.c b/src/core/or/or_periodic.c index fe28c99192..0e79008275 100644 --- a/src/core/or/or_periodic.c +++ b/src/core/or/or_periodic.c @@ -20,11 +20,13 @@ #include "feature/relay/routermode.h" +#ifndef COCCI #define DECLARE_EVENT(name, roles, flags) \ static periodic_event_item_t name ## _event = \ PERIODIC_EVENT(name, \ PERIODIC_EVENT_ROLE_##roles, \ flags) +#endif /* !defined(COCCI) */ #define FL(name) (PERIODIC_EVENT_FLAG_ ## name) diff --git a/src/core/or/origin_circuit_st.h b/src/core/or/origin_circuit_st.h index 01bbc84ae2..cdb3f95a99 100644 --- a/src/core/or/origin_circuit_st.h +++ b/src/core/or/origin_circuit_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file origin_circuit_st.h + * @brief Origin circuit structure. + **/ + #ifndef ORIGIN_CIRCUIT_ST_H #define ORIGIN_CIRCUIT_ST_H diff --git a/src/core/or/port_cfg_st.h b/src/core/or/port_cfg_st.h index e9e82bb1de..f27c81d951 100644 --- a/src/core/or/port_cfg_st.h +++ b/src/core/or/port_cfg_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file port_cfg_st.h + * @brief Listener port configuration structure. + **/ + #ifndef PORT_CFG_ST_H #define PORT_CFG_ST_H @@ -32,4 +37,3 @@ struct port_cfg_t { }; #endif /* !defined(PORT_CFG_ST_H) */ - diff --git a/src/core/or/relay_crypto_st.h b/src/core/or/relay_crypto_st.h index 83bbd329a6..1b1eb16df1 100644 --- a/src/core/or/relay_crypto_st.h +++ b/src/core/or/relay_crypto_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file relay_crypto_st.h + * @brief Relay-cell encryption state structure. + **/ + #ifndef RELAY_CRYPTO_ST_H #define RELAY_CRYPTO_ST_H diff --git a/src/core/or/scheduler_kist.c b/src/core/or/scheduler_kist.c index 35b613cb8a..f4bac7b877 100644 --- a/src/core/or/scheduler_kist.c +++ b/src/core/or/scheduler_kist.c @@ -1,6 +1,11 @@ /* Copyright (c) 2017-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file scheduler_kist.c + * @brief Implements the KIST cell scheduler. + **/ + #define SCHEDULER_KIST_PRIVATE #include "core/or/or.h" diff --git a/src/core/or/scheduler_vanilla.c b/src/core/or/scheduler_vanilla.c index 33536ae04b..bd84a4e4ef 100644 --- a/src/core/or/scheduler_vanilla.c +++ b/src/core/or/scheduler_vanilla.c @@ -1,6 +1,11 @@ /* Copyright (c) 2017-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file scheduler_vanilla.c + * @brief "Vanilla" (pre-KIST) cell scheduler code. + **/ + #include "core/or/or.h" #include "app/config/config.h" #define TOR_CHANNEL_INTERNAL_ @@ -172,4 +177,3 @@ get_vanilla_scheduler(void) { return &vanilla_scheduler; } - diff --git a/src/core/or/server_port_cfg_st.h b/src/core/or/server_port_cfg_st.h index 0738735c61..c160576714 100644 --- a/src/core/or/server_port_cfg_st.h +++ b/src/core/or/server_port_cfg_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file server_port_cfg_st.h + * @brief Cnfiguration structure for server ports. + **/ + #ifndef SERVER_PORT_CFG_ST_H #define SERVER_PORT_CFG_ST_H @@ -17,4 +22,3 @@ struct server_port_cfg_t { }; #endif /* !defined(SERVER_PORT_CFG_ST_H) */ - diff --git a/src/core/or/socks_request_st.h b/src/core/or/socks_request_st.h index 9fb941ff7e..2931543ee2 100644 --- a/src/core/or/socks_request_st.h +++ b/src/core/or/socks_request_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file socks_request_st.h + * @brief Client request structure. + **/ + #ifndef SOCKS_REQUEST_ST_H #define SOCKS_REQUEST_ST_H diff --git a/src/core/or/status.h b/src/core/or/status.h index 3467501ebb..3568f39d6d 100644 --- a/src/core/or/status.h +++ b/src/core/or/status.h @@ -1,6 +1,11 @@ /* Copyright (c) 2010-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file status.h + * @brief Header for status.c + **/ + #ifndef TOR_STATUS_H #define TOR_STATUS_H @@ -15,4 +20,3 @@ STATIC char *bytes_to_usage(uint64_t bytes); #endif #endif /* !defined(TOR_STATUS_H) */ - diff --git a/src/core/or/tor_version_st.h b/src/core/or/tor_version_st.h index c5bdcaf07b..c3ef00b960 100644 --- a/src/core/or/tor_version_st.h +++ b/src/core/or/tor_version_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file tor_version_st.h + * @brief Parsed Tor version structure. + **/ + #ifndef TOR_VERSION_ST_H #define TOR_VERSION_ST_H @@ -29,4 +34,3 @@ struct tor_version_t { }; #endif /* !defined(TOR_VERSION_ST_H) */ - diff --git a/src/core/or/var_cell_st.h b/src/core/or/var_cell_st.h index 607c0d6c83..5c847202a9 100644 --- a/src/core/or/var_cell_st.h +++ b/src/core/or/var_cell_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file var_cell_st.h + * @brief Variable-length cell structure. + **/ + #ifndef VAR_CELL_ST_H #define VAR_CELL_ST_H @@ -20,4 +25,3 @@ struct var_cell_t { }; #endif /* !defined(VAR_CELL_ST_H) */ - diff --git a/src/core/proto/core_proto.dox b/src/core/proto/core_proto.dox new file mode 100644 index 0000000000..13ce751a76 --- /dev/null +++ b/src/core/proto/core_proto.dox @@ -0,0 +1,8 @@ +/** +@dir /core/proto +@brief core/proto: Protocol encoding/decoding + +These functions should (but do not always) exist at a lower level than most +of the rest of core. + +**/ diff --git a/src/core/proto/proto_cell.c b/src/core/proto/proto_cell.c index 697fed29e1..aed94b4ff1 100644 --- a/src/core/proto/proto_cell.c +++ b/src/core/proto/proto_cell.c @@ -4,6 +4,13 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file proto_cell.c + * @brief Decodes Tor cells from buffers. + **/ +/* Right now it only handles variable-length cells, but eventually + * we should refactor other cell-reading code into here. */ + #include "core/or/or.h" #include "lib/buf/buffers.h" #include "core/proto/proto_cell.h" @@ -83,4 +90,3 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto) *out = result; return 1; } - diff --git a/src/core/proto/proto_cell.h b/src/core/proto/proto_cell.h index 4f3982ea43..b5bfb09c49 100644 --- a/src/core/proto/proto_cell.h +++ b/src/core/proto/proto_cell.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file proto_cell.h + * @brief Header for proto_cell.c + **/ + #ifndef TOR_PROTO_CELL_H #define TOR_PROTO_CELL_H @@ -14,4 +19,3 @@ int fetch_var_cell_from_buf(struct buf_t *buf, struct var_cell_t **out, int linkproto); #endif /* !defined(TOR_PROTO_CELL_H) */ - diff --git a/src/core/proto/proto_control0.c b/src/core/proto/proto_control0.c index d741f28f09..3aa6a814f2 100644 --- a/src/core/proto/proto_control0.c +++ b/src/core/proto/proto_control0.c @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file proto_control0.c + * @brief Code to detect the obsolete v0 control protocol. + **/ + #include "core/or/or.h" #include "lib/buf/buffers.h" #include "core/proto/proto_control0.h" @@ -23,4 +28,3 @@ peek_buf_has_control0_command(buf_t *buf) } return 0; } - diff --git a/src/core/proto/proto_control0.h b/src/core/proto/proto_control0.h index 162e513a1b..ecb834bfba 100644 --- a/src/core/proto/proto_control0.h +++ b/src/core/proto/proto_control0.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file proto_control0.h + * @brief Header for proto_control0.c + **/ + #ifndef TOR_PROTO_CONTROL0_H #define TOR_PROTO_CONTROL0_H @@ -11,4 +16,3 @@ struct buf_t; int peek_buf_has_control0_command(struct buf_t *buf); #endif /* !defined(TOR_PROTO_CONTROL0_H) */ - diff --git a/src/core/proto/proto_ext_or.c b/src/core/proto/proto_ext_or.c index 4213bc14dd..db491e352d 100644 --- a/src/core/proto/proto_ext_or.c +++ b/src/core/proto/proto_ext_or.c @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file proto_ext_or.c + * @brief Parsing/encoding for the extended OR protocol. + **/ + #include "core/or/or.h" #include "lib/buf/buffers.h" #include "feature/relay/ext_orport.h" @@ -37,4 +42,3 @@ fetch_ext_or_command_from_buf(buf_t *buf, ext_or_cmd_t **out) buf_get_bytes(buf, (*out)->body, len); return 1; } - diff --git a/src/core/proto/proto_ext_or.h b/src/core/proto/proto_ext_or.h index b2bc64af85..de3fbdb814 100644 --- a/src/core/proto/proto_ext_or.h +++ b/src/core/proto/proto_ext_or.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file proto_ext_or.h + * @brief Header for proto_ext_or.c + **/ + #ifndef TOR_PROTO_EXT_OR_H #define TOR_PROTO_EXT_OR_H diff --git a/src/core/proto/proto_http.c b/src/core/proto/proto_http.c index 88c59ef561..2668bdcc7d 100644 --- a/src/core/proto/proto_http.c +++ b/src/core/proto/proto_http.c @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file proto_http.c + * @brief Parse a subset of the HTTP protocol. + **/ + #define PROTO_HTTP_PRIVATE #include "core/or/or.h" #include "lib/buf/buffers.h" @@ -168,4 +173,3 @@ buf_http_find_content_length(const char *headers, size_t headerlen, return ok ? 1 : -1; } - diff --git a/src/core/proto/proto_http.h b/src/core/proto/proto_http.h index cd70050205..6f38f99067 100644 --- a/src/core/proto/proto_http.h +++ b/src/core/proto/proto_http.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file proto_http.h + * @brief Header for proto_http.c + **/ + #ifndef TOR_PROTO_HTTP_H #define TOR_PROTO_HTTP_H @@ -21,4 +26,3 @@ STATIC int buf_http_find_content_length(const char *headers, size_t headerlen, #endif #endif /* !defined(TOR_PROTO_HTTP_H) */ - diff --git a/src/core/proto/proto_socks.c b/src/core/proto/proto_socks.c index b657a7b758..e48b373382 100644 --- a/src/core/proto/proto_socks.c +++ b/src/core/proto/proto_socks.c @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file proto_socks.c + * @brief Implementations for SOCKS4 and SOCKS5 protocols. + **/ + #include "core/or/or.h" #include "feature/client/addressmap.h" #include "lib/buf/buffers.h" @@ -105,7 +110,7 @@ socks_request_free_(socks_request_t *req) /** * Parse a single SOCKS4 request from buffer <b>raw_data</b> of length * <b>datalen</b> and update relevant fields of <b>req</b>. If SOCKS4a - * request is detected, set <b>*is_socks4a<b> to true. Set <b>*drain_out</b> + * request is detected, set <b>*is_socks4a</b> to true. Set <b>*drain_out</b> * to number of bytes we parsed so far. * * Return SOCKS_RESULT_DONE if parsing succeeded, SOCKS_RESULT_INVALID if diff --git a/src/core/proto/proto_socks.h b/src/core/proto/proto_socks.h index 2a387bf848..a29df92f64 100644 --- a/src/core/proto/proto_socks.h +++ b/src/core/proto/proto_socks.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file proto_socks.h + * @brief Header for proto_socks.c + **/ + #ifndef TOR_PROTO_SOCKS_H #define TOR_PROTO_SOCKS_H diff --git a/src/feature/api/feature_api.dox b/src/feature/api/feature_api.dox new file mode 100644 index 0000000000..06112120c3 --- /dev/null +++ b/src/feature/api/feature_api.dox @@ -0,0 +1,4 @@ +/** +@dir /feature/api +@brief feature/api: In-process interface to starting/stopping Tor. +**/ diff --git a/src/feature/api/tor_api_internal.h b/src/feature/api/tor_api_internal.h index 60e0f3aa59..115d33d58e 100644 --- a/src/feature/api/tor_api_internal.h +++ b/src/feature/api/tor_api_internal.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file tor_api_internal.h + * @brief Internal declarations for in-process Tor API. + **/ + #ifndef TOR_API_INTERNAL_H #define TOR_API_INTERNAL_H diff --git a/src/feature/client/addressmap.h b/src/feature/client/addressmap.h index 9179aef1d0..eb9742c50b 100644 --- a/src/feature/client/addressmap.h +++ b/src/feature/client/addressmap.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file addressmap.h + * @brief Header for addressmap.c + **/ + #ifndef TOR_ADDRESSMAP_H #define TOR_ADDRESSMAP_H @@ -62,4 +67,3 @@ STATIC void get_random_virtual_addr(const virtual_addr_conf_t *conf, #endif /* defined(ADDRESSMAP_PRIVATE) */ #endif /* !defined(TOR_ADDRESSMAP_H) */ - diff --git a/src/feature/client/entrynodes.c b/src/feature/client/entrynodes.c index 36b575ef20..8af8f14bb0 100644 --- a/src/feature/client/entrynodes.c +++ b/src/feature/client/entrynodes.c @@ -114,7 +114,7 @@ #include "core/or/or.h" #include "app/config/config.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "app/config/statefile.h" #include "core/mainloop/connection.h" #include "core/mainloop/mainloop.h" @@ -1038,7 +1038,7 @@ get_max_sample_size(guard_selection_t *gs, * Return a smartlist of the all the guards that are not currently * members of the sample (GUARDS - SAMPLED_GUARDS). The elements of * this list are node_t pointers in the non-bridge case, and - * bridge_info_t pointers in the bridge case. Set *<b>n_guards_out/b> + * bridge_info_t pointers in the bridge case. Set *<b>n_guards_out</b> * to the number of guards that we found in GUARDS, including those * that were already sampled. */ diff --git a/src/feature/client/feature_client.dox b/src/feature/client/feature_client.dox new file mode 100644 index 0000000000..a8263b494c --- /dev/null +++ b/src/feature/client/feature_client.dox @@ -0,0 +1,7 @@ +/** +@dir /feature/client +@brief feature/client: Client-specific code + +(There is also a bunch of client-specific code in other modules.) + +**/ diff --git a/src/feature/client/proxymode.c b/src/feature/client/proxymode.c new file mode 100644 index 0000000000..0682205336 --- /dev/null +++ b/src/feature/client/proxymode.c @@ -0,0 +1,32 @@ +/* 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 proxymode.c + * @brief Determine whether we are trying to be a proxy. + **/ + +#include "core/or/or.h" + +#include "app/config/config.h" +#include "core/mainloop/connection.h" +#include "core/or/port_cfg_st.h" +#include "feature/client/proxymode.h" + +/** Return true iff we are trying to proxy client connections. */ +int +proxy_mode(const or_options_t *options) +{ + (void)options; + SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) { + if (p->type == CONN_TYPE_AP_LISTENER || + p->type == CONN_TYPE_AP_TRANS_LISTENER || + p->type == CONN_TYPE_AP_DNS_LISTENER || + p->type == CONN_TYPE_AP_NATD_LISTENER) + return 1; + } SMARTLIST_FOREACH_END(p); + return 0; +} diff --git a/src/feature/client/proxymode.h b/src/feature/client/proxymode.h new file mode 100644 index 0000000000..770a519155 --- /dev/null +++ b/src/feature/client/proxymode.h @@ -0,0 +1,17 @@ +/* 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 proxymode.h + * \brief Header file for proxymode.c. + **/ + +#ifndef TOR_PROXYMODE_H +#define TOR_PROXYMODE_H + +int proxy_mode(const or_options_t *options); + +#endif /* !defined(TOR_PROXYMODE_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/control/control_cmd.c b/src/feature/control/control_cmd.c index de1bef7e59..e1a8292c9f 100644 --- a/src/feature/control/control_cmd.c +++ b/src/feature/control/control_cmd.c @@ -13,7 +13,7 @@ #include "core/or/or.h" #include "app/config/config.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "app/main/main.h" #include "core/mainloop/connection.h" #include "core/or/circuitbuild.h" @@ -590,7 +590,7 @@ control_setconf_helper(control_connection_t *conn, const unsigned flags = CAL_CLEAR_FIRST | (use_defaults ? CAL_USE_DEFAULTS : 0); - // We need a copy here, since confparse.c wants to canonicalize cases. + // We need a copy here, since confmgt.c wants to canonicalize cases. config_line_t *lines = config_lines_dup(args->kwargs); opt_err = options_trial_assign(lines, flags, &errstring); @@ -2248,6 +2248,7 @@ typedef struct control_cmd_def_t { */ #define CMD_FL_WIPE (1u<<0) +#ifndef COCCI /** Macro: declare a command with a one-line argument, a given set of flags, * and a syntax definition. **/ @@ -2280,6 +2281,7 @@ typedef struct control_cmd_def_t { 0, \ &obsolete_syntax, \ } +#endif /* !defined(COCCI) */ /** * An array defining all the recognized controller commands. diff --git a/src/feature/control/control_connection_st.h b/src/feature/control/control_connection_st.h index c9164f03b3..8ecce5ee69 100644 --- a/src/feature/control/control_connection_st.h +++ b/src/feature/control/control_connection_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file control_connection_st.h + * @brief Controller connection structure. + **/ + #ifndef CONTROL_CONNECTION_ST_H #define CONTROL_CONNECTION_ST_H diff --git a/src/feature/control/control_events.c b/src/feature/control/control_events.c index 82ea943999..12b73641b2 100644 --- a/src/feature/control/control_events.c +++ b/src/feature/control/control_events.c @@ -1653,13 +1653,17 @@ control_event_status(int type, int severity, const char *format, va_list args) log_warn(LD_BUG, "Format string too long."); return -1; } - tor_vasprintf(&user_buf, format, args); + if (tor_vasprintf(&user_buf, format, args)<0) { + log_warn(LD_BUG, "Failed to create user buffer."); + return -1; + } send_control_event(type, "%s %s\r\n", format_buf, user_buf); tor_free(user_buf); return 0; } +#ifndef COCCI #define CONTROL_EVENT_STATUS_BODY(event, sev) \ int r; \ do { \ @@ -1671,6 +1675,7 @@ control_event_status(int type, int severity, const char *format, va_list args) r = control_event_status((event), (sev), format, ap); \ va_end(ap); \ } while (0) +#endif /* !defined(COCCI) */ /** Format and send an EVENT_STATUS_GENERAL event whose main text is obtained * by formatting the arguments using the printf-style <b>format</b>. */ diff --git a/src/feature/control/control_getinfo.c b/src/feature/control/control_getinfo.c index 3e31bb9e8f..979fa4480d 100644 --- a/src/feature/control/control_getinfo.c +++ b/src/feature/control/control_getinfo.c @@ -325,6 +325,41 @@ getinfo_helper_current_time(control_connection_t *control_conn, return 0; } +/** GETINFO helper for dumping different consensus flavors + * returns: 0 on success -1 on error. */ +STATIC int +getinfo_helper_current_consensus(consensus_flavor_t flavor, + char** answer, + const char** errmsg) +{ + const char *flavor_name = networkstatus_get_flavor_name(flavor); + if (BUG(!strcmp(flavor_name, "??"))) { + *errmsg = "Internal error: unrecognized flavor name."; + return -1; + } + if (we_want_to_fetch_flavor(get_options(), flavor)) { + /** Check from the cache */ + const cached_dir_t *consensus = dirserv_get_consensus(flavor_name); + if (consensus) { + *answer = tor_strdup(consensus->dir); + } + } + if (!*answer) { /* try loading it from disk */ + + tor_mmap_t *mapped = networkstatus_map_cached_consensus(flavor_name); + if (mapped) { + *answer = tor_memdup_nulterm(mapped->data, mapped->size); + tor_munmap_file(mapped); + } + if (!*answer) { /* generate an error */ + *errmsg = "Could not open cached consensus. " + "Make sure FetchUselessDescriptors is set to 1."; + return -1; + } + } + return 0; +} + /** Implementation helper for GETINFO: knows the answers for questions about * directory information. */ STATIC int @@ -576,23 +611,18 @@ getinfo_helper_dir(control_connection_t *control_conn, smartlist_free(descs); } else if (!strcmpstart(question, "dir/status/")) { *answer = tor_strdup(""); - } else if (!strcmp(question, "dir/status-vote/current/consensus")) { /* v3 */ - if (we_want_to_fetch_flavor(get_options(), FLAV_NS)) { - const cached_dir_t *consensus = dirserv_get_consensus("ns"); - if (consensus) - *answer = tor_strdup(consensus->dir); + } else if (!strcmp(question, "dir/status-vote/current/consensus")) { + int consensus_result = getinfo_helper_current_consensus(FLAV_NS, + answer, errmsg); + if (consensus_result < 0) { + return -1; } - if (!*answer) { /* try loading it from disk */ - tor_mmap_t *mapped = networkstatus_map_cached_consensus("ns"); - if (mapped) { - *answer = tor_memdup_nulterm(mapped->data, mapped->size); - tor_munmap_file(mapped); - } - if (!*answer) { /* generate an error */ - *errmsg = "Could not open cached consensus. " - "Make sure FetchUselessDescriptors is set to 1."; - return -1; - } + } else if (!strcmp(question, + "dir/status-vote/current/consensus-microdesc")) { + int consensus_result = getinfo_helper_current_consensus(FLAV_MICRODESC, + answer, errmsg); + if (consensus_result < 0) { + return -1; } } else if (!strcmp(question, "network-status")) { /* v1 */ static int network_status_warned = 0; @@ -1513,6 +1543,8 @@ static const getinfo_item_t getinfo_items[] = { "v2 networkstatus docs as retrieved from a DirPort."), ITEM("dir/status-vote/current/consensus", dir, "v3 Networkstatus consensus as retrieved from a DirPort."), + ITEM("dir/status-vote/current/consensus-microdesc", dir, + "v3 Microdescriptor consensus as retrieved from a DirPort."), ITEM("exit-policy/default", policies, "The default value appended to the configured exit policy."), ITEM("exit-policy/reject-private/default", policies, diff --git a/src/feature/control/control_getinfo.h b/src/feature/control/control_getinfo.h index 52978686d8..86aaf7c4f7 100644 --- a/src/feature/control/control_getinfo.h +++ b/src/feature/control/control_getinfo.h @@ -48,6 +48,10 @@ STATIC int getinfo_helper_downloads( control_connection_t *control_conn, const char *question, char **answer, const char **errmsg); +STATIC int getinfo_helper_current_consensus( + consensus_flavor_t flavor, + char **answer, + const char **errmsg); STATIC int getinfo_helper_dir( control_connection_t *control_conn, const char *question, char **answer, diff --git a/src/feature/control/feature_control.dox b/src/feature/control/feature_control.dox new file mode 100644 index 0000000000..a0bf9413a1 --- /dev/null +++ b/src/feature/control/feature_control.dox @@ -0,0 +1,10 @@ +/** +@dir /feature/control +@brief feature/control: Controller API. + +The Controller API is a text-based protocol that another program (or another +thread, if you're running Tor in-process) can use to configure and control +Tor while it is running. The current protocol is documented in +[control-spec.txt](https://gitweb.torproject.org/torspec.git/tree/control-spec.txt). + +**/ diff --git a/src/feature/control/fmt_serverstatus.c b/src/feature/control/fmt_serverstatus.c index 33c5ba1336..92db70758f 100644 --- a/src/feature/control/fmt_serverstatus.c +++ b/src/feature/control/fmt_serverstatus.c @@ -3,6 +3,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file fmt_serverstatus.c + * @brief Format relay info for a controller. + **/ + #include "core/or/or.h" #include "feature/control/fmt_serverstatus.h" diff --git a/src/feature/control/getinfo_geoip.c b/src/feature/control/getinfo_geoip.c index d188725fa3..4636ede039 100644 --- a/src/feature/control/getinfo_geoip.c +++ b/src/feature/control/getinfo_geoip.c @@ -1,3 +1,12 @@ +/* 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 getinfo_geoip.c + * @brief GEOIP-related contoller GETINFO commands. + **/ #include "core/or/or.h" #include "core/mainloop/connection.h" diff --git a/src/feature/control/getinfo_geoip.h b/src/feature/control/getinfo_geoip.h index 94759d0d18..f6bc86cb53 100644 --- a/src/feature/control/getinfo_geoip.h +++ b/src/feature/control/getinfo_geoip.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file getinfo_geoip.h + * @brief Header for getinfo_geoip.c + **/ + #ifndef TOR_GETINFO_GEOIP_H #define TOR_GETINFO_GEOIP_H diff --git a/src/feature/dirauth/authmode.h b/src/feature/dirauth/authmode.h index bfd5f4dc04..11bc40d8d1 100644 --- a/src/feature/dirauth/authmode.h +++ b/src/feature/dirauth/authmode.h @@ -27,6 +27,7 @@ authdir_mode_v3(const or_options_t *options) return authdir_mode(options) && options->V3AuthoritativeDir != 0; } +/* Is the dirauth module enabled? */ #define have_module_dirauth() (1) #else /* !defined(HAVE_MODULE_DIRAUTH) */ diff --git a/src/feature/dirauth/bridgeauth.c b/src/feature/dirauth/bridgeauth.c index 4aaefc7a6d..56782011c2 100644 --- a/src/feature/dirauth/bridgeauth.c +++ b/src/feature/dirauth/bridgeauth.c @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file bridgeauth.c + * @brief Bridge authority code + **/ + #include "core/or/or.h" #include "feature/dirauth/bridgeauth.h" #include "feature/dirauth/voteflags.h" diff --git a/src/feature/dirauth/bridgeauth.h b/src/feature/dirauth/bridgeauth.h index 4905e9c3ee..76676e8db5 100644 --- a/src/feature/dirauth/bridgeauth.h +++ b/src/feature/dirauth/bridgeauth.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file bridgeauth.h + * @brief Header for bridgeauth.c + **/ + #ifndef TOR_DIRAUTH_BRIDGEAUTH_H #define TOR_DIRAUTH_BRIDGEAUTH_H 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 <b>old</b> to <b>new</b> + * affects the timing of the voting subsystem + */ +static int +options_transition_affects_dirauth_timing(const or_options_t *old_options, + const or_options_t *new_options) +{ + tor_assert(old_options); + tor_assert(new_options); + + if (authdir_mode_v3(old_options) != authdir_mode_v3(new_options)) + return 1; + if (! authdir_mode_v3(new_options)) + return 0; + + YES_IF_CHANGED_INT(V3AuthVotingInterval); + YES_IF_CHANGED_INT(V3AuthVoteDelay); + YES_IF_CHANGED_INT(V3AuthDistDelay); + YES_IF_CHANGED_INT(TestingV3AuthInitialVotingInterval); + YES_IF_CHANGED_INT(TestingV3AuthInitialVoteDelay); + YES_IF_CHANGED_INT(TestingV3AuthInitialDistDelay); + YES_IF_CHANGED_INT(TestingV3AuthVotingStartOffset); + + return 0; +} + +/** Fetch the active option list, and take dirauth actions based on it. All of + * the things we do should survive being done repeatedly. If present, + * <b>old_options</b> contains the previous value of the options. + * + * 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, + * <b>old_options</b> 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, <b>old_options</b> contains the previous value of the options. + * + * Sets <b>*print_notice_out</b> 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/dirauth/dirauth_periodic.c b/src/feature/dirauth/dirauth_periodic.c index 02727d61b4..96194b4677 100644 --- a/src/feature/dirauth/dirauth_periodic.c +++ b/src/feature/dirauth/dirauth_periodic.c @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file dirauth_periodic.c + * @brief Peridoic events for directory authorities. + **/ + #include "core/or/or.h" #include "app/config/or_options_st.h" @@ -18,11 +23,13 @@ #include "core/mainloop/periodic.h" +#ifndef COCCI #define DECLARE_EVENT(name, roles, flags) \ static periodic_event_item_t name ## _event = \ PERIODIC_EVENT(name, \ PERIODIC_EVENT_ROLE_##roles, \ flags) +#endif /* !defined(COCCI) */ #define FL(name) (PERIODIC_EVENT_FLAG_##name) diff --git a/src/feature/dirauth/dirauth_periodic.h b/src/feature/dirauth/dirauth_periodic.h index 866fbd35de..de4a799d37 100644 --- a/src/feature/dirauth/dirauth_periodic.h +++ b/src/feature/dirauth/dirauth_periodic.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file dirauth_periodic.h + * @brief Header for dirauth_periodic.c + **/ + #ifndef DIRVOTE_PERIODIC_H #define DIRVOTE_PERIODIC_H diff --git a/src/feature/dirauth/dirauth_sys.c b/src/feature/dirauth/dirauth_sys.c index e38d391300..090e9129f2 100644 --- a/src/feature/dirauth/dirauth_sys.c +++ b/src/feature/dirauth/dirauth_sys.c @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file dirauth_sys.c + * @brief Directory authority subsystem declarations + **/ + #include "core/or/or.h" #include "feature/dirauth/bwauth.h" diff --git a/src/feature/dirauth/dirauth_sys.h b/src/feature/dirauth/dirauth_sys.h index 4e9b6a2ab4..2d5a0cb3e7 100644 --- a/src/feature/dirauth/dirauth_sys.h +++ b/src/feature/dirauth/dirauth_sys.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file dirauth_sys.h + * @brief Header for dirauth_sys.c + **/ + #ifndef DIRAUTH_SYS_H #define DIRAUTH_SYS_H diff --git a/src/feature/dirauth/feature_dirauth.dox b/src/feature/dirauth/feature_dirauth.dox new file mode 100644 index 0000000000..9ee2d04589 --- /dev/null +++ b/src/feature/dirauth/feature_dirauth.dox @@ -0,0 +1,11 @@ +/** +@dir /feature/dirauth +@brief feature/dirauth: Directory authority implementation. + +This module handles running Tor as a directory authority. + +The directory protocol is specified in +[dir-spec.txt](https://gitweb.torproject.org/torspec.git/tree/dir-spec.txt). + + +**/ diff --git a/src/feature/dirauth/keypin.h b/src/feature/dirauth/keypin.h index 1de84f6d4a..d77f6fc5f3 100644 --- a/src/feature/dirauth/keypin.h +++ b/src/feature/dirauth/keypin.h @@ -1,6 +1,11 @@ /* Copyright (c) 2014-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file keypin.h + * @brief Header for keypin.c + **/ + #ifndef TOR_KEYPIN_H #define TOR_KEYPIN_H diff --git a/src/feature/dirauth/ns_detached_signatures_st.h b/src/feature/dirauth/ns_detached_signatures_st.h index 61d20b7525..7c50cda40a 100644 --- a/src/feature/dirauth/ns_detached_signatures_st.h +++ b/src/feature/dirauth/ns_detached_signatures_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file ns_detached_signatures_st.h + * @brief Detached consensus signatures structure. + **/ + #ifndef NS_DETACHED_SIGNATURES_ST_H #define NS_DETACHED_SIGNATURES_ST_H @@ -19,4 +24,3 @@ struct ns_detached_signatures_t { }; #endif /* !defined(NS_DETACHED_SIGNATURES_ST_H) */ - diff --git a/src/feature/dirauth/shared_random.c b/src/feature/dirauth/shared_random.c index a45f0a29c3..ebc595e517 100644 --- a/src/feature/dirauth/shared_random.c +++ b/src/feature/dirauth/shared_random.c @@ -90,7 +90,7 @@ #include "core/or/or.h" #include "feature/dirauth/shared_random.h" #include "app/config/config.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "lib/crypt_ops/crypto_rand.h" #include "lib/crypt_ops/crypto_util.h" #include "feature/nodelist/networkstatus.h" @@ -107,19 +107,19 @@ #include "feature/nodelist/authority_cert_st.h" #include "feature/nodelist/networkstatus_st.h" -/* String prefix of shared random values in votes/consensuses. */ +/** String prefix of shared random values in votes/consensuses. */ static const char previous_srv_str[] = "shared-rand-previous-value"; static const char current_srv_str[] = "shared-rand-current-value"; static const char commit_ns_str[] = "shared-rand-commit"; static const char sr_flag_ns_str[] = "shared-rand-participate"; -/* The value of the consensus param AuthDirNumSRVAgreements found in the +/** The value of the consensus param AuthDirNumSRVAgreements found in the * vote. This is set once the consensus creation subsystem requests the * SRV(s) that should be put in the consensus. We use this value to decide * if we keep or not an SRV. */ static int32_t num_srv_agreements_from_vote; -/* Return a heap allocated copy of the SRV <b>orig</b>. */ +/** Return a heap allocated copy of the SRV <b>orig</b>. */ sr_srv_t * sr_srv_dup(const sr_srv_t *orig) { @@ -135,7 +135,7 @@ sr_srv_dup(const sr_srv_t *orig) return duplicate; } -/* Allocate a new commit object and initializing it with <b>rsa_identity</b> +/** Allocate a new commit object and initializing it with <b>rsa_identity</b> * that MUST be provided. The digest algorithm is set to the default one * that is supported. The rest is uninitialized. This never returns NULL. */ static sr_commit_t * @@ -153,7 +153,7 @@ commit_new(const char *rsa_identity) return commit; } -/* Issue a log message describing <b>commit</b>. */ +/** Issue a log message describing <b>commit</b>. */ static void commit_log(const sr_commit_t *commit) { @@ -166,7 +166,7 @@ commit_log(const sr_commit_t *commit) commit->reveal_ts, safe_str(commit->encoded_reveal)); } -/* Make sure that the commitment and reveal information in <b>commit</b> +/** Make sure that the commitment and reveal information in <b>commit</b> * match. If they match return 0, return -1 otherwise. This function MUST be * used everytime we receive a new reveal value. Furthermore, the commit * object MUST have a reveal value and the hash of the reveal value. */ @@ -220,7 +220,7 @@ verify_commit_and_reveal(const sr_commit_t *commit) return -1; } -/* Return true iff the commit contains an encoded reveal value. */ +/** Return true iff the commit contains an encoded reveal value. */ STATIC int commit_has_reveal_value(const sr_commit_t *commit) { @@ -228,7 +228,7 @@ commit_has_reveal_value(const sr_commit_t *commit) sizeof(commit->encoded_reveal)); } -/* Parse the encoded commit. The format is: +/** Parse the encoded commit. The format is: * base64-encode( TIMESTAMP || H(REVEAL) ) * * If successfully decoded and parsed, commit is updated and 0 is returned. @@ -283,7 +283,7 @@ commit_decode(const char *encoded, sr_commit_t *commit) return -1; } -/* Parse the b64 blob at <b>encoded</b> containing reveal information and +/** Parse the b64 blob at <b>encoded</b> containing reveal information and * store the information in-place in <b>commit</b>. Return 0 on success else * a negative value. */ STATIC int @@ -333,7 +333,7 @@ reveal_decode(const char *encoded, sr_commit_t *commit) return -1; } -/* Encode a reveal element using a given commit object to dst which is a +/** Encode a reveal element using a given commit object to dst which is a * buffer large enough to put the base64-encoded reveal construction. The * format is as follow: * REVEAL = base64-encode( TIMESTAMP || H(RN) ) @@ -362,7 +362,7 @@ reveal_encode(const sr_commit_t *commit, char *dst, size_t len) return ret; } -/* Encode the given commit object to dst which is a buffer large enough to +/** Encode the given commit object to dst which is a buffer large enough to * put the base64-encoded commit. The format is as follow: * COMMIT = base64-encode( TIMESTAMP || H(H(RN)) ) * Return base64 encoded length on success else a negative value. @@ -388,14 +388,14 @@ commit_encode(const sr_commit_t *commit, char *dst, size_t len) return base64_encode(dst, len, buf, sizeof(buf), 0); } -/* Cleanup both our global state and disk state. */ +/** Cleanup both our global state and disk state. */ static void sr_cleanup(void) { sr_state_free_all(); } -/* Using <b>commit</b>, return a newly allocated string containing the commit +/** Using <b>commit</b>, return a newly allocated string containing the commit * information that should be used during SRV calculation. It's the caller * responsibility to free the memory. Return NULL if this is not a commit to be * used for SRV calculation. */ @@ -414,7 +414,7 @@ get_srv_element_from_commit(const sr_commit_t *commit) return element; } -/* Return a srv object that is built with the construction: +/** Return a srv object that is built with the construction: * SRV = SHA3-256("shared-random" | INT_8(reveal_num) | * INT_4(version) | HASHED_REVEALS | previous_SRV) * This function cannot fail. */ @@ -456,7 +456,7 @@ generate_srv(const char *hashed_reveals, uint64_t reveal_num, return srv; } -/* Compare reveal values and return the result. This should exclusively be +/** Compare reveal values and return the result. This should exclusively be * used by smartlist_sort(). */ static int compare_reveal_(const void **_a, const void **_b) @@ -466,7 +466,7 @@ compare_reveal_(const void **_a, const void **_b) sizeof(a->hashed_reveal)); } -/* Given <b>commit</b> give the line that we should place in our votes. +/** Given <b>commit</b> give the line that we should place in our votes. * It's the responsibility of the caller to free the string. */ static char * get_vote_line_from_commit(const sr_commit_t *commit, sr_phase_t phase) @@ -506,7 +506,7 @@ get_vote_line_from_commit(const sr_commit_t *commit, sr_phase_t phase) return vote_line; } -/* Return a heap allocated string that contains the given <b>srv</b> string +/** Return a heap allocated string that contains the given <b>srv</b> string * representation formatted for a networkstatus document using the * <b>key</b> as the start of the line. This doesn't return NULL. */ static char * @@ -524,7 +524,7 @@ srv_to_ns_string(const sr_srv_t *srv, const char *key) return srv_str; } -/* Given the previous SRV and the current SRV, return a heap allocated +/** Given the previous SRV and the current SRV, return a heap allocated * string with their data that could be put in a vote or a consensus. Caller * must free the returned string. Return NULL if no SRVs were provided. */ static char * @@ -557,7 +557,7 @@ get_ns_str_from_sr_values(const sr_srv_t *prev_srv, const sr_srv_t *cur_srv) return srv_str; } -/* Return 1 iff the two commits have the same commitment values. This +/** Return 1 iff the two commits have the same commitment values. This * function does not care about reveal values. */ STATIC int commitments_are_the_same(const sr_commit_t *commit_one, @@ -572,7 +572,7 @@ commitments_are_the_same(const sr_commit_t *commit_one, return 1; } -/* We just received a commit from the vote of authority with +/** We just received a commit from the vote of authority with * <b>identity_digest</b>. Return 1 if this commit is authorititative that * is, it belongs to the authority that voted it. Else return 0 if not. */ STATIC int @@ -586,7 +586,7 @@ commit_is_authoritative(const sr_commit_t *commit, sizeof(commit->rsa_identity)); } -/* Decide if the newly received <b>commit</b> should be kept depending on +/** Decide if the newly received <b>commit</b> should be kept depending on * the current phase and state of the protocol. The <b>voter_key</b> is the * RSA identity key fingerprint of the authority's vote from which the * commit comes from. The <b>phase</b> is the phase we should be validating @@ -705,7 +705,7 @@ should_keep_commit(const sr_commit_t *commit, const char *voter_key, return 0; } -/* We are in reveal phase and we found a valid and verified <b>commit</b> in +/** We are in reveal phase and we found a valid and verified <b>commit</b> in * a vote that contains reveal values that we could use. Update the commit * we have in our state. Never call this with an unverified commit. */ STATIC void @@ -726,7 +726,7 @@ save_commit_during_reveal_phase(const sr_commit_t *commit) sr_state_copy_reveal_info(saved_commit, commit); } -/* Save <b>commit</b> to our persistent state. Depending on the current +/** Save <b>commit</b> to our persistent state. Depending on the current * phase, different actions are taken. Steals reference of <b>commit</b>. * The commit object MUST be valid and verified before adding it to the * state. */ @@ -751,7 +751,7 @@ save_commit_to_state(sr_commit_t *commit) } } -/* Return 1 if we should we keep an SRV voted by <b>n_agreements</b> auths. +/** Return 1 if we should we keep an SRV voted by <b>n_agreements</b> auths. * Return 0 if we should ignore it. */ static int should_keep_srv(int n_agreements) @@ -781,7 +781,7 @@ should_keep_srv(int n_agreements) return 1; } -/* Helper: compare two DIGEST256_LEN digests. */ +/** Helper: compare two DIGEST256_LEN digests. */ static int compare_srvs_(const void **_a, const void **_b) { @@ -789,7 +789,7 @@ compare_srvs_(const void **_a, const void **_b) return tor_memcmp(a->value, b->value, sizeof(a->value)); } -/* Return the most frequent member of the sorted list of DIGEST256_LEN +/** Return the most frequent member of the sorted list of DIGEST256_LEN * digests in <b>sl</b> with the count of that most frequent element. */ static sr_srv_t * smartlist_get_most_frequent_srv(const smartlist_t *sl, int *count_out) @@ -806,7 +806,7 @@ compare_srv_(const void **_a, const void **_b) sizeof(a->value)); } -/* Using a list of <b>votes</b>, return the SRV object from them that has +/** Using a list of <b>votes</b>, return the SRV object from them that has * been voted by the majority of dirauths. If <b>current</b> is set, we look * for the current SRV value else the previous one. The returned pointer is * an object located inside a vote. NULL is returned if no appropriate value @@ -868,7 +868,7 @@ get_majority_srv_from_votes(const smartlist_t *votes, int current) return the_srv; } -/* Free a commit object. */ +/** Free a commit object. */ void sr_commit_free_(sr_commit_t *commit) { @@ -880,7 +880,7 @@ sr_commit_free_(sr_commit_t *commit) tor_free(commit); } -/* Generate the commitment/reveal value for the protocol run starting at +/** Generate the commitment/reveal value for the protocol run starting at * <b>timestamp</b>. <b>my_rsa_cert</b> is our authority RSA certificate. */ sr_commit_t * sr_generate_our_commit(time_t timestamp, const authority_cert_t *my_rsa_cert) @@ -937,7 +937,8 @@ sr_generate_our_commit(time_t timestamp, const authority_cert_t *my_rsa_cert) return NULL; } -/* Compute the shared random value based on the active commits in our state. */ +/** Compute the shared random value based on the active commits in our + * state. */ void sr_compute_srv(void) { @@ -1010,7 +1011,7 @@ sr_compute_srv(void) tor_free(reveals); } -/* Parse a commit from a vote or from our disk state and return a newly +/** Parse a commit from a vote or from our disk state and return a newly * allocated commit object. NULL is returned on error. * * The commit's data is in <b>args</b> and the order matters very much: @@ -1082,7 +1083,7 @@ sr_parse_commit(const smartlist_t *args) return NULL; } -/* Called when we are done parsing a vote by <b>voter_key</b> that might +/** Called when we are done parsing a vote by <b>voter_key</b> that might * contain some useful <b>commits</b>. Find if any of them should be kept * and update our state accordingly. Once done, the list of commitments will * be empty. */ @@ -1120,7 +1121,7 @@ sr_handle_received_commits(smartlist_t *commits, crypto_pk_t *voter_key) } SMARTLIST_FOREACH_END(commit); } -/* Return a heap-allocated string containing commits that should be put in +/** Return a heap-allocated string containing commits that should be put in * the votes. It's the responsibility of the caller to free the string. * This always return a valid string, either empty or with line(s). */ char * @@ -1178,7 +1179,7 @@ sr_get_string_for_vote(void) return vote_str; } -/* Return a heap-allocated string that should be put in the consensus and +/** Return a heap-allocated string that should be put in the consensus and * contains the shared randomness values. It's the responsibility of the * caller to free the string. NULL is returned if no SRV(s) available. * @@ -1222,7 +1223,7 @@ sr_get_string_for_consensus(const smartlist_t *votes, return NULL; } -/* We just computed a new <b>consensus</b>. Update our state with the SRVs +/** We just computed a new <b>consensus</b>. Update our state with the SRVs * from the consensus (might be NULL as well). Register the SRVs in our SR * state and prepare for the upcoming protocol round. */ void @@ -1261,7 +1262,7 @@ sr_act_post_consensus(const networkstatus_t *consensus) sr_state_update(voting_schedule_get_next_valid_after_time()); } -/* Initialize shared random subsystem. This MUST be called early in the boot +/** Initialize shared random subsystem. This MUST be called early in the boot * process of tor. Return 0 on success else -1 on error. */ int sr_init(int save_to_disk) @@ -1269,7 +1270,7 @@ sr_init(int save_to_disk) return sr_state_init(save_to_disk, 1); } -/* Save our state to disk and cleanup everything. */ +/** Save our state to disk and cleanup everything. */ void sr_save_and_cleanup(void) { @@ -1279,7 +1280,7 @@ sr_save_and_cleanup(void) #ifdef TOR_UNIT_TESTS -/* Set the global value of number of SRV agreements so the test can play +/** Set the global value of number of SRV agreements so the test can play * along by calling specific functions that don't parse the votes prior for * the AuthDirNumSRVAgreements value. */ void diff --git a/src/feature/dirauth/shared_random.h b/src/feature/dirauth/shared_random.h index 7ff9f15512..b3b4b3a2aa 100644 --- a/src/feature/dirauth/shared_random.h +++ b/src/feature/dirauth/shared_random.h @@ -4,83 +4,85 @@ #ifndef TOR_SHARED_RANDOM_H #define TOR_SHARED_RANDOM_H -/* - * This file contains ABI/API of the shared random protocol defined in +/** + * \file shared_random.h + * + * \brief This file contains ABI/API of the shared random protocol defined in * proposal #250. Every public functions and data structure are namespaced * with "sr_" which stands for shared random. */ #include "core/or/or.h" -/* Protocol version */ +/** Protocol version */ #define SR_PROTO_VERSION 1 -/* Default digest algorithm. */ +/** Default digest algorithm. */ #define SR_DIGEST_ALG DIGEST_SHA3_256 -/* Invariant token in the SRV calculation. */ +/** Invariant token in the SRV calculation. */ #define SR_SRV_TOKEN "shared-random" -/* Don't count the NUL terminated byte even though the TOKEN has it. */ +/** Don't count the NUL terminated byte even though the TOKEN has it. */ #define SR_SRV_TOKEN_LEN (sizeof(SR_SRV_TOKEN) - 1) -/* Length of the random number (in bytes). */ +/** Length of the random number (in bytes). */ #define SR_RANDOM_NUMBER_LEN 32 -/* Size of a decoded commit value in a vote or state. It's a hash and a +/** Size of a decoded commit value in a vote or state. It's a hash and a * timestamp. It adds up to 40 bytes. */ #define SR_COMMIT_LEN (sizeof(uint64_t) + DIGEST256_LEN) -/* Size of a decoded reveal value from a vote or state. It's a 64 bit +/** Size of a decoded reveal value from a vote or state. It's a 64 bit * timestamp and the hashed random number. This adds up to 40 bytes. */ #define SR_REVEAL_LEN (sizeof(uint64_t) + DIGEST256_LEN) -/* Size of SRV message length. The construction is has follow: +/** Size of SRV message length. The construction is has follow: * "shared-random" | INT_8(reveal_num) | INT_4(version) | PREV_SRV */ #define SR_SRV_MSG_LEN \ (SR_SRV_TOKEN_LEN + sizeof(uint64_t) + sizeof(uint32_t) + DIGEST256_LEN) -/* Length of base64 encoded commit NOT including the NUL terminated byte. +/** Length of base64 encoded commit NOT including the NUL terminated byte. * Formula is taken from base64_encode_size. This adds up to 56 bytes. */ #define SR_COMMIT_BASE64_LEN (BASE64_LEN(SR_COMMIT_LEN)) -/* Length of base64 encoded reveal NOT including the NUL terminated byte. +/** Length of base64 encoded reveal NOT including the NUL terminated byte. * Formula is taken from base64_encode_size. This adds up to 56 bytes. */ #define SR_REVEAL_BASE64_LEN (BASE64_LEN(SR_REVEAL_LEN)) -/* Length of base64 encoded shared random value. It's 32 bytes long so 44 +/** Length of base64 encoded shared random value. It's 32 bytes long so 44 * bytes from the base64_encode_size formula. That includes the '=' * character at the end. */ #define SR_SRV_VALUE_BASE64_LEN (BASE64_LEN(DIGEST256_LEN)) -/* Assert if commit valid flag is not set. */ +/** Assert if commit valid flag is not set. */ #define ASSERT_COMMIT_VALID(c) tor_assert((c)->valid) -/* Protocol phase. */ +/** Protocol phase. */ typedef enum { - /* Commitment phase */ + /** Commitment phase */ SR_PHASE_COMMIT = 1, - /* Reveal phase */ + /** Reveal phase */ SR_PHASE_REVEAL = 2, } sr_phase_t; -/* A shared random value (SRV). */ +/** A shared random value (SRV). */ typedef struct sr_srv_t { - /* The number of reveal values used to derive this SRV. */ + /** The number of reveal values used to derive this SRV. */ uint64_t num_reveals; - /* The actual value. This is the stored result of SHA3-256. */ + /** The actual value. This is the stored result of SHA3-256. */ uint8_t value[DIGEST256_LEN]; } sr_srv_t; -/* A commit (either ours or from another authority). */ +/** A commit (either ours or from another authority). */ typedef struct sr_commit_t { - /* Hashing algorithm used. */ + /** Hashing algorithm used. */ digest_algorithm_t alg; - /* Indicate if this commit has been verified thus valid. */ + /** Indicate if this commit has been verified thus valid. */ unsigned int valid:1; /* Commit owner info */ - /* The RSA identity key of the authority and its base16 representation, + /** The RSA identity key of the authority and its base16 representation, * which includes the NUL terminated byte. */ char rsa_identity[DIGEST_LEN]; char rsa_identity_hex[HEX_DIGEST_LEN + 1]; /* Commitment information */ - /* Timestamp of reveal. Correspond to TIMESTAMP. */ + /** Timestamp of reveal. Correspond to TIMESTAMP. */ uint64_t reveal_ts; /* H(REVEAL) as found in COMMIT message. */ char hashed_reveal[DIGEST256_LEN]; @@ -89,13 +91,13 @@ typedef struct sr_commit_t { /* Reveal information */ - /* H(RN) which is what we used as the random value for this commit. We + /** H(RN) which is what we used as the random value for this commit. We * don't use the raw bytes since those are sent on the network thus * avoiding possible information leaks of our PRNG. */ uint8_t random_number[SR_RANDOM_NUMBER_LEN]; - /* Timestamp of commit. Correspond to TIMESTAMP. */ + /** Timestamp of commit. Correspond to TIMESTAMP. */ uint64_t commit_ts; - /* This is the whole reveal message. We use it during verification */ + /** This is the whole reveal message. We use it during verification */ char encoded_reveal[SR_REVEAL_BASE64_LEN + 1]; } sr_commit_t; @@ -191,4 +193,3 @@ void set_num_srv_agreements(int32_t value); #endif /* TOR_UNIT_TESTS */ #endif /* !defined(TOR_SHARED_RANDOM_H) */ - diff --git a/src/feature/dirauth/shared_random_state.c b/src/feature/dirauth/shared_random_state.c index 76befb0f5f..759b3b8104 100644 --- a/src/feature/dirauth/shared_random_state.c +++ b/src/feature/dirauth/shared_random_state.c @@ -12,7 +12,7 @@ #include "core/or/or.h" #include "app/config/config.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "lib/crypt_ops/crypto_util.h" #include "feature/dirauth/dirvote.h" #include "feature/nodelist/networkstatus.h" @@ -26,18 +26,18 @@ #include "app/config/or_state_st.h" -/* Default filename of the shared random state on disk. */ +/** Default filename of the shared random state on disk. */ static const char default_fname[] = "sr-state"; -/* String representation of a protocol phase. */ +/** String representation of a protocol phase. */ static const char *phase_str[] = { "unknown", "commit", "reveal" }; -/* Our shared random protocol state. There is only one possible state per +/** Our shared random protocol state. There is only one possible state per * protocol run so this is the global state which is reset at every run once * the shared random value has been computed. */ static sr_state_t *sr_state = NULL; -/* Representation of our persistent state on disk. The sr_state above +/** Representation of our persistent state on disk. The sr_state above * contains the data parsed from this state. When we save to disk, we * translate the sr_state to this sr_disk_state. */ static sr_disk_state_t *sr_disk_state = NULL; @@ -56,14 +56,10 @@ DUMMY_TYPECHECK_INSTANCE(sr_disk_state_t); #define V(member,conftype,initvalue) \ VAR(#member, conftype, member, initvalue) -/* Our persistent state magic number. */ +/** Our persistent state magic number. */ #define SR_DISK_STATE_MAGIC 0x98AB1254 -static int -disk_state_validate_cb(void *old_state, void *state, void *default_state, - int from_setconf, char **msg); - -/* Array of variables that are saved to disk as a persistent state. */ +/** Array of variables that are saved to disk as a persistent state. */ static const config_var_t state_vars[] = { V(Version, POSINT, "0"), V(TorVersion, STRING, NULL), @@ -78,7 +74,7 @@ static const config_var_t state_vars[] = { END_OF_CONFIG_VARS }; -/* "Extra" variable in the state that receives lines we can't parse. This +/** "Extra" variable in the state that receives lines we can't parse. This * lets us preserve options from versions of Tor newer than us. */ static const struct_member_t state_extra_var = { .name = "__extra", @@ -86,24 +82,20 @@ static const struct_member_t state_extra_var = { .offset = offsetof(sr_disk_state_t, ExtraLines), }; -/* Configuration format of sr_disk_state_t. */ +/** Configuration format of sr_disk_state_t. */ static const config_format_t state_format = { - sizeof(sr_disk_state_t), - { + .size = sizeof(sr_disk_state_t), + .magic = { "sr_disk_state_t", SR_DISK_STATE_MAGIC, offsetof(sr_disk_state_t, magic_), }, - NULL, - NULL, - state_vars, - disk_state_validate_cb, - NULL, - &state_extra_var, - -1, + .vars = state_vars, + .extra = &state_extra_var, + .config_suite_offset = -1, }; -/* Global configuration manager for the shared-random state file */ +/** Global configuration manager for the shared-random state file */ static config_mgr_t *shared_random_state_mgr = NULL; /** Return the configuration manager for the shared-random state file. */ @@ -119,7 +111,7 @@ get_srs_mgr(void) static void state_query_del_(sr_state_object_t obj_type, void *data); -/* Return a string representation of a protocol phase. */ +/** Return a string representation of a protocol phase. */ STATIC const char * get_phase_str(sr_phase_t phase) { @@ -137,7 +129,7 @@ get_phase_str(sr_phase_t phase) return the_string; } -/* Return the time we should expire the state file created at <b>now</b>. +/** Return the time we should expire the state file created at <b>now</b>. * We expire the state file in the beginning of the next protocol run. */ STATIC time_t get_state_valid_until_time(time_t now) @@ -168,7 +160,7 @@ get_state_valid_until_time(time_t now) return valid_until; } -/* Given the consensus 'valid-after' time, return the protocol phase we should +/** Given the consensus 'valid-after' time, return the protocol phase we should * be in. */ STATIC sr_phase_t get_sr_protocol_phase(time_t valid_after) @@ -188,7 +180,7 @@ get_sr_protocol_phase(time_t valid_after) } } -/* Add the given <b>commit</b> to <b>state</b>. It MUST be a valid commit +/** Add the given <b>commit</b> to <b>state</b>. It MUST be a valid commit * and there shouldn't be a commit from the same authority in the state * already else verification hasn't been done prior. This takes ownership of * the commit once in our state. */ @@ -213,7 +205,7 @@ commit_add_to_state(sr_commit_t *commit, sr_state_t *state) } } -/* Helper: deallocate a commit object. (Used with digestmap_free(), which +/** Helper: deallocate a commit object. (Used with digestmap_free(), which * requires a function pointer whose argument is void *). */ static void commit_free_(void *p) @@ -224,7 +216,7 @@ commit_free_(void *p) #define state_free(val) \ FREE_AND_NULL(sr_state_t, state_free_, (val)) -/* Free a state that was allocated with state_new(). */ +/** Free a state that was allocated with state_new(). */ static void state_free_(sr_state_t *state) { @@ -238,7 +230,7 @@ state_free_(sr_state_t *state) tor_free(state); } -/* Allocate an sr_state_t object and returns it. If no <b>fname</b>, the +/** Allocate an sr_state_t object and returns it. If no <b>fname</b>, the * default file name is used. This function does NOT initialize the state * timestamp, phase or shared random value. NULL is never returned. */ static sr_state_t * @@ -257,7 +249,7 @@ state_new(const char *fname, time_t now) return new_state; } -/* Set our global state pointer with the one given. */ +/** Set our global state pointer with the one given. */ static void state_set(sr_state_t *state) { @@ -271,7 +263,7 @@ state_set(sr_state_t *state) #define disk_state_free(val) \ FREE_AND_NULL(sr_disk_state_t, disk_state_free_, (val)) -/* Free an allocated disk state. */ +/** Free an allocated disk state. */ static void disk_state_free_(sr_disk_state_t *state) { @@ -281,7 +273,7 @@ disk_state_free_(sr_disk_state_t *state) config_free(get_srs_mgr(), state); } -/* Allocate a new disk state, initialize it and return it. */ +/** Allocate a new disk state, initialize it and return it. */ static sr_disk_state_t * disk_state_new(time_t now) { @@ -297,7 +289,7 @@ disk_state_new(time_t now) return new_state; } -/* Set our global disk state with the given state. */ +/** Set our global disk state with the given state. */ static void disk_state_set(sr_disk_state_t *state) { @@ -308,7 +300,7 @@ disk_state_set(sr_disk_state_t *state) sr_disk_state = state; } -/* Return -1 if the disk state is invalid (something in there that we can't or +/** Return -1 if the disk state is invalid (something in there that we can't or * shouldn't use). Return 0 if everything checks out. */ static int disk_state_validate(const sr_disk_state_t *state) @@ -343,25 +335,7 @@ disk_state_validate(const sr_disk_state_t *state) return -1; } -/* Validate the disk state (NOP for now). */ -static int -disk_state_validate_cb(void *old_state, void *state, void *default_state, - int from_setconf, char **msg) -{ - /* We don't use these; only options do. */ - (void) from_setconf; - (void) default_state; - (void) old_state; - - /* This is called by config_dump which is just before we are about to - * write it to disk. At that point, our global memory state has been - * copied to the disk state so it's fair to assume it's trustable. */ - (void) state; - (void) msg; - return 0; -} - -/* Parse the Commit line(s) in the disk state and translate them to the +/** Parse the Commit line(s) in the disk state and translate them to the * the memory state. Return 0 on success else -1 on error. */ static int disk_state_parse_commits(sr_state_t *state, @@ -416,7 +390,7 @@ disk_state_parse_commits(sr_state_t *state, return -1; } -/* Parse a share random value line from the disk state and save it to dst +/** Parse a share random value line from the disk state and save it to dst * which is an allocated srv object. Return 0 on success else -1. */ static int disk_state_parse_srv(const char *value, sr_srv_t *dst) @@ -451,7 +425,7 @@ disk_state_parse_srv(const char *value, sr_srv_t *dst) return ret; } -/* Parse both SharedRandCurrentValue and SharedRandPreviousValue line from +/** Parse both SharedRandCurrentValue and SharedRandPreviousValue line from * the state. Return 0 on success else -1. */ static int disk_state_parse_sr_values(sr_state_t *state, @@ -502,7 +476,7 @@ disk_state_parse_sr_values(sr_state_t *state, return -1; } -/* Parse the given disk state and set a newly allocated state. On success, +/** Parse the given disk state and set a newly allocated state. On success, * return that state else NULL. */ static sr_state_t * disk_state_parse(const sr_disk_state_t *new_disk_state) @@ -536,7 +510,7 @@ disk_state_parse(const sr_disk_state_t *new_disk_state) return NULL; } -/* From a valid commit object and an allocated config line, set the line's +/** From a valid commit object and an allocated config line, set the line's * value to the state string representation of a commit. */ static void disk_state_put_commit_line(const sr_commit_t *commit, config_line_t *line) @@ -563,7 +537,7 @@ disk_state_put_commit_line(const sr_commit_t *commit, config_line_t *line) } } -/* From a valid srv object and an allocated config line, set the line's +/** From a valid srv object and an allocated config line, set the line's * value to the state string representation of a shared random value. */ static void disk_state_put_srv_line(const sr_srv_t *srv, config_line_t *line) @@ -581,7 +555,7 @@ disk_state_put_srv_line(const sr_srv_t *srv, config_line_t *line) tor_asprintf(&line->value, "%" PRIu64 " %s", srv->num_reveals, encoded); } -/* Reset disk state that is free allocated memory and zeroed the object. */ +/** Reset disk state that is free allocated memory and zeroed the object. */ static void disk_state_reset(void) { @@ -600,7 +574,7 @@ disk_state_reset(void) sr_disk_state->TorVersion = tor_strdup(get_version()); } -/* Update our disk state based on our global SR state. */ +/** Update our disk state based on our global SR state. */ static void disk_state_update(void) { @@ -644,7 +618,7 @@ disk_state_update(void) } DIGESTMAP_FOREACH_END; } -/* Load state from disk and put it into our disk state. If the state passes +/** Load state from disk and put it into our disk state. If the state passes * validation, our global state will be updated with it. Return 0 on * success. On error, -EINVAL is returned if the state on disk did contained * something malformed or is unreadable. -ENOENT is returned indicating that @@ -662,7 +636,7 @@ disk_state_load_from_disk(void) return ret; } -/* Helper for disk_state_load_from_disk(). */ +/** Helper for disk_state_load_from_disk(). */ STATIC int disk_state_load_from_disk_impl(const char *fname) { @@ -724,7 +698,7 @@ disk_state_load_from_disk_impl(const char *fname) return ret; } -/* Save the disk state to disk but before that update it from the current +/** Save the disk state to disk but before that update it from the current * state so we always have the latest. Return 0 on success else -1. */ static int disk_state_save_to_disk(void) @@ -768,7 +742,7 @@ disk_state_save_to_disk(void) return ret; } -/* Reset our state to prepare for a new protocol run. Once this returns, all +/** Reset our state to prepare for a new protocol run. Once this returns, all * commits in the state will be removed and freed. */ STATIC void reset_state_for_new_protocol_run(time_t valid_after) @@ -789,7 +763,7 @@ reset_state_for_new_protocol_run(time_t valid_after) sr_state_delete_commits(); } -/* This is the first round of the new protocol run starting at +/** This is the first round of the new protocol run starting at * <b>valid_after</b>. Do the necessary housekeeping. */ STATIC void new_protocol_run(time_t valid_after) @@ -823,7 +797,7 @@ new_protocol_run(time_t valid_after) } } -/* Return 1 iff the <b>next_phase</b> is a phase transition from the current +/** Return 1 iff the <b>next_phase</b> is a phase transition from the current * phase that is it's different. */ STATIC int is_phase_transition(sr_phase_t next_phase) @@ -831,7 +805,7 @@ is_phase_transition(sr_phase_t next_phase) return sr_state->phase != next_phase; } -/* Helper function: return a commit using the RSA fingerprint of the +/** Helper function: return a commit using the RSA fingerprint of the * authority or NULL if no such commit is known. */ static sr_commit_t * state_query_get_commit(const char *rsa_fpr) @@ -840,7 +814,7 @@ state_query_get_commit(const char *rsa_fpr) return digestmap_get(sr_state->commits, rsa_fpr); } -/* Helper function: This handles the GET state action using an +/** Helper function: This handles the GET state action using an * <b>obj_type</b> and <b>data</b> needed for the action. */ static void * state_query_get_(sr_state_object_t obj_type, const void *data) @@ -875,7 +849,7 @@ state_query_get_(sr_state_object_t obj_type, const void *data) return obj; } -/* Helper function: This handles the PUT state action using an +/** Helper function: This handles the PUT state action using an * <b>obj_type</b> and <b>data</b> needed for the action. * PUT frees the previous data before replacing it, if needed. */ static void @@ -928,7 +902,7 @@ state_query_put_(sr_state_object_t obj_type, void *data) } } -/* Helper function: This handles the DEL_ALL state action using an +/** Helper function: This handles the DEL_ALL state action using an * <b>obj_type</b> and <b>data</b> needed for the action. */ static void state_query_del_all_(sr_state_object_t obj_type) @@ -957,7 +931,7 @@ state_query_del_all_(sr_state_object_t obj_type) } } -/* Helper function: This handles the DEL state action using an +/** Helper function: This handles the DEL state action using an * <b>obj_type</b> and <b>data</b> needed for the action. */ static void state_query_del_(sr_state_object_t obj_type, void *data) @@ -983,7 +957,7 @@ state_query_del_(sr_state_object_t obj_type, void *data) } } -/* Query state using an <b>action</b> for an object type <b>obj_type</b>. +/** Query state using an <b>action</b> for an object type <b>obj_type</b>. * The <b>data</b> pointer needs to point to an object that the action needs * to use and if anything is required to be returned, it is stored in * <b>out</b>. @@ -1025,7 +999,7 @@ state_query(sr_state_action_t action, sr_state_object_t obj_type, } } -/* Delete the current SRV value from the state freeing it and the value is set +/** Delete the current SRV value from the state freeing it and the value is set * to NULL meaning empty. */ STATIC void state_del_current_srv(void) @@ -1033,7 +1007,7 @@ state_del_current_srv(void) state_query(SR_STATE_ACTION_DEL, SR_STATE_OBJ_CURSRV, NULL, NULL); } -/* Delete the previous SRV value from the state freeing it and the value is +/** Delete the previous SRV value from the state freeing it and the value is * set to NULL meaning empty. */ STATIC void state_del_previous_srv(void) @@ -1041,7 +1015,7 @@ state_del_previous_srv(void) state_query(SR_STATE_ACTION_DEL, SR_STATE_OBJ_PREVSRV, NULL, NULL); } -/* Rotate SRV value by setting the previous SRV to the current SRV, and +/** Rotate SRV value by setting the previous SRV to the current SRV, and * clearing the current SRV. */ STATIC void state_rotate_srv(void) @@ -1054,7 +1028,7 @@ state_rotate_srv(void) sr_state_set_current_srv(NULL); } -/* Set valid after time in the our state. */ +/** Set valid after time in the our state. */ void sr_state_set_valid_after(time_t valid_after) { @@ -1062,7 +1036,7 @@ sr_state_set_valid_after(time_t valid_after) (void *) &valid_after, NULL); } -/* Return the phase we are currently in according to our state. */ +/** Return the phase we are currently in according to our state. */ sr_phase_t sr_state_get_phase(void) { @@ -1071,7 +1045,7 @@ sr_state_get_phase(void) return *(sr_phase_t *) ptr; } -/* Return the previous SRV value from our state. Value CAN be NULL. +/** Return the previous SRV value from our state. Value CAN be NULL. * The state object owns the SRV, so the calling code should not free the SRV. * Use sr_srv_dup() if you want to keep a copy of the SRV. */ const sr_srv_t * @@ -1083,7 +1057,7 @@ sr_state_get_previous_srv(void) return srv; } -/* Set the current SRV value from our state. Value CAN be NULL. The srv +/** Set the current SRV value from our state. Value CAN be NULL. The srv * object ownership is transferred to the state object. */ void sr_state_set_previous_srv(const sr_srv_t *srv) @@ -1092,7 +1066,7 @@ sr_state_set_previous_srv(const sr_srv_t *srv) NULL); } -/* Return the current SRV value from our state. Value CAN be NULL. +/** Return the current SRV value from our state. Value CAN be NULL. * The state object owns the SRV, so the calling code should not free the SRV. * Use sr_srv_dup() if you want to keep a copy of the SRV. */ const sr_srv_t * @@ -1104,7 +1078,7 @@ sr_state_get_current_srv(void) return srv; } -/* Set the current SRV value from our state. Value CAN be NULL. The srv +/** Set the current SRV value from our state. Value CAN be NULL. The srv * object ownership is transferred to the state object. */ void sr_state_set_current_srv(const sr_srv_t *srv) @@ -1113,7 +1087,7 @@ sr_state_set_current_srv(const sr_srv_t *srv) NULL); } -/* Clean all the SRVs in our state. */ +/** Clean all the SRVs in our state. */ void sr_state_clean_srvs(void) { @@ -1122,7 +1096,7 @@ sr_state_clean_srvs(void) state_del_current_srv(); } -/* Return a pointer to the commits map from our state. CANNOT be NULL. */ +/** Return a pointer to the commits map from our state. CANNOT be NULL. */ digestmap_t * sr_state_get_commits(void) { @@ -1133,7 +1107,7 @@ sr_state_get_commits(void) return commits; } -/* Update the current SR state as needed for the upcoming voting round at +/** Update the current SR state as needed for the upcoming voting round at * <b>valid_after</b>. */ void sr_state_update(time_t valid_after) @@ -1197,7 +1171,7 @@ sr_state_update(time_t valid_after) } } -/* Return commit object from the given authority digest <b>rsa_identity</b>. +/** Return commit object from the given authority digest <b>rsa_identity</b>. * Return NULL if not found. */ sr_commit_t * sr_state_get_commit(const char *rsa_identity) @@ -1211,7 +1185,7 @@ sr_state_get_commit(const char *rsa_identity) return commit; } -/* Add <b>commit</b> to the permanent state. The commit object ownership is +/** Add <b>commit</b> to the permanent state. The commit object ownership is * transferred to the state so the caller MUST not free it. */ void sr_state_add_commit(sr_commit_t *commit) @@ -1226,14 +1200,14 @@ sr_state_add_commit(sr_commit_t *commit) sr_commit_get_rsa_fpr(commit)); } -/* Remove all commits from our state. */ +/** Remove all commits from our state. */ void sr_state_delete_commits(void) { state_query(SR_STATE_ACTION_DEL_ALL, SR_STATE_OBJ_COMMIT, NULL, NULL); } -/* Copy the reveal information from <b>commit</b> into <b>saved_commit</b>. +/** Copy the reveal information from <b>commit</b> into <b>saved_commit</b>. * This <b>saved_commit</b> MUST come from our current SR state. Once modified, * the disk state is updated. */ void @@ -1254,7 +1228,7 @@ sr_state_copy_reveal_info(sr_commit_t *saved_commit, const sr_commit_t *commit) sr_commit_get_rsa_fpr(saved_commit)); } -/* Set the fresh SRV flag from our state. This doesn't need to trigger a +/** Set the fresh SRV flag from our state. This doesn't need to trigger a * disk state synchronization so we directly change the state. */ void sr_state_set_fresh_srv(void) @@ -1262,7 +1236,7 @@ sr_state_set_fresh_srv(void) sr_state->is_srv_fresh = 1; } -/* Unset the fresh SRV flag from our state. This doesn't need to trigger a +/** Unset the fresh SRV flag from our state. This doesn't need to trigger a * disk state synchronization so we directly change the state. */ void sr_state_unset_fresh_srv(void) @@ -1270,14 +1244,14 @@ sr_state_unset_fresh_srv(void) sr_state->is_srv_fresh = 0; } -/* Return the value of the fresh SRV flag. */ +/** Return the value of the fresh SRV flag. */ unsigned int sr_state_srv_is_fresh(void) { return sr_state->is_srv_fresh; } -/* Cleanup and free our disk and memory state. */ +/** Cleanup and free our disk and memory state. */ void sr_state_free_all(void) { @@ -1289,7 +1263,7 @@ sr_state_free_all(void) config_mgr_free(shared_random_state_mgr); } -/* Save our current state in memory to disk. */ +/** Save our current state in memory to disk. */ void sr_state_save(void) { @@ -1297,7 +1271,7 @@ sr_state_save(void) state_query(SR_STATE_ACTION_SAVE, 0, NULL, NULL); } -/* Return 1 iff the state has been initialized that is it exists in memory. +/** Return 1 iff the state has been initialized that is it exists in memory. * Return 0 otherwise. */ int sr_state_is_initialized(void) @@ -1305,7 +1279,7 @@ sr_state_is_initialized(void) return sr_state == NULL ? 0 : 1; } -/* Initialize the disk and memory state. +/** Initialize the disk and memory state. * * If save_to_disk is set to 1, the state is immediately saved to disk after * creation else it's not thus only kept in memory. @@ -1368,7 +1342,7 @@ sr_state_init(int save_to_disk, int read_from_disk) #ifdef TOR_UNIT_TESTS -/* Set the current phase of the protocol. Used only by unit tests. */ +/** Set the current phase of the protocol. Used only by unit tests. */ void set_sr_phase(sr_phase_t phase) { @@ -1377,7 +1351,7 @@ set_sr_phase(sr_phase_t phase) sr_state->phase = phase; } -/* Get the SR state. Used only by unit tests */ +/** Get the SR state. Used only by unit tests */ sr_state_t * get_sr_state(void) { diff --git a/src/feature/dirauth/shared_random_state.h b/src/feature/dirauth/shared_random_state.h index 08f999f9d4..74792967a7 100644 --- a/src/feature/dirauth/shared_random_state.h +++ b/src/feature/dirauth/shared_random_state.h @@ -1,12 +1,17 @@ /* Copyright (c) 2016-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file shared_random_state.h + * @brief Header for shared_random_state.c + **/ + #ifndef TOR_SHARED_RANDOM_STATE_H #define TOR_SHARED_RANDOM_STATE_H #include "feature/dirauth/shared_random.h" -/* Action that can be performed on the state for any objects. */ +/** Action that can be performed on the state for any objects. */ typedef enum { SR_STATE_ACTION_GET = 1, SR_STATE_ACTION_PUT = 2, @@ -15,52 +20,53 @@ typedef enum { SR_STATE_ACTION_SAVE = 5, } sr_state_action_t; -/* Object in the state that can be queried through the state API. */ +/** Object in the state that can be queried through the state API. */ typedef enum { - /* Will return a single commit using an authority identity key. */ + /** Will return a single commit using an authority identity key. */ SR_STATE_OBJ_COMMIT, - /* Returns the entire list of commits from the state. */ + /** Returns the entire list of commits from the state. */ SR_STATE_OBJ_COMMITS, - /* Return the current SRV object pointer. */ + /** Return the current SRV object pointer. */ SR_STATE_OBJ_CURSRV, - /* Return the previous SRV object pointer. */ + /** Return the previous SRV object pointer. */ SR_STATE_OBJ_PREVSRV, - /* Return the phase. */ + /** Return the phase. */ SR_STATE_OBJ_PHASE, - /* Get or Put the valid after time. */ + /** Get or Put the valid after time. */ SR_STATE_OBJ_VALID_AFTER, } sr_state_object_t; -/* State of the protocol. It's also saved on disk in fname. This data +/** State of the protocol. It's also saved on disk in fname. This data * structure MUST be synchronized at all time with the one on disk. */ typedef struct sr_state_t { - /* Filename of the state file on disk. */ + /** Filename of the state file on disk. */ char *fname; - /* Version of the protocol. */ + /** Version of the protocol. */ uint32_t version; - /* The valid-after of the voting period we have prepared the state for. */ + /** The valid-after of the voting period we have prepared the state for. */ time_t valid_after; - /* Until when is this state valid? */ + /** Until when is this state valid? */ time_t valid_until; - /* Protocol phase. */ + /** Protocol phase. */ sr_phase_t phase; - /* Number of runs completed. */ + /** Number of runs completed. */ uint64_t n_protocol_runs; - /* The number of commitment rounds we've performed in this protocol run. */ + /** The number of commitment rounds we've performed in this protocol run. */ unsigned int n_commit_rounds; - /* The number of reveal rounds we've performed in this protocol run. */ + /** The number of reveal rounds we've performed in this protocol run. */ unsigned int n_reveal_rounds; - /* A map of all the received commitments for this protocol run. This is + /** A map of all the received commitments for this protocol run. This is * indexed by authority RSA identity digest. */ digestmap_t *commits; - /* Current and previous shared random value. */ + /** Current shared random value. */ sr_srv_t *previous_srv; + /** Previous shared random value. */ sr_srv_t *current_srv; - /* Indicate if the state contains an SRV that was _just_ generated. This is + /** Indicate if the state contains an SRV that was _just_ generated. This is * used during voting so that we know whether to use the super majority rule * or not when deciding on keeping it for the consensus. It is _always_ set * to 0 post consensus. @@ -73,22 +79,22 @@ typedef struct sr_state_t { unsigned int is_srv_fresh:1; } sr_state_t; -/* Persistent state of the protocol, as saved to disk. */ +/** Persistent state of the protocol, as saved to disk. */ typedef struct sr_disk_state_t { uint32_t magic_; - /* Version of the protocol. */ + /** Version of the protocol. */ int Version; - /* Version of our running tor. */ + /** Version of our running tor. */ char *TorVersion; - /* Creation time of this state */ + /** Creation time of this state */ time_t ValidAfter; - /* State valid until? */ + /** State valid until? */ time_t ValidUntil; - /* All commits seen that are valid. */ + /** All commits seen that are valid. */ struct config_line_t *Commit; - /* Previous and current shared random value. */ + /** Previous and current shared random value. */ struct config_line_t *SharedRandValues; - /* Extra Lines for configuration we might not know. */ + /** Extra Lines for configuration we might not know. */ struct config_line_t *ExtraLines; } sr_disk_state_t; diff --git a/src/feature/dirauth/vote_microdesc_hash_st.h b/src/feature/dirauth/vote_microdesc_hash_st.h index 7869f92b4f..24c7443b36 100644 --- a/src/feature/dirauth/vote_microdesc_hash_st.h +++ b/src/feature/dirauth/vote_microdesc_hash_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file vote_microdesc_hash_st.h + * @brief Microdescriptor-hash voting strcture. + **/ + #ifndef VOTE_MICRODESC_HASH_ST_H #define VOTE_MICRODESC_HASH_ST_H @@ -19,4 +24,3 @@ struct vote_microdesc_hash_t { }; #endif /* !defined(VOTE_MICRODESC_HASH_ST_H) */ - diff --git a/src/feature/dircache/cached_dir_st.h b/src/feature/dircache/cached_dir_st.h index a28802f905..e086f5b11d 100644 --- a/src/feature/dircache/cached_dir_st.h +++ b/src/feature/dircache/cached_dir_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file cached_dir_st.h + * @brief Cached large directory object structure. + **/ + #ifndef CACHED_DIR_ST_H #define CACHED_DIR_ST_H @@ -22,4 +27,3 @@ struct cached_dir_t { }; #endif /* !defined(CACHED_DIR_ST_H) */ - diff --git a/src/feature/dircache/conscache.c b/src/feature/dircache/conscache.c index 2ec9981c03..903fa5bc0a 100644 --- a/src/feature/dircache/conscache.c +++ b/src/feature/dircache/conscache.c @@ -1,6 +1,11 @@ /* Copyright (c) 2017-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file conscache.c + * @brief Consensus and diff on-disk cache. + **/ + #include "core/or/or.h" #include "app/config/config.h" @@ -246,7 +251,7 @@ consensus_cache_find_first(consensus_cache_t *cache, } /** - * Given a <b>cache</b>, add every entry to <b>out<b> for which + * Given a <b>cache</b>, add every entry to <b>out</b> for which * <b>key</b>=<b>value</b>. If <b>key</b> is NULL, add every entry. * * Do not add any entry that has been marked for removal. diff --git a/src/feature/dircache/conscache.h b/src/feature/dircache/conscache.h index d848e57617..54c081c068 100644 --- a/src/feature/dircache/conscache.h +++ b/src/feature/dircache/conscache.h @@ -1,6 +1,11 @@ /* Copyright (c) 2017-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file conscache.h + * @brief Header for conscache.c + **/ + #ifndef TOR_CONSCACHE_H #define TOR_CONSCACHE_H diff --git a/src/feature/dircache/consdiffmgr.c b/src/feature/dircache/consdiffmgr.c index 397efa0341..058ff1f500 100644 --- a/src/feature/dircache/consdiffmgr.c +++ b/src/feature/dircache/consdiffmgr.c @@ -2,7 +2,7 @@ /* See LICENSE for licensing information */ /** - * \file consdiffmsr.c + * \file consdiffmgr.c * * \brief consensus diff manager functions * @@ -1293,7 +1293,7 @@ typedef struct compressed_result_t { /** * Compress the bytestring <b>input</b> of length <b>len</b> using the - * <n>n_methods</b> compression methods listed in the array <b>methods</b>. + * <b>n_methods</b> compression methods listed in the array <b>methods</b>. * * For each successful compression, set the fields in the <b>results_out</b> * array in the position corresponding to the compression method. Use diff --git a/src/feature/dircache/consdiffmgr.h b/src/feature/dircache/consdiffmgr.h index b1b3323b6c..7222353650 100644 --- a/src/feature/dircache/consdiffmgr.h +++ b/src/feature/dircache/consdiffmgr.h @@ -1,6 +1,11 @@ /* Copyright (c) 2017-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file consdiffmgr.h + * @brief Header for consdiffmgr.c + **/ + #ifndef TOR_CONSDIFFMGR_H #define TOR_CONSDIFFMGR_H diff --git a/src/feature/dircache/dircache.c b/src/feature/dircache/dircache.c index d4d0ad9939..9938f9426c 100644 --- a/src/feature/dircache/dircache.c +++ b/src/feature/dircache/dircache.c @@ -3,6 +3,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file dircache.c + * @brief Cache directories and serve them to clients. + **/ + #define DIRCACHE_PRIVATE #include "core/or/or.h" @@ -23,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" @@ -473,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; @@ -560,7 +566,7 @@ parse_one_diff_hash(uint8_t *digest, const char *hex, const char *location, } /** If there is an X-Or-Diff-From-Consensus header included in <b>headers</b>, - * set <b>digest_out<b> to a new smartlist containing every 256-bit + * set <b>digest_out</b> to a new smartlist containing every 256-bit * hex-encoded digest listed in that header and return 0. Otherwise return * -1. */ static int @@ -1379,7 +1385,7 @@ handle_get_hs_descriptor_v2(dir_connection_t *conn, return 0; } -/** Helper function for GET /tor/hs/3/<z>. Only for version 3. +/** Helper function for GET `/tor/hs/3/...`. Only for version 3. */ STATIC int handle_get_hs_descriptor_v3(dir_connection_t *conn, diff --git a/src/feature/dircache/dirserv.c b/src/feature/dircache/dirserv.c index 79400bf15f..85331bfeaa 100644 --- a/src/feature/dircache/dirserv.c +++ b/src/feature/dircache/dirserv.c @@ -259,8 +259,8 @@ dirserv_set_cached_consensus_networkstatus(const char *networkstatus, /** Return the latest downloaded consensus networkstatus in encoded, signed, * optionally compressed format, suitable for sending to clients. */ -cached_dir_t * -dirserv_get_consensus(const char *flavor_name) +MOCK_IMPL(cached_dir_t *, +dirserv_get_consensus,(const char *flavor_name)) { if (!cached_consensuses) return NULL; diff --git a/src/feature/dircache/dirserv.h b/src/feature/dircache/dirserv.h index 7f944459da..0c15c9ad19 100644 --- a/src/feature/dircache/dirserv.h +++ b/src/feature/dircache/dirserv.h @@ -82,7 +82,7 @@ int directory_permits_begindir_requests(const or_options_t *options); int directory_too_idle_to_fetch_descriptors(const or_options_t *options, time_t now); -cached_dir_t *dirserv_get_consensus(const char *flavor_name); +MOCK_DECL(cached_dir_t *, dirserv_get_consensus, (const char *flavor_name)); void dirserv_set_cached_consensus_networkstatus(const char *consensus, size_t consensus_len, const char *flavor_name, diff --git a/src/feature/dircache/feature_dircache.dox b/src/feature/dircache/feature_dircache.dox new file mode 100644 index 0000000000..ef8a51aa9e --- /dev/null +++ b/src/feature/dircache/feature_dircache.dox @@ -0,0 +1,8 @@ +/** +@dir /feature/dircache +@brief feature/dircache: Run as a directory cache server + +This module handles the directory caching functionality that all relays may +provide, for serving cached directory objects to objects. + +**/ diff --git a/src/feature/dirclient/dir_server_st.h b/src/feature/dirclient/dir_server_st.h index 8e35532435..69c3856185 100644 --- a/src/feature/dirclient/dir_server_st.h +++ b/src/feature/dirclient/dir_server_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file dir_server_st.h + * @brief Trusted/fallback directory server structure. + **/ + #ifndef DIR_SERVER_ST_H #define DIR_SERVER_ST_H diff --git a/src/feature/dirclient/dirclient.c b/src/feature/dirclient/dirclient.c index 1ea50fd350..a97b425944 100644 --- a/src/feature/dirclient/dirclient.c +++ b/src/feature/dirclient/dirclient.c @@ -3,6 +3,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file dirclient.c + * @brief Download directory information + **/ + #define DIRCLIENT_PRIVATE #include "core/or/or.h" diff --git a/src/feature/dirclient/dlstatus.c b/src/feature/dirclient/dlstatus.c index 0842a2c676..c6fdbebed9 100644 --- a/src/feature/dirclient/dlstatus.c +++ b/src/feature/dirclient/dlstatus.c @@ -3,6 +3,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file dlstatus.c + * @brief Track status and retry schedule of a downloadable object. + **/ + #define DLSTATUS_PRIVATE #include "core/or/or.h" diff --git a/src/feature/dirclient/download_status_st.h b/src/feature/dirclient/download_status_st.h index 39a5ad2860..29d0dd5d5f 100644 --- a/src/feature/dirclient/download_status_st.h +++ b/src/feature/dirclient/download_status_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file download_status_st.h + * @brief Directory download status/schedule structure. + **/ + #ifndef DOWNLOAD_STATUS_ST_H #define DOWNLOAD_STATUS_ST_H @@ -62,4 +67,3 @@ struct download_status_t { }; #endif /* !defined(DOWNLOAD_STATUS_ST_H) */ - diff --git a/src/feature/dirclient/feature_dirclient.dox b/src/feature/dirclient/feature_dirclient.dox new file mode 100644 index 0000000000..0cbae69111 --- /dev/null +++ b/src/feature/dirclient/feature_dirclient.dox @@ -0,0 +1,9 @@ +/** +@dir /feature/dirclient +@brief feature/dirclient: Directory client implementation. + +The code here is used by all Tor instances that need to download directory +information. Currently, that is all of them, since even authorities need to +launch downloads to learn about relays that other authorities have listed. + +**/ diff --git a/src/feature/dircommon/consdiff.c b/src/feature/dircommon/consdiff.c index 8e93953f73..fbfa9e0c0a 100644 --- a/src/feature/dircommon/consdiff.c +++ b/src/feature/dircommon/consdiff.c @@ -530,10 +530,12 @@ typedef struct router_id_iterator_t { cdline_t hash; } router_id_iterator_t; +#ifndef COCCI /** * Initializer for a router_id_iterator_t. */ #define ROUTER_ID_ITERATOR_INIT { { NULL, 0 }, { NULL, 0 } } +#endif /* !defined(COCCI) */ /** Given an index *<b>idxp</b> into the consensus at <b>cons</b>, advance * the index to the next router line ("r ...") in the consensus, or to @@ -570,7 +572,7 @@ find_next_router_line(const smartlist_t *cons, /** Pre-process a consensus in <b>cons</b> (represented as a list of cdline_t) * to remove the signatures from it. If the footer is removed, return a * cdline_t containing a delete command to delete the footer, allocated in - * <b>area</>. If no footer is removed, return NULL. + * <b>area</b>. If no footer is removed, return NULL. * * We remove the signatures here because they are not themselves signed, and * as such there might be different encodings for them. diff --git a/src/feature/dircommon/consdiff.h b/src/feature/dircommon/consdiff.h index b63fcb2cc6..0e8c4b4d8e 100644 --- a/src/feature/dircommon/consdiff.h +++ b/src/feature/dircommon/consdiff.h @@ -2,6 +2,11 @@ * Copyright (c) 2014-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file consdiff.h + * @brief Header for consdiff.c + **/ + #ifndef TOR_CONSDIFF_H #define TOR_CONSDIFF_H diff --git a/src/feature/dircommon/dir_connection_st.h b/src/feature/dircommon/dir_connection_st.h index a858560c29..ba978e142a 100644 --- a/src/feature/dircommon/dir_connection_st.h +++ b/src/feature/dircommon/dir_connection_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file dir_connection_st.h + * @brief Client/server directory connection structure. + **/ + #ifndef DIR_CONNECTION_ST_H #define DIR_CONNECTION_ST_H diff --git a/src/feature/dircommon/feature_dircommon.dox b/src/feature/dircommon/feature_dircommon.dox new file mode 100644 index 0000000000..2d9866da01 --- /dev/null +++ b/src/feature/dircommon/feature_dircommon.dox @@ -0,0 +1,9 @@ +/** +@dir /feature/dircommon +@brief feature/dircommon: Directory client and server shared code + +This module has the code that directory clients (anybody who download +information about relays) and directory servers (anybody who serves such +information) share in common. + +**/ diff --git a/src/feature/dircommon/vote_timing_st.h b/src/feature/dircommon/vote_timing_st.h index 814a325314..352a69b2dd 100644 --- a/src/feature/dircommon/vote_timing_st.h +++ b/src/feature/dircommon/vote_timing_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file vote_timing_st.h + * @brief Directory voting schedule structure. + **/ + #ifndef VOTE_TIMING_ST_H #define VOTE_TIMING_ST_H @@ -21,4 +26,3 @@ struct vote_timing_t { }; #endif /* !defined(VOTE_TIMING_ST_H) */ - diff --git a/src/feature/dircommon/voting_schedule.h b/src/feature/dircommon/voting_schedule.h index d78c7ee2da..fd677fc836 100644 --- a/src/feature/dircommon/voting_schedule.h +++ b/src/feature/dircommon/voting_schedule.h @@ -26,15 +26,15 @@ typedef struct { /** When do we publish the consensus? */ time_t interval_starts; - /* True iff we have generated and distributed our vote. */ + /** True iff we have generated and distributed our vote. */ int have_voted; - /* True iff we've requested missing votes. */ + /** True iff we've requested missing votes. */ int have_fetched_missing_votes; - /* True iff we have built a consensus and sent the signatures around. */ + /** True iff we have built a consensus and sent the signatures around. */ int have_built_consensus; - /* True iff we've fetched missing signatures. */ + /** True iff we've fetched missing signatures. */ int have_fetched_missing_signatures; - /* True iff we have published our consensus. */ + /** True iff we have published our consensus. */ int have_published_consensus; /* True iff this voting schedule was set on demand meaning not through the @@ -62,4 +62,3 @@ time_t voting_schedule_get_start_of_next_interval(time_t now, time_t voting_schedule_get_next_valid_after_time(void); #endif /* !defined(TOR_VOTING_SCHEDULE_H) */ - diff --git a/src/feature/dirparse/authcert_members.h b/src/feature/dirparse/authcert_members.h new file mode 100644 index 0000000000..3b44c3eb02 --- /dev/null +++ b/src/feature/dirparse/authcert_members.h @@ -0,0 +1,29 @@ +/* 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 authcert_members.h + * + * @brief List of tokens common to V3 authority certificates and V3 + * consensuses. + **/ + +#ifndef TOR_AUTHCERT_MEMBERS_H +#define TOR_AUTHCERT_MEMBERS_H + +#define AUTHCERT_MEMBERS \ + T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \ + GE(1), NO_OBJ ), \ + T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\ + T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ),\ + T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ),\ + T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\ + T1("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),\ + T1("dir-key-certification", K_DIR_KEY_CERTIFICATION,\ + NO_ARGS, NEED_OBJ),\ + T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ) + +#endif /* !defined(TOR_AUTHCERT_MEMBERS_H) */ diff --git a/src/feature/dirparse/authcert_members.i b/src/feature/dirparse/authcert_members.i deleted file mode 100644 index 08cffca97a..0000000000 --- a/src/feature/dirparse/authcert_members.i +++ /dev/null @@ -1,13 +0,0 @@ -/* - * List of tokens common to V3 authority certificates and V3 consensuses. - */ - T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, - GE(1), NO_OBJ ), - T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ), - T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), - T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), - T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ), - T1("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ), - T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, - NO_ARGS, NEED_OBJ), - T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ), diff --git a/src/feature/dirparse/authcert_parse.c b/src/feature/dirparse/authcert_parse.c index 8ba5a53981..b18e1159f3 100644 --- a/src/feature/dirparse/authcert_parse.c +++ b/src/feature/dirparse/authcert_parse.c @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file authcert_parse.c + * @brief Authority certificate parsing. + **/ + #include "core/or/or.h" #include "feature/dirparse/authcert_parse.h" #include "feature/dirparse/parsecommon.h" @@ -13,10 +18,11 @@ #include "lib/memarea/memarea.h" #include "feature/nodelist/authority_cert_st.h" +#include "feature/dirparse/authcert_members.h" /** List of tokens recognized in V3 authority certificates. */ static token_rule_t dir_key_certificate_table[] = { -#include "feature/dirparse/authcert_members.i" + AUTHCERT_MEMBERS, T1("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ), END_OF_TABLE }; diff --git a/src/feature/dirparse/feature_dirparse.dox b/src/feature/dirparse/feature_dirparse.dox new file mode 100644 index 0000000000..4f2136b02b --- /dev/null +++ b/src/feature/dirparse/feature_dirparse.dox @@ -0,0 +1,10 @@ +/** +@dir /feature/dirparse +@brief feature/dirparse: Parsing Tor directory objects + +We define a number of "directory objects" in +[dir-spec.txt](https://gitweb.torproject.org/torspec.git/tree/dir-spec.txt), +all of them using a common line-oriented meta-format. This module is used by +other parts of Tor to parse them. + +**/ diff --git a/src/feature/dirparse/microdesc_parse.c b/src/feature/dirparse/microdesc_parse.c index 4bb4db7821..e526a355c1 100644 --- a/src/feature/dirparse/microdesc_parse.c +++ b/src/feature/dirparse/microdesc_parse.c @@ -164,7 +164,7 @@ microdesc_extract_body(microdesc_t *md, /** * Parse a microdescriptor which begins at <b>s</b> and ends at - * <b>start_of_next_microdesc. Store its fields into <b>md</b>. Use + * <b>start_of_next_microdesc</b>. Store its fields into <b>md</b>. Use * <b>where</b> for generating log information. If <b>allow_annotations</b> * is true, then one or more annotations may precede the microdescriptor body * proper. Use <b>area</b> for memory management, clearing it when done. diff --git a/src/feature/dirparse/ns_parse.c b/src/feature/dirparse/ns_parse.c index d5405e6464..4bb5798094 100644 --- a/src/feature/dirparse/ns_parse.c +++ b/src/feature/dirparse/ns_parse.c @@ -36,6 +36,7 @@ #include "feature/nodelist/networkstatus_st.h" #include "feature/nodelist/networkstatus_voter_info_st.h" #include "feature/nodelist/vote_routerstatus_st.h" +#include "feature/dirparse/authcert_members.h" #undef log #include <math.h> @@ -84,7 +85,7 @@ static token_rule_t networkstatus_token_table[] = { T01("required-relay-protocols", K_REQUIRED_RELAY_PROTOCOLS, CONCAT_ARGS, NO_OBJ ), -#include "feature/dirparse/authcert_members.i" + AUTHCERT_MEMBERS, T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ), T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ), diff --git a/src/feature/dirparse/unparseable.c b/src/feature/dirparse/unparseable.c index 941b5a1f6d..3b96df9e30 100644 --- a/src/feature/dirparse/unparseable.c +++ b/src/feature/dirparse/unparseable.c @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file unparseable.c + * @brief Dump unparseable objects to disk. + **/ + #define UNPARSEABLE_PRIVATE #include "core/or/or.h" diff --git a/src/feature/feature.dox b/src/feature/feature.dox new file mode 100644 index 0000000000..03759f9a17 --- /dev/null +++ b/src/feature/feature.dox @@ -0,0 +1,9 @@ +/** +@dir /feature +@brief feature: domain-specific modules + +The "feature" directory has modules that Tor uses only for a particular +role or service, such as maintaining/using an onion service, operating as a +relay or a client, or being a directory authority. + +**/ diff --git a/src/feature/hibernate/feature_hibernate.dox b/src/feature/hibernate/feature_hibernate.dox new file mode 100644 index 0000000000..eebb2d51a2 --- /dev/null +++ b/src/feature/hibernate/feature_hibernate.dox @@ -0,0 +1,16 @@ +/** +@dir /feature/hibernate +@brief feature/hibernate: Bandwidth accounting and hibernation (!) + +This module implements two features that are only somewhat related, and +should probably be separated in the future. One feature is bandwidth +accounting (making sure we use no more than so many gigabytes in a day) and +hibernation (avoiding network activity while we have used up all/most of our +configured gigabytes). The other feature is clean shutdown, where we stop +accepting new connections for a while and give the old ones time to close. + +The two features are related only in the sense that "soft hibernation" (being +almost out of ) is very close to the "shutting down" state. But it would be +better in the long run to make the two completely separate. + +**/ diff --git a/src/feature/hs/feature_hs.dox b/src/feature/hs/feature_hs.dox new file mode 100644 index 0000000000..32f44d57fb --- /dev/null +++ b/src/feature/hs/feature_hs.dox @@ -0,0 +1,10 @@ +/** +@dir /feature/hs +@brief feature/hs: v3 (current) onion service protocol + +This directory implements the v3 onion service protocol, +as specified in +[rend-spec-v3.txt](https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt). + + +**/ diff --git a/src/feature/hs/hs_cache.c b/src/feature/hs/hs_cache.c index 9817113b23..395839fce0 100644 --- a/src/feature/hs/hs_cache.c +++ b/src/feature/hs/hs_cache.c @@ -29,10 +29,10 @@ static int cached_client_descriptor_has_expired(time_t now, /********************** Directory HS cache ******************/ -/* Directory descriptor cache. Map indexed by blinded key. */ +/** Directory descriptor cache. Map indexed by blinded key. */ static digest256map_t *hs_cache_v3_dir; -/* Remove a given descriptor from our cache. */ +/** Remove a given descriptor from our cache. */ static void remove_v3_desc_as_dir(const hs_cache_dir_descriptor_t *desc) { @@ -40,7 +40,7 @@ remove_v3_desc_as_dir(const hs_cache_dir_descriptor_t *desc) digest256map_remove(hs_cache_v3_dir, desc->key); } -/* Store a given descriptor in our cache. */ +/** Store a given descriptor in our cache. */ static void store_v3_desc_as_dir(hs_cache_dir_descriptor_t *desc) { @@ -48,7 +48,7 @@ store_v3_desc_as_dir(hs_cache_dir_descriptor_t *desc) digest256map_set(hs_cache_v3_dir, desc->key, desc); } -/* Query our cache and return the entry or NULL if not found. */ +/** Query our cache and return the entry or NULL if not found. */ static hs_cache_dir_descriptor_t * lookup_v3_desc_as_dir(const uint8_t *key) { @@ -59,7 +59,7 @@ lookup_v3_desc_as_dir(const uint8_t *key) #define cache_dir_desc_free(val) \ FREE_AND_NULL(hs_cache_dir_descriptor_t, cache_dir_desc_free_, (val)) -/* Free a directory descriptor object. */ +/** Free a directory descriptor object. */ static void cache_dir_desc_free_(hs_cache_dir_descriptor_t *desc) { @@ -71,7 +71,7 @@ cache_dir_desc_free_(hs_cache_dir_descriptor_t *desc) tor_free(desc); } -/* Helper function: Use by the free all function using the digest256map +/** Helper function: Use by the free all function using the digest256map * interface to cache entries. */ static void cache_dir_desc_free_void(void *ptr) @@ -79,7 +79,7 @@ cache_dir_desc_free_void(void *ptr) cache_dir_desc_free_(ptr); } -/* Create a new directory cache descriptor object from a encoded descriptor. +/** Create a new directory cache descriptor object from a encoded descriptor. * On success, return the heap-allocated cache object, otherwise return NULL if * we can't decode the descriptor. */ static hs_cache_dir_descriptor_t * @@ -109,7 +109,7 @@ cache_dir_desc_new(const char *desc) return NULL; } -/* Return the size of a cache entry in bytes. */ +/** Return the size of a cache entry in bytes. */ static size_t cache_get_dir_entry_size(const hs_cache_dir_descriptor_t *entry) { @@ -117,7 +117,7 @@ cache_get_dir_entry_size(const hs_cache_dir_descriptor_t *entry) + strlen(entry->encoded_desc)); } -/* Try to store a valid version 3 descriptor in the directory cache. Return 0 +/** Try to store a valid version 3 descriptor in the directory cache. Return 0 * on success else a negative value is returned indicating that we have a * newer version in our cache. On error, caller is responsible to free the * given descriptor desc. */ @@ -167,7 +167,7 @@ cache_store_v3_as_dir(hs_cache_dir_descriptor_t *desc) return -1; } -/* Using the query which is the base64 encoded blinded key of a version 3 +/** Using the query which is the base64 encoded blinded key of a version 3 * descriptor, lookup in our directory cache the entry. If found, 1 is * returned and desc_out is populated with a newly allocated string being the * encoded descriptor. If not found, 0 is returned and desc_out is untouched. @@ -202,7 +202,7 @@ cache_lookup_v3_as_dir(const char *query, const char **desc_out) return -1; } -/* Clean the v3 cache by removing any entry that has expired using the +/** Clean the v3 cache by removing any entry that has expired using the * <b>global_cutoff</b> value. If <b>global_cutoff</b> is 0, the cleaning * process will use the lifetime found in the plaintext data section. Return * the number of bytes cleaned. */ @@ -252,7 +252,7 @@ cache_clean_v3_as_dir(time_t now, time_t global_cutoff) return bytes_removed; } -/* Given an encoded descriptor, store it in the directory cache depending on +/** Given an encoded descriptor, store it in the directory cache depending on * which version it is. Return a negative value on error. On success, 0 is * returned. */ int @@ -287,7 +287,7 @@ hs_cache_store_as_dir(const char *desc) return -1; } -/* Using the query, lookup in our directory cache the entry. If found, 1 is +/** Using the query, lookup in our directory cache the entry. If found, 1 is * returned and desc_out is populated with a newly allocated string being * the encoded descriptor. If not found, 0 is returned and desc_out is * untouched. On error, a negative value is returned and desc_out is @@ -312,7 +312,7 @@ hs_cache_lookup_as_dir(uint32_t version, const char *query, return found; } -/* Clean all directory caches using the current time now. */ +/** Clean all directory caches using the current time now. */ void hs_cache_clean_as_dir(time_t now) { @@ -329,15 +329,15 @@ hs_cache_clean_as_dir(time_t now) /********************** Client-side HS cache ******************/ -/* Client-side HS descriptor cache. Map indexed by service identity key. */ +/** Client-side HS descriptor cache. Map indexed by service identity key. */ static digest256map_t *hs_cache_v3_client; -/* Client-side introduction point state cache. Map indexed by service public +/** Client-side introduction point state cache. Map indexed by service public * identity key (onion address). It contains hs_cache_client_intro_state_t * objects all related to a specific service. */ static digest256map_t *hs_cache_client_intro_state; -/* Return the size of a client cache entry in bytes. */ +/** Return the size of a client cache entry in bytes. */ static size_t cache_get_client_entry_size(const hs_cache_client_descriptor_t *entry) { @@ -345,7 +345,7 @@ cache_get_client_entry_size(const hs_cache_client_descriptor_t *entry) strlen(entry->encoded_desc) + hs_desc_obj_size(entry->desc); } -/* Remove a given descriptor from our cache. */ +/** Remove a given descriptor from our cache. */ static void remove_v3_desc_as_client(const hs_cache_client_descriptor_t *desc) { @@ -355,7 +355,7 @@ remove_v3_desc_as_client(const hs_cache_client_descriptor_t *desc) rend_cache_decrement_allocation(cache_get_client_entry_size(desc)); } -/* Store a given descriptor in our cache. */ +/** Store a given descriptor in our cache. */ static void store_v3_desc_as_client(hs_cache_client_descriptor_t *desc) { @@ -365,7 +365,7 @@ store_v3_desc_as_client(hs_cache_client_descriptor_t *desc) rend_cache_increment_allocation(cache_get_client_entry_size(desc)); } -/* Query our cache and return the entry or NULL if not found or if expired. */ +/** Query our cache and return the entry or NULL if not found or if expired. */ STATIC hs_cache_client_descriptor_t * lookup_v3_desc_as_client(const uint8_t *key) { @@ -388,8 +388,8 @@ lookup_v3_desc_as_client(const uint8_t *key) return cached_desc; } -/* Parse the encoded descriptor in <b>desc_str</b> using - * <b>service_identity_pk<b> to decrypt it first. +/** Parse the encoded descriptor in <b>desc_str</b> using + * <b>service_identity_pk</b> to decrypt it first. * * If everything goes well, allocate and return a new * hs_cache_client_descriptor_t object. In case of error, return NULL. */ @@ -448,7 +448,7 @@ cache_client_desc_free_void(void *ptr) cache_client_desc_free(desc); } -/* Return a newly allocated and initialized hs_cache_intro_state_t object. */ +/** Return a newly allocated and initialized hs_cache_intro_state_t object. */ static hs_cache_intro_state_t * cache_intro_state_new(void) { @@ -460,21 +460,21 @@ cache_intro_state_new(void) #define cache_intro_state_free(val) \ FREE_AND_NULL(hs_cache_intro_state_t, cache_intro_state_free_, (val)) -/* Free an hs_cache_intro_state_t object. */ +/** Free an hs_cache_intro_state_t object. */ static void cache_intro_state_free_(hs_cache_intro_state_t *state) { tor_free(state); } -/* Helper function: used by the free all function. */ +/** Helper function: used by the free all function. */ static void cache_intro_state_free_void(void *state) { cache_intro_state_free_(state); } -/* Return a newly allocated and initialized hs_cache_client_intro_state_t +/** Return a newly allocated and initialized hs_cache_client_intro_state_t * object. */ static hs_cache_client_intro_state_t * cache_client_intro_state_new(void) @@ -488,7 +488,7 @@ cache_client_intro_state_new(void) FREE_AND_NULL(hs_cache_client_intro_state_t, \ cache_client_intro_state_free_, (val)) -/* Free a cache_client_intro_state object. */ +/** Free a cache_client_intro_state object. */ static void cache_client_intro_state_free_(hs_cache_client_intro_state_t *cache) { @@ -499,14 +499,14 @@ cache_client_intro_state_free_(hs_cache_client_intro_state_t *cache) tor_free(cache); } -/* Helper function: used by the free all function. */ +/** Helper function: used by the free all function. */ static void cache_client_intro_state_free_void(void *entry) { cache_client_intro_state_free_(entry); } -/* For the given service identity key service_pk and an introduction +/** For the given service identity key service_pk and an introduction * authentication key auth_key, lookup the intro state object. Return 1 if * found and put it in entry if not NULL. Return 0 if not found and entry is * untouched. */ @@ -541,7 +541,7 @@ cache_client_intro_state_lookup(const ed25519_public_key_t *service_pk, return 0; } -/* Note the given failure in state. */ +/** Note the given failure in state. */ static void cache_client_intro_state_note(hs_cache_intro_state_t *state, rend_intro_point_failure_t failure) @@ -563,7 +563,7 @@ cache_client_intro_state_note(hs_cache_intro_state_t *state, } } -/* For the given service identity key service_pk and an introduction +/** For the given service identity key service_pk and an introduction * authentication key auth_key, add an entry in the client intro state cache * If no entry exists for the service, it will create one. If state is non * NULL, it will point to the new intro state entry. */ @@ -597,7 +597,7 @@ cache_client_intro_state_add(const ed25519_public_key_t *service_pk, } } -/* Remove every intro point state entry from cache that has been created +/** Remove every intro point state entry from cache that has been created * before or at the cutoff. */ static void cache_client_intro_state_clean(time_t cutoff, @@ -614,7 +614,7 @@ cache_client_intro_state_clean(time_t cutoff, } DIGEST256MAP_FOREACH_END; } -/* Return true iff no intro points are in this cache. */ +/** Return true iff no intro points are in this cache. */ static int cache_client_intro_state_is_empty(const hs_cache_client_intro_state_t *cache) { @@ -664,7 +664,7 @@ cache_store_as_client(hs_cache_client_descriptor_t *client_desc) return 0; } -/* Return true iff the cached client descriptor at <b>cached_desc</b has +/** Return true iff the cached client descriptor at <b>cached_desc</b> has * expired. */ static int cached_client_descriptor_has_expired(time_t now, @@ -687,7 +687,7 @@ cached_client_descriptor_has_expired(time_t now, return 0; } -/* clean the client cache using now as the current time. Return the total size +/** clean the client cache using now as the current time. Return the total size * of removed bytes from the cache. */ static size_t cache_clean_v3_as_client(time_t now) @@ -800,7 +800,7 @@ hs_cache_store_as_client(const char *desc_str, return -1; } -/* Clean all client caches using the current time now. */ +/** Clean all client caches using the current time now. */ void hs_cache_clean_as_client(time_t now) { @@ -811,7 +811,7 @@ hs_cache_clean_as_client(time_t now) cache_clean_v3_as_client(now); } -/* Purge the client descriptor cache. */ +/** Purge the client descriptor cache. */ void hs_cache_purge_as_client(void) { @@ -828,7 +828,7 @@ hs_cache_purge_as_client(void) log_info(LD_REND, "Hidden service client descriptor cache purged."); } -/* For a given service identity public key and an introduction authentication +/** For a given service identity public key and an introduction authentication * key, note the given failure in the client intro state cache. */ void hs_cache_client_intro_state_note(const ed25519_public_key_t *service_pk, @@ -850,7 +850,7 @@ hs_cache_client_intro_state_note(const ed25519_public_key_t *service_pk, cache_client_intro_state_note(entry, failure); } -/* For a given service identity public key and an introduction authentication +/** For a given service identity public key and an introduction authentication * key, return true iff it is present in the failure cache. */ const hs_cache_intro_state_t * hs_cache_client_intro_state_find(const ed25519_public_key_t *service_pk, @@ -861,7 +861,7 @@ hs_cache_client_intro_state_find(const ed25519_public_key_t *service_pk, return state; } -/* Cleanup the client introduction state cache. */ +/** Cleanup the client introduction state cache. */ void hs_cache_client_intro_state_clean(time_t now) { @@ -881,7 +881,7 @@ hs_cache_client_intro_state_clean(time_t now) } DIGEST256MAP_FOREACH_END; } -/* Purge the client introduction state cache. */ +/** Purge the client introduction state cache. */ void hs_cache_client_intro_state_purge(void) { @@ -897,7 +897,7 @@ hs_cache_client_intro_state_purge(void) /**************** Generics *********************************/ -/* Do a round of OOM cleanup on all directory caches. Return the amount of +/** Do a round of OOM cleanup on all directory caches. Return the amount of * removed bytes. It is possible that the returned value is lower than * min_remove_bytes if the caches get emptied out so the caller should be * aware of this. */ @@ -951,7 +951,7 @@ hs_cache_handle_oom(time_t now, size_t min_remove_bytes) return bytes_removed; } -/* Return the maximum size of a v3 HS descriptor. */ +/** Return the maximum size of a v3 HS descriptor. */ unsigned int hs_cache_get_max_descriptor_size(void) { @@ -960,7 +960,7 @@ hs_cache_get_max_descriptor_size(void) HS_DESC_MAX_LEN, 1, INT32_MAX); } -/* Initialize the hidden service cache subsystem. */ +/** Initialize the hidden service cache subsystem. */ void hs_cache_init(void) { @@ -975,7 +975,7 @@ hs_cache_init(void) hs_cache_client_intro_state = digest256map_new(); } -/* Cleanup the hidden service cache subsystem. */ +/** Cleanup the hidden service cache subsystem. */ void hs_cache_free_all(void) { diff --git a/src/feature/hs/hs_cache.h b/src/feature/hs/hs_cache.h index 079d31d437..5df7e54fc0 100644 --- a/src/feature/hs/hs_cache.h +++ b/src/feature/hs/hs_cache.h @@ -18,47 +18,47 @@ struct ed25519_public_key_t; -/* This is the maximum time an introduction point state object can stay in the +/** This is the maximum time an introduction point state object can stay in the * client cache in seconds (2 mins or 120 seconds). */ #define HS_CACHE_CLIENT_INTRO_STATE_MAX_AGE (2 * 60) -/* Introduction point state. */ +/** Introduction point state. */ typedef struct hs_cache_intro_state_t { - /* When this entry was created and put in the cache. */ + /** When this entry was created and put in the cache. */ time_t created_ts; - /* Did it suffered a generic error? */ + /** Did it suffered a generic error? */ unsigned int error : 1; - /* Did it timed out? */ + /** Did it timed out? */ unsigned int timed_out : 1; - /* How many times we tried to reached it and it was unreachable. */ + /** How many times we tried to reached it and it was unreachable. */ uint32_t unreachable_count; } hs_cache_intro_state_t; typedef struct hs_cache_client_intro_state_t { - /* Contains hs_cache_intro_state_t object indexed by introduction point + /** Contains hs_cache_intro_state_t object indexed by introduction point * authentication key. */ digest256map_t *intro_points; } hs_cache_client_intro_state_t; -/* Descriptor representation on the directory side which is a subset of +/** Descriptor representation on the directory side which is a subset of * information that the HSDir can decode and serve it. */ typedef struct hs_cache_dir_descriptor_t { - /* This object is indexed using the blinded pubkey located in the plaintext + /** This object is indexed using the blinded pubkey located in the plaintext * data which is populated only once the descriptor has been successfully * decoded and validated. This simply points to that pubkey. */ const uint8_t *key; - /* When does this entry has been created. Used to expire entries. */ + /** When does this entry has been created. Used to expire entries. */ time_t created_ts; - /* Descriptor plaintext information. Obviously, we can't decrypt the + /** Descriptor plaintext information. Obviously, we can't decrypt the * encrypted part of the descriptor. */ hs_desc_plaintext_data_t *plaintext_data; - /* Encoded descriptor which is basically in text form. It's a NUL terminated + /** Encoded descriptor which is basically in text form. It's a NUL terminated * string thus safe to strlen(). */ char *encoded_desc; } hs_cache_dir_descriptor_t; @@ -104,19 +104,19 @@ void hs_cache_client_intro_state_purge(void); /** Represents a locally cached HS descriptor on a hidden service client. */ typedef struct hs_cache_client_descriptor_t { - /* This object is indexed using the service identity public key */ + /** This object is indexed using the service identity public key */ struct ed25519_public_key_t key; - /* When will this entry expire? We expire cached client descriptors in the + /** When will this entry expire? We expire cached client descriptors in the * start of the next time period, since that's when clients need to start * using the next blinded key of the service. */ time_t expiration_ts; - /* The cached descriptor, this object is the owner. It can't be NULL. A + /** The cached descriptor, this object is the owner. It can't be NULL. A * cache object without a valid descriptor is not possible. */ hs_descriptor_t *desc; - /* Encoded descriptor in string form. Can't be NULL. */ + /** Encoded descriptor in string form. Can't be NULL. */ char *encoded_desc; } hs_cache_client_descriptor_t; diff --git a/src/feature/hs/hs_cell.c b/src/feature/hs/hs_cell.c index df59f73c1b..eaf8820e9f 100644 --- a/src/feature/hs/hs_cell.c +++ b/src/feature/hs/hs_cell.c @@ -24,7 +24,7 @@ #include "trunnel/hs/cell_introduce1.h" #include "trunnel/hs/cell_rendezvous.h" -/* Compute the MAC of an INTRODUCE cell in mac_out. The encoded_cell param is +/** Compute the MAC of an INTRODUCE cell in mac_out. The encoded_cell param is * the cell content up to the ENCRYPTED section of length encoded_cell_len. * The encrypted param is the start of the ENCRYPTED section of length * encrypted_len. The mac_key is the key needed for the computation of the MAC @@ -67,7 +67,7 @@ compute_introduce_mac(const uint8_t *encoded_cell, size_t encoded_cell_len, memwipe(mac_msg, 0, sizeof(mac_msg)); } -/* From a set of keys, subcredential and the ENCRYPTED section of an +/** From a set of keys, subcredential and the ENCRYPTED section of an * INTRODUCE2 cell, return a newly allocated intro cell keys structure. * Finally, the client public key is copied in client_pk. On error, return * NULL. */ @@ -101,7 +101,7 @@ get_introduce2_key_material(const ed25519_public_key_t *auth_key, return keys; } -/* Using the given encryption key, decrypt the encrypted_section of length +/** Using the given encryption key, decrypt the encrypted_section of length * encrypted_section_len of an INTRODUCE2 cell and return a newly allocated * buffer containing the decrypted data. On decryption failure, NULL is * returned. */ @@ -136,7 +136,7 @@ decrypt_introduce2(const uint8_t *enc_key, const uint8_t *encrypted_section, return decrypted; } -/* Given a pointer to the decrypted data of the ENCRYPTED section of an +/** Given a pointer to the decrypted data of the ENCRYPTED section of an * INTRODUCE2 cell of length decrypted_len, parse and validate the cell * content. Return a newly allocated cell structure or NULL on error. The * circuit and service object are only used for logging purposes. */ @@ -188,7 +188,7 @@ parse_introduce2_encrypted(const uint8_t *decrypted_data, return NULL; } -/* Build a legacy ESTABLISH_INTRO cell with the given circuit nonce and RSA +/** Build a legacy ESTABLISH_INTRO cell with the given circuit nonce and RSA * encryption key. The encoded cell is put in cell_out that MUST at least be * of the size of RELAY_PAYLOAD_SIZE. Return the encoded cell length on * success else a negative value and cell_out is untouched. */ @@ -210,7 +210,7 @@ build_legacy_establish_intro(const char *circ_nonce, crypto_pk_t *enc_key, return cell_len; } -/* Parse an INTRODUCE2 cell from payload of size payload_len for the given +/** Parse an INTRODUCE2 cell from payload of size payload_len for the given * service and circuit which are used only for logging purposes. The resulting * parsed cell is put in cell_ptr_out. * @@ -249,7 +249,7 @@ parse_introduce2_cell(const hs_service_t *service, return -1; } -/* Set the onion public key onion_pk in cell, the encrypted section of an +/** Set the onion public key onion_pk in cell, the encrypted section of an * INTRODUCE1 cell. */ static void introduce1_set_encrypted_onion_key(trn_cell_introduce_encrypted_t *cell, @@ -266,7 +266,7 @@ introduce1_set_encrypted_onion_key(trn_cell_introduce_encrypted_t *cell, trn_cell_introduce_encrypted_getlen_onion_key(cell)); } -/* Set the link specifiers in lspecs in cell, the encrypted section of an +/** Set the link specifiers in lspecs in cell, the encrypted section of an * INTRODUCE1 cell. */ static void introduce1_set_encrypted_link_spec(trn_cell_introduce_encrypted_t *cell, @@ -286,7 +286,7 @@ introduce1_set_encrypted_link_spec(trn_cell_introduce_encrypted_t *cell, trn_cell_introduce_encrypted_add_nspecs(cell, ls)); } -/* Set padding in the enc_cell only if needed that is the total length of both +/** Set padding in the enc_cell only if needed that is the total length of both * sections are below the mininum required for an INTRODUCE1 cell. */ static void introduce1_set_encrypted_padding(const trn_cell_introduce1_t *cell, @@ -306,7 +306,7 @@ introduce1_set_encrypted_padding(const trn_cell_introduce1_t *cell, } } -/* Encrypt the ENCRYPTED payload and encode it in the cell using the enc_cell +/** Encrypt the ENCRYPTED payload and encode it in the cell using the enc_cell * and the INTRODUCE1 data. * * This can't fail but it is very important that the caller sets every field @@ -394,7 +394,7 @@ introduce1_encrypt_and_encode(trn_cell_introduce1_t *cell, tor_free(encrypted); } -/* Using the INTRODUCE1 data, setup the ENCRYPTED section in cell. This means +/** Using the INTRODUCE1 data, setup the ENCRYPTED section in cell. This means * set it, encrypt it and encode it. */ static void introduce1_set_encrypted(trn_cell_introduce1_t *cell, @@ -435,7 +435,7 @@ introduce1_set_encrypted(trn_cell_introduce1_t *cell, trn_cell_introduce_encrypted_free(enc_cell); } -/* Set the authentication key in the INTRODUCE1 cell from the given data. */ +/** Set the authentication key in the INTRODUCE1 cell from the given data. */ static void introduce1_set_auth_key(trn_cell_introduce1_t *cell, const hs_cell_introduce1_data_t *data) @@ -451,7 +451,7 @@ introduce1_set_auth_key(trn_cell_introduce1_t *cell, data->auth_pk->pubkey, trn_cell_introduce1_getlen_auth_key(cell)); } -/* Set the legacy ID field in the INTRODUCE1 cell from the given data. */ +/** Set the legacy ID field in the INTRODUCE1 cell from the given data. */ static void introduce1_set_legacy_id(trn_cell_introduce1_t *cell, const hs_cell_introduce1_data_t *data) @@ -473,7 +473,7 @@ introduce1_set_legacy_id(trn_cell_introduce1_t *cell, } } -/* Build and add to the given DoS cell extension the given parameter type and +/** Build and add to the given DoS cell extension the given parameter type and * value. */ static void build_establish_intro_dos_param(trn_cell_extension_dos_t *dos_ext, @@ -493,7 +493,7 @@ build_establish_intro_dos_param(trn_cell_extension_dos_t *dos_ext, /* Not freeing the trunnel object because it is now owned by dos_ext. */ } -/* Build the DoS defense cell extension and put it in the given extensions +/** Build the DoS defense cell extension and put it in the given extensions * object. Return 0 on success, -1 on failure. (Right now, failure is only * possible if there is a bug.) */ static int @@ -568,7 +568,7 @@ build_establish_intro_dos_extension(const hs_service_config_t *service_config, /* Public API */ /* ========== */ -/* Allocate and build all the ESTABLISH_INTRO cell extension. The given +/** Allocate and build all the ESTABLISH_INTRO cell extension. The given * extensions pointer is always set to a valid cell extension object. */ STATIC trn_cell_extension_t * build_establish_intro_extensions(const hs_service_config_t *service_config, @@ -599,7 +599,7 @@ build_establish_intro_extensions(const hs_service_config_t *service_config, return extensions; } -/* Build an ESTABLISH_INTRO cell with the given circuit nonce and intro point +/** Build an ESTABLISH_INTRO cell with the given circuit nonce and intro point * object. The encoded cell is put in cell_out that MUST at least be of the * size of RELAY_PAYLOAD_SIZE. Return the encoded cell length on success else * a negative value and cell_out is untouched. This function also supports @@ -725,7 +725,7 @@ hs_cell_build_establish_intro(const char *circ_nonce, return cell_len; } -/* Parse the INTRO_ESTABLISHED cell in the payload of size payload_len. If we +/** Parse the INTRO_ESTABLISHED cell in the payload of size payload_len. If we * are successful at parsing it, return the length of the parsed cell else a * negative value on error. */ ssize_t @@ -747,7 +747,7 @@ hs_cell_parse_intro_established(const uint8_t *payload, size_t payload_len) return ret; } -/* Parse the INTRODUCE2 cell using data which contains everything we need to +/** Parse the INTRODUCE2 cell using data which contains everything we need to * do so and contains the destination buffers of information we extract and * compute from the cell. Return 0 on success else a negative value. The * service and circ are only used for logging purposes. */ @@ -908,7 +908,7 @@ hs_cell_parse_introduce2(hs_cell_introduce2_data_t *data, return ret; } -/* Build a RENDEZVOUS1 cell with the given rendezvous cookie and handshake +/** Build a RENDEZVOUS1 cell with the given rendezvous cookie and handshake * info. The encoded cell is put in cell_out and the length of the data is * returned. This can't fail. */ ssize_t @@ -942,7 +942,7 @@ hs_cell_build_rendezvous1(const uint8_t *rendezvous_cookie, return cell_len; } -/* Build an INTRODUCE1 cell from the given data. The encoded cell is put in +/** Build an INTRODUCE1 cell from the given data. The encoded cell is put in * cell_out which must be of at least size RELAY_PAYLOAD_SIZE. On success, the * encoded length is returned else a negative value and the content of * cell_out should be ignored. */ @@ -983,7 +983,7 @@ hs_cell_build_introduce1(const hs_cell_introduce1_data_t *data, return cell_len; } -/* Build an ESTABLISH_RENDEZVOUS cell from the given rendezvous_cookie. The +/** Build an ESTABLISH_RENDEZVOUS cell from the given rendezvous_cookie. The * encoded cell is put in cell_out which must be of at least * RELAY_PAYLOAD_SIZE. On success, the encoded length is returned and the * caller should clear up the content of the cell. @@ -1000,7 +1000,7 @@ hs_cell_build_establish_rendezvous(const uint8_t *rendezvous_cookie, return HS_REND_COOKIE_LEN; } -/* Handle an INTRODUCE_ACK cell encoded in payload of length payload_len. +/** Handle an INTRODUCE_ACK cell encoded in payload of length payload_len. * Return the status code on success else a negative value if the cell as not * decodable. */ int @@ -1035,7 +1035,7 @@ hs_cell_parse_introduce_ack(const uint8_t *payload, size_t payload_len) return ret; } -/* Handle a RENDEZVOUS2 cell encoded in payload of length payload_len. On +/** Handle a RENDEZVOUS2 cell encoded in payload of length payload_len. On * success, handshake_info contains the data in the HANDSHAKE_INFO field, and * 0 is returned. On error, a negative value is returned. */ int @@ -1067,7 +1067,7 @@ hs_cell_parse_rendezvous2(const uint8_t *payload, size_t payload_len, return ret; } -/* Clear the given INTRODUCE1 data structure data. */ +/** Clear the given INTRODUCE1 data structure data. */ void hs_cell_introduce1_data_clear(hs_cell_introduce1_data_t *data) { diff --git a/src/feature/hs/hs_cell.h b/src/feature/hs/hs_cell.h index 864b6fda5f..5ee4347944 100644 --- a/src/feature/hs/hs_cell.h +++ b/src/feature/hs/hs_cell.h @@ -12,35 +12,35 @@ #include "core/or/or.h" #include "feature/hs/hs_service.h" -/* An INTRODUCE1 cell requires at least this amount of bytes (see section +/** An INTRODUCE1 cell requires at least this amount of bytes (see section * 3.2.2 of the specification). Below this value, the cell must be padded. */ #define HS_CELL_INTRODUCE1_MIN_SIZE 246 -/* This data structure contains data that we need to build an INTRODUCE1 cell +/** This data structure contains data that we need to build an INTRODUCE1 cell * used by the INTRODUCE1 build function. */ typedef struct hs_cell_introduce1_data_t { - /* Is this a legacy introduction point? */ + /** Is this a legacy introduction point? */ unsigned int is_legacy : 1; - /* (Legacy only) The encryption key for a legacy intro point. Only set if + /** (Legacy only) The encryption key for a legacy intro point. Only set if * is_legacy is true. */ const crypto_pk_t *legacy_key; - /* Introduction point authentication public key. */ + /** Introduction point authentication public key. */ const ed25519_public_key_t *auth_pk; - /* Introduction point encryption public key. */ + /** Introduction point encryption public key. */ const curve25519_public_key_t *enc_pk; - /* Subcredentials of the service. */ + /** Subcredentials of the service. */ const uint8_t *subcredential; - /* Onion public key for the ntor handshake. */ + /** Onion public key for the ntor handshake. */ const curve25519_public_key_t *onion_pk; - /* Rendezvous cookie. */ + /** Rendezvous cookie. */ const uint8_t *rendezvous_cookie; - /* Public key put before the encrypted data (CLIENT_PK). */ + /** Public key put before the encrypted data (CLIENT_PK). */ const curve25519_keypair_t *client_kp; - /* Rendezvous point link specifiers. */ + /** Rendezvous point link specifiers. */ smartlist_t *link_specifiers; } hs_cell_introduce1_data_t; -/* This data structure contains data that we need to parse an INTRODUCE2 cell +/** This data structure contains data that we need to parse an INTRODUCE2 cell * which is used by the INTRODUCE2 cell parsing function. On a successful * parsing, the onion_pk and rendezvous_cookie will be populated with the * computed key material from the cell data. This structure is only used during @@ -48,32 +48,32 @@ typedef struct hs_cell_introduce1_data_t { typedef struct hs_cell_introduce2_data_t { /*** Immutable Section: Set on structure init. ***/ - /* Introduction point authentication public key. Pointer owned by the + /** Introduction point authentication public key. Pointer owned by the introduction point object through which we received the INTRO2 cell. */ const ed25519_public_key_t *auth_pk; - /* Introduction point encryption keypair for the ntor handshake. Pointer + /** Introduction point encryption keypair for the ntor handshake. Pointer owned by the introduction point object through which we received the INTRO2 cell*/ const curve25519_keypair_t *enc_kp; - /* Subcredentials of the service. Pointer owned by the descriptor that owns + /** Subcredentials of the service. Pointer owned by the descriptor that owns the introduction point through which we received the INTRO2 cell. */ const uint8_t *subcredential; - /* Payload of the received encoded cell. */ + /** Payload of the received encoded cell. */ const uint8_t *payload; - /* Size of the payload of the received encoded cell. */ + /** Size of the payload of the received encoded cell. */ size_t payload_len; /*** Mutable Section: Set upon parsing INTRODUCE2 cell. ***/ - /* Onion public key computed using the INTRODUCE2 encrypted section. */ + /** Onion public key computed using the INTRODUCE2 encrypted section. */ curve25519_public_key_t onion_pk; - /* Rendezvous cookie taken from the INTRODUCE2 encrypted section. */ + /** Rendezvous cookie taken from the INTRODUCE2 encrypted section. */ uint8_t rendezvous_cookie[REND_COOKIE_LEN]; - /* Client public key from the INTRODUCE2 encrypted section. */ + /** Client public key from the INTRODUCE2 encrypted section. */ curve25519_public_key_t client_pk; - /* Link specifiers of the rendezvous point. Contains link_specifier_t. */ + /** Link specifiers of the rendezvous point. Contains link_specifier_t. */ smartlist_t *link_specifiers; - /* Replay cache of the introduction point. */ + /** Replay cache of the introduction point. */ replaycache_t *replay_cache; } hs_cell_introduce2_data_t; @@ -117,4 +117,3 @@ build_establish_intro_extensions(const hs_service_config_t *service_config, #endif /* defined(TOR_UNIT_TESTS) */ #endif /* !defined(TOR_HS_CELL_H) */ - diff --git a/src/feature/hs/hs_circuit.c b/src/feature/hs/hs_circuit.c index 5e213b5aba..e1e9c7c790 100644 --- a/src/feature/hs/hs_circuit.c +++ b/src/feature/hs/hs_circuit.c @@ -637,6 +637,27 @@ hs_circ_service_get_intro_circ(const hs_service_intro_point_t *ip) } } +/* Return an introduction point established circuit matching the given intro + * point object. The circuit purpose has to be CIRCUIT_PURPOSE_S_INTRO. NULL + * is returned is no such circuit can be found. */ +origin_circuit_t * +hs_circ_service_get_established_intro_circ(const hs_service_intro_point_t *ip) +{ + origin_circuit_t *circ; + + tor_assert(ip); + + if (ip->base.is_only_legacy) { + circ = hs_circuitmap_get_intro_circ_v2_service_side(ip->legacy_key_digest); + } else { + circ = hs_circuitmap_get_intro_circ_v3_service_side( + &ip->auth_key_kp.pubkey); + } + + /* Only return circuit if it is established. */ + return (TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_INTRO) ? circ : NULL; +} + /* Called when we fail building a rendezvous circuit at some point other than * the last hop: launches a new circuit to the same rendezvous point. This * supports legacy service. diff --git a/src/feature/hs/hs_circuit.h b/src/feature/hs/hs_circuit.h index e168b301f1..c817f3e37a 100644 --- a/src/feature/hs/hs_circuit.h +++ b/src/feature/hs/hs_circuit.h @@ -35,6 +35,8 @@ void hs_circ_retry_service_rendezvous_point(origin_circuit_t *circ); origin_circuit_t *hs_circ_service_get_intro_circ( const hs_service_intro_point_t *ip); +origin_circuit_t *hs_circ_service_get_established_intro_circ( + const hs_service_intro_point_t *ip); /* Cell API. */ int hs_circ_handle_intro_established(const hs_service_t *service, diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c index 492e77faff..c79bc63393 100644 --- a/src/feature/hs/hs_client.c +++ b/src/feature/hs/hs_client.c @@ -43,13 +43,13 @@ #include "core/or/extend_info_st.h" #include "core/or/origin_circuit_st.h" -/* Client-side authorizations for hidden services; map of service identity +/** Client-side authorizations for hidden services; map of service identity * public key to hs_client_service_authorization_t *. */ static digest256map_t *client_auths = NULL; #include "trunnel/hs/cell_introduce1.h" -/* Return a human-readable string for the client fetch status code. */ +/** Return a human-readable string for the client fetch status code. */ static const char * fetch_status_to_string(hs_client_fetch_status_t status) { @@ -73,7 +73,7 @@ fetch_status_to_string(hs_client_fetch_status_t status) } } -/* Return true iff tor should close the SOCKS request(s) for the descriptor +/** Return true iff tor should close the SOCKS request(s) for the descriptor * fetch that ended up with this given status code. */ static int fetch_status_should_close_socks(hs_client_fetch_status_t status) @@ -100,7 +100,7 @@ fetch_status_should_close_socks(hs_client_fetch_status_t status) return 1; } -/* Cancel all descriptor fetches currently in progress. */ +/** Cancel all descriptor fetches currently in progress. */ static void cancel_descriptor_fetches(void) { @@ -124,7 +124,7 @@ cancel_descriptor_fetches(void) log_info(LD_REND, "Hidden service client descriptor fetches cancelled."); } -/* Get all connections that are waiting on a circuit and flag them back to +/** Get all connections that are waiting on a circuit and flag them back to * waiting for a hidden service descriptor for the given service key * service_identity_pk. */ static void @@ -151,7 +151,7 @@ flag_all_conn_wait_desc(const ed25519_public_key_t *service_identity_pk) smartlist_free(conns); } -/* Remove tracked HSDir requests from our history for this hidden service +/** Remove tracked HSDir requests from our history for this hidden service * identity public key. */ static void purge_hid_serv_request(const ed25519_public_key_t *identity_pk) @@ -172,7 +172,7 @@ purge_hid_serv_request(const ed25519_public_key_t *identity_pk) hs_purge_hid_serv_from_last_hid_serv_requests(base64_blinded_pk); } -/* Return true iff there is at least one pending directory descriptor request +/** Return true iff there is at least one pending directory descriptor request * for the service identity_pk. */ static int directory_request_is_pending(const ed25519_public_key_t *identity_pk) @@ -200,7 +200,7 @@ directory_request_is_pending(const ed25519_public_key_t *identity_pk) return ret; } -/* Helper function that changes the state of an entry connection to waiting +/** Helper function that changes the state of an entry connection to waiting * for a circuit. For this to work properly, the connection timestamps are set * to now and the connection is then marked as pending for a circuit. */ static void @@ -220,7 +220,7 @@ mark_conn_as_waiting_for_circuit(connection_t *conn, time_t now) connection_ap_mark_as_pending_circuit(TO_ENTRY_CONN(conn)); } -/* We failed to fetch a descriptor for the service with <b>identity_pk</b> +/** We failed to fetch a descriptor for the service with <b>identity_pk</b> * because of <b>status</b>. Find all pending SOCKS connections for this * service that are waiting on the descriptor and close them with * <b>reason</b>. */ @@ -265,7 +265,7 @@ close_all_socks_conns_waiting_for_desc(const ed25519_public_key_t *identity_pk, smartlist_free(conns); } -/* Find all pending SOCKS connection waiting for a descriptor and retry them +/** Find all pending SOCKS connection waiting for a descriptor and retry them * all. This is called when the directory information changed. */ STATIC void retry_all_socks_conn_waiting_for_desc(void) @@ -321,7 +321,7 @@ retry_all_socks_conn_waiting_for_desc(void) smartlist_free(conns); } -/* A v3 HS circuit successfully connected to the hidden service. Update the +/** A v3 HS circuit successfully connected to the hidden service. Update the * stream state at <b>hs_conn_ident</b> appropriately. */ static void note_connection_attempt_succeeded(const hs_ident_edge_conn_t *hs_conn_ident) @@ -343,7 +343,7 @@ note_connection_attempt_succeeded(const hs_ident_edge_conn_t *hs_conn_ident) * will be reset and thus possible to be retried. */ } -/* Given the pubkey of a hidden service in <b>onion_identity_pk</b>, fetch its +/** Given the pubkey of a hidden service in <b>onion_identity_pk</b>, fetch its * descriptor by launching a dir connection to <b>hsdir</b>. Return a * hs_client_fetch_status_t status code depending on how it went. */ static hs_client_fetch_status_t @@ -451,7 +451,7 @@ fetch_v3_desc, (const ed25519_public_key_t *onion_identity_pk)) return directory_launch_v3_desc_fetch(onion_identity_pk, hsdir_rs); } -/* With a given <b>onion_identity_pk</b>, fetch its descriptor. If +/** With a given <b>onion_identity_pk</b>, fetch its descriptor. If * <b>hsdirs</b> is specified, use the directory servers specified in the list. * Else, use a random server. */ void @@ -469,7 +469,7 @@ hs_client_launch_v3_desc_fetch(const ed25519_public_key_t *onion_identity_pk, } } -/* Make sure that the given v3 origin circuit circ is a valid correct +/** Make sure that the given v3 origin circuit circ is a valid correct * introduction circuit. This will BUG() on any problems and hard assert if * the anonymity of the circuit is not ok. Return 0 on success else -1 where * the circuit should be mark for closed immediately. */ @@ -498,7 +498,7 @@ intro_circ_is_ok(const origin_circuit_t *circ) return ret; } -/* Find a descriptor intro point object that matches the given ident in the +/** Find a descriptor intro point object that matches the given ident in the * given descriptor desc. Return NULL if not found. */ static const hs_desc_intro_point_t * find_desc_intro_point_by_ident(const hs_ident_circuit_t *ident, @@ -521,7 +521,7 @@ find_desc_intro_point_by_ident(const hs_ident_circuit_t *ident, return intro_point; } -/* Find a descriptor intro point object from the descriptor object desc that +/** Find a descriptor intro point object from the descriptor object desc that * matches the given legacy identity digest in legacy_id. Return NULL if not * found. */ static hs_desc_intro_point_t * @@ -559,7 +559,7 @@ find_desc_intro_point_by_legacy_id(const char *legacy_id, return ret_ip; } -/* Send an INTRODUCE1 cell along the intro circuit and populate the rend +/** Send an INTRODUCE1 cell along the intro circuit and populate the rend * circuit identifier with the needed key material for the e2e encryption. * Return 0 on success, -1 if there is a transient error such that an action * has been taken to recover and -2 if there is a permanent error indicating @@ -671,7 +671,7 @@ send_introduce1(origin_circuit_t *intro_circ, return status; } -/* Using the introduction circuit circ, setup the authentication key of the +/** Using the introduction circuit circ, setup the authentication key of the * intro point this circuit has extended to. */ static void setup_intro_circ_auth_key(origin_circuit_t *circ) @@ -710,7 +710,7 @@ setup_intro_circ_auth_key(origin_circuit_t *circ) return; } -/* Called when an introduction circuit has opened. */ +/** Called when an introduction circuit has opened. */ static void client_intro_circ_has_opened(origin_circuit_t *circ) { @@ -727,7 +727,7 @@ client_intro_circ_has_opened(origin_circuit_t *circ) connection_ap_attach_pending(1); } -/* Called when a rendezvous circuit has opened. */ +/** Called when a rendezvous circuit has opened. */ static void client_rendezvous_circ_has_opened(origin_circuit_t *circ) { @@ -761,7 +761,7 @@ client_rendezvous_circ_has_opened(origin_circuit_t *circ) } } -/* This is an helper function that convert a descriptor intro point object ip +/** This is an helper function that convert a descriptor intro point object ip * to a newly allocated extend_info_t object fully initialized. Return NULL if * we can't convert it for which chances are that we are missing or malformed * link specifiers. */ @@ -779,7 +779,7 @@ desc_intro_point_to_extend_info(const hs_desc_intro_point_t *ip) return ei; } -/* Return true iff the intro point ip for the service service_pk is usable. +/** Return true iff the intro point ip for the service service_pk is usable. * This function checks if the intro point is in the client intro state cache * and checks at the failures. It is considered usable if: * - No error happened (INTRO_POINT_FAILURE_GENERIC) @@ -824,7 +824,7 @@ intro_point_is_usable(const ed25519_public_key_t *service_pk, return 0; } -/* Using a descriptor desc, return a newly allocated extend_info_t object of a +/** Using a descriptor desc, return a newly allocated extend_info_t object of a * randomly picked introduction point from its list. Return NULL if none are * usable. */ STATIC extend_info_t * @@ -929,7 +929,7 @@ client_get_random_intro(const ed25519_public_key_t *service_pk) return ei; } -/* For this introduction circuit, we'll look at if we have any usable +/** For this introduction circuit, we'll look at if we have any usable * introduction point left for this service. If so, we'll use the circuit to * re-extend to a new intro point. Else, we'll close the circuit and its * corresponding rendezvous circuit. Return 0 if we are re-extending else -1 @@ -986,7 +986,7 @@ close_or_reextend_intro_circ(origin_circuit_t *intro_circ) return ret; } -/* Called when we get an INTRODUCE_ACK success status code. Do the appropriate +/** Called when we get an INTRODUCE_ACK success status code. Do the appropriate * actions for the rendezvous point and finally close intro_circ. */ static void handle_introduce_ack_success(origin_circuit_t *intro_circ) @@ -1032,7 +1032,7 @@ handle_introduce_ack_success(origin_circuit_t *intro_circ) return; } -/* Called when we get an INTRODUCE_ACK failure status code. Depending on our +/** Called when we get an INTRODUCE_ACK failure status code. Depending on our * failure cache status, either close the circuit or re-extend to a new * introduction point. */ static void @@ -1054,7 +1054,7 @@ handle_introduce_ack_bad(origin_circuit_t *circ, int status) INTRO_POINT_FAILURE_GENERIC); } -/* Called when we get an INTRODUCE_ACK on the intro circuit circ. The encoded +/** Called when we get an INTRODUCE_ACK on the intro circuit circ. The encoded * cell is in payload of length payload_len. Return 0 on success else a * negative value. The circuit is either close or reuse to re-extend to a new * introduction point. */ @@ -1093,7 +1093,7 @@ handle_introduce_ack(origin_circuit_t *circ, const uint8_t *payload, return ret; } -/* Called when we get a RENDEZVOUS2 cell on the rendezvous circuit circ. The +/** Called when we get a RENDEZVOUS2 cell on the rendezvous circuit circ. The * encoded cell is in payload of length payload_len. Return 0 on success or a * negative value on error. On error, the circuit is marked for close. */ STATIC int @@ -1155,7 +1155,7 @@ handle_rendezvous2(origin_circuit_t *circ, const uint8_t *payload, return ret; } -/* Return true iff the client can fetch a descriptor for this service public +/** Return true iff the client can fetch a descriptor for this service public * identity key and status_out if not NULL is untouched. If the client can * _not_ fetch the descriptor and if status_out is not NULL, it is set with * the fetch status code. */ @@ -1222,7 +1222,7 @@ can_client_refetch_desc(const ed25519_public_key_t *identity_pk, return 0; } -/* Return the client auth in the map using the service identity public key. +/** Return the client auth in the map using the service identity public key. * Return NULL if it does not exist in the map. */ static hs_client_service_authorization_t * find_client_auth(const ed25519_public_key_t *service_identity_pk) @@ -1260,7 +1260,7 @@ hs_client_note_connection_attempt_succeeded(const edge_connection_t *conn) } } -/* With the given encoded descriptor in desc_str and the service key in +/** With the given encoded descriptor in desc_str and the service key in * service_identity_pk, decode the descriptor and set the desc pointer with a * newly allocated descriptor object. * @@ -1319,7 +1319,7 @@ hs_client_decode_descriptor(const char *desc_str, return -1; } -/* Return true iff there are at least one usable intro point in the service +/** Return true iff there are at least one usable intro point in the service * descriptor desc. */ int hs_client_any_intro_points_usable(const ed25519_public_key_t *service_pk, @@ -1368,7 +1368,7 @@ hs_client_refetch_hsdesc(const ed25519_public_key_t *identity_pk) return status; } -/* This is called when we are trying to attach an AP connection to these +/** This is called when we are trying to attach an AP connection to these * hidden service circuits from connection_ap_handshake_attach_circuit(). * Return 0 on success, -1 for a transient error that is actions were * triggered to recover or -2 for a permenent error where both circuits will @@ -1384,7 +1384,7 @@ hs_client_send_introduce1(origin_circuit_t *intro_circ, rend_circ); } -/* Called when the client circuit circ has been established. It can be either +/** Called when the client circuit circ has been established. It can be either * an introduction or rendezvous circuit. This function handles all hidden * service versions. */ void @@ -1414,7 +1414,7 @@ hs_client_circuit_has_opened(origin_circuit_t *circ) } } -/* Called when we receive a RENDEZVOUS_ESTABLISHED cell. Change the state of +/** Called when we receive a RENDEZVOUS_ESTABLISHED cell. Change the state of * the circuit to CIRCUIT_PURPOSE_C_REND_READY. Return 0 on success else a * negative value and the circuit marked for close. */ int @@ -1485,7 +1485,7 @@ client_service_authorization_free_all(void) digest256map_free(client_auths, client_service_authorization_free_void); } -/* Check if the auth key file name is valid or not. Return 1 if valid, +/** Check if the auth key file name is valid or not. Return 1 if valid, * otherwise return 0. */ STATIC int auth_key_filename_is_valid(const char *filename) @@ -1570,7 +1570,7 @@ parse_auth_file_content(const char *client_key_str) return auth; } -/* From a set of <b>options</b>, setup every client authorization detail +/** From a set of <b>options</b>, setup every client authorization detail * found. Return 0 on success or -1 on failure. If <b>validate_only</b> * is set, parse, warn and return as normal, but don't actually change * the configuration. */ @@ -1685,7 +1685,7 @@ hs_config_client_authorization(const or_options_t *options, return ret; } -/* This is called when a descriptor has arrived following a fetch request and +/** This is called when a descriptor has arrived following a fetch request and * has been stored in the client cache. Every entry connection that matches * the service identity key in the ident will get attached to the hidden * service circuit. */ @@ -1743,7 +1743,7 @@ hs_client_desc_has_arrived(const hs_ident_dir_conn_t *ident) smartlist_free(conns); } -/* Return a newly allocated extend_info_t for a randomly chosen introduction +/** Return a newly allocated extend_info_t for a randomly chosen introduction * point for the given edge connection identifier ident. Return NULL if we * can't pick any usable introduction points. */ extend_info_t * @@ -1756,7 +1756,7 @@ hs_client_get_random_intro_from_edge(const edge_connection_t *edge_conn) rend_client_get_random_intro(edge_conn->rend_data); } -/* Called when get an INTRODUCE_ACK cell on the introduction circuit circ. +/** Called when get an INTRODUCE_ACK cell on the introduction circuit circ. * Return 0 on success else a negative value is returned. The circuit will be * closed or reuse to extend again to another intro point. */ int @@ -1785,7 +1785,7 @@ hs_client_receive_introduce_ack(origin_circuit_t *circ, return ret; } -/* Called when get a RENDEZVOUS2 cell on the rendezvous circuit circ. Return +/** Called when get a RENDEZVOUS2 cell on the rendezvous circuit circ. Return * 0 on success else a negative value is returned. The circuit will be closed * on error. */ int @@ -1818,7 +1818,7 @@ hs_client_receive_rendezvous2(origin_circuit_t *circ, return ret; } -/* Extend the introduction circuit circ to another valid introduction point +/** Extend the introduction circuit circ to another valid introduction point * for the hidden service it is trying to connect to, or mark it and launch a * new circuit if we can't extend it. Return 0 on success or possible * success. Return -1 and mark the introduction circuit for close on permanent @@ -1868,7 +1868,7 @@ hs_client_reextend_intro_circuit(origin_circuit_t *circ) return ret; } -/* Close all client introduction circuits related to the given descriptor. +/** Close all client introduction circuits related to the given descriptor. * This is called with a descriptor that is about to get replaced in the * client cache. * @@ -1900,7 +1900,7 @@ hs_client_close_intro_circuits_from_desc(const hs_descriptor_t *desc) } } -/* Release all the storage held by the client subsystem. */ +/** Release all the storage held by the client subsystem. */ void hs_client_free_all(void) { @@ -1909,7 +1909,7 @@ hs_client_free_all(void) client_service_authorization_free_all(); } -/* Purge all potentially remotely-detectable state held in the hidden +/** Purge all potentially remotely-detectable state held in the hidden * service client code. Called on SIGNAL NEWNYM. */ void hs_client_purge_state(void) @@ -1930,7 +1930,7 @@ hs_client_purge_state(void) log_info(LD_REND, "Hidden service client state has been purged."); } -/* Called when our directory information has changed. */ +/** Called when our directory information has changed. */ void hs_client_dir_info_changed(void) { diff --git a/src/feature/hs/hs_client.h b/src/feature/hs/hs_client.h index 96a96755fd..69e48ca31b 100644 --- a/src/feature/hs/hs_client.h +++ b/src/feature/hs/hs_client.h @@ -13,31 +13,31 @@ #include "feature/hs/hs_descriptor.h" #include "feature/hs/hs_ident.h" -/* Status code of a descriptor fetch request. */ +/** Status code of a descriptor fetch request. */ typedef enum { - /* Something internally went wrong. */ + /** Something internally went wrong. */ HS_CLIENT_FETCH_ERROR = -1, - /* The fetch request has been launched successfully. */ + /** The fetch request has been launched successfully. */ HS_CLIENT_FETCH_LAUNCHED = 0, - /* We already have a usable descriptor. No fetch. */ + /** We already have a usable descriptor. No fetch. */ HS_CLIENT_FETCH_HAVE_DESC = 1, - /* No more HSDir available to query. */ + /** No more HSDir available to query. */ HS_CLIENT_FETCH_NO_HSDIRS = 2, - /* The fetch request is not allowed. */ + /** The fetch request is not allowed. */ HS_CLIENT_FETCH_NOT_ALLOWED = 3, - /* We are missing information to be able to launch a request. */ + /** We are missing information to be able to launch a request. */ HS_CLIENT_FETCH_MISSING_INFO = 4, - /* There is a pending fetch for the requested service. */ + /** There is a pending fetch for the requested service. */ HS_CLIENT_FETCH_PENDING = 5, } hs_client_fetch_status_t; /** Client-side configuration of authorization for a service. */ typedef struct hs_client_service_authorization_t { - /* An curve25519 secret key used to compute decryption keys that + /** An curve25519 secret key used to compute decryption keys that * allow the client to decrypt the hidden service descriptor. */ curve25519_secret_key_t enc_seckey; - /* An onion address that is used to connect to the onion service. */ + /** An onion address that is used to connect to the onion service. */ char onion_address[HS_SERVICE_ADDR_LEN_BASE32+1]; } hs_client_service_authorization_t; @@ -120,4 +120,3 @@ STATIC digest256map_t *get_hs_client_auths_map(void); #endif /* defined(HS_CLIENT_PRIVATE) */ #endif /* !defined(TOR_HS_CLIENT_H) */ - diff --git a/src/feature/hs/hs_common.c b/src/feature/hs/hs_common.c index 036d23a6b0..cf98bea320 100644 --- a/src/feature/hs/hs_common.c +++ b/src/feature/hs/hs_common.c @@ -44,7 +44,7 @@ /* Trunnel */ #include "trunnel/ed25519_cert.h" -/* Ed25519 Basepoint value. Taken from section 5 of +/** Ed25519 Basepoint value. Taken from section 5 of * https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03 */ static const char *str_ed25519_basepoint = "(15112221349535400772501151409588531511" @@ -106,7 +106,7 @@ add_unix_port(smartlist_t *ports, rend_service_port_config_t *p) #endif /* defined(HAVE_SYS_UN_H) */ -/* Helper function: The key is a digest that we compare to a node_t object +/** Helper function: The key is a digest that we compare to a node_t object * current hsdir_index. */ static int compare_digest_to_fetch_hsdir_index(const void *_key, const void **_member) @@ -116,7 +116,7 @@ compare_digest_to_fetch_hsdir_index(const void *_key, const void **_member) return tor_memcmp(key, node->hsdir_index.fetch, DIGEST256_LEN); } -/* Helper function: The key is a digest that we compare to a node_t object +/** Helper function: The key is a digest that we compare to a node_t object * next hsdir_index. */ static int compare_digest_to_store_first_hsdir_index(const void *_key, @@ -127,7 +127,7 @@ compare_digest_to_store_first_hsdir_index(const void *_key, return tor_memcmp(key, node->hsdir_index.store_first, DIGEST256_LEN); } -/* Helper function: The key is a digest that we compare to a node_t object +/** Helper function: The key is a digest that we compare to a node_t object * next hsdir_index. */ static int compare_digest_to_store_second_hsdir_index(const void *_key, @@ -138,7 +138,7 @@ compare_digest_to_store_second_hsdir_index(const void *_key, return tor_memcmp(key, node->hsdir_index.store_second, DIGEST256_LEN); } -/* Helper function: Compare two node_t objects current hsdir_index. */ +/** Helper function: Compare two node_t objects current hsdir_index. */ static int compare_node_fetch_hsdir_index(const void **a, const void **b) { @@ -149,7 +149,7 @@ compare_node_fetch_hsdir_index(const void **a, const void **b) DIGEST256_LEN); } -/* Helper function: Compare two node_t objects next hsdir_index. */ +/** Helper function: Compare two node_t objects next hsdir_index. */ static int compare_node_store_first_hsdir_index(const void **a, const void **b) { @@ -160,7 +160,7 @@ compare_node_store_first_hsdir_index(const void **a, const void **b) DIGEST256_LEN); } -/* Helper function: Compare two node_t objects next hsdir_index. */ +/** Helper function: Compare two node_t objects next hsdir_index. */ static int compare_node_store_second_hsdir_index(const void **a, const void **b) { @@ -171,7 +171,7 @@ compare_node_store_second_hsdir_index(const void **a, const void **b) DIGEST256_LEN); } -/* Allocate and return a string containing the path to filename in directory. +/** Allocate and return a string containing the path to filename in directory. * This function will never return NULL. The caller must free this path. */ char * hs_path_from_filename(const char *directory, const char *filename) @@ -185,8 +185,9 @@ hs_path_from_filename(const char *directory, const char *filename) return file_path; } -/* Make sure that the directory for <b>service</b> is private, using the config - * <b>username</b>. +/** Make sure that the directory for <b>service</b> is private, using the + * config <b>username</b>. + * * If <b>create</b> is true: * - if the directory exists, change permissions if needed, * - if the directory does not exist, create it with the correct permissions. @@ -313,9 +314,9 @@ hs_get_previous_time_period_num(time_t now) return hs_get_time_period_num(now) - 1; } -/* Return the start time of the upcoming time period based on <b>now</b>. If - <b>now</b> is not set, we try to get the time ourselves from a live - consensus. */ +/** Return the start time of the upcoming time period based on <b>now</b>. If + * <b>now</b> is not set, we try to get the time ourselves from a live + * consensus. */ time_t hs_get_start_time_of_next_time_period(time_t now) { @@ -330,7 +331,7 @@ hs_get_start_time_of_next_time_period(time_t now) return (time_t)(start_of_next_tp_in_mins * 60 + time_period_rotation_offset); } -/* Create a new rend_data_t for a specific given <b>version</b>. +/** Create a new rend_data_t for a specific given <b>version</b>. * Return a pointer to the newly allocated data structure. */ static rend_data_t * rend_data_alloc(uint32_t version) @@ -379,7 +380,7 @@ rend_data_free_(rend_data_t *data) } } -/* Allocate and return a deep copy of <b>data</b>. */ +/** Allocate and return a deep copy of <b>data</b>. */ rend_data_t * rend_data_dup(const rend_data_t *data) { @@ -409,7 +410,7 @@ rend_data_dup(const rend_data_t *data) return data_dup; } -/* Compute the descriptor ID for each HS descriptor replica and save them. A +/** Compute the descriptor ID for each HS descriptor replica and save them. A * valid onion address must be present in the <b>rend_data</b>. * * Return 0 on success else -1. */ @@ -447,7 +448,7 @@ compute_desc_id(rend_data_t *rend_data) return ret; } -/* Allocate and initialize a rend_data_t object for a service using the +/** Allocate and initialize a rend_data_t object for a service using the * provided arguments. All arguments are optional (can be NULL), except from * <b>onion_address</b> which MUST be set. The <b>pk_digest</b> is the hash of * the service private key. The <b>cookie</b> is the rendezvous cookie and @@ -479,7 +480,7 @@ rend_data_service_create(const char *onion_address, const char *pk_digest, return rend_data; } -/* Allocate and initialize a rend_data_t object for a client request using the +/** Allocate and initialize a rend_data_t object for a client request using the * given arguments. Either an onion address or a descriptor ID is needed. Both * can be given but in this case only the onion address will be used to make * the descriptor fetch. The <b>cookie</b> is the rendezvous cookie and @@ -520,7 +521,7 @@ rend_data_client_create(const char *onion_address, const char *desc_id, return NULL; } -/* Return the onion address from the rend data. Depending on the version, +/** Return the onion address from the rend data. Depending on the version, * the size of the address can vary but it's always NUL terminated. */ const char * rend_data_get_address(const rend_data_t *rend_data) @@ -536,7 +537,7 @@ rend_data_get_address(const rend_data_t *rend_data) } } -/* Return the descriptor ID for a specific replica number from the rend +/** Return the descriptor ID for a specific replica number from the rend * data. The returned data is a binary digest and depending on the version its * size can vary. The size of the descriptor ID is put in <b>len_out</b> if * non NULL. */ @@ -559,7 +560,7 @@ rend_data_get_desc_id(const rend_data_t *rend_data, uint8_t replica, } } -/* Return the public key digest using the given <b>rend_data</b>. The size of +/** Return the public key digest using the given <b>rend_data</b>. The size of * the digest is put in <b>len_out</b> (if set) which can differ depending on * the version. */ const uint8_t * @@ -582,7 +583,7 @@ rend_data_get_pk_digest(const rend_data_t *rend_data, size_t *len_out) } } -/* Using the given time period number, compute the disaster shared random +/** Using the given time period number, compute the disaster shared random * value and put it in srv_out. It MUST be at least DIGEST256_LEN bytes. */ static void compute_disaster_srv(uint64_t time_period_num, uint8_t *srv_out) @@ -670,7 +671,7 @@ get_second_cached_disaster_srv(void) #endif /* defined(TOR_UNIT_TESTS) */ -/* When creating a blinded key, we need a parameter which construction is as +/** When creating a blinded key, we need a parameter which construction is as * follow: H(pubkey | [secret] | ed25519-basepoint | nonce). * * The nonce has a pre-defined format which uses the time period number @@ -751,7 +752,7 @@ build_hs_checksum(const ed25519_public_key_t *key, uint8_t version, DIGEST_SHA3_256); } -/* Using an ed25519 public key, checksum and version to build the binary +/** Using an ed25519 public key, checksum and version to build the binary * representation of a service address. Put in addr_out. Format is: * addr_out = PUBKEY || CHECKSUM || VERSION * @@ -774,7 +775,7 @@ build_hs_address(const ed25519_public_key_t *key, const uint8_t *checksum, tor_assert(offset == HS_SERVICE_ADDR_LEN); } -/* Helper for hs_parse_address(): Using a binary representation of a service +/** Helper for hs_parse_address(): Using a binary representation of a service * address, parse its content into the key_out, checksum_out and version_out. * Any out variable can be NULL in case the caller would want only one field. * checksum_out MUST at least be 2 bytes long. address must be at least @@ -806,7 +807,7 @@ hs_parse_address_impl(const char *address, ed25519_public_key_t *key_out, tor_assert(offset == HS_SERVICE_ADDR_LEN); } -/* Using the given identity public key and a blinded public key, compute the +/** Using the given identity public key and a blinded public key, compute the * subcredential and put it in subcred_out (must be of size DIGEST256_LEN). * This can't fail. */ void @@ -846,7 +847,7 @@ hs_get_subcredential(const ed25519_public_key_t *identity_pk, memwipe(credential, 0, sizeof(credential)); } -/* From the given list of hidden service ports, find the ones that match the +/** From the given list of hidden service ports, find the ones that match the * given edge connection conn, pick one at random and use it to set the * connection address. Return 0 on success or -1 if none. */ int @@ -903,7 +904,7 @@ hs_set_conn_addr_port(const smartlist_t *ports, edge_connection_t *conn) return (chosen_port) ? 0 : -1; } -/* Using a base32 representation of a service address, parse its content into +/** Using a base32 representation of a service address, parse its content into * the key_out, checksum_out and version_out. Any out variable can be NULL in * case the caller would want only one field. checksum_out MUST at least be 2 * bytes long. @@ -943,7 +944,7 @@ hs_parse_address(const char *address, ed25519_public_key_t *key_out, return -1; } -/* Validate a given onion address. The length, the base32 decoding, and +/** Validate a given onion address. The length, the base32 decoding, and * checksum are validated. Return 1 if valid else 0. */ int hs_address_is_valid(const char *address) @@ -982,7 +983,7 @@ hs_address_is_valid(const char *address) return 0; } -/* Build a service address using an ed25519 public key and a given version. +/** Build a service address using an ed25519 public key and a given version. * The returned address is base32 encoded and put in addr_out. The caller MUST * make sure the addr_out is at least HS_SERVICE_ADDR_LEN_BASE32 + 1 long. * @@ -1012,7 +1013,7 @@ hs_build_address(const ed25519_public_key_t *key, uint8_t version, tor_assert(hs_address_is_valid(addr_out)); } -/* From a given ed25519 public key pk and an optional secret, compute a +/** From a given ed25519 public key pk and an optional secret, compute a * blinded public key and put it in blinded_pk_out. This is only useful to * the client side because the client only has access to the identity public * key of the service. */ @@ -1036,7 +1037,7 @@ hs_build_blinded_pubkey(const ed25519_public_key_t *pk, memwipe(param, 0, sizeof(param)); } -/* From a given ed25519 keypair kp and an optional secret, compute a blinded +/** From a given ed25519 keypair kp and an optional secret, compute a blinded * keypair for the current time period and put it in blinded_kp_out. This is * only useful by the service side because the client doesn't have access to * the identity secret key. */ @@ -1062,7 +1063,7 @@ hs_build_blinded_keypair(const ed25519_keypair_t *kp, memwipe(param, 0, sizeof(param)); } -/* Return true if we are currently in the time segment between a new time +/** Return true if we are currently in the time segment between a new time * period and a new SRV (in the real network that happens between 12:00 and * 00:00 UTC). Here is a diagram showing exactly when this returns true: * @@ -1102,7 +1103,7 @@ hs_in_period_between_tp_and_srv,(const networkstatus_t *consensus, time_t now)) return 1; } -/* Return 1 if any virtual port in ports needs a circuit with good uptime. +/** Return 1 if any virtual port in ports needs a circuit with good uptime. * Else return 0. */ int hs_service_requires_uptime_circ(const smartlist_t *ports) @@ -1118,7 +1119,7 @@ hs_service_requires_uptime_circ(const smartlist_t *ports) return 0; } -/* Build hs_index which is used to find the responsible hsdirs. This index +/** Build hs_index which is used to find the responsible hsdirs. This index * value is used to select the responsible HSDir where their hsdir_index is * closest to this value. * SHA3-256("store-at-idx" | blinded_public_key | @@ -1160,7 +1161,7 @@ hs_build_hs_index(uint64_t replica, const ed25519_public_key_t *blinded_pk, crypto_digest_free(digest); } -/* Build hsdir_index which is used to find the responsible hsdirs. This is the +/** Build hsdir_index which is used to find the responsible hsdirs. This is the * index value that is compare to the hs_index when selecting an HSDir. * SHA3-256("node-idx" | node_identity | * shared_random_value | INT_8(period_length) | INT_8(period_num) ) @@ -1201,7 +1202,7 @@ hs_build_hsdir_index(const ed25519_public_key_t *identity_pk, crypto_digest_free(digest); } -/* Return a newly allocated buffer containing the current shared random value +/** Return a newly allocated buffer containing the current shared random value * or if not present, a disaster value is computed using the given time period * number. If a consensus is provided in <b>ns</b>, use it to get the SRV * value. This function can't fail. */ @@ -1220,7 +1221,7 @@ hs_get_current_srv(uint64_t time_period_num, const networkstatus_t *ns) return sr_value; } -/* Return a newly allocated buffer containing the previous shared random +/** Return a newly allocated buffer containing the previous shared random * value or if not present, a disaster value is computed using the given time * period number. This function can't fail. */ uint8_t * @@ -1238,7 +1239,7 @@ hs_get_previous_srv(uint64_t time_period_num, const networkstatus_t *ns) return sr_value; } -/* Return the number of replicas defined by a consensus parameter or the +/** Return the number of replicas defined by a consensus parameter or the * default value. */ int32_t hs_get_hsdir_n_replicas(void) @@ -1248,7 +1249,7 @@ hs_get_hsdir_n_replicas(void) HS_DEFAULT_HSDIR_N_REPLICAS, 1, 16); } -/* Return the spread fetch value defined by a consensus parameter or the +/** Return the spread fetch value defined by a consensus parameter or the * default value. */ int32_t hs_get_hsdir_spread_fetch(void) @@ -1258,7 +1259,7 @@ hs_get_hsdir_spread_fetch(void) HS_DEFAULT_HSDIR_SPREAD_FETCH, 1, 128); } -/* Return the spread store value defined by a consensus parameter or the +/** Return the spread store value defined by a consensus parameter or the * default value. */ int32_t hs_get_hsdir_spread_store(void) @@ -1301,7 +1302,7 @@ node_has_hsdir_index(const node_t *node) return 1; } -/* For a given blinded key and time period number, get the responsible HSDir +/** For a given blinded key and time period number, get the responsible HSDir * and put their routerstatus_t object in the responsible_dirs list. If * 'use_second_hsdir_index' is true, use the second hsdir_index of the node_t * is used. If 'for_fetching' is true, the spread fetch consensus parameter is @@ -1674,7 +1675,7 @@ hs_pick_hsdir(smartlist_t *responsible_dirs, const char *req_key_str, return hs_dir; } -/* Given a list of link specifiers lspecs, a curve 25519 onion_key, and +/** Given a list of link specifiers lspecs, a curve 25519 onion_key, and * a direct connection boolean direct_conn (true for single onion services), * return a newly allocated extend_info_t object. * @@ -1787,7 +1788,7 @@ hs_get_extend_info_from_lspecs(const smartlist_t *lspecs, /***********************************************************************/ -/* Initialize the entire HS subsytem. This is called in tor_init() before any +/** Initialize the entire HS subsytem. This is called in tor_init() before any * torrc options are loaded. Only for >= v3. */ void hs_init(void) @@ -1797,7 +1798,7 @@ hs_init(void) hs_cache_init(); } -/* Release and cleanup all memory of the HS subsystem (all version). This is +/** Release and cleanup all memory of the HS subsystem (all version). This is * called by tor_free_all(). */ void hs_free_all(void) @@ -1808,7 +1809,7 @@ hs_free_all(void) hs_client_free_all(); } -/* For the given origin circuit circ, decrement the number of rendezvous +/** For the given origin circuit circ, decrement the number of rendezvous * stream counter. This handles every hidden service version. */ void hs_dec_rdv_stream_counter(origin_circuit_t *circ) @@ -1825,7 +1826,7 @@ hs_dec_rdv_stream_counter(origin_circuit_t *circ) } } -/* For the given origin circuit circ, increment the number of rendezvous +/** For the given origin circuit circ, increment the number of rendezvous * stream counter. This handles every hidden service version. */ void hs_inc_rdv_stream_counter(origin_circuit_t *circ) @@ -1842,7 +1843,7 @@ hs_inc_rdv_stream_counter(origin_circuit_t *circ) } } -/* Return a newly allocated link specifier object that is a copy of dst. */ +/** Return a newly allocated link specifier object that is a copy of dst. */ link_specifier_t * link_specifier_dup(const link_specifier_t *src) { diff --git a/src/feature/hs/hs_common.h b/src/feature/hs/hs_common.h index 3009780d90..1a3c563261 100644 --- a/src/feature/hs/hs_common.h +++ b/src/feature/hs/hs_common.h @@ -19,13 +19,14 @@ struct ed25519_keypair_t; /* Trunnel */ #include "trunnel/ed25519_cert.h" -/* Protocol version 2. Use this instead of hardcoding "2" in the code base, +/** Protocol version 2. Use this instead of hardcoding "2" in the code base, * this adds a clearer semantic to the value when used. */ #define HS_VERSION_TWO 2 -/* Version 3 of the protocol (prop224). */ +/** Version 3 of the protocol (prop224). */ #define HS_VERSION_THREE 3 -/* Earliest and latest version we support. */ +/** Earliest version we support. */ #define HS_VERSION_MIN HS_VERSION_TWO +/** Latest version we support. */ #define HS_VERSION_MAX HS_VERSION_THREE /** Try to maintain this many intro points per service by default. */ @@ -48,94 +49,95 @@ struct ed25519_keypair_t; * rendezvous point before giving up? */ #define MAX_REND_TIMEOUT 30 -/* String prefix for the signature of ESTABLISH_INTRO */ +/** String prefix for the signature of ESTABLISH_INTRO */ #define ESTABLISH_INTRO_SIG_PREFIX "Tor establish-intro cell v1" -/* The default HS time period length */ +/** The default HS time period length */ #define HS_TIME_PERIOD_LENGTH_DEFAULT 1440 /* 1440 minutes == one day */ -/* The minimum time period length as seen in prop224 section [TIME-PERIODS] */ +/** The minimum time period length as seen in prop224 section [TIME-PERIODS] */ #define HS_TIME_PERIOD_LENGTH_MIN 30 /* minutes */ -/* The minimum time period length as seen in prop224 section [TIME-PERIODS] */ +/** The minimum time period length as seen in prop224 section [TIME-PERIODS] */ #define HS_TIME_PERIOD_LENGTH_MAX (60 * 24 * 10) /* 10 days or 14400 minutes */ -/* Prefix of the onion address checksum. */ +/** Prefix of the onion address checksum. */ #define HS_SERVICE_ADDR_CHECKSUM_PREFIX ".onion checksum" -/* Length of the checksum prefix minus the NUL terminated byte. */ +/** Length of the checksum prefix minus the NUL terminated byte. */ #define HS_SERVICE_ADDR_CHECKSUM_PREFIX_LEN \ (sizeof(HS_SERVICE_ADDR_CHECKSUM_PREFIX) - 1) -/* Length of the resulting checksum of the address. The construction of this +/** Length of the resulting checksum of the address. The construction of this * checksum looks like: * CHECKSUM = ".onion checksum" || PUBKEY || VERSION * where VERSION is 1 byte. This is pre-hashing. */ #define HS_SERVICE_ADDR_CHECKSUM_INPUT_LEN \ (HS_SERVICE_ADDR_CHECKSUM_PREFIX_LEN + ED25519_PUBKEY_LEN + sizeof(uint8_t)) -/* The amount of bytes we use from the address checksum. */ +/** The amount of bytes we use from the address checksum. */ #define HS_SERVICE_ADDR_CHECKSUM_LEN_USED 2 -/* Length of the binary encoded service address which is of course before the +/** Length of the binary encoded service address which is of course before the * base32 encoding. Construction is: * PUBKEY || CHECKSUM || VERSION * with 1 byte VERSION and 2 bytes CHECKSUM. The following is 35 bytes. */ #define HS_SERVICE_ADDR_LEN \ (ED25519_PUBKEY_LEN + HS_SERVICE_ADDR_CHECKSUM_LEN_USED + sizeof(uint8_t)) -/* Length of 'y' portion of 'y.onion' URL. This is base32 encoded and the +/** Length of 'y' portion of 'y.onion' URL. This is base32 encoded and the * length ends up to 56 bytes (not counting the terminated NUL byte.) */ #define HS_SERVICE_ADDR_LEN_BASE32 \ (CEIL_DIV(HS_SERVICE_ADDR_LEN * 8, 5)) -/* The default HS time period length */ +/** The default HS time period length */ #define HS_TIME_PERIOD_LENGTH_DEFAULT 1440 /* 1440 minutes == one day */ -/* The minimum time period length as seen in prop224 section [TIME-PERIODS] */ +/** The minimum time period length as seen in prop224 section [TIME-PERIODS] */ #define HS_TIME_PERIOD_LENGTH_MIN 30 /* minutes */ -/* The minimum time period length as seen in prop224 section [TIME-PERIODS] */ +/** The minimum time period length as seen in prop224 section [TIME-PERIODS] */ #define HS_TIME_PERIOD_LENGTH_MAX (60 * 24 * 10) /* 10 days or 14400 minutes */ -/* The time period rotation offset as seen in prop224 section [TIME-PERIODS] */ +/** The time period rotation offset as seen in prop224 section + * [TIME-PERIODS] */ #define HS_TIME_PERIOD_ROTATION_OFFSET (12 * 60) /* minutes */ -/* Keyblinding parameter construction is as follow: +/** Keyblinding parameter construction is as follow: * "key-blind" || INT_8(period_num) || INT_8(start_period_sec) */ #define HS_KEYBLIND_NONCE_PREFIX "key-blind" #define HS_KEYBLIND_NONCE_PREFIX_LEN (sizeof(HS_KEYBLIND_NONCE_PREFIX) - 1) #define HS_KEYBLIND_NONCE_LEN \ (HS_KEYBLIND_NONCE_PREFIX_LEN + sizeof(uint64_t) + sizeof(uint64_t)) -/* Credential and subcredential prefix value. */ +/** Credential and subcredential prefix value. */ #define HS_CREDENTIAL_PREFIX "credential" #define HS_CREDENTIAL_PREFIX_LEN (sizeof(HS_CREDENTIAL_PREFIX) - 1) #define HS_SUBCREDENTIAL_PREFIX "subcredential" #define HS_SUBCREDENTIAL_PREFIX_LEN (sizeof(HS_SUBCREDENTIAL_PREFIX) - 1) -/* Node hidden service stored at index prefix value. */ +/** Node hidden service stored at index prefix value. */ #define HS_INDEX_PREFIX "store-at-idx" #define HS_INDEX_PREFIX_LEN (sizeof(HS_INDEX_PREFIX) - 1) -/* Node hidden service directory index prefix value. */ +/** Node hidden service directory index prefix value. */ #define HSDIR_INDEX_PREFIX "node-idx" #define HSDIR_INDEX_PREFIX_LEN (sizeof(HSDIR_INDEX_PREFIX) - 1) -/* Prefix of the shared random value disaster mode. */ +/** Prefix of the shared random value disaster mode. */ #define HS_SRV_DISASTER_PREFIX "shared-random-disaster" #define HS_SRV_DISASTER_PREFIX_LEN (sizeof(HS_SRV_DISASTER_PREFIX) - 1) -/* Default value of number of hsdir replicas (hsdir_n_replicas). */ +/** Default value of number of hsdir replicas (hsdir_n_replicas). */ #define HS_DEFAULT_HSDIR_N_REPLICAS 2 -/* Default value of hsdir spread store (hsdir_spread_store). */ +/** Default value of hsdir spread store (hsdir_spread_store). */ #define HS_DEFAULT_HSDIR_SPREAD_STORE 4 -/* Default value of hsdir spread fetch (hsdir_spread_fetch). */ +/** Default value of hsdir spread fetch (hsdir_spread_fetch). */ #define HS_DEFAULT_HSDIR_SPREAD_FETCH 3 -/* The size of a legacy RENDEZVOUS1 cell which adds up to 168 bytes. It is +/** The size of a legacy RENDEZVOUS1 cell which adds up to 168 bytes. It is * bigger than the 84 bytes needed for version 3 so we need to pad up to that * length so it is indistinguishable between versions. */ #define HS_LEGACY_RENDEZVOUS_CELL_SIZE \ (REND_COOKIE_LEN + DH1024_KEY_LEN + DIGEST_LEN) -/* Type of authentication key used by an introduction point. */ +/** Type of authentication key used by an introduction point. */ typedef enum { HS_AUTH_KEY_TYPE_LEGACY = 1, HS_AUTH_KEY_TYPE_ED25519 = 2, } hs_auth_key_type_t; -/* Return value when adding an ephemeral service through the ADD_ONION +/** Return value when adding an ephemeral service through the ADD_ONION * control port command. Both v2 and v3 share these. */ typedef enum { RSAE_BADAUTH = -5, /**< Invalid auth_type/auth_clients */ @@ -146,18 +148,18 @@ typedef enum { RSAE_OKAY = 0 /**< Service added as expected */ } hs_service_add_ephemeral_status_t; -/* Represents the mapping from a virtual port of a rendezvous service to a +/** Represents the mapping from a virtual port of a rendezvous service to a * real port on some IP. */ typedef struct rend_service_port_config_t { - /* The incoming HS virtual port we're mapping */ + /** The incoming HS virtual port we're mapping */ uint16_t virtual_port; - /* Is this an AF_UNIX port? */ + /** Is this an AF_UNIX port? */ unsigned int is_unix_addr:1; - /* The outgoing TCP port to use, if !is_unix_addr */ + /** The outgoing TCP port to use, if !is_unix_addr */ uint16_t real_port; - /* The outgoing IPv4 or IPv6 address to use, if !is_unix_addr */ + /** The outgoing IPv4 or IPv6 address to use, if !is_unix_addr */ tor_addr_t real_addr; - /* The socket path to connect to, if is_unix_addr */ + /** The socket path to connect to, if is_unix_addr */ char unix_addr[FLEXIBLE_ARRAY_MEMBER]; } rend_service_port_config_t; diff --git a/src/feature/hs/hs_descriptor.c b/src/feature/hs/hs_descriptor.c index 924ab3115e..60f2bfb0de 100644 --- a/src/feature/hs/hs_descriptor.c +++ b/src/feature/hs/hs_descriptor.c @@ -102,7 +102,7 @@ #define str_desc_auth_client "auth-client" #define str_encrypted "encrypted" -/* Authentication supported types. */ +/** Authentication supported types. */ static const struct { hs_desc_auth_type_t type; const char *identifier; @@ -112,7 +112,7 @@ static const struct { { 0, NULL } }; -/* Descriptor ruleset. */ +/** Descriptor ruleset. */ static token_rule_t hs_desc_v3_token_table[] = { T1_START(str_hs_desc, R_HS_DESCRIPTOR, EQ(1), NO_OBJ), T1(str_lifetime, R3_DESC_LIFETIME, EQ(1), NO_OBJ), @@ -123,7 +123,7 @@ static token_rule_t hs_desc_v3_token_table[] = { END_OF_TABLE }; -/* Descriptor ruleset for the superencrypted section. */ +/** Descriptor ruleset for the superencrypted section. */ static token_rule_t hs_desc_superencrypted_v3_token_table[] = { T1_START(str_desc_auth_type, R3_DESC_AUTH_TYPE, GE(1), NO_OBJ), T1(str_desc_auth_key, R3_DESC_AUTH_KEY, GE(1), NO_OBJ), @@ -132,7 +132,7 @@ static token_rule_t hs_desc_superencrypted_v3_token_table[] = { END_OF_TABLE }; -/* Descriptor ruleset for the encrypted section. */ +/** Descriptor ruleset for the encrypted section. */ static token_rule_t hs_desc_encrypted_v3_token_table[] = { T1_START(str_create2_formats, R3_CREATE2_FORMATS, CONCAT_ARGS, NO_OBJ), T01(str_intro_auth_required, R3_INTRO_AUTH_REQUIRED, ARGS, NO_OBJ), @@ -140,7 +140,7 @@ static token_rule_t hs_desc_encrypted_v3_token_table[] = { END_OF_TABLE }; -/* Descriptor ruleset for the introduction points section. */ +/** Descriptor ruleset for the introduction points section. */ static token_rule_t hs_desc_intro_point_v3_token_table[] = { T1_START(str_intro_point, R3_INTRODUCTION_POINT, EQ(1), NO_OBJ), T1N(str_ip_onion_key, R3_INTRO_ONION_KEY, GE(2), OBJ_OK), @@ -152,7 +152,7 @@ static token_rule_t hs_desc_intro_point_v3_token_table[] = { END_OF_TABLE }; -/* Using a key, salt and encrypted payload, build a MAC and put it in mac_out. +/** Using a key, salt and encrypted payload, build a MAC and put it in mac_out. * We use SHA3-256 for the MAC computation. * This function can't fail. */ static void @@ -184,7 +184,7 @@ build_mac(const uint8_t *mac_key, size_t mac_key_len, crypto_digest_free(digest); } -/* Using a secret data and a given decriptor object, build the secret +/** Using a secret data and a given decriptor object, build the secret * input needed for the KDF. * * secret_input = SECRET_DATA | subcredential | INT_8(revision_counter) @@ -224,7 +224,7 @@ build_secret_input(const hs_descriptor_t *desc, return secret_input_len; } -/* Do the KDF construction and put the resulting data in key_out which is of +/** Do the KDF construction and put the resulting data in key_out which is of * key_out_len length. It uses SHAKE-256 as specified in the spec. */ static void build_kdf_key(const hs_descriptor_t *desc, @@ -269,7 +269,7 @@ build_kdf_key(const hs_descriptor_t *desc, tor_free(secret_input); } -/* Using the given descriptor, secret data, and salt, run it through our +/** Using the given descriptor, secret data, and salt, run it through our * KDF function and then extract a secret key in key_out, the IV in iv_out * and MAC in mac_out. This function can't fail. */ static void @@ -308,7 +308,7 @@ build_secret_key_iv_mac(const hs_descriptor_t *desc, /* === ENCODING === */ -/* Encode the given link specifier objects into a newly allocated string. +/** Encode the given link specifier objects into a newly allocated string. * This can't fail so caller can always assume a valid string being * returned. */ STATIC char * @@ -355,7 +355,7 @@ encode_link_specifiers(const smartlist_t *specs) return encoded_b64; } -/* Encode an introduction point legacy key and certificate. Return a newly +/** Encode an introduction point legacy key and certificate. Return a newly * allocated string with it. On failure, return NULL. */ static char * encode_legacy_key(const hs_desc_intro_point_t *ip) @@ -392,7 +392,7 @@ encode_legacy_key(const hs_desc_intro_point_t *ip) return encoded; } -/* Encode an introduction point encryption key and certificate. Return a newly +/** Encode an introduction point encryption key and certificate. Return a newly * allocated string with it. On failure, return NULL. */ static char * encode_enc_key(const hs_desc_intro_point_t *ip) @@ -418,7 +418,7 @@ encode_enc_key(const hs_desc_intro_point_t *ip) return encoded; } -/* Encode an introduction point onion key. Return a newly allocated string +/** Encode an introduction point onion key. Return a newly allocated string * with it. Can not fail. */ static char * encode_onion_key(const hs_desc_intro_point_t *ip) @@ -435,7 +435,7 @@ encode_onion_key(const hs_desc_intro_point_t *ip) return encoded; } -/* Encode an introduction point object and return a newly allocated string +/** Encode an introduction point object and return a newly allocated string * with it. On failure, return NULL. */ static char * encode_intro_point(const ed25519_public_key_t *sig_key, @@ -505,7 +505,7 @@ encode_intro_point(const ed25519_public_key_t *sig_key, return encoded_ip; } -/* Given a source length, return the new size including padding for the +/** Given a source length, return the new size including padding for the * plaintext encryption. */ static size_t compute_padded_plaintext_length(size_t plaintext_len) @@ -525,7 +525,7 @@ compute_padded_plaintext_length(size_t plaintext_len) return plaintext_padded_len; } -/* Given a buffer, pad it up to the encrypted section padding requirement. Set +/** Given a buffer, pad it up to the encrypted section padding requirement. Set * the newly allocated string in padded_out and return the length of the * padded buffer. */ STATIC size_t @@ -548,7 +548,7 @@ build_plaintext_padding(const char *plaintext, size_t plaintext_len, return padded_len; } -/* Using a key, IV and plaintext data of length plaintext_len, create the +/** Using a key, IV and plaintext data of length plaintext_len, create the * encrypted section by encrypting it and setting encrypted_out with the * data. Return size of the encrypted data buffer. */ static size_t @@ -593,7 +593,7 @@ build_encrypted(const uint8_t *key, const uint8_t *iv, const char *plaintext, return encrypted_len; } -/* Encrypt the given <b>plaintext</b> buffer using <b>desc</b> and +/** Encrypt the given <b>plaintext</b> buffer using <b>desc</b> and * <b>secret_data</b> to get the keys. Set encrypted_out with the encrypted * data and return the length of it. <b>is_superencrypted_layer</b> is set * if this is the outer encrypted layer of the descriptor. */ @@ -663,7 +663,7 @@ encrypt_descriptor_data(const hs_descriptor_t *desc, return final_blob_len; } -/* Create and return a string containing a client-auth entry. It's the +/** Create and return a string containing a client-auth entry. It's the * responsibility of the caller to free the returned string. This function * will never fail. */ static char * @@ -733,7 +733,7 @@ get_all_auth_client_lines(const hs_descriptor_t *desc) return auth_client_lines_str; } -/* Create the inner layer of the descriptor (which includes the intro points, +/** Create the inner layer of the descriptor (which includes the intro points, * etc.). Return a newly-allocated string with the layer plaintext, or NULL if * an error occurred. It's the responsibility of the caller to free the * returned string. */ @@ -789,7 +789,7 @@ get_inner_encrypted_layer_plaintext(const hs_descriptor_t *desc) return encoded_str; } -/* Create the middle layer of the descriptor, which includes the client auth +/** Create the middle layer of the descriptor, which includes the client auth * data and the encrypted inner layer (provided as a base64 string at * <b>layer2_b64_ciphertext</b>). Return a newly-allocated string with the * layer plaintext. It's the responsibility of the caller to free the returned @@ -845,7 +845,7 @@ get_outer_encrypted_layer_plaintext(const hs_descriptor_t *desc, return layer1_str; } -/* Encrypt <b>encoded_str</b> into an encrypted blob and then base64 it before +/** Encrypt <b>encoded_str</b> into an encrypted blob and then base64 it before * returning it. <b>desc</b> is provided to derive the encryption * keys. <b>secret_data</b> is also proved to derive the encryption keys. * <b>is_superencrypted_layer</b> is set if <b>encoded_str</b> is the @@ -878,7 +878,7 @@ encrypt_desc_data_and_base64(const hs_descriptor_t *desc, return enc_b64; } -/* Generate the secret data which is used to encrypt/decrypt the descriptor. +/** Generate the secret data which is used to encrypt/decrypt the descriptor. * * SECRET_DATA = blinded-public-key * SECRET_DATA = blinded-public-key | descriptor_cookie @@ -925,7 +925,7 @@ build_secret_data(const ed25519_public_key_t *blinded_pubkey, return secret_data_len; } -/* Generate and encode the superencrypted portion of <b>desc</b>. This also +/** Generate and encode the superencrypted portion of <b>desc</b>. This also * involves generating the encrypted portion of the descriptor, and performing * the superencryption. A newly allocated NUL-terminated string pointer * containing the encrypted encoded blob is put in encrypted_blob_out. Return 0 @@ -999,7 +999,7 @@ encode_superencrypted_data(const hs_descriptor_t *desc, return ret; } -/* Encode a v3 HS descriptor. Return 0 on success and set encoded_out to the +/** Encode a v3 HS descriptor. Return 0 on success and set encoded_out to the * newly allocated string of the encoded descriptor. On error, -1 is returned * and encoded_out is untouched. */ static int @@ -1111,7 +1111,7 @@ desc_encode_v3(const hs_descriptor_t *desc, /* === DECODING === */ -/* Given the token tok for an auth client, decode it as +/** Given the token tok for an auth client, decode it as * hs_desc_authorized_client_t. tok->args MUST contain at least 3 elements * Return 0 on success else -1 on failure. */ static int @@ -1147,7 +1147,7 @@ decode_auth_client(const directory_token_t *tok, return ret; } -/* Given an encoded string of the link specifiers, return a newly allocated +/** Given an encoded string of the link specifiers, return a newly allocated * list of decoded link specifiers. Return NULL on error. */ STATIC smartlist_t * decode_link_specifiers(const char *encoded) @@ -1201,7 +1201,7 @@ decode_link_specifiers(const char *encoded) return results; } -/* Given a list of authentication types, decode it and put it in the encrypted +/** Given a list of authentication types, decode it and put it in the encrypted * data section. Return 1 if we at least know one of the type or 0 if we know * none of them. */ static int @@ -1229,7 +1229,7 @@ decode_auth_type(hs_desc_encrypted_data_t *desc, const char *list) return match; } -/* Parse a space-delimited list of integers representing CREATE2 formats into +/** Parse a space-delimited list of integers representing CREATE2 formats into * the bitfield in hs_desc_encrypted_data_t. Ignore unrecognized values. */ static void decode_create2_list(hs_desc_encrypted_data_t *desc, const char *list) @@ -1263,7 +1263,7 @@ decode_create2_list(hs_desc_encrypted_data_t *desc, const char *list) smartlist_free(tokens); } -/* Given a certificate, validate the certificate for certain conditions which +/** Given a certificate, validate the certificate for certain conditions which * are if the given type matches the cert's one, if the signing key is * included and if the that key was actually used to sign the certificate. * @@ -1300,7 +1300,7 @@ cert_is_valid(tor_cert_t *cert, uint8_t type, const char *log_obj_type) return 0; } -/* Given some binary data, try to parse it to get a certificate object. If we +/** Given some binary data, try to parse it to get a certificate object. If we * have a valid cert, validate it using the given wanted type. On error, print * a log using the err_msg has the certificate identifier adding semantic to * the log and cert_out is set to NULL. On success, 0 is returned and cert_out @@ -1337,7 +1337,7 @@ cert_parse_and_validate(tor_cert_t **cert_out, const char *data, return -1; } -/* Return true iff the given length of the encrypted data of a descriptor +/** Return true iff the given length of the encrypted data of a descriptor * passes validation. */ STATIC int encrypted_data_length_is_valid(size_t len) @@ -1356,7 +1356,7 @@ encrypted_data_length_is_valid(size_t len) return 0; } -/* Build the KEYS component for the authorized client computation. The format +/** Build the KEYS component for the authorized client computation. The format * of the construction is: * * SECRET_SEED = x25519(sk, pk) @@ -1400,7 +1400,7 @@ build_descriptor_cookie_keys(const uint8_t *subcredential, return keystream_len; } -/* Decrypt the descriptor cookie given the descriptor, the auth client, +/** Decrypt the descriptor cookie given the descriptor, the auth client, * and the client secret key. On sucess, return 0 and a newly allocated * descriptor cookie descriptor_cookie_out. On error or if the client id * is invalid, return -1 and descriptor_cookie_out is set to @@ -1592,7 +1592,7 @@ decrypt_desc_layer,(const hs_descriptor_t *desc, return result_len; } -/* Decrypt the superencrypted section of the descriptor using the given +/** Decrypt the superencrypted section of the descriptor using the given * descriptor object <b>desc</b>. A newly allocated NUL terminated string is * put in decrypted_out which contains the superencrypted layer of the * descriptor. Return the length of decrypted_out on success else 0 is @@ -1624,7 +1624,7 @@ desc_decrypt_superencrypted(const hs_descriptor_t *desc, char **decrypted_out) return superencrypted_len; } -/* Decrypt the encrypted section of the descriptor using the given descriptor +/** Decrypt the encrypted section of the descriptor using the given descriptor * object <b>desc</b>. A newly allocated NUL terminated string is put in * decrypted_out which contains the encrypted layer of the descriptor. * Return the length of decrypted_out on success else 0 is returned and @@ -1677,7 +1677,7 @@ desc_decrypt_encrypted(const hs_descriptor_t *desc, return encrypted_len; } -/* Given the token tok for an intro point legacy key, the list of tokens, the +/** Given the token tok for an intro point legacy key, the list of tokens, the * introduction point ip being decoded and the descriptor desc from which it * comes from, decode the legacy key and set the intro point object. Return 0 * on success else -1 on failure. */ @@ -1735,7 +1735,7 @@ decode_intro_legacy_key(const directory_token_t *tok, return -1; } -/* Dig into the descriptor <b>tokens</b> to find the onion key we should use +/** Dig into the descriptor <b>tokens</b> to find the onion key we should use * for this intro point, and set it into <b>onion_key_out</b>. Return 0 if it * was found and well-formed, otherwise return -1 in case of errors. */ static int @@ -1779,7 +1779,7 @@ set_intro_point_onion_key(curve25519_public_key_t *onion_key_out, return retval; } -/* Given the start of a section and the end of it, decode a single +/** Given the start of a section and the end of it, decode a single * introduction point from that section. Return a newly allocated introduction * point object containing the decoded data. Return NULL if the section can't * be decoded. */ @@ -1908,7 +1908,7 @@ decode_introduction_point(const hs_descriptor_t *desc, const char *start) return ip; } -/* Given a descriptor string at <b>data</b>, decode all possible introduction +/** Given a descriptor string at <b>data</b>, decode all possible introduction * points that we can find. Add the introduction point object to desc_enc as we * find them. This function can't fail and it is possible that zero * introduction points can be decoded. */ @@ -1972,7 +1972,7 @@ decode_intro_points(const hs_descriptor_t *desc, smartlist_free(intro_points); } -/* Return 1 iff the given base64 encoded signature in b64_sig from the encoded +/** Return 1 iff the given base64 encoded signature in b64_sig from the encoded * descriptor in encoded_desc validates the descriptor content. */ STATIC int desc_sig_is_valid(const char *b64_sig, @@ -2031,7 +2031,7 @@ desc_sig_is_valid(const char *b64_sig, return ret; } -/* Decode descriptor plaintext data for version 3. Given a list of tokens, an +/** Decode descriptor plaintext data for version 3. Given a list of tokens, an * allocated plaintext object that will be populated and the encoded * descriptor with its length. The last one is needed for signature * verification. Unknown tokens are simply ignored so this won't error on @@ -2134,7 +2134,7 @@ desc_decode_plaintext_v3(smartlist_t *tokens, return -1; } -/* Decode the version 3 superencrypted section of the given descriptor desc. +/** Decode the version 3 superencrypted section of the given descriptor desc. * The desc_superencrypted_out will be populated with the decoded data. * Return 0 on success else -1. */ static int @@ -2249,7 +2249,7 @@ desc_decode_superencrypted_v3(const hs_descriptor_t *desc, return ret; } -/* Decode the version 3 encrypted section of the given descriptor desc. The +/** Decode the version 3 encrypted section of the given descriptor desc. The * desc_encrypted_out will be populated with the decoded data. Return 0 on * success else -1. */ static int @@ -2364,7 +2364,7 @@ desc_decode_encrypted_v3(const hs_descriptor_t *desc, return ret; } -/* Table of encrypted decode function version specific. The function are +/** Table of encrypted decode function version specific. The function are * indexed by the version number so v3 callback is at index 3 in the array. */ static int (*decode_encrypted_handlers[])( @@ -2376,7 +2376,7 @@ static int desc_decode_encrypted_v3, }; -/* Decode the encrypted data section of the given descriptor and store the +/** Decode the encrypted data section of the given descriptor and store the * data in the given encrypted data object. Return 0 on success else a * negative value on error. */ int @@ -2417,7 +2417,7 @@ hs_desc_decode_encrypted(const hs_descriptor_t *desc, return ret; } -/* Table of superencrypted decode function version specific. The function are +/** Table of superencrypted decode function version specific. The function are * indexed by the version number so v3 callback is at index 3 in the array. */ static int (*decode_superencrypted_handlers[])( @@ -2428,9 +2428,9 @@ static int desc_decode_superencrypted_v3, }; -/* Decode the superencrypted data section of the given descriptor and store the - * data in the given superencrypted data object. Return 0 on success else a - * negative value on error. */ +/** Decode the superencrypted data section of the given descriptor and store + * the data in the given superencrypted data object. Return 0 on success else + * a negative value on error. */ int hs_desc_decode_superencrypted(const hs_descriptor_t *desc, hs_desc_superencrypted_data_t * @@ -2468,7 +2468,7 @@ hs_desc_decode_superencrypted(const hs_descriptor_t *desc, return ret; } -/* Table of plaintext decode function version specific. The function are +/** Table of plaintext decode function version specific. The function are * indexed by the version number so v3 callback is at index 3 in the array. */ static int (*decode_plaintext_handlers[])( @@ -2481,7 +2481,7 @@ static int desc_decode_plaintext_v3, }; -/* Fully decode the given descriptor plaintext and store the data in the +/** Fully decode the given descriptor plaintext and store the data in the * plaintext data object. Returns 0 on success else a negative value. */ int hs_desc_decode_plaintext(const char *encoded, @@ -2554,7 +2554,7 @@ hs_desc_decode_plaintext(const char *encoded, return ret; } -/* Fully decode an encoded descriptor and set a newly allocated descriptor +/** Fully decode an encoded descriptor and set a newly allocated descriptor * object in desc_out. Client secret key is used to decrypt the "encrypted" * section if not NULL else it's ignored. * @@ -2614,7 +2614,7 @@ hs_desc_decode_descriptor(const char *encoded, return ret; } -/* Table of encode function version specific. The functions are indexed by the +/** Table of encode function version specific. The functions are indexed by the * version number so v3 callback is at index 3 in the array. */ static int (*encode_handlers[])( @@ -2627,7 +2627,7 @@ static int desc_encode_v3, }; -/* Encode the given descriptor desc including signing with the given key pair +/** Encode the given descriptor desc including signing with the given key pair * signing_kp and encrypting with the given descriptor cookie. * * If the client authorization is enabled, descriptor_cookie must be the same @@ -2684,7 +2684,7 @@ hs_desc_encode_descriptor,(const hs_descriptor_t *desc, return ret; } -/* Free the content of the plaintext section of a descriptor. */ +/** Free the content of the plaintext section of a descriptor. */ void hs_desc_plaintext_data_free_contents(hs_desc_plaintext_data_t *desc) { @@ -2700,7 +2700,7 @@ hs_desc_plaintext_data_free_contents(hs_desc_plaintext_data_t *desc) memwipe(desc, 0, sizeof(*desc)); } -/* Free the content of the superencrypted section of a descriptor. */ +/** Free the content of the superencrypted section of a descriptor. */ void hs_desc_superencrypted_data_free_contents(hs_desc_superencrypted_data_t *desc) { @@ -2720,7 +2720,7 @@ hs_desc_superencrypted_data_free_contents(hs_desc_superencrypted_data_t *desc) memwipe(desc, 0, sizeof(*desc)); } -/* Free the content of the encrypted section of a descriptor. */ +/** Free the content of the encrypted section of a descriptor. */ void hs_desc_encrypted_data_free_contents(hs_desc_encrypted_data_t *desc) { @@ -2740,7 +2740,7 @@ hs_desc_encrypted_data_free_contents(hs_desc_encrypted_data_t *desc) memwipe(desc, 0, sizeof(*desc)); } -/* Free the descriptor plaintext data object. */ +/** Free the descriptor plaintext data object. */ void hs_desc_plaintext_data_free_(hs_desc_plaintext_data_t *desc) { @@ -2748,7 +2748,7 @@ hs_desc_plaintext_data_free_(hs_desc_plaintext_data_t *desc) tor_free(desc); } -/* Free the descriptor plaintext data object. */ +/** Free the descriptor plaintext data object. */ void hs_desc_superencrypted_data_free_(hs_desc_superencrypted_data_t *desc) { @@ -2756,7 +2756,7 @@ hs_desc_superencrypted_data_free_(hs_desc_superencrypted_data_t *desc) tor_free(desc); } -/* Free the descriptor encrypted data object. */ +/** Free the descriptor encrypted data object. */ void hs_desc_encrypted_data_free_(hs_desc_encrypted_data_t *desc) { @@ -2764,7 +2764,7 @@ hs_desc_encrypted_data_free_(hs_desc_encrypted_data_t *desc) tor_free(desc); } -/* Free the given descriptor object. */ +/** Free the given descriptor object. */ void hs_descriptor_free_(hs_descriptor_t *desc) { @@ -2778,7 +2778,7 @@ hs_descriptor_free_(hs_descriptor_t *desc) tor_free(desc); } -/* Return the size in bytes of the given plaintext data object. A sizeof() is +/** Return the size in bytes of the given plaintext data object. A sizeof() is * not enough because the object contains pointers and the encrypted blob. * This is particularly useful for our OOM subsystem that tracks the HSDir * cache size for instance. */ @@ -2790,7 +2790,7 @@ hs_desc_plaintext_obj_size(const hs_desc_plaintext_data_t *data) data->superencrypted_blob_size); } -/* Return the size in bytes of the given encrypted data object. Used by OOM +/** Return the size in bytes of the given encrypted data object. Used by OOM * subsystem. */ static size_t hs_desc_encrypted_obj_size(const hs_desc_encrypted_data_t *data) @@ -2810,7 +2810,7 @@ hs_desc_encrypted_obj_size(const hs_desc_encrypted_data_t *data) return sizeof(*data) + intro_size; } -/* Return the size in bytes of the given descriptor object. Used by OOM +/** Return the size in bytes of the given descriptor object. Used by OOM * subsystem. */ size_t hs_desc_obj_size(const hs_descriptor_t *data) @@ -2821,7 +2821,7 @@ hs_desc_obj_size(const hs_descriptor_t *data) sizeof(data->subcredential)); } -/* Return a newly allocated descriptor intro point. */ +/** Return a newly allocated descriptor intro point. */ hs_desc_intro_point_t * hs_desc_intro_point_new(void) { @@ -2830,7 +2830,7 @@ hs_desc_intro_point_new(void) return ip; } -/* Free a descriptor intro point object. */ +/** Free a descriptor intro point object. */ void hs_desc_intro_point_free_(hs_desc_intro_point_t *ip) { @@ -2849,7 +2849,7 @@ hs_desc_intro_point_free_(hs_desc_intro_point_t *ip) tor_free(ip); } -/* Allocate and build a new fake client info for the descriptor. Return a +/** Allocate and build a new fake client info for the descriptor. Return a * newly allocated object. This can't fail. */ hs_desc_authorized_client_t * hs_desc_build_fake_authorized_client(void) @@ -2867,7 +2867,7 @@ hs_desc_build_fake_authorized_client(void) return client_auth; } -/* Using the service's subcredential, client public key, auth ephemeral secret +/** Using the service's subcredential, client public key, auth ephemeral secret * key, and descriptor cookie, build the auth client so we can then encode the * descriptor for publication. client_out must be already allocated. */ void @@ -2925,14 +2925,14 @@ hs_desc_build_authorized_client(const uint8_t *subcredential, crypto_cipher_free(cipher); } -/* Free an authoriezd client object. */ +/** Free an authoriezd client object. */ void hs_desc_authorized_client_free_(hs_desc_authorized_client_t *client) { tor_free(client); } -/* From the given descriptor, remove and free every introduction point. */ +/** From the given descriptor, remove and free every introduction point. */ void hs_descriptor_clear_intro_points(hs_descriptor_t *desc) { diff --git a/src/feature/hs/hs_descriptor.h b/src/feature/hs/hs_descriptor.h index 0a843f4f3c..731e0c5ce9 100644 --- a/src/feature/hs/hs_descriptor.h +++ b/src/feature/hs/hs_descriptor.h @@ -18,88 +18,88 @@ /* Trunnel */ struct link_specifier_t; -/* The earliest descriptor format version we support. */ +/** The earliest descriptor format version we support. */ #define HS_DESC_SUPPORTED_FORMAT_VERSION_MIN 3 -/* The latest descriptor format version we support. */ +/** The latest descriptor format version we support. */ #define HS_DESC_SUPPORTED_FORMAT_VERSION_MAX 3 -/* Default lifetime of a descriptor in seconds. The valus is set at 3 hours +/** Default lifetime of a descriptor in seconds. The valus is set at 3 hours * which is 180 minutes or 10800 seconds. */ #define HS_DESC_DEFAULT_LIFETIME (3 * 60 * 60) -/* Maximum lifetime of a descriptor in seconds. The value is set at 12 hours +/** Maximum lifetime of a descriptor in seconds. The value is set at 12 hours * which is 720 minutes or 43200 seconds. */ #define HS_DESC_MAX_LIFETIME (12 * 60 * 60) -/* Lifetime of certificate in the descriptor. This defines the lifetime of the +/** Lifetime of certificate in the descriptor. This defines the lifetime of the * descriptor signing key and the cross certification cert of that key. It is * set to 54 hours because a descriptor can be around for 48 hours and because * consensuses are used after the hour, add an extra 6 hours to give some time * for the service to stop using it. */ #define HS_DESC_CERT_LIFETIME (54 * 60 * 60) -/* Length of the salt needed for the encrypted section of a descriptor. */ +/** Length of the salt needed for the encrypted section of a descriptor. */ #define HS_DESC_ENCRYPTED_SALT_LEN 16 -/* Length of the KDF output value which is the length of the secret key, +/** Length of the KDF output value which is the length of the secret key, * the secret IV and MAC key length which is the length of H() output. */ #define HS_DESC_ENCRYPTED_KDF_OUTPUT_LEN \ CIPHER256_KEY_LEN + CIPHER_IV_LEN + DIGEST256_LEN -/* Pad plaintext of superencrypted data section before encryption so that its +/** Pad plaintext of superencrypted data section before encryption so that its * length is a multiple of this value. */ #define HS_DESC_SUPERENC_PLAINTEXT_PAD_MULTIPLE 10000 -/* Maximum length in bytes of a full hidden service descriptor. */ +/** Maximum length in bytes of a full hidden service descriptor. */ #define HS_DESC_MAX_LEN 50000 /* 50kb max size */ -/* Key length for the descriptor symmetric encryption. As specified in the +/** Key length for the descriptor symmetric encryption. As specified in the * protocol, we use AES-256 for the encrypted section of the descriptor. The * following is the length in bytes and the bit size. */ #define HS_DESC_ENCRYPTED_KEY_LEN CIPHER256_KEY_LEN #define HS_DESC_ENCRYPTED_BIT_SIZE (HS_DESC_ENCRYPTED_KEY_LEN * 8) -/* Length of each components in the auth client section in the descriptor. */ +/** Length of each components in the auth client section in the descriptor. */ #define HS_DESC_CLIENT_ID_LEN 8 #define HS_DESC_DESCRIPTOR_COOKIE_LEN 16 #define HS_DESC_COOKIE_KEY_LEN 32 #define HS_DESC_COOKIE_KEY_BIT_SIZE (HS_DESC_COOKIE_KEY_LEN * 8) #define HS_DESC_ENCRYPED_COOKIE_LEN HS_DESC_DESCRIPTOR_COOKIE_LEN -/* The number of auth client entries in the descriptor must be the multiple +/** The number of auth client entries in the descriptor must be the multiple * of this constant. */ #define HS_DESC_AUTH_CLIENT_MULTIPLE 16 -/* Type of authentication in the descriptor. */ +/** Type of authentication in the descriptor. */ typedef enum { HS_DESC_AUTH_ED25519 = 1 } hs_desc_auth_type_t; -/* Introduction point information located in a descriptor. */ +/** Introduction point information located in a descriptor. */ typedef struct hs_desc_intro_point_t { - /* Link specifier(s) which details how to extend to the relay. This list + /** Link specifier(s) which details how to extend to the relay. This list * contains link_specifier_t objects. It MUST have at least one. */ smartlist_t *link_specifiers; - /* Onion key of the introduction point used to extend to it for the ntor + /** Onion key of the introduction point used to extend to it for the ntor * handshake. */ curve25519_public_key_t onion_key; - /* Authentication key used to establish the introduction point circuit and + /** Authentication key used to establish the introduction point circuit and * cross-certifies the blinded public key for the replica thus signed by * the blinded key and in turn signs it. */ tor_cert_t *auth_key_cert; - /* Encryption key for the "ntor" type. */ + /** Encryption key for the "ntor" type. */ curve25519_public_key_t enc_key; - /* Certificate cross certifying the descriptor signing key by the encryption + /** Certificate cross certifying the descriptor signing key by the encryption * curve25519 key. This certificate contains the signing key and is of type * CERT_TYPE_CROSS_HS_IP_KEYS [0B]. */ tor_cert_t *enc_key_cert; - /* (Optional): If this introduction point is a legacy one that is version <= + /** (Optional): If this introduction point is a legacy one that is version <= * 0.2.9.x (HSIntro=3), we use this extra key for the intro point to be able * to relay the cells to the service correctly. */ struct { - /* RSA public key. */ + /** RSA public key. */ crypto_pk_t *key; - /* Cross certified cert with the descriptor signing key (RSA->Ed). Because + /** Cross certified cert with the descriptor signing key (RSA->Ed). Because * of the cross certification API, we need to keep the certificate binary * blob and its length in order to properly encode it after. */ struct { @@ -108,115 +108,115 @@ typedef struct hs_desc_intro_point_t { } cert; } legacy; - /* True iff the introduction point has passed the cross certification. Upon + /** True iff the introduction point has passed the cross certification. Upon * decoding an intro point, this must be true. */ unsigned int cross_certified : 1; } hs_desc_intro_point_t; -/* Authorized client information located in a descriptor. */ +/** Authorized client information located in a descriptor. */ typedef struct hs_desc_authorized_client_t { - /* An identifier that the client will use to identify which auth client + /** An identifier that the client will use to identify which auth client * entry it needs to use. */ uint8_t client_id[HS_DESC_CLIENT_ID_LEN]; - /* An IV that is used to decrypt the encrypted descriptor cookie. */ + /** An IV that is used to decrypt the encrypted descriptor cookie. */ uint8_t iv[CIPHER_IV_LEN]; - /* An encrypted descriptor cookie that the client needs to decrypt to use + /** An encrypted descriptor cookie that the client needs to decrypt to use * it to decrypt the descriptor. */ uint8_t encrypted_cookie[HS_DESC_ENCRYPED_COOKIE_LEN]; } hs_desc_authorized_client_t; -/* The encrypted data section of a descriptor. Obviously the data in this is +/** The encrypted data section of a descriptor. Obviously the data in this is * in plaintext but encrypted once encoded. */ typedef struct hs_desc_encrypted_data_t { - /* Bitfield of CREATE2 cell supported formats. The only currently supported + /** Bitfield of CREATE2 cell supported formats. The only currently supported * format is ntor. */ unsigned int create2_ntor : 1; - /* A list of authentication types that a client must at least support one + /** A list of authentication types that a client must at least support one * in order to contact the service. Contains NULL terminated strings. */ smartlist_t *intro_auth_types; - /* Is this descriptor a single onion service? */ + /** Is this descriptor a single onion service? */ unsigned int single_onion_service : 1; - /* A list of intro points. Contains hs_desc_intro_point_t objects. */ + /** A list of intro points. Contains hs_desc_intro_point_t objects. */ smartlist_t *intro_points; } hs_desc_encrypted_data_t; -/* The superencrypted data section of a descriptor. Obviously the data in +/** The superencrypted data section of a descriptor. Obviously the data in * this is in plaintext but encrypted once encoded. */ typedef struct hs_desc_superencrypted_data_t { - /* This field contains ephemeral x25519 public key which is used by + /** This field contains ephemeral x25519 public key which is used by * the encryption scheme in the client authorization. */ curve25519_public_key_t auth_ephemeral_pubkey; - /* A list of authorized clients. Contains hs_desc_authorized_client_t + /** A list of authorized clients. Contains hs_desc_authorized_client_t * objects. */ smartlist_t *clients; - /* Decoding only: The b64-decoded encrypted blob from the descriptor */ + /** Decoding only: The b64-decoded encrypted blob from the descriptor */ uint8_t *encrypted_blob; - /* Decoding only: Size of the encrypted_blob */ + /** Decoding only: Size of the encrypted_blob */ size_t encrypted_blob_size; } hs_desc_superencrypted_data_t; -/* Plaintext data that is unencrypted information of the descriptor. */ +/** Plaintext data that is unencrypted information of the descriptor. */ typedef struct hs_desc_plaintext_data_t { - /* Version of the descriptor format. Spec specifies this field as a + /** Version of the descriptor format. Spec specifies this field as a * positive integer. */ uint32_t version; - /* The lifetime of the descriptor in seconds. */ + /** The lifetime of the descriptor in seconds. */ uint32_t lifetime_sec; - /* Certificate with the short-term ed22519 descriptor signing key for the + /** Certificate with the short-term ed22519 descriptor signing key for the * replica which is signed by the blinded public key for that replica. */ tor_cert_t *signing_key_cert; - /* Signing public key which is used to sign the descriptor. Same public key + /** Signing public key which is used to sign the descriptor. Same public key * as in the signing key certificate. */ ed25519_public_key_t signing_pubkey; - /* Blinded public key used for this descriptor derived from the master + /** Blinded public key used for this descriptor derived from the master * identity key and generated for a specific replica number. */ ed25519_public_key_t blinded_pubkey; - /* Revision counter is incremented at each upload, regardless of whether + /** Revision counter is incremented at each upload, regardless of whether * the descriptor has changed. This avoids leaking whether the descriptor * has changed. Spec specifies this as a 8 bytes positive integer. */ uint64_t revision_counter; - /* Decoding only: The b64-decoded superencrypted blob from the descriptor */ + /** Decoding only: The b64-decoded superencrypted blob from the descriptor */ uint8_t *superencrypted_blob; - /* Decoding only: Size of the superencrypted_blob */ + /** Decoding only: Size of the superencrypted_blob */ size_t superencrypted_blob_size; } hs_desc_plaintext_data_t; -/* Service descriptor in its decoded form. */ +/** Service descriptor in its decoded form. */ typedef struct hs_descriptor_t { - /* Contains the plaintext part of the descriptor. */ + /** Contains the plaintext part of the descriptor. */ hs_desc_plaintext_data_t plaintext_data; - /* The following contains what's in the superencrypted part of the + /** The following contains what's in the superencrypted part of the * descriptor. It's only encrypted in the encoded version of the descriptor * thus the data contained in that object is in plaintext. */ hs_desc_superencrypted_data_t superencrypted_data; - /* The following contains what's in the encrypted part of the descriptor. + /** The following contains what's in the encrypted part of the descriptor. * It's only encrypted in the encoded version of the descriptor thus the * data contained in that object is in plaintext. */ hs_desc_encrypted_data_t encrypted_data; - /* Subcredentials of a service, used by the client and service to decrypt + /** Subcredentials of a service, used by the client and service to decrypt * the encrypted data. */ uint8_t subcredential[DIGEST256_LEN]; } hs_descriptor_t; -/* Return true iff the given descriptor format version is supported. */ +/** Return true iff the given descriptor format version is supported. */ static inline int hs_desc_is_supported_version(uint32_t version) { diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c index 18c38ebc0a..d0fb77fdaa 100644 --- a/src/feature/hs/hs_service.c +++ b/src/feature/hs/hs_service.c @@ -67,7 +67,8 @@ #include <unistd.h> #endif -/* Helper macro. Iterate over every service in the global map. The var is the +#ifndef COCCI +/** Helper macro. Iterate over every service in the global map. The var is the * name of the service pointer. */ #define FOR_EACH_SERVICE_BEGIN(var) \ STMT_BEGIN \ @@ -76,7 +77,7 @@ var = *var##_iter; #define FOR_EACH_SERVICE_END } STMT_END ; -/* Helper macro. Iterate over both current and previous descriptor of a +/** Helper macro. Iterate over both current and previous descriptor of a * service. The var is the name of the descriptor pointer. This macro skips * any descriptor object of the service that is NULL. */ #define FOR_EACH_DESCRIPTOR_BEGIN(service, var) \ @@ -88,6 +89,7 @@ (var = service->desc_next); \ if (var == NULL) continue; #define FOR_EACH_DESCRIPTOR_END } STMT_END ; +#endif /* !defined(COCCI) */ /* Onion service directory file names. */ static const char fname_keyfile_prefix[] = "hs_ed25519"; @@ -95,7 +97,7 @@ static const char dname_client_pubkeys[] = "authorized_clients"; static const char fname_hostname[] = "hostname"; static const char address_tld[] = "onion"; -/* Staging list of service object. When configuring service, we add them to +/** Staging list of service object. When configuring service, we add them to * this list considered a staging area and they will get added to our global * map once the keys have been loaded. These two steps are separated because * loading keys requires that we are an actual running tor process. */ @@ -118,7 +120,7 @@ static int service_encode_descriptor(const hs_service_t *service, const ed25519_keypair_t *signing_kp, char **encoded_out); -/* Helper: Function to compare two objects in the service map. Return 1 if the +/** Helper: Function to compare two objects in the service map. Return 1 if the * two service have the same master public identity key. */ static inline int hs_service_ht_eq(const hs_service_t *first, const hs_service_t *second) @@ -130,7 +132,7 @@ hs_service_ht_eq(const hs_service_t *first, const hs_service_t *second) &second->keys.identity_pk); } -/* Helper: Function for the service hash table code below. The key used is the +/** Helper: Function for the service hash table code below. The key used is the * master public identity key which is ultimately the onion address. */ static inline unsigned int hs_service_ht_hash(const hs_service_t *service) @@ -140,7 +142,7 @@ hs_service_ht_hash(const hs_service_t *service) sizeof(service->keys.identity_pk.pubkey)); } -/* This is _the_ global hash map of hidden services which indexed the service +/** This is _the_ global hash map of hidden services which indexed the service * contained in it by master public identity key which is roughly the onion * address of the service. */ static struct hs_service_ht *hs_service_map; @@ -156,7 +158,7 @@ HT_GENERATE2(hs_service_ht, hs_service_t, hs_service_node, hs_service_ht_hash, hs_service_ht_eq, 0.6, tor_reallocarray, tor_free_) -/* Query the given service map with a public key and return a service object +/** Query the given service map with a public key and return a service object * if found else NULL. It is also possible to set a directory path in the * search query. If pk is NULL, then it will be set to zero indicating the * hash table to compare the directory path instead. */ @@ -171,7 +173,7 @@ find_service(hs_service_ht *map, const ed25519_public_key_t *pk) return HT_FIND(hs_service_ht, map, &dummy_service); } -/* Register the given service in the given map. If the service already exists +/** Register the given service in the given map. If the service already exists * in the map, -1 is returned. On success, 0 is returned and the service * ownership has been transferred to the global map. */ STATIC int @@ -196,7 +198,7 @@ register_service(hs_service_ht *map, hs_service_t *service) return 0; } -/* Remove a given service from the given map. If service is NULL or the +/** Remove a given service from the given map. If service is NULL or the * service key is unset, return gracefully. */ STATIC void remove_service(hs_service_ht *map, hs_service_t *service) @@ -226,7 +228,7 @@ remove_service(hs_service_ht *map, hs_service_t *service) } } -/* Set the default values for a service configuration object <b>c</b>. */ +/** Set the default values for a service configuration object <b>c</b>. */ static void set_service_default_config(hs_service_config_t *c, const or_options_t *options) @@ -247,7 +249,7 @@ set_service_default_config(hs_service_config_t *c, c->intro_dos_burst_per_sec = HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_DEFAULT; } -/* From a service configuration object config, clear everything from it +/** From a service configuration object config, clear everything from it * meaning free allocated pointers and reset the values. */ STATIC void service_clear_config(hs_service_config_t *config) @@ -269,7 +271,7 @@ service_clear_config(hs_service_config_t *config) memset(config, 0, sizeof(*config)); } -/* Helper function to return a human readable description of the given intro +/** Helper function to return a human readable description of the given intro * point object. * * This function is not thread-safe. Each call to this invalidates the @@ -301,7 +303,7 @@ describe_intro_point(const hs_service_intro_point_t *ip) return buf; } -/* Return the lower bound of maximum INTRODUCE2 cells per circuit before we +/** Return the lower bound of maximum INTRODUCE2 cells per circuit before we * rotate intro point (defined by a consensus parameter or the default * value). */ static int32_t @@ -314,7 +316,7 @@ get_intro_point_min_introduce2(void) 0, INT32_MAX); } -/* Return the upper bound of maximum INTRODUCE2 cells per circuit before we +/** Return the upper bound of maximum INTRODUCE2 cells per circuit before we * rotate intro point (defined by a consensus parameter or the default * value). */ static int32_t @@ -327,8 +329,8 @@ get_intro_point_max_introduce2(void) 0, INT32_MAX); } -/* Return the minimum lifetime in seconds of an introduction point defined by a - * consensus parameter or the default value. */ +/** Return the minimum lifetime in seconds of an introduction point defined by + * a consensus parameter or the default value. */ static int32_t get_intro_point_min_lifetime(void) { @@ -344,8 +346,8 @@ get_intro_point_min_lifetime(void) 0, INT32_MAX); } -/* Return the maximum lifetime in seconds of an introduction point defined by a - * consensus parameter or the default value. */ +/** Return the maximum lifetime in seconds of an introduction point defined by + * a consensus parameter or the default value. */ static int32_t get_intro_point_max_lifetime(void) { @@ -361,7 +363,7 @@ get_intro_point_max_lifetime(void) 0, INT32_MAX); } -/* Return the number of extra introduction point defined by a consensus +/** Return the number of extra introduction point defined by a consensus * parameter or the default value. */ static int32_t get_intro_point_num_extra(void) @@ -372,7 +374,7 @@ get_intro_point_num_extra(void) NUM_INTRO_POINTS_EXTRA, 0, 128); } -/* Helper: Function that needs to return 1 for the HT for each loop which +/** Helper: Function that needs to return 1 for the HT for each loop which * frees every service in an hash map. */ static int ht_free_service_(struct hs_service_t *service, void *data) @@ -384,7 +386,7 @@ ht_free_service_(struct hs_service_t *service, void *data) return 1; } -/* Free every service that can be found in the global map. Once done, clear +/** Free every service that can be found in the global map. Once done, clear * and free the global map. */ static void service_free_all(void) @@ -406,7 +408,7 @@ service_free_all(void) } } -/* Free a given service intro point object. */ +/** Free a given service intro point object. */ STATIC void service_intro_point_free_(hs_service_intro_point_t *ip) { @@ -421,7 +423,7 @@ service_intro_point_free_(hs_service_intro_point_t *ip) tor_free(ip); } -/* Helper: free an hs_service_intro_point_t object. This function is used by +/** Helper: free an hs_service_intro_point_t object. This function is used by * digest256map_free() which requires a void * pointer. */ static void service_intro_point_free_void(void *obj) @@ -429,7 +431,7 @@ service_intro_point_free_void(void *obj) service_intro_point_free_(obj); } -/* Return a newly allocated service intro point and fully initialized from the +/** Return a newly allocated service intro point and fully initialized from the * given node_t node, if non NULL. * * If node is NULL, returns a hs_service_intro_point_t with an empty link @@ -523,7 +525,7 @@ service_intro_point_add(digest256map_t *map, hs_service_intro_point_t *ip) tor_assert_nonfatal(!old_ip_entry); } -/* For a given service, remove the intro point from that service's descriptors +/** For a given service, remove the intro point from that service's descriptors * (check both current and next descriptor) */ STATIC void service_intro_point_remove(const hs_service_t *service, @@ -541,7 +543,7 @@ service_intro_point_remove(const hs_service_t *service, } FOR_EACH_DESCRIPTOR_END; } -/* For a given service and authentication key, return the intro point or NULL +/** For a given service and authentication key, return the intro point or NULL * if not found. This will check both descriptors in the service. */ STATIC hs_service_intro_point_t * service_intro_point_find(const hs_service_t *service, @@ -572,7 +574,7 @@ service_intro_point_find(const hs_service_t *service, return ip; } -/* For a given service and intro point, return the descriptor for which the +/** For a given service and intro point, return the descriptor for which the * intro point is assigned to. NULL is returned if not found. */ STATIC hs_service_descriptor_t * service_desc_find_by_intro(const hs_service_t *service, @@ -594,7 +596,7 @@ service_desc_find_by_intro(const hs_service_t *service, return descp; } -/* From a circuit identifier, get all the possible objects associated with the +/** From a circuit identifier, get all the possible objects associated with the * ident. If not NULL, service, ip or desc are set if the object can be found. * They are untouched if they can't be found. * @@ -627,7 +629,7 @@ get_objects_from_ident(const hs_ident_circuit_t *ident, } } -/* From a given intro point, return the first link specifier of type +/** From a given intro point, return the first link specifier of type * encountered in the link specifier list. Return NULL if it can't be found. * * The caller does NOT have ownership of the object, the intro point does. */ @@ -650,7 +652,7 @@ get_link_spec_by_type(const hs_service_intro_point_t *ip, uint8_t type) return lnk_spec; } -/* Given a service intro point, return the node_t associated to it. This can +/** Given a service intro point, return the node_t associated to it. This can * return NULL if the given intro point has no legacy ID or if the node can't * be found in the consensus. */ STATIC const node_t * @@ -669,7 +671,7 @@ get_node_from_intro_point(const hs_service_intro_point_t *ip) (const char *) link_specifier_getconstarray_un_legacy_id(ls)); } -/* Given a service intro point, return the extend_info_t for it. This can +/** Given a service intro point, return the extend_info_t for it. This can * return NULL if the node can't be found for the intro point or the extend * info can't be created for the found node. If direct_conn is set, the extend * info is validated on if we can connect directly. */ @@ -698,7 +700,7 @@ get_extend_info_from_intro_point(const hs_service_intro_point_t *ip, return info; } -/* Return the number of introduction points that are established for the +/** Return the number of introduction points that are established for the * given descriptor. */ static unsigned int count_desc_circuit_established(const hs_service_descriptor_t *desc) @@ -709,13 +711,13 @@ count_desc_circuit_established(const hs_service_descriptor_t *desc) DIGEST256MAP_FOREACH(desc->intro_points.map, key, const hs_service_intro_point_t *, ip) { - count += ip->circuit_established; + count += !!hs_circ_service_get_established_intro_circ(ip); } DIGEST256MAP_FOREACH_END; return count; } -/* For a given service and descriptor of that service, close all active +/** For a given service and descriptor of that service, close all active * directory connections. */ static void close_directory_connections(const hs_service_t *service, @@ -750,7 +752,7 @@ close_directory_connections(const hs_service_t *service, smartlist_free(dir_conns); } -/* Close all rendezvous circuits for the given service. */ +/** Close all rendezvous circuits for the given service. */ static void close_service_rp_circuits(hs_service_t *service) { @@ -780,7 +782,7 @@ close_service_rp_circuits(hs_service_t *service) } } -/* Close the circuit(s) for the given map of introduction points. */ +/** Close the circuit(s) for the given map of introduction points. */ static void close_intro_circuits(hs_service_intropoints_t *intro_points) { @@ -798,7 +800,7 @@ close_intro_circuits(hs_service_intropoints_t *intro_points) } DIGEST256MAP_FOREACH_END; } -/* Close all introduction circuits for the given service. */ +/** Close all introduction circuits for the given service. */ static void close_service_intro_circuits(hs_service_t *service) { @@ -809,7 +811,7 @@ close_service_intro_circuits(hs_service_t *service) } FOR_EACH_DESCRIPTOR_END; } -/* Close any circuits related to the given service. */ +/** Close any circuits related to the given service. */ static void close_service_circuits(hs_service_t *service) { @@ -825,7 +827,7 @@ close_service_circuits(hs_service_t *service) close_service_rp_circuits(service); } -/* Move every ephemeral services from the src service map to the dst service +/** Move every ephemeral services from the src service map to the dst service * map. It is possible that a service can't be register to the dst map which * won't stop the process of moving them all but will trigger a log warn. */ static void @@ -855,7 +857,7 @@ move_ephemeral_services(hs_service_ht *src, hs_service_ht *dst) } } -/* Return a const string of the directory path escaped. If this is an +/** Return a const string of the directory path escaped. If this is an * ephemeral service, it returns "[EPHEMERAL]". This can only be called from * the main thread because escaped() uses a static variable. */ static const char * @@ -889,7 +891,7 @@ move_hs_state(hs_service_t *src_service, hs_service_t *dst_service) src->replay_cache_rend_cookie = NULL; /* steal pointer reference */ } -/* Register services that are in the staging list. Once this function returns, +/** Register services that are in the staging list. Once this function returns, * the global service map will be set with the right content and all non * surviving services will be cleaned up. */ static void @@ -957,7 +959,7 @@ register_all_services(void) hs_service_map_has_changed(); } -/* Write the onion address of a given service to the given filename fname_ in +/** Write the onion address of a given service to the given filename fname_ in * the service directory. Return 0 on success else -1 on error. */ STATIC int write_address_to_file(const hs_service_t *service, const char *fname_) @@ -998,7 +1000,7 @@ write_address_to_file(const hs_service_t *service, const char *fname_) return ret; } -/* Load and/or generate private keys for the given service. On success, the +/** Load and/or generate private keys for the given service. On success, the * hostname file will be written to disk along with the master private key iff * the service is not configured for offline keys. Return 0 on success else -1 * on failure. */ @@ -1096,7 +1098,7 @@ client_filename_is_valid(const char *filename) return ret; } -/* Parse an authorized client from a string. The format of a client string +/** Parse an authorized client from a string. The format of a client string * looks like (see rend-spec-v3.txt): * * <auth-type>:<key-type>:<base32-encoded-public-key> @@ -1178,7 +1180,7 @@ parse_authorized_client(const char *client_key_str) return client; } -/* Load all the client public keys for the given service. Return 0 on +/** Load all the client public keys for the given service. Return 0 on * success else -1 on failure. */ static int load_client_keys(hs_service_t *service) @@ -1281,6 +1283,7 @@ load_client_keys(hs_service_t *service) return ret; } +/** Release all storage held in <b>client</b>. */ STATIC void service_authorized_client_free_(hs_service_authorized_client_t *client) { @@ -1291,7 +1294,7 @@ service_authorized_client_free_(hs_service_authorized_client_t *client) tor_free(client); } -/* Free a given service descriptor object and all key material is wiped. */ +/** Free a given service descriptor object and all key material is wiped. */ STATIC void service_descriptor_free_(hs_service_descriptor_t *desc) { @@ -1312,7 +1315,7 @@ service_descriptor_free_(hs_service_descriptor_t *desc) tor_free(desc); } -/* Return a newly allocated service descriptor object. */ +/** Return a newly allocated service descriptor object. */ STATIC hs_service_descriptor_t * service_descriptor_new(void) { @@ -1325,7 +1328,7 @@ service_descriptor_new(void) return sdesc; } -/* Allocate and return a deep copy of client. */ +/** Allocate and return a deep copy of client. */ static hs_service_authorized_client_t * service_authorized_client_dup(const hs_service_authorized_client_t *client) { @@ -1343,7 +1346,7 @@ service_authorized_client_dup(const hs_service_authorized_client_t *client) return client_dup; } -/* If two authorized clients are equal, return 0. If the first one should come +/** If two authorized clients are equal, return 0. If the first one should come * before the second, return less than zero. If the first should come after * the second, return greater than zero. */ static int @@ -1360,7 +1363,7 @@ service_authorized_client_cmp(const hs_service_authorized_client_t *client1, CURVE25519_PUBKEY_LEN); } -/* Helper for sorting authorized clients. */ +/** Helper for sorting authorized clients. */ static int compare_service_authorzized_client_(const void **_a, const void **_b) { @@ -1368,7 +1371,7 @@ compare_service_authorzized_client_(const void **_a, const void **_b) return service_authorized_client_cmp(a, b); } -/* If the list of hs_service_authorized_client_t's is different between +/** If the list of hs_service_authorized_client_t's is different between * src and dst, return 1. Otherwise, return 0. */ STATIC int service_authorized_client_config_equal(const hs_service_config_t *config1, @@ -1429,7 +1432,7 @@ service_authorized_client_config_equal(const hs_service_config_t *config1, return ret; } -/* Move descriptor(s) from the src service to the dst service and modify their +/** Move descriptor(s) from the src service to the dst service and modify their * content if necessary. We do this during SIGHUP when we re-create our * hidden services. */ static void @@ -1488,7 +1491,7 @@ move_descriptors(hs_service_t *src, hs_service_t *dst) service_descriptor_free(dst->desc_next); } -/* From the given service, remove all expired failing intro points for each +/** From the given service, remove all expired failing intro points for each * descriptor. */ static void remove_expired_failing_intro(hs_service_t *service, time_t now) @@ -1507,7 +1510,7 @@ remove_expired_failing_intro(hs_service_t *service, time_t now) } FOR_EACH_DESCRIPTOR_END; } -/* For the given descriptor desc, put all node_t object found from its failing +/** For the given descriptor desc, put all node_t object found from its failing * intro point list and put them in the given node_list. */ static void setup_intro_point_exclude_list(const hs_service_descriptor_t *desc, @@ -1525,7 +1528,7 @@ setup_intro_point_exclude_list(const hs_service_descriptor_t *desc, } DIGESTMAP_FOREACH_END; } -/* For the given failing intro point ip, we add its time of failure to the +/** For the given failing intro point ip, we add its time of failure to the * failed map and index it by identity digest (legacy ID) in the descriptor * desc failed id map. */ static void @@ -1549,7 +1552,7 @@ remember_failing_intro_point(const hs_service_intro_point_t *ip, tor_free(prev_ptr); } -/* Using a given descriptor signing keypair signing_kp, a service intro point +/** Using a given descriptor signing keypair signing_kp, a service intro point * object ip and the time now, setup the content of an already allocated * descriptor intro desc_ip. * @@ -1638,7 +1641,7 @@ setup_desc_intro_point(const ed25519_keypair_t *signing_kp, return ret; } -/* Using the given descriptor from the given service, build the descriptor +/** Using the given descriptor from the given service, build the descriptor * intro point list so we can then encode the descriptor for publication. This * function does not pick intro points, they have to be in the descriptor * current map. Cryptographic material (keys) must be initialized in the @@ -1659,7 +1662,7 @@ build_desc_intro_points(const hs_service_t *service, DIGEST256MAP_FOREACH(desc->intro_points.map, key, const hs_service_intro_point_t *, ip) { - if (!ip->circuit_established) { + if (!hs_circ_service_get_established_intro_circ(ip)) { /* Ignore un-established intro points. They can linger in that list * because their circuit has not opened and they haven't been removed * yet even though we have enough intro circuits. @@ -1678,7 +1681,7 @@ build_desc_intro_points(const hs_service_t *service, } DIGEST256MAP_FOREACH_END; } -/* Build the descriptor signing key certificate. */ +/** Build the descriptor signing key certificate. */ static void build_desc_signing_key_cert(hs_service_descriptor_t *desc, time_t now) { @@ -1704,7 +1707,7 @@ build_desc_signing_key_cert(hs_service_descriptor_t *desc, time_t now) tor_assert_nonfatal(plaintext->signing_key_cert); } -/* Populate the descriptor encrypted section from the given service object. +/** Populate the descriptor encrypted section from the given service object. * This will generate a valid list of introduction points that can be used * after for circuit creation. Return 0 on success else -1 on error. */ static int @@ -1817,7 +1820,7 @@ build_service_desc_superencrypted(const hs_service_t *service, return 0; } -/* Populate the descriptor plaintext section from the given service object. +/** Populate the descriptor plaintext section from the given service object. * The caller must make sure that the keys in the descriptors are valid that * is are non-zero. This can't fail. */ static void @@ -1868,7 +1871,7 @@ generate_ope_cipher_for_desc(const hs_service_descriptor_t *hs_desc) return crypto_ope_new(key); } -/* For the given service and descriptor object, create the key material which +/** For the given service and descriptor object, create the key material which * is the blinded keypair, the descriptor signing keypair, the ephemeral * keypair, and the descriptor cookie. Return 0 on success else -1 on error * where the generated keys MUST be ignored. */ @@ -1930,7 +1933,7 @@ build_service_desc_keys(const hs_service_t *service, return ret; } -/* Given a service and the current time, build a descriptor for the service. +/** Given a service and the current time, build a descriptor for the service. * This function does not pick introduction point, this needs to be done by * the update function. On success, desc_out will point to the newly allocated * descriptor object. @@ -1987,7 +1990,7 @@ build_service_descriptor(hs_service_t *service, uint64_t time_period_num, service_descriptor_free(desc); } -/* Build both descriptors for the given service that has just booted up. +/** Build both descriptors for the given service that has just booted up. * Because it's a special case, it deserves its special function ;). */ static void build_descriptors_for_new_service(hs_service_t *service, time_t now) @@ -2037,7 +2040,7 @@ build_descriptors_for_new_service(hs_service_t *service, time_t now) safe_str_client(service->onion_address)); } -/* Build descriptors for each service if needed. There are conditions to build +/** Build descriptors for each service if needed. There are conditions to build * a descriptor which are details in the function. */ STATIC void build_all_descriptors(time_t now) @@ -2070,7 +2073,7 @@ build_all_descriptors(time_t now) } FOR_EACH_DESCRIPTOR_END; } -/* Randomly pick a node to become an introduction point but not present in the +/** Randomly pick a node to become an introduction point but not present in the * given exclude_nodes list. The chosen node is put in the exclude list * regardless of success or not because in case of failure, the node is simply * unsusable from that point on. @@ -2131,7 +2134,7 @@ pick_intro_point(unsigned int direct_conn, smartlist_t *exclude_nodes) return NULL; } -/* For a given descriptor from the given service, pick any needed intro points +/** For a given descriptor from the given service, pick any needed intro points * and update the current map with those newly picked intro points. Return the * number node that might have been added to the descriptor current map. */ static unsigned int @@ -2255,7 +2258,7 @@ service_desc_schedule_upload(hs_service_descriptor_t *desc, } } -/* Pick missing intro points for this descriptor if needed. */ +/** Pick missing intro points for this descriptor if needed. */ static void update_service_descriptor_intro_points(hs_service_t *service, hs_service_descriptor_t *desc, time_t now) @@ -2296,7 +2299,7 @@ update_service_descriptor_intro_points(hs_service_t *service, } } -/* Update descriptor intro points for each service if needed. We do this as +/** Update descriptor intro points for each service if needed. We do this as * part of the periodic event because we need to establish intro point circuits * before we publish descriptors. */ STATIC void @@ -2311,7 +2314,7 @@ update_all_descriptors_intro_points(time_t now) } FOR_EACH_SERVICE_END; } -/* Return true iff the given intro point has expired that is it has been used +/** Return true iff the given intro point has expired that is it has been used * for too long or we've reached our max seen INTRODUCE2 cell. */ STATIC int intro_point_should_expire(const hs_service_intro_point_t *ip, @@ -2333,7 +2336,7 @@ intro_point_should_expire(const hs_service_intro_point_t *ip, return 1; } -/* Return true iff we should remove the intro point ip from its service. +/** Return true iff we should remove the intro point ip from its service. * * We remove an intro point from the service descriptor list if one of * these criteria is met: @@ -2369,10 +2372,6 @@ should_remove_intro_point(hs_service_intro_point_t *ip, time_t now) * remove it because it might simply be valid and opened at the previous * scheduled event for the last retry. */ - /* Did we established already? */ - if (ip->circuit_established) { - goto end; - } /* Do we simply have an existing circuit regardless of its state? */ if (hs_circ_service_get_intro_circ(ip)) { goto end; @@ -2395,7 +2394,7 @@ should_remove_intro_point(hs_service_intro_point_t *ip, time_t now) return ret; } -/* Go over the given set of intro points for each service and remove any +/** Go over the given set of intro points for each service and remove any * invalid ones. * * If an intro point is removed, the circuit (if any) is immediately close. @@ -2458,7 +2457,7 @@ cleanup_intro_points(hs_service_t *service, time_t now) smartlist_free(ips_to_free); } -/* Set the next rotation time of the descriptors for the given service for the +/** Set the next rotation time of the descriptors for the given service for the * time now. */ static void set_rotation_time(hs_service_t *service) @@ -2477,7 +2476,7 @@ set_rotation_time(hs_service_t *service) } } -/* Return true iff the service should rotate its descriptor. The time now is +/** Return true iff the service should rotate its descriptor. The time now is * only used to fetch the live consensus and if none can be found, this * returns false. */ static unsigned int @@ -2529,7 +2528,7 @@ should_rotate_descriptors(hs_service_t *service, time_t now) return 1; } -/* Rotate the service descriptors of the given service. The current descriptor +/** Rotate the service descriptors of the given service. The current descriptor * will be freed, the next one put in as the current and finally the next * descriptor pointer is NULLified. */ static void @@ -2551,7 +2550,7 @@ rotate_service_descriptors(hs_service_t *service) set_rotation_time(service); } -/* Rotate descriptors for each service if needed. A non existing current +/** Rotate descriptors for each service if needed. A non existing current * descriptor will trigger a descriptor build for the next time period. */ STATIC void rotate_all_descriptors(time_t now) @@ -2580,7 +2579,7 @@ rotate_all_descriptors(time_t now) } FOR_EACH_SERVICE_END; } -/* Scheduled event run from the main loop. Make sure all our services are up +/** Scheduled event run from the main loop. Make sure all our services are up * to date and ready for the other scheduled events. This includes looking at * the introduction points status and descriptor rotation time. */ STATIC void @@ -2615,7 +2614,7 @@ run_housekeeping_event(time_t now) } FOR_EACH_SERVICE_END; } -/* Scheduled event run from the main loop. Make sure all descriptors are up to +/** Scheduled event run from the main loop. Make sure all descriptors are up to * date. Once this returns, each service descriptor needs to be considered for * new introduction circuits and then for upload. */ static void @@ -2692,7 +2691,7 @@ launch_intro_point_circuits(hs_service_t *service) } FOR_EACH_DESCRIPTOR_END; } -/* Don't try to build more than this many circuits before giving up for a +/** Don't try to build more than this many circuits before giving up for a * while. Dynamically calculated based on the configured number of intro * points for the given service and how many descriptor exists. The default * use case of 3 introduction points and two descriptors will allow 28 @@ -2708,7 +2707,7 @@ get_max_intro_circ_per_period(const hs_service_t *service) tor_assert(service->config.num_intro_points <= HS_CONFIG_V3_MAX_INTRO_POINTS); -/* For a testing network, allow to do it for the maximum amount so circuit +/** For a testing network, allow to do it for the maximum amount so circuit * creation and rotation and so on can actually be tested without limit. */ #define MAX_INTRO_POINT_CIRCUIT_RETRIES_TESTING -1 if (get_options()->TestingTorNetwork) { @@ -2737,7 +2736,7 @@ get_max_intro_circ_per_period(const hs_service_t *service) return (count * multiplier); } -/* For the given service, return 1 if the service is allowed to launch more +/** For the given service, return 1 if the service is allowed to launch more * introduction circuits else 0 if the maximum has been reached for the retry * period of INTRO_CIRC_RETRY_PERIOD. */ STATIC int @@ -2783,7 +2782,7 @@ can_service_launch_intro_circuit(hs_service_t *service, time_t now) return 1; } -/* Scheduled event run from the main loop. Make sure we have all the circuits +/** Scheduled event run from the main loop. Make sure we have all the circuits * we need for each service. */ static void run_build_circuit_event(time_t now) @@ -2813,7 +2812,7 @@ run_build_circuit_event(time_t now) } FOR_EACH_SERVICE_END; } -/* Encode and sign the service descriptor desc and upload it to the given +/** Encode and sign the service descriptor desc and upload it to the given * hidden service directory. This does nothing if PublishHidServDescriptors * is false. */ static void @@ -2949,7 +2948,7 @@ set_descriptor_revision_counter(hs_service_descriptor_t *hs_desc, time_t now, hs_desc->desc->plaintext_data.revision_counter = rev_counter; } -/* Encode and sign the service descriptor desc and upload it to the +/** Encode and sign the service descriptor desc and upload it to the * responsible hidden service directories. If for_next_period is true, the set * of directories are selected using the next hsdir_index. This does nothing * if PublishHidServDescriptors is false. */ @@ -3046,7 +3045,7 @@ service_desc_hsdirs_changed(const hs_service_t *service, return should_reupload; } -/* Return 1 if the given descriptor from the given service can be uploaded +/** Return 1 if the given descriptor from the given service can be uploaded * else return 0 if it can not. */ static int should_service_upload_descriptor(const hs_service_t *service, @@ -3103,7 +3102,7 @@ should_service_upload_descriptor(const hs_service_t *service, return 0; } -/* Refresh the given service descriptor meaning this will update every mutable +/** Refresh the given service descriptor meaning this will update every mutable * field that needs to be updated before we upload. * * This should ONLY be called before uploading a descriptor. It assumes that @@ -3134,7 +3133,7 @@ refresh_service_descriptor(const hs_service_t *service, set_descriptor_revision_counter(desc, now, service->desc_current == desc); } -/* Scheduled event run from the main loop. Try to upload the descriptor for +/** Scheduled event run from the main loop. Try to upload the descriptor for * each service. */ STATIC void run_upload_descriptor_event(time_t now) @@ -3183,7 +3182,7 @@ run_upload_descriptor_event(time_t now) consider_republishing_hs_descriptors = 0; } -/* Called when the introduction point circuit is done building and ready to be +/** Called when the introduction point circuit is done building and ready to be * used. */ static void service_intro_circ_has_opened(origin_circuit_t *circ) @@ -3241,7 +3240,7 @@ service_intro_circ_has_opened(origin_circuit_t *circ) return; } -/* Called when a rendezvous circuit is done building and ready to be used. */ +/** Called when a rendezvous circuit is done building and ready to be used. */ static void service_rendezvous_circ_has_opened(origin_circuit_t *circ) { @@ -3282,7 +3281,7 @@ service_rendezvous_circ_has_opened(origin_circuit_t *circ) return; } -/* We've been expecting an INTRO_ESTABLISHED cell on this circuit and it just +/** We've been expecting an INTRO_ESTABLISHED cell on this circuit and it just * arrived. Handle the INTRO_ESTABLISHED cell arriving on the given * introduction circuit. Return 0 on success else a negative value. */ static int @@ -3325,11 +3324,6 @@ service_handle_intro_established(origin_circuit_t *circ, goto err; } - /* Flag that we have an established circuit for this intro point. This value - * is what indicates the upload scheduled event if we are ready to build the - * intro point into the descriptor and upload. */ - ip->circuit_established = 1; - log_info(LD_REND, "Successfully received an INTRO_ESTABLISHED cell " "on circuit %u for service %s", TO_CIRCUIT(circ)->n_circ_id, @@ -3340,7 +3334,7 @@ service_handle_intro_established(origin_circuit_t *circ, return -1; } -/* We just received an INTRODUCE2 cell on the established introduction circuit +/** We just received an INTRODUCE2 cell on the established introduction circuit * circ. Handle the cell and return 0 on success else a negative value. */ static int service_handle_introduce2(origin_circuit_t *circ, const uint8_t *payload, @@ -3388,7 +3382,7 @@ service_handle_introduce2(origin_circuit_t *circ, const uint8_t *payload, return -1; } -/* Add to list every filename used by service. This is used by the sandbox +/** Add to list every filename used by service. This is used by the sandbox * subsystem. */ static void service_add_fnames_to_list(const hs_service_t *service, smartlist_t *list) @@ -3410,7 +3404,7 @@ service_add_fnames_to_list(const hs_service_t *service, smartlist_t *list) smartlist_add(list, hs_path_from_filename(s_dir, fname)); } -/* Return true iff the given service identity key is present on disk. */ +/** Return true iff the given service identity key is present on disk. */ static int service_key_on_disk(const char *directory_path) { @@ -3434,7 +3428,7 @@ service_key_on_disk(const char *directory_path) return ret; } -/* This is a proxy function before actually calling hs_desc_encode_descriptor +/** This is a proxy function before actually calling hs_desc_encode_descriptor * because we need some preprocessing here */ static int service_encode_descriptor(const hs_service_t *service, @@ -3465,7 +3459,7 @@ service_encode_descriptor(const hs_service_t *service, /* Public API */ /* ========== */ -/* This is called everytime the service map (v2 or v3) changes that is if an +/** This is called everytime the service map (v2 or v3) changes that is if an * element is added or removed. */ void hs_service_map_has_changed(void) @@ -3476,7 +3470,7 @@ hs_service_map_has_changed(void) rescan_periodic_events(get_options()); } -/* Upload an encoded descriptor in encoded_desc of the given version. This +/** Upload an encoded descriptor in encoded_desc of the given version. This * descriptor is for the service identity_pk and blinded_pk used to setup the * directory connection identifier. It is uploaded to the directory hsdir_rs * routerstatus_t object. @@ -3524,7 +3518,7 @@ hs_service_upload_desc_to_dir(const char *encoded_desc, directory_request_free(dir_req); } -/* Add the ephemeral service using the secret key sk and ports. Both max +/** Add the ephemeral service using the secret key sk and ports. Both max * streams parameter will be set in the newly created service. * * Ownership of sk and ports is passed to this routine. Regardless of @@ -3604,7 +3598,7 @@ hs_service_add_ephemeral(ed25519_secret_key_t *sk, smartlist_t *ports, return ret; } -/* For the given onion address, delete the ephemeral service. Return 0 on +/** For the given onion address, delete the ephemeral service. Return 0 on * success else -1 on error. */ int hs_service_del_ephemeral(const char *address) @@ -3654,7 +3648,7 @@ hs_service_del_ephemeral(const char *address) return -1; } -/* Using the ed25519 public key pk, find a service for that key and return the +/** Using the ed25519 public key pk, find a service for that key and return the * current encoded descriptor as a newly allocated string or NULL if not * found. This is used by the control port subsystem. */ char * @@ -3680,7 +3674,7 @@ hs_service_lookup_current_desc(const ed25519_public_key_t *pk) return NULL; } -/* Return the number of service we have configured and usable. */ +/** Return the number of service we have configured and usable. */ MOCK_IMPL(unsigned int, hs_service_get_num_services,(void)) { @@ -3690,7 +3684,7 @@ hs_service_get_num_services,(void)) return HT_SIZE(hs_service_map); } -/* Called once an introduction circuit is closed. If the circuit doesn't have +/** Called once an introduction circuit is closed. If the circuit doesn't have * a v3 identifier, it is ignored. */ void hs_service_intro_circ_has_closed(origin_circuit_t *circ) @@ -3724,15 +3718,11 @@ hs_service_intro_circ_has_closed(origin_circuit_t *circ) /* Can't have an intro point object without a descriptor. */ tor_assert(desc); - /* Circuit disappeared so make sure the intro point is updated. By - * keeping the object in the descriptor, we'll be able to retry. */ - ip->circuit_established = 0; - end: return; } -/* Given conn, a rendezvous edge connection acting as an exit stream, look up +/** Given conn, a rendezvous edge connection acting as an exit stream, look up * the hidden service for the circuit circ, and look up the port and address * based on the connection port. Assign the actual connection address. * @@ -3830,7 +3820,7 @@ hs_service_exports_circuit_id(const ed25519_public_key_t *pk) return service->config.circuit_id_protocol; } -/* Add to file_list every filename used by a configured hidden service, and to +/** Add to file_list every filename used by a configured hidden service, and to * dir_list every directory path used by a configured hidden service. This is * used by the sandbox subsystem to whitelist those. */ void @@ -3855,7 +3845,7 @@ hs_service_lists_fnames_for_sandbox(smartlist_t *file_list, } FOR_EACH_DESCRIPTOR_END; } -/* Called when our internal view of the directory has changed. We might have +/** Called when our internal view of the directory has changed. We might have * received a new batch of descriptors which might affect the shape of the * HSDir hash ring. Signal that we should reexamine the hash ring and * re-upload our HS descriptors if needed. */ @@ -3872,7 +3862,7 @@ hs_service_dir_info_changed(void) } } -/* Called when we get an INTRODUCE2 cell on the circ. Respond to the cell and +/** Called when we get an INTRODUCE2 cell on the circ. Respond to the cell and * launch a circuit to the rendezvous point. */ int hs_service_receive_introduce2(origin_circuit_t *circ, const uint8_t *payload, @@ -3903,7 +3893,7 @@ hs_service_receive_introduce2(origin_circuit_t *circ, const uint8_t *payload, return ret; } -/* Called when we get an INTRO_ESTABLISHED cell. Mark the circuit as an +/** Called when we get an INTRO_ESTABLISHED cell. Mark the circuit as an * established introduction point. Return 0 on success else a negative value * and the circuit is closed. */ int @@ -3940,7 +3930,7 @@ hs_service_receive_intro_established(origin_circuit_t *circ, return -1; } -/* Called when any kind of hidden service circuit is done building thus +/** Called when any kind of hidden service circuit is done building thus * opened. This is the entry point from the circuit subsystem. */ void hs_service_circuit_has_opened(origin_circuit_t *circ) @@ -3969,7 +3959,7 @@ hs_service_circuit_has_opened(origin_circuit_t *circ) } } -/* Return the service version by looking at the key in the service directory. +/** Return the service version by looking at the key in the service directory. * If the key is not found or unrecognized, -1 is returned. Else, the service * version is returned. */ int @@ -3999,7 +3989,7 @@ hs_service_get_version_from_key(const hs_service_t *service) return version; } -/* Load and/or generate keys for all onion services including the client +/** Load and/or generate keys for all onion services including the client * authorization if any. Return 0 on success, -1 on failure. */ int hs_service_load_all_keys(void) @@ -4035,7 +4025,7 @@ hs_service_load_all_keys(void) return -1; } -/* Put all service object in the given service list. After this, the caller +/** Put all service object in the given service list. After this, the caller * looses ownership of every elements in the list and responsible to free the * list pointer. */ void @@ -4052,7 +4042,7 @@ hs_service_stage_services(const smartlist_t *service_list) smartlist_add_all(hs_service_staging_list, service_list); } -/* Allocate and initilize a service object. The service configuration will +/** Allocate and initilize a service object. The service configuration will * contain the default values. Return the newly allocated object pointer. This * function can't fail. */ hs_service_t * @@ -4070,7 +4060,7 @@ hs_service_new(const or_options_t *options) return service; } -/* Free the given <b>service</b> object and all its content. This function +/** Free the given <b>service</b> object and all its content. This function * also takes care of wiping service keys from memory. It is safe to pass a * NULL pointer. */ void @@ -4099,7 +4089,7 @@ hs_service_free_(hs_service_t *service) tor_free(service); } -/* Periodic callback. Entry point from the main loop to the HS service +/** Periodic callback. Entry point from the main loop to the HS service * subsystem. This is call every second. This is skipped if tor can't build a * circuit or the network is disabled. */ void @@ -4122,7 +4112,7 @@ hs_service_run_scheduled_events(time_t now) run_upload_descriptor_event(now); } -/* Initialize the service HS subsystem. */ +/** Initialize the service HS subsystem. */ void hs_service_init(void) { @@ -4139,7 +4129,7 @@ hs_service_init(void) hs_service_staging_list = smartlist_new(); } -/* Release all global storage of the hidden service subsystem. */ +/** Release all global storage of the hidden service subsystem. */ void hs_service_free_all(void) { @@ -4149,14 +4139,14 @@ hs_service_free_all(void) #ifdef TOR_UNIT_TESTS -/* Return the global service map size. Only used by unit test. */ +/** Return the global service map size. Only used by unit test. */ STATIC unsigned int get_hs_service_map_size(void) { return HT_SIZE(hs_service_map); } -/* Return the staging list size. Only used by unit test. */ +/** Return the staging list size. Only used by unit test. */ STATIC int get_hs_service_staging_list_size(void) { diff --git a/src/feature/hs/hs_service.h b/src/feature/hs/hs_service.h index c4bbb293bb..193e08546f 100644 --- a/src/feature/hs/hs_service.h +++ b/src/feature/hs/hs_service.h @@ -21,92 +21,89 @@ /* Trunnel */ #include "trunnel/hs/cell_establish_intro.h" -/* When loading and configuring a service, this is the default version it will +/** When loading and configuring a service, this is the default version it will * be configured for as it is possible that no HiddenServiceVersion is * present. */ #define HS_SERVICE_DEFAULT_VERSION HS_VERSION_THREE -/* As described in the specification, service publishes their next descriptor +/** As described in the specification, service publishes their next descriptor * at a random time between those two values (in seconds). */ #define HS_SERVICE_NEXT_UPLOAD_TIME_MIN (60 * 60) #define HS_SERVICE_NEXT_UPLOAD_TIME_MAX (120 * 60) -/* Service side introduction point. */ +/** Service side introduction point. */ typedef struct hs_service_intro_point_t { - /* Top level intropoint "shared" data between client/service. */ + /** Top level intropoint "shared" data between client/service. */ hs_intropoint_t base; - /* Onion key of the introduction point used to extend to it for the ntor + /** Onion key of the introduction point used to extend to it for the ntor * handshake. */ curve25519_public_key_t onion_key; - /* Authentication keypair used to create the authentication certificate + /** Authentication keypair used to create the authentication certificate * which is published in the descriptor. */ ed25519_keypair_t auth_key_kp; - /* Encryption keypair for the "ntor" type. */ + /** Encryption keypair for the "ntor" type. */ curve25519_keypair_t enc_key_kp; - /* Legacy key if that intro point doesn't support v3. This should be used if + /** Legacy key if that intro point doesn't support v3. This should be used if * the base object legacy flag is set. */ crypto_pk_t *legacy_key; - /* Legacy key SHA1 public key digest. This should be used only if the base + /** Legacy key SHA1 public key digest. This should be used only if the base * object legacy flag is set. */ uint8_t legacy_key_digest[DIGEST_LEN]; - /* Amount of INTRODUCE2 cell accepted from this intro point. */ + /** Amount of INTRODUCE2 cell accepted from this intro point. */ uint64_t introduce2_count; - /* Maximum number of INTRODUCE2 cell this intro point should accept. */ + /** Maximum number of INTRODUCE2 cell this intro point should accept. */ uint64_t introduce2_max; - /* The time at which this intro point should expire and stop being used. */ + /** The time at which this intro point should expire and stop being used. */ time_t time_to_expire; - /* The amount of circuit creation we've made to this intro point. This is + /** The amount of circuit creation we've made to this intro point. This is * incremented every time we do a circuit relaunch on this intro point which * is triggered when the circuit dies but the node is still in the * consensus. After MAX_INTRO_POINT_CIRCUIT_RETRIES, we give up on it. */ uint32_t circuit_retries; - /* Set if this intro point has an established circuit. */ - unsigned int circuit_established : 1; - - /* Replay cache recording the encrypted part of an INTRODUCE2 cell that the + /** Replay cache recording the encrypted part of an INTRODUCE2 cell that the * circuit associated with this intro point has received. This is used to * prevent replay attacks. */ replaycache_t *replay_cache; - /* Support the INTRO2 DoS defense. If set, the DoS extension described by + /** Support the INTRO2 DoS defense. If set, the DoS extension described by * proposal 305 is sent. */ unsigned int support_intro2_dos_defense : 1; } hs_service_intro_point_t; -/* Object handling introduction points of a service. */ +/** Object handling introduction points of a service. */ typedef struct hs_service_intropoints_t { - /* The time at which we've started our retry period to build circuits. We + /** The time at which we've started our retry period to build circuits. We * don't want to stress circuit creation so we can only retry for a certain * time and then after we stop and wait. */ time_t retry_period_started; - /* Number of circuit we've launched during a single retry period. */ + /** Number of circuit we've launched during a single retry period. */ unsigned int num_circuits_launched; - /* Contains the current hs_service_intro_point_t objects indexed by + /** Contains the current hs_service_intro_point_t objects indexed by * authentication public key. */ digest256map_t *map; - /* Contains node's identity key digest that were introduction point for this + /** Contains node's identity key digest that were introduction point for this * descriptor but were retried to many times. We keep those so we avoid * re-picking them over and over for a circuit retry period. * XXX: Once we have #22173, change this to only use ed25519 identity. */ digestmap_t *failed_id; } hs_service_intropoints_t; -/* Representation of a service descriptor. +/** Representation of a service descriptor. * * Some elements of the descriptor are mutable whereas others are immutable: - + * * Immutable elements are initialized once when the descriptor is built (when * service descriptors gets rotated). This means that these elements are * initialized once and then they don't change for the lifetime of the @@ -121,40 +118,42 @@ typedef struct hs_service_intropoints_t { * update_service_descriptor_intro_points(). */ typedef struct hs_service_descriptor_t { - /* Immutable: Client authorization ephemeral keypair. */ + /** Immutable: Client authorization ephemeral keypair. */ curve25519_keypair_t auth_ephemeral_kp; - /* Immutable: Descriptor cookie used to encrypt the descriptor, when the + /** Immutable: Descriptor cookie used to encrypt the descriptor, when the * client authorization is enabled */ uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN]; - /* Immutable: Descriptor signing keypair. */ + /** Immutable: Descriptor signing keypair. */ ed25519_keypair_t signing_kp; - /* Immutable: Blinded keypair derived from the master identity public key. */ + /** Immutable: Blinded keypair derived from the master identity public + * key. */ ed25519_keypair_t blinded_kp; - /* Immutable: The time period number this descriptor has been created for. */ + /** Immutable: The time period number this descriptor has been created + * for. */ uint64_t time_period_num; /** Immutable: The OPE cipher for encrypting revision counters for this * descriptor. Tied to the descriptor blinded key. */ struct crypto_ope_t *ope_cipher; - /* Mutable: Decoded descriptor. This object is used for encoding when the + /** Mutable: Decoded descriptor. This object is used for encoding when the * service publishes the descriptor. */ hs_descriptor_t *desc; - /* Mutable: When is the next time when we should upload the descriptor. */ + /** Mutable: When is the next time when we should upload the descriptor. */ time_t next_upload_time; - /* Mutable: Introduction points assign to this descriptor which contains + /** Mutable: Introduction points assign to this descriptor which contains * hs_service_intropoints_t object indexed by authentication key (the RSA key * if the node is legacy). */ hs_service_intropoints_t intro_points; - /* Mutable: True iff we have missing intro points for this descriptor because - * we couldn't pick any nodes. */ + /** Mutable: True iff we have missing intro points for this descriptor + * because we couldn't pick any nodes. */ unsigned int missing_intro_points : 1; /** Mutable: List of the responsible HSDirs (their b64ed identity digest) @@ -164,20 +163,20 @@ typedef struct hs_service_descriptor_t { smartlist_t *previous_hsdirs; } hs_service_descriptor_t; -/* Service key material. */ +/** Service key material. */ typedef struct hs_service_keys_t { - /* Master identify public key. */ + /** Master identify public key. */ ed25519_public_key_t identity_pk; - /* Master identity private key. */ + /** Master identity private key. */ ed25519_secret_key_t identity_sk; - /* True iff the key is kept offline which means the identity_sk MUST not be + /** True iff the key is kept offline which means the identity_sk MUST not be * used in that case. */ unsigned int is_identify_key_offline : 1; } hs_service_keys_t; /** Service side configuration of client authorization. */ typedef struct hs_service_authorized_client_t { - /* The client auth public key used to encrypt the descriptor cookie. */ + /** The client auth public key used to encrypt the descriptor cookie. */ curve25519_public_key_t client_pk; } hs_service_authorized_client_t; @@ -190,60 +189,60 @@ typedef enum { HS_CIRCUIT_ID_PROTOCOL_HAPROXY } hs_circuit_id_protocol_t; -/* Service configuration. The following are set from the torrc options either +/** Service configuration. The following are set from the torrc options either * set by the configuration file or by the control port. Nothing else should * change those values. */ typedef struct hs_service_config_t { - /* Protocol version of the service. Specified by HiddenServiceVersion + /** Protocol version of the service. Specified by HiddenServiceVersion * option. */ uint32_t version; - /* Have we explicitly set HiddenServiceVersion? */ + /** Have we explicitly set HiddenServiceVersion? */ unsigned int hs_version_explicitly_set : 1; - /* List of rend_service_port_config_t */ + /** List of rend_service_port_config_t */ smartlist_t *ports; - /* Path on the filesystem where the service persistent data is stored. NULL + /** Path on the filesystem where the service persistent data is stored. NULL * if the service is ephemeral. Specified by HiddenServiceDir option. */ char *directory_path; - /* The maximum number of simultaneous streams per rendezvous circuit that + /** The maximum number of simultaneous streams per rendezvous circuit that * are allowed to be created. No limit if 0. Specified by * HiddenServiceMaxStreams option. */ uint64_t max_streams_per_rdv_circuit; - /* If true, we close circuits that exceed the max_streams_per_rdv_circuit + /** If true, we close circuits that exceed the max_streams_per_rdv_circuit * limit. Specified by HiddenServiceMaxStreamsCloseCircuit option. */ unsigned int max_streams_close_circuit : 1; - /* How many introduction points this service has. Specified by + /** How many introduction points this service has. Specified by * HiddenServiceNumIntroductionPoints option. */ unsigned int num_intro_points; - /* True iff the client auth is enabled. */ + /** True iff the client auth is enabled. */ unsigned int is_client_auth_enabled : 1; - /* List of hs_service_authorized_client_t's of clients that may access this + /** List of hs_service_authorized_client_t's of clients that may access this * service. Specified by HiddenServiceAuthorizeClient option. */ smartlist_t *clients; - /* True iff we allow request made on unknown ports. Specified by + /** True iff we allow request made on unknown ports. Specified by * HiddenServiceAllowUnknownPorts option. */ unsigned int allow_unknown_ports : 1; - /* If true, this service is a Single Onion Service. Specified by + /** If true, this service is a Single Onion Service. Specified by * HiddenServiceSingleHopMode and HiddenServiceNonAnonymousMode options. */ unsigned int is_single_onion : 1; - /* If true, allow group read permissions on the directory_path. Specified by + /** If true, allow group read permissions on the directory_path. Specified by * HiddenServiceDirGroupReadable option. */ unsigned int dir_group_readable : 1; - /* Is this service ephemeral? */ + /** Is this service ephemeral? */ unsigned int is_ephemeral : 1; - /* Does this service export the circuit ID of its clients? */ + /** Does this service export the circuit ID of its clients? */ hs_circuit_id_protocol_t circuit_id_protocol; /* DoS defenses. For the ESTABLISH_INTRO cell extension. */ @@ -252,58 +251,58 @@ typedef struct hs_service_config_t { uint32_t intro_dos_burst_per_sec; } hs_service_config_t; -/* Service state. */ +/** Service state. */ typedef struct hs_service_state_t { - /* The time at which we've started our retry period to build circuits. We + /** The time at which we've started our retry period to build circuits. We * don't want to stress circuit creation so we can only retry for a certain * time and then after we stop and wait. */ time_t intro_circ_retry_started_time; - /* Number of circuit we've launched during a single retry period. This + /** Number of circuit we've launched during a single retry period. This * should never go over MAX_INTRO_CIRCS_PER_PERIOD. */ unsigned int num_intro_circ_launched; - /* Replay cache tracking the REND_COOKIE found in INTRODUCE2 cell to detect + /** Replay cache tracking the REND_COOKIE found in INTRODUCE2 cell to detect * repeats. Clients may send INTRODUCE1 cells for the same rendezvous point * through two or more different introduction points; when they do, this * keeps us from launching multiple simultaneous attempts to connect to the * same rend point. */ replaycache_t *replay_cache_rend_cookie; - /* When is the next time we should rotate our descriptors. This is has to be + /** When is the next time we should rotate our descriptors. This is has to be * done at the start time of the next SRV protocol run. */ time_t next_rotation_time; } hs_service_state_t; -/* Representation of a service running on this tor instance. */ +/** Representation of a service running on this tor instance. */ typedef struct hs_service_t { - /* Onion address base32 encoded and NUL terminated. We keep it for logging + /** Onion address base32 encoded and NUL terminated. We keep it for logging * purposes so we don't have to build it everytime. */ char onion_address[HS_SERVICE_ADDR_LEN_BASE32 + 1]; - /* Hashtable node: use to look up the service by its master public identity + /** Hashtable node: use to look up the service by its master public identity * key in the service global map. */ HT_ENTRY(hs_service_t) hs_service_node; - /* Service state which contains various flags and counters. */ + /** Service state which contains various flags and counters. */ hs_service_state_t state; - /* Key material of the service. */ + /** Key material of the service. */ hs_service_keys_t keys; - /* Configuration of the service. */ + /** Configuration of the service. */ hs_service_config_t config; - /* Current descriptor. */ + /** Current descriptor. */ hs_service_descriptor_t *desc_current; - /* Next descriptor. */ + /** Next descriptor. */ hs_service_descriptor_t *desc_next; /* XXX: Credential (client auth.) #20700. */ } hs_service_t; -/* For the service global hash map, we define a specific type for it which +/** For the service global hash map, we define a specific type for it which * will make it safe to use and specific to some controlled parameters such as * the hashing function and how to compare services. */ typedef HT_HEAD(hs_service_ht, hs_service_t) hs_service_ht; diff --git a/src/feature/hs/hsdir_index_st.h b/src/feature/hs/hsdir_index_st.h index 6c86c02f47..34ff84f91f 100644 --- a/src/feature/hs/hsdir_index_st.h +++ b/src/feature/hs/hsdir_index_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file hsdir_index_st.h + * @brief HS directory index structure + **/ + #ifndef HSDIR_INDEX_ST_H #define HSDIR_INDEX_ST_H @@ -21,4 +26,3 @@ struct hsdir_index_t { }; #endif /* !defined(HSDIR_INDEX_ST_H) */ - diff --git a/src/feature/hs_common/feature_hs_common.dox b/src/feature/hs_common/feature_hs_common.dox new file mode 100644 index 0000000000..85d7585872 --- /dev/null +++ b/src/feature/hs_common/feature_hs_common.dox @@ -0,0 +1,5 @@ +/** +@dir /feature/hs_common +@brief feature/hs_common: Common to v2 (old) and v3 (current) onion services + +**/ diff --git a/src/feature/keymgt/feature_keymgt.dox b/src/feature/keymgt/feature_keymgt.dox new file mode 100644 index 0000000000..acc840eb2e --- /dev/null +++ b/src/feature/keymgt/feature_keymgt.dox @@ -0,0 +1,5 @@ +/** +@dir /feature/keymgt +@brief feature/keymgt: Store keys for relays, authorities, etc. + +**/ diff --git a/src/feature/keymgt/loadkey.c b/src/feature/keymgt/loadkey.c index a8cbf0e582..5c1e6353b8 100644 --- a/src/feature/keymgt/loadkey.c +++ b/src/feature/keymgt/loadkey.c @@ -33,7 +33,7 @@ /** Try to read an RSA key from <b>fname</b>. If <b>fname</b> doesn't exist * and <b>generate</b> is true, create a new RSA key and save it in * <b>fname</b>. Return the read/created key, or NULL on error. Log all - * errors at level <b>severity</b>. If <b>created_out/b> is non-NULL and a + * errors at level <b>severity</b>. If <b>created_out</b> is non-NULL and a * new key was created, set *<b>created_out</b> to true. */ crypto_pk_t * diff --git a/src/feature/nodelist/authority_cert_st.h b/src/feature/nodelist/authority_cert_st.h index bf9b690c24..6787487c7c 100644 --- a/src/feature/nodelist/authority_cert_st.h +++ b/src/feature/nodelist/authority_cert_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file authority_cert_st.h + * @brief Authority certificate structure. + **/ + #ifndef AUTHORITY_CERT_ST_H #define AUTHORITY_CERT_ST_H @@ -29,4 +34,3 @@ struct authority_cert_t { }; #endif /* !defined(AUTHORITY_CERT_ST_H) */ - diff --git a/src/feature/nodelist/desc_store_st.h b/src/feature/nodelist/desc_store_st.h index 4d1378cdfa..75300ecf97 100644 --- a/src/feature/nodelist/desc_store_st.h +++ b/src/feature/nodelist/desc_store_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file desc_store_st.h + * @brief Routerinfo/extrainfo storage structure. + **/ + #ifndef DESC_STORE_ST_H #define DESC_STORE_ST_H diff --git a/src/feature/nodelist/document_signature_st.h b/src/feature/nodelist/document_signature_st.h index ac2a803252..ba4581c1b8 100644 --- a/src/feature/nodelist/document_signature_st.h +++ b/src/feature/nodelist/document_signature_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file document_signature_st.h + * @brief Authority signature structure + **/ + #ifndef DOCUMENT_SIGNATURE_ST_H #define DOCUMENT_SIGNATURE_ST_H @@ -26,4 +31,3 @@ struct document_signature_t { }; #endif /* !defined(DOCUMENT_SIGNATURE_ST_H) */ - diff --git a/src/feature/nodelist/extrainfo_st.h b/src/feature/nodelist/extrainfo_st.h index 22c708f018..6d707bea05 100644 --- a/src/feature/nodelist/extrainfo_st.h +++ b/src/feature/nodelist/extrainfo_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file extrainfo_st.h + * @brief A relay's extra-info structure. + **/ + #ifndef EXTRAINFO_ST_H #define EXTRAINFO_ST_H @@ -27,4 +32,3 @@ struct extrainfo_t { }; #endif /* !defined(EXTRAINFO_ST_H) */ - diff --git a/src/feature/nodelist/feature_nodelist.dox b/src/feature/nodelist/feature_nodelist.dox new file mode 100644 index 0000000000..0b25dd246d --- /dev/null +++ b/src/feature/nodelist/feature_nodelist.dox @@ -0,0 +1,4 @@ +/** +@dir /feature/nodelist +@brief feature/nodelist: Download and manage a list of relays +**/ diff --git a/src/feature/nodelist/microdesc_st.h b/src/feature/nodelist/microdesc_st.h index e017c46c79..58b0630573 100644 --- a/src/feature/nodelist/microdesc_st.h +++ b/src/feature/nodelist/microdesc_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file microdesc_st.h + * @brief Microdescriptor structure + **/ + #ifndef MICRODESC_ST_H #define MICRODESC_ST_H diff --git a/src/feature/nodelist/networkstatus.c b/src/feature/nodelist/networkstatus.c index 496bafb865..b4b98301b0 100644 --- a/src/feature/nodelist/networkstatus.c +++ b/src/feature/nodelist/networkstatus.c @@ -216,10 +216,10 @@ networkstatus_reset_download_failures(void) } /** Return the filename used to cache the consensus of a given flavor */ -static char * -networkstatus_get_cache_fname(int flav, - const char *flavorname, - int unverified_consensus) +MOCK_IMPL(char *, +networkstatus_get_cache_fname,(int flav, + const char *flavorname, + int unverified_consensus)) { char buf[128]; const char *prefix; diff --git a/src/feature/nodelist/networkstatus.h b/src/feature/nodelist/networkstatus.h index 600fd7fbd5..e2c6ba611a 100644 --- a/src/feature/nodelist/networkstatus.h +++ b/src/feature/nodelist/networkstatus.h @@ -16,6 +16,9 @@ void networkstatus_reset_warnings(void); void networkstatus_reset_download_failures(void); +MOCK_DECL(char *,networkstatus_get_cache_fname,(int flav, + const char *flavorname, + int unverified_consensus)); tor_mmap_t *networkstatus_map_cached_consensus(const char *flavorname); int router_reload_consensus_networkstatus(void); void routerstatus_free_(routerstatus_t *rs); diff --git a/src/feature/nodelist/networkstatus_sr_info_st.h b/src/feature/nodelist/networkstatus_sr_info_st.h index 420c3d61e4..1392fa6853 100644 --- a/src/feature/nodelist/networkstatus_sr_info_st.h +++ b/src/feature/nodelist/networkstatus_sr_info_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file networkstatus_sr_info_st.h + * @brief Shared-randomness structure. + **/ + #ifndef NETWORKSTATUS_SR_INFO_ST_H #define NETWORKSTATUS_SR_INFO_ST_H @@ -20,4 +25,3 @@ struct networkstatus_sr_info_t { }; #endif /* !defined(NETWORKSTATUS_SR_INFO_ST_H) */ - diff --git a/src/feature/nodelist/networkstatus_st.h b/src/feature/nodelist/networkstatus_st.h index 6e84c170d6..a23ef0c193 100644 --- a/src/feature/nodelist/networkstatus_st.h +++ b/src/feature/nodelist/networkstatus_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file networkstatus_st.h + * @brief Networkstatus consensus/vote structure. + **/ + #ifndef NETWORKSTATUS_ST_H #define NETWORKSTATUS_ST_H diff --git a/src/feature/nodelist/networkstatus_voter_info_st.h b/src/feature/nodelist/networkstatus_voter_info_st.h index 66af82a8e3..629cb52254 100644 --- a/src/feature/nodelist/networkstatus_voter_info_st.h +++ b/src/feature/nodelist/networkstatus_voter_info_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file networkstatus_voter_info_st.h + * @brief Single consensus voter structure. + **/ + #ifndef NETWORKSTATUS_VOTER_INFO_ST_H #define NETWORKSTATUS_VOTER_INFO_ST_H diff --git a/src/feature/nodelist/node_select.c b/src/feature/nodelist/node_select.c index 719b4b1b27..8ac0b664c3 100644 --- a/src/feature/nodelist/node_select.c +++ b/src/feature/nodelist/node_select.c @@ -147,7 +147,7 @@ router_pick_dirserver_generic(smartlist_t *sourcelist, try_ip_pref = 0; \ goto retry_label; \ } \ - STMT_END \ + STMT_END /* Common retry code for router_pick_directory_server_impl and * router_pick_trusteddirserver_impl. Retry without excluding nodes, but with diff --git a/src/feature/nodelist/node_st.h b/src/feature/nodelist/node_st.h index c63a535a19..6ad10bb85a 100644 --- a/src/feature/nodelist/node_st.h +++ b/src/feature/nodelist/node_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file node_st.h + * @brief Node information structure. + **/ + #ifndef NODE_ST_H #define NODE_ST_H diff --git a/src/feature/nodelist/nodefamily_st.h b/src/feature/nodelist/nodefamily_st.h index 20390c9308..4aa00b0255 100644 --- a/src/feature/nodelist/nodefamily_st.h +++ b/src/feature/nodelist/nodefamily_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file nodefamily_st.h + * @brief Compact node-family structure + **/ + #ifndef TOR_NODEFAMILY_ST_H #define TOR_NODEFAMILY_ST_H diff --git a/src/feature/nodelist/routerinfo.c b/src/feature/nodelist/routerinfo.c index 975b503615..4e570fcbb2 100644 --- a/src/feature/nodelist/routerinfo.c +++ b/src/feature/nodelist/routerinfo.c @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file routerinfo.c + * @brief Manipulate full router descriptors. + **/ + #include "core/or/or.h" #include "feature/nodelist/nodelist.h" diff --git a/src/feature/nodelist/routerinfo_st.h b/src/feature/nodelist/routerinfo_st.h index 59fd56d0a0..16387f1005 100644 --- a/src/feature/nodelist/routerinfo_st.h +++ b/src/feature/nodelist/routerinfo_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file routerinfo_st.h + * @brief Router descriptor structure. + **/ + #ifndef ROUTERINFO_ST_H #define ROUTERINFO_ST_H diff --git a/src/feature/nodelist/routerlist_st.h b/src/feature/nodelist/routerlist_st.h index 10b919a1bf..d3a3874983 100644 --- a/src/feature/nodelist/routerlist_st.h +++ b/src/feature/nodelist/routerlist_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file routerlist_st.h + * @brief Router descriptor list structure. + **/ + #ifndef ROUTERLIST_ST_H #define ROUTERLIST_ST_H @@ -37,4 +42,3 @@ struct routerlist_t { }; #endif /* !defined(ROUTERLIST_ST_H) */ - diff --git a/src/feature/nodelist/routerset.c b/src/feature/nodelist/routerset.c index 9a205d39b7..4f2406d10f 100644 --- a/src/feature/nodelist/routerset.c +++ b/src/feature/nodelist/routerset.c @@ -17,7 +17,7 @@ * * Routersets are typically used for user-specified restrictions, and * are created by invoking routerset_new and routerset_parse from - * config.c and confparse.c. To use a routerset, invoke one of + * config.c and confmgt.c. To use a routerset, invoke one of * routerset_contains_...() functions , or use * routerstatus_get_all_nodes() / routerstatus_subtract_nodes() to * manipulate a smartlist of node_t pointers. diff --git a/src/feature/nodelist/routerset.h b/src/feature/nodelist/routerset.h index f3bf4a1f7c..dc6ce0b667 100644 --- a/src/feature/nodelist/routerset.h +++ b/src/feature/nodelist/routerset.h @@ -4,7 +4,7 @@ /* See LICENSE for licensing information */ /** - * \file routerlist.h + * \file routerset.h * \brief Header file for routerset.c **/ diff --git a/src/feature/nodelist/routerstatus_st.h b/src/feature/nodelist/routerstatus_st.h index 46337c9e52..b60e0e41d0 100644 --- a/src/feature/nodelist/routerstatus_st.h +++ b/src/feature/nodelist/routerstatus_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file routerstatus_st.h + * @brief Routerstatus (consensus entry) structure + **/ + #ifndef ROUTERSTATUS_ST_H #define ROUTERSTATUS_ST_H @@ -79,4 +84,3 @@ struct routerstatus_t { }; #endif /* !defined(ROUTERSTATUS_ST_H) */ - diff --git a/src/feature/nodelist/signed_descriptor_st.h b/src/feature/nodelist/signed_descriptor_st.h index 64c28f7440..952fc702f4 100644 --- a/src/feature/nodelist/signed_descriptor_st.h +++ b/src/feature/nodelist/signed_descriptor_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file signed_descriptor_st.h + * @brief Descriptor/extrainfo signature structure + **/ + #ifndef SIGNED_DESCRIPTOR_ST_H #define SIGNED_DESCRIPTOR_ST_H @@ -58,4 +63,3 @@ struct signed_descriptor_t { }; #endif /* !defined(SIGNED_DESCRIPTOR_ST_H) */ - diff --git a/src/feature/nodelist/torcert.h b/src/feature/nodelist/torcert.h index 03d5bdca93..5a1f932392 100644 --- a/src/feature/nodelist/torcert.h +++ b/src/feature/nodelist/torcert.h @@ -1,6 +1,11 @@ /* Copyright (c) 2014-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file torcert.h + * @brief Header for torcert.c + **/ + #ifndef TORCERT_H_INCLUDED #define TORCERT_H_INCLUDED diff --git a/src/feature/nodelist/vote_routerstatus_st.h b/src/feature/nodelist/vote_routerstatus_st.h index 0d909da260..e34b5e5f69 100644 --- a/src/feature/nodelist/vote_routerstatus_st.h +++ b/src/feature/nodelist/vote_routerstatus_st.h @@ -4,6 +4,10 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file vote_routerstatus_st.h + * @brief Routerstatus (vote entry) structure + **/ #ifndef VOTE_ROUTERSTATUS_ST_H #define VOTE_ROUTERSTATUS_ST_H diff --git a/src/feature/relay/ext_orport.h b/src/feature/relay/ext_orport.h index 7313ebd03d..a981ca80c2 100644 --- a/src/feature/relay/ext_orport.h +++ b/src/feature/relay/ext_orport.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file ext_orport.h + * @brief Header for ext_orport.c + **/ + #ifndef EXT_ORPORT_H #define EXT_ORPORT_H diff --git a/src/feature/relay/feature_relay.dox b/src/feature/relay/feature_relay.dox new file mode 100644 index 0000000000..6867818257 --- /dev/null +++ b/src/feature/relay/feature_relay.dox @@ -0,0 +1,6 @@ +/** +@dir /feature/relay +@brief feature/relay: Relay-specific code + +(There is also a bunch of relay-specific code in other modules.) +**/ 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 <b>ports</b> 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 <b>port_cfg_t</b> in <b>ports</b>, check them for internal + * consistency and warn as appropriate. On Unix-based OSes, set + * *<b>n_low_ports_out</b> 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 <b>options</b>. On success, add parsed ports to + * <b>ports</b>, and return 0. On failure, set *<b>msg</b> 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 <b>options</b> from <b>ports</b>. */ +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 <b>options</b>-\>PublishServerDescriptor + * and write it to <b>options</b>-\>PublishServerDescriptor_. Treat "1" + * as "v3" unless BridgeRelay is 1, in which case treat it as "bridge". + * Treat "0" as "". + * Return 0 on success or -1 if not a recognized authority type (in which + * case the value of PublishServerDescriptor_ is undefined). */ +static int +compute_publishserverdescriptor(or_options_t *options) +{ + smartlist_t *list = options->PublishServerDescriptor; + dirinfo_type_t *auth = &options->PublishServerDescriptor_; + *auth = NO_DIRINFO; + if (!list) /* empty list, answer is none */ + return 0; + SMARTLIST_FOREACH_BEGIN(list, const char *, string) { + if (!strcasecmp(string, "v1")) + log_warn(LD_CONFIG, "PublishServerDescriptor v1 has no effect, because " + "there are no v1 directory authorities anymore."); + else if (!strcmp(string, "1")) + if (options->BridgeRelay) + *auth |= BRIDGE_DIRINFO; + else + *auth |= V3_DIRINFO; + else if (!strcasecmp(string, "v2")) + log_warn(LD_CONFIG, "PublishServerDescriptor v2 has no effect, because " + "there are no v2 directory authorities anymore."); + else if (!strcasecmp(string, "v3")) + *auth |= V3_DIRINFO; + else if (!strcasecmp(string, "bridge")) + *auth |= BRIDGE_DIRINFO; + else if (!strcasecmp(string, "hidserv")) + log_warn(LD_CONFIG, + "PublishServerDescriptor hidserv is invalid. See " + "PublishHidServDescriptors."); + else if (!strcasecmp(string, "") || !strcmp(string, "0")) + /* no authority */; + else + return -1; + } SMARTLIST_FOREACH_END(string); + return 0; +} + +/** + * Validate the configured bridge distribution method from a BridgeDistribution + * config line. + * + * The input <b>bd</b>, is a string taken from the BridgeDistribution config + * line (if present). If the option wasn't set, return 0 immediately. The + * BridgeDistribution option is then validated. Currently valid, recognised + * options are: + * + * - "none" + * - "any" + * - "https" + * - "email" + * - "moat" + * - "hyphae" + * + * If the option string is unrecognised, a warning will be logged and 0 is + * returned. If the option string contains an invalid character, -1 is + * returned. + **/ +STATIC int +check_bridge_distribution_setting(const char *bd) +{ + if (bd == NULL) + return 0; + + const char *RECOGNIZED[] = { + "none", "any", "https", "email", "moat", "hyphae" + }; + unsigned i; + for (i = 0; i < ARRAY_LENGTH(RECOGNIZED); ++i) { + if (!strcmp(bd, RECOGNIZED[i])) + return 0; + } + + const char *cp = bd; + // Method = (KeywordChar | "_") + + while (TOR_ISALNUM(*cp) || *cp == '-' || *cp == '_') + ++cp; + + if (*cp == 0) { + log_warn(LD_CONFIG, "Unrecognized BridgeDistribution value %s. I'll " + "assume you know what you are doing...", escaped(bd)); + return 0; // we reached the end of the string; all is well + } else { + return -1; // we found a bad character in the string. + } +} + +/** + * 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 <b>lst</b> to prefix '$' + * to any nickname or fingerprint that needs it. Also splits comma-separated + * list elements into multiple elements. Return 0 on success. + * Warn and return -1 on failure. + */ +static int +normalize_nickname_list(config_line_t **normalized_out, + const config_line_t *lst, const char *name, + char **msg) +{ + if (!lst) + return 0; + + config_line_t *new_nicknames = NULL; + config_line_t **new_nicknames_next = &new_nicknames; + + const config_line_t *cl; + for (cl = lst; cl; cl = cl->next) { + const char *line = cl->value; + if (!line) + continue; + + int valid_line = 1; + smartlist_t *sl = smartlist_new(); + smartlist_split_string(sl, line, ",", + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0); + SMARTLIST_FOREACH_BEGIN(sl, char *, s) + { + char *normalized = NULL; + if (!is_legal_nickname_or_hexdigest(s)) { + // check if first char is dollar + if (s[0] != '$') { + // Try again but with a dollar symbol prepended + char *prepended; + tor_asprintf(&prepended, "$%s", s); + + if (is_legal_nickname_or_hexdigest(prepended)) { + // The nickname is valid when it's prepended, set it as the + // normalized version + normalized = prepended; + } else { + // Still not valid, free and fallback to error message + tor_free(prepended); + } + } + + if (!normalized) { + tor_asprintf(msg, "Invalid nickname '%s' in %s line", s, name); + valid_line = 0; + break; + } + } else { + normalized = tor_strdup(s); + } + + config_line_t *next = tor_malloc_zero(sizeof(*next)); + next->key = tor_strdup(cl->key); + next->value = normalized; + next->next = NULL; + + *new_nicknames_next = next; + new_nicknames_next = &next->next; + } SMARTLIST_FOREACH_END(s); + + SMARTLIST_FOREACH(sl, char *, s, tor_free(s)); + smartlist_free(sl); + + if (!valid_line) { + config_free_lines(new_nicknames); + return -1; + } + } + + *normalized_out = new_nicknames; + + return 0; +} + +#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 <b>old_options</b> to <b>new_options</b> + * will require us to rotate the CPU and DNS workers; else return 0. */ +static int +options_transition_affects_workers(const or_options_t *old_options, + const or_options_t *new_options) +{ + YES_IF_CHANGED_STRING(DataDirectory); + YES_IF_CHANGED_INT(NumCPUs); + YES_IF_CHANGED_LINELIST(ORPort_lines); + YES_IF_CHANGED_BOOL(ServerDNSSearchDomains); + YES_IF_CHANGED_BOOL(SafeLogging_); + YES_IF_CHANGED_BOOL(ClientOnly); + YES_IF_CHANGED_BOOL(LogMessageDomains); + YES_IF_CHANGED_LINELIST(Logs); + + if (server_mode(old_options) != server_mode(new_options) || + public_server_mode(old_options) != public_server_mode(new_options) || + dir_server_mode(old_options) != dir_server_mode(new_options)) + return 1; + + /* Nothing that changed matters. */ + return 0; +} + +/** Return 1 if any change from <b>old_options</b> to <b>new_options</b> + * will require us to generate a new descriptor; else return 0. */ +static int +options_transition_affects_descriptor(const or_options_t *old_options, + const or_options_t *new_options) +{ + /* XXX We can be smarter here. If your DirPort isn't being + * published and you just turned it off, no need to republish. Etc. */ + + YES_IF_CHANGED_STRING(DataDirectory); + YES_IF_CHANGED_STRING(Nickname); + YES_IF_CHANGED_STRING(Address); + YES_IF_CHANGED_LINELIST(ExitPolicy); + YES_IF_CHANGED_BOOL(ExitRelay); + YES_IF_CHANGED_BOOL(ExitPolicyRejectPrivate); + YES_IF_CHANGED_BOOL(ExitPolicyRejectLocalInterfaces); + YES_IF_CHANGED_BOOL(IPv6Exit); + YES_IF_CHANGED_LINELIST(ORPort_lines); + YES_IF_CHANGED_LINELIST(DirPort_lines); + YES_IF_CHANGED_LINELIST(DirPort_lines); + YES_IF_CHANGED_BOOL(ClientOnly); + YES_IF_CHANGED_BOOL(DisableNetwork); + YES_IF_CHANGED_BOOL(PublishServerDescriptor_); + YES_IF_CHANGED_STRING(ContactInfo); + YES_IF_CHANGED_STRING(BridgeDistribution); + YES_IF_CHANGED_LINELIST(MyFamily); + YES_IF_CHANGED_STRING(AccountingStart); + YES_IF_CHANGED_INT(AccountingMax); + YES_IF_CHANGED_INT(AccountingRule); + YES_IF_CHANGED_BOOL(DirCache); + YES_IF_CHANGED_BOOL(AssumeReachable); + + if (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, + * <b>old_options</b> 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, <b>old_options</b> 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, <b>old_options</b> 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, <b>old_options</b> 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, <b>old_options</b> contains the previous value of the options. + * + * Sets <b>*print_notice_out</b> 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, <b>old_options</b> 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, <b>old_options</b> 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, <b>old_options</b> 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/relay_periodic.c b/src/feature/relay/relay_periodic.c index b48b495895..d1b3183953 100644 --- a/src/feature/relay/relay_periodic.c +++ b/src/feature/relay/relay_periodic.c @@ -31,11 +31,13 @@ #include "feature/nodelist/routerinfo_st.h" #include "feature/control/control_events.h" +#ifndef COCCI #define DECLARE_EVENT(name, roles, flags) \ static periodic_event_item_t name ## _event = \ PERIODIC_EVENT(name, \ PERIODIC_EVENT_ROLE_##roles, \ flags) +#endif /* !defined(COCCI) */ #define FL(name) (PERIODIC_EVENT_FLAG_##name) diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c index ab0762e17e..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" @@ -372,6 +373,8 @@ assert_identity_keys_ok(void) } } +#ifdef HAVE_MODULE_RELAY + /** Returns the current server identity key; requires that the key has * been set, and that we are running as a Tor server. */ @@ -384,6 +387,8 @@ get_server_identity_key,(void)) return server_identitykey; } +#endif /* defined(HAVE_MODULE_RELAY) */ + /** Return true iff we are a server and the server identity key * has been set. */ int @@ -1218,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 " @@ -2037,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/router.h b/src/feature/relay/router.h index 55b9ef9e68..a708b24889 100644 --- a/src/feature/relay/router.h +++ b/src/feature/relay/router.h @@ -28,7 +28,13 @@ struct ed25519_keypair_t; MOCK_DECL(crypto_pk_t *,get_onion_key,(void)); time_t get_onion_key_set_at(void); void set_server_identity_key(crypto_pk_t *k); +/* Some compilers are clever enough to know that when relay mode is disabled, + * this function never returns. */ +#ifdef HAVE_MODULE_RELAY MOCK_DECL(crypto_pk_t *,get_server_identity_key,(void)); +#else +#define get_server_identity_key() (tor_abort_(),NULL) +#endif int server_identity_key_is_set(void); void set_client_identity_key(crypto_pk_t *k); crypto_pk_t *get_tlsclient_identity_key(void); diff --git a/src/feature/relay/routerkeys.h b/src/feature/relay/routerkeys.h index cde07b52c3..d2860718b2 100644 --- a/src/feature/relay/routerkeys.h +++ b/src/feature/relay/routerkeys.h @@ -1,6 +1,11 @@ /* Copyright (c) 2014-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file routerkeys.h + * @brief Header for routerkeys.c + **/ + #ifndef TOR_ROUTERKEYS_H #define TOR_ROUTERKEYS_H diff --git a/src/feature/relay/routermode.c b/src/feature/relay/routermode.c index 2a9ddeac4d..92bcfaf8fa 100644 --- a/src/feature/relay/routermode.c +++ b/src/feature/relay/routermode.c @@ -4,11 +4,14 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file routermode.c + * @brief Check if we're running as a relay/cache. + **/ + #include "core/or/or.h" #include "app/config/config.h" -#include "core/mainloop/connection.h" -#include "core/or/port_cfg_st.h" #include "feature/relay/router.h" #include "feature/relay/routermode.h" @@ -25,21 +28,6 @@ dir_server_mode(const or_options_t *options) (server_mode(options) && router_has_bandwidth_to_be_dirserver(options)); } -/** Return true iff we are trying to proxy client connections. */ -int -proxy_mode(const or_options_t *options) -{ - (void)options; - SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) { - if (p->type == CONN_TYPE_AP_LISTENER || - p->type == CONN_TYPE_AP_TRANS_LISTENER || - p->type == CONN_TYPE_AP_DNS_LISTENER || - p->type == CONN_TYPE_AP_NATD_LISTENER) - return 1; - } SMARTLIST_FOREACH_END(p); - return 0; -} - /** Return true iff we are trying to be a server. */ MOCK_IMPL(int, diff --git a/src/feature/relay/routermode.h b/src/feature/relay/routermode.h index be535af478..9891a038ad 100644 --- a/src/feature/relay/routermode.h +++ b/src/feature/relay/routermode.h @@ -12,13 +12,31 @@ #ifndef TOR_ROUTERMODE_H #define TOR_ROUTERMODE_H +#ifdef HAVE_MODULE_RELAY + int dir_server_mode(const or_options_t *options); MOCK_DECL(int, server_mode, (const or_options_t *options)); MOCK_DECL(int, public_server_mode, (const or_options_t *options)); MOCK_DECL(int, advertised_server_mode, (void)); -int proxy_mode(const or_options_t *options); void set_server_advertised(int s); +/** Is the relay module enabled? */ +#define have_module_relay() (1) + +#else /* !defined(HAVE_MODULE_RELAY) */ + +#define dir_server_mode(options) (((void)(options)),0) +#define server_mode(options) (((void)(options)),0) +#define public_server_mode(options) (((void)(options)),0) +#define advertised_server_mode() (0) + +/* We shouldn't be publishing descriptors when relay mode is disabled. */ +#define set_server_advertised(s) tor_assert_nonfatal(!(s)) + +#define have_module_relay() (0) + +#endif /* defined(HAVE_MODULE_RELAY) */ + #endif /* !defined(TOR_ROUTERMODE_H) */ 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 <b>line</b>, return its + * <address:port> string. Return NULL if the line was not + * well-formed. + * + * If <b>transport</b> is set, return NULL if the line is not + * referring to <b>transport</b>. + * + * The returned string is allocated on the heap and it's the + * responsibility of the caller to free it. */ +static char * +get_bindaddr_from_transport_listen_line(const char *line, + const char *transport) +{ + smartlist_t *items = NULL; + const char *parsed_transport = NULL; + char *addrport = NULL; + tor_addr_t addr; + uint16_t port = 0; + + items = smartlist_new(); + smartlist_split_string(items, line, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); + + if (smartlist_len(items) < 2) { + log_warn(LD_CONFIG,"Too few arguments on ServerTransportListenAddr line."); + goto err; + } + + parsed_transport = smartlist_get(items, 0); + addrport = tor_strdup(smartlist_get(items, 1)); + + /* If 'transport' is given, check if it matches the one on the line */ + if (transport && strcmp(transport, parsed_transport)) + goto err; + + /* Validate addrport */ + if (tor_addr_port_parse(LOG_WARN, addrport, &addr, &port, -1)<0) { + log_warn(LD_CONFIG, "Error parsing ServerTransportListenAddr " + "address '%s'", addrport); + goto err; + } + + goto done; + + err: + tor_free(addrport); + addrport = NULL; + + done: + SMARTLIST_FOREACH(items, char*, s, tor_free(s)); + smartlist_free(items); + + return addrport; +} + +/** Given the name of a pluggable transport in <b>transport</b>, check + * the configuration file to see if the user has explicitly asked for + * it to listen on a specific port. Return a <address:port> string if + * so, otherwise NULL. */ +char * +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 <b>line</b>, return a smartlist + * with the options. Return NULL if the line was not well-formed. + * + * If <b>transport</b> is set, return NULL if the line is not + * referring to <b>transport</b>. + * + * The returned smartlist and its strings are allocated on the heap + * and it's the responsibility of the caller to free it. */ +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 <b>transport</b>, check + * the configuration file to see if the user has asked us to pass any + * parameters to the pluggable transport. Return a smartlist + * containing the parameters, otherwise NULL. */ +smartlist_t * +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, <b>old_options</b> 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/feature/rend/feature_rend.dox b/src/feature/rend/feature_rend.dox new file mode 100644 index 0000000000..ed0784521c --- /dev/null +++ b/src/feature/rend/feature_rend.dox @@ -0,0 +1,9 @@ +/** +@dir /feature/rend +@brief feature/rend: version 2 (old) hidden services + +This directory implements the v2 onion service protocol, +as specified in +[rend-spec-v2.txt](https://gitweb.torproject.org/torspec.git/tree/rend-spec-v2.txt). + +**/ diff --git a/src/feature/rend/rend_authorized_client_st.h b/src/feature/rend/rend_authorized_client_st.h index 51a1798fcb..0819f2134a 100644 --- a/src/feature/rend/rend_authorized_client_st.h +++ b/src/feature/rend/rend_authorized_client_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file rend_authorized_client_st.h + * @brief Hidden-service authorized client structure. + **/ + #ifndef REND_AUTHORIZED_CLIENT_ST_H #define REND_AUTHORIZED_CLIENT_ST_H @@ -15,4 +20,3 @@ struct rend_authorized_client_t { }; #endif /* !defined(REND_AUTHORIZED_CLIENT_ST_H) */ - diff --git a/src/feature/rend/rend_encoded_v2_service_descriptor_st.h b/src/feature/rend/rend_encoded_v2_service_descriptor_st.h index bd8a60f0d9..5eec600fd1 100644 --- a/src/feature/rend/rend_encoded_v2_service_descriptor_st.h +++ b/src/feature/rend/rend_encoded_v2_service_descriptor_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file rend_encoded_v2_service_descriptor_st.h + * @brief Encoded v2 HS descriptor structure. + **/ + #ifndef REND_ENCODED_V2_SERVICE_DESCRIPTOR_ST_H #define REND_ENCODED_V2_SERVICE_DESCRIPTOR_ST_H @@ -14,4 +19,3 @@ struct rend_encoded_v2_service_descriptor_t { }; #endif /* !defined(REND_ENCODED_V2_SERVICE_DESCRIPTOR_ST_H) */ - diff --git a/src/feature/rend/rend_intro_point_st.h b/src/feature/rend/rend_intro_point_st.h index 4882b62752..9acf155708 100644 --- a/src/feature/rend/rend_intro_point_st.h +++ b/src/feature/rend/rend_intro_point_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file rend_intro_point_st.h + * @brief v2 hidden service introduction point structure. + **/ + #ifndef REND_INTRO_POINT_ST_H #define REND_INTRO_POINT_ST_H diff --git a/src/feature/rend/rend_service_descriptor_st.h b/src/feature/rend/rend_service_descriptor_st.h index ff7627ce96..bdfe87dcae 100644 --- a/src/feature/rend/rend_service_descriptor_st.h +++ b/src/feature/rend/rend_service_descriptor_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file rend_service_descriptor_st.h + * @brief Parsed v2 HS descriptor structure. + **/ + #ifndef REND_SERVICE_DESCRIPTOR_ST_H #define REND_SERVICE_DESCRIPTOR_ST_H @@ -31,4 +36,3 @@ struct rend_service_descriptor_t { }; #endif /* !defined(REND_SERVICE_DESCRIPTOR_ST_H) */ - diff --git a/src/feature/rend/rendcache.c b/src/feature/rend/rendcache.c index c3f86d8c82..2d8de2a80d 100644 --- a/src/feature/rend/rendcache.c +++ b/src/feature/rend/rendcache.c @@ -228,6 +228,17 @@ rend_cache_entry_free_void(void *p) rend_cache_entry_free_(p); } +/** Check if a failure cache entry exists for the given intro point. */ +bool +rend_cache_intro_failure_exists(const char *service_id, + const uint8_t *intro_identity) +{ + tor_assert(service_id); + tor_assert(intro_identity); + + return cache_failure_intro_lookup(intro_identity, service_id, NULL); +} + /** Free all storage held by the service descriptor cache. */ void rend_cache_free_all(void) diff --git a/src/feature/rend/rendcache.h b/src/feature/rend/rendcache.h index aec97eabb8..c83f36d189 100644 --- a/src/feature/rend/rendcache.h +++ b/src/feature/rend/rendcache.h @@ -80,6 +80,8 @@ int rend_cache_store_v2_desc_as_client(const char *desc, rend_cache_entry_t **entry); size_t rend_cache_get_total_allocation(void); +bool rend_cache_intro_failure_exists(const char *service_id, + const uint8_t *intro_identity); void rend_cache_intro_failure_note(rend_intro_point_failure_t failure, const uint8_t *identity, const char *service_id); diff --git a/src/feature/rend/rendclient.c b/src/feature/rend/rendclient.c index 2540066dfc..6f4ee8b8c1 100644 --- a/src/feature/rend/rendclient.c +++ b/src/feature/rend/rendclient.c @@ -1048,18 +1048,30 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry, const or_options_t *options = get_options(); smartlist_t *usable_nodes; int n_excluded = 0; + char service_id[REND_SERVICE_ID_LEN_BASE32 + 1]; /* We'll keep a separate list of the usable nodes. If this becomes empty, * no nodes are usable. */ usable_nodes = smartlist_new(); smartlist_add_all(usable_nodes, entry->parsed->intro_nodes); + /* Get service ID so we can use it to query the failure cache. If we fail to + * parse it, this cache entry is no good. */ + if (BUG(rend_get_service_id(entry->parsed->pk, service_id) < 0)) { + smartlist_free(usable_nodes); + return NULL; + } + /* Remove the intro points that have timed out during this HS * connection attempt from our list of usable nodes. */ - SMARTLIST_FOREACH(usable_nodes, rend_intro_point_t *, ip, - if (ip->timed_out) { - SMARTLIST_DEL_CURRENT(usable_nodes, ip); - }); + SMARTLIST_FOREACH_BEGIN(usable_nodes, const rend_intro_point_t *, ip) { + bool failed_intro = + rend_cache_intro_failure_exists(service_id, + (const uint8_t *) ip->extend_info->identity_digest); + if (ip->timed_out || failed_intro) { + SMARTLIST_DEL_CURRENT(usable_nodes, ip); + }; + } SMARTLIST_FOREACH_END(ip); again: if (smartlist_len(usable_nodes) == 0) { diff --git a/src/feature/rend/rendparse.h b/src/feature/rend/rendparse.h index b1ccce9b6c..da2c2e4b7f 100644 --- a/src/feature/rend/rendparse.h +++ b/src/feature/rend/rendparse.h @@ -5,8 +5,8 @@ /* See LICENSE for licensing information */ /** - * \file rend_parse.h - * \brief Header file for rend_parse.c. + * \file rendparse.h + * \brief Header file for rendparse.c. **/ #ifndef TOR_REND_PARSE_H diff --git a/src/feature/stats/feature_stats.dox b/src/feature/stats/feature_stats.dox new file mode 100644 index 0000000000..0ced00ce58 --- /dev/null +++ b/src/feature/stats/feature_stats.dox @@ -0,0 +1,12 @@ +/** +@dir /feature/stats +@brief feature/stats: Relay statistics. Also, port prediction. + +This module collects anonymized relay statistics in order to publish them in +relays' routerinfo and extrainfo documents. + +Additionally, it contains predict_ports.c, which remembers which ports we've +visited recently as a client, so we can make sure we have open circuits that +support them. + +**/ diff --git a/src/feature/stats/predict_ports.h b/src/feature/stats/predict_ports.h index 45b206c23a..a994db1d17 100644 --- a/src/feature/stats/predict_ports.h +++ b/src/feature/stats/predict_ports.h @@ -5,7 +5,7 @@ /* See LICENSE for licensing information */ /** - * \file predict_portst.h + * \file predict_ports.h * \brief Header file for predict_ports.c. **/ diff --git a/src/lib/arch/lib_arch.dox b/src/lib/arch/lib_arch.dox new file mode 100644 index 0000000000..edb0cbbf1d --- /dev/null +++ b/src/lib/arch/lib_arch.dox @@ -0,0 +1,4 @@ +/** +@dir /lib/arch +@brief lib/arch: Compatibility code for handling different CPU architectures. +**/ diff --git a/src/lib/buf/buffers.c b/src/lib/buf/buffers.c index 4d026bd37d..4adc08fdbf 100644 --- a/src/lib/buf/buffers.c +++ b/src/lib/buf/buffers.c @@ -99,6 +99,7 @@ #define DBG_S(s) (void)0 #endif +#ifndef COCCI #ifdef DISABLE_MEMORY_SENTINELS #define CHUNK_SET_SENTINEL(chunk, alloclen) STMT_NIL #else @@ -109,6 +110,7 @@ memset(a,0,SENTINEL_LEN); \ } while (0) #endif /* defined(DISABLE_MEMORY_SENTINELS) */ +#endif /* !defined(COCCI) */ /** Move all bytes stored in <b>chunk</b> to the front of <b>chunk</b>->mem, * to free up space at the end. */ @@ -578,6 +580,7 @@ buf_add_vprintf(buf_t *buf, const char *format, va_list args) /* XXXX Faster implementations are easy enough, but let's optimize later */ char *tmp; tor_vasprintf(&tmp, format, args); + tor_assert(tmp != NULL); buf_add(buf, tmp, strlen(tmp)); tor_free(tmp); } diff --git a/src/lib/buf/lib_buf.dox b/src/lib/buf/lib_buf.dox new file mode 100644 index 0000000000..a2ac23ee4c --- /dev/null +++ b/src/lib/buf/lib_buf.dox @@ -0,0 +1,15 @@ +/** +@dir /lib/buf +@brief lib/buf: An efficient byte queue. + +This module defines the buf_t type, which is used throughout our networking +code. The implementation is a singly-linked queue of buffer chunks, similar +to the BSD kernel's +["mbuf"](https://www.freebsd.org/cgi/man.cgi?query=mbuf&sektion=9) structure. + +The buf_t type is also reasonable for use in constructing long strings. + +See \refdir{lib/net} for networking code that uses buf_t, and +\refdir{lib/tls} for cryptographic code that uses buf_t. + +**/ diff --git a/src/lib/cc/ctassert.h b/src/lib/cc/ctassert.h index bedf0b83a6..d9d3aa40b0 100644 --- a/src/lib/cc/ctassert.h +++ b/src/lib/cc/ctassert.h @@ -46,7 +46,7 @@ #define CTASSERT_EXPN(x, a, b) CTASSERT_DECL(x, a, b) #define CTASSERT_DECL(x, a, b) \ - typedef char tor_ctassert_##a##_##b[(x) ? 1 : -1] ATTR_UNUSED + typedef char tor_ctassert_##a##_##b[(x) ? 1 : -1] ATTR_UNUSED; EAT_SEMICOLON #endif /* __STDC_VERSION__ >= 201112L */ diff --git a/src/lib/cc/lib_cc.dox b/src/lib/cc/lib_cc.dox new file mode 100644 index 0000000000..06f4e775bf --- /dev/null +++ b/src/lib/cc/lib_cc.dox @@ -0,0 +1,4 @@ +/** +@dir /lib/cc +@brief lib/cc: Macros for managing the C compiler and language. +**/ diff --git a/src/lib/compress/lib_compress.dox b/src/lib/compress/lib_compress.dox new file mode 100644 index 0000000000..599126901a --- /dev/null +++ b/src/lib/compress/lib_compress.dox @@ -0,0 +1,8 @@ +/** +@dir /lib/compress +@brief lib/compress: Wraps several compression libraries + +Currently supported are zlib (mandatory), zstd (optional), and lzma +(optional). + +**/ diff --git a/src/lib/conf/confmacros.h b/src/lib/conf/confmacros.h index 68121891f1..10de1fbcee 100644 --- a/src/lib/conf/confmacros.h +++ b/src/lib/conf/confmacros.h @@ -15,11 +15,13 @@ #include "orconfig.h" #include "lib/conf/conftesting.h" +#ifndef COCCI /** * Used to indicate the end of an array of configuration variables. **/ #define END_OF_CONFIG_VARS \ { .member = { .name = NULL } DUMMY_CONF_TEST_MEMBERS } +#endif /* !defined(COCCI) */ /** * Declare a config_var_t as a member named <b>membername</b> of the structure @@ -43,7 +45,7 @@ } /** - * As CONFIG_VAR_XTYPE, but declares a value using an extension type whose + * As CONFIG_VAR_ETYPE, but declares a value using an extension type whose * type definition is <b>vartype</b>_type_defn. **/ #define CONFIG_VAR_DEFN(structtype, varname, vartype, membername, \ @@ -59,6 +61,9 @@ CONF_TEST_MEMBERS(structtype, vartype, membername) \ } +/** + * Declare an obsolete configuration variable with a given name. + **/ #define CONFIG_VAR_OBSOLETE(varname) \ { .member = { .name = varname, .type = CONFIG_TYPE_OBSOLETE }, \ .flags = CFLG_GROUP_OBSOLETE \ diff --git a/src/lib/conf/conftesting.h b/src/lib/conf/conftesting.h index f01f52d59e..7e12fe76db 100644 --- a/src/lib/conf/conftesting.h +++ b/src/lib/conf/conftesting.h @@ -12,10 +12,12 @@ #ifndef TOR_LIB_CONF_CONFTESTING_H #define TOR_LIB_CONF_CONFTESTING_H +#ifndef COCCI #ifdef TOR_UNIT_TESTS +#define USE_CONF_TESTING /** * Union used when building in test mode typechecking the members of a type - * used with confparse.c. See CONF_CHECK_VAR_TYPE for a description of how + * used with confmgt.c. See CONF_CHECK_VAR_TYPE for a description of how * it is used. */ typedef union { char **STRING; @@ -41,13 +43,11 @@ typedef union { // XXXX this doesn't belong at this level of abstraction. struct routerset_t **ROUTERSET; } confparse_dummy_values_t; -#endif /* defined(TOR_UNIT_TESTS) */ /* Macros to define extra members inside config_var_t fields, and at the * end of a list of them. */ -#ifdef TOR_UNIT_TESTS -/* This is a somewhat magic type-checking macro for users of confparse.c. +/* This is a somewhat magic type-checking macro for users of confmgt.c. * It initializes a union member "confparse_dummy_values_t.conftype" with * the address of a static member "tp_dummy.member". This * will give a compiler warning unless the member field is of the correct @@ -72,15 +72,16 @@ typedef union { #define DUMMY_CONF_TEST_MEMBERS , .var_ptr_dummy={ .INT=NULL } #define DUMMY_TYPECHECK_INSTANCE(tp) \ static tp tp ## _dummy +#endif /* defined(TOR_UNIT_TESTS) */ +#endif /* !defined(COCCI) */ -#else /* !defined(TOR_UNIT_TESTS) */ - +#ifndef USE_CONF_TESTING #define CONF_TEST_MEMBERS(tp, conftype, member) /* Repeatedly declarable incomplete struct to absorb redundant semicolons */ #define DUMMY_TYPECHECK_INSTANCE(tp) \ struct tor_semicolon_eater #define DUMMY_CONF_TEST_MEMBERS -#endif /* defined(TOR_UNIT_TESTS) */ +#endif /* !defined(USE_CONF_TESTING) */ #endif /* !defined(TOR_LIB_CONF_CONFTESTING_H) */ diff --git a/src/lib/conf/conftypes.h b/src/lib/conf/conftypes.h index 274065cff2..d4e2ea218a 100644 --- a/src/lib/conf/conftypes.h +++ b/src/lib/conf/conftypes.h @@ -178,6 +178,11 @@ typedef struct struct_magic_decl_t { * however, setting them appends to their old value. */ #define CFLG_NOREPLACE (1u<<5) +/** + * Flag to indicate that an option or type cannot be changed while Tor is + * running. + **/ +#define CFLG_IMMUTABLE (1u<<6) /** * A group of flags that should be set on all obsolete options and types. @@ -199,4 +204,140 @@ typedef struct config_var_t { #endif } config_var_t; +/** + * An abbreviation or alias for a configuration option. + **/ +typedef struct config_abbrev_t { + /** The option name as abbreviated. Not case-sensitive. */ + const char *abbreviated; + /** The full name of the option. Not case-sensitive. */ + const char *full; + /** True if this abbreviation should only be allowed on the command line. */ + int commandline_only; + /** True if we should warn whenever this abbreviation is used. */ + int warn; +} config_abbrev_t; + +/** + * A note that a configuration option is deprecated, with an explanation why. + */ +typedef struct config_deprecation_t { + /** The option that is deprecated. */ + const char *name; + /** A user-facing string explaining why the option is deprecated. */ + const char *why_deprecated; +} config_deprecation_t; + +/** + * Handy macro for declaring "In the config file or on the command line, you + * can abbreviate <b>tok</b>s as <b>tok</b>". Used inside an array of + * config_abbrev_t. + * + * For example, to declare "NumCpu" as an abbreviation for "NumCPUs", + * you can say PLURAL(NumCpu). + **/ +#define PLURAL(tok) { #tok, #tok "s", 0, 0 } + +/** + * Validation function: verify whether a configuation object is well-formed + * and consistent. + * + * On success, return 0. On failure, set <b>msg_out</b> to a newly allocated + * string containing an error message, and return -1. */ +typedef int (*validate_fn_t)(const void *value, char **msg_out); +/** + * Validation function: verify whether a configuration object (`value`) is an + * allowable value given the previous configuration value (`old_value`). + * + * On success, return 0. On failure, set <b>msg_out</b> to a newly allocated + * string containing an error message, and return -1. */ +typedef int (*check_transition_fn_t)(const void *old_value, const void *value, + char **msg_out); +/** + * Validation function: normalize members of `value`, and compute derived + * members. + * + * This function is called before any other validation of `value`, and must + * not assume that validate_fn or check_transition_fn has passed. + * + * On success, return 0. On failure, set <b>msg_out</b> to a newly allocated + * string containing an error message, and return -1. */ +typedef int (*pre_normalize_fn_t)(void *value, char **msg_out); +/** + * Validation function: normalize members of `value`, and compute derived + * members. + * + * This function is called after validation of `value`, and may + * assume that validate_fn or check_transition_fn has passed. + * + * On success, return 0. On failure, set <b>msg_out</b> to a newly allocated + * string containing an error message, and return -1. */ +typedef int (*post_normalize_fn_t)(void *value, char **msg_out); + +/** + * Legacy function to validate whether a given configuration is + * well-formed and consistent. + * + * The configuration to validate is passed as <b>newval</b>. The previous + * configuration, if any, is provided in <b>oldval</b>. + * + * This API is deprecated, since it mixes the responsibilities of + * pre_normalize_fn_t, post_normalize_fn_t, validate_fn_t, and + * check_transition_fn_t. No new instances of this function type should + * be written. + * + * On success, return 0. On failure, set *<b>msg_out</b> to a newly allocated + * error message, and return -1. + */ +typedef int (*legacy_validate_fn_t)(const void *oldval, + void *newval, + char **msg_out); + +struct config_mgr_t; + +/** + * Callback to clear all non-managed fields of a configuration object. + * + * <b>obj</b> is the configuration object whose non-managed fields should be + * cleared. + * + * (Regular fields get cleared by config_reset(), but you might have fields + * in the object that do not correspond to configuration variables. If those + * fields need to be cleared or freed, this is where to do it.) + */ +typedef void (*clear_cfg_fn_t)(const struct config_mgr_t *mgr, void *obj); + +/** Information on the keys, value types, key-to-struct-member mappings, + * variable descriptions, validation functions, and abbreviations for a + * configuration or storage format. */ +typedef struct config_format_t { + size_t size; /**< Size of the struct that everything gets parsed into. */ + struct_magic_decl_t magic; /**< Magic number info for this struct. */ + const config_abbrev_t *abbrevs; /**< List of abbreviations that we expand + * when parsing this format. */ + const config_deprecation_t *deprecations; /** List of deprecated options */ + const config_var_t *vars; /**< List of variables we recognize, their default + * values, and where we stick them in the + * structure. */ + + /** Early-stage normalization callback. Invoked by config_validate(). */ + pre_normalize_fn_t pre_normalize_fn; + /** Configuration validation function. Invoked by config_validate(). */ + validate_fn_t validate_fn; + /** Legacy validation function. Invoked by config_validate(). */ + legacy_validate_fn_t legacy_validate_fn; + /** Transition checking function. Invoked by config_validate(). */ + check_transition_fn_t check_transition_fn; + /** Late-stage normalization callback. Invoked by config_validate(). */ + post_normalize_fn_t post_normalize_fn; + + clear_cfg_fn_t clear_fn; /**< Function to clear the configuration. */ + /** If present, extra denotes a LINELIST variable for unrecognized + * lines. Otherwise, unrecognized lines are an error. */ + const struct_member_t *extra; + /** The position of a config_suite_t pointer within the toplevel object, + * or -1 if there is no such pointer. */ + ptrdiff_t config_suite_offset; +} config_format_t; + #endif /* !defined(TOR_SRC_LIB_CONF_CONFTYPES_H) */ diff --git a/src/lib/conf/lib_conf.dox b/src/lib/conf/lib_conf.dox new file mode 100644 index 0000000000..be58fe5b55 --- /dev/null +++ b/src/lib/conf/lib_conf.dox @@ -0,0 +1,5 @@ +/** +@dir /lib/conf +@brief lib/conf: Types and macros for declaring configuration options. + +**/ diff --git a/src/lib/confmgt/confparse.c b/src/lib/confmgt/confmgt.c index 08e562f654..9377736110 100644 --- a/src/lib/confmgt/confparse.c +++ b/src/lib/confmgt/confmgt.c @@ -5,7 +5,7 @@ /* See LICENSE for licensing information */ /** - * \file confparse.c + * \file confmgt.c * * \brief Back-end for parsing and generating key-value files, used to * implement the torrc file format and the state file. @@ -21,9 +21,9 @@ * specified, and a linked list of key-value pairs. */ -#define CONFPARSE_PRIVATE +#define CONFMGT_PRIVATE #include "orconfig.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "lib/confmgt/structvar.h" #include "lib/confmgt/unitparse.h" @@ -334,6 +334,17 @@ config_mgr_list_deprecated_vars(const config_mgr_t *mgr) return result; } +/** + * Check the magic number on <b>object</b> to make sure it's a valid toplevel + * object, created with <b>mgr</b>. Exit with an assertion if it isn't. + **/ +void +config_check_toplevel_magic(const config_mgr_t *mgr, + const void *object) +{ + struct_check_magic(object, &mgr->toplevel_magic); +} + /** Assert that the magic fields in <b>options</b> and its subsidiary * objects are all okay. */ static void @@ -1142,6 +1153,146 @@ config_init(const config_mgr_t *mgr, void *options) } SMARTLIST_FOREACH_END(mv); } +/** + * Helper for config_validate_single: see whether any immutable option + * has changed between old_options and new_options. + * + * On success return 0; on failure set *msg_out to a newly allocated + * string explaining what is wrong, and return -1. + */ +static int +config_check_immutable_flags(const config_format_t *fmt, + const void *old_options, + const void *new_options, + char **msg_out) +{ + tor_assert(fmt); + tor_assert(new_options); + if (BUG(! old_options)) + return 0; + + unsigned i; + for (i = 0; fmt->vars[i].member.name; ++i) { + const config_var_t *v = &fmt->vars[i]; + if (! config_var_has_flag(v, CFLG_IMMUTABLE)) + continue; + + if (! struct_var_eq(old_options, new_options, &v->member)) { + tor_asprintf(msg_out, + "While Tor is running, changing %s is not allowed", + v->member.name); + return -1; + } + } + + return 0; +} + +/** + * Normalize and validate a single object `options` within a configuration + * suite, according to its format. `options` may be modified as appropriate + * in order to set ancillary data. If `old_options` is provided, make sure + * that the transition from `old_options` to `options` is permitted. + * + * On success return VSTAT_OK; on failure set *msg_out to a newly allocated + * string explaining what is wrong, and return a different validation_status_t + * to describe which step failed. + **/ +static validation_status_t +config_validate_single(const config_format_t *fmt, + const void *old_options, void *options, + char **msg_out) +{ + tor_assert(fmt); + tor_assert(options); + + if (fmt->pre_normalize_fn) { + if (fmt->pre_normalize_fn(options, msg_out) < 0) { + return VSTAT_PRE_NORMALIZE_ERR; + } + } + + if (fmt->legacy_validate_fn) { + if (fmt->legacy_validate_fn(old_options, options, msg_out) < 0) { + return VSTAT_LEGACY_ERR; + } + } + + if (fmt->validate_fn) { + if (fmt->validate_fn(options, msg_out) < 0) { + return VSTAT_VALIDATE_ERR; + } + } + + if (old_options) { + if (config_check_immutable_flags(fmt, old_options, options, msg_out) < 0) { + return VSTAT_TRANSITION_ERR; + } + + if (fmt->check_transition_fn) { + if (fmt->check_transition_fn(old_options, options, msg_out) < 0) { + return VSTAT_TRANSITION_ERR; + } + } + } + + if (fmt->post_normalize_fn) { + if (fmt->post_normalize_fn(options, msg_out) < 0) { + return VSTAT_POST_NORMALIZE_ERR; + } + } + + return VSTAT_OK; +} + +/** + * Normalize and validate all the options in configuration object `options` + * and its sub-objects. `options` may be modified as appropriate in order to + * set ancillary data. If `old_options` is provided, make sure that the + * transition from `old_options` to `options` is permitted. + * + * On success return VSTAT_OK; on failure set *msg_out to a newly allocated + * string explaining what is wrong, and return a different validation_status_t + * to describe which step failed. + **/ +validation_status_t +config_validate(const config_mgr_t *mgr, + const void *old_options, void *options, + char **msg_out) +{ + validation_status_t rv; + CONFIG_CHECK(mgr, options); + if (old_options) { + CONFIG_CHECK(mgr, old_options); + } + + config_suite_t **suitep_new = config_mgr_get_suite_ptr(mgr, options); + config_suite_t **suitep_old = NULL; + if (old_options) + suitep_old = config_mgr_get_suite_ptr(mgr, (void*) old_options); + + /* Validate the sub-objects */ + if (suitep_new) { + SMARTLIST_FOREACH_BEGIN(mgr->subconfigs, const config_format_t *, fmt) { + void *obj = smartlist_get((*suitep_new)->configs, fmt_sl_idx); + const void *obj_old=NULL; + if (suitep_old) + obj_old = smartlist_get((*suitep_old)->configs, fmt_sl_idx); + + rv = config_validate_single(fmt, obj_old, obj, msg_out); + if (rv < 0) + return rv; + } SMARTLIST_FOREACH_END(fmt); + } + + /* Validate the top-level object. */ + rv = config_validate_single(mgr->toplevel, old_options, options, msg_out); + if (rv < 0) + return rv; + + return VSTAT_OK; +} + /** Allocate and return a new string holding the written-out values of the vars * in 'options'. If 'minimal', do not write out any default-valued vars. * Else, if comment_defaults, write default values as comments. @@ -1166,7 +1317,7 @@ config_dump(const config_mgr_t *mgr, const void *default_options, /* XXX use a 1 here so we don't add a new log line while dumping */ if (default_options == NULL) { - if (fmt->validate_fn(NULL, defaults_tmp, defaults_tmp, 1, &msg) < 0) { + if (config_validate(mgr, NULL, defaults_tmp, &msg) < 0) { // LCOV_EXCL_START log_err(LD_BUG, "Failed to validate default config: %s", msg); tor_free(msg); @@ -1197,9 +1348,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); @@ -1207,7 +1359,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/lib/confmgt/confparse.h b/src/lib/confmgt/confmgt.h index 2332f69790..f565742c55 100644 --- a/src/lib/confmgt/confparse.h +++ b/src/lib/confmgt/confmgt.h @@ -5,112 +5,19 @@ /* See LICENSE for licensing information */ /** - * \file confparse.h + * \file confmgt.h * - * \brief Header for confparse.c. + * \brief Header for confmgt.c. */ -#ifndef TOR_CONFPARSE_H -#define TOR_CONFPARSE_H +#ifndef TOR_CONFMGT_H +#define TOR_CONFMGT_H #include "lib/conf/conftypes.h" #include "lib/conf/confmacros.h" #include "lib/testsupport/testsupport.h" /** - * An abbreviation or alias for a configuration option. - **/ -typedef struct config_abbrev_t { - /** The option name as abbreviated. Not case-sensitive. */ - const char *abbreviated; - /** The full name of the option. Not case-sensitive. */ - const char *full; - /** True if this abbreviation should only be allowed on the command line. */ - int commandline_only; - /** True if we should warn whenever this abbreviation is used. */ - int warn; -} config_abbrev_t; - -/** - * A note that a configuration option is deprecated, with an explanation why. - */ -typedef struct config_deprecation_t { - /** The option that is deprecated. */ - const char *name; - /** A user-facing string explaining why the option is deprecated. */ - const char *why_deprecated; -} config_deprecation_t; - -/** - * Handy macro for declaring "In the config file or on the command line, you - * can abbreviate <b>tok</b>s as <b>tok</b>". Used inside an array of - * config_abbrev_t. - * - * For example, to declare "NumCpu" as an abbreviation for "NumCPUs", - * you can say PLURAL(NumCpu). - **/ -#define PLURAL(tok) { #tok, #tok "s", 0, 0 } - -/** - * Type of a callback to validate whether a given configuration is - * well-formed and consistent. - * - * The configuration to validate is passed as <b>newval</b>. The previous - * configuration, if any, is provided in <b>oldval</b>. The - * <b>default_val</b> argument receives a configuration object initialized - * with default values for all its fields. The <b>from_setconf</b> argument - * is true iff the input comes from a SETCONF controller command. - * - * On success, return 0. On failure, set *<b>msg_out</b> to a newly allocated - * error message, and return -1. - * - * REFACTORING NOTE: Currently, this callback type is only used from inside - * config_dump(); later in our refactoring, it will be cleaned up and used - * more generally. - */ -typedef int (*validate_fn_t)(void *oldval, - void *newval, - void *default_val, - int from_setconf, - char **msg_out); - -struct config_mgr_t; - -/** - * Callback to clear all non-managed fields of a configuration object. - * - * <b>obj</b> is the configuration object whose non-managed fields should be - * cleared. - * - * (Regular fields get cleared by config_reset(), but you might have fields - * in the object that do not correspond to configuration variables. If those - * fields need to be cleared or freed, this is where to do it.) - */ -typedef void (*clear_cfg_fn_t)(const struct config_mgr_t *mgr, void *obj); - -/** Information on the keys, value types, key-to-struct-member mappings, - * variable descriptions, validation functions, and abbreviations for a - * configuration or storage format. */ -typedef struct config_format_t { - size_t size; /**< Size of the struct that everything gets parsed into. */ - struct_magic_decl_t magic; /**< Magic number info for this struct. */ - const config_abbrev_t *abbrevs; /**< List of abbreviations that we expand - * when parsing this format. */ - const config_deprecation_t *deprecations; /** List of deprecated options */ - const config_var_t *vars; /**< List of variables we recognize, their default - * values, and where we stick them in the - * structure. */ - validate_fn_t validate_fn; /**< Function to validate config. */ - clear_cfg_fn_t clear_fn; /**< Function to clear the configuration. */ - /** If present, extra denotes a LINELIST variable for unrecognized - * lines. Otherwise, unrecognized lines are an error. */ - const struct_member_t *extra; - /** The position of a config_suite_t pointer within the toplevel object, - * or -1 if there is no such pointer. */ - ptrdiff_t config_suite_offset; -} config_format_t; - -/** * A collection of config_format_t objects to describe several objects * that are all configured with the same configuration file. * @@ -171,10 +78,26 @@ int config_is_same(const config_mgr_t *fmt, struct config_line_t *config_get_changes(const config_mgr_t *mgr, const void *options1, const void *options2); void config_init(const config_mgr_t *mgr, void *options); + +/** An enumeration to report which validation step failed. */ +typedef enum { + VSTAT_PRE_NORMALIZE_ERR = -5, + VSTAT_VALIDATE_ERR = -4, + VSTAT_LEGACY_ERR = -3, + VSTAT_TRANSITION_ERR = -2, + VSTAT_POST_NORMALIZE_ERR = -1, + VSTAT_OK = 0, +} validation_status_t; + +validation_status_t config_validate(const config_mgr_t *mgr, + const void *old_options, void *options, + char **msg_out); void *config_dup(const config_mgr_t *mgr, const void *old); char *config_dump(const config_mgr_t *mgr, const void *default_options, const void *options, int minimal, int comment_defaults); +void config_check_toplevel_magic(const config_mgr_t *mgr, + const void *object); bool config_check_ok(const config_mgr_t *mgr, const void *options, int severity); int config_assign(const config_mgr_t *mgr, void *options, @@ -200,13 +123,13 @@ bool config_var_is_listable(const config_var_t *var); #define CFG_EQ_LINELIST(a,b,opt) config_lines_eq((a)->opt, (b)->opt) #define CFG_EQ_ROUTERSET(a,b,opt) routerset_equal((a)->opt, (b)->opt) -#ifdef CONFPARSE_PRIVATE +#ifdef CONFMGT_PRIVATE STATIC void config_reset_line(const config_mgr_t *mgr, void *options, const char *key, int use_defaults); STATIC void *config_mgr_get_obj_mutable(const config_mgr_t *mgr, void *toplevel, int idx); STATIC const void *config_mgr_get_obj(const config_mgr_t *mgr, const void *toplevel, int idx); -#endif /* defined(CONFPARSE_PRIVATE) */ +#endif /* defined(CONFMGT_PRIVATE) */ -#endif /* !defined(TOR_CONFPARSE_H) */ +#endif /* !defined(TOR_CONFMGT_H) */ diff --git a/src/lib/confmgt/include.am b/src/lib/confmgt/include.am index 81cd868e5e..d3a7a7cd69 100644 --- a/src/lib/confmgt/include.am +++ b/src/lib/confmgt/include.am @@ -6,7 +6,7 @@ endif # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_confmgt_a_SOURCES = \ - src/lib/confmgt/confparse.c \ + src/lib/confmgt/confmgt.c \ src/lib/confmgt/structvar.c \ src/lib/confmgt/type_defs.c \ src/lib/confmgt/typedvar.c \ @@ -19,7 +19,7 @@ src_lib_libtor_confmgt_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS += \ - src/lib/confmgt/confparse.h \ + src/lib/confmgt/confmgt.h \ src/lib/confmgt/structvar.h \ src/lib/confmgt/type_defs.h \ src/lib/confmgt/typedvar.h \ diff --git a/src/lib/confmgt/lib_confmgt.dox b/src/lib/confmgt/lib_confmgt.dox new file mode 100644 index 0000000000..d18fa304ca --- /dev/null +++ b/src/lib/confmgt/lib_confmgt.dox @@ -0,0 +1,9 @@ +/** +@dir /lib/confmgt +@brief lib/confmgt: Parse, encode, manipulate configuration files. + +This logic is used in common by our state files (statefile.c) and +configuration files (config.c) to manage a set of named, typed fields, +reading and writing them to disk and to the controller. + +**/ diff --git a/src/lib/container/lib_container.dox b/src/lib/container/lib_container.dox new file mode 100644 index 0000000000..675aaeef3f --- /dev/null +++ b/src/lib/container/lib_container.dox @@ -0,0 +1,51 @@ +/** +@dir /lib/container +@brief lib/container: Hash tables, dynamic arrays, bit arrays, etc. + +### Smartlists: Neither lists, nor especially smart. + +For historical reasons, we call our dynamic-allocated array type +`smartlist_t`. It can grow or shrink as elements are added and removed. + +All smartlists hold an array of `void *`. Whenever you expose a smartlist +in an API you *must* document which types its pointers actually hold. + +<!-- It would be neat to fix that, wouldn't it? -NM --> + +Smartlists are created empty with `smartlist_new()` and freed with +`smartlist_free()`. See the `containers.h` header documentation for more +information; there are many convenience functions for commonly needed +operations. + +For low-level operations on smartlists, see also +\refdir{lib/smartlist_core}. + +<!-- TODO: WRITE more about what you can do with smartlists. --> + +### Digest maps, string maps, and more. + +Tor makes frequent use of maps from 160-bit digests, 256-bit digests, +or nul-terminated strings to `void *`. These types are `digestmap_t`, +`digest256map_t`, and `strmap_t` respectively. See the containers.h +module documentation for more information. + +### Intrusive lists and hashtables + +For performance-sensitive cases, we sometimes want to use "intrusive" +collections: ones where the bookkeeping pointers are stuck inside the +structures that belong to the collection. If you've used the +BSD-style sys/queue.h macros, you'll be familiar with these. + +Unfortunately, the `sys/queue.h` macros vary significantly between the +platforms that have them, so we provide our own variants in +`ext/tor_queue.h`. + +We also provide an intrusive hashtable implementation in `ext/ht.h`. +When you're using it, you'll need to define your own hash +functions. If attacker-induced collisions are a worry here, use the +cryptographic siphash24g function to extract hashes. + +<!-- TODO: WRITE about bloom filters, namemaps, bit-arrays, order functions. +--> + +**/ diff --git a/src/lib/container/namemap.c b/src/lib/container/namemap.c index a90057b32c..909dcc9f03 100644 --- a/src/lib/container/namemap.c +++ b/src/lib/container/namemap.c @@ -3,6 +3,11 @@ * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file namemap.c + * @brief Mappings between identifiers and 16-bit ints. + **/ + #include "orconfig.h" #include "lib/container/smartlist.h" #include "lib/container/namemap.h" diff --git a/src/lib/container/namemap_st.h b/src/lib/container/namemap_st.h index 5008fd5855..20a8051918 100644 --- a/src/lib/container/namemap_st.h +++ b/src/lib/container/namemap_st.h @@ -6,6 +6,11 @@ #ifndef NAMEMAP_ST_H #define NAMEMAP_ST_H +/** + * @file namemap_st.h + * @brief Internal declarations for namemap structure. + **/ + #include "lib/cc/compat_compiler.h" #include "ext/ht.h" @@ -28,7 +33,9 @@ struct namemap_t { struct smartlist_t *names; }; +#ifndef COCCI /** Macro to initialize a namemap. */ #define NAMEMAP_INIT() { HT_INITIALIZER(), NULL } +#endif #endif /* !defined(NAMEMAP_ST_H) */ diff --git a/src/lib/container/smartlist.h b/src/lib/container/smartlist.h index 25638e4b22..984cd2d293 100644 --- a/src/lib/container/smartlist.h +++ b/src/lib/container/smartlist.h @@ -92,6 +92,7 @@ char *smartlist_join_strings2(smartlist_t *sl, const char *join, size_t join_len, int terminate, size_t *len_out) ATTR_MALLOC; +#ifndef COCCI /* Helper: Given two lists of items, possibly of different types, such that * both lists are sorted on some common field (as determined by a comparison * expression <b>cmpexpr</b>), and such that one list (<b>sl1</b>) has no @@ -165,5 +166,6 @@ char *smartlist_join_strings2(smartlist_t *sl, const char *join, #define SMARTLIST_FOREACH_JOIN_END(var1, var2) \ } \ STMT_END +#endif /* !defined(COCCI) */ #endif /* !defined(TOR_SMARTLIST_H) */ diff --git a/src/lib/crypt_ops/crypto_dh_nss.c b/src/lib/crypt_ops/crypto_dh_nss.c index 379eb84a4f..aa95fb508f 100644 --- a/src/lib/crypt_ops/crypto_dh_nss.c +++ b/src/lib/crypt_ops/crypto_dh_nss.c @@ -5,7 +5,7 @@ /* See LICENSE for licensing information */ /** - * \file crypto_dh_nss.h + * \file crypto_dh_nss.c * * \brief NSS implementation of Diffie-Hellman over Z_p. **/ diff --git a/src/lib/crypt_ops/crypto_dh_openssl.c b/src/lib/crypt_ops/crypto_dh_openssl.c index 8ae97373e8..e7f22d749b 100644 --- a/src/lib/crypt_ops/crypto_dh_openssl.c +++ b/src/lib/crypt_ops/crypto_dh_openssl.c @@ -103,7 +103,7 @@ crypto_validate_dh_params(const BIGNUM *p, const BIGNUM *g) #endif /* 0 */ /** - * Helper: convert <b>hex<b> to a bignum, and return it. Assert that the + * Helper: convert <b>hex</b> to a bignum, and return it. Assert that the * operation was successful. */ static BIGNUM * diff --git a/src/lib/crypt_ops/crypto_digest.c b/src/lib/crypt_ops/crypto_digest.c index ba226f8756..d14a40f321 100644 --- a/src/lib/crypt_ops/crypto_digest.c +++ b/src/lib/crypt_ops/crypto_digest.c @@ -150,6 +150,9 @@ struct crypto_xof_t { */ EVP_MD_CTX *ctx; #else /* !defined(OPENSSL_HAS_SHAKE3_EVP) */ + /** + * State of the Keccak sponge for the SHAKE-256 computation. + **/ keccak_state s; #endif /* defined(OPENSSL_HAS_SHAKE3_EVP) */ }; diff --git a/src/lib/crypt_ops/crypto_digest.h b/src/lib/crypt_ops/crypto_digest.h index 5869db7800..fb819b12e7 100644 --- a/src/lib/crypt_ops/crypto_digest.h +++ b/src/lib/crypt_ops/crypto_digest.h @@ -38,6 +38,9 @@ /** Length of hex encoding of SHA512 digest, not including final NUL. */ #define HEX_DIGEST512_LEN 128 +/** + * An identifier for a cryptographic digest algorithm. + **/ typedef enum { DIGEST_SHA1 = 0, DIGEST_SHA256 = 1, @@ -45,16 +48,31 @@ typedef enum { DIGEST_SHA3_256 = 3, DIGEST_SHA3_512 = 4, } digest_algorithm_t; +/** Number of digest algorithms that we know */ #define N_DIGEST_ALGORITHMS (DIGEST_SHA3_512+1) +/** Number of digest algorithms to compute when computing "all the + * commonly used digests." + * + * (This is used in common_digests_t and related functions.) + */ #define N_COMMON_DIGEST_ALGORITHMS (DIGEST_SHA256+1) +/** + * Bytes of storage needed to record the state of an in-progress SHA-1 digest. + * + * This is a deliberate overestimate. + **/ #define DIGEST_CHECKPOINT_BYTES (SIZEOF_VOID_P + 512) + /** Structure used to temporarily save the a digest object. Only implemented * for SHA1 digest for now. */ typedef struct crypto_digest_checkpoint_t { #ifdef ENABLE_NSS + /** The number of bytes used in <b>mem</b>. */ unsigned int bytes_used; #endif + /** A buffer to store the SHA1 state. Its contents are unspecified, and + * are managed by the underlying crypto library.*/ uint8_t mem[DIGEST_CHECKPOINT_BYTES]; } crypto_digest_checkpoint_t; @@ -67,10 +85,19 @@ typedef struct crypto_digest_checkpoint_t { * once. **/ typedef struct { + /** An array of digest outputs, one for each "common" digest algorithm. */ char d[N_COMMON_DIGEST_ALGORITHMS][DIGEST256_LEN]; } common_digests_t; +/** + * State for computing a digest over a stream of data. + **/ typedef struct crypto_digest_t crypto_digest_t; + +/** + * State for computing an "extendable-output function" (like SHAKE) over a + * stream of data, and/or streaming the output. + **/ typedef struct crypto_xof_t crypto_xof_t; struct smartlist_t; @@ -97,6 +124,9 @@ crypto_digest_t *crypto_digest_new(void); crypto_digest_t *crypto_digest256_new(digest_algorithm_t algorithm); crypto_digest_t *crypto_digest512_new(digest_algorithm_t algorithm); void crypto_digest_free_(crypto_digest_t *digest); +/** + * Release all storage held in <b>d</b>, and set it to NULL. + **/ #define crypto_digest_free(d) \ FREE_AND_NULL(crypto_digest_t, crypto_digest_free_, (d)) void crypto_digest_add_bytes(crypto_digest_t *digest, const char *data, @@ -122,6 +152,9 @@ crypto_xof_t *crypto_xof_new(void); void crypto_xof_add_bytes(crypto_xof_t *xof, const uint8_t *data, size_t len); void crypto_xof_squeeze_bytes(crypto_xof_t *xof, uint8_t *out, size_t len); void crypto_xof_free_(crypto_xof_t *xof); +/** + * Release all storage held in <b>xof</b>, and set it to NULL. + **/ #define crypto_xof_free(xof) \ FREE_AND_NULL(crypto_xof_t, crypto_xof_free_, (xof)) void crypto_xof(uint8_t *output, size_t output_len, diff --git a/src/lib/crypt_ops/crypto_digest_nss.c b/src/lib/crypt_ops/crypto_digest_nss.c index b73f0736fd..54fb714436 100644 --- a/src/lib/crypt_ops/crypto_digest_nss.c +++ b/src/lib/crypt_ops/crypto_digest_nss.c @@ -44,7 +44,11 @@ digest_alg_to_nss_oid(digest_algorithm_t alg) } } -/* Helper: get an unkeyed digest via pk11wrap */ +/** Helper: Compute an unkeyed digest of the <b>msg_len</b> bytes at + * <b>msg</b>, using the digest algorithm specified by <b>alg</b>. + * Store the result in the <b>len_out</b>-byte buffer at <b>digest</b>. + * Return the number of bytes written on success, and -1 on failure. + **/ static int digest_nss_internal(SECOidTag alg, char *digest, unsigned len_out, @@ -557,4 +561,3 @@ crypto_hmac_sha256(char *hmac_out, tor_assert(ok); } - diff --git a/src/lib/crypt_ops/crypto_digest_openssl.c b/src/lib/crypt_ops/crypto_digest_openssl.c index b0d8b6aee9..319714f868 100644 --- a/src/lib/crypt_ops/crypto_digest_openssl.c +++ b/src/lib/crypt_ops/crypto_digest_openssl.c @@ -147,9 +147,9 @@ crypto_digest_get_algorithm(crypto_digest_t *digest) static size_t crypto_digest_alloc_bytes(digest_algorithm_t alg) { - /* Helper: returns the number of bytes in the 'f' field of 'st' */ + /** Helper: returns the number of bytes in the 'f' field of 'st' */ #define STRUCT_FIELD_SIZE(st, f) (sizeof( ((st*)0)->f )) - /* Gives the length of crypto_digest_t through the end of the field 'd' */ + /** Gives the length of crypto_digest_t through the end of the field 'd' */ #define END_OF_FIELD(f) (offsetof(crypto_digest_t, f) + \ STRUCT_FIELD_SIZE(crypto_digest_t, f)) switch (alg) { @@ -519,4 +519,3 @@ crypto_hmac_sha256(char *hmac_out, (unsigned char*)hmac_out, NULL); tor_assert(rv); } - diff --git a/src/lib/crypt_ops/crypto_ope.c b/src/lib/crypt_ops/crypto_ope.c index ed832d852e..e4fef319e9 100644 --- a/src/lib/crypt_ops/crypto_ope.c +++ b/src/lib/crypt_ops/crypto_ope.c @@ -2,7 +2,8 @@ /* See LICENSE for licensing information */ /** - * A rudimentary order-preserving encryption scheme. + * @file crypto_ope.c + * @brief A rudimentary order-preserving encryption scheme. * * To compute the encryption of N, this scheme uses an AES-CTR stream to * generate M-byte values, and adds the first N of them together. (+1 each to @@ -143,7 +144,7 @@ crypto_ope_new(const uint8_t *key) return ope; } -/** Free all storage held in <>ope</b>. */ +/** Free all storage held in <b>ope</b>. */ void crypto_ope_free_(crypto_ope_t *ope) { diff --git a/src/lib/crypt_ops/crypto_ope.h b/src/lib/crypt_ops/crypto_ope.h index 9778dfe0f0..d6a81dbcc1 100644 --- a/src/lib/crypt_ops/crypto_ope.h +++ b/src/lib/crypt_ops/crypto_ope.h @@ -1,6 +1,11 @@ /* Copyright (c) 2018-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file crypto_ope.h + * @brief header for crypto_ope.c + **/ + #ifndef CRYPTO_OPE_H #define CRYPTO_OPE_H diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.c b/src/lib/crypt_ops/crypto_openssl_mgt.c index f51309219a..2fbebd87e0 100644 --- a/src/lib/crypt_ops/crypto_openssl_mgt.c +++ b/src/lib/crypt_ops/crypto_openssl_mgt.c @@ -121,10 +121,12 @@ crypto_openssl_get_header_version_str(void) return crypto_openssl_header_version_str; } +#ifndef COCCI #ifndef OPENSSL_THREADS -#error OpenSSL has been built without thread support. Tor requires an \ - OpenSSL library with thread support enabled. +#error "OpenSSL has been built without thread support. Tor requires an \ + OpenSSL library with thread support enabled." #endif +#endif /* !defined(COCCI) */ #ifndef NEW_THREAD_API /** Helper: OpenSSL uses this callback to manipulate mutexes. */ diff --git a/src/lib/crypt_ops/crypto_sys.h b/src/lib/crypt_ops/crypto_sys.h index 894243b175..ff449d2e0b 100644 --- a/src/lib/crypt_ops/crypto_sys.h +++ b/src/lib/crypt_ops/crypto_sys.h @@ -2,7 +2,7 @@ /* See LICENSE for licensing information */ /** - * \file log_crypto.h + * \file crypto_sys.h * \brief Declare subsystem object for the crypto module. **/ diff --git a/src/lib/crypt_ops/lib_crypt_ops.dox b/src/lib/crypt_ops/lib_crypt_ops.dox new file mode 100644 index 0000000000..515c67f1c0 --- /dev/null +++ b/src/lib/crypt_ops/lib_crypt_ops.dox @@ -0,0 +1,139 @@ +/** +@dir /lib/crypt_ops +@brief lib/crypt_ops: Cryptographic operations. + +This module contains wrappers around the cryptographic libraries that we +support, and implementations for some higher-level cryptographic +constructions that we use. + +It wraps our two major cryptographic backends (OpenSSL or NSS, as configured +by the user), and also wraps other cryptographic code in src/ext. + +Generally speaking, Tor code shouldn't be calling OpenSSL or NSS +(or any other crypto library) directly. Instead, we should indirect through +one of the functions in this directory, or through \refdir{lib/tls}. + +Cryptography functionality that's available is described below. + +### RNG facilities ### + +The most basic RNG capability in Tor is the crypto_rand() family of +functions. These currently use OpenSSL's RAND_() backend, but may use +something faster in the future. + +In addition to crypto_rand(), which fills in a buffer with random +bytes, we also have functions to produce random integers in certain +ranges; to produce random hostnames; to produce random doubles, etc. + +When you're creating a long-term cryptographic secret, you might want +to use crypto_strongest_rand() instead of crypto_rand(). It takes the +operating system's entropy source and combines it with output from +crypto_rand(). This is a pure paranoia measure, but it might help us +someday. + +You can use smartlist_choose() to pick a random element from a smartlist +and smartlist_shuffle() to randomize the order of a smartlist. Both are +potentially a bit slow. + +### Cryptographic digests and related functions ### + +We treat digests as separate types based on the length of their +outputs. We support one 160-bit digest (SHA1), two 256-bit digests +(SHA256 and SHA3-256), and two 512-bit digests (SHA512 and SHA3-512). + +You should not use SHA1 for anything new. + +The crypto_digest\*() family of functions manipulates digests. You +can either compute a digest of a chunk of memory all at once using +crypto_digest(), crypto_digest256(), or crypto_digest512(). Or you +can create a crypto_digest_t object with +crypto_digest{,256,512}_new(), feed information to it in chunks using +crypto_digest_add_bytes(), and then extract the final digest using +crypto_digest_get_digest(). You can copy the state of one of these +objects using crypto_digest_dup() or crypto_digest_assign(). + +We support the HMAC hash-based message authentication code +instantiated using SHA256. See crypto_hmac_sha256. (You should not +add any HMAC users with SHA1, and HMAC is not necessary with SHA3.) + +We also support the SHA3 cousins, SHAKE128 and SHAKE256. Unlike +digests, these are extendable output functions (or XOFs) where you can +get any amount of output. Use the crypto_xof_\*() functions to access +these. + +We have several ways to derive keys from cryptographically strong secret +inputs (like diffie-hellman outputs). The old +crypto_expand_key_material_TAP() performs an ad-hoc KDF based on SHA1 -- you +shouldn't use it for implementing anything but old versions of the Tor +protocol. You can use HKDF-SHA256 (as defined in RFC5869) for more modern +protocols. Also consider SHAKE256. + +If your input is potentially weak, like a password or passphrase, use a salt +along with the secret_to_key() functions as defined in crypto_s2k.c. Prefer +scrypt over other hashing methods when possible. If you're using a password +to encrypt something, see the "boxed file storage" section below. + +Finally, in order to store objects in hash tables, Tor includes the +randomized SipHash 2-4 function. Call it via the siphash24g() function in +src/ext/siphash.h whenever you're creating a hashtable whose keys may be +manipulated by an attacker in order to DoS you with collisions. + + +### Stream ciphers ### + +You can create instances of a stream cipher using crypto_cipher_new(). +These are stateful objects of type crypto_cipher_t. Note that these +objects only support AES-128 right now; a future version should add +support for AES-128 and/or ChaCha20. + +You can encrypt/decrypt with crypto_cipher_encrypt or +crypto_cipher_decrypt. The crypto_cipher_crypt_inplace function performs +an encryption without a copy. + +Note that sensible people should not use raw stream ciphers; they should +probably be using some kind of AEAD. Sorry. + +### Public key functionality ### + +We support four public key algorithms: DH1024, RSA, Curve25519, and +Ed25519. + +We support DH1024 over two prime groups. You access these via the +crypto_dh_\*() family of functions. + +We support RSA in many bit sizes for signing and encryption. You access +it via the crypto_pk_*() family of functions. Note that a crypto_pk_t +may or may not include a private key. See the crypto_pk_* functions in +crypto.c for a full list of functions here. + +For Curve25519 functionality, see the functions and types in +crypto_curve25519.c. Curve25519 is generally suitable for when you need +a secure fast elliptic-curve diffie hellman implementation. When +designing new protocols, prefer it over DH in Z_p. + +For Ed25519 functionality, see the functions and types in +crypto_ed25519.c. Ed25519 is a generally suitable as a secure fast +elliptic curve signature method. For new protocols, prefer it over RSA +signatures. + +### Metaformats for storage ### + +When OpenSSL manages the storage of some object, we use whatever format +OpenSSL provides -- typically, some kind of PEM-wrapped base 64 encoding +that starts with "----- BEGIN CRYPTOGRAPHIC OBJECT ----". + +When we manage the storage of some cryptographic object, we prefix the +object with 32-byte NUL-padded prefix in order to avoid accidental +object confusion; see the crypto_read_tagged_contents_from_file() and +crypto_write_tagged_contents_to_file() functions for manipulating +these. The prefix is "== type: tag ==", where type describes the object +and its encoding, and tag indicates which one it is. + +### Boxed-file storage ### + +When managing keys, you frequently want to have some way to write a +secret object to disk, encrypted with a passphrase. The crypto_pwbox +and crypto_unpwbox functions do so in a way that's likely to be +readable by future versions of Tor. + +**/ diff --git a/src/lib/ctime/lib_ctime.dox b/src/lib/ctime/lib_ctime.dox new file mode 100644 index 0000000000..2bcd0f036a --- /dev/null +++ b/src/lib/ctime/lib_ctime.dox @@ -0,0 +1,16 @@ +/** +@dir /lib/ctime +@brief lib/ctime: Constant-time code to avoid side-channels. + +This module contains constant-time implementations of various +data comparison and table lookup functions. We use these in preference to +memcmp() and so forth, since memcmp() can leak information about its inputs +based on how fast it returns. In general, your code should call tor_memeq() +and tor_memneq(), not memcmp(). + +We also define some _non_-constant-time wrappers for memcmp() here: Since we +consider calls to memcmp() to be in error, we require that code that actually +doesn't need to be constant-time to use the fast_memeq() / fast_memneq() / +fast_memcmp() aliases instead. + +**/ diff --git a/src/lib/defs/lib_defs.dox b/src/lib/defs/lib_defs.dox new file mode 100644 index 0000000000..8ed4d7a0af --- /dev/null +++ b/src/lib/defs/lib_defs.dox @@ -0,0 +1,4 @@ +/** +@dir /lib/defs +@brief lib/defs: Lowest-level constants, used in many places. +**/ diff --git a/src/lib/dispatch/dispatch_cfg.h b/src/lib/dispatch/dispatch_cfg.h index 348dce8d40..929ec54215 100644 --- a/src/lib/dispatch/dispatch_cfg.h +++ b/src/lib/dispatch/dispatch_cfg.h @@ -7,6 +7,11 @@ #ifndef TOR_DISPATCH_CFG_H #define TOR_DISPATCH_CFG_H +/** + * @file dispatch_cfg.h + * @brief Header for distpach_cfg.c + **/ + #include "lib/dispatch/msgtypes.h" #include "lib/testsupport/testsupport.h" diff --git a/src/lib/dispatch/dispatch_cfg_st.h b/src/lib/dispatch/dispatch_cfg_st.h index 57b6f0347f..d06540c4a9 100644 --- a/src/lib/dispatch/dispatch_cfg_st.h +++ b/src/lib/dispatch/dispatch_cfg_st.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file dispatch_cfg_st.h + * @brief Declarations for dispatch-configuration types. + **/ + #ifndef TOR_DISPATCH_CFG_ST_H #define TOR_DISPATCH_CFG_ST_H diff --git a/src/lib/dispatch/dispatch_naming.c b/src/lib/dispatch/dispatch_naming.c index 83d9a2d604..c501aa34bd 100644 --- a/src/lib/dispatch/dispatch_naming.c +++ b/src/lib/dispatch/dispatch_naming.c @@ -4,6 +4,11 @@ * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file dispatch_naming.c + * @brief Name-to-ID maps for our message dispatch system. + **/ + #include "orconfig.h" #include "lib/cc/compat_compiler.h" @@ -33,6 +38,7 @@ dispatch_naming_init(void) { } +#ifndef COCCI /* Helper macro: declare functions to map IDs to and from names for a given * type in a namemap_t. */ @@ -56,6 +62,7 @@ dispatch_naming_init(void) return namemap_get_size(&type##_id_map); \ } \ EAT_SEMICOLON +#endif /* !defined(COCCI) */ DECLARE_ID_MAP_FNS(message); DECLARE_ID_MAP_FNS(channel); diff --git a/src/lib/dispatch/dispatch_naming.h b/src/lib/dispatch/dispatch_naming.h index fd6c83cc12..d36851bce9 100644 --- a/src/lib/dispatch/dispatch_naming.h +++ b/src/lib/dispatch/dispatch_naming.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file dispatch_naming.h + * @brief Header for dispatch_naming.c + **/ + #ifndef TOR_DISPATCH_NAMING_H #define TOR_DISPATCH_NAMING_H diff --git a/src/lib/dispatch/lib_dispatch.dox b/src/lib/dispatch/lib_dispatch.dox new file mode 100644 index 0000000000..955b7df64f --- /dev/null +++ b/src/lib/dispatch/lib_dispatch.dox @@ -0,0 +1,16 @@ +/** +@dir /lib/dispatch +@brief lib/dispatch: In-process message delivery. + +This module provides a general in-process "message dispatch" system in which +typed messages are sent on channels. The dispatch.h header has far more +information. + +It is used by by \refdir{lib/pubsub} to implement our general +inter-module publish/subscribe system. + +This is not a fancy multi-threaded many-to-many dispatcher as you may be used +to from more sophisticated architectures: this dispatcher is intended only +for use in improving Tor's architecture. + +**/ diff --git a/src/lib/encoding/lib_encoding.dox b/src/lib/encoding/lib_encoding.dox new file mode 100644 index 0000000000..ca698cb183 --- /dev/null +++ b/src/lib/encoding/lib_encoding.dox @@ -0,0 +1,8 @@ +/** +@dir /lib/encoding +@brief lib/encoding: Encoding data in various forms, types, and transformations + +Here we have time formats (timefmt.c), quoted strings (qstring.c), C strings +(string.c) base-16/32/64 (binascii.c), and more. + +**/ diff --git a/src/lib/encoding/pem.c b/src/lib/encoding/pem.c index 24b238b130..95f93ebeff 100644 --- a/src/lib/encoding/pem.c +++ b/src/lib/encoding/pem.c @@ -42,7 +42,7 @@ pem_encoded_size(size_t src_len, const char *objtype) /** * PEM-encode the <b>srclen</b>-byte object at <b>src</b> into the - * <b>destlen<\b>-byte buffer at <b>dest</b>, tagging it with <b>objtype</b>. + * <b>destlen</b>-byte buffer at <b>dest</b>, tagging it with <b>objtype</b>. * Return 0 on success and -1 on failure. */ int diff --git a/src/lib/err/lib_err.dox b/src/lib/err/lib_err.dox new file mode 100644 index 0000000000..d1479b1140 --- /dev/null +++ b/src/lib/err/lib_err.dox @@ -0,0 +1,15 @@ +/** +@dir /lib/err +@brief lib/err: Lowest-level error handling code. + +This module is responsible for generating stack traces, handling raw +assertion failures, and otherwise reporting problems that might not be +safe to report via the regular logging module. + +There are three kinds of users for the functions in this module: + * Code that needs a way to assert(), but which cannot use the regular + `tor_assert()` macros in logging module. + * Code that needs signal-safe error reporting. + * Higher-level error handling code. + +**/ diff --git a/src/lib/evloop/compat_libevent.c b/src/lib/evloop/compat_libevent.c index 91eacb9938..500c74831c 100644 --- a/src/lib/evloop/compat_libevent.c +++ b/src/lib/evloop/compat_libevent.c @@ -422,7 +422,7 @@ mainloop_event_activate(mainloop_event_t *event) * * If the event is scheduled for a different time, cancel it and run * after this delay instead. If the event is currently pending to run - * <em>now</b>, has no effect. + * <b>now</b>, has no effect. * * Do not call this function with <b>tv</b> == NULL -- use * mainloop_event_activate() instead. diff --git a/src/lib/evloop/lib_evloop.dox b/src/lib/evloop/lib_evloop.dox new file mode 100644 index 0000000000..52fcf67755 --- /dev/null +++ b/src/lib/evloop/lib_evloop.dox @@ -0,0 +1,9 @@ +/** +@dir /lib/evloop +@brief lib/evloop: Low-level event loop. + +This modules has tools to manage the [libevent](https://libevent.org/) event +loop and related functionality, in order to implement asynchronous +networking, timers, periodic events, and other scheduling tasks. + +**/ diff --git a/src/lib/evloop/timers.c b/src/lib/evloop/timers.c index 4b2a96ef7d..c5bb0f5958 100644 --- a/src/lib/evloop/timers.c +++ b/src/lib/evloop/timers.c @@ -56,13 +56,15 @@ struct timeout_cb { /* * These definitions are for timeouts.c and timeouts.h. */ -#ifdef __GNUC__ +#ifdef COCCI +#define TIMEOUT_PUBLIC +#elif defined(__GNUC__) /* We're not exposing any of the functions outside this file. */ #define TIMEOUT_PUBLIC __attribute__((__unused__)) static #else /* We're not exposing any of the functions outside this file. */ #define TIMEOUT_PUBLIC static -#endif /* defined(__GNUC__) */ +#endif /* defined(COCCI) || ... */ /* We're not using periodic events. */ #define TIMEOUT_DISABLE_INTERVALS /* We always know the global_timeouts object, so we don't need each timeout diff --git a/src/lib/fdio/lib_fdio.dox b/src/lib/fdio/lib_fdio.dox new file mode 100644 index 0000000000..9e2fda617a --- /dev/null +++ b/src/lib/fdio/lib_fdio.dox @@ -0,0 +1,7 @@ +/** +@dir /lib/fdio +@brief lib/fdio: Code to read/write on file descriptors. + +(This module also handles sockets, on platforms where a socket is not a kind +of fd.) +**/ diff --git a/src/lib/fs/lib_fs.dox b/src/lib/fs/lib_fs.dox new file mode 100644 index 0000000000..4466250bb8 --- /dev/null +++ b/src/lib/fs/lib_fs.dox @@ -0,0 +1,11 @@ +/** +@dir /lib/fs +@brief lib/fs: Files, filenames, directories, etc. + +This module is mostly a set of compatibility wrappers around +operating-system-specific filesystem access. + +It also contains a set of convenience functions for safely writing to files, +creating directories, and so on. + +**/ diff --git a/src/lib/fs/mmap.c b/src/lib/fs/mmap.c index f71c0cff7a..9d50a476bd 100644 --- a/src/lib/fs/mmap.c +++ b/src/lib/fs/mmap.c @@ -42,8 +42,8 @@ * failure, return NULL. Sets errno properly, using ERANGE to mean * "empty file". Must only be called on trusted Tor-owned files, as changing * the underlying file's size causes unspecified behavior. */ -tor_mmap_t * -tor_mmap_file(const char *filename) +MOCK_IMPL(tor_mmap_t *, +tor_mmap_file,(const char *filename)) { int fd; /* router file */ char *string; @@ -111,8 +111,8 @@ tor_mmap_file(const char *filename) } /** Release storage held for a memory mapping; returns 0 on success, * or -1 on failure (and logs a warning). */ -int -tor_munmap_file(tor_mmap_t *handle) +MOCK_IMPL(int, +tor_munmap_file,(tor_mmap_t *handle)) { int res; @@ -132,8 +132,8 @@ tor_munmap_file(tor_mmap_t *handle) return res; } #elif defined(_WIN32) -tor_mmap_t * -tor_mmap_file(const char *filename) +MOCK_IMPL(tor_mmap_t *, +tor_mmap_file,(const char *filename)) { TCHAR tfilename[MAX_PATH]= {0}; tor_mmap_t *res = tor_malloc_zero(sizeof(tor_mmap_t)); @@ -213,8 +213,8 @@ tor_mmap_file(const char *filename) } /* Unmap the file, and return 0 for success or -1 for failure */ -int -tor_munmap_file(tor_mmap_t *handle) +MOCK_IMPL(int, +tor_munmap_file,(tor_mmap_t *handle)) { if (handle == NULL) return 0; diff --git a/src/lib/fs/mmap.h b/src/lib/fs/mmap.h index 61aad544b2..beb0535109 100644 --- a/src/lib/fs/mmap.h +++ b/src/lib/fs/mmap.h @@ -13,6 +13,7 @@ #define TOR_MMAP_H #include "lib/cc/compat_compiler.h" +#include "lib/testsupport/testsupport.h" #include <stddef.h> #ifdef _WIN32 @@ -35,7 +36,7 @@ typedef struct tor_mmap_t { } tor_mmap_t; -tor_mmap_t *tor_mmap_file(const char *filename); -int tor_munmap_file(tor_mmap_t *handle); +MOCK_DECL(tor_mmap_t *, tor_mmap_file, (const char *filename)); +MOCK_DECL(int, tor_munmap_file, (tor_mmap_t *handle)); #endif /* !defined(TOR_MMAP_H) */ diff --git a/src/lib/fs/path.c b/src/lib/fs/path.c index 28dde62aea..9f297d98e8 100644 --- a/src/lib/fs/path.c +++ b/src/lib/fs/path.c @@ -255,9 +255,10 @@ alloc_getcwd(void) #endif /* !defined(_WIN32) */ /** Expand possibly relative path <b>fname</b> to an absolute path. - * Return a newly allocated string, possibly equal to <b>fname</b>. */ + * Return a newly allocated string, which may be a duplicate of <b>fname</b>. + */ char * -make_path_absolute(char *fname) +make_path_absolute(const char *fname) { #ifdef _WIN32 char *absfname_malloced = _fullpath(NULL, fname, 1); diff --git a/src/lib/fs/path.h b/src/lib/fs/path.h index 28a1838b88..0c2a574941 100644 --- a/src/lib/fs/path.h +++ b/src/lib/fs/path.h @@ -25,6 +25,6 @@ char *expand_filename(const char *filename); int path_is_relative(const char *filename); void clean_fname_for_stat(char *name); int get_parent_directory(char *fname); -char *make_path_absolute(char *fname); +char *make_path_absolute(const char *fname); #endif /* !defined(TOR_PATH_H) */ diff --git a/src/lib/geoip/country.h b/src/lib/geoip/country.h index a24a1c4c0d..2bff4f4477 100644 --- a/src/lib/geoip/country.h +++ b/src/lib/geoip/country.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file country.h + * @brief Country type for geoip. + **/ + #ifndef TOR_COUNTRY_H #define TOR_COUNTRY_H diff --git a/src/lib/geoip/lib_geoip.dox b/src/lib/geoip/lib_geoip.dox new file mode 100644 index 0000000000..da1123640b --- /dev/null +++ b/src/lib/geoip/lib_geoip.dox @@ -0,0 +1,5 @@ +/** +@dir /lib/geoip +@brief lib/geoip: IP-to-country mapping + +**/ diff --git a/src/lib/intmath/lib_intmath.dox b/src/lib/intmath/lib_intmath.dox new file mode 100644 index 0000000000..e9b7044706 --- /dev/null +++ b/src/lib/intmath/lib_intmath.dox @@ -0,0 +1,4 @@ +/** +@dir /lib/intmath +@brief lib/intmath: Integer mathematics. +**/ diff --git a/src/lib/intmath/weakrng.h b/src/lib/intmath/weakrng.h index 40941e59b2..d583c8f79b 100644 --- a/src/lib/intmath/weakrng.h +++ b/src/lib/intmath/weakrng.h @@ -19,8 +19,11 @@ typedef struct tor_weak_rng_t { uint32_t state; } tor_weak_rng_t; +#ifndef COCCI #define TOR_WEAK_RNG_INIT {383745623} +#endif #define TOR_WEAK_RANDOM_MAX (INT_MAX) + void tor_init_weak_random(tor_weak_rng_t *weak_rng, unsigned seed); int32_t tor_weak_random(tor_weak_rng_t *weak_rng); int32_t tor_weak_random_range(tor_weak_rng_t *rng, int32_t top); diff --git a/src/lib/lib.dox b/src/lib/lib.dox new file mode 100644 index 0000000000..fdf2c47687 --- /dev/null +++ b/src/lib/lib.dox @@ -0,0 +1,133 @@ +/** +@dir /lib +@brief lib: low-level functionality. + +The "lib" directory contains low-level functionality. In general, this +code is not necessarily Tor-specific, but is instead possibly useful for +other applications. + +The modules in `lib` are currently well-factored: each one depends +only on lower-level modules. You can see an up-to-date list of the +modules, sorted from lowest to highest level, by running +`./scripts/maint/practracker/includes.py --toposort`. + +As of this writing, the library modules are (from lowest to highest +level): + + - \refdir{lib/cc} -- Macros for managing the C compiler and + language. + + - \refdir{lib/version} -- Holds the current version of Tor. + + - \refdir{lib/testsupport} -- Helpers for making + test-only code, and test mocking support. + + - \refdir{lib/defs} -- Lowest-level constants. + + - \refdir{lib/subsys} -- Types used for declaring a + "subsystem". (_A subsystem is a module with support for initialization, + shutdown, configuration, and so on._) + + - \refdir{lib/conf} -- For declaring configuration options. + + - \refdir{lib/arch} -- For handling differences in CPU + architecture. + + - \refdir{lib/err} -- Lowest-level error handling code. + + - \refdir{lib/malloc} -- Memory management. + management. + + - \refdir{lib/intmath} -- Integer mathematics. + + - \refdir{lib/fdio} -- For + reading and writing n file descriptors. + + - \refdir{lib/lock} -- Simple locking support. + (_Lower-level than the rest of the threading code._) + + - \refdir{lib/ctime} -- Constant-time code to avoid + side-channels. + + - \refdir{lib/string} -- Low-level string manipulation. + + - \refdir{lib/wallclock} -- + For inspecting and manipulating the current (UTC) time. + + - \refdir{lib/osinfo} -- For inspecting the OS version + and capabilities. + + - \refdir{lib/smartlist_core} -- The bare-bones + pieces of our dynamic array ("smartlist") implementation. + + - \refdir{lib/log} -- Log messages to files, syslogs, etc. + + - \refdir{lib/container} -- General purpose containers, + including dynamic arrays ("smartlists"), hashtables, bit arrays, + etc. + + - \refdir{lib/trace} -- A general-purpose API + function-tracing functionality Tor. (_Currently not much used._) + + - \refdir{lib/thread} -- Mid-level Threading. + + - \refdir{lib/term} -- Terminal manipulation + (like reading a password from the user). + + - \refdir{lib/memarea} -- A fast + "arena" style allocator, where the data is freed all at once. + + - \refdir{lib/encoding} -- Encoding + data in various formats, datatypes, and transformations. + + - \refdir{lib/dispatch} -- A general-purpose in-process + message delivery system. + + - \refdir{lib/sandbox} -- Our Linux seccomp2 sandbox + implementation. + + - \refdir{lib/pubsub} -- A publish/subscribe message passing system. + + - \refdir{lib/fs} -- Files, filenames, directories, etc. + + - \refdir{lib/confmgt} -- Parse, encode, and manipulate onfiguration files. + + - \refdir{lib/crypt_ops} -- Cryptographic operations. + + - \refdir{lib/meminfo} -- Functions for inspecting our + memory usage, if the malloc implementation exposes that to us. + + - \refdir{lib/time} -- Higher level time functions, including + fine-gained and monotonic timers. + + - \refdir{lib/math} -- Floating-point mathematical utilities. + + - \refdir{lib/buf} -- An efficient byte queue. + + - \refdir{lib/net} -- Networking code, including address + manipulation, compatibility wrappers, etc. + + - \refdir{lib/compress} -- Wraps several compression libraries. + + - \refdir{lib/geoip} -- IP-to-country mapping. + + - \refdir{lib/tls} -- TLS library wrappers. + + - \refdir{lib/evloop} -- Low-level event-loop. + + - \refdir{lib/process} -- Launch and manage subprocesses. + +### What belongs in lib? + +In general, if you can imagine some program wanting the functionality +you're writing, even if that program had nothing to do with Tor, your +functionality belongs in lib. + +If it falls into one of the existing "lib" categories, your +functionality belongs in lib. + +If you are using platform-specific `ifdef`s to manage compatibility +issues among platforms, you should probably consider whether you can +put your code into lib. + +**/ diff --git a/src/lib/lock/lib_lock.dox b/src/lib/lock/lib_lock.dox new file mode 100644 index 0000000000..868b5ba7d4 --- /dev/null +++ b/src/lib/lock/lib_lock.dox @@ -0,0 +1,8 @@ +/** +@dir /lib/lock +@brief lib/lock: Simple locking support. + +This module is more low-level than the rest of the threading code, since it +is needed by more intermediate-level modules. + +**/ diff --git a/src/lib/log/lib_log.dox b/src/lib/log/lib_log.dox new file mode 100644 index 0000000000..a772dc3207 --- /dev/null +++ b/src/lib/log/lib_log.dox @@ -0,0 +1,12 @@ +/** +@dir /lib/log +@brief lib/log: Log messages to files, syslogs, etc. + +You can think of this as the logical "midpoint" of the +\refdir{lib} code": much of the higher-level code is higher-level +_because_ it uses the logging module, and much of the lower-level code is +specifically written to avoid having to log, because the logging module +depends on it. + + +**/ diff --git a/src/lib/log/log.c b/src/lib/log/log.c index 83f04a3467..cb92ef07ef 100644 --- a/src/lib/log/log.c +++ b/src/lib/log/log.c @@ -276,8 +276,8 @@ static int log_time_granularity = 1; /** Define log time granularity for all logs to be <b>granularity_msec</b> * milliseconds. */ -void -set_log_time_granularity(int granularity_msec) +MOCK_IMPL(void, +set_log_time_granularity,(int granularity_msec)) { log_time_granularity = granularity_msec; tor_log_sigsafe_err_set_granularity(granularity_msec); @@ -523,7 +523,7 @@ logfile_deliver(logfile_t *lf, const char *buf, size_t msg_len, * pass them, and some very old ones do not detect overflow so well. * Regrettably, they call their maximum line length MAXLINE. */ #if MAXLINE < 64 -#warn "MAXLINE is a very low number; it might not be from syslog.h after all" +#warning "MAXLINE is a very low number; it might not be from syslog.h." #endif char *m = msg_after_prefix; if (msg_len >= MAXLINE) @@ -937,9 +937,9 @@ set_log_severity_config(int loglevelMin, int loglevelMax, /** Add a log handler named <b>name</b> to send all messages in <b>severity</b> * to <b>fd</b>. Copies <b>severity</b>. Helper: does no locking. */ -static void -add_stream_log_impl(const log_severity_list_t *severity, - const char *name, int fd) +MOCK_IMPL(STATIC void, +add_stream_log_impl,(const log_severity_list_t *severity, + const char *name, int fd)) { logfile_t *lf; lf = tor_malloc_zero(sizeof(logfile_t)); @@ -995,18 +995,16 @@ logs_set_domain_logging(int enabled) UNLOCK_LOGS(); } -/** Add a log handler to receive messages during startup (before the real - * logs are initialized). +/** Add a log handler to accept messages when no other log is configured. */ void -add_temp_log(int min_severity) +add_default_log(int min_severity) { log_severity_list_t *s = tor_malloc_zero(sizeof(log_severity_list_t)); set_log_severity_config(min_severity, LOG_ERR, s); LOCK_LOGS(); - add_stream_log_impl(s, "<temp>", fileno(stdout)); + add_stream_log_impl(s, "<default>", fileno(stdout)); tor_free(s); - logfiles->is_temporary = 1; UNLOCK_LOGS(); } @@ -1149,8 +1147,7 @@ flush_log_messages_from_startup(void) UNLOCK_LOGS(); } -/** Close any log handlers added by add_temp_log() or marked by - * mark_logs_temp(). */ +/** Close any log handlers marked by mark_logs_temp(). */ void close_temp_logs(void) { @@ -1202,10 +1199,10 @@ mark_logs_temp(void) * opening the logfile failed, -1 is returned and errno is set appropriately * (by open(2)). Takes ownership of fd. */ -int -add_file_log(const log_severity_list_t *severity, - const char *filename, - int fd) +MOCK_IMPL(int, +add_file_log,(const log_severity_list_t *severity, + const char *filename, + int fd)) { logfile_t *lf; diff --git a/src/lib/log/log.h b/src/lib/log/log.h index 8e36012616..5cf8a36cf7 100644 --- a/src/lib/log/log.h +++ b/src/lib/log/log.h @@ -23,9 +23,11 @@ #include <syslog.h> #define LOG_WARN LOG_WARNING #if LOG_DEBUG < LOG_ERR +#ifndef COCCI #error "Your syslog.h thinks high numbers are more important. " \ "We aren't prepared to deal with that." #endif +#endif /* LOG_DEBUG < LOG_ERR */ #else /* !defined(HAVE_SYSLOG_H) */ /* Note: Syslog's logging code refers to priorities, with 0 being the most * important. Thus, all our comparisons needed to be reversed when we added @@ -163,11 +165,11 @@ int parse_log_severity_config(const char **cfg, log_severity_list_t *severity_out); void set_log_severity_config(int minSeverity, int maxSeverity, log_severity_list_t *severity_out); -void add_stream_log(const log_severity_list_t *severity, const char *name, - int fd); -int add_file_log(const log_severity_list_t *severity, - const char *filename, - int fd); +void add_stream_log(const log_severity_list_t *severity, + const char *name, int fd); +MOCK_DECL(int, add_file_log,(const log_severity_list_t *severity, + const char *filename, + int fd)); #ifdef HAVE_SYSLOG_H int add_syslog_log(const log_severity_list_t *severity, @@ -185,7 +187,7 @@ int get_min_log_level(void); void switch_logs_debug(void); void logs_free_all(void); void logs_close_sigsafe(void); -void add_temp_log(int min_severity); +void add_default_log(int min_severity); void close_temp_logs(void); void rollback_log_changes(void); void mark_logs_temp(void); @@ -194,7 +196,7 @@ void change_callback_log_severity(int loglevelMin, int loglevelMax, void flush_pending_log_callbacks(void); void flush_log_messages_from_startup(void); void log_set_application_name(const char *name); -void set_log_time_granularity(int granularity_msec); +MOCK_DECL(void, set_log_time_granularity,(int granularity_msec)); void truncate_logs(void); void tor_log(int severity, log_domain_mask_t domain, const char *format, ...) @@ -306,7 +308,9 @@ extern const log_domain_mask_t LD_GENERAL_; MOCK_DECL(STATIC void, logv, (int severity, log_domain_mask_t domain, const char *funcname, const char *suffix, const char *format, va_list ap) CHECK_PRINTF(5,0)); -#endif +MOCK_DECL(STATIC void, add_stream_log_impl,( + const log_severity_list_t *severity, const char *name, int fd)); +#endif /* defined(LOG_PRIVATE) */ #if defined(LOG_PRIVATE) || defined(TOR_UNIT_TESTS) /** Given a severity, yields an index into log_severity_list_t.masks to use diff --git a/src/lib/log/ratelim.h b/src/lib/log/ratelim.h index 1db54ba726..64f52df666 100644 --- a/src/lib/log/ratelim.h +++ b/src/lib/log/ratelim.h @@ -45,7 +45,9 @@ typedef struct ratelim_t { int n_calls_since_last_time; } ratelim_t; +#ifndef COCCI #define RATELIM_INIT(r) { (r), 0, 0 } +#endif #define RATELIM_TOOMANY (16*1000*1000) char *rate_limit_log(ratelim_t *lim, time_t now); diff --git a/src/lib/log/util_bug.h b/src/lib/log/util_bug.h index c3141754de..d0a311ac61 100644 --- a/src/lib/log/util_bug.h +++ b/src/lib/log/util_bug.h @@ -131,7 +131,9 @@ #undef BUG // Coverity defines this in global headers; let's override it. This is a // magic coverity-only preprocessor thing. +#ifndef COCCI #nodef BUG(x) (x) +#endif #endif /* defined(__COVERITY__) */ #if defined(__COVERITY__) || defined(__clang_analyzer__) @@ -200,6 +202,7 @@ : 0) #endif /* defined(ALL_BUGS_ARE_FATAL) || ... */ +#ifndef COCCI #ifdef __GNUC__ #define IF_BUG_ONCE__(cond,var) \ if (( { \ @@ -208,7 +211,7 @@ if (bool_result && !var) { \ var = 1; \ tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \ - "!("#cond")", 1, NULL); \ + ("!("#cond")"), 1, NULL); \ } \ bool_result; } )) #else /* !defined(__GNUC__) */ @@ -218,10 +221,12 @@ (var ? 1 : \ (var=1, \ tor_bug_occurred_(SHORT_FILE__, __LINE__, __func__, \ - "!("#cond")", 1, NULL), \ + ("!("#cond")"), 1, NULL), \ 1)) \ : 0) #endif /* defined(__GNUC__) */ +#endif /* !defined(COCCI) */ + #define IF_BUG_ONCE_VARNAME_(a) \ warning_logged_on_ ## a ## __ #define IF_BUG_ONCE_VARNAME__(a) \ diff --git a/src/lib/malloc/lib_malloc.dox b/src/lib/malloc/lib_malloc.dox new file mode 100644 index 0000000000..c05e4c6473 --- /dev/null +++ b/src/lib/malloc/lib_malloc.dox @@ -0,0 +1,78 @@ +/** +@dir /lib/malloc +@brief lib/malloc: Wrappers and utilities for memory management. + + +Tor imposes a few light wrappers over C's native malloc and free +functions, to improve convenience, and to allow wholescale replacement +of malloc and free as needed. + +You should never use 'malloc', 'calloc', 'realloc, or 'free' on their +own; always use the variants prefixed with 'tor_'. +They are the same as the standard C functions, with the following +exceptions: + + * `tor_free(NULL)` is a no-op. + * `tor_free()` is a macro that takes an lvalue as an argument and sets it to + NULL after freeing it. To avoid this behavior, you can use `tor_free_()` + instead. + * tor_malloc() and friends fail with an assertion if they are asked to + allocate a value so large that it is probably an underflow. + * It is always safe to `tor_malloc(0)`, regardless of whether your libc + allows it. + * `tor_malloc()`, `tor_realloc()`, and friends are never allowed to fail. + Instead, Tor will die with an assertion. This means that you never + need to check their return values. See the next subsection for + information on why we think this is a good idea. + +We define additional general-purpose memory allocation functions as well: + + * `tor_malloc_zero(x)` behaves as `calloc(1, x)`, except the it makes clear + the intent to allocate a single zeroed-out value. + * `tor_reallocarray(x,y)` behaves as the OpenBSD reallocarray function. + Use it for cases when you need to realloc() in a multiplication-safe + way. + +And specific-purpose functions as well: + + * `tor_strdup()` and `tor_strndup()` behaves as the underlying libc + functions, but use `tor_malloc()` instead of the underlying function. + * `tor_memdup()` copies a chunk of memory of a given size. + * `tor_memdup_nulterm()` copies a chunk of memory of a given size, then + NUL-terminates it just to be safe. + +#### Why assert on allocation failure? + +Why don't we allow `tor_malloc()` and its allies to return NULL? + +First, it's error-prone. Many programmers forget to check for NULL return +values, and testing for `malloc()` failures is a major pain. + +Second, it's not necessarily a great way to handle OOM conditions. It's +probably better (we think) to have a memory target where we dynamically free +things ahead of time in order to stay under the target. Trying to respond to +an OOM at the point of `tor_malloc()` failure, on the other hand, would involve +a rare operation invoked from deep in the call stack. (Again, that's +error-prone and hard to debug.) + +Third, thanks to the rise of Linux and other operating systems that allow +memory to be overcommitted, you can't actually ever rely on getting a NULL +from `malloc()` when you're out of memory; instead you have to use an approach +closer to tracking the total memory usage. + +#### Conventions for your own allocation functions. + +Whenever you create a new type, the convention is to give it a pair of +`x_new()` and `x_free_()` functions, named after the type. + +Calling `x_free(NULL)` should always be a no-op. + +There should additionally be an `x_free()` macro, defined in terms of +`x_free_()`. This macro should set its lvalue to NULL. You can define it +using the FREE_AND_NULL macro, as follows: + +``` +#define x_free(ptr) FREE_AND_NULL(x_t, x_free_, (ptr)) +``` + +**/ diff --git a/src/lib/malloc/map_anon.c b/src/lib/malloc/map_anon.c index 9559cbe2d4..0e78521bd8 100644 --- a/src/lib/malloc/map_anon.c +++ b/src/lib/malloc/map_anon.c @@ -78,8 +78,8 @@ #endif /* defined(HAVE_MINHERIT) || ... */ #if defined(HAVE_MINHERIT) && !defined(FLAG_ZERO) && !defined(FLAG_NOINHERIT) -#warn "minherit() is defined, but we couldn't find the right flag for it." -#warn "This is probably a bug in Tor's support for this platform." +#warning "minherit() is defined, but we couldn't find the right flag for it." +#warning "This is probably a bug in Tor's support for this platform." #endif /** diff --git a/src/lib/math/lib_math.dox b/src/lib/math/lib_math.dox new file mode 100644 index 0000000000..f20d7092b3 --- /dev/null +++ b/src/lib/math/lib_math.dox @@ -0,0 +1,8 @@ +/** +@dir /lib/math +@brief lib/math: Floating-point math utilities. + +This module includes a bunch of floating-point compatibility code, and +implementations for several probability distributions. + +**/ diff --git a/src/lib/math/prob_distr.c b/src/lib/math/prob_distr.c index d44dc28265..f9d65073ff 100644 --- a/src/lib/math/prob_distr.c +++ b/src/lib/math/prob_distr.c @@ -178,8 +178,8 @@ clz32(uint32_t x) /** * Compute the logistic function: f(x) = 1/(1 + e^{-x}) = e^x/(1 + e^x). - * Maps a log-odds-space probability in [-\infty, +\infty] into a direct-space - * probability in [0,1]. Inverse of logit. + * Maps a log-odds-space probability in [-infinity, +infinity] into a + * direct-space probability in [0,1]. Inverse of logit. * * Ill-conditioned for large x; the identity logistic(-x) = 1 - * logistic(x) and the function logistichalf(x) = logistic(x) - 1/2 may @@ -266,7 +266,7 @@ logistic(double x) /** * Compute the logit function: log p/(1 - p). Defined on [0,1]. Maps * a direct-space probability in [0,1] to a log-odds-space probability - * in [-\infty, +\infty]. Inverse of logistic. + * in [-infinity, +infinity]. Inverse of logistic. * * Ill-conditioned near 1/2 and 1; the identity logit(1 - p) = * -logit(p) and the function logithalf(p0) = logit(1/2 + p0) may help @@ -488,7 +488,7 @@ random_uniform_01(void) /* Functions for specific probability distributions start here: */ /* - * Logistic(mu, sigma) distribution, supported on (-\infty,+\infty) + * Logistic(mu, sigma) distribution, supported on (-infinity,+infinity) * * This is the uniform distribution on [0,1] mapped into log-odds * space, scaled by sigma and translated by mu. @@ -546,7 +546,7 @@ isf_logistic(double p, double mu, double sigma) } /* - * LogLogistic(alpha, beta) distribution, supported on (0, +\infty). + * LogLogistic(alpha, beta) distribution, supported on (0, +infinity). * * This is the uniform distribution on [0,1] mapped into odds space, * scaled by positive alpha and shaped by positive beta. @@ -687,7 +687,7 @@ isf_log_logistic(double p, double alpha, double beta) } /* - * Weibull(lambda, k) distribution, supported on (0, +\infty). + * Weibull(lambda, k) distribution, supported on (0, +infinity). * * pdf(x) = (k/lambda) (x/lambda)^{k - 1} e^{-(x/lambda)^k} * cdf(x) = 1 - e^{-(x/lambda)^k} @@ -753,7 +753,7 @@ isf_weibull(double p, double lambda, double k) } /* - * GeneralizedPareto(mu, sigma, xi), supported on (mu, +\infty) for + * GeneralizedPareto(mu, sigma, xi), supported on (mu, +infinity) for * nonnegative xi, or (mu, mu - sigma/xi) for negative xi. * * Samples: @@ -793,19 +793,19 @@ cdf_genpareto(double x, double mu, double sigma, double xi) /* * log(1 + xi x_0)/xi - * = (-1/xi) \sum_{n=1}^\infty (-xi x_0)^n/n - * = (-1/xi) (-xi x_0 + \sum_{n=2}^\infty (-xi x_0)^n/n) - * = x_0 - (1/xi) \sum_{n=2}^\infty (-xi x_0)^n/n - * = x_0 - x_0 \sum_{n=2}^\infty (-xi x_0)^{n-1}/n + * = (-1/xi) \sum_{n=1}^infinity (-xi x_0)^n/n + * = (-1/xi) (-xi x_0 + \sum_{n=2}^infinity (-xi x_0)^n/n) + * = x_0 - (1/xi) \sum_{n=2}^infinity (-xi x_0)^n/n + * = x_0 - x_0 \sum_{n=2}^infinity (-xi x_0)^{n-1}/n * = x_0 (1 - d), * - * where d = \sum_{n=2}^\infty (-xi x_0)^{n-1}/n. If |xi| < + * where d = \sum_{n=2}^infinity (-xi x_0)^{n-1}/n. If |xi| < * eps/4|x_0|, then * - * |d| <= \sum_{n=2}^\infty (eps/4)^{n-1}/n - * <= \sum_{n=2}^\infty (eps/4)^{n-1} - * = \sum_{n=1}^\infty (eps/4)^n - * = (eps/4) \sum_{n=0}^\infty (eps/4)^n + * |d| <= \sum_{n=2}^infinity (eps/4)^{n-1}/n + * <= \sum_{n=2}^infinity (eps/4)^{n-1} + * = \sum_{n=1}^infinity (eps/4)^n + * = (eps/4) \sum_{n=0}^infinity (eps/4)^n * = (eps/4)/(1 - eps/4) * < eps/2 * @@ -855,20 +855,20 @@ icdf_genpareto(double p, double mu, double sigma, double xi) * for xi near zero (note f(xi) --> -log U as xi --> 0), write * the absolutely convergent Taylor expansion * - * f(xi) = (1/xi)*(-xi log U + \sum_{n=2}^\infty (-xi log U)^n/n! - * = -log U + (1/xi)*\sum_{n=2}^\infty (-xi log U)^n/n! - * = -log U + \sum_{n=2}^\infty xi^{n-1} (-log U)^n/n! - * = -log U - log U \sum_{n=2}^\infty (-xi log U)^{n-1}/n! - * = -log U (1 + \sum_{n=2}^\infty (-xi log U)^{n-1}/n!). + * f(xi) = (1/xi)*(-xi log U + \sum_{n=2}^infinity (-xi log U)^n/n! + * = -log U + (1/xi)*\sum_{n=2}^infinity (-xi log U)^n/n! + * = -log U + \sum_{n=2}^infinity xi^{n-1} (-log U)^n/n! + * = -log U - log U \sum_{n=2}^infinity (-xi log U)^{n-1}/n! + * = -log U (1 + \sum_{n=2}^infinity (-xi log U)^{n-1}/n!). * - * Let d = \sum_{n=2}^\infty (-xi log U)^{n-1}/n!. What do we + * Let d = \sum_{n=2}^infinity (-xi log U)^{n-1}/n!. What do we * lose if we discard it and use -log U as an approximation to * f(xi)? If |xi| < eps/-4log U, then * - * |d| <= \sum_{n=2}^\infty |xi log U|^{n-1}/n! - * <= \sum_{n=2}^\infty (eps/4)^{n-1}/n! - * <= \sum_{n=1}^\infty (eps/4)^n - * = (eps/4) \sum_{n=0}^\infty (eps/4)^n + * |d| <= \sum_{n=2}^infinity |xi log U|^{n-1}/n! + * <= \sum_{n=2}^infinity (eps/4)^{n-1}/n! + * <= \sum_{n=1}^infinity (eps/4)^n + * = (eps/4) \sum_{n=0}^infinity (eps/4)^n * = (eps/4)/(1 - eps/4) * < eps/2, * @@ -1098,10 +1098,10 @@ sample_logistic(uint32_t s, double t, double p0) * We carve up the interval (0, 1) into subregions to compute * the inverse CDF precisely: * - * A = (0, 1/(1 + e)] ---> (-\infty, -1] + * A = (0, 1/(1 + e)] ---> (-infinity, -1] * B = [1/(1 + e), 1/2] ---> [-1, 0] * C = [1/2, 1 - 1/(1 + e)] ---> [0, 1] - * D = [1 - 1/(1 + e), 1) ---> [1, +\infty) + * D = [1 - 1/(1 + e), 1) ---> [1, +infinity) * * Cases D and C are mirror images of cases A and B, * respectively, so we choose between them by the sign chosen @@ -1234,19 +1234,19 @@ sample_genpareto(uint32_t s, double p0, double xi) * Write f(xi) = (e^{xi x} - 1)/xi for xi near zero as the * absolutely convergent Taylor series * - * f(x) = (1/xi) (xi x + \sum_{n=2}^\infty (xi x)^n/n!) - * = x + (1/xi) \sum_{n=2}^\inty (xi x)^n/n! - * = x + \sum_{n=2}^\infty xi^{n-1} x^n/n! - * = x + x \sum_{n=2}^\infty (xi x)^{n-1}/n! - * = x (1 + \sum_{n=2}^\infty (xi x)^{n-1}/n!). + * f(x) = (1/xi) (xi x + \sum_{n=2}^infinity (xi x)^n/n!) + * = x + (1/xi) \sum_{n=2}^infinity (xi x)^n/n! + * = x + \sum_{n=2}^infinity xi^{n-1} x^n/n! + * = x + x \sum_{n=2}^infinity (xi x)^{n-1}/n! + * = x (1 + \sum_{n=2}^infinity (xi x)^{n-1}/n!). * - * d = \sum_{n=2}^\infty (xi x)^{n-1}/n! is the relative error + * d = \sum_{n=2}^infinity (xi x)^{n-1}/n! is the relative error * of f(x) from x. If |xi| < eps/4x, then * - * |d| <= \sum_{n=2}^\infty |xi x|^{n-1}/n! - * <= \sum_{n=2}^\infty (eps/4)^{n-1}/n! - * <= \sum_{n=1}^\infty (eps/4) - * = (eps/4) \sum_{n=0}^\infty (eps/4)^n + * |d| <= \sum_{n=2}^infinity |xi x|^{n-1}/n! + * <= \sum_{n=2}^infinity (eps/4)^{n-1}/n! + * <= \sum_{n=1}^infinity (eps/4) + * = (eps/4) \sum_{n=0}^infinity (eps/4)^n * = (eps/4)/(1 - eps/4) * < eps/2, * diff --git a/src/lib/math/prob_distr.h b/src/lib/math/prob_distr.h index 7254dc8623..a93d888950 100644 --- a/src/lib/math/prob_distr.h +++ b/src/lib/math/prob_distr.h @@ -66,41 +66,41 @@ struct dist { * type-specific macro built out of it -- but if you did use this * directly, it would be something like: * -* struct weibull mydist = { -* DIST_BASE_TYPED(&weibull_ops, mydist, struct weibull), -* .lambda = ..., -* .k = ..., -* }; +* struct weibull mydist = { +* DIST_BASE_TYPED(&weibull_ops, mydist, struct weibull), +* .lambda = ..., +* .k = ..., +* }; * * If you want to define a distribution type, define a canonical set of * operations and define a type-specific initializer element like so: * -* struct foo { -* struct dist base; -* int omega; -* double tau; -* double phi; -* }; +* struct foo { +* struct dist base; +* int omega; +* double tau; +* double phi; +* }; * -* struct dist_ops foo_ops = ...; +* struct dist_ops foo_ops = ...; * -* #define FOO(OBJ) DIST_BASE_TYPED(&foo_ops, OBJ, struct foo) +* #define FOO(OBJ) DIST_BASE_TYPED(&foo_ops, OBJ, struct foo) * * Then users can do: * -* struct foo mydist = { -* FOO(mydist), -* .omega = ..., -* .tau = ..., -* .phi = ..., -* }; +* struct foo mydist = { +* FOO(mydist), +* .omega = ..., +* .tau = ..., +* .phi = ..., +* }; * * If you accidentally write * -* struct bar mydist = { -* FOO(mydist), -* ... -* }; +* struct bar mydist = { +* FOO(mydist), +* ... +* }; * * then the compiler will report a type mismatch in the sizeof * expression, which otherwise evaporates at runtime. diff --git a/src/lib/memarea/lib_memarea.dox b/src/lib/memarea/lib_memarea.dox new file mode 100644 index 0000000000..041191482d --- /dev/null +++ b/src/lib/memarea/lib_memarea.dox @@ -0,0 +1,30 @@ +/** +@dir /lib/memarea +@brief lib/memarea: A fast arena-style allocator. + +This module has a fast "arena" style allocator, where memory is freed all at +once. This kind of allocation is very fast and avoids fragmentation, at the +expense of requiring all the data to be freed at the same time. We use this +for parsing and diff calculations. + +It's often handy to allocate a large number of tiny objects, all of which +need to disappear at the same time. You can do this in tor using the +memarea.c abstraction, which uses a set of grow-only buffers for allocation, +and only supports a single "free" operation at the end. + +Using memareas also helps you avoid memory fragmentation. You see, some libc +malloc implementations perform badly on the case where a large number of +small temporary objects are allocated at the same time as a few long-lived +objects of similar size. But if you use tor_malloc() for the long-lived ones +and a memarea for the temporary object, the malloc implementation is likelier +to do better. + +To create a new memarea, use `memarea_new()`. To drop all the storage from a +memarea, and invalidate its pointers, use `memarea_drop_all()`. + +The allocation functions `memarea_alloc()`, `memarea_alloc_zero()`, +`memarea_memdup()`, `memarea_strdup()`, and `memarea_strndup()` are analogous +to the similarly-named malloc() functions. There is intentionally no +`memarea_free()` or `memarea_realloc()`. + +**/ diff --git a/src/lib/meminfo/lib_meminfo.dox b/src/lib/meminfo/lib_meminfo.dox new file mode 100644 index 0000000000..b57e60525e --- /dev/null +++ b/src/lib/meminfo/lib_meminfo.dox @@ -0,0 +1,7 @@ +/** +@dir /lib/meminfo +@brief lib/meminfo: Inspecting malloc() usage. + +Only available when malloc() provides mallinfo() or something similar. + +**/ diff --git a/src/lib/net/address.c b/src/lib/net/address.c index 0a2c84caf2..106e560a48 100644 --- a/src/lib/net/address.c +++ b/src/lib/net/address.c @@ -1392,7 +1392,7 @@ get_interface_addresses_win32(int severity, sa_family_t family) /* This is defined on Mac OS X */ #ifndef _SIZEOF_ADDR_IFREQ -#define _SIZEOF_ADDR_IFREQ sizeof +#define _SIZEOF_ADDR_IFREQ(x) sizeof(x) #endif /* Free ifc->ifc_buf safely. */ @@ -2001,7 +2001,7 @@ tor_addr_port_new(const tor_addr_t *addr, uint16_t port) return ap; } -/** Return true iff <a>a</b> and <b>b</b> are the same address and port */ +/** Return true iff <b>a</b> and <b>b</b> are the same address and port */ int tor_addr_port_eq(const tor_addr_port_t *a, const tor_addr_port_t *b) diff --git a/src/lib/net/lib_net.dox b/src/lib/net/lib_net.dox new file mode 100644 index 0000000000..b4c00405d7 --- /dev/null +++ b/src/lib/net/lib_net.dox @@ -0,0 +1,8 @@ +/** +@dir /lib/net +@brief lib/net: Low-level network-related code. + +This module includes address manipulation, compatibility wrappers, +convenience functions, and so on. + +**/ diff --git a/src/lib/net/network_sys.h b/src/lib/net/network_sys.h index 43e62592ca..34ac3d120c 100644 --- a/src/lib/net/network_sys.h +++ b/src/lib/net/network_sys.h @@ -2,7 +2,7 @@ /* See LICENSE for licensing information */ /** - * \file log_network.h + * \file network_sys.h * \brief Declare subsystem object for the network module. **/ diff --git a/src/lib/net/socketpair.c b/src/lib/net/socketpair.c index f3a0c3770a..aa88c58266 100644 --- a/src/lib/net/socketpair.c +++ b/src/lib/net/socketpair.c @@ -2,6 +2,11 @@ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. * Copyright (c) 2007-2019, The Tor Project, Inc. */ +/** + * @file socketpair.c + * @brief Replacement socketpair() for systems that lack it + **/ + #include "lib/cc/torint.h" #include "lib/net/socketpair.h" #include "lib/net/inaddr_st.h" diff --git a/src/lib/net/socketpair.h b/src/lib/net/socketpair.h index 5820606973..c2e99d505e 100644 --- a/src/lib/net/socketpair.h +++ b/src/lib/net/socketpair.h @@ -6,6 +6,11 @@ #ifndef TOR_SOCKETPAIR_H #define TOR_SOCKETPAIR_H +/** + * @file socketpair.h + * @brief Header for socketpair.c + **/ + #include "orconfig.h" #include "lib/testsupport/testsupport.h" #include "lib/net/nettypes.h" diff --git a/src/lib/osinfo/lib_osinfo.dox b/src/lib/osinfo/lib_osinfo.dox new file mode 100644 index 0000000000..4d9b1a6d76 --- /dev/null +++ b/src/lib/osinfo/lib_osinfo.dox @@ -0,0 +1,10 @@ +/** +@dir /lib/osinfo +@brief lib/osinfo: For inspecting the OS version and capabilities. + +In general, we use this module when we're telling the user what operating +system they are running. We shouldn't make decisions based on the output of +these checks: instead, we should have more specific checks, either at compile +time or run time, based on the observed system behavior. + +**/ diff --git a/src/lib/process/lib_process.dox b/src/lib/process/lib_process.dox new file mode 100644 index 0000000000..723c9f193d --- /dev/null +++ b/src/lib/process/lib_process.dox @@ -0,0 +1,4 @@ +/** +@dir /lib/process +@brief lib/process: Launch and manage subprocesses. +**/ diff --git a/src/lib/process/process.c b/src/lib/process/process.c index 2194a603ff..b01c99992c 100644 --- a/src/lib/process/process.c +++ b/src/lib/process/process.c @@ -550,6 +550,7 @@ process_vprintf(process_t *process, char *data; size = tor_vasprintf(&data, format, args); + tor_assert(data != NULL); process_write(process, (uint8_t *)data, size); tor_free(data); } diff --git a/src/lib/process/process.h b/src/lib/process/process.h index 05c091a5bf..b28f55e0a1 100644 --- a/src/lib/process/process.h +++ b/src/lib/process/process.h @@ -35,8 +35,8 @@ typedef enum { const char *process_status_to_string(process_status_t status); typedef enum { - /** Pass complete \n-terminated lines to the - * callback (with the \n or \r\n removed). */ + /** Pass complete newline-terminated lines to the + * callback (with the LF or CRLF removed). */ PROCESS_PROTOCOL_LINE, /** Pass the raw response from read() to the callback. */ diff --git a/src/lib/pubsub/lib_pubsub.dox b/src/lib/pubsub/lib_pubsub.dox new file mode 100644 index 0000000000..c033660121 --- /dev/null +++ b/src/lib/pubsub/lib_pubsub.dox @@ -0,0 +1,16 @@ +/** +@dir /lib/pubsub +@brief lib/pubsub: Publish-subscribe message passing. + +This module wraps the \refdir{lib/dispatch} module, to provide a more +ergonomic and type-safe approach to message passing. + +In general, we favor this mechanism for cases where higher-level modules +need to be notified when something happens in lower-level modules. (The +alternative would be calling up from the lower-level modules, which +would be error-prone; or maintaining lists of function-pointers, which +would be clumsy and tend to complicate the call graph.) + +See pubsub.c for more information. + +**/ diff --git a/src/lib/pubsub/pubsub_publish.h b/src/lib/pubsub/pubsub_publish.h index 0686a465de..6369725405 100644 --- a/src/lib/pubsub/pubsub_publish.h +++ b/src/lib/pubsub/pubsub_publish.h @@ -4,6 +4,11 @@ * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file pubsub_publish.h + * @brief Header for pubsub_publish.c + **/ + #ifndef TOR_PUBSUB_PUBLISH_H #define TOR_PUBSUB_PUBLISH_H diff --git a/src/lib/sandbox/lib_sandbox.dox b/src/lib/sandbox/lib_sandbox.dox new file mode 100644 index 0000000000..48eddac685 --- /dev/null +++ b/src/lib/sandbox/lib_sandbox.dox @@ -0,0 +1,17 @@ +/** +@dir /lib/sandbox +@brief lib/sandbox: Linux seccomp2-based sandbox. + +This module uses Linux's seccomp2 facility via the +[`libseccomp` library](https://github.com/seccomp/libseccomp), to restrict +the set of system calls that Tor is allowed to invoke while it is running. + +Because there are many libc versions that invoke different system calls, and +because handling strings is quite complex, this module is more complex and +less portable than it needs to be. + +A better architecture would put the responsibility for invoking tricky system +calls (like open()) in another, less restricted process, and give that +process responsibility for enforcing our sandbox rules. + +**/ diff --git a/src/lib/smartlist_core/lib_smartlist_core.dox b/src/lib/smartlist_core/lib_smartlist_core.dox new file mode 100644 index 0000000000..73c3b69056 --- /dev/null +++ b/src/lib/smartlist_core/lib_smartlist_core.dox @@ -0,0 +1,12 @@ +/** +@dir /lib/smartlist_core +@brief lib/smartlist_core: Minimal dynamic array implementation + +A `smartlist_t` is a dynamic array type for holding `void *`. We use it +throughout the rest of the codebase. + +There are higher-level pieces in \refdir{lib/container} but +the ones in lib/smartlist_core are used by the logging code, and therefore +cannot use the logging code. + +**/ diff --git a/src/lib/string/lib_string.dox b/src/lib/string/lib_string.dox new file mode 100644 index 0000000000..c8793ddf91 --- /dev/null +++ b/src/lib/string/lib_string.dox @@ -0,0 +1,15 @@ +/** +@dir /lib/string +@brief lib/string: Low-level string manipulation. + +We have a number of compatibility functions here: some are for handling +functionality that is not implemented (or not implemented the same) on every +platform; some are for providing locale-independent versions of libc +functions that would otherwise be defined differently for different users. + +Other functions here are for common string-manipulation operations that we do +in the rest of the codebase. + +Any string function high-level enough to need logging belongs in a +higher-level module. +**/ diff --git a/src/lib/string/parse_int.c b/src/lib/string/parse_int.c index fbdd554a47..fd4422ecd0 100644 --- a/src/lib/string/parse_int.c +++ b/src/lib/string/parse_int.c @@ -9,6 +9,7 @@ **/ #include "lib/string/parse_int.h" +#include "lib/cc/compat_compiler.h" #include <errno.h> #include <stdlib.h> @@ -17,6 +18,7 @@ /* Helper: common code to check whether the result of a strtol or strtoul or * strtoll is correct. */ #define CHECK_STRTOX_RESULT() \ + STMT_BEGIN \ /* Did an overflow occur? */ \ if (errno == ERANGE) \ goto err; \ @@ -38,7 +40,8 @@ err: \ if (ok) *ok = 0; \ if (next) *next = endptr; \ - return 0 + return 0; \ + STMT_END /** Extract a long from the start of <b>s</b>, in the given numeric * <b>base</b>. If <b>base</b> is 0, <b>s</b> is parsed as a decimal, diff --git a/src/lib/subsys/lib_subsys.dox b/src/lib/subsys/lib_subsys.dox new file mode 100644 index 0000000000..1a22a2d808 --- /dev/null +++ b/src/lib/subsys/lib_subsys.dox @@ -0,0 +1,34 @@ +/** +@dir /lib/subsys +@brief lib/subsys: Types for declaring a "subsystem". + +## Subsystems in Tor + +A subsystem is a module with support for initialization, shutdown, +configuration, and so on. + +Many parts of Tor can be initialized, cleaned up, and configured somewhat +independently through a table-driven mechanism. Each such part is called a +"subsystem". + +To declare a subsystem, make a global `const` instance of the `subsys_fns_t` +type, filling in the function pointer fields that you require with ones +corresponding to your subsystem. Any function pointers left as "NULL" will +be a no-op. Each system must have a name and a "level", which corresponds to +the order in which it is initialized. (See `app/main/subsystem_list.c` for a +list of current subsystems and their levels.) + +Then, insert your subsystem in the list in `app/main/subsystem_list.c`. It +will need to occupy a position corresponding to its level. + +At this point, your subsystem will be handled like the others: it will get +initialized at startup, torn down at exit, and so on. + +Historical note: Not all of Tor's code is currently handled as +subsystems. As you work with older code, you may see some parts of the code +that are initialized from `tor_init()` or `run_tor_main_loop()` or +`tor_run_main()`; and torn down from `tor_cleanup()`. We aim to migrate +these to subsystems over time; please don't add any new code that follows +this pattern. + +**/ diff --git a/src/lib/subsys/subsys.h b/src/lib/subsys/subsys.h index 21f984f32d..35a30680ee 100644 --- a/src/lib/subsys/subsys.h +++ b/src/lib/subsys/subsys.h @@ -3,6 +3,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file subsys.h + * @brief Types used to declare a subsystem. + **/ + #ifndef TOR_SUBSYS_T #define TOR_SUBSYS_T diff --git a/src/lib/term/lib_term.dox b/src/lib/term/lib_term.dox new file mode 100644 index 0000000000..3bf2f960ab --- /dev/null +++ b/src/lib/term/lib_term.dox @@ -0,0 +1,4 @@ +/** +@dir /lib/term +@brief lib/term: Terminal operations (password input). +**/ diff --git a/src/lib/testsupport/lib_testsupport.dox b/src/lib/testsupport/lib_testsupport.dox new file mode 100644 index 0000000000..c09c32e478 --- /dev/null +++ b/src/lib/testsupport/lib_testsupport.dox @@ -0,0 +1,4 @@ +/** +@dir /lib/testsupport +@brief lib/testsupport: Helpers for test-only code and for function mocking. +**/ diff --git a/src/lib/thread/lib_thread.dox b/src/lib/thread/lib_thread.dox new file mode 100644 index 0000000000..2773aa009d --- /dev/null +++ b/src/lib/thread/lib_thread.dox @@ -0,0 +1,9 @@ +/** +@dir /lib/thread +@brief lib/thread: Mid-level threading. + +This module contains compatibility and convenience code for multithreading, +except for low-level locks (which are in \refdir{lib/lock} and +workqueue/threadpool code (which belongs in \refdir{lib/evloop}.) + +**/ diff --git a/src/lib/thread/thread_sys.h b/src/lib/thread/thread_sys.h index c0daf2b5e9..ef27134a32 100644 --- a/src/lib/thread/thread_sys.h +++ b/src/lib/thread/thread_sys.h @@ -2,7 +2,7 @@ /* See LICENSE for licensing information */ /** - * \file threads_sys.h + * \file thread_sys.h * \brief Declare subsystem object for threads library **/ diff --git a/src/lib/thread/threads.h b/src/lib/thread/threads.h index 4b42b9abd9..ad9ad98c70 100644 --- a/src/lib/thread/threads.h +++ b/src/lib/thread/threads.h @@ -106,7 +106,9 @@ void tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value); typedef struct atomic_counter_t { atomic_size_t val; } atomic_counter_t; +#ifndef COCCI #define ATOMIC_LINKAGE static +#endif #else /* !defined(HAVE_WORKING_STDATOMIC) */ typedef struct atomic_counter_t { tor_mutex_t mutex; diff --git a/src/lib/time/lib_time.dox b/src/lib/time/lib_time.dox new file mode 100644 index 0000000000..b76a31fb97 --- /dev/null +++ b/src/lib/time/lib_time.dox @@ -0,0 +1,11 @@ +/** +@dir /lib/time +@brief lib/time: Higher-level time functions + +This includes both fine-grained timers and monotonic timers, along with +wrappers for them to try to improve efficiency. + +For "what time is it" in UTC, see \refdir{lib/wallclock}. For parsing and +encoding times and dates, see \refdir{lib/encoding}. + +**/ diff --git a/src/lib/tls/lib_tls.dox b/src/lib/tls/lib_tls.dox new file mode 100644 index 0000000000..f0dba269e8 --- /dev/null +++ b/src/lib/tls/lib_tls.dox @@ -0,0 +1,13 @@ +/** +@dir /lib/tls +@brief lib/tls: TLS library wrappers + +This module has compatibility wrappers around the library (NSS or OpenSSL, +depending on configuration) that Tor uses to implement the TLS link security +protocol. + +It also implements the logic for some legacy TLS protocol usage we used to +support in old versions of Tor, involving conditional delivery of certificate +chains (v1 link protocol) and conditional renegotiation (v2 link protocol). + +**/ diff --git a/src/lib/tls/tortls.c b/src/lib/tls/tortls.c index 1aff40c437..f3c117efa3 100644 --- a/src/lib/tls/tortls.c +++ b/src/lib/tls/tortls.c @@ -3,6 +3,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file tortls.c + * @brief Shared functionality for our TLS backends. + **/ + #define TORTLS_PRIVATE #define TOR_X509_PRIVATE #include "lib/tls/x509.h" diff --git a/src/lib/tls/tortls_internal.h b/src/lib/tls/tortls_internal.h index 866483a94c..a7aee524f3 100644 --- a/src/lib/tls/tortls_internal.h +++ b/src/lib/tls/tortls_internal.h @@ -3,6 +3,11 @@ * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +/** + * @file tortls_internal.h + * @brief Declare internal functions for lib/tls + **/ + #ifndef TORTLS_INTERNAL_H #define TORTLS_INTERNAL_H diff --git a/src/lib/tls/tortls_openssl.c b/src/lib/tls/tortls_openssl.c index 5bafcf676d..9184cafd60 100644 --- a/src/lib/tls/tortls_openssl.c +++ b/src/lib/tls/tortls_openssl.c @@ -464,7 +464,9 @@ static const char UNRESTRICTED_SERVER_CIPHER_LIST[] = /** List of ciphers that clients should advertise, omitting items that * our OpenSSL doesn't know about. */ static const char CLIENT_CIPHER_LIST[] = +#ifndef COCCI #include "lib/tls/ciphers.inc" +#endif /* Tell it not to use SSLv2 ciphers, so that it can select an SSLv3 version * of any cipher we say. */ "!SSLv2" diff --git a/src/lib/tls/tortls_st.h b/src/lib/tls/tortls_st.h index 73f6e6ecca..37935894f3 100644 --- a/src/lib/tls/tortls_st.h +++ b/src/lib/tls/tortls_st.h @@ -6,6 +6,14 @@ #ifndef TOR_TORTLS_ST_H #define TOR_TORTLS_ST_H +/** + * @file tortls_st.h + * @brief Structure declarations for internal TLS types. + * + * These should generally be treated as opaque outside of the + * lib/tls module. + **/ + #include "lib/net/socket.h" #define TOR_TLS_MAGIC 0x71571571 diff --git a/src/lib/trace/lib_trace.dox b/src/lib/trace/lib_trace.dox new file mode 100644 index 0000000000..64f762bc3e --- /dev/null +++ b/src/lib/trace/lib_trace.dox @@ -0,0 +1,8 @@ +/** +@dir /lib/trace +@brief lib/trace: Function-tracing functionality API. + +This module is used for adding "trace" support (low-granularity function +logging) to Tor. Right now it doesn't have many users. + +**/ diff --git a/src/lib/version/git_revision.c b/src/lib/version/git_revision.c index 900a1e12a0..e87620a20c 100644 --- a/src/lib/version/git_revision.c +++ b/src/lib/version/git_revision.c @@ -6,19 +6,28 @@ #include "orconfig.h" #include "lib/version/git_revision.h" +/** + * @file git_revision.c + * @brief Strings to describe the current Git commit. + **/ + /** String describing which Tor Git repository version the source was * built from. This string is generated by a bit of shell kludging in * src/core/include.am, and is usually right. */ const char tor_git_revision[] = +#ifndef COCCI #ifndef _MSC_VER #include "micro-revision.i" #endif +#endif ""; const char tor_bug_suffix[] = " (on Tor " VERSION +#ifndef COCCI #ifndef _MSC_VER " " #include "micro-revision.i" #endif +#endif /* !defined(COCCI) */ ")"; diff --git a/src/lib/version/git_revision.h b/src/lib/version/git_revision.h index 79e3c6684b..5d08e84b84 100644 --- a/src/lib/version/git_revision.h +++ b/src/lib/version/git_revision.h @@ -6,6 +6,11 @@ #ifndef TOR_GIT_REVISION_H #define TOR_GIT_REVISION_H +/** + * @file git_revision.h + * @brief Header for git_revision.c + **/ + extern const char tor_git_revision[]; extern const char tor_bug_suffix[]; diff --git a/src/lib/version/lib_version.dox b/src/lib/version/lib_version.dox new file mode 100644 index 0000000000..93d2fb6b9b --- /dev/null +++ b/src/lib/version/lib_version.dox @@ -0,0 +1,4 @@ +/** +@dir /lib/version +@brief lib/version: holds the current version of Tor. +**/ diff --git a/src/lib/version/torversion.h b/src/lib/version/torversion.h index 7b0fb66ec0..50d646bd23 100644 --- a/src/lib/version/torversion.h +++ b/src/lib/version/torversion.h @@ -6,6 +6,11 @@ #ifndef TOR_VERSION_H #define TOR_VERSION_H +/** + * @file torversion.h + * @brief Header for version.c. + **/ + const char *get_version(void); const char *get_short_version(void); diff --git a/src/lib/version/version.c b/src/lib/version/version.c index 434e6fb424..b2f25e97b5 100644 --- a/src/lib/version/version.c +++ b/src/lib/version/version.c @@ -10,6 +10,11 @@ #include <stdio.h> #include <string.h> +/** + * @file version.c + * @brief Functions to get the version of Tor. + **/ + /** A shorter version of this Tor process's version, for export in our router * descriptor. (Does not include the git version, if any.) */ static const char the_short_tor_version[] = diff --git a/src/lib/wallclock/lib_wallclock.dox b/src/lib/wallclock/lib_wallclock.dox new file mode 100644 index 0000000000..7d43fa6129 --- /dev/null +++ b/src/lib/wallclock/lib_wallclock.dox @@ -0,0 +1,13 @@ +/** +@dir /lib/wallclock +@brief lib/wallclock: Inspect and manipulate the current time. + +This module handles our concept of "what time is it" or "what time does the +world agree it is?" Generally, if you want something derived from UTC, this +is the module for you. + +For versions of the time that are more local, more monotonic, or more +accurate, see \refdir{lib/time}. For parsing and encoding times and dates, +see \refdir{lib/encoding}. + +**/ diff --git a/src/lib/wallclock/timeval.h b/src/lib/wallclock/timeval.h index e632d04a04..4710a3dfd7 100644 --- a/src/lib/wallclock/timeval.h +++ b/src/lib/wallclock/timeval.h @@ -69,6 +69,7 @@ } while (0) #endif /* !defined(timersub) */ +#ifndef COCCI #ifndef timercmp /** Replacement for timercmp on platforms that do not have it: returns true * iff the relational operator "op" makes the expression tv1 op tv2 true. @@ -82,5 +83,6 @@ ((tv1)->tv_usec op (tv2)->tv_usec) : \ ((tv1)->tv_sec op (tv2)->tv_sec)) #endif /* !defined(timercmp) */ +#endif /* !defined(COCCI) */ #endif /* !defined(TOR_TIMEVAL_H) */ diff --git a/src/mainpage.dox b/src/mainpage.dox new file mode 100644 index 0000000000..02ce8675e7 --- /dev/null +++ b/src/mainpage.dox @@ -0,0 +1,122 @@ +/** +@mainpage Tor source reference + +@section intro Welcome to Tor + +This documentation describes the general structure of the Tor codebase, how +it fits together, what functionality is available for extending Tor, and +gives some notes on how Tor got that way. It also includes a reference for +nearly every function, type, file, and module in the Tor source code. The +high-level documentation is a work in progress. + +Tor itself remains a work in progress too: We've been working on it for +nearly two decades, and we've learned a lot about good coding since we first +started. This means, however, that some of the older pieces of Tor will have +some "code smell" in them that could stand a brisk refactoring. So when we +describe a piece of code, we'll sometimes give a note on how it got that way, +and whether we still think that's a good idea. + +This document is not an overview of the Tor protocol. For that, see the +design paper and the specifications at https://spec.torproject.org/ . + +For more information about Tor's coding standards and some helpful +development tools, see +[doc/HACKING](https://gitweb.torproject.org/tor.git/tree/doc/HACKING) in the +Tor repository. + +@section highlevel The very high level + +Ultimately, Tor runs as an event-driven network daemon: it responds to +network events, signals, and timers by sending and receiving things over +the network. Clients, relays, and directory authorities all use the +same codebase: the Tor process will run as a client, relay, or authority +depending on its configuration. + +Tor has a few major dependencies, including Libevent (used to tell which +sockets are readable and writable), OpenSSL or NSS (used for many encryption +functions, and to implement the TLS protocol), and zlib (used to +compress and uncompress directory information). + +Most of Tor's work today is done in a single event-driven main thread. +Tor also spawns one or more worker threads to handle CPU-intensive +tasks. (Right now, this only includes circuit encryption and the more +expensive compression algorithms.) + +On startup, Tor initializes its libraries, reads and responds to its +configuration files, and launches a main event loop. At first, the only +events that Tor listens for are a few signals (like TERM and HUP), and +one or more listener sockets (for different kinds of incoming +connections). Tor also configures several timers to handle periodic +events. As Tor runs over time, other events will open, and new events +will be scheduled. + +The codebase is divided into a few top-level subdirectories, each of +which contains several sub-modules. + + - `ext` -- Code maintained elsewhere that we include in the Tor + source distribution. + + - \refdir{lib} -- Lower-level utility code, not necessarily + tor-specific. + + - `trunnel` -- Automatically generated code (from the Trunnel + tool): used to parse and encode binary formats. + + - \refdir{core} -- Networking code that is implements the central + parts of the Tor protocol and main loop. + + - \refdir{feature} -- Aspects of Tor (like directory management, + running a relay, running a directory authorities, managing a list of + nodes, running and using onion services) that are built on top of the + mainloop code. + + - \refdir{app} -- Highest-level functionality; responsible for setting + up and configuring the Tor daemon, making sure all the lower-level + modules start up when required, and so on. + + - \refdir{tools} -- Binaries other than Tor that we produce. + Currently this is tor-resolve, tor-gencert, and the tor_runner.o helper + module. + + - `test` -- unit tests, regression tests, and a few integration + tests. + +In theory, the above parts of the codebase are sorted from highest-level to +lowest-level, where high-level code is only allowed to invoke lower-level +code, and lower-level code never includes or depends on code of a higher +level. In practice, this refactoring is incomplete: The modules in +\refdir{lib} are well-factored, but there are many layer violations ("upward +dependencies") in \refdir{core} and \refdir{feature}. +We aim to eliminate those over time. + +@section keyabstractions Some key high-level abstractions + +The most important abstractions at Tor's high-level are Connections, +Channels, Circuits, and Nodes. + +A 'Connection' (connection_t) represents a stream-based information flow. +Most connections are TCP connections to remote Tor servers and clients. (But +as a shortcut, a relay will sometimes make a connection to itself without +actually using a TCP connection. More details later on.) Connections exist +in different varieties, depending on what functionality they provide. The +principle types of connection are edge_connection_t (eg a socks connection or +a connection from an exit relay to a destination), or_connection_t (a TLS +stream connecting to a relay), dir_connection_t (an HTTP connection to learn +about the network), and control_connection_t (a connection from a +controller). + +A 'Circuit' (circuit_t) is persistent tunnel through the Tor network, +established with public-key cryptography, and used to send cells one or more +hops. Clients keep track of multi-hop circuits (origin_circuit_t), and the +cryptography associated with each hop. Relays, on the other hand, keep track +only of their hop of each circuit (or_circuit_t). + +A 'Channel' (channel_t) is an abstract view of sending cells to and from a +Tor relay. Currently, all channels are implemented using OR connections +(channel_tls_t). If we switch to other strategies in the future, we'll have +more connection types. + +A 'Node' (node_t) is a view of a Tor instance's current knowledge and opinions +about a Tor relay or bridge. + +**/ 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 b/src/test/conf_examples/bridgeauth_1/expected new file mode 100644 index 0000000000..d43aaf2c8b --- /dev/null +++ b/src/test/conf_examples/bridgeauth_1/expected @@ -0,0 +1,7 @@ +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/torrc b/src/test/conf_examples/bridgeauth_1/torrc new file mode 100644 index 0000000000..740bc6c2eb --- /dev/null +++ b/src/test/conf_examples/bridgeauth_1/torrc @@ -0,0 +1,8 @@ +AuthoritativeDirectory 1 +BridgeAuthoritativeDir 1 + +ContactInfo tor_parse_test@example.com + +Address 198.51.100.123 +ORPort 443 +DirPort 80 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 b/src/test/conf_examples/dirauth_1/expected new file mode 100644 index 0000000000..901f7d947f --- /dev/null +++ b/src/test/conf_examples/dirauth_1/expected @@ -0,0 +1,8 @@ +Address 192.0.2.1 +AuthoritativeDirectory 1 +ContactInfo tor_parse_test@example.net +DirPort 9030 +DownloadExtraInfo 1 +Nickname Unnamed +ORPort 9001 +V3AuthoritativeDirectory 1 diff --git a/src/test/conf_examples/dirauth_1/torrc b/src/test/conf_examples/dirauth_1/torrc new file mode 100644 index 0000000000..b870e6e8e0 --- /dev/null +++ b/src/test/conf_examples/dirauth_1/torrc @@ -0,0 +1,8 @@ +AuthoritativeDirectory 1 +V3AuthoritativeDirectory 1 + +ContactInfo tor_parse_test@example.net + +Address 192.0.2.1 +ORPort 9001 +DirPort 9030 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/lzma_zstd_1/error b/src/test/conf_examples/lzma_zstd_1/error new file mode 100644 index 0000000000..a5531ca21e --- /dev/null +++ b/src/test/conf_examples/lzma_zstd_1/error @@ -0,0 +1 @@ +Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma N/A, and Libzstd N/A diff --git a/src/test/conf_examples/lzma_zstd_1/error_lzma b/src/test/conf_examples/lzma_zstd_1/error_lzma new file mode 100644 index 0000000000..2947e5991b --- /dev/null +++ b/src/test/conf_examples/lzma_zstd_1/error_lzma @@ -0,0 +1 @@ +Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma .*, and Libzstd N/A diff --git a/src/test/conf_examples/lzma_zstd_1/error_lzma_zstd b/src/test/conf_examples/lzma_zstd_1/error_lzma_zstd new file mode 100644 index 0000000000..e76e4357f8 --- /dev/null +++ b/src/test/conf_examples/lzma_zstd_1/error_lzma_zstd @@ -0,0 +1 @@ +Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma .*, and Libzstd .*
\ No newline at end of file diff --git a/src/test/conf_examples/lzma_zstd_1/error_zstd b/src/test/conf_examples/lzma_zstd_1/error_zstd new file mode 100644 index 0000000000..c8b174423b --- /dev/null +++ b/src/test/conf_examples/lzma_zstd_1/error_zstd @@ -0,0 +1 @@ +Tor 0.* running on .* with Libevent .*, .*, Zlib .*, Liblzma N/A, and Libzstd .*
\ No newline at end of file diff --git a/src/test/conf_examples/lzma_zstd_1/torrc b/src/test/conf_examples/lzma_zstd_1/torrc new file mode 100644 index 0000000000..91a4656b77 --- /dev/null +++ b/src/test/conf_examples/lzma_zstd_1/torrc @@ -0,0 +1,4 @@ +# Deliberately bad options, to cause an error message +# But this test actually checks for the optional library list in tor's logs, +# not the error message +bad bad bad
\ No newline at end of file diff --git a/src/test/conf_examples/missing_cl_arg/cmdline b/src/test/conf_examples/missing_cl_arg/cmdline new file mode 100644 index 0000000000..7fc4d0a54d --- /dev/null +++ b/src/test/conf_examples/missing_cl_arg/cmdline @@ -0,0 +1 @@ +--hash-password diff --git a/src/test/conf_examples/missing_cl_arg/error b/src/test/conf_examples/missing_cl_arg/error new file mode 100644 index 0000000000..61dbeac8aa --- /dev/null +++ b/src/test/conf_examples/missing_cl_arg/error @@ -0,0 +1 @@ +Command-line option '--hash-password' with no value. diff --git a/src/test/conf_examples/missing_cl_arg/torrc b/src/test/conf_examples/missing_cl_arg/torrc new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/src/test/conf_examples/missing_cl_arg/torrc diff --git a/src/test/conf_examples/nss_1/error b/src/test/conf_examples/nss_1/error new file mode 100644 index 0000000000..32e8cfc2f8 --- /dev/null +++ b/src/test/conf_examples/nss_1/error @@ -0,0 +1 @@ +Tor 0.* running on .* with Libevent .*, OpenSSL .*, Zlib .*, Liblzma .*, and Libzstd .* diff --git a/src/test/conf_examples/nss_1/error_nss b/src/test/conf_examples/nss_1/error_nss new file mode 100644 index 0000000000..c0fe7b003c --- /dev/null +++ b/src/test/conf_examples/nss_1/error_nss @@ -0,0 +1 @@ +Tor 0.* running on .* with Libevent .*, NSS .*, Zlib .*, Liblzma .*, and Libzstd .* diff --git a/src/test/conf_examples/nss_1/torrc b/src/test/conf_examples/nss_1/torrc new file mode 100644 index 0000000000..91a4656b77 --- /dev/null +++ b/src/test/conf_examples/nss_1/torrc @@ -0,0 +1,4 @@ +# Deliberately bad options, to cause an error message +# But this test actually checks for the optional library list in tor's logs, +# not the error message +bad bad bad
\ No newline at end of file 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_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_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_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/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 --- /dev/null +++ b/src/test/conf_examples/pt_01/expected 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 --- /dev/null +++ b/src/test/conf_examples/pt_02/expected 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 --- /dev/null +++ b/src/test/conf_examples/pt_09/expected 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 --- /dev/null +++ b/src/test/conf_examples/relay_01/expected 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 --- /dev/null +++ b/src/test/conf_examples/relay_02/expected 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/fakecircs.c b/src/test/fakecircs.c new file mode 100644 index 0000000000..82a8722ba8 --- /dev/null +++ b/src/test/fakecircs.c @@ -0,0 +1,92 @@ +/* Copyright (c) 2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file fakecircs.c + * \brief Fake circuits API for unit test. + **/ + +#define CHANNEL_PRIVATE +#define CIRCUITBUILD_PRIVATE +#define CIRCUITLIST_PRIVATE +#define CRYPT_PATH_PRIVATE + +#include "core/or/or.h" + +#include "core/crypto/relay_crypto.h" +#include "core/or/channel.h" +#include "core/or/circuitbuild.h" +#include "core/or/circuitlist.h" +#include "core/or/circuitpadding.h" +#include "core/or/crypt_path.h" +#include "core/or/relay.h" +#include "core/or/relay_crypto_st.h" + +#include "fakecircs.h" + +/** Return newly allocated OR circuit using the given nchan and pchan. It must + * be freed with the free_fake_orcirc(). */ +or_circuit_t * +new_fake_orcirc(channel_t *nchan, channel_t *pchan) +{ + or_circuit_t *orcirc = NULL; + circuit_t *circ = NULL; + crypt_path_t tmp_cpath; + char whatevs_key[CPATH_KEY_MATERIAL_LEN]; + + orcirc = tor_malloc_zero(sizeof(*orcirc)); + circ = &(orcirc->base_); + circ->magic = OR_CIRCUIT_MAGIC; + + circuit_set_n_circid_chan(circ, get_unique_circ_id_by_chan(nchan), nchan); + cell_queue_init(&(circ->n_chan_cells)); + + circ->n_hop = NULL; + circ->streams_blocked_on_n_chan = 0; + circ->streams_blocked_on_p_chan = 0; + circ->n_delete_pending = 0; + circ->p_delete_pending = 0; + circ->received_destroy = 0; + circ->state = CIRCUIT_STATE_OPEN; + circ->purpose = CIRCUIT_PURPOSE_OR; + circ->package_window = CIRCWINDOW_START_MAX; + circ->deliver_window = CIRCWINDOW_START_MAX; + circ->n_chan_create_cell = NULL; + + circuit_set_p_circid_chan(orcirc, get_unique_circ_id_by_chan(pchan), pchan); + cell_queue_init(&(orcirc->p_chan_cells)); + + memset(&tmp_cpath, 0, sizeof(tmp_cpath)); + if (cpath_init_circuit_crypto(&tmp_cpath, whatevs_key, + sizeof(whatevs_key), 0, 0)<0) { + log_warn(LD_BUG,"Circuit initialization failed"); + return NULL; + } + orcirc->crypto = tmp_cpath.pvt_crypto; + + return orcirc; +} + +/** Free fake OR circuit which MUST be created by new_fake_orcirc(). */ +void +free_fake_orcirc(or_circuit_t *orcirc) +{ + if (!orcirc) { + return; + } + + circuit_t *circ = TO_CIRCUIT(orcirc); + + relay_crypto_clear(&orcirc->crypto); + + circpad_circuit_free_all_machineinfos(circ); + + if (orcirc->p_chan && orcirc->p_chan->cmux) { + circuitmux_detach_circuit(orcirc->p_chan->cmux, circ); + } + if (circ->n_chan && circ->n_chan->cmux) { + circuitmux_detach_circuit(circ->n_chan->cmux, circ); + } + + tor_free_(circ); +} diff --git a/src/test/fakecircs.h b/src/test/fakecircs.h new file mode 100644 index 0000000000..5fd02027f0 --- /dev/null +++ b/src/test/fakecircs.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file fakecircs.h + * \brief Declarations for fake circuits for test suite use. + **/ + +#ifndef TOR_FAKECIRCS_H +#define TOR_FAKECIRCS_H + +#include "core/or/or_circuit_st.h" + +or_circuit_t *new_fake_orcirc(channel_t *nchan, channel_t *pchan); +void free_fake_orcirc(or_circuit_t *orcirc); + +#endif /* TOR_FAKECIRCS_H */ diff --git a/src/test/hs_test_helpers.c b/src/test/hs_test_helpers.c index 0a21fe576b..22be4aea23 100644 --- a/src/test/hs_test_helpers.c +++ b/src/test/hs_test_helpers.c @@ -53,7 +53,7 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now, } ret = ed25519_keypair_generate(&auth_kp, 0); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); ip->auth_key_cert = tor_cert_create(signing_kp, CERT_TYPE_AUTH_HS_IP_KEY, &auth_kp.pubkey, now, HS_DESC_CERT_LIFETIME, @@ -64,7 +64,7 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now, ip->legacy.key = crypto_pk_new(); tt_assert(ip->legacy.key); ret = crypto_pk_generate_key(ip->legacy.key); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); ssize_t cert_len = tor_make_rsa_ed25519_crosscert( &signing_kp->pubkey, ip->legacy.key, now + HS_DESC_CERT_LIFETIME, @@ -82,7 +82,7 @@ hs_helper_build_intro_point(const ed25519_keypair_t *signing_kp, time_t now, tor_cert_t *cross_cert; ret = curve25519_keypair_generate(&curve25519_kp, 0); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); ed25519_keypair_from_curve25519_keypair(&ed25519_kp, &signbit, &curve25519_kp); cross_cert = tor_cert_create(signing_kp, CERT_TYPE_CROSS_HS_IP_KEYS, @@ -140,7 +140,7 @@ hs_helper_build_hs_desc_impl(unsigned int no_ip, /* Setup superencrypted data section. */ ret = curve25519_keypair_generate(&auth_ephemeral_kp, 0); - tt_int_op(ret, ==, 0); + tt_int_op(ret, OP_EQ, 0); memcpy(&desc->superencrypted_data.auth_ephemeral_pubkey, &auth_ephemeral_kp.pubkey, sizeof(curve25519_public_key_t)); @@ -224,7 +224,7 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1, tt_mem_op(desc1->plaintext_data.blinded_pubkey.pubkey, OP_EQ, desc2->plaintext_data.blinded_pubkey.pubkey, ED25519_PUBKEY_LEN); - tt_u64_op(desc1->plaintext_data.revision_counter, ==, + tt_u64_op(desc1->plaintext_data.revision_counter, OP_EQ, desc2->plaintext_data.revision_counter); /* NOTE: We can't compare the encrypted blob because when encoding the @@ -241,7 +241,7 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1, { tt_assert(desc1->superencrypted_data.clients); tt_assert(desc2->superencrypted_data.clients); - tt_int_op(smartlist_len(desc1->superencrypted_data.clients), ==, + tt_int_op(smartlist_len(desc1->superencrypted_data.clients), OP_EQ, smartlist_len(desc2->superencrypted_data.clients)); for (int i=0; i < smartlist_len(desc1->superencrypted_data.clients); @@ -259,15 +259,15 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1, } /* Encrypted data section. */ - tt_uint_op(desc1->encrypted_data.create2_ntor, ==, + tt_uint_op(desc1->encrypted_data.create2_ntor, OP_EQ, desc2->encrypted_data.create2_ntor); /* Authentication type. */ - tt_int_op(!!desc1->encrypted_data.intro_auth_types, ==, + tt_int_op(!!desc1->encrypted_data.intro_auth_types, OP_EQ, !!desc2->encrypted_data.intro_auth_types); if (desc1->encrypted_data.intro_auth_types && desc2->encrypted_data.intro_auth_types) { - tt_int_op(smartlist_len(desc1->encrypted_data.intro_auth_types), ==, + tt_int_op(smartlist_len(desc1->encrypted_data.intro_auth_types), OP_EQ, smartlist_len(desc2->encrypted_data.intro_auth_types)); for (int i = 0; i < smartlist_len(desc1->encrypted_data.intro_auth_types); @@ -281,7 +281,7 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1, { tt_assert(desc1->encrypted_data.intro_points); tt_assert(desc2->encrypted_data.intro_points); - tt_int_op(smartlist_len(desc1->encrypted_data.intro_points), ==, + tt_int_op(smartlist_len(desc1->encrypted_data.intro_points), OP_EQ, smartlist_len(desc2->encrypted_data.intro_points)); for (int i=0; i < smartlist_len(desc1->encrypted_data.intro_points); i++) { hs_desc_intro_point_t *ip1 = smartlist_get(desc1->encrypted_data @@ -296,12 +296,12 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1, tt_mem_op(&ip1->enc_key, OP_EQ, &ip2->enc_key, CURVE25519_PUBKEY_LEN); } - tt_int_op(smartlist_len(ip1->link_specifiers), ==, + tt_int_op(smartlist_len(ip1->link_specifiers), OP_EQ, smartlist_len(ip2->link_specifiers)); for (int j = 0; j < smartlist_len(ip1->link_specifiers); j++) { link_specifier_t *ls1 = smartlist_get(ip1->link_specifiers, j), *ls2 = smartlist_get(ip2->link_specifiers, j); - tt_int_op(link_specifier_get_ls_type(ls1), ==, + tt_int_op(link_specifier_get_ls_type(ls1), OP_EQ, link_specifier_get_ls_type(ls2)); switch (link_specifier_get_ls_type(ls1)) { case LS_IPV4: @@ -311,7 +311,7 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1, tt_int_op(addr1, OP_EQ, addr2); uint16_t port1 = link_specifier_get_un_ipv4_port(ls1); uint16_t port2 = link_specifier_get_un_ipv4_port(ls2); - tt_int_op(port1, ==, port2); + tt_int_op(port1, OP_EQ, port2); } break; case LS_IPV6: @@ -326,7 +326,7 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1, link_specifier_getlen_un_ipv6_addr(ls1)); uint16_t port1 = link_specifier_get_un_ipv6_port(ls1); uint16_t port2 = link_specifier_get_un_ipv6_port(ls2); - tt_int_op(port1, ==, port2); + tt_int_op(port1, OP_EQ, port2); } break; case LS_LEGACY_ID: diff --git a/src/test/include.am b/src/test/include.am index d8e25dea9f..bd7ab71a20 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -99,6 +99,7 @@ if UNITTESTS_ENABLED # ADD_C_FILE: INSERT SOURCES HERE. src_test_test_SOURCES += \ + src/test/fakecircs.c \ src/test/log_test_helpers.c \ src/test/hs_test_helpers.c \ src/test/rend_test_helpers.c \ @@ -122,6 +123,7 @@ src_test_test_SOURCES += \ src/test/test_checkdir.c \ src/test/test_circuitlist.c \ src/test/test_circuitmux.c \ + src/test/test_circuitmux_ewma.c \ src/test/test_circuitbuild.c \ src/test/test_circuituse.c \ src/test/test_circuitstats.c \ @@ -201,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 \ @@ -339,6 +342,7 @@ src_test_test_timers_LDFLAGS = $(src_test_test_LDFLAGS) # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS+= \ src/test/fakechans.h \ + src/test/fakecircs.h \ src/test/hs_test_helpers.h \ src/test/log_test_helpers.h \ src/test/rend_test_helpers.h \ diff --git a/src/test/test.c b/src/test/test.c index 6dbec26fa8..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 }; @@ -836,6 +674,7 @@ struct testgroup_t testgroups[] = { { "circuitpadding/", circuitpadding_tests }, { "circuitlist/", circuitlist_tests }, { "circuitmux/", circuitmux_tests }, + { "circuitmux_ewma/", circuitmux_ewma_tests }, { "circuitstats/", circuitstats_tests }, { "circuituse/", circuituse_tests }, { "compat/libevent/", compat_libevent_tests }, @@ -918,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 76c4c0ec75..967562890f 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -37,6 +37,7 @@ #define test_memeq_hex(expr1, hex) test_mem_op_hex(expr1, OP_EQ, hex) +#ifndef COCCI #define tt_double_op(a,op,b) \ tt_assert_test_type(a,b,#a" "#op" "#b,double,(val1_ op val2_),"%g", \ TT_EXIT_TEST_FUNCTION) @@ -64,6 +65,7 @@ tt_assert_test_fmt_type(a,b,#a" "#op" "#b,int64_t,(val1_ op val2_), \ int64_t, "%"PRId64, \ {print_ = (int64_t) value_;}, {}, TT_EXIT_TEST_FUNCTION) +#endif /* !defined(COCCI) */ /** * Declare that the test is done, even though no tt___op() calls were made. @@ -145,6 +147,7 @@ void free_pregenerated_keys(void); #define NAME_TEST_(name) #name #define NAME_TEST(name) NAME_TEST_(name) #define ASPECT(test_module, test_name) US2_CONCAT_2__(test_module, test_name) +#ifndef COCCI #define TEST_CASE(function) \ { \ NAME_TEST(function), \ @@ -161,15 +164,18 @@ void free_pregenerated_keys(void); NULL, \ NULL, \ } +#endif /* !defined(COCCI) */ #define NS(name) US_CONCAT_3_(NS_MODULE, NS_SUBMODULE, name) #define NS_FULL(module, submodule, name) US_CONCAT_3_(module, submodule, name) #define CALLED(mock_name) US_CONCAT_2_(NS(mock_name), called) +#ifndef COCCI #define NS_DECL(retval, mock_fn, args) \ extern int CALLED(mock_fn); \ static retval NS(mock_fn) args; int CALLED(mock_fn) = 0 #define NS_MOCK(name) MOCK(name, NS(name)) +#endif /* !defined(COCCI) */ #define NS_UNMOCK(name) UNMOCK(name) extern const struct testcase_setup_t passthrough_setup; @@ -193,6 +199,7 @@ extern struct testcase_t checkdir_tests[]; extern struct testcase_t circuitbuild_tests[]; extern struct testcase_t circuitlist_tests[]; extern struct testcase_t circuitmux_tests[]; +extern struct testcase_t circuitmux_ewma_tests[]; extern struct testcase_t circuitstats_tests[]; extern struct testcase_t circuituse_tests[]; extern struct testcase_t compat_libevent_tests[]; @@ -273,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_addr.c b/src/test/test_addr.c index c89c6e78d4..04380d1ccf 100644 --- a/src/test/test_addr.c +++ b/src/test/test_addr.c @@ -52,6 +52,7 @@ test_addr_basic(void *arg) ; } +#ifndef COCCI #define test_op_ip6_(a,op,b,e1,e2) \ STMT_BEGIN \ tt_assert_test_fmt_type(a,b,e1" "#op" "e2,struct in6_addr*, \ @@ -69,6 +70,7 @@ test_addr_basic(void *arg) TT_EXIT_TEST_FUNCTION \ ); \ STMT_END +#endif /* !defined(COCCI) */ /** Helper: Assert that two strings both decode as IPv6 addresses with * tor_inet_pton(), and both decode to the same address. */ @@ -111,6 +113,7 @@ test_addr_basic(void *arg) TT_DIE(("%s was not internal", a)); \ STMT_END +#ifndef COCCI /** Helper: Assert that <b>a</b> and <b>b</b>, when parsed by * tor_inet_pton(), give addresses that compare in the order defined by * <b>op</b> with tor_addr_compare(). */ @@ -135,6 +138,7 @@ test_addr_basic(void *arg) TT_DIE(("Failed: tor_addr_compare_masked(%s,%s,%d) %s 0", \ a, b, m, #op)); \ STMT_END +#endif /* !defined(COCCI) */ /** Helper: assert that <b>xx</b> is parseable as a masked IPv6 address with * ports by tor_parse_mask_addr_ports(), with family <b>f</b>, IP address @@ -1649,8 +1653,10 @@ test_addr_rfc6598(void *arg) ; } +#ifndef COCCI #define ADDR_LEGACY(name) \ { #name, test_addr_ ## name , 0, NULL, NULL } +#endif struct testcase_t addr_tests[] = { ADDR_LEGACY(basic), diff --git a/src/test/test_circuitmux.c b/src/test/test_circuitmux.c index a2b3e62fe8..6d9e5c472d 100644 --- a/src/test/test_circuitmux.c +++ b/src/test/test_circuitmux.c @@ -5,29 +5,23 @@ #define CIRCUITMUX_PRIVATE #define CIRCUITMUX_EWMA_PRIVATE #define RELAY_PRIVATE + #include "core/or/or.h" #include "core/or/channel.h" #include "core/or/circuitmux.h" #include "core/or/circuitmux_ewma.h" +#include "core/or/destroy_cell_queue_st.h" #include "core/or/relay.h" #include "core/or/scheduler.h" -#include "test/test.h" -#include "core/or/destroy_cell_queue_st.h" +#include "test/fakechans.h" +#include "test/fakecircs.h" +#include "test/test.h" #include <math.h> -/* XXXX duplicated function from test_circuitlist.c */ -static channel_t * -new_fake_channel(void) -{ - channel_t *chan = tor_malloc_zero(sizeof(channel_t)); - channel_init(chan); - return chan; -} - static int -has_queued_writes(channel_t *c) +mock_has_queued_writes_true(channel_t *c) { (void) c; return 1; @@ -44,16 +38,14 @@ test_cmux_destroy_cell_queue(void *arg) packed_cell_t *pc = NULL; destroy_cell_t *dc = NULL; - scheduler_init(); + MOCK(scheduler_release_channel, scheduler_release_channel_mock); (void) arg; - cmux = circuitmux_alloc(); - tt_assert(cmux); ch = new_fake_channel(); - circuitmux_set_policy(cmux, &ewma_policy); - ch->has_queued_writes = has_queued_writes; + ch->has_queued_writes = mock_has_queued_writes_true; ch->wide_circ_ids = 1; + cmux = ch->cmux; circ = circuitmux_get_first_active_circuit(cmux, &cq); tt_ptr_op(circ, OP_EQ, NULL); @@ -78,10 +70,11 @@ test_cmux_destroy_cell_queue(void *arg) tt_int_op(circuitmux_num_cells(cmux), OP_EQ, 2); done: - circuitmux_free(cmux); - channel_free(ch); + free_fake_channel(ch); packed_cell_free(pc); tor_free(dc); + + UNMOCK(scheduler_release_channel); } static void @@ -125,9 +118,364 @@ test_cmux_compute_ticks(void *arg) ; } +static void +test_cmux_allocate(void *arg) +{ + circuitmux_t *cmux = NULL; + + (void) arg; + + cmux = circuitmux_alloc(); + tt_assert(cmux); + tt_assert(cmux->chanid_circid_map); + tt_int_op(HT_SIZE(cmux->chanid_circid_map), OP_EQ, 0); + tt_uint_op(cmux->n_circuits, OP_EQ, 0); + tt_uint_op(cmux->n_active_circuits, OP_EQ, 0); + tt_uint_op(cmux->n_cells, OP_EQ, 0); + tt_uint_op(cmux->last_cell_was_destroy, OP_EQ, 0); + tt_int_op(cmux->destroy_ctr, OP_EQ, 0); + tt_ptr_op(cmux->policy, OP_EQ, NULL); + tt_ptr_op(cmux->policy_data, OP_EQ, NULL); + + tt_assert(TOR_SIMPLEQ_EMPTY(&cmux->destroy_cell_queue.head)); + + done: + circuitmux_free(cmux); +} + +static void +test_cmux_attach_circuit(void *arg) +{ + circuit_t *circ = NULL; + or_circuit_t *orcirc = NULL; + channel_t *pchan = NULL, *nchan = NULL; + cell_direction_t cdir; + unsigned int n_cells; + + (void) arg; + + pchan = new_fake_channel(); + tt_assert(pchan); + nchan = new_fake_channel(); + tt_assert(nchan); + + orcirc = new_fake_orcirc(nchan, pchan); + tt_assert(orcirc); + circ = TO_CIRCUIT(orcirc); + + /* While assigning a new circuit IDs, the circuitmux_attach_circuit() is + * called for a new channel on the circuit. This means, we should now have + * the created circuit attached on both the pchan and nchan cmux. */ + tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 1); + tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 1); + + /* There should be _no_ active circuit due to no queued cells. */ + tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 0); + tt_uint_op(circuitmux_num_active_circuits(nchan->cmux), OP_EQ, 0); + + /* Circuit should not be active on the cmux. */ + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_active(nchan->cmux, circ), OP_EQ, 0); + + /* Not active so no cells. */ + n_cells = circuitmux_num_cells_for_circuit(pchan->cmux, circ); + tt_uint_op(n_cells, OP_EQ, 0); + n_cells = circuitmux_num_cells(pchan->cmux); + tt_uint_op(n_cells, OP_EQ, 0); + n_cells = circuitmux_num_cells_for_circuit(nchan->cmux, circ); + tt_uint_op(n_cells, OP_EQ, 0); + n_cells = circuitmux_num_cells(nchan->cmux); + tt_uint_op(n_cells, OP_EQ, 0); + + /* So it should be attached :) */ + tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 1); + tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 1); + + /* Query the chanid<->circid map in the cmux subsytem with what we just + * created and validate the cell direction. */ + cdir = circuitmux_attached_circuit_direction(pchan->cmux, circ); + tt_int_op(cdir, OP_EQ, CELL_DIRECTION_IN); + cdir = circuitmux_attached_circuit_direction(nchan->cmux, circ); + tt_int_op(cdir, OP_EQ, CELL_DIRECTION_OUT); + + /* + * We'll activate->deactivate->activate to test all code paths of + * circuitmux_set_num_cells(). + */ + + /* Activate circuit. */ + circuitmux_set_num_cells(pchan->cmux, circ, 4); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1); + + /* Deactivate. */ + circuitmux_clear_num_cells(pchan->cmux, circ); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0); + tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 0); + + /* Re-activate. */ + circuitmux_set_num_cells(pchan->cmux, circ, 4); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1); + + /* Once re-attached, it should become inactive because the circuit has no + * cells while the chanid<->circid object has some. The attach code will + * reset the count on the cmux for that circuit: + * + * if (chanid_circid_muxinfo_t->muxinfo.cell_count > 0 && cell_count == 0) { + */ + circuitmux_attach_circuit(pchan->cmux, circ, CELL_DIRECTION_IN); + n_cells = circuitmux_num_cells_for_circuit(pchan->cmux, circ); + tt_uint_op(n_cells, OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0); + tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 0); + + /* Lets queue a cell on the circuit now so it becomes active when + * re-attaching: + * + * else if (chanid_circid_muxinfo_t->muxinfo.cell_count == 0 && + * cell_count > 0) { + */ + orcirc->p_chan_cells.n = 1; + circuitmux_attach_circuit(pchan->cmux, circ, CELL_DIRECTION_IN); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1); + + done: + free_fake_orcirc(orcirc); + free_fake_channel(pchan); + free_fake_channel(nchan); +} + +static void +test_cmux_detach_circuit(void *arg) +{ + circuit_t *circ = NULL; + or_circuit_t *orcirc = NULL; + channel_t *pchan = NULL, *nchan = NULL; + + (void) arg; + + pchan = new_fake_channel(); + tt_assert(pchan); + nchan = new_fake_channel(); + tt_assert(nchan); + + orcirc = new_fake_orcirc(nchan, pchan); + tt_assert(orcirc); + circ = TO_CIRCUIT(orcirc); + + /* While assigning a new circuit IDs, the circuitmux_attach_circuit() is + * called for a new channel on the circuit. This means, we should now have + * the created circuit attached on both the pchan and nchan cmux. */ + tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 1); + tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 1); + tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 1); + tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 1); + + /* Now, detach the circuit from pchan and then nchan. */ + circuitmux_detach_circuit(pchan->cmux, circ); + tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 0); + circuitmux_detach_circuit(nchan->cmux, circ); + tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 0); + + done: + free_fake_orcirc(orcirc); + free_fake_channel(pchan); + free_fake_channel(nchan); +} + +static void +test_cmux_detach_all_circuits(void *arg) +{ + circuit_t *circ = NULL; + or_circuit_t *orcirc = NULL; + channel_t *pchan = NULL, *nchan = NULL; + smartlist_t *detached_out = smartlist_new(); + + (void) arg; + + /* Channels need to be registered in order for the detach all circuit + * function to find them. */ + pchan = new_fake_channel(); + tt_assert(pchan); + channel_register(pchan); + nchan = new_fake_channel(); + tt_assert(nchan); + channel_register(nchan); + + orcirc = new_fake_orcirc(nchan, pchan); + tt_assert(orcirc); + circ = TO_CIRCUIT(orcirc); + + /* Just make sure it is attached. */ + tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 1); + tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 1); + tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 1); + tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 1); + + /* Queue some cells so we can test if the circuit becomes inactive on the + * cmux after the mass detach. */ + circuitmux_set_num_cells(pchan->cmux, circ, 4); + circuitmux_set_num_cells(nchan->cmux, circ, 4); + + /* Detach all on pchan and then nchan. */ + circuitmux_detach_all_circuits(pchan->cmux, detached_out); + tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0); + tt_int_op(smartlist_len(detached_out), OP_EQ, 1); + circuitmux_detach_all_circuits(nchan->cmux, NULL); + tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_active(nchan->cmux, circ), OP_EQ, 0); + + done: + smartlist_free(detached_out); + free_fake_orcirc(orcirc); + free_fake_channel(pchan); + free_fake_channel(nchan); +} + +static void +test_cmux_policy(void *arg) +{ + circuit_t *circ = NULL; + or_circuit_t *orcirc = NULL; + channel_t *pchan = NULL, *nchan = NULL; + + (void) arg; + + pchan = new_fake_channel(); + tt_assert(pchan); + channel_register(pchan); + nchan = new_fake_channel(); + tt_assert(nchan); + channel_register(nchan); + + orcirc = new_fake_orcirc(nchan, pchan); + tt_assert(orcirc); + circ = TO_CIRCUIT(orcirc); + + /* Confirm we have the EWMA policy by default for new channels. */ + tt_ptr_op(circuitmux_get_policy(pchan->cmux), OP_EQ, &ewma_policy); + tt_ptr_op(circuitmux_get_policy(nchan->cmux), OP_EQ, &ewma_policy); + + /* Putting cell on the cmux means will make the notify policy code path to + * trigger. */ + circuitmux_set_num_cells(pchan->cmux, circ, 4); + + /* Clear it out. */ + circuitmux_clear_policy(pchan->cmux); + + /* Set back the EWMA policy. */ + circuitmux_set_policy(pchan->cmux, &ewma_policy); + + done: + free_fake_orcirc(orcirc); + free_fake_channel(pchan); + free_fake_channel(nchan); +} + +static void +test_cmux_xmit_cell(void *arg) +{ + circuit_t *circ = NULL; + or_circuit_t *orcirc = NULL; + channel_t *pchan = NULL, *nchan = NULL; + + (void) arg; + + pchan = new_fake_channel(); + tt_assert(pchan); + nchan = new_fake_channel(); + tt_assert(nchan); + + orcirc = new_fake_orcirc(nchan, pchan); + tt_assert(orcirc); + circ = TO_CIRCUIT(orcirc); + + /* Queue 4 cells on the circuit. */ + circuitmux_set_num_cells(pchan->cmux, circ, 4); + tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 4); + tt_uint_op(circuitmux_num_cells(pchan->cmux), OP_EQ, 4); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1); + tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 1); + + /* Emit the first cell. Circuit should still be active. */ + circuitmux_notify_xmit_cells(pchan->cmux, circ, 1); + tt_uint_op(circuitmux_num_cells(pchan->cmux), OP_EQ, 3); + tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 3); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1); + tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 1); + + /* Emit the last 3 cells. Circuit should become inactive. */ + circuitmux_notify_xmit_cells(pchan->cmux, circ, 3); + tt_uint_op(circuitmux_num_cells(pchan->cmux), OP_EQ, 0); + tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 0); + tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0); + tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 0); + + /* Queue a DESTROY cell. */ + pchan->has_queued_writes = mock_has_queued_writes_true; + circuitmux_append_destroy_cell(pchan, pchan->cmux, orcirc->p_circ_id, 0); + tt_int_op(pchan->cmux->destroy_ctr, OP_EQ, 1); + tt_int_op(pchan->cmux->destroy_cell_queue.n, OP_EQ, 1); + tt_int_op(circuitmux_count_queued_destroy_cells(pchan, pchan->cmux), + OP_EQ, 1); + + /* Emit the DESTROY cell. */ + circuitmux_notify_xmit_destroy(pchan->cmux); + tt_int_op(pchan->cmux->destroy_ctr, OP_EQ, 0); + + done: + free_fake_orcirc(orcirc); + free_fake_channel(pchan); + free_fake_channel(nchan); +} + +static void * +cmux_setup_test(const struct testcase_t *tc) +{ + static int whatever; + + (void) tc; + + cell_ewma_initialize_ticks(); + return &whatever; +} + +static int +cmux_cleanup_test(const struct testcase_t *tc, void *ptr) +{ + (void) tc; + (void) ptr; + + circuitmux_ewma_free_all(); + + return 1; +} + +static struct testcase_setup_t cmux_test_setup = { + .setup_fn = cmux_setup_test, + .cleanup_fn = cmux_cleanup_test, +}; + +#define TEST_CMUX(name) \ + { #name, test_cmux_##name, TT_FORK, &cmux_test_setup, NULL } + struct testcase_t circuitmux_tests[] = { - { "destroy_cell_queue", test_cmux_destroy_cell_queue, TT_FORK, NULL, NULL }, - { "compute_ticks", test_cmux_compute_ticks, TT_FORK, NULL, NULL }, + /* Test circuitmux_t object */ + TEST_CMUX(allocate), + TEST_CMUX(attach_circuit), + TEST_CMUX(detach_circuit), + TEST_CMUX(detach_all_circuits), + TEST_CMUX(policy), + TEST_CMUX(xmit_cell), + + /* Misc. */ + TEST_CMUX(compute_ticks), + TEST_CMUX(destroy_cell_queue), + END_OF_TESTCASES }; diff --git a/src/test/test_circuitmux_ewma.c b/src/test/test_circuitmux_ewma.c new file mode 100644 index 0000000000..8b3edf2b06 --- /dev/null +++ b/src/test/test_circuitmux_ewma.c @@ -0,0 +1,228 @@ +/* Copyright (c) 2013-2019, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#define CIRCUITMUX_PRIVATE +#define CIRCUITMUX_EWMA_PRIVATE + +#include "core/or/or.h" +#include "core/or/circuitmux.h" +#include "core/or/circuitmux_ewma.h" + +#include "test/fakechans.h" +#include "test/fakecircs.h" +#include "test/test.h" + +static void +test_cmux_ewma_active_circuit(void *arg) +{ + circuitmux_t cmux; /* garbage */ + circuitmux_policy_data_t *pol_data = NULL; + circuit_t circ; /* garbage */ + circuitmux_policy_circ_data_t *circ_data = NULL; + + (void) arg; + + pol_data = ewma_policy.alloc_cmux_data(&cmux); + tt_assert(pol_data); + circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ, + CELL_DIRECTION_OUT, 42); + tt_assert(circ_data); + + /* Get EWMA specific objects. */ + + /* Make circuit active. */ + ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data); + + circuit_t *entry = ewma_policy.pick_active_circuit(&cmux, pol_data); + tt_mem_op(entry, OP_EQ, &circ, sizeof(circ)); + + done: + ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data); + ewma_policy.free_cmux_data(&cmux, pol_data); +} + +static void +test_cmux_ewma_xmit_cell(void *arg) +{ + circuitmux_t cmux; /* garbage */ + circuitmux_policy_data_t *pol_data = NULL; + circuit_t circ; /* garbage */ + circuitmux_policy_circ_data_t *circ_data = NULL; + ewma_policy_data_t *ewma_pol_data; + ewma_policy_circ_data_t *ewma_data; + double old_cell_count; + + (void) arg; + + pol_data = ewma_policy.alloc_cmux_data(&cmux); + tt_assert(pol_data); + circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ, + CELL_DIRECTION_OUT, 42); + tt_assert(circ_data); + ewma_pol_data = TO_EWMA_POL_DATA(pol_data); + ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data); + + /* Make circuit active. */ + ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data); + + /* Move back in time the last time we calibrated so we scale the active + * circuit when emitting a cell. */ + ewma_pol_data->active_circuit_pqueue_last_recalibrated -= 100; + ewma_data->cell_ewma.last_adjusted_tick = + ewma_pol_data->active_circuit_pqueue_last_recalibrated; + + /* Grab old cell count. */ + old_cell_count = ewma_data->cell_ewma.cell_count; + + ewma_policy.notify_xmit_cells(&cmux, pol_data, &circ, circ_data, 1); + + /* Our old cell count should be lower to what we have since we just emitted + * a cell and thus we scale. */ + tt_double_op(old_cell_count, OP_LT, ewma_data->cell_ewma.cell_count); + + done: + ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data); + ewma_policy.free_cmux_data(&cmux, pol_data); +} + +static void +test_cmux_ewma_notify_circ(void *arg) +{ + circuitmux_t cmux; /* garbage */ + circuitmux_policy_data_t *pol_data = NULL; + circuit_t circ; /* garbage */ + circuitmux_policy_circ_data_t *circ_data = NULL; + const ewma_policy_data_t *ewma_pol_data; + + (void) arg; + + pol_data = ewma_policy.alloc_cmux_data(&cmux); + tt_assert(pol_data); + circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ, + CELL_DIRECTION_OUT, 42); + tt_assert(circ_data); + + /* Currently, notify_circ_active() ignores cmux and circ. They can not be + * NULL so it is fine to pass garbage. */ + ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data); + + /* We should have an active circuit in the queue so its EWMA value can be + * tracked. */ + ewma_pol_data = TO_EWMA_POL_DATA(pol_data); + tt_int_op(smartlist_len(ewma_pol_data->active_circuit_pqueue), OP_EQ, 1); + tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0); + + ewma_policy.notify_circ_inactive(&cmux, pol_data, &circ, circ_data); + /* Should be removed from the active queue. */ + ewma_pol_data = TO_EWMA_POL_DATA(pol_data); + tt_int_op(smartlist_len(ewma_pol_data->active_circuit_pqueue), OP_EQ, 0); + tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0); + + done: + ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data); + ewma_policy.free_cmux_data(&cmux, pol_data); +} + +static void +test_cmux_ewma_policy_circ_data(void *arg) +{ + circuitmux_t cmux; /* garbage */ + circuitmux_policy_data_t pol_data; /* garbage */ + circuit_t circ; /* garbage */ + circuitmux_policy_circ_data_t *circ_data = NULL; + const ewma_policy_circ_data_t *ewma_data; + + (void) arg; + + /* Currently, alloc_circ_data() ignores every parameter _except_ the cell + * direction so it is OK to pass garbage. They can not be NULL. */ + circ_data = ewma_policy.alloc_circ_data(&cmux, &pol_data, &circ, + CELL_DIRECTION_OUT, 42); + tt_assert(circ_data); + tt_uint_op(circ_data->magic, OP_EQ, EWMA_POL_CIRC_DATA_MAGIC); + + ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data); + tt_mem_op(ewma_data->circ, OP_EQ, &circ, sizeof(circuit_t)); + tt_double_op(ewma_data->cell_ewma.cell_count, OP_LE, 0.0); + tt_int_op(ewma_data->cell_ewma.heap_index, OP_EQ, -1); + tt_uint_op(ewma_data->cell_ewma.is_for_p_chan, OP_EQ, 0); + ewma_policy.free_circ_data(&cmux, &pol_data, &circ, circ_data); + + circ_data = ewma_policy.alloc_circ_data(&cmux, &pol_data, &circ, + CELL_DIRECTION_IN, 42); + tt_assert(circ_data); + tt_uint_op(circ_data->magic, OP_EQ, EWMA_POL_CIRC_DATA_MAGIC); + + ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data); + tt_mem_op(ewma_data->circ, OP_EQ, &circ, sizeof(circuit_t)); + tt_double_op(ewma_data->cell_ewma.cell_count, OP_LE, 0.0); + tt_int_op(ewma_data->cell_ewma.heap_index, OP_EQ, -1); + tt_uint_op(ewma_data->cell_ewma.is_for_p_chan, OP_EQ, 1); + + done: + ewma_policy.free_circ_data(&cmux, &pol_data, &circ, circ_data); +} + +static void +test_cmux_ewma_policy_data(void *arg) +{ + circuitmux_t cmux; /* garbage. */ + circuitmux_policy_data_t *pol_data = NULL; + const ewma_policy_data_t *ewma_pol_data; + + (void) arg; + + pol_data = ewma_policy.alloc_cmux_data(&cmux); + tt_assert(pol_data); + tt_uint_op(pol_data->magic, OP_EQ, EWMA_POL_DATA_MAGIC); + + /* Test EWMA object. */ + ewma_pol_data = TO_EWMA_POL_DATA(pol_data); + tt_assert(ewma_pol_data->active_circuit_pqueue); + tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0); + + done: + ewma_policy.free_cmux_data(&cmux, pol_data); +} + +static void * +cmux_ewma_setup_test(const struct testcase_t *tc) +{ + static int whatever; + + (void) tc; + + cell_ewma_initialize_ticks(); + cmux_ewma_set_options(NULL, NULL); + + return &whatever; +} + +static int +cmux_ewma_cleanup_test(const struct testcase_t *tc, void *ptr) +{ + (void) tc; + (void) ptr; + + circuitmux_ewma_free_all(); + + return 1; +} + +static struct testcase_setup_t cmux_ewma_test_setup = { + .setup_fn = cmux_ewma_setup_test, + .cleanup_fn = cmux_ewma_cleanup_test, +}; + +#define TEST_CMUX_EWMA(name) \ + { #name, test_cmux_ewma_##name, TT_FORK, &cmux_ewma_test_setup, NULL } + +struct testcase_t circuitmux_ewma_tests[] = { + TEST_CMUX_EWMA(active_circuit), + TEST_CMUX_EWMA(policy_data), + TEST_CMUX_EWMA(policy_circ_data), + TEST_CMUX_EWMA(notify_circ), + TEST_CMUX_EWMA(xmit_cell), + + END_OF_TESTCASES +}; diff --git a/src/test/test_circuitpadding.c b/src/test/test_circuitpadding.c index 934ddb0208..70e2081c55 100644 --- a/src/test/test_circuitpadding.c +++ b/src/test/test_circuitpadding.c @@ -38,6 +38,7 @@ #include "core/or/or_circuit_st.h" #include "core/or/origin_circuit_st.h" +#include "test/fakecircs.h" #include "test/rng_test_helpers.h" /* Start our monotime mocking at 1 second past whatever monotime_init() @@ -53,7 +54,6 @@ circid_t get_unique_circ_id_by_chan(channel_t *chan); void helper_create_basic_machine(void); static void helper_create_conditional_machines(void); -static or_circuit_t * new_fake_orcirc(channel_t *nchan, channel_t *pchan); channel_t *new_fake_channel(void); void test_circuitpadding_negotiation(void *arg); void test_circuitpadding_wronghop(void *arg); @@ -67,7 +67,6 @@ void test_circuitpadding_state_length(void *arg); static void simulate_single_hop_extend(circuit_t *client, circuit_t *mid_relay, int padding); -void free_fake_orcirc(circuit_t *circ); void free_fake_origin_circuit(origin_circuit_t *circ); static int deliver_negotiated = 1; @@ -127,62 +126,6 @@ circuit_get_nth_node_mock(origin_circuit_t *circ, int hop) return &padding_node; } -static or_circuit_t * -new_fake_orcirc(channel_t *nchan, channel_t *pchan) -{ - or_circuit_t *orcirc = NULL; - circuit_t *circ = NULL; - crypt_path_t tmp_cpath; - char whatevs_key[CPATH_KEY_MATERIAL_LEN]; - - orcirc = tor_malloc_zero(sizeof(*orcirc)); - circ = &(orcirc->base_); - circ->magic = OR_CIRCUIT_MAGIC; - - //circ->n_chan = nchan; - circ->n_circ_id = get_unique_circ_id_by_chan(nchan); - cell_queue_init(&(circ->n_chan_cells)); - circ->n_hop = NULL; - circ->streams_blocked_on_n_chan = 0; - circ->streams_blocked_on_p_chan = 0; - circ->n_delete_pending = 0; - circ->p_delete_pending = 0; - circ->received_destroy = 0; - circ->state = CIRCUIT_STATE_OPEN; - circ->purpose = CIRCUIT_PURPOSE_OR; - circ->package_window = CIRCWINDOW_START_MAX; - circ->deliver_window = CIRCWINDOW_START_MAX; - circ->n_chan_create_cell = NULL; - - //orcirc->p_chan = pchan; - orcirc->p_circ_id = get_unique_circ_id_by_chan(pchan); - cell_queue_init(&(orcirc->p_chan_cells)); - - circuit_set_p_circid_chan(orcirc, orcirc->p_circ_id, pchan); - circuit_set_n_circid_chan(circ, circ->n_circ_id, nchan); - - memset(&tmp_cpath, 0, sizeof(tmp_cpath)); - if (cpath_init_circuit_crypto(&tmp_cpath, whatevs_key, - sizeof(whatevs_key), 0, 0)<0) { - log_warn(LD_BUG,"Circuit initialization failed"); - return NULL; - } - orcirc->crypto = tmp_cpath.pvt_crypto; - - return orcirc; -} - -void -free_fake_orcirc(circuit_t *circ) -{ - or_circuit_t *orcirc = TO_OR_CIRCUIT(circ); - - relay_crypto_clear(&orcirc->crypto); - - circpad_circuit_free_all_machineinfos(circ); - tor_free(circ); -} - void free_fake_origin_circuit(origin_circuit_t *circ) { @@ -413,7 +356,7 @@ test_circuitpadding_rtt(void *arg) circpad_machine_current_state( client_side->padding_info[0])->histogram_edges[0]); done: - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); circuitmux_detach_all_circuits(dummy_channel.cmux, NULL); circuitmux_free(dummy_channel.cmux); timers_shutdown(); @@ -1439,7 +1382,7 @@ test_circuitpadding_wronghop(void *arg) /* Test 2: Test no padding */ free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); client_side = TO_CIRCUIT(origin_circuit_new()); relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, @@ -1484,7 +1427,7 @@ test_circuitpadding_wronghop(void *arg) done: free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); circuitmux_detach_all_circuits(dummy_channel.cmux, NULL); circuitmux_free(dummy_channel.cmux); monotime_disable_test_mocking(); @@ -1553,7 +1496,7 @@ test_circuitpadding_negotiation(void *arg) /* Test 2: Test no padding */ free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); client_side = TO_CIRCUIT(origin_circuit_new()); relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel)); @@ -1591,7 +1534,7 @@ test_circuitpadding_negotiation(void *arg) /* 3. Test failure to negotiate a machine due to desync */ free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); client_side = TO_CIRCUIT(origin_circuit_new()); relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel)); @@ -1619,7 +1562,7 @@ test_circuitpadding_negotiation(void *arg) done: free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); circuitmux_detach_all_circuits(dummy_channel.cmux, NULL); circuitmux_free(dummy_channel.cmux); monotime_disable_test_mocking(); @@ -1939,7 +1882,7 @@ test_circuitpadding_state_length(void *arg) tor_free(client_machine); free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); circuitmux_detach_all_circuits(dummy_channel.cmux, NULL); circuitmux_free(dummy_channel.cmux); @@ -2312,7 +2255,7 @@ test_circuitpadding_circuitsetup_machine(void *arg) tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec, OP_NE, 0); circuit_mark_for_close(client_side, END_CIRC_REASON_FLAG_REMOTE); - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); timers_advance_and_run(5000); /* No cells sent */ @@ -2616,7 +2559,7 @@ test_circuitpadding_global_rate_limiting(void *arg) tt_int_op(retval, OP_EQ, 0); done: - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); circuitmux_detach_all_circuits(dummy_channel.cmux, NULL); circuitmux_free(dummy_channel.cmux); SMARTLIST_FOREACH(vote1.net_params, char *, cp, tor_free(cp)); @@ -2769,7 +2712,7 @@ test_circuitpadding_reduce_disable(void *arg) tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL); done: - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); circuitmux_detach_all_circuits(dummy_channel.cmux, NULL); circuitmux_free(dummy_channel.cmux); testing_disable_reproducible_rng(); @@ -3075,7 +3018,7 @@ helper_test_hs_machines(bool test_intro_circs) } done: - free_fake_orcirc(relay_side); + free_fake_orcirc(TO_OR_CIRCUIT(relay_side)); circuitmux_detach_all_circuits(dummy_channel.cmux, NULL); circuitmux_free(dummy_channel.cmux); free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side)); 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 cbb84e4dcf..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,7 +18,9 @@ #include "core/or/circuitmux_ewma.h" #include "core/or/circuitbuild.h" #include "app/config/config.h" -#include "lib/confmgt/confparse.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" #include "test/test.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); @@ -906,14 +910,12 @@ test_config_fix_my_family(void *arg) family3->next = NULL; or_options_t* options = options_new(); - or_options_t* defaults = options_new(); (void) arg; options_init(options); - options_init(defaults); options->MyFamily_lines = family; - options_validate(NULL, options, defaults, 0, &err) ; + options_validate(NULL, options, &err) ; if (err != NULL) { TT_FAIL(("options_validate failed: %s", err)); @@ -935,7 +937,6 @@ test_config_fix_my_family(void *arg) done: tor_free(err); or_options_free(options); - or_options_free(defaults); } static int n_hostname_01010101 = 0; @@ -3816,7 +3817,9 @@ static void test_config_default_fallback_dirs(void *arg) { const char *fallback[] = { +#ifndef COCCI #include "app/config/fallback_dirs.inc" +#endif NULL }; @@ -3998,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); @@ -4042,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); @@ -4073,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); @@ -4105,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); @@ -4119,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); @@ -4128,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); @@ -4141,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); @@ -4157,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); @@ -4170,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 @@ -4192,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 @@ -4214,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); @@ -4226,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); @@ -4237,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 @@ -4258,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 @@ -4277,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 @@ -4293,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); @@ -4323,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); @@ -4336,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); @@ -4349,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); @@ -4362,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); @@ -4375,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); @@ -4388,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); @@ -4399,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); @@ -4408,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); @@ -4421,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); @@ -4434,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); @@ -4447,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); @@ -4460,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); @@ -4473,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); @@ -4486,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); @@ -4499,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); @@ -4512,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); @@ -4525,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); @@ -4537,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); @@ -4552,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); @@ -4567,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); @@ -4575,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); @@ -4591,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); @@ -4606,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); @@ -4616,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); @@ -4626,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); @@ -4635,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); @@ -4647,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); @@ -4657,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); @@ -4670,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); @@ -4684,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); @@ -4698,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); @@ -4711,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); @@ -4721,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); @@ -4735,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); @@ -4744,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); @@ -4754,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 @@ -4790,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); @@ -4803,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); @@ -4817,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); @@ -4826,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); @@ -4839,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); @@ -4853,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); @@ -4862,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); @@ -4873,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); @@ -4882,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); @@ -4891,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); @@ -5640,7 +5643,6 @@ test_config_check_bridge_distribution_setting_not_a_bridge(void *arg) { or_options_t* options = get_options_mutable(); or_options_t* old_options = options; - or_options_t* default_options = options; char* message = NULL; int ret; @@ -5649,7 +5651,7 @@ test_config_check_bridge_distribution_setting_not_a_bridge(void *arg) options->BridgeRelay = 0; options->BridgeDistribution = (char*)("https"); - ret = options_validate(old_options, options, default_options, 0, &message); + ret = options_validate(old_options, options, &message); tt_int_op(ret, OP_EQ, -1); tt_str_op(message, OP_EQ, "You set BridgeDistribution, but you " diff --git a/src/test/test_confmgr.c b/src/test/test_confmgr.c index d5c73b48e4..375a513c07 100644 --- a/src/test/test_confmgr.c +++ b/src/test/test_confmgr.c @@ -4,16 +4,16 @@ /* See LICENSE for licensing information */ /* - * Tests for confparse.c's features that support multiple configuration + * Tests for confmgt.c's features that support multiple configuration * formats and configuration objects. */ -#define CONFPARSE_PRIVATE +#define CONFMGT_PRIVATE #include "orconfig.h" #include "core/or/or.h" #include "lib/encoding/confline.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "test/test.h" #include "test/log_test_helpers.h" @@ -43,6 +43,8 @@ typedef struct { int fuzziness; char *alpacaname; int n_wings; /* deprecated; alpacas don't have wings. */ + + int square_fuzziness; /* Derived from fuzziness. */ } alpaca_cfg_t; /* @@ -105,6 +107,84 @@ static config_abbrev_t llama_abbrevs[] = { { NULL, NULL, 0, 0 }, }; +static int +legacy_validate_pasture(const void *old_, void *obj, char **msg_out) +{ + const pasture_cfg_t *old = old_; + pasture_cfg_t *p = obj; + + // llamas can't find their way home if the letters are lowercase. + if (p->address) + tor_strupper(p->address); + + if (old && old->address && + (!p->address || strcmp(old->address, p->address))) { + *msg_out = tor_strdup("You can't move a pasture."); + return -1; + } + + return 0; +} + +static int +validate_llama(const void *obj, char **msg_out) +{ + const llama_cfg_t *llama = obj; + tor_assert(llama->magic == 0x11aa11); + + if (! llama->llamaname || strlen(llama->llamaname) == 0) { + *msg_out = tor_strdup("A llama has no name!?"); + return -1; + } + + if (strspn(llama->llamaname, "0123456789") == strlen(llama->llamaname)) { + *msg_out = tor_strdup("It is not a number; it is a free llama!"); + return -1; + } + + return 0; +} + +static int +check_transition_alpaca(const void *old_, const void *new_, char **msg_out) +{ + const alpaca_cfg_t *old_alpaca = old_; + const alpaca_cfg_t *new_alpaca = new_; + + tor_assert(old_alpaca && new_alpaca); + tor_assert(old_alpaca->magic == 0xa15aca); + tor_assert(new_alpaca->magic == 0xa15aca); + + if (old_alpaca->fuzziness > new_alpaca->fuzziness) { + *msg_out = tor_strdup("An alpaca only becomes more fuzzy over time."); + return -1; + } + + return 0; +} + +static int +post_normalize_llama(void *obj, char **msg_out) +{ + (void)msg_out; + llama_cfg_t *llama = obj; + tor_assert(llama->magic == 0x11aa11); + tor_assert(llama->llamaname); // we have already checked for a NULL name. + tor_free(llama->description); + tor_asprintf(&llama->description, "A llama called %s.", llama->llamaname); + return 0; +} + +static int +pre_normalize_alpaca(void *obj, char **msg_out) +{ + (void)msg_out; + alpaca_cfg_t *alpaca = obj; + tor_assert(alpaca->magic == 0xa15aca); + alpaca->square_fuzziness = alpaca->fuzziness * alpaca->fuzziness; + return 0; +} + static const config_format_t pasture_fmt = { sizeof(pasture_cfg_t), { @@ -114,6 +194,7 @@ static const config_format_t pasture_fmt = { }, .vars = pasture_vars, .config_suite_offset = offsetof(pasture_cfg_t, subobjs), + .legacy_validate_fn = legacy_validate_pasture, }; static const config_format_t llama_fmt = { @@ -128,6 +209,8 @@ static const config_format_t llama_fmt = { .deprecations = llama_deprecations, .abbrevs = llama_abbrevs, .clear_fn = clear_llama_cfg, + .validate_fn = validate_llama, + .post_normalize_fn = post_normalize_llama, }; static const config_format_t alpaca_fmt = { @@ -140,6 +223,8 @@ static const config_format_t alpaca_fmt = { .vars = alpaca_vars, .config_suite_offset = -1, .deprecations = alpaca_deprecations, + .pre_normalize_fn = pre_normalize_alpaca, + .check_transition_fn = check_transition_alpaca, }; #define LLAMA_IDX 0 @@ -313,6 +398,95 @@ test_confmgr_dump(void *arg) tor_free(s); } +static pasture_cfg_t * +parse_and_validate(config_mgr_t *mgr, + const char *inp, const pasture_cfg_t *old, char **msg_out) +{ + pasture_cfg_t *p = config_new(mgr); + pasture_cfg_t *result = NULL; + config_line_t *lines = NULL; + + config_init(mgr, p); // set defaults. + int r = config_get_lines(inp, &lines, 0); + tt_int_op(r, OP_EQ, 0); + r = config_assign(mgr, p, lines, 0, msg_out); + tt_int_op(r, OP_EQ, 0); + tor_free(*msg_out); // sets it to NULL + r = config_validate(mgr, old, p, msg_out); + if (r < 0) + goto done; + + tt_ptr_op(*msg_out, OP_EQ, NULL); + result = p; + p = NULL; // prevent free + done: + config_free(mgr, p); + config_free_lines(lines); + return result; +} + +static void +test_confmgr_validate(void *arg) +{ + (void)arg; + char *msg = NULL; + config_mgr_t *mgr = get_mgr(true); + pasture_cfg_t *p_orig, *p=NULL; + + p_orig = parse_and_validate(mgr, "Llamaname Quest\n" + "Address 99 camelid way\n" + "Fuzziness 8\n", NULL, &msg); + tt_assert(p_orig); + + // Make sure normalization code was run. + const alpaca_cfg_t *ac0 = config_mgr_get_obj(mgr, p_orig, ALPACA_IDX); + const llama_cfg_t *lc0 = config_mgr_get_obj(mgr, p_orig, LLAMA_IDX); + tt_int_op(ac0->fuzziness, OP_EQ, 8); + tt_int_op(ac0->square_fuzziness, OP_EQ, 64); + tt_str_op(lc0->description, OP_EQ, "A llama called Quest."); + tt_str_op(p_orig->address, OP_EQ, "99 CAMELID WAY"); + + // try a bad llamaname. + p = parse_and_validate(mgr, "llamaname 123", p_orig, &msg); + tt_assert(!p); + tt_str_op(msg, OP_EQ, "It is not a number; it is a free llama!"); + tor_free(msg); + + // try a llamaname that would crash the post_normalize step, if it ran. + p = parse_and_validate(mgr, "", p_orig, &msg); + tt_assert(!p); + tt_str_op(msg, OP_EQ, "A llama has no name!?"); + tor_free(msg); + + // Verify that a transition to a less fuzzy alpaca fails. + p = parse_and_validate(mgr, "Llamaname Quest\n" + "Address 99 camelid way\n" + "Fuzziness 4\n", p_orig, &msg); + tt_assert(!p); + tt_str_op(msg, OP_EQ, "An alpaca only becomes more fuzzy over time."); + tor_free(msg); + + // Try a transition to a more fuzzy alpaca; it should work fine. + p = parse_and_validate(mgr, "Llamaname Mercutio\n" + // the default fuzziness is 50 + "Address 99 camelid way\n", p_orig, &msg); + tt_assert(p); + config_free(mgr, p); + + // Verify that we can't move the pasture. + p = parse_and_validate(mgr, "Llamaname Montague\n" + // the default fuzziness is 50 + "Address 99 ungulate st\n", p_orig, &msg); + tt_assert(!p); + tt_str_op(msg, OP_EQ, "You can't move a pasture."); + + done: + config_free(mgr, p); + config_free(mgr, p_orig); + config_mgr_free(mgr); + tor_free(msg); +} + #define CONFMGR_TEST(name, flags) \ { #name, test_confmgr_ ## name, flags, NULL, NULL } @@ -321,5 +495,6 @@ struct testcase_t confmgr_tests[] = { CONFMGR_TEST(magic, 0), CONFMGR_TEST(parse, 0), CONFMGR_TEST(dump, 0), + CONFMGR_TEST(validate, 0), END_OF_TESTCASES }; diff --git a/src/test/test_confparse.c b/src/test/test_confparse.c index 5f29a22c10..39e2de866c 100644 --- a/src/test/test_confparse.c +++ b/src/test/test_confparse.c @@ -4,17 +4,17 @@ /* See LICENSE for licensing information */ /* - * Tests for confparse.c module that we use to parse various + * Tests for confmgt.c module that we use to parse various * configuration/state file types. */ -#define CONFPARSE_PRIVATE +#define CONFMGT_PRIVATE #include "orconfig.h" #include "core/or/or.h" #include "lib/encoding/confline.h" #include "feature/nodelist/routerset.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "test/test.h" #include "test/log_test_helpers.h" @@ -103,12 +103,9 @@ static config_deprecation_t test_deprecation_notes[] = { }; static int -test_validate_cb(void *old_options, void *options, void *default_options, - int from_setconf, char **msg) +test_validate_cb(const void *old_options, void *options, char **msg) { (void)old_options; - (void)default_options; - (void)from_setconf; (void)msg; test_struct_t *ts = options; @@ -122,19 +119,17 @@ test_validate_cb(void *old_options, void *options, void *default_options, #define TEST_MAGIC 0x1337 static const config_format_t test_fmt = { - sizeof(test_struct_t), - { + .size = sizeof(test_struct_t), + .magic = { "test_struct_t", TEST_MAGIC, offsetof(test_struct_t, magic), }, - test_abbrevs, - test_deprecation_notes, - test_vars, - test_validate_cb, - NULL, - NULL, - -1, + .abbrevs = test_abbrevs, + .deprecations = test_deprecation_notes, + .vars = test_vars, + .legacy_validate_fn = test_validate_cb, + .config_suite_offset = -1, }; /* Make sure that config_init sets everything to the right defaults. */ @@ -818,19 +813,18 @@ static struct_member_t extra = { }; static config_format_t etest_fmt = { - sizeof(test_struct_t), - { + .size = sizeof(test_struct_t), + .magic = { "test_struct_t (with extra lines)", ETEST_MAGIC, offsetof(test_struct_t, magic), }, - test_abbrevs, - test_deprecation_notes, - test_vars, - test_validate_cb, - NULL, - &extra, - -1, + .abbrevs = test_abbrevs, + .deprecations = test_deprecation_notes, + .vars = test_vars, + .legacy_validate_fn = test_validate_cb, + .extra = &extra, + .config_suite_offset = -1, }; /* Try out the feature where we can store unrecognized lines and dump them @@ -1037,12 +1031,14 @@ test_confparse_find_option_name(void *arg) config_mgr_free(mgr); } +#ifndef COCCI #define CONFPARSE_TEST(name, flags) \ { #name, test_confparse_ ## name, flags, NULL, NULL } #define BADVAL_TEST(name) \ { "badval_" #name, test_confparse_assign_badval, 0, \ &passthrough_setup, (void*)&bv_ ## name } +#endif /* !defined(COCCI) */ struct testcase_t confparse_tests[] = { CONFPARSE_TEST(init, 0), diff --git a/src/test/test_connection.c b/src/test/test_connection.c index ebe7c6d36f..0d28276702 100644 --- a/src/test/test_connection.c +++ b/src/test/test_connection.c @@ -881,12 +881,14 @@ test_failed_orconn_tracker(void *arg) ; } +#ifndef COCCI #define CONNECTION_TESTCASE(name, fork, setup) \ { #name, test_conn_##name, fork, &setup, NULL } /* where arg is an expression (constant, variable, compound expression) */ #define CONNECTION_TESTCASE_ARG(name, fork, setup, arg) \ { #name "_" #arg, test_conn_##name, fork, &setup, (void *)arg } +#endif /* !defined(COCCI) */ struct testcase_t connection_tests[] = { CONNECTION_TESTCASE(get_basic, TT_FORK, test_conn_get_basic_st), diff --git a/src/test/test_controller.c b/src/test/test_controller.c index 55eb79e448..793696c474 100644 --- a/src/test/test_controller.c +++ b/src/test/test_controller.c @@ -27,6 +27,7 @@ #include "feature/dirclient/download_status_st.h" #include "feature/nodelist/microdesc_st.h" #include "feature/nodelist/node_st.h" +#include "feature/dircache/dirserv.c" typedef struct { const char *input; @@ -119,6 +120,7 @@ test_controller_parse_cmd(void *arg) control_cmd_args_free(result); } +#ifndef COCCI #define OK(inp, out) \ { inp "\r\n", out, NULL } #define ERR(inp, err) \ @@ -128,6 +130,7 @@ test_controller_parse_cmd(void *arg) { &syntax, \ ARRAY_LENGTH(array), \ array } +#endif /* !defined(COCCI) */ static const parser_testcase_t one_to_three_tests[] = { ERR("", "Need at least 1 argument(s)"), @@ -1691,6 +1694,138 @@ test_download_status_bridge(void *arg) return; } +/** Mock cached consensus */ +static cached_dir_t *mock_ns_consensus_cache; +static cached_dir_t *mock_microdesc_consensus_cache; + +/** Mock the function that retrieves consensus from cache. These use a + * global variable so that they can be cleared from within the test. + * The actual code retains the pointer to the consensus data, but + * we are doing this here, to prevent memory leaks + * from within the tests */ +static cached_dir_t * +mock_dirserv_get_consensus(const char *flavor_name) +{ + if (!strcmp(flavor_name, "ns")) { + mock_ns_consensus_cache = tor_malloc_zero(sizeof(cached_dir_t)); + mock_ns_consensus_cache->dir = tor_strdup("mock_ns_consensus"); + return mock_ns_consensus_cache; + } else { + mock_microdesc_consensus_cache = tor_malloc_zero(sizeof(cached_dir_t)); + mock_microdesc_consensus_cache->dir = tor_strdup( + "mock_microdesc_consensus"); + return mock_microdesc_consensus_cache; + } +} + +/** Mock the function that retrieves consensuses + * from a files in the directory. */ +static tor_mmap_t * +mock_tor_mmap_file(const char* filename) +{ + tor_mmap_t *res; + res = tor_malloc_zero(sizeof(tor_mmap_t)); + if (strstr(filename, "cached-consensus") != NULL) { + res->data = "mock_ns_consensus"; + } else if (strstr(filename, "cached-microdesc-consensus") != NULL) { + res->data = "mock_microdesc_consensus"; + } else { + res->data = "."; + } + res->size = strlen(res->data); + return res; +} + +/** Mock the function that clears file data + * loaded into the memory */ +static int +mock_tor_munmap_file(tor_mmap_t *handle) +{ + tor_free(handle); + return 0; +} + +static void +test_getinfo_helper_current_consensus_from_file(void *arg) +{ + /* We just need one of these to pass, it doesn't matter what's in it */ + control_connection_t dummy; + /* Get results out */ + char *answer = NULL; + const char *errmsg = NULL; + + (void)arg; + + MOCK(tor_mmap_file, mock_tor_mmap_file); + MOCK(tor_munmap_file, mock_tor_munmap_file); + + getinfo_helper_dir(&dummy, + "dir/status-vote/current/consensus", + &answer, + &errmsg); + tt_str_op(answer, OP_EQ, "mock_ns_consensus"); + tt_ptr_op(errmsg, OP_EQ, NULL); + tor_free(answer); + errmsg = NULL; + + getinfo_helper_dir(&dummy, + "dir/status-vote/current/consensus-microdesc", + &answer, + &errmsg); + tt_str_op(answer, OP_EQ, "mock_microdesc_consensus"); + tt_ptr_op(errmsg, OP_EQ, NULL); + errmsg = NULL; + + done: + tor_free(answer); + UNMOCK(tor_mmap_file); + UNMOCK(tor_munmap_file); + return; +} + +static void +test_getinfo_helper_current_consensus_from_cache(void *arg) +{ + /* We just need one of these to pass, it doesn't matter what's in it */ + control_connection_t dummy; + /* Get results out */ + char *answer = NULL; + const char *errmsg = NULL; + + (void)arg; + or_options_t *options = get_options_mutable(); + options->FetchUselessDescriptors = 1; + MOCK(dirserv_get_consensus, mock_dirserv_get_consensus); + + getinfo_helper_dir(&dummy, + "dir/status-vote/current/consensus", + &answer, + &errmsg); + tt_str_op(answer, OP_EQ, "mock_ns_consensus"); + tt_ptr_op(errmsg, OP_EQ, NULL); + tor_free(answer); + tor_free(mock_ns_consensus_cache->dir); + tor_free(mock_ns_consensus_cache); + errmsg = NULL; + + getinfo_helper_dir(&dummy, + "dir/status-vote/current/consensus-microdesc", + &answer, + &errmsg); + tt_str_op(answer, OP_EQ, "mock_microdesc_consensus"); + tt_ptr_op(errmsg, OP_EQ, NULL); + tor_free(mock_microdesc_consensus_cache->dir); + tor_free(answer); + errmsg = NULL; + + done: + options->FetchUselessDescriptors = 0; + tor_free(answer); + tor_free(mock_microdesc_consensus_cache); + UNMOCK(dirserv_get_consensus); + return; +} + /** Set timeval to a mock date and time. This is necessary * to make tor_gettimeofday() mockable. */ static void @@ -1820,9 +1955,11 @@ test_getinfo_md_all(void *arg) return; } +#ifndef COCCI #define PARSER_TEST(type) \ { "parse/" #type, test_controller_parse_cmd, 0, &passthrough_setup, \ (void*)&parse_ ## type ## _params } +#endif struct testcase_t controller_tests[] = { PARSER_TEST(one_to_three), @@ -1840,6 +1977,10 @@ struct testcase_t controller_tests[] = { NULL }, { "download_status_consensus", test_download_status_consensus, 0, NULL, NULL }, + {"getinfo_helper_current_consensus_from_cache", + test_getinfo_helper_current_consensus_from_cache, 0, NULL, NULL }, + {"getinfo_helper_current_consensus_from_file", + test_getinfo_helper_current_consensus_from_file, 0, NULL, NULL }, { "download_status_cert", test_download_status_cert, 0, NULL, NULL }, { "download_status_desc", test_download_status_desc, 0, NULL, NULL }, diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index 67940aeac5..2c57e50a4c 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -2971,6 +2971,7 @@ test_crypto_failure_modes(void *arg) ; } +#ifndef COCCI #define CRYPTO_LEGACY(name) \ { #name, test_crypto_ ## name , 0, NULL, NULL } @@ -2981,6 +2982,7 @@ test_crypto_failure_modes(void *arg) #define ED25519_TEST(name, fl) \ ED25519_TEST_ONE(name, (fl), "donna"), \ ED25519_TEST_ONE(name, (fl), "ref10") +#endif /* !defined(COCCI) */ struct testcase_t crypto_tests[] = { CRYPTO_LEGACY(formats), diff --git a/src/test/test_crypto_slow.c b/src/test/test_crypto_slow.c index 3b20dfa587..9ee7b100b3 100644 --- a/src/test/test_crypto_slow.c +++ b/src/test/test_crypto_slow.c @@ -584,6 +584,7 @@ test_crypto_ed25519_fuzz_donna(void *arg) ; } +#ifndef COCCI #define CRYPTO_LEGACY(name) \ { #name, test_crypto_ ## name , 0, NULL, NULL } @@ -594,6 +595,7 @@ test_crypto_ed25519_fuzz_donna(void *arg) #define ED25519_TEST(name, fl) \ ED25519_TEST_ONE(name, (fl), "donna"), \ ED25519_TEST_ONE(name, (fl), "ref10") +#endif /* !defined(COCCI) */ struct testcase_t slow_crypto_tests[] = { CRYPTO_LEGACY(s2k_rfc2440), diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 6329ff7750..02465b07f0 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -26,7 +26,7 @@ #include "core/or/or.h" #include "app/config/config.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "core/mainloop/connection.h" #include "core/or/relay.h" #include "core/or/versions.h" @@ -635,7 +635,6 @@ setup_dir_formats_options(const char *arg, or_options_t *options) STMT_BEGIN \ tt_assert(r1); \ tt_assert(rp1); \ -\ tt_int_op(rp1->addr,OP_EQ, r1->addr); \ tt_int_op(rp1->or_port,OP_EQ, r1->or_port); \ tt_int_op(rp1->dir_port,OP_EQ, r1->dir_port); \ @@ -7210,6 +7209,7 @@ test_dir_format_versions_list(void *arg) teardown_capture_of_logs(); } +#ifndef COCCI #define DIR_LEGACY(name) \ { #name, test_dir_ ## name , TT_FORK, NULL, NULL } @@ -7219,6 +7219,7 @@ test_dir_format_versions_list(void *arg) /* where arg is a string constant */ #define DIR_ARG(name,flags,arg) \ { #name "_" arg, test_dir_##name, (flags), &passthrough_setup, (void*) arg } +#endif /* !defined(COCCI) */ struct testcase_t dir_tests[] = { DIR_LEGACY(nicknames), 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_entryconn.c b/src/test/test_entryconn.c index 8f2d507743..c64c1e814a 100644 --- a/src/test/test_entryconn.c +++ b/src/test/test_entryconn.c @@ -11,7 +11,7 @@ #include "feature/client/addressmap.h" #include "app/config/config.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "core/mainloop/connection.h" #include "core/or/connection_edge.h" #include "feature/nodelist/nodelist.h" diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c index d59b1c7153..ca699b3cf1 100644 --- a/src/test/test_entrynodes.c +++ b/src/test/test_entrynodes.c @@ -18,7 +18,7 @@ #include "core/or/circuitlist.h" #include "core/or/circuitbuild.h" #include "app/config/config.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "lib/crypt_ops/crypto_rand.h" #include "feature/dircommon/directory.h" #include "feature/dirclient/dirclient.h" @@ -3039,6 +3039,7 @@ static const struct testcase_setup_t upgrade_circuits = { upgrade_circuits_setup, upgrade_circuits_cleanup }; +#ifndef COCCI #define NO_PREFIX_TEST(name) \ { #name, test_ ## name, 0, NULL, NULL } @@ -3061,6 +3062,7 @@ static const struct testcase_setup_t upgrade_circuits = { &upgrade_circuits, (void*)(arg REASONABLY_FUTURE) }, \ { #name "_reasonably_past", test_entry_guard_ ## name, TT_FORK, \ &upgrade_circuits, (void*)(arg REASONABLY_PAST) } +#endif /* !defined(COCCI) */ struct testcase_t entrynodes_tests[] = { NO_PREFIX_TEST(node_preferred_orport), diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c index 8eb3c2c928..29743a0d15 100644 --- a/src/test/test_helpers.c +++ b/src/test/test_helpers.c @@ -16,7 +16,7 @@ #include "lib/buf/buffers.h" #include "app/config/config.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "app/main/subsysmgr.h" #include "core/mainloop/connection.h" #include "lib/crypt_ops/crypto_rand.h" diff --git a/src/test/test_hs_ntor.sh b/src/test/test_hs_ntor.sh index 8a0003d44a..ee7141cc9a 100755 --- a/src/test/test_hs_ntor.sh +++ b/src/test/test_hs_ntor.sh @@ -3,7 +3,7 @@ exitcode=0 -# Run the python integration test sand return the exitcode of the python +# Run the python integration tests and return the exitcode of the python # script. The python script might ask the testsuite to skip it if not all # python dependencies are covered. "${PYTHON:-python}" "${abs_top_srcdir:-.}/src/test/hs_ntor_ref.py" || exitcode=$? diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c index 66194cee3d..45c8cb9846 100644 --- a/src/test/test_hs_service.c +++ b/src/test/test_hs_service.c @@ -1013,7 +1013,6 @@ test_intro_established(void *arg) /* Send an empty payload. INTRO_ESTABLISHED cells are basically zeroes. */ ret = hs_service_receive_intro_established(circ, payload, sizeof(payload)); tt_int_op(ret, OP_EQ, 0); - tt_u64_op(ip->circuit_established, OP_EQ, 1); tt_int_op(TO_CIRCUIT(circ)->purpose, OP_EQ, CIRCUIT_PURPOSE_S_INTRO); done: @@ -1296,18 +1295,11 @@ test_service_event(void *arg) * descriptor map so we can retry it. */ ip = helper_create_service_ip(); service_intro_point_add(service->desc_current->intro_points.map, ip); - ip->circuit_established = 1; /* We'll test that, it MUST be 0 after. */ - run_housekeeping_event(now); - tt_int_op(digest256map_size(service->desc_current->intro_points.map), - OP_EQ, 1); - /* No removal if we have an established circuit after retries. */ - ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES + 1; run_housekeeping_event(now); tt_int_op(digest256map_size(service->desc_current->intro_points.map), OP_EQ, 1); /* Remove the IP object at once for the next test. */ ip->circuit_retries = MAX_INTRO_POINT_CIRCUIT_RETRIES + 1; - ip->circuit_established = 0; run_housekeeping_event(now); tt_int_op(digest256map_size(service->desc_current->intro_points.map), OP_EQ, 0); diff --git a/src/test/test_key_expiration.sh b/src/test/test_key_expiration.sh index 54abb4a2fa..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,11 +35,21 @@ 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 fi if [ $# -ge 1 ]; then diff --git a/src/test/test_keygen.sh b/src/test/test_keygen.sh index cbdfd1909c..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,14 +35,22 @@ 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 +fi if [ $# -ge 1 ]; then dflt=0 diff --git a/src/test/test_link_handshake.c b/src/test/test_link_handshake.c index 5e78e1ce4d..18c1700031 100644 --- a/src/test/test_link_handshake.c +++ b/src/test/test_link_handshake.c @@ -1492,6 +1492,7 @@ AUTHENTICATE_FAIL(missing_ed_auth, "authentication certificate"; }) +#ifndef COCCI #define TEST_RSA(name, flags) \ { #name , test_link_handshake_ ## name, (flags), \ &passthrough_setup, (void*)"RSA" } @@ -1527,6 +1528,7 @@ AUTHENTICATE_FAIL(missing_ed_auth, #define TEST_AUTHENTICATE_ED(name) \ { "authenticate/" #name "_ed25519" , test_link_handshake_auth_ ## name, \ TT_FORK, &setup_authenticate, (void*)3 } +#endif /* !defined(COCCI) */ struct testcase_t link_handshake_tests[] = { TEST_RSA(certs_ok, TT_FORK), diff --git a/src/test/test_options.c b/src/test/test_options.c index 69407a999b..c06fb998fb 100644 --- a/src/test/test_options.c +++ b/src/test/test_options.c @@ -4,9 +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/confparse.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" @@ -91,16 +95,57 @@ clear_log_messages(void) messages = NULL; } -#define setup_options(opt,dflt) \ +#define setup_options(opt) \ do { \ opt = options_new(); \ opt->command = CMD_RUN_TOR; \ options_init(opt); \ - \ - dflt = config_dup(get_options_mgr(), opt); \ - clear_log_messages(); \ } 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" @@ -180,12 +225,11 @@ test_options_validate_impl(const char *configuration, int phase) { or_options_t *opt=NULL; - or_options_t *dflt; config_line_t *cl=NULL; char *msg=NULL; int r; - setup_options(opt, dflt); + setup_options(opt); r = config_get_lines(configuration, &cl, 1); if (phase == PH_GETLINES) { @@ -208,7 +252,7 @@ test_options_validate_impl(const char *configuration, if (r) goto done; - r = options_validate(NULL, opt, dflt, 0, &msg); + r = options_validate(NULL, opt, &msg); if (phase == PH_VALIDATE) { if (test_options_checkmsgs(configuration, expect_errmsg, expect_log_severity, @@ -222,7 +266,6 @@ test_options_validate_impl(const char *configuration, policies_free_all(); config_free_lines(cl); or_options_free(opt); - or_options_free(dflt); tor_free(msg); clear_log_messages(); } @@ -294,15 +337,13 @@ test_have_enough_mem_for_dircache(void *arg) { (void)arg; or_options_t *opt=NULL; - or_options_t *dflt=NULL; config_line_t *cl=NULL; char *msg=NULL; int r; const char *configuration = "ORPort 8080\nDirCache 1", *expect_errmsg; - setup_options(opt, dflt); + setup_options(opt); setup_log_callback(); - (void)dflt; r = config_get_lines(configuration, &cl, 1); tt_int_op(r, OP_EQ, 0); @@ -376,7 +417,6 @@ test_have_enough_mem_for_dircache(void *arg) done: if (msg) tor_free(msg); - or_options_free(dflt); or_options_free(opt); config_free_lines(cl); return; @@ -390,33 +430,8 @@ fixed_get_uname(void) return fixed_get_uname_result; } -#define TEST_OPTIONS_OLD_VALUES "TestingV3AuthInitialVotingInterval 1800\n" \ - "ClientBootstrapConsensusMaxInProgressTries 3\n" \ - "TestingV3AuthInitialVoteDelay 300\n" \ - "TestingV3AuthInitialDistDelay 300\n" \ - "TestingClientMaxIntervalWithoutRequest 600\n" \ - "TestingDirConnectionMaxStall 600\n" \ - -#define TEST_OPTIONS_DEFAULT_VALUES TEST_OPTIONS_OLD_VALUES \ - "MaxClientCircuitsPending 1\n" \ - "RendPostPeriod 1000\n" \ - "KeepAlivePeriod 1\n" \ - "ConnLimit 1\n" \ - "V3AuthVotingInterval 300\n" \ - "V3AuthVoteDelay 20\n" \ - "V3AuthDistDelay 20\n" \ - "V3AuthNIntervalsValid 3\n" \ - "ClientUseIPv4 1\n" \ - "VirtualAddrNetworkIPv4 127.192.0.0/10\n" \ - "VirtualAddrNetworkIPv6 [FE80::]/10\n" \ - "UseEntryGuards 1\n" \ - "Schedulers Vanilla\n" \ - "ClientDNSRejectInternalAddresses 1\n" - typedef struct { - or_options_t *old_opt; or_options_t *opt; - or_options_t *def_opt; } options_test_data_t; static void free_options_test_data(options_test_data_t *td); @@ -429,15 +444,8 @@ get_options_test_data(const char *conf) config_line_t *cl=NULL; options_test_data_t *result = tor_malloc(sizeof(options_test_data_t)); result->opt = options_new(); - result->old_opt = options_new(); - result->def_opt = options_new(); - // XXX: Really, all of these options should be set to defaults - // with options_init(), but about a dozen tests break when I do that. - // Being kinda lame and just fixing the immedate breakage for now.. - result->opt->ConnectionPadding = -1; // default must be "auto" - result->opt->DormantClientTimeout = 1800; // must be over 600. - result->opt->CircuitPadding = 1; // default must be "1" + options_init(result->opt); rv = config_get_lines(conf, &cl, 1); tt_int_op(rv, OP_EQ, 0); @@ -450,13 +458,7 @@ get_options_test_data(const char *conf) config_free_lines(cl); result->opt->LogTimeGranularity = 1; result->opt->TokenBucketRefillInterval = 1; - rv = config_get_lines(TEST_OPTIONS_OLD_VALUES, &cl, 1); - tt_int_op(rv, OP_EQ, 0); - rv = config_assign(get_options_mgr(), result->def_opt, cl, 0, &msg); - if (msg) { - /* Display the parse error message by comparing it with an empty string */ - tt_str_op(msg, OP_EQ, ""); - } + rv = config_get_lines("", &cl, 1); tt_int_op(rv, OP_EQ, 0); done: @@ -475,9 +477,7 @@ static void free_options_test_data(options_test_data_t *td) { if (!td) return; - or_options_free(td->old_opt); or_options_free(td->opt); - or_options_free(td->def_opt); tor_free(td); } @@ -499,7 +499,7 @@ test_options_validate__uname_for_server(void *ignored) MOCK(get_uname, fixed_get_uname); fixed_get_uname_result = "Windows 95"; - options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + options_validate(NULL, tdata->opt, &msg); expect_log_msg("Tor is running as a server, but you" " are running Windows 95; this probably won't work. See https://www" ".torproject.org/docs/faq.html#BestOSForRelay for details.\n"); @@ -507,7 +507,7 @@ test_options_validate__uname_for_server(void *ignored) fixed_get_uname_result = "Windows 98"; mock_clean_saved_logs(); - options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + options_validate(NULL, tdata->opt, &msg); expect_log_msg("Tor is running as a server, but you" " are running Windows 98; this probably won't work. See https://www" ".torproject.org/docs/faq.html#BestOSForRelay for details.\n"); @@ -515,7 +515,7 @@ test_options_validate__uname_for_server(void *ignored) fixed_get_uname_result = "Windows Me"; mock_clean_saved_logs(); - options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + options_validate(NULL, tdata->opt, &msg); expect_log_msg("Tor is running as a server, but you" " are running Windows Me; this probably won't work. See https://www" ".torproject.org/docs/faq.html#BestOSForRelay for details.\n"); @@ -523,8 +523,8 @@ test_options_validate__uname_for_server(void *ignored) fixed_get_uname_result = "Windows 2000"; mock_clean_saved_logs(); - options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - expect_no_log_entry(); + options_validate(NULL, tdata->opt, &msg); + expect_no_log_msg("Tor is running as a server, but you "); tor_free(msg); done: @@ -547,7 +547,7 @@ test_options_validate__outbound_addresses(void *ignored) options_test_data_t *tdata = get_options_test_data( "OutboundBindAddress xxyy!!!sdfaf"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Multiple outbound bind addresses configured: " "xxyy!!!sdfaf"); @@ -584,7 +584,7 @@ test_options_validate__data_directory(void *ignored) "ONGLONGlongreallylongLONG" "LONG"); // 440 characters - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Invalid DataDirectory"); @@ -602,7 +602,7 @@ test_options_validate__nickname(void *ignored) options_test_data_t *tdata = get_options_test_data( "Nickname ThisNickNameIsABitTooLong"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Nickname 'ThisNickNameIsABitTooLong', nicknames must be between " @@ -612,16 +612,14 @@ test_options_validate__nickname(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("Nickname AMoreValidNick"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); - tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("DataDirectory /tmp/somewhere"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); - tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); done: free_options_test_data(tdata); @@ -639,8 +637,8 @@ test_options_validate__contactinfo(void *ignored) setup_capture_of_logs(LOG_DEBUG); tdata->opt->ContactInfo = NULL; - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); expect_log_msg( "Your ContactInfo config option is not" " set. Please consider setting it, so we can contact you if your" @@ -651,8 +649,8 @@ test_options_validate__contactinfo(void *ignored) tdata = get_options_test_data("ORPort 127.0.0.1:5555\n" "ContactInfo hella@example.org"); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "Your ContactInfo config option is not" " set. Please consider setting it, so we can contact you if your" @@ -677,50 +675,53 @@ test_options_validate__logs(void *ignored) tdata->opt->Logs = NULL; tdata->opt->RunAsDaemon = 0; - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_str_op(tdata->opt->Logs->key, OP_EQ, "Log"); - tt_str_op(tdata->opt->Logs->value, OP_EQ, "notice stdout"); + ret = options_validate(NULL, tdata->opt, &msg); + tt_assert(!tdata->opt->Logs); tor_free(msg); - tt_int_op(ret, OP_EQ, -1); + tt_int_op(ret, OP_EQ, 0); free_options_test_data(tdata); tdata = get_options_test_data(""); tdata->opt->Logs = NULL; tdata->opt->RunAsDaemon = 0; quiet_level = 1; - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_str_op(tdata->opt->Logs->key, OP_EQ, "Log"); - tt_str_op(tdata->opt->Logs->value, OP_EQ, "warn stdout"); + ret = options_validate(NULL, tdata->opt, &msg); + tt_assert(!tdata->opt->Logs); tor_free(msg); - tt_int_op(ret, OP_EQ, -1); + tt_int_op(ret, OP_EQ, 0); free_options_test_data(tdata); tdata = get_options_test_data(""); tdata->opt->Logs = NULL; tdata->opt->RunAsDaemon = 0; quiet_level = 2; - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_assert(!tdata->opt->Logs); tor_free(msg); - tt_int_op(ret, OP_EQ, -1); + tt_int_op(ret, OP_EQ, 0); free_options_test_data(tdata); tdata = get_options_test_data(""); tdata->opt->Logs = NULL; tdata->opt->RunAsDaemon = 0; - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 1, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_assert(!tdata->opt->Logs); tor_free(msg); - tt_int_op(ret, OP_EQ, -1); + tt_int_op(ret, OP_EQ, 0); free_options_test_data(tdata); tdata = get_options_test_data(""); tdata->opt->Logs = NULL; tdata->opt->RunAsDaemon = 1; - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_assert(!tdata->opt->Logs); tor_free(msg); +#ifdef _WIN32 + /* Can't RunAsDaemon on Windows. */ tt_int_op(ret, OP_EQ, -1); +#else + tt_int_op(ret, OP_EQ, 0); +#endif /* defined(_WIN32) */ free_options_test_data(tdata); tdata = get_options_test_data(""); @@ -728,7 +729,7 @@ test_options_validate__logs(void *ignored) config_line_t *cl=NULL; config_get_lines("Log foo", &cl, 1); tdata->opt->Logs = cl; - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op((intptr_t)tdata->opt->Logs, OP_EQ, (intptr_t)cl); tt_int_op(ret, OP_EQ, -1); @@ -756,13 +757,13 @@ 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(); MOCK(tor_addr_lookup, mock_tor_addr_lookup__fail_on_bad_addrs); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); UNMOCK(tor_addr_lookup); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Failed to resolve/guess local address. See logs for" @@ -772,245 +773,222 @@ 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(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Authoritative directory servers must set " "ContactInfo"); 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(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Authoritative directory servers must set ContactInfo"); 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(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); 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" - "ContactInfo hello@hello.com\n"); + tdata = get_options_test_data(ENABLE_AUTHORITY); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); 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" - "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(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + options_validate(NULL, tdata->opt, &msg); tt_str_op(tdata->opt->RecommendedClientVersions->value, OP_EQ, "1.2, 3.14"); tt_str_op(tdata->opt->RecommendedServerVersions->value, OP_EQ, "1.2, 3.14"); 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(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + options_validate(NULL, tdata->opt, &msg); tt_str_op(tdata->opt->RecommendedClientVersions->value, OP_EQ, "25"); tt_str_op(tdata->opt->RecommendedServerVersions->value, OP_EQ, "4.18"); 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(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + 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" + 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(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + options_validate(NULL, tdata->opt, &msg); tt_str_op(msg, OP_EQ, "Versioning authoritative dir servers must set " "Recommended*Versions."); 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(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + options_validate(NULL, tdata->opt, &msg); tt_str_op(msg, OP_EQ, "Versioning authoritative dir servers must set " "Recommended*Versions."); 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(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + options_validate(NULL, tdata->opt, &msg); expect_log_msg("Authoritative directory servers " "can't set UseEntryGuards. Disabling.\n"); tt_int_op(tdata->opt->UseEntryGuards, OP_EQ, 0); 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(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + options_validate(NULL, tdata->opt, &msg); expect_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" - "DownloadExtraInfo 1\n" - "V3AuthoritativeDir 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(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &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); + options_validate(NULL, tdata->opt, &msg); + 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" - "ContactInfo hello@hello.com\n"); + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 + "GuardfractionFile non-existent-file\n"); mock_clean_saved_logs(); - options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_str_op(msg, OP_EQ, "AuthoritativeDir is set, but none of (Bridge/V3)" - "AuthoritativeDir is set."); + options_validate(NULL, tdata->opt, &msg); + 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" - "V3BandwidthsFile non-existent-file\n"); + "ORPort 2000\n" + "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); - options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + 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("AuthoritativeDirectory 1\n" + tdata = get_options_test_data(ENABLE_AUTHORITY_BRIDGE_MIN "Address 100.200.10.1\n" - "BridgeAuthoritativeDir 1\n" - "ContactInfo hello@hello.com\n" - "V3BandwidthsFile non-existent-file\n"); + "ORPort 2000\n" + "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); - options_validate(NULL, tdata->opt, tdata->def_opt, 0, &msg); + 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("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"); + "DirPort 999\n" + "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); - options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + 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."); + "Running as authoritative directory, but no ORPort set."); 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" - "BridgeAuthoritativeDir 1\n" - "ContactInfo hello@hello.com\n" - "GuardfractionFile non-existent-file\n"); + "DirPort 999\n" + "ContactInfo hello@hello.com\n"); mock_clean_saved_logs(); - options_validate(NULL, tdata->opt, tdata->def_opt, 0, &msg); + 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."); + "Running as authoritative directory, but no ORPort 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 + "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(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + 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 no DirPort set."); + 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("AuthoritativeDirectory 1\n" - "Address 100.200.10.1\n" - "DirPort 999\n" - "BridgeAuthoritativeDir 1\n" - "ContactInfo hello@hello.com\n"); + 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(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + 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 no ORPort set."); + tt_str_op(msg, OP_EQ, "Running as authoritative directory, " + "but ClientOnly also 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(tdata->old_opt, 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_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(); @@ -1024,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" @@ -1032,7 +1011,8 @@ test_options_validate__relay_with_hidden_services(void *ignored) "HiddenServicePort 80 127.0.0.1:8080\n" ); - options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &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" @@ -1045,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(tdata->old_opt, 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) @@ -1079,15 +1057,15 @@ test_options_validate__transproxy(void *ignored) // Test default trans proxy tdata = get_options_test_data("TransProxyType default\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->TransProxyType_parsed, OP_EQ, TPT_DEFAULT); tor_free(msg); // Test pf-divert trans proxy free_options_test_data(tdata); tdata = get_options_test_data("TransProxyType pf-divert\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); #if !defined(OpenBSD) && !defined( DARWIN ) @@ -1103,7 +1081,7 @@ test_options_validate__transproxy(void *ignored) // Test tproxy trans proxy free_options_test_data(tdata); tdata = get_options_test_data("TransProxyType tproxy\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); #if !defined(__linux__) @@ -1118,7 +1096,7 @@ test_options_validate__transproxy(void *ignored) // Test ipfw trans proxy free_options_test_data(tdata); tdata = get_options_test_data("TransProxyType ipfw\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); #ifndef KERNEL_MAY_SUPPORT_IPFW @@ -1134,7 +1112,7 @@ test_options_validate__transproxy(void *ignored) // Test unknown trans proxy free_options_test_data(tdata); tdata = get_options_test_data("TransProxyType non-existent\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Unrecognized value for TransProxyType"); tor_free(msg); @@ -1146,29 +1124,25 @@ test_options_validate__transproxy(void *ignored) #if defined(__linux__) tdata = get_options_test_data("TransProxyType tproxy\n" "TransPort 127.0.0.1:123\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); - tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); #elif defined(KERNEL_MAY_SUPPORT_IPFW) tdata = get_options_test_data("TransProxyType ipfw\n" "TransPort 127.0.0.1:123\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); - tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tor_free(msg); #elif defined(OpenBSD) tdata = get_options_test_data("TransProxyType pf-divert\n" "TransPort 127.0.0.1:123\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); - tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tor_free(msg); #elif defined(__NetBSD__) tdata = get_options_test_data("TransProxyType default\n" "TransPort 127.0.0.1:123\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); - tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tor_free(msg); #endif /* defined(__linux__) || ... */ @@ -1178,7 +1152,7 @@ test_options_validate__transproxy(void *ignored) #else /* !defined(USE_TRANSPARENT) */ tdata = get_options_test_data("TransPort 127.0.0.1:555\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TransPort is disabled in this build."); tor_free(msg); @@ -1213,8 +1187,8 @@ test_options_validate__exclude_nodes(void *ignored) options_test_data_t *tdata = get_options_test_data( "ExcludeExitNodes {us}\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(tdata->opt->ExcludeExitNodesUnion_->list), OP_EQ, 1); tt_str_op((char *) (smartlist_get(tdata->opt->ExcludeExitNodesUnion_->list, 0)), @@ -1223,8 +1197,8 @@ test_options_validate__exclude_nodes(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("ExcludeNodes {cn}\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(tdata->opt->ExcludeExitNodesUnion_->list), OP_EQ, 1); tt_str_op((char *) (smartlist_get(tdata->opt->ExcludeExitNodesUnion_->list, 0)), @@ -1234,8 +1208,8 @@ test_options_validate__exclude_nodes(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("ExcludeNodes {cn}\n" "ExcludeExitNodes {us} {cn}\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tt_int_op(smartlist_len(tdata->opt->ExcludeExitNodesUnion_->list), OP_EQ, 2); tt_str_op((char *) (smartlist_get(tdata->opt->ExcludeExitNodesUnion_->list, 0)), @@ -1249,8 +1223,8 @@ test_options_validate__exclude_nodes(void *ignored) tdata = get_options_test_data("ExcludeNodes {cn}\n" "StrictNodes 1\n"); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); expect_log_msg( "You have asked to exclude certain relays from all positions " "in your circuits. Expect hidden services and other Tor " @@ -1260,8 +1234,8 @@ test_options_validate__exclude_nodes(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("ExcludeNodes {cn}\n"); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "You have asked to exclude certain relays from all positions " "in your circuits. Expect hidden services and other Tor " @@ -1285,8 +1259,8 @@ test_options_validate__node_families(void *ignored) "NodeFamily flux, flax\n" "NodeFamily somewhere\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tt_assert(tdata->opt->NodeFamilySets); tt_int_op(smartlist_len(tdata->opt->NodeFamilySets), OP_EQ, 2); tt_str_op((char *)(smartlist_get( @@ -1303,15 +1277,15 @@ test_options_validate__node_families(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data(""); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tt_assert(!tdata->opt->NodeFamilySets); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("NodeFamily !flux\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_assert(tdata->opt->NodeFamilySets); tt_int_op(smartlist_len(tdata->opt->NodeFamilySets), OP_EQ, 0); @@ -1331,14 +1305,14 @@ test_options_validate__token_bucket(void *ignored) options_test_data_t *tdata = get_options_test_data(""); tdata->opt->TokenBucketRefillInterval = 0; - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TokenBucketRefillInterval must be between 1 and 1000 inclusive."); tor_free(msg); tdata->opt->TokenBucketRefillInterval = 1001; - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TokenBucketRefillInterval must be between 1 and 1000 inclusive."); @@ -1359,7 +1333,7 @@ test_options_validate__fetch_dir(void *ignored) "FetchDirInfoExtraEarly 1\n" "FetchDirInfoEarly 0\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "FetchDirInfoExtraEarly requires that you" " also set FetchDirInfoEarly"); @@ -1369,10 +1343,8 @@ test_options_validate__fetch_dir(void *ignored) tdata = get_options_test_data("FetchDirInfoExtraEarly 1\n" "FetchDirInfoEarly 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); - tt_str_op(msg, OP_NE, "FetchDirInfoExtraEarly requires that you" - " also set FetchDirInfoEarly"); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tor_free(msg); done: @@ -1389,7 +1361,7 @@ test_options_validate__conn_limit(void *ignored) options_test_data_t *tdata = get_options_test_data( "ConnLimit 0\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "ConnLimit must be greater than 0, but was set to 0"); tor_free(msg); @@ -1397,10 +1369,8 @@ test_options_validate__conn_limit(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("ConnLimit 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); - tt_str_op(msg, OP_EQ, "MaxClientCircuitsPending must be between 1 and 1024, " - "but was set to 0"); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tor_free(msg); done: @@ -1423,11 +1393,10 @@ test_options_validate__paths_needed(void *ignored) setup_capture_of_logs(LOG_WARN); options_test_data_t *tdata = get_options_test_data( - "PathsNeededToBuildCircuits 0.1\n" - "ConnLimit 1\n"); + "PathsNeededToBuildCircuits 0.1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tt_assert(tdata->opt->PathsNeededToBuildCircuits > 0.24 && tdata->opt->PathsNeededToBuildCircuits < 0.26); expect_log_msg("PathsNeededToBuildCircuits is too low. " @@ -1436,11 +1405,10 @@ test_options_validate__paths_needed(void *ignored) free_options_test_data(tdata); mock_clean_saved_logs(); - tdata = get_options_test_data("PathsNeededToBuildCircuits 0.99\n" - "ConnLimit 1\n"); + tdata = get_options_test_data("PathsNeededToBuildCircuits 0.99\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tt_assert(tdata->opt->PathsNeededToBuildCircuits > 0.94 && tdata->opt->PathsNeededToBuildCircuits < 0.96); expect_log_msg("PathsNeededToBuildCircuits is " @@ -1449,14 +1417,13 @@ test_options_validate__paths_needed(void *ignored) free_options_test_data(tdata); mock_clean_saved_logs(); - tdata = get_options_test_data("PathsNeededToBuildCircuits 0.91\n" - "ConnLimit 1\n"); + tdata = get_options_test_data("PathsNeededToBuildCircuits 0.91\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tt_assert(tdata->opt->PathsNeededToBuildCircuits > 0.90 && tdata->opt->PathsNeededToBuildCircuits < 0.92); - expect_no_log_entry(); + expect_no_log_msg_containing("PathsNeededToBuildCircuits"); tor_free(msg); done: @@ -1476,32 +1443,28 @@ test_options_validate__max_client_circuits(void *ignored) int ret; char *msg; options_test_data_t *tdata = get_options_test_data( - "MaxClientCircuitsPending 0\n" - "ConnLimit 1\n"); + "MaxClientCircuitsPending 0\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "MaxClientCircuitsPending must be between 1 and 1024," " but was set to 0"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("MaxClientCircuitsPending 1025\n" - "ConnLimit 1\n"); + tdata = get_options_test_data("MaxClientCircuitsPending 1025\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "MaxClientCircuitsPending must be between 1 and 1024," " but was set to 1025"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + tdata = get_options_test_data("MaxClientCircuitsPending 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); - tt_str_op(msg, OP_EQ, "KeepalivePeriod option must be positive."); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tor_free(msg); done: @@ -1515,23 +1478,18 @@ test_options_validate__ports(void *ignored) (void)ignored; int ret; char *msg; - options_test_data_t *tdata = get_options_test_data( - "FirewallPorts 65537\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + options_test_data_t *tdata = get_options_test_data("FirewallPorts 65537\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Port '65537' out of range in FirewallPorts"); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("FirewallPorts 1\n" - "LongLivedPorts 124444\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + "LongLivedPorts 124444\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Port '124444' out of range in LongLivedPorts"); tor_free(msg); @@ -1539,11 +1497,9 @@ test_options_validate__ports(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("FirewallPorts 1\n" "LongLivedPorts 2\n" - "RejectPlaintextPorts 112233\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + "RejectPlaintextPorts 112233\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Port '112233' out of range in RejectPlaintextPorts"); tor_free(msg); @@ -1552,11 +1508,9 @@ test_options_validate__ports(void *ignored) tdata = get_options_test_data("FirewallPorts 1\n" "LongLivedPorts 2\n" "RejectPlaintextPorts 3\n" - "WarnPlaintextPorts 65536\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + "WarnPlaintextPorts 65536\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Port '65536' out of range in WarnPlaintextPorts"); tor_free(msg); @@ -1565,13 +1519,10 @@ test_options_validate__ports(void *ignored) tdata = get_options_test_data("FirewallPorts 1\n" "LongLivedPorts 2\n" "RejectPlaintextPorts 3\n" - "WarnPlaintextPorts 4\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + "WarnPlaintextPorts 4\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); - tt_str_op(msg, OP_EQ, "KeepalivePeriod option must be positive."); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tor_free(msg); done: @@ -1586,13 +1537,10 @@ test_options_validate__reachable_addresses(void *ignored) int ret; char *msg; setup_capture_of_logs(LOG_NOTICE); - options_test_data_t *tdata = get_options_test_data( - "FascistFirewall 1\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + options_test_data_t *tdata = get_options_test_data("FascistFirewall 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); expect_log_msg("Converting FascistFirewall config " "option to new format: \"ReachableDirAddresses *:80\"\n"); tt_str_op(tdata->opt->ReachableDirAddresses->value, OP_EQ, "*:80"); @@ -1605,13 +1553,17 @@ test_options_validate__reachable_addresses(void *ignored) mock_clean_saved_logs(); tdata = get_options_test_data("FascistFirewall 1\n" "ReachableDirAddresses *:81\n" - "ReachableORAddresses *:444\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); - tdata->opt->FirewallPorts = smartlist_new(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + "ReachableORAddresses *:444\n"); + tt_assert(tdata->opt->FirewallPorts); + SMARTLIST_FOREACH(tdata->opt->FirewallPorts, char *, cp, tor_free(cp)); + smartlist_clear(tdata->opt->FirewallPorts); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); +#if 0 + /* This does not actually produce any logs, and did not produce any relevant + * logs before. */ expect_log_entry(); +#endif tt_str_op(tdata->opt->ReachableDirAddresses->value, OP_EQ, "*:81"); tt_str_op(tdata->opt->ReachableORAddresses->value, OP_EQ, "*:444"); tor_free(msg); @@ -1619,12 +1571,10 @@ test_options_validate__reachable_addresses(void *ignored) free_options_test_data(tdata); mock_clean_saved_logs(); tdata = get_options_test_data("FascistFirewall 1\n" - "FirewallPort 123\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + "FirewallPort 123\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); expect_log_msg("Converting FascistFirewall and " "FirewallPorts config options to new format: " "\"ReachableAddresses *:123\"\n"); @@ -1636,25 +1586,25 @@ test_options_validate__reachable_addresses(void *ignored) tdata = get_options_test_data("FascistFirewall 1\n" "ReachableAddresses *:82\n" "ReachableAddresses *:83\n" - "ReachableAddresses reject *:*\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + "ReachableAddresses reject *:*\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); +#if 0 + /* This does not actually produce any logs, and did not produce any relevant + * logs before. */ expect_log_entry(); +#endif tt_str_op(tdata->opt->ReachableAddresses->value, OP_EQ, "*:82"); tor_free(msg); free_options_test_data(tdata); mock_clean_saved_logs(); tdata = get_options_test_data("FascistFirewall 1\n" - "ReachableAddresses *:82\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + "ReachableAddresses *:82\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tt_ptr_op(tdata->opt->ReachableAddresses->next, OP_EQ, NULL); tor_free(msg); @@ -1664,44 +1614,36 @@ test_options_validate__reachable_addresses(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("ReachableAddresses *:82\n" - "ORPort 127.0.0.1:5555\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + "ORPort 127.0.0.1:5555\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, SERVERS_REACHABLE_MSG); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("ReachableORAddresses *:82\n" - "ORPort 127.0.0.1:5555\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + "ORPort 127.0.0.1:5555\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, SERVERS_REACHABLE_MSG); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("ReachableDirAddresses *:82\n" - "ORPort 127.0.0.1:5555\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + "ORPort 127.0.0.1:5555\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, SERVERS_REACHABLE_MSG); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data("ClientUseIPv4 0\n" - "ORPort 127.0.0.1:5555\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + "ORPort 127.0.0.1:5555\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, SERVERS_REACHABLE_MSG); tor_free(msg); @@ -1709,74 +1651,68 @@ test_options_validate__reachable_addresses(void *ignored) /* Test IPv4-only clients setting IPv6 preferences */ free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ClientUseIPv4 1\n" + tdata = get_options_test_data("ClientUseIPv4 1\n" "ClientUseIPv6 0\n" "UseBridges 0\n" "ClientPreferIPv6ORPort 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ClientUseIPv4 1\n" + tdata = get_options_test_data("ClientUseIPv4 1\n" "ClientUseIPv6 0\n" "UseBridges 0\n" "ClientPreferIPv6DirPort 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); /* Now test an IPv4/IPv6 client setting IPv6 preferences */ free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ClientUseIPv4 1\n" + tdata = get_options_test_data("ClientUseIPv4 1\n" "ClientUseIPv6 1\n" "ClientPreferIPv6ORPort 1\n" "ClientPreferIPv6DirPort 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); /* Now test an IPv6 client setting IPv6 preferences */ free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ClientUseIPv6 1\n" + tdata = get_options_test_data("ClientUseIPv6 1\n" "ClientPreferIPv6ORPort 1\n" "ClientPreferIPv6DirPort 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); /* And an implicit (IPv4 disabled) IPv6 client setting IPv6 preferences */ free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ClientUseIPv4 0\n" + tdata = get_options_test_data("ClientUseIPv4 0\n" "ClientPreferIPv6ORPort 1\n" "ClientPreferIPv6DirPort 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); /* And an implicit (bridge) client setting IPv6 preferences */ free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "UseBridges 1\n" + tdata = get_options_test_data("UseBridges 1\n" "Bridge 127.0.0.1:12345\n" "ClientPreferIPv6ORPort 1\n" "ClientPreferIPv6DirPort 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); @@ -1795,22 +1731,18 @@ test_options_validate__use_bridges(void *ignored) options_test_data_t *tdata = get_options_test_data( "UseBridges 1\n" "ClientUseIPv4 1\n" - "ORPort 127.0.0.1:5555\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + "ORPort 127.0.0.1:5555\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Servers must be able to freely connect to the rest of" " the Internet, so they must not set UseBridges."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("UseBridges 1\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + tdata = get_options_test_data("UseBridges 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_NE, "Servers must be able to freely connect to the rest of" " the Internet, so they must not set UseBridges."); @@ -1819,46 +1751,41 @@ test_options_validate__use_bridges(void *ignored) NS_MOCK(geoip_get_country); free_options_test_data(tdata); tdata = get_options_test_data("UseBridges 1\n" - "EntryNodes {cn}\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + "EntryNodes {cn}\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "You cannot set both UseBridges and EntryNodes."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "UseBridges 1\n"); + tdata = get_options_test_data("UseBridges 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "If you set UseBridges, you must specify at least one bridge."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "UseBridges 1\n" + tdata = get_options_test_data("UseBridges 1\n" "Bridge 10.0.0.1\n" "UseEntryGuards 0\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Setting UseBridges requires also setting UseEntryGuards."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "UseBridges 1\n" + tdata = get_options_test_data("UseBridges 1\n" "Bridge 10.0.0.1\n" "Bridge !!!\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Bridge line did not parse. See logs for details."); tor_free(msg); @@ -1879,11 +1806,9 @@ test_options_validate__entry_nodes(void *ignored) NS_MOCK(geoip_get_country); options_test_data_t *tdata = get_options_test_data( "EntryNodes {cn}\n" - "UseEntryGuards 0\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + "UseEntryGuards 0\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "If EntryNodes is set, UseEntryGuards must be enabled."); @@ -1891,13 +1816,10 @@ test_options_validate__entry_nodes(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("EntryNodes {cn}\n" - "UseEntryGuards 1\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + "UseEntryGuards 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); - tt_str_op(msg, OP_EQ, "KeepalivePeriod option must be positive."); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tor_free(msg); done: @@ -1912,51 +1834,41 @@ test_options_validate__safe_logging(void *ignored) (void)ignored; int ret; char *msg; - options_test_data_t *tdata = get_options_test_data( - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + options_test_data_t *tdata = get_options_test_data("SafeLogging 0\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->SafeLogging_, OP_EQ, SAFELOG_SCRUB_NONE); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("SafeLogging 0\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + tdata = get_options_test_data("SafeLogging 0\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->SafeLogging_, OP_EQ, SAFELOG_SCRUB_NONE); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("SafeLogging Relay\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + tdata = get_options_test_data("SafeLogging Relay\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->SafeLogging_, OP_EQ, SAFELOG_SCRUB_RELAY); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("SafeLogging 1\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + tdata = get_options_test_data("SafeLogging 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); - tt_int_op(ret, OP_EQ, -1); + ret = options_validate(NULL, tdata->opt, &msg); + tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->SafeLogging_, OP_EQ, SAFELOG_SCRUB_ALL); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("SafeLogging stuffy\n" - "MaxClientCircuitsPending 1\n" - "ConnLimit 1\n"); + tdata = get_options_test_data("SafeLogging stuffy\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Unrecognized value '\"stuffy\"' in SafeLogging"); tor_free(msg); @@ -1975,27 +1887,24 @@ test_options_validate__publish_server_descriptor(void *ignored) char *msg; setup_capture_of_logs(LOG_WARN); options_test_data_t *tdata = get_options_test_data( - "PublishServerDescriptor bridge\n" TEST_OPTIONS_DEFAULT_VALUES - ); + "PublishServerDescriptor bridge\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_assert(!msg); free_options_test_data(tdata); - tdata = get_options_test_data("PublishServerDescriptor humma\n" - TEST_OPTIONS_DEFAULT_VALUES); + tdata = get_options_test_data("PublishServerDescriptor humma\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Unrecognized value in PublishServerDescriptor"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("PublishServerDescriptor bridge, v3\n" - TEST_OPTIONS_DEFAULT_VALUES); + tdata = get_options_test_data("PublishServerDescriptor bridge, v3\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Bridges are not supposed to publish router " "descriptors to the directory authorities. Please correct your " @@ -2004,10 +1913,9 @@ test_options_validate__publish_server_descriptor(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("BridgeRelay 1\n" - "PublishServerDescriptor v3\n" - TEST_OPTIONS_DEFAULT_VALUES); + "PublishServerDescriptor v3\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Bridges are not supposed to publish router " "descriptors to the directory authorities. Please correct your " @@ -2015,9 +1923,9 @@ test_options_validate__publish_server_descriptor(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data("BridgeRelay 1\n" TEST_OPTIONS_DEFAULT_VALUES); + tdata = get_options_test_data("BridgeRelay 1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_NE, "Bridges are not supposed to publish router " "descriptors to the directory authorities. Please correct your " @@ -2026,10 +1934,10 @@ test_options_validate__publish_server_descriptor(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data("BridgeRelay 1\n" - "DirPort 999\n" TEST_OPTIONS_DEFAULT_VALUES); + "DirPort 999\n"); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); expect_log_msg("Can't set a DirPort on a bridge " "relay; disabling DirPort\n"); @@ -2054,21 +1962,19 @@ test_options_validate__testing(void *ignored) #define ENSURE_DEFAULT(varname, varval) \ STMT_BEGIN \ free_options_test_data(tdata); \ - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \ - #varname " " #varval "\n"); \ - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\ + tdata = get_options_test_data(#varname " " #varval "\n"); \ + ret = options_validate(NULL, tdata->opt, &msg); \ tt_str_op(msg, OP_EQ, \ #varname " may only be changed in testing Tor networks!"); \ tt_int_op(ret, OP_EQ, -1); \ tor_free(msg); \ \ free_options_test_data(tdata); \ - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \ - #varname " " #varval "\n" \ + tdata = get_options_test_data(#varname " " #varval "\n" \ VALID_DIR_AUTH \ "TestingTorNetwork 1\n"); \ \ - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\ + ret = options_validate(NULL, tdata->opt, &msg); \ if (msg) { \ tt_str_op(msg, OP_NE, \ #varname " may only be changed in testing Tor networks!"); \ @@ -2076,11 +1982,10 @@ test_options_validate__testing(void *ignored) } \ \ free_options_test_data(tdata); \ - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \ - #varname " " #varval "\n" \ + tdata = get_options_test_data(#varname " " #varval "\n" \ "___UsingTestNetworkDefaults 1\n"); \ \ - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\ + ret = options_validate(NULL, tdata->opt, &msg);\ if (msg) { \ tt_str_op(msg, OP_NE, \ #varname " may only be changed in testing Tor networks!"); \ @@ -2123,21 +2028,12 @@ test_options_validate__hidserv(void *ignored) char *msg; setup_capture_of_logs(LOG_WARN); - options_test_data_t *tdata = get_options_test_data( - TEST_OPTIONS_DEFAULT_VALUES); - tdata->opt->MinUptimeHidServDirectoryV2 = -1; - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &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(TEST_OPTIONS_DEFAULT_VALUES - "RendPostPeriod 1\n" ); + tdata = get_options_test_data("RendPostPeriod 1\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("RendPostPeriod option is too short;" " raising to 600 seconds.\n"); @@ -2145,10 +2041,9 @@ test_options_validate__hidserv(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "RendPostPeriod 302401\n" ); + tdata = get_options_test_data("RendPostPeriod 302401\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("RendPostPeriod is too large; " "clipping to 302400s.\n"); @@ -2170,45 +2065,40 @@ test_options_validate__path_bias(void *ignored) char *msg; options_test_data_t *tdata = get_options_test_data( - TEST_OPTIONS_DEFAULT_VALUES "PathBiasNoticeRate 1.1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "PathBiasNoticeRate is too high. It must be between 0 and 1.0"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "PathBiasWarnRate 1.1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("PathBiasWarnRate 1.1\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "PathBiasWarnRate is too high. It must be between 0 and 1.0"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "PathBiasExtremeRate 1.1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("PathBiasExtremeRate 1.1\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "PathBiasExtremeRate is too high. It must be between 0 and 1.0"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "PathBiasNoticeUseRate 1.1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("PathBiasNoticeUseRate 1.1\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "PathBiasNoticeUseRate is too high. It must be between 0 and 1.0"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "PathBiasExtremeUseRate 1.1\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("PathBiasExtremeUseRate 1.1\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "PathBiasExtremeUseRate is too high. It must be between 0 and 1.0"); @@ -2227,130 +2117,141 @@ 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(TEST_OPTIONS_DEFAULT_VALUES #p " 3Gb\n"); \ - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &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(TEST_OPTIONS_DEFAULT_VALUES - "RelayBandwidthRate 1000\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("RelayBandwidthRate 1000\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_u64_op(tdata->opt->RelayBandwidthBurst, OP_EQ, 1000); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "RelayBandwidthBurst 1001\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("RelayBandwidthBurst 1001\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_u64_op(tdata->opt->RelayBandwidthRate, OP_EQ, 1001); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "RelayBandwidthRate 1001\n" + tdata = get_options_test_data("RelayBandwidthRate 1001\n" "RelayBandwidthBurst 1000\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "RelayBandwidthBurst must be at least equal to " "RelayBandwidthRate."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "BandwidthRate 1001\n" + tdata = get_options_test_data("BandwidthRate 1001\n" "BandwidthBurst 1000\n"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "BandwidthBurst must be at least equal to BandwidthRate."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "RelayBandwidthRate 1001\n" + tdata = get_options_test_data("RelayBandwidthRate 1001\n" "BandwidthRate 1000\n" "BandwidthBurst 1000\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_u64_op(tdata->opt->BandwidthRate, OP_EQ, 1001); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "RelayBandwidthRate 1001\n" + tdata = get_options_test_data("RelayBandwidthRate 1001\n" "BandwidthRate 1000\n" "RelayBandwidthBurst 1001\n" "BandwidthBurst 1000\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_u64_op(tdata->opt->BandwidthBurst, OP_EQ, 1001); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ORPort 127.0.0.1:5555\n" + tdata = get_options_test_data("ORPort 127.0.0.1:5555\n" "BandwidthRate 1\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "BandwidthRate is set to 1 bytes/second. For servers," " it must be at least 76800."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ORPort 127.0.0.1:5555\n" + tdata = get_options_test_data("ORPort 127.0.0.1:5555\n" "BandwidthRate 76800\n" "MaxAdvertisedBandwidth 30000\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "MaxAdvertisedBandwidth is set to 30000 bytes/second." " For servers, it must be at least 38400."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ORPort 127.0.0.1:5555\n" + tdata = get_options_test_data("ORPort 127.0.0.1:5555\n" "BandwidthRate 76800\n" "RelayBandwidthRate 1\n" "MaxAdvertisedBandwidth 38400\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "RelayBandwidthRate is set to 1 bytes/second. For " "servers, it must be at least 76800."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ORPort 127.0.0.1:5555\n" + tdata = get_options_test_data("ORPort 127.0.0.1:5555\n" "BandwidthRate 76800\n" "BandwidthBurst 76800\n" "RelayBandwidthRate 76800\n" "MaxAdvertisedBandwidth 38400\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); @@ -2369,9 +2270,8 @@ test_options_validate__circuits(void *ignored) setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "MaxCircuitDirtiness 2592001\n"); - options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("MaxCircuitDirtiness 2592001\n"); + options_validate(NULL, tdata->opt, &msg); expect_log_msg("MaxCircuitDirtiness option is too " "high; setting to 30 days.\n"); tt_int_op(tdata->opt->MaxCircuitDirtiness, OP_EQ, 2592000); @@ -2379,9 +2279,8 @@ test_options_validate__circuits(void *ignored) free_options_test_data(tdata); mock_clean_saved_logs(); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "CircuitStreamTimeout 1\n"); - options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("CircuitStreamTimeout 1\n"); + options_validate(NULL, tdata->opt, &msg); expect_log_msg("CircuitStreamTimeout option is too" " short; raising to 10 seconds.\n"); tt_int_op(tdata->opt->CircuitStreamTimeout, OP_EQ, 10); @@ -2389,9 +2288,8 @@ test_options_validate__circuits(void *ignored) free_options_test_data(tdata); mock_clean_saved_logs(); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "CircuitStreamTimeout 111\n"); - options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("CircuitStreamTimeout 111\n"); + options_validate(NULL, tdata->opt, &msg); expect_no_log_msg("CircuitStreamTimeout option is too" " short; raising to 10 seconds.\n"); tt_int_op(tdata->opt->CircuitStreamTimeout, OP_EQ, 111); @@ -2399,9 +2297,8 @@ test_options_validate__circuits(void *ignored) free_options_test_data(tdata); mock_clean_saved_logs(); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HeartbeatPeriod 1\n"); - options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("HeartbeatPeriod 1\n"); + options_validate(NULL, tdata->opt, &msg); expect_log_msg("HeartbeatPeriod option is too short;" " raising to 1800 seconds.\n"); tt_int_op(tdata->opt->HeartbeatPeriod, OP_EQ, 1800); @@ -2409,9 +2306,8 @@ test_options_validate__circuits(void *ignored) free_options_test_data(tdata); mock_clean_saved_logs(); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HeartbeatPeriod 1982\n"); - options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("HeartbeatPeriod 1982\n"); + options_validate(NULL, tdata->opt, &msg); expect_no_log_msg("HeartbeatPeriod option is too short;" " raising to 1800 seconds.\n"); tt_int_op(tdata->opt->HeartbeatPeriod, OP_EQ, 1982); @@ -2419,10 +2315,10 @@ test_options_validate__circuits(void *ignored) free_options_test_data(tdata); mock_clean_saved_logs(); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data("LearnCircuitBuildTimeout 0\n" "CircuitBuildTimeout 1\n" ); - options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + options_validate(NULL, tdata->opt, &msg); expect_log_msg("CircuitBuildTimeout is shorter (1" " seconds) than the recommended minimum (10 seconds), and " "LearnCircuitBuildTimeout is disabled. If tor isn't working, " @@ -2431,10 +2327,9 @@ test_options_validate__circuits(void *ignored) free_options_test_data(tdata); mock_clean_saved_logs(); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "CircuitBuildTimeout 11\n" + tdata = get_options_test_data("CircuitBuildTimeout 11\n" ); - options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + options_validate(NULL, tdata->opt, &msg); expect_no_log_msg("CircuitBuildTimeout is shorter (1 " "seconds) than the recommended minimum (10 seconds), and " "LearnCircuitBuildTimeout is disabled. If tor isn't working, " @@ -2458,12 +2353,12 @@ test_options_validate__rend(void *ignored) setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data( "UseEntryGuards 0\n" "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" "HiddenServicePort 80 127.0.0.1:8080\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("UseEntryGuards is disabled, but you" " have configured one or more hidden services on this Tor " @@ -2474,13 +2369,12 @@ test_options_validate__rend(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data( - TEST_OPTIONS_DEFAULT_VALUES "UseEntryGuards 1\n" "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" "HiddenServicePort 80 127.0.0.1:8080\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg("UseEntryGuards is disabled, but you" " have configured one or more hidden services on this Tor " @@ -2489,20 +2383,16 @@ test_options_validate__rend(void *ignored) "attack06 for details.\n"); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HiddenServicePort 80 127.0.0.1:8080\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("HiddenServicePort 80 127.0.0.1:8080\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Failed to configure rendezvous options. See logs for details."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HidServAuth failed\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("HidServAuth failed\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Failed to configure client authorization for hidden " "services. See logs for details."); @@ -2526,11 +2416,10 @@ test_options_validate__single_onion(void *ignored) /* Test that HiddenServiceSingleHopMode must come with * HiddenServiceNonAnonymousMode */ - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "SOCKSPort 0\n" + tdata = get_options_test_data("SOCKSPort 0\n" "HiddenServiceSingleHopMode 1\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HiddenServiceSingleHopMode does not provide any " "server anonymity. It must be used with " @@ -2538,12 +2427,11 @@ test_options_validate__single_onion(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "SOCKSPort 0\n" + tdata = get_options_test_data("SOCKSPort 0\n" "HiddenServiceSingleHopMode 1\n" "HiddenServiceNonAnonymousMode 0\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HiddenServiceSingleHopMode does not provide any " "server anonymity. It must be used with " @@ -2551,23 +2439,21 @@ test_options_validate__single_onion(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "SOCKSPort 0\n" + tdata = get_options_test_data("SOCKSPort 0\n" "HiddenServiceSingleHopMode 1\n" "HiddenServiceNonAnonymousMode 1\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); free_options_test_data(tdata); /* Test that SOCKSPort if HiddenServiceSingleHopMode is 1 */ - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "SOCKSPort 5000\n" + tdata = get_options_test_data("SOCKSPort 5000\n" "HiddenServiceSingleHopMode 1\n" "HiddenServiceNonAnonymousMode 1\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HiddenServiceNonAnonymousMode is incompatible with " "using Tor as an anonymous client. Please set " @@ -2576,32 +2462,30 @@ test_options_validate__single_onion(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "SOCKSPort 0\n" + tdata = get_options_test_data("SOCKSPort 0\n" "HiddenServiceSingleHopMode 1\n" "HiddenServiceNonAnonymousMode 1\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "SOCKSPort 5000\n" + tdata = get_options_test_data("SOCKSPort 5000\n" "HiddenServiceSingleHopMode 0\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); free_options_test_data(tdata); /* Test that a hidden service can't be run in non anonymous mode. */ - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data( "HiddenServiceNonAnonymousMode 1\n" "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" "HiddenServicePort 80 127.0.0.1:8080\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HiddenServiceNonAnonymousMode does not provide any " "server anonymity. It must be used with " @@ -2609,10 +2493,10 @@ test_options_validate__single_onion(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data( "HiddenServiceNonAnonymousMode 1\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HiddenServiceNonAnonymousMode does not provide any " "server anonymity. It must be used with " @@ -2620,23 +2504,23 @@ test_options_validate__single_onion(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data( "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" "HiddenServicePort 80 127.0.0.1:8080\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data( "HiddenServiceNonAnonymousMode 1\n" "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" "HiddenServicePort 80 127.0.0.1:8080\n" "HiddenServiceSingleHopMode 1\n" "SOCKSPort 0\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_ptr_op(msg, OP_EQ, NULL); @@ -2657,53 +2541,56 @@ test_options_validate__accounting(void *ignored) setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "AccountingRule something_bad\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("AccountingRule something_bad\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "AccountingRule must be 'sum', 'max', 'in', or 'out'"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "AccountingRule sum\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("AccountingRule sum\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->AccountingRule, OP_EQ, ACCT_SUM); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "AccountingRule max\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("AccountingRule max\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->AccountingRule, OP_EQ, ACCT_MAX); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "AccountingStart fail\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + 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); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Failed to parse accounting options. See logs for details."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "AccountingMax 10\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("AccountingMax 10\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data( - TEST_OPTIONS_DEFAULT_VALUES "ORPort 127.0.0.1:5555\n" "BandwidthRate 76800\n" "BandwidthBurst 76800\n" @@ -2713,7 +2600,7 @@ test_options_validate__accounting(void *ignored) "AccountingMax 10\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("Using accounting with a hidden " "service and an ORPort is risky: your hidden service(s) and " @@ -2724,13 +2611,12 @@ test_options_validate__accounting(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data( - TEST_OPTIONS_DEFAULT_VALUES "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" "HiddenServicePort 80 127.0.0.1:8080\n" "AccountingMax 10\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg("Using accounting with a hidden " "service and an ORPort is risky: your hidden service(s) and " @@ -2741,7 +2627,6 @@ test_options_validate__accounting(void *ignored) free_options_test_data(tdata); tdata = get_options_test_data( - TEST_OPTIONS_DEFAULT_VALUES "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service/\n" "HiddenServicePort 80 127.0.0.1:8080\n" "HiddenServiceDir /Library/Tor/var/lib/tor/hidden_service2/\n" @@ -2749,7 +2634,7 @@ test_options_validate__accounting(void *ignored) "AccountingMax 10\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("Using accounting with multiple " "hidden services is risky: they will all turn off at the same" @@ -2776,36 +2661,29 @@ test_options_validate__proxy(void *ignored) MOCK(tor_addr_lookup, mock_tor_addr_lookup__fail_on_bad_addrs); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HttpProxy 127.0.42.1\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("HttpProxy 127.0.42.1\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->HTTPProxyPort, OP_EQ, 80); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HttpProxy 127.0.42.1:444\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("HttpProxy 127.0.42.1:444\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->HTTPProxyPort, OP_EQ, 444); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HttpProxy not_so_valid!\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("HttpProxy not_so_valid!\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HTTPProxy failed to parse or resolve. Please fix."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HttpProxyAuthenticator " + tdata = get_options_test_data("HttpProxyAuthenticator " "onetwothreonetwothreonetwothreonetwothreonetw" "othreonetwothreonetwothreonetwothreonetwothre" "onetwothreonetwothreonetwothreonetwothreonetw" @@ -2818,52 +2696,41 @@ test_options_validate__proxy(void *ignored) "othreonetwothreonetwothreonetwothreonetwothre" "onetwothreonetwothreonetwothreonetwothreonetw" "othreonetwothreeonetwothreeonetwothree" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HTTPProxyAuthenticator is too long (>= 512 chars)."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HttpProxyAuthenticator validauth\n" - - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("HttpProxyAuthenticator validauth\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HttpsProxy 127.0.42.1\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("HttpsProxy 127.0.42.1\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->HTTPSProxyPort, OP_EQ, 443); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HttpsProxy 127.0.42.1:444\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("HttpsProxy 127.0.42.1:444\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->HTTPSProxyPort, OP_EQ, 444); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HttpsProxy not_so_valid!\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("HttpsProxy not_so_valid!\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HTTPSProxy failed to parse or resolve. Please fix."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HttpsProxyAuthenticator " + tdata = get_options_test_data("HttpsProxyAuthenticator " "onetwothreonetwothreonetwothreonetwothreonetw" "othreonetwothreonetwothreonetwothreonetwothre" "onetwothreonetwothreonetwothreonetwothreonetw" @@ -2878,90 +2745,73 @@ test_options_validate__proxy(void *ignored) "othreonetwothreeonetwothreeonetwothree" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "HTTPSProxyAuthenticator is too long (>= 512 chars)."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HttpsProxyAuthenticator validauth\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("HttpsProxyAuthenticator validauth\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "Socks4Proxy 127.0.42.1\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("Socks4Proxy 127.0.42.1\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->Socks4ProxyPort, OP_EQ, 1080); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "Socks4Proxy 127.0.42.1:444\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("Socks4Proxy 127.0.42.1:444\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->Socks4ProxyPort, OP_EQ, 444); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "Socks4Proxy not_so_valid!\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("Socks4Proxy not_so_valid!\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Socks4Proxy failed to parse or resolve. Please fix."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "Socks5Proxy 127.0.42.1\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("Socks5Proxy 127.0.42.1\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->Socks5ProxyPort, OP_EQ, 1080); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "Socks5Proxy 127.0.42.1:444\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("Socks5Proxy 127.0.42.1:444\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->Socks5ProxyPort, OP_EQ, 444); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "Socks5Proxy not_so_valid!\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("Socks5Proxy not_so_valid!\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Socks5Proxy failed to parse or resolve. Please fix."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "Socks4Proxy 215.1.1.1\n" + tdata = get_options_test_data("Socks4Proxy 215.1.1.1\n" "Socks5Proxy 215.1.1.2\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "You have configured more than one proxy type. " "(Socks4Proxy|Socks5Proxy|HTTPSProxy)"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HttpProxy 215.1.1.1\n" - ); + tdata = get_options_test_data("HttpProxy 215.1.1.1\n"); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("HTTPProxy configured, but no SOCKS " "proxy or HTTPS proxy configured. Watch out: this configuration " @@ -2969,12 +2819,11 @@ test_options_validate__proxy(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HttpProxy 215.1.1.1\n" + tdata = get_options_test_data("HttpProxy 215.1.1.1\n" "Socks4Proxy 215.1.1.1\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg("HTTPProxy configured, but no SOCKS " "proxy or HTTPS proxy configured. Watch out: this configuration " @@ -2982,12 +2831,11 @@ test_options_validate__proxy(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HttpProxy 215.1.1.1\n" + tdata = get_options_test_data("HttpProxy 215.1.1.1\n" "Socks5Proxy 215.1.1.1\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg("HTTPProxy configured, but no SOCKS " "proxy or HTTPS proxy configured. Watch out: this configuration " @@ -2995,12 +2843,11 @@ test_options_validate__proxy(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HttpProxy 215.1.1.1\n" + tdata = get_options_test_data("HttpProxy 215.1.1.1\n" "HttpsProxy 215.1.1.1\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "HTTPProxy configured, but no SOCKS proxy or HTTPS proxy " @@ -3009,81 +2856,69 @@ test_options_validate__proxy(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - ); + tdata = get_options_test_data(""); tdata->opt->Socks5ProxyUsername = tor_strdup(""); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Socks5ProxyUsername must be between 1 and 255 characters."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - ); + tdata = get_options_test_data(""); tdata->opt->Socks5ProxyUsername = tor_strdup("ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789AB" "CDEABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCD" "EABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEA" "BCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEABC" "DE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Socks5ProxyUsername must be between 1 and 255 characters."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "Socks5ProxyUsername hello_world\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("Socks5ProxyUsername hello_world\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Socks5ProxyPassword must be included with " "Socks5ProxyUsername."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "Socks5ProxyUsername hello_world\n" - ); + tdata = get_options_test_data("Socks5ProxyUsername hello_world\n"); tdata->opt->Socks5ProxyPassword = tor_strdup(""); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Socks5ProxyPassword must be between 1 and 255 characters."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "Socks5ProxyUsername hello_world\n" - ); + tdata = get_options_test_data("Socks5ProxyUsername hello_world\n"); tdata->opt->Socks5ProxyPassword = tor_strdup("ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789AB" "CDEABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCD" "EABCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEA" "BCDE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789ABCDEABC" "DE0123456789ABCDEABCDE0123456789ABCDEABCDE0123456789"); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Socks5ProxyPassword must be between 1 and 255 characters."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "Socks5ProxyUsername hello_world\n" - "Socks5ProxyPassword world_hello\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("Socks5ProxyUsername hello_world\n" + "Socks5ProxyPassword world_hello\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "Socks5ProxyPassword hello_world\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("Socks5ProxyPassword hello_world\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Socks5ProxyPassword must be included with " "Socks5ProxyUsername."); @@ -3108,69 +2943,62 @@ test_options_validate__control(void *ignored) setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HashedControlPassword something_incorrect\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data( + "HashedControlPassword something_incorrect\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Bad HashedControlPassword: wrong length or bad encoding"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "HashedControlPassword 16:872860B76453A77D60CA" + tdata = get_options_test_data("HashedControlPassword 16:872860B76453A77D60CA" "2BB8C1A7042072093276A3D701AD684053EC4C\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data( - TEST_OPTIONS_DEFAULT_VALUES "__HashedControlSessionPassword something_incorrect\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Bad HashedControlSessionPassword: wrong length or " "bad encoding"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "__HashedControlSessionPassword 16:872860B7645" + tdata = get_options_test_data("__HashedControlSessionPassword 16:872860B7645" "3A77D60CA2BB8C1A7042072093276A3D701AD684053EC" "4C\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); tdata = get_options_test_data( - TEST_OPTIONS_DEFAULT_VALUES "__OwningControllerProcess something_incorrect\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Bad OwningControllerProcess: invalid PID"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "__OwningControllerProcess 123\n" + tdata = get_options_test_data("__OwningControllerProcess 123\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ControlPort 127.0.0.1:1234\n" + tdata = get_options_test_data("ControlPort 127.0.0.1:1234\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg( "ControlPort is open, but no authentication method has been " @@ -3180,13 +3008,12 @@ test_options_validate__control(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ControlPort 127.0.0.1:1234\n" + tdata = get_options_test_data("ControlPort 127.0.0.1:1234\n" "HashedControlPassword 16:872860B76453A77D60CA" "2BB8C1A7042072093276A3D701AD684053EC4C\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "ControlPort is open, but no authentication method has been " @@ -3196,14 +3023,13 @@ test_options_validate__control(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ControlPort 127.0.0.1:1234\n" + tdata = get_options_test_data("ControlPort 127.0.0.1:1234\n" "__HashedControlSessionPassword 16:872860B7645" "3A77D60CA2BB8C1A7042072093276A3D701AD684053EC" "4C\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "ControlPort is open, but no authentication method has been " @@ -3213,12 +3039,11 @@ test_options_validate__control(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ControlPort 127.0.0.1:1234\n" + tdata = get_options_test_data("ControlPort 127.0.0.1:1234\n" "CookieAuthentication 1\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "ControlPort is open, but no authentication method has been " @@ -3229,11 +3054,9 @@ test_options_validate__control(void *ignored) #ifdef HAVE_SYS_UN_H free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ControlSocket unix:/tmp WorldWritable\n" - ); + tdata = get_options_test_data("ControlSocket unix:/tmp WorldWritable\n"); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg( "ControlSocket is world writable, but no authentication method has" @@ -3243,13 +3066,12 @@ test_options_validate__control(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ControlSocket unix:/tmp WorldWritable\n" + tdata = get_options_test_data("ControlSocket unix:/tmp WorldWritable\n" "HashedControlPassword 16:872860B76453A77D60CA" "2BB8C1A7042072093276A3D701AD684053EC4C\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "ControlSocket is world writable, but no authentication method has" @@ -3259,14 +3081,13 @@ test_options_validate__control(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ControlSocket unix:/tmp WorldWritable\n" + tdata = get_options_test_data("ControlSocket unix:/tmp WorldWritable\n" "__HashedControlSessionPassword 16:872860B7645" "3A77D60CA2BB8C1A7042072093276A3D701AD684053EC" "4C\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "ControlSocket is world writable, but no authentication method has" @@ -3276,12 +3097,11 @@ test_options_validate__control(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ControlSocket unix:/tmp WorldWritable\n" + tdata = get_options_test_data("ControlSocket unix:/tmp WorldWritable\n" "CookieAuthentication 1\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "ControlSocket is world writable, but no authentication method has" @@ -3292,11 +3112,10 @@ test_options_validate__control(void *ignored) #endif /* defined(HAVE_SYS_UN_H) */ free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "CookieAuthFileGroupReadable 1\n" + tdata = get_options_test_data("CookieAuthFileGroupReadable 1\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg( "CookieAuthFileGroupReadable is set, but will have no effect: you " @@ -3305,12 +3124,11 @@ test_options_validate__control(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "CookieAuthFileGroupReadable 1\n" + tdata = get_options_test_data("CookieAuthFileGroupReadable 1\n" "CookieAuthFile /tmp/somewhere\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "CookieAuthFileGroupReadable is set, but will have no effect: you " @@ -3335,8 +3153,7 @@ test_options_validate__families(void *ignored) setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "MyFamily home\n" + tdata = get_options_test_data("MyFamily home\n" "BridgeRelay 1\n" "ORPort 127.0.0.1:5555\n" "BandwidthRate 51300\n" @@ -3345,7 +3162,7 @@ test_options_validate__families(void *ignored) "DirCache 1\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg( "Listing a family for a bridge relay is not supported: it can " @@ -3355,11 +3172,9 @@ test_options_validate__families(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "MyFamily home\n" - ); + tdata = get_options_test_data("MyFamily home\n"); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "Listing a family for a bridge relay is not supported: it can " @@ -3369,22 +3184,18 @@ test_options_validate__families(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "MyFamily !\n" - ); + tdata = get_options_test_data("MyFamily !\n"); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Invalid nickname '!' in MyFamily line"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "NodeFamily foo\n" - "NodeFamily !\n" - ); + tdata = get_options_test_data("NodeFamily foo\n" + "NodeFamily !\n"); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_assert(!msg); tor_free(msg); @@ -3405,11 +3216,10 @@ test_options_validate__addr_policies(void *ignored) options_test_data_t *tdata = NULL; free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ExitPolicy !!!\n" + tdata = get_options_test_data("ExitPolicy !!!\n" "ExitRelay 1\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Error in ExitPolicy entry."); tor_free(msg); @@ -3430,12 +3240,11 @@ test_options_validate__dir_auth(void *ignored) setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - VALID_DIR_AUTH + tdata = get_options_test_data(VALID_DIR_AUTH VALID_ALT_DIR_AUTH ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Directory authority/fallback line did not parse. See logs for " @@ -3445,10 +3254,8 @@ test_options_validate__dir_auth(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "TestingTorNetwork 1\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("TestingTorNetwork 1\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingTorNetwork may only be configured in combination with a " @@ -3457,20 +3264,18 @@ test_options_validate__dir_auth(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - VALID_DIR_AUTH + tdata = get_options_test_data(VALID_DIR_AUTH "TestingTorNetwork 1\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "TestingTorNetwork 1\n" + tdata = get_options_test_data("TestingTorNetwork 1\n" VALID_ALT_DIR_AUTH ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingTorNetwork may only be configured in combination with a " @@ -3479,11 +3284,10 @@ test_options_validate__dir_auth(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "TestingTorNetwork 1\n" + tdata = get_options_test_data("TestingTorNetwork 1\n" VALID_ALT_BRIDGE_AUTH ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingTorNetwork may only be configured in " "combination with a non-default set of DirAuthority or both of " @@ -3491,12 +3295,11 @@ test_options_validate__dir_auth(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - VALID_ALT_DIR_AUTH + tdata = get_options_test_data(VALID_ALT_DIR_AUTH VALID_ALT_BRIDGE_AUTH "TestingTorNetwork 1\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); @@ -3517,11 +3320,10 @@ test_options_validate__transport(void *ignored) setup_capture_of_logs(LOG_NOTICE); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ClientTransportPlugin !!\n" + tdata = get_options_test_data("ClientTransportPlugin !!\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Invalid client transport line. See logs for details."); @@ -3530,20 +3332,17 @@ test_options_validate__transport(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ClientTransportPlugin foo exec bar\n" + tdata = get_options_test_data("ClientTransportPlugin foo exec bar\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ServerTransportPlugin !!\n" - ); + tdata = get_options_test_data("ServerTransportPlugin !!\n"); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Invalid server transport line. See logs for details."); @@ -3552,11 +3351,9 @@ test_options_validate__transport(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ServerTransportPlugin foo exec bar\n" - ); + tdata = get_options_test_data("ServerTransportPlugin foo exec bar\n"); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg( "Tor is not configured as a relay but you specified a " @@ -3565,15 +3362,14 @@ test_options_validate__transport(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ServerTransportPlugin foo exec bar\n" + tdata = get_options_test_data("ServerTransportPlugin foo exec bar\n" "ORPort 127.0.0.1:5555\n" "BandwidthRate 76900\n" "BandwidthBurst 76900\n" "MaxAdvertisedBandwidth 38500\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "Tor is not configured as a relay but you specified a " @@ -3582,22 +3378,19 @@ test_options_validate__transport(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ServerTransportListenAddr foo 127.0.0.42:55\n" - "ServerTransportListenAddr !\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("ServerTransportListenAddr foo 127.0.0.42:55\n" + "ServerTransportListenAddr !\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "ServerTransportListenAddr did not parse. See logs for details."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ServerTransportListenAddr foo 127.0.0.42:55\n" + tdata = get_options_test_data("ServerTransportListenAddr foo 127.0.0.42:55\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg( "You need at least a single managed-proxy to specify a transport " @@ -3606,8 +3399,7 @@ test_options_validate__transport(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ServerTransportListenAddr foo 127.0.0.42:55\n" + tdata = get_options_test_data("ServerTransportListenAddr foo 127.0.0.42:55\n" "ServerTransportPlugin foo exec bar\n" "ORPort 127.0.0.1:5555\n" "BandwidthRate 76900\n" @@ -3615,7 +3407,7 @@ test_options_validate__transport(void *ignored) "MaxAdvertisedBandwidth 38500\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "You need at least a single managed-proxy to specify a transport " @@ -3640,50 +3432,46 @@ test_options_validate__constrained_sockets(void *ignored) setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ConstrainedSockets 1\n" + tdata = get_options_test_data("ConstrainedSockets 1\n" "ConstrainedSockSize 0\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "ConstrainedSockSize is invalid. Must be a value " "between 2048 and 262144 in 1024 byte increments."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ConstrainedSockets 1\n" + tdata = get_options_test_data("ConstrainedSockets 1\n" "ConstrainedSockSize 263168\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "ConstrainedSockSize is invalid. Must be a value " "between 2048 and 262144 in 1024 byte increments."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ConstrainedSockets 1\n" + tdata = get_options_test_data("ConstrainedSockets 1\n" "ConstrainedSockSize 2047\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "ConstrainedSockSize is invalid. Must be a value " "between 2048 and 262144 in 1024 byte increments."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ConstrainedSockets 1\n" + tdata = get_options_test_data("ConstrainedSockets 1\n" "ConstrainedSockSize 2048\n" "DirPort 999\n" "DirCache 1\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("You have requested constrained " "socket buffers while also serving directory entries via DirPort." @@ -3692,12 +3480,11 @@ test_options_validate__constrained_sockets(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "ConstrainedSockets 1\n" + tdata = get_options_test_data("ConstrainedSockets 1\n" "ConstrainedSockSize 2048\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg( "You have requested constrained socket buffers while also serving" @@ -3723,12 +3510,12 @@ test_options_validate__v3_auth(void *ignored) setup_capture_of_logs(LOG_WARN); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 "V3AuthVoteDelay 1000\n" "V3AuthDistDelay 1000\n" "V3AuthVotingInterval 1000\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + 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 " @@ -3736,20 +3523,18 @@ test_options_validate__v3_auth(void *ignored) tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "V3AuthVoteDelay 1\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + 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(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 "V3AuthVoteDelay 1\n" - "TestingTorNetwork 1\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + "TestingTorNetwork 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); @@ -3759,87 +3544,127 @@ test_options_validate__v3_auth(void *ignored) // since they are the same free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "V3AuthDistDelay 1\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + 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(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 "V3AuthDistDelay 1\n" "TestingTorNetwork 1\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + 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); - // 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(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 "V3AuthNIntervalsValid 1\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "V3AuthNIntervalsValid must be at least 2."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 "V3AuthVoteDelay 49\n" "V3AuthDistDelay 49\n" "V3AuthVotingInterval 200\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "V3AuthVotingInterval is insanely low."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + 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" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "V3AuthVotingInterval is insanely high."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 "V3AuthVoteDelay 49\n" "V3AuthDistDelay 49\n" "V3AuthVotingInterval 1441\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("V3AuthVotingInterval does not divide" " evenly into 24 hours.\n"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 "V3AuthVoteDelay 49\n" "V3AuthDistDelay 49\n" "V3AuthVotingInterval 1440\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_no_log_msg("V3AuthVotingInterval does not divide" " evenly into 24 hours.\n"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 "V3AuthVoteDelay 49\n" "V3AuthDistDelay 49\n" "V3AuthVotingInterval 299\n" @@ -3847,84 +3672,125 @@ test_options_validate__v3_auth(void *ignored) "TestingTorNetwork 1\n" ); mock_clean_saved_logs(); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); expect_log_msg("V3AuthVotingInterval is very low. " "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(tdata->old_opt, 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(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 "TestingV3AuthInitialVoteDelay 1\n" VALID_DIR_AUTH "TestingTorNetwork 1\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingV3AuthInitialVoteDelay is way too low."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 "TestingV3AuthInitialDistDelay 1\n" VALID_DIR_AUTH "TestingTorNetwork 1\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingV3AuthInitialDistDelay is way too low."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 VALID_DIR_AUTH "TestingTorNetwork 1\n" ); tdata->opt->TestingV3AuthVotingStartOffset = 100000; - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingV3AuthVotingStartOffset is higher than the " "voting interval."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 VALID_DIR_AUTH "TestingTorNetwork 1\n" ); tdata->opt->TestingV3AuthVotingStartOffset = -1; - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingV3AuthVotingStartOffset must be non-negative."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES + tdata = get_options_test_data(ENABLE_AUTHORITY_V3 VALID_DIR_AUTH "TestingTorNetwork 1\n" "TestingV3AuthInitialVotingInterval 4\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); 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(); @@ -3941,19 +3807,16 @@ test_options_validate__virtual_addr(void *ignored) options_test_data_t *tdata = NULL; free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "VirtualAddrNetworkIPv4 !!" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("VirtualAddrNetworkIPv4 !!"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Error parsing VirtualAddressNetwork !!"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "VirtualAddrNetworkIPv6 !!" + tdata = get_options_test_data("VirtualAddrNetworkIPv6 !!" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Error parsing VirtualAddressNetworkIPv6 !!"); tor_free(msg); @@ -3974,135 +3837,143 @@ 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(TEST_OPTIONS_DEFAULT_VALUES \ + tdata = get_options_test_data(EXTRA_OPT_STR \ VALID_DIR_AUTH \ "TestingTorNetwork 1\n" \ ); \ tdata->opt-> name = low_val; \ - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\ + ret = options_validate(NULL, tdata->opt, &msg); \ tt_int_op(ret, OP_EQ, -1); \ tt_str_op(msg, OP_EQ, #name " " err_low); \ tor_free(msg); \ \ free_options_test_data(tdata); \ - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES \ + 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(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg);\ + 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.", ""); + TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, -1, 3601, + "is way too low.", ""); + TEST_TESTING_OPTION(TestingDirConnectionMaxStall, 1, 3601, + "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."); + "must be non-negative.", ENABLE_AUTHORITY_BRIDGE); TEST_TESTING_OPTION(TestingClientMaxIntervalWithoutRequest, -1, 3601, - "is way too low."); + "is way too low.", ENABLE_AUTHORITY_BRIDGE); TEST_TESTING_OPTION(TestingDirConnectionMaxStall, 1, 3601, - "is way too low."); + "is way too low.", ENABLE_AUTHORITY_BRIDGE); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "TestingEnableConnBwEvent 1\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("TestingEnableConnBwEvent 1\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingEnableConnBwEvent may only be changed in " "testing Tor networks!"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "TestingEnableConnBwEvent 1\n" + tdata = get_options_test_data("TestingEnableConnBwEvent 1\n" VALID_DIR_AUTH "TestingTorNetwork 1\n" "___UsingTestNetworkDefaults 0\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_assert(!msg); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "TestingEnableConnBwEvent 1\n" + tdata = get_options_test_data("TestingEnableConnBwEvent 1\n" VALID_DIR_AUTH "TestingTorNetwork 0\n" "___UsingTestNetworkDefaults 1\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_assert(!msg); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "TestingEnableCellStatsEvent 1\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("TestingEnableCellStatsEvent 1\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "TestingEnableCellStatsEvent may only be changed in " "testing Tor networks!"); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "TestingEnableCellStatsEvent 1\n" + tdata = get_options_test_data("TestingEnableCellStatsEvent 1\n" VALID_DIR_AUTH "TestingTorNetwork 1\n" "___UsingTestNetworkDefaults 0\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_assert(!msg); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "TestingEnableCellStatsEvent 1\n" + tdata = get_options_test_data("TestingEnableCellStatsEvent 1\n" VALID_DIR_AUTH "TestingTorNetwork 0\n" "___UsingTestNetworkDefaults 1\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_assert(!msg); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "TestingEnableTbEmptyEvent 1\n" + tdata = get_options_test_data("TestingEnableTbEmptyEvent 1\n" VALID_DIR_AUTH "TestingTorNetwork 1\n" "___UsingTestNetworkDefaults 0\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_assert(!msg); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "TestingEnableTbEmptyEvent 1\n" + tdata = get_options_test_data("TestingEnableTbEmptyEvent 1\n" VALID_DIR_AUTH "TestingTorNetwork 0\n" "___UsingTestNetworkDefaults 1\n" ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_assert(!msg); tor_free(msg); @@ -4123,40 +3994,32 @@ test_options_validate__accel(void *ignored) options_test_data_t *tdata = NULL; free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "AccelName foo\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("AccelName foo\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->HardwareAccel, OP_EQ, 1); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "AccelName foo\n" - ); + tdata = get_options_test_data("AccelName foo\n"); tdata->opt->HardwareAccel = 2; - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tt_int_op(tdata->opt->HardwareAccel, OP_EQ, 2); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "AccelDir 1\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("AccelDir 1\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, -1); tt_str_op(msg, OP_EQ, "Can't use hardware crypto accelerator dir without engine name."); tor_free(msg); free_options_test_data(tdata); - tdata = get_options_test_data(TEST_OPTIONS_DEFAULT_VALUES - "AccelDir 1\n" - "AccelName something\n" - ); - ret = options_validate(tdata->old_opt, tdata->opt, tdata->def_opt, 0, &msg); + tdata = get_options_test_data("AccelDir 1\n" + "AccelName something\n"); + ret = options_validate(NULL, tdata->opt, &msg); tt_int_op(ret, OP_EQ, 0); tor_free(msg); @@ -4166,8 +4029,278 @@ test_options_validate__accel(void *ignored) tor_free(msg); } +static int mocked_granularity; + +static void +mock_set_log_time_granularity(int g) +{ + mocked_granularity = g; +} + +static void +test_options_init_logs_granularity(void *arg) +{ + options_test_data_t *tdata = get_options_test_data(""); + int rv; + (void) arg; + + MOCK(set_log_time_granularity, mock_set_log_time_granularity); + + /* Reasonable value. */ + tdata->opt->LogTimeGranularity = 100; + mocked_granularity = -1; + rv = options_init_logs(NULL, tdata->opt, 0); + tt_int_op(rv, OP_EQ, 0); + tt_int_op(mocked_granularity, OP_EQ, 100); + + /* Doesn't divide 1000. */ + tdata->opt->LogTimeGranularity = 249; + mocked_granularity = -1; + rv = options_init_logs(NULL, tdata->opt, 0); + tt_int_op(rv, OP_EQ, 0); + tt_int_op(mocked_granularity, OP_EQ, 250); + + /* Doesn't divide 1000. */ + tdata->opt->LogTimeGranularity = 3; + mocked_granularity = -1; + rv = options_init_logs(NULL, tdata->opt, 0); + tt_int_op(rv, OP_EQ, 0); + tt_int_op(mocked_granularity, OP_EQ, 4); + + /* Not a multiple of 1000. */ + tdata->opt->LogTimeGranularity = 1500; + mocked_granularity = -1; + rv = options_init_logs(NULL, tdata->opt, 0); + tt_int_op(rv, OP_EQ, 0); + tt_int_op(mocked_granularity, OP_EQ, 2000); + + /* Reasonable value. */ + tdata->opt->LogTimeGranularity = 3000; + mocked_granularity = -1; + rv = options_init_logs(NULL, tdata->opt, 0); + tt_int_op(rv, OP_EQ, 0); + tt_int_op(mocked_granularity, OP_EQ, 3000); + + /* Negative. (Shouldn't be allowed by rest of config parsing.) */ + tdata->opt->LogTimeGranularity = -1; + mocked_granularity = -1; + rv = options_init_logs(NULL, tdata->opt, 0); + tt_int_op(rv, OP_EQ, -1); + + /* Very big */ + tdata->opt->LogTimeGranularity = 3600 * 1000; + mocked_granularity = -1; + rv = options_init_logs(NULL, tdata->opt, 0); + tt_int_op(rv, OP_EQ, 0); + tt_int_op(mocked_granularity, OP_EQ, 3600 * 1000); + + done: + free_options_test_data(tdata); + UNMOCK(set_log_time_granularity); +} + +typedef struct { + char *name; + log_severity_list_t sev; + int fd; + bool stream; +} added_log_t; + +static smartlist_t *added_logs = NULL; + +static void +mock_add_stream_log_impl(const log_severity_list_t *sev, const char *name, + int fd) +{ + added_log_t *a = tor_malloc_zero(sizeof(added_log_t)); + a->name = tor_strdup(name); + memcpy(&a->sev, sev, sizeof(log_severity_list_t)); + a->fd = fd; + a->stream = true; + smartlist_add(added_logs, a); +} + +static int +mock_add_file_log(const log_severity_list_t *sev, const char *name, int fd) +{ + added_log_t *a = tor_malloc_zero(sizeof(added_log_t)); + a->name = tor_strdup(name); + memcpy(&a->sev, sev, sizeof(log_severity_list_t)); + a->fd = fd; + smartlist_add(added_logs, a); + return 0; +} + +static void +clear_added_logs(void) +{ + SMARTLIST_FOREACH(added_logs, added_log_t *, a, + { tor_free(a->name); tor_free(a); }); + smartlist_clear(added_logs); +} + +static void +test_options_init_logs_quiet(void *arg) +{ + (void)arg; + char *cfg = NULL; + options_test_data_t *tdata = get_options_test_data(""); + char *fn1 = tor_strdup(get_fname_rnd("log")); + const added_log_t *a; + int rv; + tdata->opt->RunAsDaemon = 0; + + added_logs = smartlist_new(); + MOCK(add_stream_log_impl, mock_add_stream_log_impl); + MOCK(add_file_log, mock_add_file_log); + + tt_ptr_op(tdata->opt->Logs, OP_EQ, NULL); + + /* First, try with no configured logs, and make sure that our configured + logs match the quiet level. */ + quiet_level = QUIET_SILENT; + rv = options_init_logs(NULL, tdata->opt, 0); + tt_int_op(rv, OP_EQ, 0); + tt_int_op(smartlist_len(added_logs), OP_EQ, 0); + + quiet_level = QUIET_HUSH; + rv = options_init_logs(NULL, tdata->opt, 0); + tt_int_op(rv, OP_EQ, 0); + tt_int_op(smartlist_len(added_logs), OP_EQ, 1); + a = smartlist_get(added_logs, 0); + tt_assert(a); + tt_assert(a->stream); + tt_int_op(a->fd, OP_EQ, fileno(stdout)); + tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_INFO)], OP_EQ, 0); + tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_NOTICE)], OP_EQ, 0); + tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_WARN)], OP_EQ, LD_ALL_DOMAINS); + clear_added_logs(); + + quiet_level = QUIET_NONE; + rv = options_init_logs(NULL, tdata->opt, 0); + tt_int_op(rv, OP_EQ, 0); + tt_int_op(smartlist_len(added_logs), OP_EQ, 1); + a = smartlist_get(added_logs, 0); + tt_assert(a); + tt_assert(a->stream); + tt_int_op(a->fd, OP_EQ, fileno(stdout)); + tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_INFO)], OP_EQ, 0); + tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_NOTICE)], OP_EQ, + LD_ALL_DOMAINS); + tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_WARN)], OP_EQ, LD_ALL_DOMAINS); + clear_added_logs(); + + /* Make sure that adding a configured log makes the default logs go away. */ + tor_asprintf(&cfg, "Log info file %s\n", fn1); + free_options_test_data(tdata); + tdata = get_options_test_data(cfg); + rv = options_init_logs(NULL, tdata->opt, 0); + tt_int_op(rv, OP_EQ, 0); + tt_int_op(smartlist_len(added_logs), OP_EQ, 1); + a = smartlist_get(added_logs, 0); + tt_assert(a); + tt_assert(! a->stream); + tt_int_op(a->fd, OP_NE, fileno(stdout)); + tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_INFO)], OP_EQ, LD_ALL_DOMAINS); + tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_NOTICE)], OP_EQ, + LD_ALL_DOMAINS); + tt_u64_op(a->sev.masks[SEVERITY_MASK_IDX(LOG_WARN)], OP_EQ, LD_ALL_DOMAINS); + + done: + free_options_test_data(tdata); + tor_free(fn1); + tor_free(cfg); + clear_added_logs(); + smartlist_free(added_logs); + UNMOCK(add_stream_log_impl); + UNMOCK(add_file_log); +} + +static int mock_options_act_status = 0; +static int +mock_options_act(const or_options_t *old_options) +{ + (void)old_options; + return mock_options_act_status; +} +static int +mock_options_act_reversible(const or_options_t *old_options, char **msg_out) +{ + (void)old_options; + (void)msg_out; + return 0; +} + +static void +test_options_trial_assign(void *arg) +{ + (void)arg; + setopt_err_t v; + config_line_t *lines = NULL; + char *msg = NULL; + int r; + + // replace options_act*() so that we don't actually launch tor here. + MOCK(options_act, mock_options_act); + MOCK(options_act_reversible, mock_options_act_reversible); + + // Try assigning nothing; that should work. + v = options_trial_assign(lines, 0, &msg); + if (msg) + puts(msg); + tt_ptr_op(msg, OP_EQ, NULL); + tt_int_op(v, OP_EQ, SETOPT_OK); + + // Assigning a nickname is okay + r = config_get_lines("Nickname Hemiramphinae", &lines, 0); + tt_int_op(r, OP_EQ, 0); + v = options_trial_assign(lines, 0, &msg); + tt_ptr_op(msg, OP_EQ, NULL); + tt_int_op(v, OP_EQ, SETOPT_OK); + tt_str_op(get_options()->Nickname, OP_EQ, "Hemiramphinae"); + config_free_lines(lines); + + // We can't change the User; that's a transition error. + r = config_get_lines("User Heraclitus", &lines, 0); + tt_int_op(r, OP_EQ, 0); + v = options_trial_assign(lines, 0, &msg); + tt_int_op(v, OP_EQ, SETOPT_ERR_TRANSITION); + tt_str_op(msg, OP_EQ, "While Tor is running, changing User is not allowed"); + tor_free(msg); + config_free_lines(lines); + + // We can't set the ORPort to nonsense: that's a validation error. + r = config_get_lines("ORPort fractabling planished", &lines, 0); + tt_int_op(r, OP_EQ, 0); + v = options_trial_assign(lines, 0, &msg); + tt_int_op(v, OP_EQ, SETOPT_ERR_PARSE); // (same error code for now) + tt_str_op(msg, OP_EQ, "Invalid ORPort configuration"); + tor_free(msg); + config_free_lines(lines); + + // We can't set UseBridges to a non-boolean: that's a parse error. + r = config_get_lines("UseBridges ambidextrous", &lines, 0); + tt_int_op(r, OP_EQ, 0); + v = options_trial_assign(lines, 0, &msg); + tt_int_op(v, OP_EQ, SETOPT_ERR_PARSE); + tt_str_op(msg, OP_EQ, "Unrecognized value ambidextrous."); + tor_free(msg); + config_free_lines(lines); + + // this didn't change. + tt_str_op(get_options()->Nickname, OP_EQ, "Hemiramphinae"); + + done: + config_free_lines(lines); + tor_free(msg); + UNMOCK(options_act); + UNMOCK(options_act_reversible); +} + +#ifndef COCCI #define LOCAL_VALIDATE_TEST(name) \ { "validate__" #name, test_options_validate__ ## name, TT_FORK, NULL, NULL } +#endif struct testcase_t options_tests[] = { { "validate", test_options_validate, TT_FORK, NULL, NULL }, @@ -4180,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), @@ -4213,5 +4347,10 @@ struct testcase_t options_tests[] = { LOCAL_VALIDATE_TEST(virtual_addr), LOCAL_VALIDATE_TEST(testing_options), LOCAL_VALIDATE_TEST(accel), + { "init_logs/granularity", test_options_init_logs_granularity, TT_FORK, + NULL, NULL }, + { "init_logs/quiet", test_options_init_logs_quiet, TT_FORK, + NULL, NULL }, + { "trial_assign", test_options_trial_assign, TT_FORK, NULL, NULL }, END_OF_TESTCASES /* */ }; diff --git a/src/test/test_parseconf.sh b/src/test/test_parseconf.sh index eeb80cdfa7..85a23a6a36 100755 --- a/src/test/test_parseconf.sh +++ b/src/test/test_parseconf.sh @@ -36,6 +36,45 @@ # matched by some line in the output of "--verify-config", which must # fail. Exactly one of "expected" or "error" must be present, or the # test will fail. +# +# {expected,error}_${TOR_LIBS_ENABLED}* -- If this file is present, +# then the outcome is different when some optional libraries are +# enabled. If there is no result file matching the exact list of enabled +# libraries, the script searches for result files with one or more of +# those libraries disabled. The search terminates at the standard result +# file. +# +# For example: +# A test that succeeds, regardless of any enabled libraries: +# - expected +# A test that has a different result if the nss library is enabled +# (but the same result if any other library is enabled): +# - expected +# - expected_nss +# A test that fails if the lzma and zstd modules are *not* enabled: +# - error +# - expected_lzma_zstd +# +# {expected,error}*_no_${TOR_MODULES_DISABLED} -- If this file is present, +# then the outcome is different when some modules are disabled. If there +# is no result file matching the exact list of disabled modules, the +# standard result file is used. +# +# For example: +# A test that succeeds, regardless of any disabled modules: +# - expected +# A test that has a different result if the relay module is disabled +# (but the same result if just the dirauth module is disabled): +# - expected +# - expected_no_relay_dirauth +# A test that fails if the dirauth module is disabled: +# - expected +# - error_no_dirauth +# - error_no_relay_dirauth +# (Disabling the relay module also disables dirauth module. But we don't +# want to encode that knowledge in this test script, so we supply a +# separate result file for every combination of disabled modules that +# has a different result.) umask 077 set -e @@ -64,6 +103,8 @@ fi TOR_BINARY="$(abspath "$TOR_BINARY")" +echo "TOR BINARY IS ${TOR_BINARY}" + # make a safe space for temporary files DATA_DIR=$(mktemp -d -t tor_parseconf_tests.XXXXXX) trap 'rm -rf "$DATA_DIR"' 0 @@ -90,7 +131,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" @@ -98,7 +141,54 @@ else FILTER="cat" fi -touch "${DATA_DIR}/EMPTY" || die "Couldn't create empty file." +EMPTY="${DATA_DIR}/EMPTY" + +touch "$EMPTY" || die "Couldn't create empty file." + +STANDARD_LIBS="libevent\\|openssl\\|zlib" +# Lib names are restricted to [a-z0-9]* at the moment +# We don't actually want to support foreign accents here +# shellcheck disable=SC2018,SC2019 +TOR_LIBS_ENABLED="$("$TOR_BINARY" --verify-config \ + -f "$EMPTY" --defaults-torrc "$EMPTY" \ + | sed -n 's/.* Tor .* running on .* with\(.*\)\./\1/p' \ + | tr 'A-Z' 'a-z' | tr ',' '\n' \ + | grep -v "$STANDARD_LIBS" | grep -v "n/a" \ + | sed 's/\( and\)* \(lib\)*\([a-z0-9]*\) .*/\3/' \ + | sort | tr '\n' '_')" +# Remove the last underscore, if there is one +TOR_LIBS_ENABLED=${TOR_LIBS_ENABLED%_} + +# If we ever have more than 3 optional libraries, we'll need more code here +TOR_LIBS_ENABLED_COUNT="$(echo "$TOR_LIBS_ENABLED_SEARCH" \ + | tr ' ' '\n' | wc -l)" +if [ "$TOR_LIBS_ENABLED_COUNT" -gt 3 ]; then + echo "$0 can not handle more than 3 optional libraries" + exit 1 +fi +# Brute-force the combinations of libraries +TOR_LIBS_ENABLED_SEARCH_3="$(echo "$TOR_LIBS_ENABLED" \ + | sed -n \ + 's/^\([^_]*\)_\([^_]*\)_\([^_]*\)$/_\1_\2 _\1_\3 _\2_\3 _\1 _\2 _\3/p')" +TOR_LIBS_ENABLED_SEARCH_2="$(echo "$TOR_LIBS_ENABLED" \ + | sed -n 's/^\([^_]*\)_\([^_]*\)$/_\1 _\2/p')" +TOR_LIBS_ENABLED_SEARCH="_$TOR_LIBS_ENABLED \ + $TOR_LIBS_ENABLED_SEARCH_3 \ + $TOR_LIBS_ENABLED_SEARCH_2" +TOR_LIBS_ENABLED_SEARCH="$(echo "$TOR_LIBS_ENABLED_SEARCH" | tr ' ' '\n' \ + | grep -v '^_*$' | tr '\n' ' ')" + +TOR_MODULES_DISABLED="$("$TOR_BINARY" --list-modules | grep ': no' \ + | cut -d ':' -f1 | sort | tr '\n' '_')" +# Remove the last underscore, if there is one +TOR_MODULES_DISABLED=${TOR_MODULES_DISABLED%_} + +echo "Tor is configured with:" +echo "Optional Libraries: ${TOR_LIBS_ENABLED:-(None)}" +if [ -n "${TOR_LIBS_ENABLED}" ]; then + echo "Optional Library Search List: $TOR_LIBS_ENABLED_SEARCH" +fi +echo "Disabled Modules: ${TOR_MODULES_DISABLED:-(None)}" for dir in "${EXAMPLEDIR}"/*; do if ! test -d "${dir}"; then @@ -125,12 +215,43 @@ for dir in "${EXAMPLEDIR}"/*; do CMDLINE="" fi - if test -f "./expected"; then - if test -f "./error"; then - echo "FAIL: Found both ${dir}/expected and ${dir}/error." - echo "(Only one of these files should exist.)" - exit $EXITCODE + EXPECTED= + ERROR= + # Search for a custom result file for any combination of enabled optional + # libraries + # The libs in the list are [A-Za-z0-9_]* and space-separated. + # shellcheck disable=SC2086 + for lib_suffix in $TOR_LIBS_ENABLED_SEARCH ""; do + # Search for a custom result file for any disabled modules + for mod_suffix in "_no_${TOR_MODULES_DISABLED}" ""; do + suffix="${lib_suffix}${mod_suffix}" + + if test -f "./expected${suffix}"; then + + # Check for broken configs + if test -f "./error${suffix}"; then + 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}" + break + + elif test -f "./error${suffix}"; then + ERROR="./error${suffix}" + break + fi + done + + # Exit as soon as the inner loop finds a file + if test -f "$EXPECTED" || test -f "$ERROR"; then + break fi + done + + if test -f "$EXPECTED"; then # This case should succeed: run dump-config and see if it does. @@ -139,26 +260,27 @@ 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 + if cmp "$EXPECTED" "${DATA_DIR}/output.${testname}">/dev/null ; then # Check round-trip. "${TOR_BINARY}" -f "${DATA_DIR}/output.${testname}" \ --defaults-torrc "${DATA_DIR}/empty" \ --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" \ @@ -166,39 +288,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 + 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)" + 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_pt.c b/src/test/test_pt.c index 8f3ce03c42..0e391c1baa 100644 --- a/src/test/test_pt.c +++ b/src/test/test_pt.c @@ -11,7 +11,7 @@ #define PROCESS_PRIVATE #include "core/or/or.h" #include "app/config/config.h" -#include "lib/confmgt/confparse.h" +#include "lib/confmgt/confmgt.h" #include "feature/control/control.h" #include "feature/control/control_events.h" #include "feature/client/transports.h" 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_relay.c b/src/test/test_relay.c index 0b7a7be332..f7809b47ef 100644 --- a/src/test/test_relay.c +++ b/src/test/test_relay.c @@ -21,42 +21,10 @@ /* Test suite stuff */ #include "test/test.h" #include "test/fakechans.h" - -static or_circuit_t * new_fake_orcirc(channel_t *nchan, channel_t *pchan); +#include "test/fakecircs.h" static void test_relay_append_cell_to_circuit_queue(void *arg); -static or_circuit_t * -new_fake_orcirc(channel_t *nchan, channel_t *pchan) -{ - or_circuit_t *orcirc = NULL; - circuit_t *circ = NULL; - - orcirc = tor_malloc_zero(sizeof(*orcirc)); - circ = &(orcirc->base_); - circ->magic = OR_CIRCUIT_MAGIC; - - circuit_set_n_circid_chan(circ, get_unique_circ_id_by_chan(nchan), nchan); - cell_queue_init(&(circ->n_chan_cells)); - - circ->n_hop = NULL; - circ->streams_blocked_on_n_chan = 0; - circ->streams_blocked_on_p_chan = 0; - circ->n_delete_pending = 0; - circ->p_delete_pending = 0; - circ->received_destroy = 0; - circ->state = CIRCUIT_STATE_OPEN; - circ->purpose = CIRCUIT_PURPOSE_OR; - circ->package_window = CIRCWINDOW_START_MAX; - circ->deliver_window = CIRCWINDOW_START_MAX; - circ->n_chan_create_cell = NULL; - - circuit_set_p_circid_chan(orcirc, get_unique_circ_id_by_chan(pchan), pchan); - cell_queue_init(&(orcirc->p_chan_cells)); - - return orcirc; -} - static void assert_circuit_ok_mock(const circuit_t *c) { @@ -145,7 +113,7 @@ test_relay_close_circuit(void *arg) cell_queue_clear(&orcirc->base_.n_chan_cells); cell_queue_clear(&orcirc->p_chan_cells); } - tor_free(orcirc); + free_fake_orcirc(orcirc); free_fake_channel(nchan); free_fake_channel(pchan); UNMOCK(assert_circuit_ok); @@ -218,7 +186,7 @@ test_relay_append_cell_to_circuit_queue(void *arg) cell_queue_clear(&orcirc->base_.n_chan_cells); cell_queue_clear(&orcirc->p_chan_cells); } - tor_free(orcirc); + free_fake_orcirc(orcirc); free_fake_channel(nchan); free_fake_channel(pchan); diff --git a/src/test/test_router.c b/src/test/test_router.c index 5477ab51e9..24c7d32bc1 100644 --- a/src/test/test_router.c +++ b/src/test/test_router.c @@ -92,13 +92,13 @@ test_router_dump_router_to_string_no_bridge_distribution_method(void *arg) options->BridgeRelay = 1; /* Generate keys which router_dump_router_to_string() expects to exist. */ - tt_int_op(0, ==, curve25519_keypair_generate(&ntor_keypair, 0)); - tt_int_op(0, ==, ed25519_keypair_generate(&signing_keypair, 0)); + tt_int_op(0, OP_EQ, curve25519_keypair_generate(&ntor_keypair, 0)); + tt_int_op(0, OP_EQ, ed25519_keypair_generate(&signing_keypair, 0)); /* Set up part of our routerinfo_t so that we don't trigger any other * assertions in router_dump_router_to_string(). */ router = (routerinfo_t*)router_get_my_routerinfo(); - tt_ptr_op(router, !=, NULL); + tt_ptr_op(router, OP_NE, NULL); /* The real router_get_my_routerinfo() looks up onion_curve25519_pkey using * get_current_curve25519_keypair(), but we don't initialise static data in @@ -115,9 +115,9 @@ test_router_dump_router_to_string_no_bridge_distribution_method(void *arg) &ntor_keypair, &signing_keypair); crypto_pk_free(onion_pkey); - tt_ptr_op(desc, !=, NULL); + tt_ptr_op(desc, OP_NE, NULL); found = strstr(desc, needle); - tt_ptr_op(found, !=, NULL); + tt_ptr_op(found, OP_NE, NULL); done: NS_UNMOCK(router_get_my_routerinfo); diff --git a/src/test/test_scheduler.c b/src/test/test_scheduler.c index bf9c6a49cd..39c4963fce 100644 --- a/src/test/test_scheduler.c +++ b/src/test/test_scheduler.c @@ -848,8 +848,8 @@ test_scheduler_initfree(void *arg) { (void)arg; - tt_ptr_op(channels_pending, ==, NULL); - tt_ptr_op(run_sched_ev, ==, NULL); + tt_ptr_op(channels_pending, OP_EQ, NULL); + tt_ptr_op(run_sched_ev, OP_EQ, NULL); MOCK(get_options, mock_get_options); set_scheduler_options(SCHEDULER_KIST); @@ -858,17 +858,17 @@ test_scheduler_initfree(void *arg) scheduler_init(); - tt_ptr_op(channels_pending, !=, NULL); - tt_ptr_op(run_sched_ev, !=, NULL); + tt_ptr_op(channels_pending, OP_NE, NULL); + tt_ptr_op(run_sched_ev, OP_NE, NULL); /* We have specified nothing in the torrc and there's no consensus so the * KIST scheduler is what should be in use */ - tt_ptr_op(the_scheduler, ==, get_kist_scheduler()); - tt_int_op(sched_run_interval, ==, 10); + tt_ptr_op(the_scheduler, OP_EQ, get_kist_scheduler()); + tt_int_op(sched_run_interval, OP_EQ, 10); scheduler_free_all(); - tt_ptr_op(channels_pending, ==, NULL); - tt_ptr_op(run_sched_ev, ==, NULL); + tt_ptr_op(channels_pending, OP_EQ, NULL); + tt_ptr_op(run_sched_ev, OP_EQ, NULL); done: UNMOCK(get_options); @@ -890,11 +890,11 @@ test_scheduler_can_use_kist(void *arg) res_should = scheduler_can_use_kist(); res_freq = kist_scheduler_run_interval(); #ifdef HAVE_KIST_SUPPORT - tt_int_op(res_should, ==, 1); + tt_int_op(res_should, OP_EQ, 1); #else /* HAVE_KIST_SUPPORT */ - tt_int_op(res_should, ==, 0); + tt_int_op(res_should, OP_EQ, 0); #endif /* HAVE_KIST_SUPPORT */ - tt_int_op(res_freq, ==, 1234); + tt_int_op(res_freq, OP_EQ, 1234); /* Test defer to consensus, but no consensus available */ clear_options(); @@ -902,11 +902,11 @@ test_scheduler_can_use_kist(void *arg) res_should = scheduler_can_use_kist(); res_freq = kist_scheduler_run_interval(); #ifdef HAVE_KIST_SUPPORT - tt_int_op(res_should, ==, 1); + tt_int_op(res_should, OP_EQ, 1); #else /* HAVE_KIST_SUPPORT */ - tt_int_op(res_should, ==, 0); + tt_int_op(res_should, OP_EQ, 0); #endif /* HAVE_KIST_SUPPORT */ - tt_int_op(res_freq, ==, 10); + tt_int_op(res_freq, OP_EQ, 10); /* Test defer to consensus, and kist consensus available */ MOCK(networkstatus_get_param, mock_kist_networkstatus_get_param); @@ -915,11 +915,11 @@ test_scheduler_can_use_kist(void *arg) res_should = scheduler_can_use_kist(); res_freq = kist_scheduler_run_interval(); #ifdef HAVE_KIST_SUPPORT - tt_int_op(res_should, ==, 1); + tt_int_op(res_should, OP_EQ, 1); #else /* HAVE_KIST_SUPPORT */ - tt_int_op(res_should, ==, 0); + tt_int_op(res_should, OP_EQ, 0); #endif /* HAVE_KIST_SUPPORT */ - tt_int_op(res_freq, ==, 12); + tt_int_op(res_freq, OP_EQ, 12); UNMOCK(networkstatus_get_param); /* Test defer to consensus, and vanilla consensus available */ @@ -928,8 +928,8 @@ test_scheduler_can_use_kist(void *arg) mocked_options.KISTSchedRunInterval = 0; res_should = scheduler_can_use_kist(); res_freq = kist_scheduler_run_interval(); - tt_int_op(res_should, ==, 0); - tt_int_op(res_freq, ==, 0); + tt_int_op(res_should, OP_EQ, 0); + tt_int_op(res_freq, OP_EQ, 0); UNMOCK(networkstatus_get_param); done: @@ -956,7 +956,7 @@ test_scheduler_ns_changed(void *arg) set_scheduler_options(SCHEDULER_KIST); set_scheduler_options(SCHEDULER_VANILLA); - tt_ptr_op(the_scheduler, ==, NULL); + tt_ptr_op(the_scheduler, OP_EQ, NULL); /* Change from vanilla to kist via consensus */ the_scheduler = get_vanilla_scheduler(); @@ -964,9 +964,9 @@ test_scheduler_ns_changed(void *arg) scheduler_notify_networkstatus_changed(); UNMOCK(networkstatus_get_param); #ifdef HAVE_KIST_SUPPORT - tt_ptr_op(the_scheduler, ==, get_kist_scheduler()); + tt_ptr_op(the_scheduler, OP_EQ, get_kist_scheduler()); #else - tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler()); + tt_ptr_op(the_scheduler, OP_EQ, get_vanilla_scheduler()); #endif /* Change from kist to vanilla via consensus */ @@ -974,7 +974,7 @@ test_scheduler_ns_changed(void *arg) MOCK(networkstatus_get_param, mock_vanilla_networkstatus_get_param); scheduler_notify_networkstatus_changed(); UNMOCK(networkstatus_get_param); - tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler()); + tt_ptr_op(the_scheduler, OP_EQ, get_vanilla_scheduler()); /* Doesn't change when using KIST */ the_scheduler = get_kist_scheduler(); @@ -982,9 +982,9 @@ test_scheduler_ns_changed(void *arg) scheduler_notify_networkstatus_changed(); UNMOCK(networkstatus_get_param); #ifdef HAVE_KIST_SUPPORT - tt_ptr_op(the_scheduler, ==, get_kist_scheduler()); + tt_ptr_op(the_scheduler, OP_EQ, get_kist_scheduler()); #else - tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler()); + tt_ptr_op(the_scheduler, OP_EQ, get_vanilla_scheduler()); #endif /* Doesn't change when using vanilla */ @@ -992,7 +992,7 @@ test_scheduler_ns_changed(void *arg) MOCK(networkstatus_get_param, mock_vanilla_networkstatus_get_param); scheduler_notify_networkstatus_changed(); UNMOCK(networkstatus_get_param); - tt_ptr_op(the_scheduler, ==, get_vanilla_scheduler()); + tt_ptr_op(the_scheduler, OP_EQ, get_vanilla_scheduler()); done: UNMOCK(get_options); 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 <stdio.h> + +#ifdef _WIN32 +/* For mkdir() */ +#include <direct.h> +#else +#include <dirent.h> +#endif /* defined(_WIN32) */ + +#include <math.h> + +/* 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_util.c b/src/test/test_util.c index aebefe64c5..3e4975fcd8 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -304,6 +304,7 @@ test_util_write_chunks_to_file(void *arg) tor_free(temp_str); } +#ifndef COCCI #define _TFE(a, b, f) tt_int_op((a).f, OP_EQ, (b).f) /** test the minimum set of struct tm fields needed for a unique epoch value * this is also the set we use to test tor_timegm */ @@ -316,6 +317,7 @@ test_util_write_chunks_to_file(void *arg) _TFE(a, b, tm_min ); \ _TFE(a, b, tm_sec ); \ TT_STMT_END +#endif /* !defined(COCCI) */ static void test_util_time(void *arg) @@ -6257,6 +6259,7 @@ test_util_map_anon_nofork(void *arg) #endif /* defined(_WIN32) */ } +#ifndef COCCI #define UTIL_LEGACY(name) \ { #name, test_util_ ## name , 0, NULL, NULL } @@ -6281,6 +6284,7 @@ test_util_map_anon_nofork(void *arg) { "compress_dos/" #name, test_util_decompress_dos, 0, \ &compress_setup, \ (char*)(identifier) } +#endif /* !defined(COCCI) */ #ifdef _WIN32 #define UTIL_TEST_NO_WIN(n, f) { #n, NULL, TT_SKIP, NULL, NULL } diff --git a/src/test/test_zero_length_keys.sh b/src/test/test_zero_length_keys.sh index 84ca513b0a..b944d9bf3f 100755 --- a/src/test/test_zero_length_keys.sh +++ b/src/test/test_zero_length_keys.sh @@ -1,10 +1,44 @@ #!/bin/sh # Check that tor regenerates keys when key files are zero-length +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} diff --git a/src/test/testing_common.c b/src/test/testing_common.c index ff6028ddb4..c5a4e81fbe 100644 --- a/src/test/testing_common.c +++ b/src/test/testing_common.c @@ -272,6 +272,9 @@ main(int c, const char **v) control_initialize_event_queue(); + /* Don't add default logs; the tests manage their own. */ + quiet_level = QUIET_SILENT; + for (i_out = i = 1; i < c; ++i) { if (!strcmp(v[i], "--warn")) { loglevel = LOG_WARN; @@ -323,6 +326,7 @@ main(int c, const char **v) initialize_mainloop_events(); options_init(options); options->DataDirectory = tor_strdup(temp_dir); + options->DataDirectory_option = tor_strdup(temp_dir); tor_asprintf(&options->KeyDirectory, "%s"PATH_SEPARATOR"keys", options->DataDirectory); options->CacheDirectory = tor_strdup(temp_dir); diff --git a/src/tools/tools.dox b/src/tools/tools.dox new file mode 100644 index 0000000000..1168ed5bad --- /dev/null +++ b/src/tools/tools.dox @@ -0,0 +1,8 @@ +/** +@dir /tools +@brief tools: other command-line tools for use with Tor. + +The "tools" directory has a few other programs that use Tor, but are not part +of the main Tor binary. + +**/ diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c index 5d97696c18..25bda26549 100644 --- a/src/tools/tor-resolve.c +++ b/src/tools/tor-resolve.c @@ -45,8 +45,10 @@ #define RESPONSE_LEN_4 8 #define log_sock_error(act, _s) \ - STMT_BEGIN log_fn(LOG_ERR, LD_NET, "Error while %s: %s", act, \ - tor_socket_strerror(tor_socket_errno(_s))); STMT_END + STMT_BEGIN \ + log_fn(LOG_ERR, LD_NET, "Error while %s: %s", act, \ + tor_socket_strerror(tor_socket_errno(_s))); \ + STMT_END static void usage(void) ATTR_NORETURN; diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h index bd38e7208d..5fb1340465 100644 --- a/src/win32/orconfig.h +++ b/src/win32/orconfig.h @@ -218,7 +218,7 @@ #define USING_TWOS_COMPLEMENT /* Version number of package */ -#define VERSION "0.4.2.3-alpha-dev" +#define VERSION "0.4.3.0-alpha-dev" |